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