libgo: add misc/cgo files
[official-gcc.git] / gcc / godump.c
blob3e905319b8fcf20565c11ddc5cb6c707fc89563e
1 /* Output Go language descriptions of types.
2 Copyright (C) 2008-2017 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 "wide-int-print.h"
35 #include "diagnostic-core.h"
36 #include "debug.h"
37 #include "stor-layout.h"
39 /* We dump this information from the debug hooks. This gives us a
40 stable and maintainable API to hook into. In order to work
41 correctly when -g is used, we build our own hooks structure which
42 wraps the hooks we need to change. */
44 /* Our debug hooks. This is initialized by dump_go_spec_init. */
46 static struct gcc_debug_hooks go_debug_hooks;
48 /* The real debug hooks. */
50 static const struct gcc_debug_hooks *real_debug_hooks;
52 /* The file where we should write information. */
54 static FILE *go_dump_file;
56 /* A queue of decls to output. */
58 static GTY(()) vec<tree, va_gc> *queue;
60 /* A hash table of macros we have seen. */
62 static htab_t macro_hash;
64 /* The type of a value in macro_hash. */
66 struct macro_hash_value
68 /* The name stored in the hash table. */
69 char *name;
70 /* The value of the macro. */
71 char *value;
74 /* Returns the number of units necessary to represent an integer with the given
75 PRECISION (in bits). */
77 static inline unsigned int
78 precision_to_units (unsigned int precision)
80 return (precision + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
83 /* Calculate the hash value for an entry in the macro hash table. */
85 static hashval_t
86 macro_hash_hashval (const void *val)
88 const struct macro_hash_value *mhval = (const struct macro_hash_value *) val;
89 return htab_hash_string (mhval->name);
92 /* Compare values in the macro hash table for equality. */
94 static int
95 macro_hash_eq (const void *v1, const void *v2)
97 const struct macro_hash_value *mhv1 = (const struct macro_hash_value *) v1;
98 const struct macro_hash_value *mhv2 = (const struct macro_hash_value *) v2;
99 return strcmp (mhv1->name, mhv2->name) == 0;
102 /* Free values deleted from the macro hash table. */
104 static void
105 macro_hash_del (void *v)
107 struct macro_hash_value *mhv = (struct macro_hash_value *) v;
108 XDELETEVEC (mhv->name);
109 XDELETEVEC (mhv->value);
110 XDELETE (mhv);
113 /* For the string hash tables. */
115 static int
116 string_hash_eq (const void *y1, const void *y2)
118 return strcmp ((const char *) y1, (const char *) y2) == 0;
121 /* A macro definition. */
123 static void
124 go_define (unsigned int lineno, const char *buffer)
126 const char *p;
127 const char *name_end;
128 size_t out_len;
129 char *out_buffer;
130 char *q;
131 bool saw_operand;
132 bool need_operand;
133 struct macro_hash_value *mhval;
134 char *copy;
135 hashval_t hashval;
136 void **slot;
138 real_debug_hooks->define (lineno, buffer);
140 /* Skip macro functions. */
141 for (p = buffer; *p != '\0' && *p != ' '; ++p)
142 if (*p == '(')
143 return;
145 if (*p == '\0')
146 return;
148 name_end = p;
150 ++p;
151 if (*p == '\0')
152 return;
154 copy = XNEWVEC (char, name_end - buffer + 1);
155 memcpy (copy, buffer, name_end - buffer);
156 copy[name_end - buffer] = '\0';
158 mhval = XNEW (struct macro_hash_value);
159 mhval->name = copy;
160 mhval->value = NULL;
162 hashval = htab_hash_string (copy);
163 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, NO_INSERT);
165 /* For simplicity, we force all names to be hidden by adding an
166 initial underscore, and let the user undo this as needed. */
167 out_len = strlen (p) * 2 + 1;
168 out_buffer = XNEWVEC (char, out_len);
169 q = out_buffer;
170 saw_operand = false;
171 need_operand = false;
172 while (*p != '\0')
174 switch (*p)
176 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
177 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
178 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
179 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
180 case 'Y': case 'Z':
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 '_':
188 /* The start of an identifier. Technically we should also
189 worry about UTF-8 identifiers, but they are not a
190 problem for practical uses of -fdump-go-spec so we
191 don't worry about them. */
192 const char *start;
193 char *n;
194 struct macro_hash_value idval;
196 if (saw_operand)
197 goto unknown;
199 start = p;
200 while (ISALNUM (*p) || *p == '_')
201 ++p;
202 n = XALLOCAVEC (char, p - start + 1);
203 memcpy (n, start, p - start);
204 n[p - start] = '\0';
205 idval.name = n;
206 idval.value = NULL;
207 if (htab_find (macro_hash, &idval) == NULL)
209 /* This is a reference to a name which was not defined
210 as a macro. */
211 goto unknown;
214 *q++ = '_';
215 memcpy (q, start, p - start);
216 q += p - start;
218 saw_operand = true;
219 need_operand = false;
221 break;
223 case '.':
224 if (!ISDIGIT (p[1]))
225 goto unknown;
226 /* Fall through. */
227 case '0': case '1': case '2': case '3': case '4':
228 case '5': case '6': case '7': case '8': case '9':
230 const char *start;
231 bool is_hex;
233 start = p;
234 is_hex = false;
235 if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
237 p += 2;
238 is_hex = true;
240 while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
241 || (is_hex
242 && ((*p >= 'a' && *p <= 'f')
243 || (*p >= 'A' && *p <= 'F'))))
244 ++p;
245 memcpy (q, start, p - start);
246 q += p - start;
247 while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
248 || *p == 'f' || *p == 'F'
249 || *p == 'd' || *p == 'D')
251 /* Go doesn't use any of these trailing type
252 modifiers. */
253 ++p;
256 /* We'll pick up the exponent, if any, as an
257 expression. */
259 saw_operand = true;
260 need_operand = false;
262 break;
264 case ' ': case '\t':
265 *q++ = *p++;
266 break;
268 case '(':
269 /* Always OK, not part of an operand, presumed to start an
270 operand. */
271 *q++ = *p++;
272 saw_operand = false;
273 need_operand = false;
274 break;
276 case ')':
277 /* OK if we don't need an operand, and presumed to indicate
278 an operand. */
279 if (need_operand)
280 goto unknown;
281 *q++ = *p++;
282 saw_operand = true;
283 break;
285 case '+': case '-':
286 /* Always OK, but not part of an operand. */
287 *q++ = *p++;
288 saw_operand = false;
289 break;
291 case '*': case '/': case '%': case '|': case '&': case '^':
292 /* Must be a binary operator. */
293 if (!saw_operand)
294 goto unknown;
295 *q++ = *p++;
296 saw_operand = false;
297 need_operand = true;
298 break;
300 case '=':
301 *q++ = *p++;
302 if (*p != '=')
303 goto unknown;
304 /* Must be a binary operator. */
305 if (!saw_operand)
306 goto unknown;
307 *q++ = *p++;
308 saw_operand = false;
309 need_operand = true;
310 break;
312 case '!':
313 *q++ = *p++;
314 if (*p == '=')
316 /* Must be a binary operator. */
317 if (!saw_operand)
318 goto unknown;
319 *q++ = *p++;
320 saw_operand = false;
321 need_operand = true;
323 else
325 /* Must be a unary operator. */
326 if (saw_operand)
327 goto unknown;
328 need_operand = true;
330 break;
332 case '<': case '>':
333 /* Must be a binary operand, may be << or >> or <= or >=. */
334 if (!saw_operand)
335 goto unknown;
336 *q++ = *p++;
337 if (*p == *(p - 1) || *p == '=')
338 *q++ = *p++;
339 saw_operand = false;
340 need_operand = true;
341 break;
343 case '~':
344 /* Must be a unary operand, must be translated for Go. */
345 if (saw_operand)
346 goto unknown;
347 *q++ = '^';
348 p++;
349 need_operand = true;
350 break;
352 case '"':
353 case '\'':
355 char quote;
356 int count;
358 if (saw_operand)
359 goto unknown;
360 quote = *p;
361 *q++ = *p++;
362 count = 0;
363 while (*p != quote)
365 int c;
367 if (*p == '\0')
368 goto unknown;
370 ++count;
372 if (*p != '\\')
374 *q++ = *p++;
375 continue;
378 *q++ = *p++;
379 switch (*p)
381 case '0': case '1': case '2': case '3':
382 case '4': case '5': case '6': case '7':
383 c = 0;
384 while (*p >= '0' && *p <= '7')
386 *q++ = *p++;
387 ++c;
389 /* Go octal characters are always 3
390 digits. */
391 if (c != 3)
392 goto unknown;
393 break;
395 case 'x':
396 *q++ = *p++;
397 c = 0;
398 while (ISXDIGIT (*p))
400 *q++ = *p++;
401 ++c;
403 /* Go hex characters are always 2 digits. */
404 if (c != 2)
405 goto unknown;
406 break;
408 case 'a': case 'b': case 'f': case 'n': case 'r':
409 case 't': case 'v': case '\\': case '\'': case '"':
410 *q++ = *p++;
411 break;
413 default:
414 goto unknown;
418 *q++ = *p++;
420 if (quote == '\'' && count != 1)
421 goto unknown;
423 saw_operand = true;
424 need_operand = false;
426 break;
429 default:
430 goto unknown;
434 if (need_operand)
435 goto unknown;
437 gcc_assert ((size_t) (q - out_buffer) < out_len);
438 *q = '\0';
440 mhval->value = out_buffer;
442 if (slot == NULL)
444 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, INSERT);
445 gcc_assert (slot != NULL && *slot == NULL);
447 else
449 if (*slot != NULL)
450 macro_hash_del (*slot);
453 *slot = mhval;
455 return;
457 unknown:
458 fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
459 if (slot != NULL)
460 htab_clear_slot (macro_hash, slot);
461 XDELETEVEC (out_buffer);
462 XDELETEVEC (copy);
465 /* A macro undef. */
467 static void
468 go_undef (unsigned int lineno, const char *buffer)
470 struct macro_hash_value mhval;
471 void **slot;
473 real_debug_hooks->undef (lineno, buffer);
475 mhval.name = CONST_CAST (char *, buffer);
476 mhval.value = NULL;
477 slot = htab_find_slot (macro_hash, &mhval, NO_INSERT);
478 if (slot != NULL)
479 htab_clear_slot (macro_hash, slot);
482 /* A function or variable decl. */
484 static void
485 go_decl (tree decl)
487 if (!TREE_PUBLIC (decl)
488 || DECL_IS_BUILTIN (decl)
489 || DECL_NAME (decl) == NULL_TREE)
490 return;
491 vec_safe_push (queue, decl);
494 /* A function decl. */
496 static void
497 go_function_decl (tree decl)
499 real_debug_hooks->function_decl (decl);
500 go_decl (decl);
503 static void
504 go_early_global_decl (tree decl)
506 go_decl (decl);
507 if (TREE_CODE (decl) != FUNCTION_DECL || DECL_STRUCT_FUNCTION (decl) != NULL)
508 real_debug_hooks->early_global_decl (decl);
511 /* A global variable decl. */
513 static void
514 go_late_global_decl (tree decl)
516 real_debug_hooks->late_global_decl (decl);
519 /* A type declaration. */
521 static void
522 go_type_decl (tree decl, int local)
524 real_debug_hooks->type_decl (decl, local);
526 if (local || DECL_IS_BUILTIN (decl))
527 return;
528 if (DECL_NAME (decl) == NULL_TREE
529 && (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE
530 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) != IDENTIFIER_NODE)
531 && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
532 return;
533 vec_safe_push (queue, decl);
536 /* A container for the data we pass around when generating information
537 at the end of the compilation. */
539 struct godump_container
541 /* DECLs that we have already seen. */
542 hash_set<tree> decls_seen;
544 /* Types which may potentially have to be defined as dummy
545 types. */
546 hash_set<const char *> pot_dummy_types;
548 /* Go keywords. */
549 htab_t keyword_hash;
551 /* Global type definitions. */
552 htab_t type_hash;
554 /* Invalid types. */
555 htab_t invalid_hash;
557 /* Obstack used to write out a type definition. */
558 struct obstack type_obstack;
561 /* Append an IDENTIFIER_NODE to OB. */
563 static void
564 go_append_string (struct obstack *ob, tree id)
566 obstack_grow (ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
569 /* Given an integer PRECISION in bits, returns a constant string that is the
570 matching go int or uint type (depending on the IS_UNSIGNED flag). Returns a
571 NULL pointer if there is no matching go type. */
573 static const char *
574 go_get_uinttype_for_precision (unsigned int precision, bool is_unsigned)
576 switch (precision)
578 case 8:
579 return is_unsigned ? "uint8" : "int8";
580 case 16:
581 return is_unsigned ? "uint16" : "int16";
582 case 32:
583 return is_unsigned ? "uint32" : "int32";
584 case 64:
585 return is_unsigned ? "uint64" : "int64";
586 default:
587 return NULL;
591 /* Append an artificial variable name with the suffix _INDEX to OB. Returns
592 INDEX + 1. */
594 static unsigned int
595 go_append_artificial_name (struct obstack *ob, unsigned int index)
597 char buf[100];
599 /* FIXME: identifier may not be unique. */
600 obstack_grow (ob, "Godump_", 7);
601 snprintf (buf, sizeof buf, "%u", index);
602 obstack_grow (ob, buf, strlen (buf));
604 return index + 1;
607 /* Append the variable name from DECL to OB. If the name is in the
608 KEYWORD_HASH, prepend an '_'. */
610 static void
611 go_append_decl_name (struct obstack *ob, tree decl, htab_t keyword_hash)
613 const char *var_name;
614 void **slot;
616 /* Start variable name with an underscore if a keyword. */
617 var_name = IDENTIFIER_POINTER (DECL_NAME (decl));
618 slot = htab_find_slot (keyword_hash, var_name, NO_INSERT);
619 if (slot != NULL)
620 obstack_1grow (ob, '_');
621 go_append_string (ob, DECL_NAME (decl));
624 /* Appends a byte array with the necessary number of elements and the name
625 "Godump_INDEX_pad" to pad from FROM_OFFSET to TO_OFFSET to OB assuming that
626 the next field is automatically aligned to ALIGN_UNITS. Returns INDEX + 1,
627 or INDEX if no padding had to be appended. The resulting offset where the
628 next field is allocated is returned through RET_OFFSET. */
630 static unsigned int
631 go_append_padding (struct obstack *ob, unsigned int from_offset,
632 unsigned int to_offset, unsigned int align_units,
633 unsigned int index, unsigned int *ret_offset)
635 if (from_offset % align_units > 0)
636 from_offset += align_units - (from_offset % align_units);
637 gcc_assert (to_offset >= from_offset);
638 if (to_offset > from_offset)
640 char buf[100];
642 index = go_append_artificial_name (ob, index);
643 snprintf (buf, sizeof buf, "_pad [%u]byte; ", to_offset - from_offset);
644 obstack_grow (ob, buf, strlen (buf));
646 *ret_offset = to_offset;
648 return index;
651 /* Appends an array of type TYPE_STRING with zero elements and the name
652 "Godump_INDEX_align" to OB. If TYPE_STRING is a null pointer, ERROR_STRING
653 is appended instead of the type. Returns INDEX + 1. */
655 static unsigned int
656 go_force_record_alignment (struct obstack *ob, const char *type_string,
657 unsigned int index, const char *error_string)
659 index = go_append_artificial_name (ob, index);
660 obstack_grow (ob, "_align ", 7);
661 if (type_string == NULL)
662 obstack_grow (ob, error_string, strlen (error_string));
663 else
665 obstack_grow (ob, "[0]", 3);
666 obstack_grow (ob, type_string, strlen (type_string));
668 obstack_grow (ob, "; ", 2);
670 return index;
673 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
674 USE_TYPE_NAME is true if we can simply use a type name here without
675 needing to define it. IS_FUNC_OK is true if we can output a func
676 type here; the "func" keyword will already have been added.
677 Return true if the type can be represented in Go, false otherwise.
678 P_ART_I is used for indexing artificial elements in nested structures and
679 should always be a NULL pointer when called, except by certain recursive
680 calls from go_format_type() itself. */
682 static bool
683 go_format_type (struct godump_container *container, tree type,
684 bool use_type_name, bool is_func_ok, unsigned int *p_art_i,
685 bool is_anon_record_or_union)
687 bool ret;
688 struct obstack *ob;
689 unsigned int art_i_dummy;
690 bool is_union = false;
692 if (p_art_i == NULL)
694 art_i_dummy = 0;
695 p_art_i = &art_i_dummy;
697 ret = true;
698 ob = &container->type_obstack;
700 if (TYPE_NAME (type) != NULL_TREE
701 && (container->decls_seen.contains (type)
702 || container->decls_seen.contains (TYPE_NAME (type)))
703 && (AGGREGATE_TYPE_P (type)
704 || POINTER_TYPE_P (type)
705 || TREE_CODE (type) == FUNCTION_TYPE))
707 tree name;
708 void **slot;
710 name = TYPE_IDENTIFIER (type);
712 slot = htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (name),
713 NO_INSERT);
714 if (slot != NULL)
715 ret = false;
717 obstack_1grow (ob, '_');
718 go_append_string (ob, name);
719 return ret;
722 container->decls_seen.add (type);
724 switch (TREE_CODE (type))
726 case TYPE_DECL:
728 void **slot;
730 slot = htab_find_slot (container->invalid_hash,
731 IDENTIFIER_POINTER (DECL_NAME (type)),
732 NO_INSERT);
733 if (slot != NULL)
734 ret = false;
736 obstack_1grow (ob, '_');
737 go_append_string (ob, DECL_NAME (type));
739 break;
741 case ENUMERAL_TYPE:
742 case INTEGER_TYPE:
744 const char *s;
745 char buf[100];
747 s = go_get_uinttype_for_precision (TYPE_PRECISION (type),
748 TYPE_UNSIGNED (type));
749 if (s == NULL)
751 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
752 TYPE_PRECISION (type),
753 TYPE_UNSIGNED (type) ? "u" : "");
754 s = buf;
755 ret = false;
757 obstack_grow (ob, s, strlen (s));
759 break;
761 case REAL_TYPE:
763 const char *s;
764 char buf[100];
766 switch (TYPE_PRECISION (type))
768 case 32:
769 s = "float32";
770 break;
771 case 64:
772 s = "float64";
773 break;
774 default:
775 snprintf (buf, sizeof buf, "INVALID-float-%u",
776 TYPE_PRECISION (type));
777 s = buf;
778 ret = false;
779 break;
781 obstack_grow (ob, s, strlen (s));
783 break;
785 case COMPLEX_TYPE:
787 const char *s;
788 char buf[100];
789 tree real_type;
791 real_type = TREE_TYPE (type);
792 if (TREE_CODE (real_type) == REAL_TYPE)
794 switch (TYPE_PRECISION (real_type))
796 case 32:
797 s = "complex64";
798 break;
799 case 64:
800 s = "complex128";
801 break;
802 default:
803 snprintf (buf, sizeof buf, "INVALID-complex-%u",
804 2 * TYPE_PRECISION (real_type));
805 s = buf;
806 ret = false;
807 break;
810 else
812 s = "INVALID-complex-non-real";
813 ret = false;
815 obstack_grow (ob, s, strlen (s));
817 break;
819 case BOOLEAN_TYPE:
820 obstack_grow (ob, "bool", 4);
821 break;
823 case POINTER_TYPE:
824 if (use_type_name
825 && TYPE_NAME (TREE_TYPE (type)) != NULL_TREE
826 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))
827 || (POINTER_TYPE_P (TREE_TYPE (type))
828 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type)))
829 == FUNCTION_TYPE))))
831 tree name;
832 void **slot;
834 name = TYPE_IDENTIFIER (TREE_TYPE (type));
836 slot = htab_find_slot (container->invalid_hash,
837 IDENTIFIER_POINTER (name), NO_INSERT);
838 if (slot != NULL)
839 ret = false;
841 obstack_grow (ob, "*_", 2);
842 go_append_string (ob, name);
844 /* The pointer here can be used without the struct or union
845 definition. So this struct or union is a potential dummy
846 type. */
847 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
848 container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
850 return ret;
852 if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
853 obstack_grow (ob, "func", 4);
854 else
855 obstack_1grow (ob, '*');
856 if (VOID_TYPE_P (TREE_TYPE (type)))
857 obstack_grow (ob, "byte", 4);
858 else
860 if (!go_format_type (container, TREE_TYPE (type), use_type_name,
861 true, NULL, false))
862 ret = false;
864 break;
866 case ARRAY_TYPE:
867 obstack_1grow (ob, '[');
868 if (TYPE_DOMAIN (type) != NULL_TREE
869 && TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
870 && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
871 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
872 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0
873 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
874 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
875 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
877 char buf[100];
879 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
880 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type))));
881 obstack_grow (ob, buf, strlen (buf));
883 else
884 obstack_1grow (ob, '0');
885 obstack_1grow (ob, ']');
886 if (!go_format_type (container, TREE_TYPE (type), use_type_name, false,
887 NULL, false))
888 ret = false;
889 break;
891 case UNION_TYPE:
892 is_union = true;
893 /* Fall through to RECORD_TYPE case. */
894 gcc_fallthrough ();
895 case RECORD_TYPE:
897 unsigned int prev_field_end;
898 unsigned int known_alignment;
899 tree field;
900 bool emitted_a_field;
902 /* FIXME: Why is this necessary? Without it we can get a core
903 dump on the s390x headers, or from a file containing simply
904 "typedef struct S T;". */
905 layout_type (type);
907 prev_field_end = 0;
908 known_alignment = 1;
909 /* Anonymous records and unions are flattened, i.e. they are not put
910 into "struct { ... }". */
911 if (!is_anon_record_or_union)
912 obstack_grow (ob, "struct { ", 9);
913 for (field = TYPE_FIELDS (type), emitted_a_field = false;
914 field != NULL_TREE;
915 field = TREE_CHAIN (field))
917 if (TREE_CODE (field) != FIELD_DECL)
918 continue;
919 if (DECL_BIT_FIELD (field))
920 /* Bit fields are replaced by padding. */
921 continue;
922 /* Only the first non-bitfield field is emitted for unions. */
923 if (!is_union || !emitted_a_field)
925 /* Emit the field. */
926 bool field_ok;
927 bool is_anon_substructure;
928 unsigned int decl_align_unit;
929 unsigned int decl_offset;
931 field_ok = true;
932 emitted_a_field = true;
933 is_anon_substructure =
934 (DECL_NAME (field) == NULL
935 && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
936 || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE));
937 /* Keep track of the alignment of named substructures, either
938 of the whole record, or the alignment of the emitted field
939 (for unions). */
940 decl_align_unit = DECL_ALIGN_UNIT (field);
941 if (!is_anon_substructure && decl_align_unit > known_alignment)
942 known_alignment = decl_align_unit;
943 /* Pad to start of field. */
944 decl_offset =
945 TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
946 + precision_to_units
947 (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)));
949 unsigned int align_unit;
951 /* For anonymous records and unions there is no automatic
952 structure alignment, so use 1 as the alignment. */
953 align_unit = (is_anon_substructure) ? 1 : decl_align_unit;
954 *p_art_i = go_append_padding
955 (ob, prev_field_end, decl_offset, align_unit, *p_art_i,
956 &prev_field_end);
958 if (DECL_SIZE_UNIT (field))
959 prev_field_end +=
960 TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
961 /* Emit the field name, but not for anonymous records and
962 unions. */
963 if (!is_anon_substructure)
965 if ((DECL_NAME (field) == NULL))
966 *p_art_i = go_append_artificial_name (ob, *p_art_i);
967 else
968 go_append_decl_name
969 (ob, field, container->keyword_hash);
970 obstack_1grow (ob, ' ');
972 /* Do not expand type if a record or union type or a function
973 pointer. */
974 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
975 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
976 || (POINTER_TYPE_P (TREE_TYPE (field))
977 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
978 == FUNCTION_TYPE))))
980 tree name;
981 void **slot;
983 name = TYPE_IDENTIFIER (TREE_TYPE (field));
985 slot = htab_find_slot (container->invalid_hash,
986 IDENTIFIER_POINTER (name),
987 NO_INSERT);
988 if (slot != NULL)
989 field_ok = false;
991 obstack_1grow (ob, '_');
992 go_append_string (ob, name);
994 else
996 if (!go_format_type (container, TREE_TYPE (field), true,
997 false, p_art_i, is_anon_substructure))
998 field_ok = false;
1000 if (!is_anon_substructure)
1001 obstack_grow (ob, "; ", 2);
1002 if (!field_ok)
1003 ret = false;
1006 /* Padding. */
1007 *p_art_i = go_append_padding (ob, prev_field_end,
1008 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type)),
1009 1, *p_art_i, &prev_field_end);
1010 /* Alignment. */
1011 if (!is_anon_record_or_union
1012 && known_alignment < TYPE_ALIGN_UNIT (type))
1014 const char *s;
1015 char buf[100];
1017 /* Enforce proper record alignment. */
1018 s = go_get_uinttype_for_precision
1019 (TYPE_ALIGN (type), TYPE_UNSIGNED (type));
1020 if (s == NULL)
1022 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
1023 TYPE_ALIGN (type), TYPE_UNSIGNED (type) ? "u" : "");
1024 s = buf;
1025 ret = false;
1027 *p_art_i = go_force_record_alignment (ob, s, *p_art_i, buf);
1029 if (!is_anon_record_or_union)
1030 obstack_1grow (ob, '}');
1032 break;
1034 case FUNCTION_TYPE:
1036 tree arg_type;
1037 bool is_varargs;
1038 tree result;
1039 function_args_iterator iter;
1040 bool seen_arg;
1042 /* Go has no way to write a type which is a function but not a
1043 pointer to a function. */
1044 if (!is_func_ok)
1046 obstack_grow (ob, "func*", 5);
1047 ret = false;
1050 obstack_1grow (ob, '(');
1051 is_varargs = stdarg_p (type);
1052 seen_arg = false;
1053 FOREACH_FUNCTION_ARGS (type, arg_type, iter)
1055 if (VOID_TYPE_P (arg_type))
1056 break;
1057 if (seen_arg)
1058 obstack_grow (ob, ", ", 2);
1059 if (!go_format_type (container, arg_type, true, false, NULL, false))
1060 ret = false;
1061 seen_arg = true;
1063 if (is_varargs)
1065 if (prototype_p (type))
1066 obstack_grow (ob, ", ", 2);
1067 obstack_grow (ob, "...interface{}", 14);
1069 obstack_1grow (ob, ')');
1071 result = TREE_TYPE (type);
1072 if (!VOID_TYPE_P (result))
1074 obstack_1grow (ob, ' ');
1075 if (!go_format_type (container, result, use_type_name, false, NULL,
1076 false))
1077 ret = false;
1080 break;
1082 default:
1083 obstack_grow (ob, "INVALID-type", 12);
1084 ret = false;
1085 break;
1088 return ret;
1091 /* Output the type which was built on the type obstack, and then free
1092 it. */
1094 static void
1095 go_output_type (struct godump_container *container)
1097 struct obstack *ob;
1099 ob = &container->type_obstack;
1100 obstack_1grow (ob, '\0');
1101 fputs ((char *) obstack_base (ob), go_dump_file);
1102 obstack_free (ob, obstack_base (ob));
1105 /* Output a function declaration. */
1107 static void
1108 go_output_fndecl (struct godump_container *container, tree decl)
1110 if (!go_format_type (container, TREE_TYPE (decl), false, true, NULL, false))
1111 fprintf (go_dump_file, "// ");
1112 fprintf (go_dump_file, "func _%s ",
1113 IDENTIFIER_POINTER (DECL_NAME (decl)));
1114 go_output_type (container);
1115 fprintf (go_dump_file, " __asm__(\"%s\")\n",
1116 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
1119 /* Output a typedef or something like a struct definition. */
1121 static void
1122 go_output_typedef (struct godump_container *container, tree decl)
1124 /* If we have an enum type, output the enum constants
1125 separately. */
1126 if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
1127 && TYPE_SIZE (TREE_TYPE (decl)) != 0
1128 && !container->decls_seen.contains (TREE_TYPE (decl))
1129 && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
1130 || !container->decls_seen.contains
1131 (TYPE_CANONICAL (TREE_TYPE (decl)))))
1133 tree element;
1135 for (element = TYPE_VALUES (TREE_TYPE (decl));
1136 element != NULL_TREE;
1137 element = TREE_CHAIN (element))
1139 const char *name;
1140 struct macro_hash_value *mhval;
1141 void **slot;
1142 char buf[WIDE_INT_PRINT_BUFFER_SIZE];
1144 name = IDENTIFIER_POINTER (TREE_PURPOSE (element));
1146 /* Sometimes a name will be defined as both an enum constant
1147 and a macro. Avoid duplicate definition errors by
1148 treating enum constants as macros. */
1149 mhval = XNEW (struct macro_hash_value);
1150 mhval->name = xstrdup (name);
1151 mhval->value = NULL;
1152 slot = htab_find_slot (macro_hash, mhval, INSERT);
1153 if (*slot != NULL)
1154 macro_hash_del (*slot);
1156 if (tree_fits_shwi_p (TREE_VALUE (element)))
1157 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC,
1158 tree_to_shwi (TREE_VALUE (element)));
1159 else if (tree_fits_uhwi_p (TREE_VALUE (element)))
1160 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_UNSIGNED,
1161 tree_to_uhwi (TREE_VALUE (element)));
1162 else
1163 print_hex (element, buf);
1165 mhval->value = xstrdup (buf);
1166 *slot = mhval;
1168 container->decls_seen.add (TREE_TYPE (decl));
1169 if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
1170 container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl)));
1173 if (DECL_NAME (decl) != NULL_TREE)
1175 void **slot;
1176 const char *type;
1178 type = IDENTIFIER_POINTER (DECL_NAME (decl));
1179 /* If type defined already, skip. */
1180 slot = htab_find_slot (container->type_hash, type, INSERT);
1181 if (*slot != NULL)
1182 return;
1183 *slot = CONST_CAST (void *, (const void *) type);
1185 if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL,
1186 false))
1188 fprintf (go_dump_file, "// ");
1189 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1190 *slot = CONST_CAST (void *, (const void *) type);
1192 fprintf (go_dump_file, "type _%s ",
1193 IDENTIFIER_POINTER (DECL_NAME (decl)));
1194 go_output_type (container);
1196 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1198 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
1200 if (size > 0)
1201 fprintf (go_dump_file,
1202 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1203 IDENTIFIER_POINTER (DECL_NAME (decl)),
1204 size);
1207 container->decls_seen.add (decl);
1209 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1211 void **slot;
1212 const char *type;
1213 HOST_WIDE_INT size;
1215 type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
1216 /* If type defined already, skip. */
1217 slot = htab_find_slot (container->type_hash, type, INSERT);
1218 if (*slot != NULL)
1219 return;
1220 *slot = CONST_CAST (void *, (const void *) type);
1222 if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL,
1223 false))
1225 fprintf (go_dump_file, "// ");
1226 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1227 *slot = CONST_CAST (void *, (const void *) type);
1229 fprintf (go_dump_file, "type _%s ",
1230 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
1231 go_output_type (container);
1233 size = int_size_in_bytes (TREE_TYPE (decl));
1234 if (size > 0)
1235 fprintf (go_dump_file,
1236 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1237 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))),
1238 size);
1240 else
1241 return;
1243 fprintf (go_dump_file, "\n");
1246 /* Output a variable. */
1248 static void
1249 go_output_var (struct godump_container *container, tree decl)
1251 bool is_valid;
1252 tree type_name;
1253 tree id;
1255 if (container->decls_seen.contains (decl)
1256 || container->decls_seen.contains (DECL_NAME (decl)))
1257 return;
1258 container->decls_seen.add (decl);
1259 container->decls_seen.add (DECL_NAME (decl));
1261 type_name = TYPE_NAME (TREE_TYPE (decl));
1262 id = NULL_TREE;
1263 if (type_name != NULL_TREE && TREE_CODE (type_name) == IDENTIFIER_NODE)
1264 id = type_name;
1265 else if (type_name != NULL_TREE && TREE_CODE (type_name) == TYPE_DECL
1266 && DECL_SOURCE_LOCATION (type_name) != BUILTINS_LOCATION
1267 && DECL_NAME (type_name))
1268 id = DECL_NAME (type_name);
1269 if (id != NULL_TREE
1270 && (!htab_find_slot (container->type_hash, IDENTIFIER_POINTER (id),
1271 NO_INSERT)
1272 || htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (id),
1273 NO_INSERT)))
1274 id = NULL_TREE;
1275 if (id != NULL_TREE)
1277 struct obstack *ob;
1279 ob = &container->type_obstack;
1280 obstack_1grow (ob, '_');
1281 go_append_string (ob, id);
1282 is_valid = htab_find_slot (container->type_hash, IDENTIFIER_POINTER (id),
1283 NO_INSERT) != NULL;
1285 else
1286 is_valid = go_format_type (container, TREE_TYPE (decl), true, false, NULL,
1287 false);
1288 if (is_valid
1289 && htab_find_slot (container->type_hash,
1290 IDENTIFIER_POINTER (DECL_NAME (decl)),
1291 NO_INSERT) != NULL)
1293 /* There is already a type with this name, probably from a
1294 struct tag. Prefer the type to the variable. */
1295 is_valid = false;
1297 if (!is_valid)
1298 fprintf (go_dump_file, "// ");
1300 fprintf (go_dump_file, "var _%s ",
1301 IDENTIFIER_POINTER (DECL_NAME (decl)));
1302 go_output_type (container);
1303 fprintf (go_dump_file, "\n");
1305 /* Sometimes an extern variable is declared with an unknown struct
1306 type. */
1307 if (type_name != NULL_TREE && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1309 if (TREE_CODE (type_name) == IDENTIFIER_NODE)
1310 container->pot_dummy_types.add (IDENTIFIER_POINTER (type_name));
1311 else if (TREE_CODE (type_name) == TYPE_DECL)
1312 container->pot_dummy_types.add
1313 (IDENTIFIER_POINTER (DECL_NAME (type_name)));
1317 /* Output the final value of a preprocessor macro or enum constant.
1318 This is called via htab_traverse_noresize. */
1320 static int
1321 go_print_macro (void **slot, void *arg ATTRIBUTE_UNUSED)
1323 struct macro_hash_value *mhval = (struct macro_hash_value *) *slot;
1324 fprintf (go_dump_file, "const _%s = %s\n", mhval->name, mhval->value);
1325 return 1;
1328 /* Build a hash table with the Go keywords. */
1330 static const char * const keywords[] = {
1331 "__asm__", "break", "case", "chan", "const", "continue", "default",
1332 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1333 "import", "interface", "map", "package", "range", "return", "select",
1334 "struct", "switch", "type", "var"
1337 static void
1338 keyword_hash_init (struct godump_container *container)
1340 size_t i;
1341 size_t count = sizeof (keywords) / sizeof (keywords[0]);
1342 void **slot;
1344 for (i = 0; i < count; i++)
1346 slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
1347 *slot = CONST_CAST (void *, (const void *) keywords[i]);
1351 /* Traversing the pot_dummy_types and seeing which types are present
1352 in the global types hash table and creating dummy definitions if
1353 not found. This function is invoked by hash_set::traverse. */
1355 bool
1356 find_dummy_types (const char *const &ptr, godump_container *adata)
1358 struct godump_container *data = (struct godump_container *) adata;
1359 const char *type = (const char *) ptr;
1360 void **slot;
1361 void **islot;
1363 slot = htab_find_slot (data->type_hash, type, NO_INSERT);
1364 islot = htab_find_slot (data->invalid_hash, type, NO_INSERT);
1365 if (slot == NULL || islot != NULL)
1366 fprintf (go_dump_file, "type _%s struct {}\n", type);
1367 return true;
1370 /* Output symbols. */
1372 static void
1373 go_finish (const char *filename)
1375 struct godump_container container;
1376 unsigned int ix;
1377 tree decl;
1379 real_debug_hooks->finish (filename);
1381 container.type_hash = htab_create (100, htab_hash_string,
1382 string_hash_eq, NULL);
1383 container.invalid_hash = htab_create (10, htab_hash_string,
1384 string_hash_eq, NULL);
1385 container.keyword_hash = htab_create (50, htab_hash_string,
1386 string_hash_eq, NULL);
1387 obstack_init (&container.type_obstack);
1389 keyword_hash_init (&container);
1391 FOR_EACH_VEC_SAFE_ELT (queue, ix, decl)
1393 switch (TREE_CODE (decl))
1395 case FUNCTION_DECL:
1396 go_output_fndecl (&container, decl);
1397 break;
1399 case TYPE_DECL:
1400 go_output_typedef (&container, decl);
1401 break;
1403 case VAR_DECL:
1404 go_output_var (&container, decl);
1405 break;
1407 default:
1408 gcc_unreachable ();
1412 htab_traverse_noresize (macro_hash, go_print_macro, NULL);
1414 /* To emit dummy definitions. */
1415 container.pot_dummy_types.traverse<godump_container *, find_dummy_types>
1416 (&container);
1418 htab_delete (container.type_hash);
1419 htab_delete (container.invalid_hash);
1420 htab_delete (container.keyword_hash);
1421 obstack_free (&container.type_obstack, NULL);
1423 vec_free (queue);
1425 if (fclose (go_dump_file) != 0)
1426 error ("could not close Go dump file: %m");
1427 go_dump_file = NULL;
1430 /* Set up our hooks. */
1432 const struct gcc_debug_hooks *
1433 dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
1435 go_dump_file = fopen (filename, "w");
1436 if (go_dump_file == NULL)
1438 error ("could not open Go dump file %qs: %m", filename);
1439 return hooks;
1442 go_debug_hooks = *hooks;
1443 real_debug_hooks = hooks;
1445 go_debug_hooks.finish = go_finish;
1446 go_debug_hooks.define = go_define;
1447 go_debug_hooks.undef = go_undef;
1448 go_debug_hooks.function_decl = go_function_decl;
1449 go_debug_hooks.early_global_decl = go_early_global_decl;
1450 go_debug_hooks.late_global_decl = go_late_global_decl;
1451 go_debug_hooks.type_decl = go_type_decl;
1453 macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq,
1454 macro_hash_del);
1456 return &go_debug_hooks;
1459 #include "gt-godump.h"