2015-03-02 Hristian Kirtchev <kirtchev@adacore.com>
[official-gcc.git] / gcc / godump.c
blob4147f7547313f28aff5c82db1b543c0bb92039d9
1 /* Output Go language descriptions of types.
2 Copyright (C) 2008-2015 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor <iant@google.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 /* This file is used during the build process to emit Go language
22 descriptions of declarations from C header files. It uses the
23 debug info hooks to emit the descriptions. The Go language
24 descriptions then become part of the Go runtime support
25 library.
27 All global names are output with a leading underscore, so that they
28 are all hidden in Go. */
30 #include "config.h"
31 #include "system.h"
32 #include "coretypes.h"
33 #include "diagnostic-core.h"
34 #include "hash-set.h"
35 #include "machmode.h"
36 #include "vec.h"
37 #include "double-int.h"
38 #include "input.h"
39 #include "alias.h"
40 #include "symtab.h"
41 #include "options.h"
42 #include "wide-int.h"
43 #include "inchash.h"
44 #include "tree.h"
45 #include "ggc.h"
46 #include "hash-set.h"
47 #include "obstack.h"
48 #include "debug.h"
49 #include "wide-int-print.h"
50 #include "stor-layout.h"
51 #include "defaults.h"
53 /* We dump this information from the debug hooks. This gives us a
54 stable and maintainable API to hook into. In order to work
55 correctly when -g is used, we build our own hooks structure which
56 wraps the hooks we need to change. */
58 /* Our debug hooks. This is initialized by dump_go_spec_init. */
60 static struct gcc_debug_hooks go_debug_hooks;
62 /* The real debug hooks. */
64 static const struct gcc_debug_hooks *real_debug_hooks;
66 /* The file where we should write information. */
68 static FILE *go_dump_file;
70 /* A queue of decls to output. */
72 static GTY(()) vec<tree, va_gc> *queue;
74 /* A hash table of macros we have seen. */
76 static htab_t macro_hash;
78 /* The type of a value in macro_hash. */
80 struct macro_hash_value
82 /* The name stored in the hash table. */
83 char *name;
84 /* The value of the macro. */
85 char *value;
88 /* Returns the number of units necessary to represent an integer with the given
89 PRECISION (in bits). */
91 static inline unsigned int
92 precision_to_units (unsigned int precision)
94 return (precision + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
97 /* Calculate the hash value for an entry in the macro hash table. */
99 static hashval_t
100 macro_hash_hashval (const void *val)
102 const struct macro_hash_value *mhval = (const struct macro_hash_value *) val;
103 return htab_hash_string (mhval->name);
106 /* Compare values in the macro hash table for equality. */
108 static int
109 macro_hash_eq (const void *v1, const void *v2)
111 const struct macro_hash_value *mhv1 = (const struct macro_hash_value *) v1;
112 const struct macro_hash_value *mhv2 = (const struct macro_hash_value *) v2;
113 return strcmp (mhv1->name, mhv2->name) == 0;
116 /* Free values deleted from the macro hash table. */
118 static void
119 macro_hash_del (void *v)
121 struct macro_hash_value *mhv = (struct macro_hash_value *) v;
122 XDELETEVEC (mhv->name);
123 XDELETEVEC (mhv->value);
124 XDELETE (mhv);
127 /* For the string hash tables. */
129 static int
130 string_hash_eq (const void *y1, const void *y2)
132 return strcmp ((const char *) y1, (const char *) y2) == 0;
135 /* A macro definition. */
137 static void
138 go_define (unsigned int lineno, const char *buffer)
140 const char *p;
141 const char *name_end;
142 size_t out_len;
143 char *out_buffer;
144 char *q;
145 bool saw_operand;
146 bool need_operand;
147 struct macro_hash_value *mhval;
148 char *copy;
149 hashval_t hashval;
150 void **slot;
152 real_debug_hooks->define (lineno, buffer);
154 /* Skip macro functions. */
155 for (p = buffer; *p != '\0' && *p != ' '; ++p)
156 if (*p == '(')
157 return;
159 if (*p == '\0')
160 return;
162 name_end = p;
164 ++p;
165 if (*p == '\0')
166 return;
168 copy = XNEWVEC (char, name_end - buffer + 1);
169 memcpy (copy, buffer, name_end - buffer);
170 copy[name_end - buffer] = '\0';
172 mhval = XNEW (struct macro_hash_value);
173 mhval->name = copy;
174 mhval->value = NULL;
176 hashval = htab_hash_string (copy);
177 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, NO_INSERT);
179 /* For simplicity, we force all names to be hidden by adding an
180 initial underscore, and let the user undo this as needed. */
181 out_len = strlen (p) * 2 + 1;
182 out_buffer = XNEWVEC (char, out_len);
183 q = out_buffer;
184 saw_operand = false;
185 need_operand = false;
186 while (*p != '\0')
188 switch (*p)
190 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
191 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
192 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
193 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
194 case 'Y': case 'Z':
195 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
196 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
197 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
198 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
199 case 'y': case 'z':
200 case '_':
202 /* The start of an identifier. Technically we should also
203 worry about UTF-8 identifiers, but they are not a
204 problem for practical uses of -fdump-go-spec so we
205 don't worry about them. */
206 const char *start;
207 char *n;
208 struct macro_hash_value idval;
210 if (saw_operand)
211 goto unknown;
213 start = p;
214 while (ISALNUM (*p) || *p == '_')
215 ++p;
216 n = XALLOCAVEC (char, p - start + 1);
217 memcpy (n, start, p - start);
218 n[p - start] = '\0';
219 idval.name = n;
220 idval.value = NULL;
221 if (htab_find (macro_hash, &idval) == NULL)
223 /* This is a reference to a name which was not defined
224 as a macro. */
225 goto unknown;
228 *q++ = '_';
229 memcpy (q, start, p - start);
230 q += p - start;
232 saw_operand = true;
233 need_operand = false;
235 break;
237 case '.':
238 if (!ISDIGIT (p[1]))
239 goto unknown;
240 /* Fall through. */
241 case '0': case '1': case '2': case '3': case '4':
242 case '5': case '6': case '7': case '8': case '9':
244 const char *start;
245 bool is_hex;
247 start = p;
248 is_hex = false;
249 if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
251 p += 2;
252 is_hex = true;
254 while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
255 || (is_hex
256 && ((*p >= 'a' && *p <= 'f')
257 || (*p >= 'A' && *p <= 'F'))))
258 ++p;
259 memcpy (q, start, p - start);
260 q += p - start;
261 while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
262 || *p == 'f' || *p == 'F'
263 || *p == 'd' || *p == 'D')
265 /* Go doesn't use any of these trailing type
266 modifiers. */
267 ++p;
270 /* We'll pick up the exponent, if any, as an
271 expression. */
273 saw_operand = true;
274 need_operand = false;
276 break;
278 case ' ': case '\t':
279 *q++ = *p++;
280 break;
282 case '(':
283 /* Always OK, not part of an operand, presumed to start an
284 operand. */
285 *q++ = *p++;
286 saw_operand = false;
287 need_operand = false;
288 break;
290 case ')':
291 /* OK if we don't need an operand, and presumed to indicate
292 an operand. */
293 if (need_operand)
294 goto unknown;
295 *q++ = *p++;
296 saw_operand = true;
297 break;
299 case '+': case '-':
300 /* Always OK, but not part of an operand. */
301 *q++ = *p++;
302 saw_operand = false;
303 break;
305 case '*': case '/': case '%': case '|': case '&': case '^':
306 /* Must be a binary operator. */
307 if (!saw_operand)
308 goto unknown;
309 *q++ = *p++;
310 saw_operand = false;
311 need_operand = true;
312 break;
314 case '=':
315 *q++ = *p++;
316 if (*p != '=')
317 goto unknown;
318 /* Must be a binary operator. */
319 if (!saw_operand)
320 goto unknown;
321 *q++ = *p++;
322 saw_operand = false;
323 need_operand = true;
324 break;
326 case '!':
327 *q++ = *p++;
328 if (*p == '=')
330 /* Must be a binary operator. */
331 if (!saw_operand)
332 goto unknown;
333 *q++ = *p++;
334 saw_operand = false;
335 need_operand = true;
337 else
339 /* Must be a unary operator. */
340 if (saw_operand)
341 goto unknown;
342 need_operand = true;
344 break;
346 case '<': case '>':
347 /* Must be a binary operand, may be << or >> or <= or >=. */
348 if (!saw_operand)
349 goto unknown;
350 *q++ = *p++;
351 if (*p == *(p - 1) || *p == '=')
352 *q++ = *p++;
353 saw_operand = false;
354 need_operand = true;
355 break;
357 case '~':
358 /* Must be a unary operand, must be translated for Go. */
359 if (saw_operand)
360 goto unknown;
361 *q++ = '^';
362 p++;
363 need_operand = true;
364 break;
366 case '"':
367 case '\'':
369 char quote;
370 int count;
372 if (saw_operand)
373 goto unknown;
374 quote = *p;
375 *q++ = *p++;
376 count = 0;
377 while (*p != quote)
379 int c;
381 if (*p == '\0')
382 goto unknown;
384 ++count;
386 if (*p != '\\')
388 *q++ = *p++;
389 continue;
392 *q++ = *p++;
393 switch (*p)
395 case '0': case '1': case '2': case '3':
396 case '4': case '5': case '6': case '7':
397 c = 0;
398 while (*p >= '0' && *p <= '7')
400 *q++ = *p++;
401 ++c;
403 /* Go octal characters are always 3
404 digits. */
405 if (c != 3)
406 goto unknown;
407 break;
409 case 'x':
410 *q++ = *p++;
411 c = 0;
412 while (ISXDIGIT (*p))
414 *q++ = *p++;
415 ++c;
417 /* Go hex characters are always 2 digits. */
418 if (c != 2)
419 goto unknown;
420 break;
422 case 'a': case 'b': case 'f': case 'n': case 'r':
423 case 't': case 'v': case '\\': case '\'': case '"':
424 *q++ = *p++;
425 break;
427 default:
428 goto unknown;
432 *q++ = *p++;
434 if (quote == '\'' && count != 1)
435 goto unknown;
437 saw_operand = true;
438 need_operand = false;
440 break;
443 default:
444 goto unknown;
448 if (need_operand)
449 goto unknown;
451 gcc_assert ((size_t) (q - out_buffer) < out_len);
452 *q = '\0';
454 mhval->value = out_buffer;
456 if (slot == NULL)
458 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, INSERT);
459 gcc_assert (slot != NULL && *slot == NULL);
461 else
463 if (*slot != NULL)
464 macro_hash_del (*slot);
467 *slot = mhval;
469 return;
471 unknown:
472 fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
473 if (slot != NULL)
474 htab_clear_slot (macro_hash, slot);
475 XDELETEVEC (out_buffer);
476 XDELETEVEC (copy);
479 /* A macro undef. */
481 static void
482 go_undef (unsigned int lineno, const char *buffer)
484 struct macro_hash_value mhval;
485 void **slot;
487 real_debug_hooks->undef (lineno, buffer);
489 mhval.name = CONST_CAST (char *, buffer);
490 mhval.value = NULL;
491 slot = htab_find_slot (macro_hash, &mhval, NO_INSERT);
492 if (slot != NULL)
493 htab_clear_slot (macro_hash, slot);
496 /* A function or variable decl. */
498 static void
499 go_decl (tree decl)
501 if (!TREE_PUBLIC (decl)
502 || DECL_IS_BUILTIN (decl)
503 || DECL_NAME (decl) == NULL_TREE)
504 return;
505 vec_safe_push (queue, decl);
508 /* A function decl. */
510 static void
511 go_function_decl (tree decl)
513 real_debug_hooks->function_decl (decl);
514 go_decl (decl);
517 /* A global variable decl. */
519 static void
520 go_global_decl (tree decl)
522 real_debug_hooks->global_decl (decl);
523 go_decl (decl);
526 /* A type declaration. */
528 static void
529 go_type_decl (tree decl, int local)
531 real_debug_hooks->type_decl (decl, local);
533 if (local || DECL_IS_BUILTIN (decl))
534 return;
535 if (DECL_NAME (decl) == NULL_TREE
536 && (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE
537 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) != IDENTIFIER_NODE)
538 && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
539 return;
540 vec_safe_push (queue, decl);
543 /* A container for the data we pass around when generating information
544 at the end of the compilation. */
546 struct godump_container
548 /* DECLs that we have already seen. */
549 hash_set<tree> decls_seen;
551 /* Types which may potentially have to be defined as dummy
552 types. */
553 hash_set<const char *> pot_dummy_types;
555 /* Go keywords. */
556 htab_t keyword_hash;
558 /* Global type definitions. */
559 htab_t type_hash;
561 /* Invalid types. */
562 htab_t invalid_hash;
564 /* Obstack used to write out a type definition. */
565 struct obstack type_obstack;
568 /* Append an IDENTIFIER_NODE to OB. */
570 static void
571 go_append_string (struct obstack *ob, tree id)
573 obstack_grow (ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
576 /* Given an integer PRECISION in bits, returns a constant string that is the
577 matching go int or uint type (depending on the IS_UNSIGNED flag). Returns a
578 NULL pointer if there is no matching go type. */
580 static const char *
581 go_get_uinttype_for_precision (unsigned int precision, bool is_unsigned)
583 switch (precision)
585 case 8:
586 return is_unsigned ? "uint8" : "int8";
587 case 16:
588 return is_unsigned ? "uint16" : "int16";
589 case 32:
590 return is_unsigned ? "uint32" : "int32";
591 case 64:
592 return is_unsigned ? "uint64" : "int64";
593 default:
594 return NULL;
598 /* Append an artificial variable name with the suffix _INDEX to OB. Returns
599 INDEX + 1. */
601 static unsigned int
602 go_append_artificial_name (struct obstack *ob, unsigned int index)
604 char buf[100];
606 /* FIXME: identifier may not be unique. */
607 obstack_grow (ob, "Godump_", 7);
608 snprintf (buf, sizeof buf, "%u", index);
609 obstack_grow (ob, buf, strlen (buf));
611 return index + 1;
614 /* Append the variable name from DECL to OB. If the name is in the
615 KEYWORD_HASH, prepend an '_'. */
617 static void
618 go_append_decl_name (struct obstack *ob, tree decl, htab_t keyword_hash)
620 const char *var_name;
621 void **slot;
623 /* Start variable name with an underscore if a keyword. */
624 var_name = IDENTIFIER_POINTER (DECL_NAME (decl));
625 slot = htab_find_slot (keyword_hash, var_name, NO_INSERT);
626 if (slot != NULL)
627 obstack_1grow (ob, '_');
628 go_append_string (ob, DECL_NAME (decl));
631 /* Appends a byte array with the necessary number of elements and the name
632 "Godump_INDEX_pad" to pad from FROM_OFFSET to TO_OFFSET to OB assuming that
633 the next field is automatically aligned to ALIGN_UNITS. Returns INDEX + 1,
634 or INDEX if no padding had to be appended. The resulting offset where the
635 next field is allocated is returned through RET_OFFSET. */
637 static unsigned int
638 go_append_padding (struct obstack *ob, unsigned int from_offset,
639 unsigned int to_offset, unsigned int align_units,
640 unsigned int index, unsigned int *ret_offset)
642 if (from_offset % align_units > 0)
643 from_offset += align_units - (from_offset % align_units);
644 gcc_assert (to_offset >= from_offset);
645 if (to_offset > from_offset)
647 char buf[100];
649 index = go_append_artificial_name (ob, index);
650 snprintf (buf, sizeof buf, "_pad [%u]byte; ", to_offset - from_offset);
651 obstack_grow (ob, buf, strlen (buf));
653 *ret_offset = to_offset;
655 return index;
658 /* Appends an array of type TYPE_STRING with zero elements and the name
659 "Godump_INDEX_align" to OB. If TYPE_STRING is a null pointer, ERROR_STRING
660 is appended instead of the type. Returns INDEX + 1. */
662 static unsigned int
663 go_force_record_alignment (struct obstack *ob, const char *type_string,
664 unsigned int index, const char *error_string)
666 index = go_append_artificial_name (ob, index);
667 obstack_grow (ob, "_align ", 7);
668 if (type_string == NULL)
669 obstack_grow (ob, error_string, strlen (error_string));
670 else
672 obstack_grow (ob, "[0]", 3);
673 obstack_grow (ob, type_string, strlen (type_string));
675 obstack_grow (ob, "; ", 2);
677 return index;
680 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
681 USE_TYPE_NAME is true if we can simply use a type name here without
682 needing to define it. IS_FUNC_OK is true if we can output a func
683 type here; the "func" keyword will already have been added.
684 Return true if the type can be represented in Go, false otherwise.
685 P_ART_I is used for indexing artificial elements in nested structures and
686 should always be a NULL pointer when called, except by certain recursive
687 calls from go_format_type() itself. */
689 static bool
690 go_format_type (struct godump_container *container, tree type,
691 bool use_type_name, bool is_func_ok, unsigned int *p_art_i,
692 bool is_anon_record_or_union)
694 bool ret;
695 struct obstack *ob;
696 unsigned int art_i_dummy;
697 bool is_union = false;
699 if (p_art_i == NULL)
701 art_i_dummy = 0;
702 p_art_i = &art_i_dummy;
704 ret = true;
705 ob = &container->type_obstack;
707 if (TYPE_NAME (type) != NULL_TREE
708 && (container->decls_seen.contains (type)
709 || container->decls_seen.contains (TYPE_NAME (type)))
710 && (AGGREGATE_TYPE_P (type)
711 || POINTER_TYPE_P (type)
712 || TREE_CODE (type) == FUNCTION_TYPE))
714 tree name;
715 void **slot;
717 name = TYPE_IDENTIFIER (type);
719 slot = htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (name),
720 NO_INSERT);
721 if (slot != NULL)
722 ret = false;
724 obstack_1grow (ob, '_');
725 go_append_string (ob, name);
726 return ret;
729 container->decls_seen.add (type);
731 switch (TREE_CODE (type))
733 case ENUMERAL_TYPE:
734 obstack_grow (ob, "int", 3);
735 break;
737 case TYPE_DECL:
739 void **slot;
741 slot = htab_find_slot (container->invalid_hash,
742 IDENTIFIER_POINTER (DECL_NAME (type)),
743 NO_INSERT);
744 if (slot != NULL)
745 ret = false;
747 obstack_1grow (ob, '_');
748 go_append_string (ob, DECL_NAME (type));
750 break;
752 case INTEGER_TYPE:
754 const char *s;
755 char buf[100];
757 s = go_get_uinttype_for_precision (TYPE_PRECISION (type),
758 TYPE_UNSIGNED (type));
759 if (s == NULL)
761 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
762 TYPE_PRECISION (type),
763 TYPE_UNSIGNED (type) ? "u" : "");
764 s = buf;
765 ret = false;
767 obstack_grow (ob, s, strlen (s));
769 break;
771 case REAL_TYPE:
773 const char *s;
774 char buf[100];
776 switch (TYPE_PRECISION (type))
778 case 32:
779 s = "float32";
780 break;
781 case 64:
782 s = "float64";
783 break;
784 default:
785 snprintf (buf, sizeof buf, "INVALID-float-%u",
786 TYPE_PRECISION (type));
787 s = buf;
788 ret = false;
789 break;
791 obstack_grow (ob, s, strlen (s));
793 break;
795 case COMPLEX_TYPE:
797 const char *s;
798 char buf[100];
799 tree real_type;
801 real_type = TREE_TYPE (type);
802 if (TREE_CODE (real_type) == REAL_TYPE)
804 switch (TYPE_PRECISION (real_type))
806 case 32:
807 s = "complex64";
808 break;
809 case 64:
810 s = "complex128";
811 break;
812 default:
813 snprintf (buf, sizeof buf, "INVALID-complex-%u",
814 2 * TYPE_PRECISION (real_type));
815 s = buf;
816 ret = false;
817 break;
820 else
822 s = "INVALID-complex-non-real";
823 ret = false;
825 obstack_grow (ob, s, strlen (s));
827 break;
829 case BOOLEAN_TYPE:
830 obstack_grow (ob, "bool", 4);
831 break;
833 case POINTER_TYPE:
834 if (use_type_name
835 && TYPE_NAME (TREE_TYPE (type)) != NULL_TREE
836 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))
837 || (POINTER_TYPE_P (TREE_TYPE (type))
838 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type)))
839 == FUNCTION_TYPE))))
841 tree name;
842 void **slot;
844 name = TYPE_IDENTIFIER (TREE_TYPE (type));
846 slot = htab_find_slot (container->invalid_hash,
847 IDENTIFIER_POINTER (name), NO_INSERT);
848 if (slot != NULL)
849 ret = false;
851 obstack_grow (ob, "*_", 2);
852 go_append_string (ob, name);
854 /* The pointer here can be used without the struct or union
855 definition. So this struct or union is a potential dummy
856 type. */
857 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
858 container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
860 return ret;
862 if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
863 obstack_grow (ob, "func", 4);
864 else
865 obstack_1grow (ob, '*');
866 if (VOID_TYPE_P (TREE_TYPE (type)))
867 obstack_grow (ob, "byte", 4);
868 else
870 if (!go_format_type (container, TREE_TYPE (type), use_type_name,
871 true, NULL, false))
872 ret = false;
874 break;
876 case ARRAY_TYPE:
877 obstack_1grow (ob, '[');
878 if (TYPE_DOMAIN (type) != NULL_TREE
879 && TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
880 && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
881 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
882 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0
883 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
884 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
885 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
887 char buf[100];
889 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
890 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type))));
891 obstack_grow (ob, buf, strlen (buf));
893 else
894 obstack_1grow (ob, '0');
895 obstack_1grow (ob, ']');
896 if (!go_format_type (container, TREE_TYPE (type), use_type_name, false,
897 NULL, false))
898 ret = false;
899 break;
901 case UNION_TYPE:
902 is_union = true;
903 /* Fall through to RECORD_TYPE case. */
904 case RECORD_TYPE:
906 unsigned int prev_field_end;
907 unsigned int known_alignment;
908 tree field;
909 bool emitted_a_field;
911 /* FIXME: Why is this necessary? Without it we can get a core
912 dump on the s390x headers, or from a file containing simply
913 "typedef struct S T;". */
914 layout_type (type);
916 prev_field_end = 0;
917 known_alignment = 1;
918 /* Anonymous records and unions are flattened, i.e. they are not put
919 into "struct { ... }". */
920 if (!is_anon_record_or_union)
921 obstack_grow (ob, "struct { ", 9);
922 for (field = TYPE_FIELDS (type), emitted_a_field = false;
923 field != NULL_TREE;
924 field = TREE_CHAIN (field))
926 if (TREE_CODE (field) != FIELD_DECL)
927 continue;
928 if (DECL_BIT_FIELD (field))
929 /* Bit fields are replaced by padding. */
930 continue;
931 /* Only the first non-bitfield field is emitted for unions. */
932 if (!is_union || !emitted_a_field)
934 /* Emit the field. */
935 bool field_ok;
936 bool is_anon_substructure;
937 unsigned int decl_align_unit;
938 unsigned int decl_offset;
940 field_ok = true;
941 emitted_a_field = true;
942 is_anon_substructure =
943 (DECL_NAME (field) == NULL
944 && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
945 || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE));
946 /* Keep track of the alignment of named substructures, either
947 of the whole record, or the alignment of the emitted field
948 (for unions). */
949 decl_align_unit = DECL_ALIGN_UNIT (field);
950 if (!is_anon_substructure && decl_align_unit > known_alignment)
951 known_alignment = decl_align_unit;
952 /* Pad to start of field. */
953 decl_offset =
954 TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
955 + precision_to_units
956 (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)));
958 unsigned int align_unit;
960 /* For anonymous records and unions there is no automatic
961 structure alignment, so use 1 as the alignment. */
962 align_unit = (is_anon_substructure) ? 1 : decl_align_unit;
963 *p_art_i = go_append_padding
964 (ob, prev_field_end, decl_offset, align_unit, *p_art_i,
965 &prev_field_end);
967 if (DECL_SIZE_UNIT (field))
968 prev_field_end +=
969 TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
970 /* Emit the field name, but not for anonymous records and
971 unions. */
972 if (!is_anon_substructure)
974 if ((DECL_NAME (field) == NULL))
975 *p_art_i = go_append_artificial_name (ob, *p_art_i);
976 else
977 go_append_decl_name
978 (ob, field, container->keyword_hash);
979 obstack_1grow (ob, ' ');
981 /* Do not expand type if a record or union type or a function
982 pointer. */
983 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
984 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
985 || (POINTER_TYPE_P (TREE_TYPE (field))
986 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
987 == FUNCTION_TYPE))))
989 tree name;
990 void **slot;
992 name = TYPE_IDENTIFIER (TREE_TYPE (field));
994 slot = htab_find_slot (container->invalid_hash,
995 IDENTIFIER_POINTER (name),
996 NO_INSERT);
997 if (slot != NULL)
998 field_ok = false;
1000 obstack_1grow (ob, '_');
1001 go_append_string (ob, name);
1003 else
1005 if (!go_format_type (container, TREE_TYPE (field), true,
1006 false, p_art_i, is_anon_substructure))
1007 field_ok = false;
1009 if (!is_anon_substructure)
1010 obstack_grow (ob, "; ", 2);
1011 if (!field_ok)
1012 ret = false;
1015 /* Padding. */
1017 unsigned int align_unit;
1019 align_unit = (is_anon_record_or_union) ? 1 : TYPE_ALIGN_UNIT (type);
1020 *p_art_i = go_append_padding
1021 (ob, prev_field_end, TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type)),
1022 align_unit, *p_art_i, &prev_field_end);
1024 /* Alignment. */
1025 if (!is_anon_record_or_union
1026 && known_alignment < TYPE_ALIGN_UNIT (type))
1028 const char *s;
1029 char buf[100];
1031 /* Enforce proper record alignment. */
1032 s = go_get_uinttype_for_precision
1033 (TYPE_ALIGN (type), TYPE_UNSIGNED (type));
1034 if (s == NULL)
1036 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
1037 TYPE_ALIGN (type), TYPE_UNSIGNED (type) ? "u" : "");
1038 s = buf;
1039 ret = false;
1041 *p_art_i = go_force_record_alignment (ob, s, *p_art_i, buf);
1043 if (!is_anon_record_or_union)
1044 obstack_1grow (ob, '}');
1046 break;
1048 case FUNCTION_TYPE:
1050 tree arg_type;
1051 bool is_varargs;
1052 tree result;
1053 function_args_iterator iter;
1054 bool seen_arg;
1056 /* Go has no way to write a type which is a function but not a
1057 pointer to a function. */
1058 if (!is_func_ok)
1060 obstack_grow (ob, "func*", 5);
1061 ret = false;
1064 obstack_1grow (ob, '(');
1065 is_varargs = stdarg_p (type);
1066 seen_arg = false;
1067 FOREACH_FUNCTION_ARGS (type, arg_type, iter)
1069 if (VOID_TYPE_P (arg_type))
1070 break;
1071 if (seen_arg)
1072 obstack_grow (ob, ", ", 2);
1073 if (!go_format_type (container, arg_type, true, false, NULL, false))
1074 ret = false;
1075 seen_arg = true;
1077 if (is_varargs)
1079 if (prototype_p (type))
1080 obstack_grow (ob, ", ", 2);
1081 obstack_grow (ob, "...interface{}", 14);
1083 obstack_1grow (ob, ')');
1085 result = TREE_TYPE (type);
1086 if (!VOID_TYPE_P (result))
1088 obstack_1grow (ob, ' ');
1089 if (!go_format_type (container, result, use_type_name, false, NULL,
1090 false))
1091 ret = false;
1094 break;
1096 default:
1097 obstack_grow (ob, "INVALID-type", 12);
1098 ret = false;
1099 break;
1102 return ret;
1105 /* Output the type which was built on the type obstack, and then free
1106 it. */
1108 static void
1109 go_output_type (struct godump_container *container)
1111 struct obstack *ob;
1113 ob = &container->type_obstack;
1114 obstack_1grow (ob, '\0');
1115 fputs ((char *) obstack_base (ob), go_dump_file);
1116 obstack_free (ob, obstack_base (ob));
1119 /* Output a function declaration. */
1121 static void
1122 go_output_fndecl (struct godump_container *container, tree decl)
1124 if (!go_format_type (container, TREE_TYPE (decl), false, true, NULL, false))
1125 fprintf (go_dump_file, "// ");
1126 fprintf (go_dump_file, "func _%s ",
1127 IDENTIFIER_POINTER (DECL_NAME (decl)));
1128 go_output_type (container);
1129 fprintf (go_dump_file, " __asm__(\"%s\")\n",
1130 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
1133 /* Output a typedef or something like a struct definition. */
1135 static void
1136 go_output_typedef (struct godump_container *container, tree decl)
1138 /* If we have an enum type, output the enum constants
1139 separately. */
1140 if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
1141 && TYPE_SIZE (TREE_TYPE (decl)) != 0
1142 && !container->decls_seen.contains (TREE_TYPE (decl))
1143 && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
1144 || !container->decls_seen.contains
1145 (TYPE_CANONICAL (TREE_TYPE (decl)))))
1147 tree element;
1149 for (element = TYPE_VALUES (TREE_TYPE (decl));
1150 element != NULL_TREE;
1151 element = TREE_CHAIN (element))
1153 const char *name;
1154 struct macro_hash_value *mhval;
1155 void **slot;
1156 char buf[WIDE_INT_PRINT_BUFFER_SIZE];
1158 name = IDENTIFIER_POINTER (TREE_PURPOSE (element));
1160 /* Sometimes a name will be defined as both an enum constant
1161 and a macro. Avoid duplicate definition errors by
1162 treating enum constants as macros. */
1163 mhval = XNEW (struct macro_hash_value);
1164 mhval->name = xstrdup (name);
1165 mhval->value = NULL;
1166 slot = htab_find_slot (macro_hash, mhval, INSERT);
1167 if (*slot != NULL)
1168 macro_hash_del (*slot);
1170 if (tree_fits_shwi_p (TREE_VALUE (element)))
1171 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC,
1172 tree_to_shwi (TREE_VALUE (element)));
1173 else if (tree_fits_uhwi_p (TREE_VALUE (element)))
1174 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_UNSIGNED,
1175 tree_to_uhwi (TREE_VALUE (element)));
1176 else
1177 print_hex (element, buf);
1179 mhval->value = xstrdup (buf);
1180 *slot = mhval;
1182 container->decls_seen.add (TREE_TYPE (decl));
1183 if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
1184 container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl)));
1187 if (DECL_NAME (decl) != NULL_TREE)
1189 void **slot;
1190 const char *type;
1192 type = IDENTIFIER_POINTER (DECL_NAME (decl));
1193 /* If type defined already, skip. */
1194 slot = htab_find_slot (container->type_hash, type, INSERT);
1195 if (*slot != NULL)
1196 return;
1197 *slot = CONST_CAST (void *, (const void *) type);
1199 if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL,
1200 false))
1202 fprintf (go_dump_file, "// ");
1203 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1204 *slot = CONST_CAST (void *, (const void *) type);
1206 fprintf (go_dump_file, "type _%s ",
1207 IDENTIFIER_POINTER (DECL_NAME (decl)));
1208 go_output_type (container);
1210 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1212 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
1214 if (size > 0)
1215 fprintf (go_dump_file,
1216 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1217 IDENTIFIER_POINTER (DECL_NAME (decl)),
1218 size);
1221 container->decls_seen.add (decl);
1223 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1225 void **slot;
1226 const char *type;
1227 HOST_WIDE_INT size;
1229 type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
1230 /* If type defined already, skip. */
1231 slot = htab_find_slot (container->type_hash, type, INSERT);
1232 if (*slot != NULL)
1233 return;
1234 *slot = CONST_CAST (void *, (const void *) type);
1236 if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL,
1237 false))
1239 fprintf (go_dump_file, "// ");
1240 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1241 *slot = CONST_CAST (void *, (const void *) type);
1243 fprintf (go_dump_file, "type _%s ",
1244 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
1245 go_output_type (container);
1247 size = int_size_in_bytes (TREE_TYPE (decl));
1248 if (size > 0)
1249 fprintf (go_dump_file,
1250 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1251 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))),
1252 size);
1254 else
1255 return;
1257 fprintf (go_dump_file, "\n");
1260 /* Output a variable. */
1262 static void
1263 go_output_var (struct godump_container *container, tree decl)
1265 bool is_valid;
1266 tree type_name;
1267 tree id;
1269 if (container->decls_seen.contains (decl)
1270 || container->decls_seen.contains (DECL_NAME (decl)))
1271 return;
1272 container->decls_seen.add (decl);
1273 container->decls_seen.add (DECL_NAME (decl));
1275 type_name = TYPE_NAME (TREE_TYPE (decl));
1276 id = NULL_TREE;
1277 if (type_name != NULL_TREE && TREE_CODE (type_name) == IDENTIFIER_NODE)
1278 id = type_name;
1279 else if (type_name != NULL_TREE && TREE_CODE (type_name) == TYPE_DECL
1280 && DECL_SOURCE_LOCATION (type_name) != BUILTINS_LOCATION
1281 && DECL_NAME (type_name))
1282 id = DECL_NAME (type_name);
1283 if (id != NULL_TREE
1284 && (!htab_find_slot (container->type_hash, IDENTIFIER_POINTER (id),
1285 NO_INSERT)
1286 || htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (id),
1287 NO_INSERT)))
1288 id = NULL_TREE;
1289 if (id != NULL_TREE)
1291 struct obstack *ob;
1293 ob = &container->type_obstack;
1294 obstack_1grow (ob, '_');
1295 go_append_string (ob, id);
1296 is_valid = htab_find_slot (container->type_hash, IDENTIFIER_POINTER (id),
1297 NO_INSERT) != NULL;
1299 else
1300 is_valid = go_format_type (container, TREE_TYPE (decl), true, false, NULL,
1301 false);
1302 if (is_valid
1303 && htab_find_slot (container->type_hash,
1304 IDENTIFIER_POINTER (DECL_NAME (decl)),
1305 NO_INSERT) != NULL)
1307 /* There is already a type with this name, probably from a
1308 struct tag. Prefer the type to the variable. */
1309 is_valid = false;
1311 if (!is_valid)
1312 fprintf (go_dump_file, "// ");
1314 fprintf (go_dump_file, "var _%s ",
1315 IDENTIFIER_POINTER (DECL_NAME (decl)));
1316 go_output_type (container);
1317 fprintf (go_dump_file, "\n");
1319 /* Sometimes an extern variable is declared with an unknown struct
1320 type. */
1321 if (type_name != NULL_TREE && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1323 if (TREE_CODE (type_name) == IDENTIFIER_NODE)
1324 container->pot_dummy_types.add (IDENTIFIER_POINTER (type_name));
1325 else if (TREE_CODE (type_name) == TYPE_DECL)
1326 container->pot_dummy_types.add
1327 (IDENTIFIER_POINTER (DECL_NAME (type_name)));
1331 /* Output the final value of a preprocessor macro or enum constant.
1332 This is called via htab_traverse_noresize. */
1334 static int
1335 go_print_macro (void **slot, void *arg ATTRIBUTE_UNUSED)
1337 struct macro_hash_value *mhval = (struct macro_hash_value *) *slot;
1338 fprintf (go_dump_file, "const _%s = %s\n", mhval->name, mhval->value);
1339 return 1;
1342 /* Build a hash table with the Go keywords. */
1344 static const char * const keywords[] = {
1345 "__asm__", "break", "case", "chan", "const", "continue", "default",
1346 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1347 "import", "interface", "map", "package", "range", "return", "select",
1348 "struct", "switch", "type", "var"
1351 static void
1352 keyword_hash_init (struct godump_container *container)
1354 size_t i;
1355 size_t count = sizeof (keywords) / sizeof (keywords[0]);
1356 void **slot;
1358 for (i = 0; i < count; i++)
1360 slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
1361 *slot = CONST_CAST (void *, (const void *) keywords[i]);
1365 /* Traversing the pot_dummy_types and seeing which types are present
1366 in the global types hash table and creating dummy definitions if
1367 not found. This function is invoked by hash_set::traverse. */
1369 bool
1370 find_dummy_types (const char *const &ptr, godump_container *adata)
1372 struct godump_container *data = (struct godump_container *) adata;
1373 const char *type = (const char *) ptr;
1374 void **slot;
1375 void **islot;
1377 slot = htab_find_slot (data->type_hash, type, NO_INSERT);
1378 islot = htab_find_slot (data->invalid_hash, type, NO_INSERT);
1379 if (slot == NULL || islot != NULL)
1380 fprintf (go_dump_file, "type _%s struct {}\n", type);
1381 return true;
1384 /* Output symbols. */
1386 static void
1387 go_finish (const char *filename)
1389 struct godump_container container;
1390 unsigned int ix;
1391 tree decl;
1393 real_debug_hooks->finish (filename);
1395 container.type_hash = htab_create (100, htab_hash_string,
1396 string_hash_eq, NULL);
1397 container.invalid_hash = htab_create (10, htab_hash_string,
1398 string_hash_eq, NULL);
1399 container.keyword_hash = htab_create (50, htab_hash_string,
1400 string_hash_eq, NULL);
1401 obstack_init (&container.type_obstack);
1403 keyword_hash_init (&container);
1405 FOR_EACH_VEC_SAFE_ELT (queue, ix, decl)
1407 switch (TREE_CODE (decl))
1409 case FUNCTION_DECL:
1410 go_output_fndecl (&container, decl);
1411 break;
1413 case TYPE_DECL:
1414 go_output_typedef (&container, decl);
1415 break;
1417 case VAR_DECL:
1418 go_output_var (&container, decl);
1419 break;
1421 default:
1422 gcc_unreachable ();
1426 htab_traverse_noresize (macro_hash, go_print_macro, NULL);
1428 /* To emit dummy definitions. */
1429 container.pot_dummy_types.traverse<godump_container *, find_dummy_types>
1430 (&container);
1432 htab_delete (container.type_hash);
1433 htab_delete (container.invalid_hash);
1434 htab_delete (container.keyword_hash);
1435 obstack_free (&container.type_obstack, NULL);
1437 vec_free (queue);
1439 if (fclose (go_dump_file) != 0)
1440 error ("could not close Go dump file: %m");
1441 go_dump_file = NULL;
1444 /* Set up our hooks. */
1446 const struct gcc_debug_hooks *
1447 dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
1449 go_dump_file = fopen (filename, "w");
1450 if (go_dump_file == NULL)
1452 error ("could not open Go dump file %qs: %m", filename);
1453 return hooks;
1456 go_debug_hooks = *hooks;
1457 real_debug_hooks = hooks;
1459 go_debug_hooks.finish = go_finish;
1460 go_debug_hooks.define = go_define;
1461 go_debug_hooks.undef = go_undef;
1462 go_debug_hooks.function_decl = go_function_decl;
1463 go_debug_hooks.global_decl = go_global_decl;
1464 go_debug_hooks.type_decl = go_type_decl;
1466 macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq,
1467 macro_hash_del);
1469 return &go_debug_hooks;
1472 #include "gt-godump.h"