compiler: add missing Slice_info_expression::do_traverse
[official-gcc.git] / gcc / godump.cc
blob0893d5fbc976bd0d0fc96cd1caf9c64aa927a4b5
1 /* Output Go language descriptions of types.
2 Copyright (C) 2008-2023 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 "tree.h"
34 #include "diagnostic-core.h"
35 #include "debug.h"
36 #include "stor-layout.h"
38 /* We dump this information from the debug hooks. This gives us a
39 stable and maintainable API to hook into. In order to work
40 correctly when -g is used, we build our own hooks structure which
41 wraps the hooks we need to change. */
43 /* Our debug hooks. This is initialized by dump_go_spec_init. */
45 static struct gcc_debug_hooks go_debug_hooks;
47 /* The real debug hooks. */
49 static const struct gcc_debug_hooks *real_debug_hooks;
51 /* The file where we should write information. */
53 static FILE *go_dump_file;
55 /* A queue of decls to output. */
57 static GTY(()) vec<tree, va_gc> *queue;
59 struct godump_str_hash : string_hash, ggc_remove <const char *> {};
61 /* A hash table of macros we have seen. */
63 static htab_t macro_hash;
65 /* The type of a value in macro_hash. */
67 struct macro_hash_value
69 /* The name stored in the hash table. */
70 char *name;
71 /* The value of the macro. */
72 char *value;
75 /* Returns the number of units necessary to represent an integer with the given
76 PRECISION (in bits). */
78 static inline unsigned int
79 precision_to_units (unsigned int precision)
81 return (precision + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
84 /* Calculate the hash value for an entry in the macro hash table. */
86 static hashval_t
87 macro_hash_hashval (const void *val)
89 const struct macro_hash_value *mhval = (const struct macro_hash_value *) val;
90 return htab_hash_string (mhval->name);
93 /* Compare values in the macro hash table for equality. */
95 static int
96 macro_hash_eq (const void *v1, const void *v2)
98 const struct macro_hash_value *mhv1 = (const struct macro_hash_value *) v1;
99 const struct macro_hash_value *mhv2 = (const struct macro_hash_value *) v2;
100 return strcmp (mhv1->name, mhv2->name) == 0;
103 /* Free values deleted from the macro hash table. */
105 static void
106 macro_hash_del (void *v)
108 struct macro_hash_value *mhv = (struct macro_hash_value *) v;
109 XDELETEVEC (mhv->name);
110 XDELETEVEC (mhv->value);
111 XDELETE (mhv);
114 /* A macro definition. */
116 static void
117 go_define (unsigned int lineno, const char *buffer)
119 const char *p;
120 const char *name_end;
121 size_t out_len;
122 char *out_buffer;
123 char *q;
124 bool saw_operand;
125 bool need_operand;
126 struct macro_hash_value *mhval;
127 char *copy;
128 hashval_t hashval;
129 void **slot;
131 real_debug_hooks->define (lineno, buffer);
133 /* Skip macro functions. */
134 for (p = buffer; *p != '\0' && *p != ' '; ++p)
135 if (*p == '(')
136 return;
138 if (*p == '\0')
139 return;
141 name_end = p;
143 ++p;
144 if (*p == '\0')
145 return;
147 copy = XNEWVEC (char, name_end - buffer + 1);
148 memcpy (copy, buffer, name_end - buffer);
149 copy[name_end - buffer] = '\0';
151 mhval = XNEW (struct macro_hash_value);
152 mhval->name = copy;
153 mhval->value = NULL;
155 hashval = htab_hash_string (copy);
156 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, NO_INSERT);
158 /* For simplicity, we force all names to be hidden by adding an
159 initial underscore, and let the user undo this as needed. */
160 out_len = strlen (p) * 2 + 1;
161 out_buffer = XNEWVEC (char, out_len);
162 q = out_buffer;
163 saw_operand = false;
164 need_operand = false;
165 while (*p != '\0')
167 switch (*p)
169 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
170 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
171 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
172 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
173 case 'Y': case 'Z':
174 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
175 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
176 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
177 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
178 case 'y': case 'z':
179 case '_':
181 /* The start of an identifier. Technically we should also
182 worry about UTF-8 identifiers, but they are not a
183 problem for practical uses of -fdump-go-spec so we
184 don't worry about them. */
185 const char *start;
186 char *n;
187 struct macro_hash_value idval;
189 if (saw_operand)
190 goto unknown;
192 start = p;
193 while (ISALNUM (*p) || *p == '_')
194 ++p;
195 n = XALLOCAVEC (char, p - start + 1);
196 memcpy (n, start, p - start);
197 n[p - start] = '\0';
198 idval.name = n;
199 idval.value = NULL;
200 if (htab_find (macro_hash, &idval) == NULL)
202 /* This is a reference to a name which was not defined
203 as a macro. */
204 goto unknown;
207 *q++ = '_';
208 memcpy (q, start, p - start);
209 q += p - start;
211 saw_operand = true;
212 need_operand = false;
214 break;
216 case '.':
217 if (!ISDIGIT (p[1]))
218 goto unknown;
219 /* Fall through. */
220 case '0': case '1': case '2': case '3': case '4':
221 case '5': case '6': case '7': case '8': case '9':
223 const char *start;
224 bool is_hex;
226 start = p;
227 is_hex = false;
228 if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
230 p += 2;
231 is_hex = true;
233 while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
234 || (is_hex
235 && ((*p >= 'a' && *p <= 'f')
236 || (*p >= 'A' && *p <= 'F'))))
237 ++p;
238 memcpy (q, start, p - start);
239 q += p - start;
240 while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
241 || *p == 'f' || *p == 'F'
242 || *p == 'd' || *p == 'D')
244 /* Go doesn't use any of these trailing type
245 modifiers. */
246 ++p;
249 /* We'll pick up the exponent, if any, as an
250 expression. */
252 saw_operand = true;
253 need_operand = false;
255 break;
257 case ' ': case '\t':
258 *q++ = *p++;
259 break;
261 case '(':
262 /* Always OK, not part of an operand, presumed to start an
263 operand. */
264 *q++ = *p++;
265 saw_operand = false;
266 need_operand = false;
267 break;
269 case ')':
270 /* OK if we don't need an operand, and presumed to indicate
271 an operand. */
272 if (need_operand)
273 goto unknown;
274 *q++ = *p++;
275 saw_operand = true;
276 break;
278 case '+': case '-':
279 /* Always OK, but not part of an operand. */
280 *q++ = *p++;
281 saw_operand = false;
282 break;
284 case '*': case '/': case '%': case '|': case '&': case '^':
285 /* Must be a binary operator. */
286 if (!saw_operand)
287 goto unknown;
288 *q++ = *p++;
289 saw_operand = false;
290 need_operand = true;
291 break;
293 case '=':
294 *q++ = *p++;
295 if (*p != '=')
296 goto unknown;
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 == '=')
309 /* Must be a binary operator. */
310 if (!saw_operand)
311 goto unknown;
312 *q++ = *p++;
313 saw_operand = false;
314 need_operand = true;
316 else
318 /* Must be a unary operator. */
319 if (saw_operand)
320 goto unknown;
321 need_operand = true;
323 break;
325 case '<': case '>':
326 /* Must be a binary operand, may be << or >> or <= or >=. */
327 if (!saw_operand)
328 goto unknown;
329 *q++ = *p++;
330 if (*p == *(p - 1) || *p == '=')
331 *q++ = *p++;
332 saw_operand = false;
333 need_operand = true;
334 break;
336 case '~':
337 /* Must be a unary operand, must be translated for Go. */
338 if (saw_operand)
339 goto unknown;
340 *q++ = '^';
341 p++;
342 need_operand = true;
343 break;
345 case '"':
346 case '\'':
348 char quote;
349 int count;
351 if (saw_operand)
352 goto unknown;
353 quote = *p;
354 *q++ = *p++;
355 count = 0;
356 while (*p != quote)
358 int c;
360 if (*p == '\0')
361 goto unknown;
363 ++count;
365 if (*p != '\\')
367 *q++ = *p++;
368 continue;
371 *q++ = *p++;
372 switch (*p)
374 case '0': case '1': case '2': case '3':
375 case '4': case '5': case '6': case '7':
376 c = 0;
377 while (*p >= '0' && *p <= '7')
379 *q++ = *p++;
380 ++c;
382 /* Go octal characters are always 3
383 digits. */
384 if (c != 3)
385 goto unknown;
386 break;
388 case 'x':
389 *q++ = *p++;
390 c = 0;
391 while (ISXDIGIT (*p))
393 *q++ = *p++;
394 ++c;
396 /* Go hex characters are always 2 digits. */
397 if (c != 2)
398 goto unknown;
399 break;
401 case 'a': case 'b': case 'f': case 'n': case 'r':
402 case 't': case 'v': case '\\': case '\'': case '"':
403 *q++ = *p++;
404 break;
406 default:
407 goto unknown;
411 *q++ = *p++;
413 if (quote == '\'' && count != 1)
414 goto unknown;
416 saw_operand = true;
417 need_operand = false;
419 break;
422 default:
423 goto unknown;
427 if (need_operand)
428 goto unknown;
430 gcc_assert ((size_t) (q - out_buffer) < out_len);
431 *q = '\0';
433 mhval->value = out_buffer;
435 if (slot == NULL)
437 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, INSERT);
438 gcc_assert (slot != NULL && *slot == NULL);
440 else
442 if (*slot != NULL)
443 macro_hash_del (*slot);
446 *slot = mhval;
448 return;
450 unknown:
451 fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
452 if (slot != NULL)
453 htab_clear_slot (macro_hash, slot);
454 XDELETEVEC (out_buffer);
455 XDELETEVEC (copy);
458 /* A macro undef. */
460 static void
461 go_undef (unsigned int lineno, const char *buffer)
463 struct macro_hash_value mhval;
464 void **slot;
466 real_debug_hooks->undef (lineno, buffer);
468 mhval.name = CONST_CAST (char *, buffer);
469 mhval.value = NULL;
470 slot = htab_find_slot (macro_hash, &mhval, NO_INSERT);
471 if (slot != NULL)
472 htab_clear_slot (macro_hash, slot);
475 /* A function or variable decl. */
477 static void
478 go_decl (tree decl)
480 if (!TREE_PUBLIC (decl)
481 || DECL_IS_UNDECLARED_BUILTIN (decl)
482 || DECL_NAME (decl) == NULL_TREE)
483 return;
484 vec_safe_push (queue, decl);
487 /* A function decl. */
489 static void
490 go_function_decl (tree decl)
492 real_debug_hooks->function_decl (decl);
493 go_decl (decl);
496 static void
497 go_early_global_decl (tree decl)
499 go_decl (decl);
500 if (TREE_CODE (decl) != FUNCTION_DECL || DECL_STRUCT_FUNCTION (decl) != NULL)
501 real_debug_hooks->early_global_decl (decl);
504 /* A global variable decl. */
506 static void
507 go_late_global_decl (tree decl)
509 real_debug_hooks->late_global_decl (decl);
512 /* A type declaration. */
514 static void
515 go_type_decl (tree decl, int local)
517 real_debug_hooks->type_decl (decl, local);
519 if (local || DECL_IS_UNDECLARED_BUILTIN (decl))
520 return;
521 if (DECL_NAME (decl) == NULL_TREE
522 && (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE
523 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) != IDENTIFIER_NODE)
524 && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
525 return;
526 vec_safe_push (queue, decl);
529 /* A container for the data we pass around when generating information
530 at the end of the compilation. */
532 class godump_container
534 public:
535 /* DECLs that we have already seen. */
536 hash_set<tree> decls_seen;
538 /* Types which may potentially have to be defined as dummy
539 types. */
540 hash_set<const char *, false, godump_str_hash> pot_dummy_types;
542 /* Go keywords. */
543 htab_t keyword_hash;
545 /* Global type definitions. */
546 htab_t type_hash;
548 /* Invalid types. */
549 htab_t invalid_hash;
551 /* Obstack used to write out a type definition. */
552 struct obstack type_obstack;
555 /* Append an IDENTIFIER_NODE to OB. */
557 static void
558 go_append_string (struct obstack *ob, tree id)
560 obstack_grow (ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
563 /* Given an integer PRECISION in bits, returns a constant string that is the
564 matching go int or uint type (depending on the IS_UNSIGNED flag). Returns a
565 NULL pointer if there is no matching go type. */
567 static const char *
568 go_get_uinttype_for_precision (unsigned int precision, bool is_unsigned)
570 switch (precision)
572 case 8:
573 return is_unsigned ? "uint8" : "int8";
574 case 16:
575 return is_unsigned ? "uint16" : "int16";
576 case 32:
577 return is_unsigned ? "uint32" : "int32";
578 case 64:
579 return is_unsigned ? "uint64" : "int64";
580 default:
581 return NULL;
585 /* Append an artificial variable name with the suffix _INDEX to OB. Returns
586 INDEX + 1. */
588 static unsigned int
589 go_append_artificial_name (struct obstack *ob, unsigned int index)
591 char buf[100];
593 /* FIXME: identifier may not be unique. */
594 obstack_grow (ob, "Godump_", 7);
595 snprintf (buf, sizeof buf, "%u", index);
596 obstack_grow (ob, buf, strlen (buf));
598 return index + 1;
601 /* Append the variable name from DECL to OB. If the name is in the
602 KEYWORD_HASH, prepend an '_'. */
604 static void
605 go_append_decl_name (struct obstack *ob, tree decl, htab_t keyword_hash)
607 const char *var_name;
608 void **slot;
610 /* Start variable name with an underscore if a keyword. */
611 var_name = IDENTIFIER_POINTER (DECL_NAME (decl));
612 slot = htab_find_slot (keyword_hash, var_name, NO_INSERT);
613 if (slot != NULL)
614 obstack_1grow (ob, '_');
615 go_append_string (ob, DECL_NAME (decl));
618 /* Appends a byte array with the necessary number of elements and the name
619 "Godump_INDEX_pad" to pad from FROM_OFFSET to TO_OFFSET to OB assuming that
620 the next field is automatically aligned to ALIGN_UNITS. Returns INDEX + 1,
621 or INDEX if no padding had to be appended. The resulting offset where the
622 next field is allocated is returned through RET_OFFSET. */
624 static unsigned int
625 go_append_padding (struct obstack *ob, unsigned int from_offset,
626 unsigned int to_offset, unsigned int align_units,
627 unsigned int index, unsigned int *ret_offset)
629 if (from_offset % align_units > 0)
630 from_offset += align_units - (from_offset % align_units);
631 gcc_assert (to_offset >= from_offset);
632 if (to_offset > from_offset)
634 char buf[100];
636 index = go_append_artificial_name (ob, index);
637 snprintf (buf, sizeof buf, "_pad [%u]byte; ", to_offset - from_offset);
638 obstack_grow (ob, buf, strlen (buf));
640 *ret_offset = to_offset;
642 return index;
645 /* Appends an array of type TYPE_STRING with zero elements and the name
646 "_" to OB. If TYPE_STRING is a null pointer, ERROR_STRING is appended
647 instead of the type. Returns INDEX + 1. */
649 static unsigned int
650 go_force_record_alignment (struct obstack *ob, const char *type_string,
651 unsigned int index, const char *error_string)
653 obstack_grow (ob, "_ ", 2);
654 if (type_string == NULL)
655 obstack_grow (ob, error_string, strlen (error_string));
656 else
658 obstack_grow (ob, "[0]", 3);
659 obstack_grow (ob, type_string, strlen (type_string));
661 obstack_grow (ob, "; ", 2);
663 return index;
666 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
667 USE_TYPE_NAME is true if we can simply use a type name here without
668 needing to define it. IS_FUNC_OK is true if we can output a func
669 type here; the "func" keyword will already have been added.
670 Return true if the type can be represented in Go, false otherwise.
671 P_ART_I is used for indexing artificial elements in nested structures and
672 should always be a NULL pointer when called, except by certain recursive
673 calls from go_format_type() itself. */
675 static bool
676 go_format_type (class godump_container *container, tree type,
677 bool use_type_name, bool is_func_ok, unsigned int *p_art_i,
678 bool is_anon_record_or_union)
680 bool ret;
681 struct obstack *ob;
682 unsigned int art_i_dummy;
683 bool is_union = false;
685 if (p_art_i == NULL)
687 art_i_dummy = 0;
688 p_art_i = &art_i_dummy;
690 ret = true;
691 ob = &container->type_obstack;
693 if (use_type_name
694 && TYPE_NAME (type) != NULL_TREE
695 && (AGGREGATE_TYPE_P (type)
696 || POINTER_TYPE_P (type)
697 || TREE_CODE (type) == FUNCTION_TYPE))
699 tree name;
700 void **slot;
702 /* References to complex builtin types cannot be translated to
703 Go. */
704 if (DECL_P (TYPE_NAME (type))
705 && DECL_IS_UNDECLARED_BUILTIN (TYPE_NAME (type)))
706 ret = false;
708 name = TYPE_IDENTIFIER (type);
710 slot = htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (name),
711 NO_INSERT);
712 if (slot != NULL)
713 ret = false;
715 /* References to incomplete structs are permitted in many
716 contexts, like behind a pointer or inside of a typedef. So
717 consider any referenced struct a potential dummy type. */
718 if (RECORD_OR_UNION_TYPE_P (type))
719 container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
721 obstack_1grow (ob, '_');
722 go_append_string (ob, name);
723 return ret;
726 switch (TREE_CODE (type))
728 case TYPE_DECL:
730 void **slot;
732 slot = htab_find_slot (container->invalid_hash,
733 IDENTIFIER_POINTER (DECL_NAME (type)),
734 NO_INSERT);
735 if (slot != NULL)
736 ret = false;
738 obstack_1grow (ob, '_');
739 go_append_string (ob, DECL_NAME (type));
741 break;
743 case ENUMERAL_TYPE:
744 case INTEGER_TYPE:
746 const char *s;
747 char buf[100];
749 s = go_get_uinttype_for_precision (TYPE_PRECISION (type),
750 TYPE_UNSIGNED (type));
751 if (s == NULL)
753 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
754 TYPE_PRECISION (type),
755 TYPE_UNSIGNED (type) ? "u" : "");
756 s = buf;
757 ret = false;
759 obstack_grow (ob, s, strlen (s));
761 break;
763 case REAL_TYPE:
765 const char *s;
766 char buf[100];
768 switch (TYPE_PRECISION (type))
770 case 32:
771 s = "float32";
772 break;
773 case 64:
774 s = "float64";
775 break;
776 default:
777 snprintf (buf, sizeof buf, "INVALID-float-%u",
778 TYPE_PRECISION (type));
779 s = buf;
780 ret = false;
781 break;
783 obstack_grow (ob, s, strlen (s));
785 break;
787 case COMPLEX_TYPE:
789 const char *s;
790 char buf[100];
791 tree real_type;
793 real_type = TREE_TYPE (type);
794 if (TREE_CODE (real_type) == REAL_TYPE)
796 switch (TYPE_PRECISION (real_type))
798 case 32:
799 s = "complex64";
800 break;
801 case 64:
802 s = "complex128";
803 break;
804 default:
805 snprintf (buf, sizeof buf, "INVALID-complex-%u",
806 2 * TYPE_PRECISION (real_type));
807 s = buf;
808 ret = false;
809 break;
812 else
814 s = "INVALID-complex-non-real";
815 ret = false;
817 obstack_grow (ob, s, strlen (s));
819 break;
821 case BOOLEAN_TYPE:
822 obstack_grow (ob, "bool", 4);
823 break;
825 case POINTER_TYPE:
826 if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
827 obstack_grow (ob, "func", 4);
828 else
829 obstack_1grow (ob, '*');
830 if (VOID_TYPE_P (TREE_TYPE (type)))
831 obstack_grow (ob, "byte", 4);
832 else
834 if (!go_format_type (container, TREE_TYPE (type), use_type_name,
835 true, NULL, false))
836 ret = false;
838 break;
840 case ARRAY_TYPE:
841 obstack_1grow (ob, '[');
842 if (TYPE_DOMAIN (type) != NULL_TREE
843 && TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
844 && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
845 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
846 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0
847 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
848 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
849 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
851 char buf[100];
853 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
854 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type))));
855 obstack_grow (ob, buf, strlen (buf));
857 else
858 obstack_1grow (ob, '0');
859 obstack_1grow (ob, ']');
860 if (!go_format_type (container, TREE_TYPE (type), use_type_name, false,
861 NULL, false))
862 ret = false;
863 break;
865 case UNION_TYPE:
866 is_union = true;
867 /* Fall through to RECORD_TYPE case. */
868 gcc_fallthrough ();
869 case RECORD_TYPE:
871 unsigned int prev_field_end;
872 unsigned int known_alignment;
873 tree field;
874 bool emitted_a_field;
876 /* FIXME: Why is this necessary? Without it we can get a core
877 dump on the s390x headers, or from a file containing simply
878 "typedef struct S T;". */
879 layout_type (type);
881 prev_field_end = 0;
882 known_alignment = 1;
883 /* Anonymous records and unions are flattened, i.e. they are not put
884 into "struct { ... }". */
885 if (!is_anon_record_or_union)
886 obstack_grow (ob, "struct { ", 9);
887 for (field = TYPE_FIELDS (type), emitted_a_field = false;
888 field != NULL_TREE;
889 field = TREE_CHAIN (field))
891 if (TREE_CODE (field) != FIELD_DECL)
892 continue;
893 if (DECL_BIT_FIELD (field))
894 /* Bit fields are replaced by padding. */
895 continue;
896 /* Only the first non-bitfield field is emitted for unions. */
897 if (!is_union || !emitted_a_field)
899 /* Emit the field. */
900 bool field_ok;
901 bool is_anon_substructure;
902 unsigned int decl_align_unit;
903 unsigned int decl_offset;
905 field_ok = true;
906 emitted_a_field = true;
907 is_anon_substructure =
908 (DECL_NAME (field) == NULL
909 && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
910 || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE));
911 /* Keep track of the alignment of named substructures, either
912 of the whole record, or the alignment of the emitted field
913 (for unions). */
914 decl_align_unit = DECL_ALIGN_UNIT (field);
915 if (!is_anon_substructure && decl_align_unit > known_alignment)
916 known_alignment = decl_align_unit;
917 /* Pad to start of field. */
918 decl_offset =
919 TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
920 + precision_to_units
921 (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)));
923 unsigned int align_unit;
925 /* For anonymous records and unions there is no automatic
926 structure alignment, so use 1 as the alignment. */
927 align_unit = (is_anon_substructure) ? 1 : decl_align_unit;
928 *p_art_i = go_append_padding
929 (ob, prev_field_end, decl_offset, align_unit, *p_art_i,
930 &prev_field_end);
932 if (DECL_SIZE_UNIT (field))
933 prev_field_end +=
934 TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
935 /* Emit the field name, but not for anonymous records and
936 unions. */
937 if (!is_anon_substructure)
939 if (DECL_NAME (field) == NULL)
940 *p_art_i = go_append_artificial_name (ob, *p_art_i);
941 else
942 go_append_decl_name
943 (ob, field, container->keyword_hash);
944 obstack_1grow (ob, ' ');
946 /* Do not expand type if a record or union type or a function
947 pointer. */
948 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
949 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
950 || (POINTER_TYPE_P (TREE_TYPE (field))
951 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
952 == FUNCTION_TYPE))))
954 tree name;
955 void **slot;
957 name = TYPE_IDENTIFIER (TREE_TYPE (field));
959 slot = htab_find_slot (container->invalid_hash,
960 IDENTIFIER_POINTER (name),
961 NO_INSERT);
962 if (slot != NULL)
963 field_ok = false;
965 obstack_1grow (ob, '_');
966 go_append_string (ob, name);
968 else
970 if (!go_format_type (container, TREE_TYPE (field), true,
971 false, p_art_i, is_anon_substructure))
972 field_ok = false;
974 if (!is_anon_substructure)
975 obstack_grow (ob, "; ", 2);
976 if (!field_ok)
977 ret = false;
980 /* Padding. */
981 *p_art_i = go_append_padding (ob, prev_field_end,
982 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type)),
983 1, *p_art_i, &prev_field_end);
984 /* Alignment. */
985 if (!is_anon_record_or_union
986 && known_alignment < TYPE_ALIGN_UNIT (type))
988 const char *s;
989 char buf[100];
991 /* Enforce proper record alignment. */
992 s = go_get_uinttype_for_precision
993 (TYPE_ALIGN (type), TYPE_UNSIGNED (type));
994 if (s == NULL)
996 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
997 TYPE_ALIGN (type), TYPE_UNSIGNED (type) ? "u" : "");
998 s = buf;
999 ret = false;
1001 *p_art_i = go_force_record_alignment (ob, s, *p_art_i, buf);
1003 if (!is_anon_record_or_union)
1004 obstack_1grow (ob, '}');
1006 break;
1008 case FUNCTION_TYPE:
1010 tree arg_type;
1011 bool is_varargs;
1012 tree result;
1013 function_args_iterator iter;
1014 bool seen_arg;
1016 /* Go has no way to write a type which is a function but not a
1017 pointer to a function. */
1018 if (!is_func_ok)
1020 obstack_grow (ob, "func*", 5);
1021 ret = false;
1024 obstack_1grow (ob, '(');
1025 is_varargs = stdarg_p (type);
1026 seen_arg = false;
1027 FOREACH_FUNCTION_ARGS (type, arg_type, iter)
1029 if (VOID_TYPE_P (arg_type))
1030 break;
1031 if (seen_arg)
1032 obstack_grow (ob, ", ", 2);
1033 if (!go_format_type (container, arg_type, true, false, NULL, false))
1034 ret = false;
1035 seen_arg = true;
1037 if (is_varargs)
1039 if (prototype_p (type))
1040 obstack_grow (ob, ", ", 2);
1041 obstack_grow (ob, "...interface{}", 14);
1043 obstack_1grow (ob, ')');
1045 result = TREE_TYPE (type);
1046 if (!VOID_TYPE_P (result))
1048 obstack_1grow (ob, ' ');
1049 if (!go_format_type (container, result, use_type_name, false, NULL,
1050 false))
1051 ret = false;
1054 break;
1056 default:
1057 obstack_grow (ob, "INVALID-type", 12);
1058 ret = false;
1059 break;
1062 return ret;
1065 /* Output the type which was built on the type obstack, and then free
1066 it. */
1068 static void
1069 go_output_type (class godump_container *container)
1071 struct obstack *ob;
1073 ob = &container->type_obstack;
1074 obstack_1grow (ob, '\0');
1075 fputs ((char *) obstack_base (ob), go_dump_file);
1076 obstack_free (ob, obstack_base (ob));
1079 /* Output a function declaration. */
1081 static void
1082 go_output_fndecl (class godump_container *container, tree decl)
1084 if (!go_format_type (container, TREE_TYPE (decl), true, true, NULL, false))
1085 fprintf (go_dump_file, "// ");
1086 fprintf (go_dump_file, "func _%s ",
1087 IDENTIFIER_POINTER (DECL_NAME (decl)));
1088 go_output_type (container);
1089 fprintf (go_dump_file, " __asm__(\"%s\")\n",
1090 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
1093 /* Output a typedef or something like a struct definition. */
1095 static void
1096 go_output_typedef (class godump_container *container, tree decl)
1098 /* If we have an enum type, output the enum constants
1099 separately. */
1100 if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
1101 && TYPE_SIZE (TREE_TYPE (decl)) != 0
1102 && !container->decls_seen.contains (TREE_TYPE (decl))
1103 && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
1104 || !container->decls_seen.contains
1105 (TYPE_CANONICAL (TREE_TYPE (decl)))))
1107 tree element;
1109 for (element = TYPE_VALUES (TREE_TYPE (decl));
1110 element != NULL_TREE;
1111 element = TREE_CHAIN (element))
1113 const char *name;
1114 struct macro_hash_value *mhval;
1115 void **slot;
1116 char buf[WIDE_INT_PRINT_BUFFER_SIZE];
1117 tree value = DECL_INITIAL (TREE_VALUE (element));
1119 name = IDENTIFIER_POINTER (TREE_PURPOSE (element));
1121 /* Sometimes a name will be defined as both an enum constant
1122 and a macro. Avoid duplicate definition errors by
1123 treating enum constants as macros. */
1124 mhval = XNEW (struct macro_hash_value);
1125 mhval->name = xstrdup (name);
1126 mhval->value = NULL;
1127 slot = htab_find_slot (macro_hash, mhval, INSERT);
1128 if (*slot != NULL)
1129 macro_hash_del (*slot);
1131 if (tree_fits_shwi_p (value))
1132 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC,
1133 tree_to_shwi (value));
1134 else if (tree_fits_uhwi_p (value))
1135 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_UNSIGNED,
1136 tree_to_uhwi (value));
1137 else
1138 print_hex (wi::to_wide (element), buf);
1140 mhval->value = xstrdup (buf);
1141 *slot = mhval;
1143 container->decls_seen.add (TREE_TYPE (decl));
1144 if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
1145 container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl)));
1148 if (DECL_NAME (decl) != NULL_TREE)
1150 void **slot;
1151 const char *type;
1152 tree original_type;
1154 type = IDENTIFIER_POINTER (DECL_NAME (decl));
1155 original_type = DECL_ORIGINAL_TYPE (decl);
1156 if (original_type == NULL_TREE)
1157 original_type = TREE_TYPE (decl);
1159 /* Suppress typedefs where the type name matches the underlying
1160 struct/union/enum tag. This way we'll emit the struct definition
1161 instead of an invalid recursive type. */
1162 if (TYPE_IDENTIFIER (original_type) != NULL
1163 && IDENTIFIER_POINTER (TYPE_IDENTIFIER (original_type)) == type)
1164 return;
1166 /* If type defined already, skip. */
1167 slot = htab_find_slot (container->type_hash, type, INSERT);
1168 if (*slot != NULL)
1169 return;
1170 *slot = CONST_CAST (void *, (const void *) type);
1172 if (!go_format_type (container, original_type, true, false,
1173 NULL, false))
1175 fprintf (go_dump_file, "// ");
1176 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1177 *slot = CONST_CAST (void *, (const void *) type);
1179 fprintf (go_dump_file, "type _%s ",
1180 IDENTIFIER_POINTER (DECL_NAME (decl)));
1181 go_output_type (container);
1183 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1185 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
1187 if (size > 0)
1188 fprintf (go_dump_file,
1189 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1190 IDENTIFIER_POINTER (DECL_NAME (decl)),
1191 size);
1194 container->decls_seen.add (decl);
1196 else if ((RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
1197 || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
1198 && TYPE_NAME (TREE_TYPE (decl)) != NULL)
1200 void **slot;
1201 const char *type;
1202 HOST_WIDE_INT size;
1204 type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
1205 /* If type defined already, skip. */
1206 slot = htab_find_slot (container->type_hash, type, INSERT);
1207 if (*slot != NULL)
1208 return;
1209 *slot = CONST_CAST (void *, (const void *) type);
1211 if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL,
1212 false))
1214 fprintf (go_dump_file, "// ");
1215 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1216 *slot = CONST_CAST (void *, (const void *) type);
1218 fprintf (go_dump_file, "type _%s ",
1219 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
1220 go_output_type (container);
1222 size = int_size_in_bytes (TREE_TYPE (decl));
1223 if (size > 0)
1224 fprintf (go_dump_file,
1225 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1226 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))),
1227 size);
1229 else
1230 return;
1232 fprintf (go_dump_file, "\n");
1235 /* Output a variable. */
1237 static void
1238 go_output_var (class godump_container *container, tree decl)
1240 bool is_valid;
1241 tree type_name;
1242 tree id;
1244 if (container->decls_seen.contains (decl)
1245 || container->decls_seen.contains (DECL_NAME (decl)))
1246 return;
1247 container->decls_seen.add (decl);
1248 container->decls_seen.add (DECL_NAME (decl));
1250 type_name = TYPE_NAME (TREE_TYPE (decl));
1251 id = NULL_TREE;
1252 if (type_name != NULL_TREE && TREE_CODE (type_name) == IDENTIFIER_NODE)
1253 id = type_name;
1254 else if (type_name != NULL_TREE && TREE_CODE (type_name) == TYPE_DECL
1255 && DECL_SOURCE_LOCATION (type_name) != BUILTINS_LOCATION
1256 && DECL_NAME (type_name))
1257 id = DECL_NAME (type_name);
1258 if (id != NULL_TREE
1259 && (!htab_find_slot (container->type_hash, IDENTIFIER_POINTER (id),
1260 NO_INSERT)
1261 || htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (id),
1262 NO_INSERT)))
1263 id = NULL_TREE;
1264 if (id != NULL_TREE)
1266 struct obstack *ob;
1268 ob = &container->type_obstack;
1269 obstack_1grow (ob, '_');
1270 go_append_string (ob, id);
1271 is_valid = htab_find_slot (container->type_hash, IDENTIFIER_POINTER (id),
1272 NO_INSERT) != NULL;
1274 else
1275 is_valid = go_format_type (container, TREE_TYPE (decl), true, false, NULL,
1276 false);
1277 if (is_valid
1278 && htab_find_slot (container->type_hash,
1279 IDENTIFIER_POINTER (DECL_NAME (decl)),
1280 NO_INSERT) != NULL)
1282 /* There is already a type with this name, probably from a
1283 struct tag. Prefer the type to the variable. */
1284 is_valid = false;
1286 if (!is_valid)
1287 fprintf (go_dump_file, "// ");
1289 fprintf (go_dump_file, "var _%s ",
1290 IDENTIFIER_POINTER (DECL_NAME (decl)));
1291 go_output_type (container);
1292 fprintf (go_dump_file, "\n");
1294 /* Sometimes an extern variable is declared with an unknown struct
1295 type. */
1296 if (type_name != NULL_TREE && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1298 if (TREE_CODE (type_name) == IDENTIFIER_NODE)
1299 container->pot_dummy_types.add (IDENTIFIER_POINTER (type_name));
1300 else if (TREE_CODE (type_name) == TYPE_DECL)
1301 container->pot_dummy_types.add
1302 (IDENTIFIER_POINTER (DECL_NAME (type_name)));
1306 /* Output the final value of a preprocessor macro or enum constant.
1307 This is called via htab_traverse_noresize. */
1309 static int
1310 go_print_macro (void **slot, void *arg ATTRIBUTE_UNUSED)
1312 struct macro_hash_value *mhval = (struct macro_hash_value *) *slot;
1313 fprintf (go_dump_file, "const _%s = %s\n", mhval->name, mhval->value);
1314 return 1;
1317 /* Build a hash table with the Go keywords. */
1319 static const char * const keywords[] = {
1320 "__asm__", "break", "case", "chan", "const", "continue", "default",
1321 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1322 "import", "interface", "map", "package", "range", "return", "select",
1323 "struct", "switch", "type", "var"
1326 static void
1327 keyword_hash_init (class godump_container *container)
1329 size_t i;
1330 size_t count = ARRAY_SIZE (keywords);
1331 void **slot;
1333 for (i = 0; i < count; i++)
1335 slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
1336 *slot = CONST_CAST (void *, (const void *) keywords[i]);
1340 /* Traversing the pot_dummy_types and seeing which types are present
1341 in the global types hash table and creating dummy definitions if
1342 not found. This function is invoked by hash_set::traverse. */
1344 bool
1345 find_dummy_types (const char *const &ptr, godump_container *adata)
1347 class godump_container *data = (class godump_container *) adata;
1348 const char *type = (const char *) ptr;
1349 void **slot;
1350 void **islot;
1352 slot = htab_find_slot (data->type_hash, type, NO_INSERT);
1353 islot = htab_find_slot (data->invalid_hash, type, NO_INSERT);
1354 if (slot == NULL || islot != NULL)
1355 fprintf (go_dump_file, "type _%s struct {}\n", type);
1356 return true;
1359 /* Output symbols. */
1361 static void
1362 go_finish (const char *filename)
1364 class godump_container container;
1365 unsigned int ix;
1366 tree decl;
1368 real_debug_hooks->finish (filename);
1370 container.type_hash = htab_create (100, htab_hash_string,
1371 htab_eq_string, NULL);
1372 container.invalid_hash = htab_create (10, htab_hash_string,
1373 htab_eq_string, NULL);
1374 container.keyword_hash = htab_create (50, htab_hash_string,
1375 htab_eq_string, NULL);
1376 obstack_init (&container.type_obstack);
1378 keyword_hash_init (&container);
1380 FOR_EACH_VEC_SAFE_ELT (queue, ix, decl)
1382 switch (TREE_CODE (decl))
1384 case FUNCTION_DECL:
1385 go_output_fndecl (&container, decl);
1386 break;
1388 case TYPE_DECL:
1389 go_output_typedef (&container, decl);
1390 break;
1392 case VAR_DECL:
1393 go_output_var (&container, decl);
1394 break;
1396 default:
1397 gcc_unreachable ();
1401 htab_traverse_noresize (macro_hash, go_print_macro, NULL);
1403 /* To emit dummy definitions. */
1404 container.pot_dummy_types.traverse<godump_container *, find_dummy_types>
1405 (&container);
1407 htab_delete (container.type_hash);
1408 htab_delete (container.invalid_hash);
1409 htab_delete (container.keyword_hash);
1410 obstack_free (&container.type_obstack, NULL);
1412 vec_free (queue);
1414 if (fclose (go_dump_file) != 0)
1415 error ("could not close Go dump file: %m");
1416 go_dump_file = NULL;
1419 /* Set up our hooks. */
1421 const struct gcc_debug_hooks *
1422 dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
1424 go_dump_file = fopen (filename, "w");
1425 if (go_dump_file == NULL)
1427 error ("could not open Go dump file %qs: %m", filename);
1428 return hooks;
1431 go_debug_hooks = *hooks;
1432 real_debug_hooks = hooks;
1434 go_debug_hooks.finish = go_finish;
1435 go_debug_hooks.define = go_define;
1436 go_debug_hooks.undef = go_undef;
1437 go_debug_hooks.function_decl = go_function_decl;
1438 go_debug_hooks.early_global_decl = go_early_global_decl;
1439 go_debug_hooks.late_global_decl = go_late_global_decl;
1440 go_debug_hooks.type_decl = go_type_decl;
1442 macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq,
1443 macro_hash_del);
1445 return &go_debug_hooks;
1448 #include "gt-godump.h"