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