]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/godump.c
2015-10-29 Andrew MacLeod <amacleod@redhat.com>
[thirdparty/gcc.git] / gcc / godump.c
1 /* Output Go language descriptions of types.
2 Copyright (C) 2008-2015 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor <iant@google.com>.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 /* This file is used during the build process to emit Go language
22 descriptions of declarations from C header files. It uses the
23 debug info hooks to emit the descriptions. The Go language
24 descriptions then become part of the Go runtime support
25 library.
26
27 All global names are output with a leading underscore, so that they
28 are all hidden in Go. */
29
30 #include "config.h"
31 #include "system.h"
32 #include "coretypes.h"
33 #include "options.h"
34 #include "obstack.h"
35 #include "tree.h"
36 #include "wide-int-print.h"
37 #include "diagnostic-core.h"
38 #include "alias.h"
39 #include "debug.h"
40 #include "stor-layout.h"
41 #include "defaults.h"
42
43 /* We dump this information from the debug hooks. This gives us a
44 stable and maintainable API to hook into. In order to work
45 correctly when -g is used, we build our own hooks structure which
46 wraps the hooks we need to change. */
47
48 /* Our debug hooks. This is initialized by dump_go_spec_init. */
49
50 static struct gcc_debug_hooks go_debug_hooks;
51
52 /* The real debug hooks. */
53
54 static const struct gcc_debug_hooks *real_debug_hooks;
55
56 /* The file where we should write information. */
57
58 static FILE *go_dump_file;
59
60 /* A queue of decls to output. */
61
62 static GTY(()) vec<tree, va_gc> *queue;
63
64 /* A hash table of macros we have seen. */
65
66 static htab_t macro_hash;
67
68 /* The type of a value in macro_hash. */
69
70 struct macro_hash_value
71 {
72 /* The name stored in the hash table. */
73 char *name;
74 /* The value of the macro. */
75 char *value;
76 };
77
78 /* Returns the number of units necessary to represent an integer with the given
79 PRECISION (in bits). */
80
81 static inline unsigned int
82 precision_to_units (unsigned int precision)
83 {
84 return (precision + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
85 }
86
87 /* Calculate the hash value for an entry in the macro hash table. */
88
89 static hashval_t
90 macro_hash_hashval (const void *val)
91 {
92 const struct macro_hash_value *mhval = (const struct macro_hash_value *) val;
93 return htab_hash_string (mhval->name);
94 }
95
96 /* Compare values in the macro hash table for equality. */
97
98 static int
99 macro_hash_eq (const void *v1, const void *v2)
100 {
101 const struct macro_hash_value *mhv1 = (const struct macro_hash_value *) v1;
102 const struct macro_hash_value *mhv2 = (const struct macro_hash_value *) v2;
103 return strcmp (mhv1->name, mhv2->name) == 0;
104 }
105
106 /* Free values deleted from the macro hash table. */
107
108 static void
109 macro_hash_del (void *v)
110 {
111 struct macro_hash_value *mhv = (struct macro_hash_value *) v;
112 XDELETEVEC (mhv->name);
113 XDELETEVEC (mhv->value);
114 XDELETE (mhv);
115 }
116
117 /* For the string hash tables. */
118
119 static int
120 string_hash_eq (const void *y1, const void *y2)
121 {
122 return strcmp ((const char *) y1, (const char *) y2) == 0;
123 }
124
125 /* A macro definition. */
126
127 static void
128 go_define (unsigned int lineno, const char *buffer)
129 {
130 const char *p;
131 const char *name_end;
132 size_t out_len;
133 char *out_buffer;
134 char *q;
135 bool saw_operand;
136 bool need_operand;
137 struct macro_hash_value *mhval;
138 char *copy;
139 hashval_t hashval;
140 void **slot;
141
142 real_debug_hooks->define (lineno, buffer);
143
144 /* Skip macro functions. */
145 for (p = buffer; *p != '\0' && *p != ' '; ++p)
146 if (*p == '(')
147 return;
148
149 if (*p == '\0')
150 return;
151
152 name_end = p;
153
154 ++p;
155 if (*p == '\0')
156 return;
157
158 copy = XNEWVEC (char, name_end - buffer + 1);
159 memcpy (copy, buffer, name_end - buffer);
160 copy[name_end - buffer] = '\0';
161
162 mhval = XNEW (struct macro_hash_value);
163 mhval->name = copy;
164 mhval->value = NULL;
165
166 hashval = htab_hash_string (copy);
167 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, NO_INSERT);
168
169 /* For simplicity, we force all names to be hidden by adding an
170 initial underscore, and let the user undo this as needed. */
171 out_len = strlen (p) * 2 + 1;
172 out_buffer = XNEWVEC (char, out_len);
173 q = out_buffer;
174 saw_operand = false;
175 need_operand = false;
176 while (*p != '\0')
177 {
178 switch (*p)
179 {
180 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
181 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
182 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
183 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
184 case 'Y': case 'Z':
185 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
186 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
187 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
188 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
189 case 'y': case 'z':
190 case '_':
191 {
192 /* The start of an identifier. Technically we should also
193 worry about UTF-8 identifiers, but they are not a
194 problem for practical uses of -fdump-go-spec so we
195 don't worry about them. */
196 const char *start;
197 char *n;
198 struct macro_hash_value idval;
199
200 if (saw_operand)
201 goto unknown;
202
203 start = p;
204 while (ISALNUM (*p) || *p == '_')
205 ++p;
206 n = XALLOCAVEC (char, p - start + 1);
207 memcpy (n, start, p - start);
208 n[p - start] = '\0';
209 idval.name = n;
210 idval.value = NULL;
211 if (htab_find (macro_hash, &idval) == NULL)
212 {
213 /* This is a reference to a name which was not defined
214 as a macro. */
215 goto unknown;
216 }
217
218 *q++ = '_';
219 memcpy (q, start, p - start);
220 q += p - start;
221
222 saw_operand = true;
223 need_operand = false;
224 }
225 break;
226
227 case '.':
228 if (!ISDIGIT (p[1]))
229 goto unknown;
230 /* Fall through. */
231 case '0': case '1': case '2': case '3': case '4':
232 case '5': case '6': case '7': case '8': case '9':
233 {
234 const char *start;
235 bool is_hex;
236
237 start = p;
238 is_hex = false;
239 if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
240 {
241 p += 2;
242 is_hex = true;
243 }
244 while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
245 || (is_hex
246 && ((*p >= 'a' && *p <= 'f')
247 || (*p >= 'A' && *p <= 'F'))))
248 ++p;
249 memcpy (q, start, p - start);
250 q += p - start;
251 while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
252 || *p == 'f' || *p == 'F'
253 || *p == 'd' || *p == 'D')
254 {
255 /* Go doesn't use any of these trailing type
256 modifiers. */
257 ++p;
258 }
259
260 /* We'll pick up the exponent, if any, as an
261 expression. */
262
263 saw_operand = true;
264 need_operand = false;
265 }
266 break;
267
268 case ' ': case '\t':
269 *q++ = *p++;
270 break;
271
272 case '(':
273 /* Always OK, not part of an operand, presumed to start an
274 operand. */
275 *q++ = *p++;
276 saw_operand = false;
277 need_operand = false;
278 break;
279
280 case ')':
281 /* OK if we don't need an operand, and presumed to indicate
282 an operand. */
283 if (need_operand)
284 goto unknown;
285 *q++ = *p++;
286 saw_operand = true;
287 break;
288
289 case '+': case '-':
290 /* Always OK, but not part of an operand. */
291 *q++ = *p++;
292 saw_operand = false;
293 break;
294
295 case '*': case '/': case '%': case '|': case '&': case '^':
296 /* Must be a binary operator. */
297 if (!saw_operand)
298 goto unknown;
299 *q++ = *p++;
300 saw_operand = false;
301 need_operand = true;
302 break;
303
304 case '=':
305 *q++ = *p++;
306 if (*p != '=')
307 goto unknown;
308 /* Must be a binary operator. */
309 if (!saw_operand)
310 goto unknown;
311 *q++ = *p++;
312 saw_operand = false;
313 need_operand = true;
314 break;
315
316 case '!':
317 *q++ = *p++;
318 if (*p == '=')
319 {
320 /* Must be a binary operator. */
321 if (!saw_operand)
322 goto unknown;
323 *q++ = *p++;
324 saw_operand = false;
325 need_operand = true;
326 }
327 else
328 {
329 /* Must be a unary operator. */
330 if (saw_operand)
331 goto unknown;
332 need_operand = true;
333 }
334 break;
335
336 case '<': case '>':
337 /* Must be a binary operand, may be << or >> or <= or >=. */
338 if (!saw_operand)
339 goto unknown;
340 *q++ = *p++;
341 if (*p == *(p - 1) || *p == '=')
342 *q++ = *p++;
343 saw_operand = false;
344 need_operand = true;
345 break;
346
347 case '~':
348 /* Must be a unary operand, must be translated for Go. */
349 if (saw_operand)
350 goto unknown;
351 *q++ = '^';
352 p++;
353 need_operand = true;
354 break;
355
356 case '"':
357 case '\'':
358 {
359 char quote;
360 int count;
361
362 if (saw_operand)
363 goto unknown;
364 quote = *p;
365 *q++ = *p++;
366 count = 0;
367 while (*p != quote)
368 {
369 int c;
370
371 if (*p == '\0')
372 goto unknown;
373
374 ++count;
375
376 if (*p != '\\')
377 {
378 *q++ = *p++;
379 continue;
380 }
381
382 *q++ = *p++;
383 switch (*p)
384 {
385 case '0': case '1': case '2': case '3':
386 case '4': case '5': case '6': case '7':
387 c = 0;
388 while (*p >= '0' && *p <= '7')
389 {
390 *q++ = *p++;
391 ++c;
392 }
393 /* Go octal characters are always 3
394 digits. */
395 if (c != 3)
396 goto unknown;
397 break;
398
399 case 'x':
400 *q++ = *p++;
401 c = 0;
402 while (ISXDIGIT (*p))
403 {
404 *q++ = *p++;
405 ++c;
406 }
407 /* Go hex characters are always 2 digits. */
408 if (c != 2)
409 goto unknown;
410 break;
411
412 case 'a': case 'b': case 'f': case 'n': case 'r':
413 case 't': case 'v': case '\\': case '\'': case '"':
414 *q++ = *p++;
415 break;
416
417 default:
418 goto unknown;
419 }
420 }
421
422 *q++ = *p++;
423
424 if (quote == '\'' && count != 1)
425 goto unknown;
426
427 saw_operand = true;
428 need_operand = false;
429
430 break;
431 }
432
433 default:
434 goto unknown;
435 }
436 }
437
438 if (need_operand)
439 goto unknown;
440
441 gcc_assert ((size_t) (q - out_buffer) < out_len);
442 *q = '\0';
443
444 mhval->value = out_buffer;
445
446 if (slot == NULL)
447 {
448 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, INSERT);
449 gcc_assert (slot != NULL && *slot == NULL);
450 }
451 else
452 {
453 if (*slot != NULL)
454 macro_hash_del (*slot);
455 }
456
457 *slot = mhval;
458
459 return;
460
461 unknown:
462 fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
463 if (slot != NULL)
464 htab_clear_slot (macro_hash, slot);
465 XDELETEVEC (out_buffer);
466 XDELETEVEC (copy);
467 }
468
469 /* A macro undef. */
470
471 static void
472 go_undef (unsigned int lineno, const char *buffer)
473 {
474 struct macro_hash_value mhval;
475 void **slot;
476
477 real_debug_hooks->undef (lineno, buffer);
478
479 mhval.name = CONST_CAST (char *, buffer);
480 mhval.value = NULL;
481 slot = htab_find_slot (macro_hash, &mhval, NO_INSERT);
482 if (slot != NULL)
483 htab_clear_slot (macro_hash, slot);
484 }
485
486 /* A function or variable decl. */
487
488 static void
489 go_decl (tree decl)
490 {
491 if (!TREE_PUBLIC (decl)
492 || DECL_IS_BUILTIN (decl)
493 || DECL_NAME (decl) == NULL_TREE)
494 return;
495 vec_safe_push (queue, decl);
496 }
497
498 /* A function decl. */
499
500 static void
501 go_function_decl (tree decl)
502 {
503 real_debug_hooks->function_decl (decl);
504 go_decl (decl);
505 }
506
507 static void
508 go_early_global_decl (tree decl)
509 {
510 go_decl (decl);
511 real_debug_hooks->early_global_decl (decl);
512 }
513
514 /* A global variable decl. */
515
516 static void
517 go_late_global_decl (tree decl)
518 {
519 real_debug_hooks->late_global_decl (decl);
520 }
521
522 /* A type declaration. */
523
524 static void
525 go_type_decl (tree decl, int local)
526 {
527 real_debug_hooks->type_decl (decl, local);
528
529 if (local || DECL_IS_BUILTIN (decl))
530 return;
531 if (DECL_NAME (decl) == NULL_TREE
532 && (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE
533 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) != IDENTIFIER_NODE)
534 && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
535 return;
536 vec_safe_push (queue, decl);
537 }
538
539 /* A container for the data we pass around when generating information
540 at the end of the compilation. */
541
542 struct godump_container
543 {
544 /* DECLs that we have already seen. */
545 hash_set<tree> decls_seen;
546
547 /* Types which may potentially have to be defined as dummy
548 types. */
549 hash_set<const char *> pot_dummy_types;
550
551 /* Go keywords. */
552 htab_t keyword_hash;
553
554 /* Global type definitions. */
555 htab_t type_hash;
556
557 /* Invalid types. */
558 htab_t invalid_hash;
559
560 /* Obstack used to write out a type definition. */
561 struct obstack type_obstack;
562 };
563
564 /* Append an IDENTIFIER_NODE to OB. */
565
566 static void
567 go_append_string (struct obstack *ob, tree id)
568 {
569 obstack_grow (ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
570 }
571
572 /* Given an integer PRECISION in bits, returns a constant string that is the
573 matching go int or uint type (depending on the IS_UNSIGNED flag). Returns a
574 NULL pointer if there is no matching go type. */
575
576 static const char *
577 go_get_uinttype_for_precision (unsigned int precision, bool is_unsigned)
578 {
579 switch (precision)
580 {
581 case 8:
582 return is_unsigned ? "uint8" : "int8";
583 case 16:
584 return is_unsigned ? "uint16" : "int16";
585 case 32:
586 return is_unsigned ? "uint32" : "int32";
587 case 64:
588 return is_unsigned ? "uint64" : "int64";
589 default:
590 return NULL;
591 }
592 }
593
594 /* Append an artificial variable name with the suffix _INDEX to OB. Returns
595 INDEX + 1. */
596
597 static unsigned int
598 go_append_artificial_name (struct obstack *ob, unsigned int index)
599 {
600 char buf[100];
601
602 /* FIXME: identifier may not be unique. */
603 obstack_grow (ob, "Godump_", 7);
604 snprintf (buf, sizeof buf, "%u", index);
605 obstack_grow (ob, buf, strlen (buf));
606
607 return index + 1;
608 }
609
610 /* Append the variable name from DECL to OB. If the name is in the
611 KEYWORD_HASH, prepend an '_'. */
612
613 static void
614 go_append_decl_name (struct obstack *ob, tree decl, htab_t keyword_hash)
615 {
616 const char *var_name;
617 void **slot;
618
619 /* Start variable name with an underscore if a keyword. */
620 var_name = IDENTIFIER_POINTER (DECL_NAME (decl));
621 slot = htab_find_slot (keyword_hash, var_name, NO_INSERT);
622 if (slot != NULL)
623 obstack_1grow (ob, '_');
624 go_append_string (ob, DECL_NAME (decl));
625 }
626
627 /* Appends a byte array with the necessary number of elements and the name
628 "Godump_INDEX_pad" to pad from FROM_OFFSET to TO_OFFSET to OB assuming that
629 the next field is automatically aligned to ALIGN_UNITS. Returns INDEX + 1,
630 or INDEX if no padding had to be appended. The resulting offset where the
631 next field is allocated is returned through RET_OFFSET. */
632
633 static unsigned int
634 go_append_padding (struct obstack *ob, unsigned int from_offset,
635 unsigned int to_offset, unsigned int align_units,
636 unsigned int index, unsigned int *ret_offset)
637 {
638 if (from_offset % align_units > 0)
639 from_offset += align_units - (from_offset % align_units);
640 gcc_assert (to_offset >= from_offset);
641 if (to_offset > from_offset)
642 {
643 char buf[100];
644
645 index = go_append_artificial_name (ob, index);
646 snprintf (buf, sizeof buf, "_pad [%u]byte; ", to_offset - from_offset);
647 obstack_grow (ob, buf, strlen (buf));
648 }
649 *ret_offset = to_offset;
650
651 return index;
652 }
653
654 /* Appends an array of type TYPE_STRING with zero elements and the name
655 "Godump_INDEX_align" to OB. If TYPE_STRING is a null pointer, ERROR_STRING
656 is appended instead of the type. Returns INDEX + 1. */
657
658 static unsigned int
659 go_force_record_alignment (struct obstack *ob, const char *type_string,
660 unsigned int index, const char *error_string)
661 {
662 index = go_append_artificial_name (ob, index);
663 obstack_grow (ob, "_align ", 7);
664 if (type_string == NULL)
665 obstack_grow (ob, error_string, strlen (error_string));
666 else
667 {
668 obstack_grow (ob, "[0]", 3);
669 obstack_grow (ob, type_string, strlen (type_string));
670 }
671 obstack_grow (ob, "; ", 2);
672
673 return index;
674 }
675
676 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
677 USE_TYPE_NAME is true if we can simply use a type name here without
678 needing to define it. IS_FUNC_OK is true if we can output a func
679 type here; the "func" keyword will already have been added.
680 Return true if the type can be represented in Go, false otherwise.
681 P_ART_I is used for indexing artificial elements in nested structures and
682 should always be a NULL pointer when called, except by certain recursive
683 calls from go_format_type() itself. */
684
685 static bool
686 go_format_type (struct godump_container *container, tree type,
687 bool use_type_name, bool is_func_ok, unsigned int *p_art_i,
688 bool is_anon_record_or_union)
689 {
690 bool ret;
691 struct obstack *ob;
692 unsigned int art_i_dummy;
693 bool is_union = false;
694
695 if (p_art_i == NULL)
696 {
697 art_i_dummy = 0;
698 p_art_i = &art_i_dummy;
699 }
700 ret = true;
701 ob = &container->type_obstack;
702
703 if (TYPE_NAME (type) != NULL_TREE
704 && (container->decls_seen.contains (type)
705 || container->decls_seen.contains (TYPE_NAME (type)))
706 && (AGGREGATE_TYPE_P (type)
707 || POINTER_TYPE_P (type)
708 || TREE_CODE (type) == FUNCTION_TYPE))
709 {
710 tree name;
711 void **slot;
712
713 name = TYPE_IDENTIFIER (type);
714
715 slot = htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (name),
716 NO_INSERT);
717 if (slot != NULL)
718 ret = false;
719
720 obstack_1grow (ob, '_');
721 go_append_string (ob, name);
722 return ret;
723 }
724
725 container->decls_seen.add (type);
726
727 switch (TREE_CODE (type))
728 {
729 case ENUMERAL_TYPE:
730 obstack_grow (ob, "int", 3);
731 break;
732
733 case TYPE_DECL:
734 {
735 void **slot;
736
737 slot = htab_find_slot (container->invalid_hash,
738 IDENTIFIER_POINTER (DECL_NAME (type)),
739 NO_INSERT);
740 if (slot != NULL)
741 ret = false;
742
743 obstack_1grow (ob, '_');
744 go_append_string (ob, DECL_NAME (type));
745 }
746 break;
747
748 case INTEGER_TYPE:
749 {
750 const char *s;
751 char buf[100];
752
753 s = go_get_uinttype_for_precision (TYPE_PRECISION (type),
754 TYPE_UNSIGNED (type));
755 if (s == NULL)
756 {
757 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
758 TYPE_PRECISION (type),
759 TYPE_UNSIGNED (type) ? "u" : "");
760 s = buf;
761 ret = false;
762 }
763 obstack_grow (ob, s, strlen (s));
764 }
765 break;
766
767 case REAL_TYPE:
768 {
769 const char *s;
770 char buf[100];
771
772 switch (TYPE_PRECISION (type))
773 {
774 case 32:
775 s = "float32";
776 break;
777 case 64:
778 s = "float64";
779 break;
780 default:
781 snprintf (buf, sizeof buf, "INVALID-float-%u",
782 TYPE_PRECISION (type));
783 s = buf;
784 ret = false;
785 break;
786 }
787 obstack_grow (ob, s, strlen (s));
788 }
789 break;
790
791 case COMPLEX_TYPE:
792 {
793 const char *s;
794 char buf[100];
795 tree real_type;
796
797 real_type = TREE_TYPE (type);
798 if (TREE_CODE (real_type) == REAL_TYPE)
799 {
800 switch (TYPE_PRECISION (real_type))
801 {
802 case 32:
803 s = "complex64";
804 break;
805 case 64:
806 s = "complex128";
807 break;
808 default:
809 snprintf (buf, sizeof buf, "INVALID-complex-%u",
810 2 * TYPE_PRECISION (real_type));
811 s = buf;
812 ret = false;
813 break;
814 }
815 }
816 else
817 {
818 s = "INVALID-complex-non-real";
819 ret = false;
820 }
821 obstack_grow (ob, s, strlen (s));
822 }
823 break;
824
825 case BOOLEAN_TYPE:
826 obstack_grow (ob, "bool", 4);
827 break;
828
829 case POINTER_TYPE:
830 if (use_type_name
831 && TYPE_NAME (TREE_TYPE (type)) != NULL_TREE
832 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))
833 || (POINTER_TYPE_P (TREE_TYPE (type))
834 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type)))
835 == FUNCTION_TYPE))))
836 {
837 tree name;
838 void **slot;
839
840 name = TYPE_IDENTIFIER (TREE_TYPE (type));
841
842 slot = htab_find_slot (container->invalid_hash,
843 IDENTIFIER_POINTER (name), NO_INSERT);
844 if (slot != NULL)
845 ret = false;
846
847 obstack_grow (ob, "*_", 2);
848 go_append_string (ob, name);
849
850 /* The pointer here can be used without the struct or union
851 definition. So this struct or union is a potential dummy
852 type. */
853 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
854 container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
855
856 return ret;
857 }
858 if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
859 obstack_grow (ob, "func", 4);
860 else
861 obstack_1grow (ob, '*');
862 if (VOID_TYPE_P (TREE_TYPE (type)))
863 obstack_grow (ob, "byte", 4);
864 else
865 {
866 if (!go_format_type (container, TREE_TYPE (type), use_type_name,
867 true, NULL, false))
868 ret = false;
869 }
870 break;
871
872 case ARRAY_TYPE:
873 obstack_1grow (ob, '[');
874 if (TYPE_DOMAIN (type) != NULL_TREE
875 && TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
876 && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
877 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
878 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0
879 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
880 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
881 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
882 {
883 char buf[100];
884
885 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
886 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type))));
887 obstack_grow (ob, buf, strlen (buf));
888 }
889 else
890 obstack_1grow (ob, '0');
891 obstack_1grow (ob, ']');
892 if (!go_format_type (container, TREE_TYPE (type), use_type_name, false,
893 NULL, false))
894 ret = false;
895 break;
896
897 case UNION_TYPE:
898 is_union = true;
899 /* Fall through to RECORD_TYPE case. */
900 case RECORD_TYPE:
901 {
902 unsigned int prev_field_end;
903 unsigned int known_alignment;
904 tree field;
905 bool emitted_a_field;
906
907 /* FIXME: Why is this necessary? Without it we can get a core
908 dump on the s390x headers, or from a file containing simply
909 "typedef struct S T;". */
910 layout_type (type);
911
912 prev_field_end = 0;
913 known_alignment = 1;
914 /* Anonymous records and unions are flattened, i.e. they are not put
915 into "struct { ... }". */
916 if (!is_anon_record_or_union)
917 obstack_grow (ob, "struct { ", 9);
918 for (field = TYPE_FIELDS (type), emitted_a_field = false;
919 field != NULL_TREE;
920 field = TREE_CHAIN (field))
921 {
922 if (TREE_CODE (field) != FIELD_DECL)
923 continue;
924 if (DECL_BIT_FIELD (field))
925 /* Bit fields are replaced by padding. */
926 continue;
927 /* Only the first non-bitfield field is emitted for unions. */
928 if (!is_union || !emitted_a_field)
929 {
930 /* Emit the field. */
931 bool field_ok;
932 bool is_anon_substructure;
933 unsigned int decl_align_unit;
934 unsigned int decl_offset;
935
936 field_ok = true;
937 emitted_a_field = true;
938 is_anon_substructure =
939 (DECL_NAME (field) == NULL
940 && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
941 || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE));
942 /* Keep track of the alignment of named substructures, either
943 of the whole record, or the alignment of the emitted field
944 (for unions). */
945 decl_align_unit = DECL_ALIGN_UNIT (field);
946 if (!is_anon_substructure && decl_align_unit > known_alignment)
947 known_alignment = decl_align_unit;
948 /* Pad to start of field. */
949 decl_offset =
950 TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
951 + precision_to_units
952 (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)));
953 {
954 unsigned int align_unit;
955
956 /* For anonymous records and unions there is no automatic
957 structure alignment, so use 1 as the alignment. */
958 align_unit = (is_anon_substructure) ? 1 : decl_align_unit;
959 *p_art_i = go_append_padding
960 (ob, prev_field_end, decl_offset, align_unit, *p_art_i,
961 &prev_field_end);
962 }
963 if (DECL_SIZE_UNIT (field))
964 prev_field_end +=
965 TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
966 /* Emit the field name, but not for anonymous records and
967 unions. */
968 if (!is_anon_substructure)
969 {
970 if ((DECL_NAME (field) == NULL))
971 *p_art_i = go_append_artificial_name (ob, *p_art_i);
972 else
973 go_append_decl_name
974 (ob, field, container->keyword_hash);
975 obstack_1grow (ob, ' ');
976 }
977 /* Do not expand type if a record or union type or a function
978 pointer. */
979 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
980 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
981 || (POINTER_TYPE_P (TREE_TYPE (field))
982 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
983 == FUNCTION_TYPE))))
984 {
985 tree name;
986 void **slot;
987
988 name = TYPE_IDENTIFIER (TREE_TYPE (field));
989
990 slot = htab_find_slot (container->invalid_hash,
991 IDENTIFIER_POINTER (name),
992 NO_INSERT);
993 if (slot != NULL)
994 field_ok = false;
995
996 obstack_1grow (ob, '_');
997 go_append_string (ob, name);
998 }
999 else
1000 {
1001 if (!go_format_type (container, TREE_TYPE (field), true,
1002 false, p_art_i, is_anon_substructure))
1003 field_ok = false;
1004 }
1005 if (!is_anon_substructure)
1006 obstack_grow (ob, "; ", 2);
1007 if (!field_ok)
1008 ret = false;
1009 }
1010 }
1011 /* Padding. */
1012 {
1013 unsigned int align_unit;
1014
1015 align_unit = (is_anon_record_or_union) ? 1 : TYPE_ALIGN_UNIT (type);
1016 *p_art_i = go_append_padding
1017 (ob, prev_field_end, TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type)),
1018 align_unit, *p_art_i, &prev_field_end);
1019 }
1020 /* Alignment. */
1021 if (!is_anon_record_or_union
1022 && known_alignment < TYPE_ALIGN_UNIT (type))
1023 {
1024 const char *s;
1025 char buf[100];
1026
1027 /* Enforce proper record alignment. */
1028 s = go_get_uinttype_for_precision
1029 (TYPE_ALIGN (type), TYPE_UNSIGNED (type));
1030 if (s == NULL)
1031 {
1032 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
1033 TYPE_ALIGN (type), TYPE_UNSIGNED (type) ? "u" : "");
1034 s = buf;
1035 ret = false;
1036 }
1037 *p_art_i = go_force_record_alignment (ob, s, *p_art_i, buf);
1038 }
1039 if (!is_anon_record_or_union)
1040 obstack_1grow (ob, '}');
1041 }
1042 break;
1043
1044 case FUNCTION_TYPE:
1045 {
1046 tree arg_type;
1047 bool is_varargs;
1048 tree result;
1049 function_args_iterator iter;
1050 bool seen_arg;
1051
1052 /* Go has no way to write a type which is a function but not a
1053 pointer to a function. */
1054 if (!is_func_ok)
1055 {
1056 obstack_grow (ob, "func*", 5);
1057 ret = false;
1058 }
1059
1060 obstack_1grow (ob, '(');
1061 is_varargs = stdarg_p (type);
1062 seen_arg = false;
1063 FOREACH_FUNCTION_ARGS (type, arg_type, iter)
1064 {
1065 if (VOID_TYPE_P (arg_type))
1066 break;
1067 if (seen_arg)
1068 obstack_grow (ob, ", ", 2);
1069 if (!go_format_type (container, arg_type, true, false, NULL, false))
1070 ret = false;
1071 seen_arg = true;
1072 }
1073 if (is_varargs)
1074 {
1075 if (prototype_p (type))
1076 obstack_grow (ob, ", ", 2);
1077 obstack_grow (ob, "...interface{}", 14);
1078 }
1079 obstack_1grow (ob, ')');
1080
1081 result = TREE_TYPE (type);
1082 if (!VOID_TYPE_P (result))
1083 {
1084 obstack_1grow (ob, ' ');
1085 if (!go_format_type (container, result, use_type_name, false, NULL,
1086 false))
1087 ret = false;
1088 }
1089 }
1090 break;
1091
1092 default:
1093 obstack_grow (ob, "INVALID-type", 12);
1094 ret = false;
1095 break;
1096 }
1097
1098 return ret;
1099 }
1100
1101 /* Output the type which was built on the type obstack, and then free
1102 it. */
1103
1104 static void
1105 go_output_type (struct godump_container *container)
1106 {
1107 struct obstack *ob;
1108
1109 ob = &container->type_obstack;
1110 obstack_1grow (ob, '\0');
1111 fputs ((char *) obstack_base (ob), go_dump_file);
1112 obstack_free (ob, obstack_base (ob));
1113 }
1114
1115 /* Output a function declaration. */
1116
1117 static void
1118 go_output_fndecl (struct godump_container *container, tree decl)
1119 {
1120 if (!go_format_type (container, TREE_TYPE (decl), false, true, NULL, false))
1121 fprintf (go_dump_file, "// ");
1122 fprintf (go_dump_file, "func _%s ",
1123 IDENTIFIER_POINTER (DECL_NAME (decl)));
1124 go_output_type (container);
1125 fprintf (go_dump_file, " __asm__(\"%s\")\n",
1126 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
1127 }
1128
1129 /* Output a typedef or something like a struct definition. */
1130
1131 static void
1132 go_output_typedef (struct godump_container *container, tree decl)
1133 {
1134 /* If we have an enum type, output the enum constants
1135 separately. */
1136 if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
1137 && TYPE_SIZE (TREE_TYPE (decl)) != 0
1138 && !container->decls_seen.contains (TREE_TYPE (decl))
1139 && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
1140 || !container->decls_seen.contains
1141 (TYPE_CANONICAL (TREE_TYPE (decl)))))
1142 {
1143 tree element;
1144
1145 for (element = TYPE_VALUES (TREE_TYPE (decl));
1146 element != NULL_TREE;
1147 element = TREE_CHAIN (element))
1148 {
1149 const char *name;
1150 struct macro_hash_value *mhval;
1151 void **slot;
1152 char buf[WIDE_INT_PRINT_BUFFER_SIZE];
1153
1154 name = IDENTIFIER_POINTER (TREE_PURPOSE (element));
1155
1156 /* Sometimes a name will be defined as both an enum constant
1157 and a macro. Avoid duplicate definition errors by
1158 treating enum constants as macros. */
1159 mhval = XNEW (struct macro_hash_value);
1160 mhval->name = xstrdup (name);
1161 mhval->value = NULL;
1162 slot = htab_find_slot (macro_hash, mhval, INSERT);
1163 if (*slot != NULL)
1164 macro_hash_del (*slot);
1165
1166 if (tree_fits_shwi_p (TREE_VALUE (element)))
1167 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC,
1168 tree_to_shwi (TREE_VALUE (element)));
1169 else if (tree_fits_uhwi_p (TREE_VALUE (element)))
1170 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_UNSIGNED,
1171 tree_to_uhwi (TREE_VALUE (element)));
1172 else
1173 print_hex (element, buf);
1174
1175 mhval->value = xstrdup (buf);
1176 *slot = mhval;
1177 }
1178 container->decls_seen.add (TREE_TYPE (decl));
1179 if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
1180 container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl)));
1181 }
1182
1183 if (DECL_NAME (decl) != NULL_TREE)
1184 {
1185 void **slot;
1186 const char *type;
1187
1188 type = IDENTIFIER_POINTER (DECL_NAME (decl));
1189 /* If type defined already, skip. */
1190 slot = htab_find_slot (container->type_hash, type, INSERT);
1191 if (*slot != NULL)
1192 return;
1193 *slot = CONST_CAST (void *, (const void *) type);
1194
1195 if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL,
1196 false))
1197 {
1198 fprintf (go_dump_file, "// ");
1199 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1200 *slot = CONST_CAST (void *, (const void *) type);
1201 }
1202 fprintf (go_dump_file, "type _%s ",
1203 IDENTIFIER_POINTER (DECL_NAME (decl)));
1204 go_output_type (container);
1205
1206 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1207 {
1208 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
1209
1210 if (size > 0)
1211 fprintf (go_dump_file,
1212 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1213 IDENTIFIER_POINTER (DECL_NAME (decl)),
1214 size);
1215 }
1216
1217 container->decls_seen.add (decl);
1218 }
1219 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1220 {
1221 void **slot;
1222 const char *type;
1223 HOST_WIDE_INT size;
1224
1225 type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
1226 /* If type defined already, skip. */
1227 slot = htab_find_slot (container->type_hash, type, INSERT);
1228 if (*slot != NULL)
1229 return;
1230 *slot = CONST_CAST (void *, (const void *) type);
1231
1232 if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL,
1233 false))
1234 {
1235 fprintf (go_dump_file, "// ");
1236 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1237 *slot = CONST_CAST (void *, (const void *) type);
1238 }
1239 fprintf (go_dump_file, "type _%s ",
1240 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
1241 go_output_type (container);
1242
1243 size = int_size_in_bytes (TREE_TYPE (decl));
1244 if (size > 0)
1245 fprintf (go_dump_file,
1246 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1247 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))),
1248 size);
1249 }
1250 else
1251 return;
1252
1253 fprintf (go_dump_file, "\n");
1254 }
1255
1256 /* Output a variable. */
1257
1258 static void
1259 go_output_var (struct godump_container *container, tree decl)
1260 {
1261 bool is_valid;
1262 tree type_name;
1263 tree id;
1264
1265 if (container->decls_seen.contains (decl)
1266 || container->decls_seen.contains (DECL_NAME (decl)))
1267 return;
1268 container->decls_seen.add (decl);
1269 container->decls_seen.add (DECL_NAME (decl));
1270
1271 type_name = TYPE_NAME (TREE_TYPE (decl));
1272 id = NULL_TREE;
1273 if (type_name != NULL_TREE && TREE_CODE (type_name) == IDENTIFIER_NODE)
1274 id = type_name;
1275 else if (type_name != NULL_TREE && TREE_CODE (type_name) == TYPE_DECL
1276 && DECL_SOURCE_LOCATION (type_name) != BUILTINS_LOCATION
1277 && DECL_NAME (type_name))
1278 id = DECL_NAME (type_name);
1279 if (id != NULL_TREE
1280 && (!htab_find_slot (container->type_hash, IDENTIFIER_POINTER (id),
1281 NO_INSERT)
1282 || htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (id),
1283 NO_INSERT)))
1284 id = NULL_TREE;
1285 if (id != NULL_TREE)
1286 {
1287 struct obstack *ob;
1288
1289 ob = &container->type_obstack;
1290 obstack_1grow (ob, '_');
1291 go_append_string (ob, id);
1292 is_valid = htab_find_slot (container->type_hash, IDENTIFIER_POINTER (id),
1293 NO_INSERT) != NULL;
1294 }
1295 else
1296 is_valid = go_format_type (container, TREE_TYPE (decl), true, false, NULL,
1297 false);
1298 if (is_valid
1299 && htab_find_slot (container->type_hash,
1300 IDENTIFIER_POINTER (DECL_NAME (decl)),
1301 NO_INSERT) != NULL)
1302 {
1303 /* There is already a type with this name, probably from a
1304 struct tag. Prefer the type to the variable. */
1305 is_valid = false;
1306 }
1307 if (!is_valid)
1308 fprintf (go_dump_file, "// ");
1309
1310 fprintf (go_dump_file, "var _%s ",
1311 IDENTIFIER_POINTER (DECL_NAME (decl)));
1312 go_output_type (container);
1313 fprintf (go_dump_file, "\n");
1314
1315 /* Sometimes an extern variable is declared with an unknown struct
1316 type. */
1317 if (type_name != NULL_TREE && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1318 {
1319 if (TREE_CODE (type_name) == IDENTIFIER_NODE)
1320 container->pot_dummy_types.add (IDENTIFIER_POINTER (type_name));
1321 else if (TREE_CODE (type_name) == TYPE_DECL)
1322 container->pot_dummy_types.add
1323 (IDENTIFIER_POINTER (DECL_NAME (type_name)));
1324 }
1325 }
1326
1327 /* Output the final value of a preprocessor macro or enum constant.
1328 This is called via htab_traverse_noresize. */
1329
1330 static int
1331 go_print_macro (void **slot, void *arg ATTRIBUTE_UNUSED)
1332 {
1333 struct macro_hash_value *mhval = (struct macro_hash_value *) *slot;
1334 fprintf (go_dump_file, "const _%s = %s\n", mhval->name, mhval->value);
1335 return 1;
1336 }
1337
1338 /* Build a hash table with the Go keywords. */
1339
1340 static const char * const keywords[] = {
1341 "__asm__", "break", "case", "chan", "const", "continue", "default",
1342 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1343 "import", "interface", "map", "package", "range", "return", "select",
1344 "struct", "switch", "type", "var"
1345 };
1346
1347 static void
1348 keyword_hash_init (struct godump_container *container)
1349 {
1350 size_t i;
1351 size_t count = sizeof (keywords) / sizeof (keywords[0]);
1352 void **slot;
1353
1354 for (i = 0; i < count; i++)
1355 {
1356 slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
1357 *slot = CONST_CAST (void *, (const void *) keywords[i]);
1358 }
1359 }
1360
1361 /* Traversing the pot_dummy_types and seeing which types are present
1362 in the global types hash table and creating dummy definitions if
1363 not found. This function is invoked by hash_set::traverse. */
1364
1365 bool
1366 find_dummy_types (const char *const &ptr, godump_container *adata)
1367 {
1368 struct godump_container *data = (struct godump_container *) adata;
1369 const char *type = (const char *) ptr;
1370 void **slot;
1371 void **islot;
1372
1373 slot = htab_find_slot (data->type_hash, type, NO_INSERT);
1374 islot = htab_find_slot (data->invalid_hash, type, NO_INSERT);
1375 if (slot == NULL || islot != NULL)
1376 fprintf (go_dump_file, "type _%s struct {}\n", type);
1377 return true;
1378 }
1379
1380 /* Output symbols. */
1381
1382 static void
1383 go_finish (const char *filename)
1384 {
1385 struct godump_container container;
1386 unsigned int ix;
1387 tree decl;
1388
1389 real_debug_hooks->finish (filename);
1390
1391 container.type_hash = htab_create (100, htab_hash_string,
1392 string_hash_eq, NULL);
1393 container.invalid_hash = htab_create (10, htab_hash_string,
1394 string_hash_eq, NULL);
1395 container.keyword_hash = htab_create (50, htab_hash_string,
1396 string_hash_eq, NULL);
1397 obstack_init (&container.type_obstack);
1398
1399 keyword_hash_init (&container);
1400
1401 FOR_EACH_VEC_SAFE_ELT (queue, ix, decl)
1402 {
1403 switch (TREE_CODE (decl))
1404 {
1405 case FUNCTION_DECL:
1406 go_output_fndecl (&container, decl);
1407 break;
1408
1409 case TYPE_DECL:
1410 go_output_typedef (&container, decl);
1411 break;
1412
1413 case VAR_DECL:
1414 go_output_var (&container, decl);
1415 break;
1416
1417 default:
1418 gcc_unreachable ();
1419 }
1420 }
1421
1422 htab_traverse_noresize (macro_hash, go_print_macro, NULL);
1423
1424 /* To emit dummy definitions. */
1425 container.pot_dummy_types.traverse<godump_container *, find_dummy_types>
1426 (&container);
1427
1428 htab_delete (container.type_hash);
1429 htab_delete (container.invalid_hash);
1430 htab_delete (container.keyword_hash);
1431 obstack_free (&container.type_obstack, NULL);
1432
1433 vec_free (queue);
1434
1435 if (fclose (go_dump_file) != 0)
1436 error ("could not close Go dump file: %m");
1437 go_dump_file = NULL;
1438 }
1439
1440 /* Set up our hooks. */
1441
1442 const struct gcc_debug_hooks *
1443 dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
1444 {
1445 go_dump_file = fopen (filename, "w");
1446 if (go_dump_file == NULL)
1447 {
1448 error ("could not open Go dump file %qs: %m", filename);
1449 return hooks;
1450 }
1451
1452 go_debug_hooks = *hooks;
1453 real_debug_hooks = hooks;
1454
1455 go_debug_hooks.finish = go_finish;
1456 go_debug_hooks.define = go_define;
1457 go_debug_hooks.undef = go_undef;
1458 go_debug_hooks.function_decl = go_function_decl;
1459 go_debug_hooks.early_global_decl = go_early_global_decl;
1460 go_debug_hooks.late_global_decl = go_late_global_decl;
1461 go_debug_hooks.type_decl = go_type_decl;
1462
1463 macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq,
1464 macro_hash_del);
1465
1466 return &go_debug_hooks;
1467 }
1468
1469 #include "gt-godump.h"