Patch ieee128-lib-patch002b
[official-gcc.git] / gcc / godump.c
bloba7cd7edf7a48c9779e048150211d1e14f494d378
1 /* Output Go language descriptions of types.
2 Copyright (C) 2008-2020 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 /* A hash table of macros we have seen. */
61 static htab_t macro_hash;
63 /* The type of a value in macro_hash. */
65 struct macro_hash_value
67 /* The name stored in the hash table. */
68 char *name;
69 /* The value of the macro. */
70 char *value;
73 /* Returns the number of units necessary to represent an integer with the given
74 PRECISION (in bits). */
76 static inline unsigned int
77 precision_to_units (unsigned int precision)
79 return (precision + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
82 /* Calculate the hash value for an entry in the macro hash table. */
84 static hashval_t
85 macro_hash_hashval (const void *val)
87 const struct macro_hash_value *mhval = (const struct macro_hash_value *) val;
88 return htab_hash_string (mhval->name);
91 /* Compare values in the macro hash table for equality. */
93 static int
94 macro_hash_eq (const void *v1, const void *v2)
96 const struct macro_hash_value *mhv1 = (const struct macro_hash_value *) v1;
97 const struct macro_hash_value *mhv2 = (const struct macro_hash_value *) v2;
98 return strcmp (mhv1->name, mhv2->name) == 0;
101 /* Free values deleted from the macro hash table. */
103 static void
104 macro_hash_del (void *v)
106 struct macro_hash_value *mhv = (struct macro_hash_value *) v;
107 XDELETEVEC (mhv->name);
108 XDELETEVEC (mhv->value);
109 XDELETE (mhv);
112 /* For the string hash tables. */
114 static int
115 string_hash_eq (const void *y1, const void *y2)
117 return strcmp ((const char *) y1, (const char *) y2) == 0;
120 /* A macro definition. */
122 static void
123 go_define (unsigned int lineno, const char *buffer)
125 const char *p;
126 const char *name_end;
127 size_t out_len;
128 char *out_buffer;
129 char *q;
130 bool saw_operand;
131 bool need_operand;
132 struct macro_hash_value *mhval;
133 char *copy;
134 hashval_t hashval;
135 void **slot;
137 real_debug_hooks->define (lineno, buffer);
139 /* Skip macro functions. */
140 for (p = buffer; *p != '\0' && *p != ' '; ++p)
141 if (*p == '(')
142 return;
144 if (*p == '\0')
145 return;
147 name_end = p;
149 ++p;
150 if (*p == '\0')
151 return;
153 copy = XNEWVEC (char, name_end - buffer + 1);
154 memcpy (copy, buffer, name_end - buffer);
155 copy[name_end - buffer] = '\0';
157 mhval = XNEW (struct macro_hash_value);
158 mhval->name = copy;
159 mhval->value = NULL;
161 hashval = htab_hash_string (copy);
162 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, NO_INSERT);
164 /* For simplicity, we force all names to be hidden by adding an
165 initial underscore, and let the user undo this as needed. */
166 out_len = strlen (p) * 2 + 1;
167 out_buffer = XNEWVEC (char, out_len);
168 q = out_buffer;
169 saw_operand = false;
170 need_operand = false;
171 while (*p != '\0')
173 switch (*p)
175 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
176 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
177 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
178 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
179 case 'Y': case 'Z':
180 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
181 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
182 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
183 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
184 case 'y': case 'z':
185 case '_':
187 /* The start of an identifier. Technically we should also
188 worry about UTF-8 identifiers, but they are not a
189 problem for practical uses of -fdump-go-spec so we
190 don't worry about them. */
191 const char *start;
192 char *n;
193 struct macro_hash_value idval;
195 if (saw_operand)
196 goto unknown;
198 start = p;
199 while (ISALNUM (*p) || *p == '_')
200 ++p;
201 n = XALLOCAVEC (char, p - start + 1);
202 memcpy (n, start, p - start);
203 n[p - start] = '\0';
204 idval.name = n;
205 idval.value = NULL;
206 if (htab_find (macro_hash, &idval) == NULL)
208 /* This is a reference to a name which was not defined
209 as a macro. */
210 goto unknown;
213 *q++ = '_';
214 memcpy (q, start, p - start);
215 q += p - start;
217 saw_operand = true;
218 need_operand = false;
220 break;
222 case '.':
223 if (!ISDIGIT (p[1]))
224 goto unknown;
225 /* Fall through. */
226 case '0': case '1': case '2': case '3': case '4':
227 case '5': case '6': case '7': case '8': case '9':
229 const char *start;
230 bool is_hex;
232 start = p;
233 is_hex = false;
234 if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
236 p += 2;
237 is_hex = true;
239 while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
240 || (is_hex
241 && ((*p >= 'a' && *p <= 'f')
242 || (*p >= 'A' && *p <= 'F'))))
243 ++p;
244 memcpy (q, start, p - start);
245 q += p - start;
246 while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
247 || *p == 'f' || *p == 'F'
248 || *p == 'd' || *p == 'D')
250 /* Go doesn't use any of these trailing type
251 modifiers. */
252 ++p;
255 /* We'll pick up the exponent, if any, as an
256 expression. */
258 saw_operand = true;
259 need_operand = false;
261 break;
263 case ' ': case '\t':
264 *q++ = *p++;
265 break;
267 case '(':
268 /* Always OK, not part of an operand, presumed to start an
269 operand. */
270 *q++ = *p++;
271 saw_operand = false;
272 need_operand = false;
273 break;
275 case ')':
276 /* OK if we don't need an operand, and presumed to indicate
277 an operand. */
278 if (need_operand)
279 goto unknown;
280 *q++ = *p++;
281 saw_operand = true;
282 break;
284 case '+': case '-':
285 /* Always OK, but not part of an operand. */
286 *q++ = *p++;
287 saw_operand = false;
288 break;
290 case '*': case '/': case '%': case '|': case '&': case '^':
291 /* Must be a binary operator. */
292 if (!saw_operand)
293 goto unknown;
294 *q++ = *p++;
295 saw_operand = false;
296 need_operand = true;
297 break;
299 case '=':
300 *q++ = *p++;
301 if (*p != '=')
302 goto unknown;
303 /* Must be a binary operator. */
304 if (!saw_operand)
305 goto unknown;
306 *q++ = *p++;
307 saw_operand = false;
308 need_operand = true;
309 break;
311 case '!':
312 *q++ = *p++;
313 if (*p == '=')
315 /* Must be a binary operator. */
316 if (!saw_operand)
317 goto unknown;
318 *q++ = *p++;
319 saw_operand = false;
320 need_operand = true;
322 else
324 /* Must be a unary operator. */
325 if (saw_operand)
326 goto unknown;
327 need_operand = true;
329 break;
331 case '<': case '>':
332 /* Must be a binary operand, may be << or >> or <= or >=. */
333 if (!saw_operand)
334 goto unknown;
335 *q++ = *p++;
336 if (*p == *(p - 1) || *p == '=')
337 *q++ = *p++;
338 saw_operand = false;
339 need_operand = true;
340 break;
342 case '~':
343 /* Must be a unary operand, must be translated for Go. */
344 if (saw_operand)
345 goto unknown;
346 *q++ = '^';
347 p++;
348 need_operand = true;
349 break;
351 case '"':
352 case '\'':
354 char quote;
355 int count;
357 if (saw_operand)
358 goto unknown;
359 quote = *p;
360 *q++ = *p++;
361 count = 0;
362 while (*p != quote)
364 int c;
366 if (*p == '\0')
367 goto unknown;
369 ++count;
371 if (*p != '\\')
373 *q++ = *p++;
374 continue;
377 *q++ = *p++;
378 switch (*p)
380 case '0': case '1': case '2': case '3':
381 case '4': case '5': case '6': case '7':
382 c = 0;
383 while (*p >= '0' && *p <= '7')
385 *q++ = *p++;
386 ++c;
388 /* Go octal characters are always 3
389 digits. */
390 if (c != 3)
391 goto unknown;
392 break;
394 case 'x':
395 *q++ = *p++;
396 c = 0;
397 while (ISXDIGIT (*p))
399 *q++ = *p++;
400 ++c;
402 /* Go hex characters are always 2 digits. */
403 if (c != 2)
404 goto unknown;
405 break;
407 case 'a': case 'b': case 'f': case 'n': case 'r':
408 case 't': case 'v': case '\\': case '\'': case '"':
409 *q++ = *p++;
410 break;
412 default:
413 goto unknown;
417 *q++ = *p++;
419 if (quote == '\'' && count != 1)
420 goto unknown;
422 saw_operand = true;
423 need_operand = false;
425 break;
428 default:
429 goto unknown;
433 if (need_operand)
434 goto unknown;
436 gcc_assert ((size_t) (q - out_buffer) < out_len);
437 *q = '\0';
439 mhval->value = out_buffer;
441 if (slot == NULL)
443 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, INSERT);
444 gcc_assert (slot != NULL && *slot == NULL);
446 else
448 if (*slot != NULL)
449 macro_hash_del (*slot);
452 *slot = mhval;
454 return;
456 unknown:
457 fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
458 if (slot != NULL)
459 htab_clear_slot (macro_hash, slot);
460 XDELETEVEC (out_buffer);
461 XDELETEVEC (copy);
464 /* A macro undef. */
466 static void
467 go_undef (unsigned int lineno, const char *buffer)
469 struct macro_hash_value mhval;
470 void **slot;
472 real_debug_hooks->undef (lineno, buffer);
474 mhval.name = CONST_CAST (char *, buffer);
475 mhval.value = NULL;
476 slot = htab_find_slot (macro_hash, &mhval, NO_INSERT);
477 if (slot != NULL)
478 htab_clear_slot (macro_hash, slot);
481 /* A function or variable decl. */
483 static void
484 go_decl (tree decl)
486 if (!TREE_PUBLIC (decl)
487 || DECL_IS_BUILTIN (decl)
488 || DECL_NAME (decl) == NULL_TREE)
489 return;
490 vec_safe_push (queue, decl);
493 /* A function decl. */
495 static void
496 go_function_decl (tree decl)
498 real_debug_hooks->function_decl (decl);
499 go_decl (decl);
502 static void
503 go_early_global_decl (tree decl)
505 go_decl (decl);
506 if (TREE_CODE (decl) != FUNCTION_DECL || DECL_STRUCT_FUNCTION (decl) != NULL)
507 real_debug_hooks->early_global_decl (decl);
510 /* A global variable decl. */
512 static void
513 go_late_global_decl (tree decl)
515 real_debug_hooks->late_global_decl (decl);
518 /* A type declaration. */
520 static void
521 go_type_decl (tree decl, int local)
523 real_debug_hooks->type_decl (decl, local);
525 if (local || DECL_IS_BUILTIN (decl))
526 return;
527 if (DECL_NAME (decl) == NULL_TREE
528 && (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE
529 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) != IDENTIFIER_NODE)
530 && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
531 return;
532 vec_safe_push (queue, decl);
535 /* A container for the data we pass around when generating information
536 at the end of the compilation. */
538 class godump_container
540 public:
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 (class 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 (class 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 (class 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 (class 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 (wi::to_wide (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), true, 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 (class 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 (class 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 class godump_container *data = (class 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 class 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"