2015-06-11 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / godump.c
blob63bd7dd440ae35840eeb68007bebb99e122b7605
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 "input.h"
35 #include "alias.h"
36 #include "symtab.h"
37 #include "options.h"
38 #include "tree.h"
39 #include "obstack.h"
40 #include "debug.h"
41 #include "wide-int-print.h"
42 #include "stor-layout.h"
43 #include "defaults.h"
45 /* We dump this information from the debug hooks. This gives us a
46 stable and maintainable API to hook into. In order to work
47 correctly when -g is used, we build our own hooks structure which
48 wraps the hooks we need to change. */
50 /* Our debug hooks. This is initialized by dump_go_spec_init. */
52 static struct gcc_debug_hooks go_debug_hooks;
54 /* The real debug hooks. */
56 static const struct gcc_debug_hooks *real_debug_hooks;
58 /* The file where we should write information. */
60 static FILE *go_dump_file;
62 /* A queue of decls to output. */
64 static GTY(()) vec<tree, va_gc> *queue;
66 /* A hash table of macros we have seen. */
68 static htab_t macro_hash;
70 /* The type of a value in macro_hash. */
72 struct macro_hash_value
74 /* The name stored in the hash table. */
75 char *name;
76 /* The value of the macro. */
77 char *value;
80 /* Returns the number of units necessary to represent an integer with the given
81 PRECISION (in bits). */
83 static inline unsigned int
84 precision_to_units (unsigned int precision)
86 return (precision + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
89 /* Calculate the hash value for an entry in the macro hash table. */
91 static hashval_t
92 macro_hash_hashval (const void *val)
94 const struct macro_hash_value *mhval = (const struct macro_hash_value *) val;
95 return htab_hash_string (mhval->name);
98 /* Compare values in the macro hash table for equality. */
100 static int
101 macro_hash_eq (const void *v1, const void *v2)
103 const struct macro_hash_value *mhv1 = (const struct macro_hash_value *) v1;
104 const struct macro_hash_value *mhv2 = (const struct macro_hash_value *) v2;
105 return strcmp (mhv1->name, mhv2->name) == 0;
108 /* Free values deleted from the macro hash table. */
110 static void
111 macro_hash_del (void *v)
113 struct macro_hash_value *mhv = (struct macro_hash_value *) v;
114 XDELETEVEC (mhv->name);
115 XDELETEVEC (mhv->value);
116 XDELETE (mhv);
119 /* For the string hash tables. */
121 static int
122 string_hash_eq (const void *y1, const void *y2)
124 return strcmp ((const char *) y1, (const char *) y2) == 0;
127 /* A macro definition. */
129 static void
130 go_define (unsigned int lineno, const char *buffer)
132 const char *p;
133 const char *name_end;
134 size_t out_len;
135 char *out_buffer;
136 char *q;
137 bool saw_operand;
138 bool need_operand;
139 struct macro_hash_value *mhval;
140 char *copy;
141 hashval_t hashval;
142 void **slot;
144 real_debug_hooks->define (lineno, buffer);
146 /* Skip macro functions. */
147 for (p = buffer; *p != '\0' && *p != ' '; ++p)
148 if (*p == '(')
149 return;
151 if (*p == '\0')
152 return;
154 name_end = p;
156 ++p;
157 if (*p == '\0')
158 return;
160 copy = XNEWVEC (char, name_end - buffer + 1);
161 memcpy (copy, buffer, name_end - buffer);
162 copy[name_end - buffer] = '\0';
164 mhval = XNEW (struct macro_hash_value);
165 mhval->name = copy;
166 mhval->value = NULL;
168 hashval = htab_hash_string (copy);
169 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, NO_INSERT);
171 /* For simplicity, we force all names to be hidden by adding an
172 initial underscore, and let the user undo this as needed. */
173 out_len = strlen (p) * 2 + 1;
174 out_buffer = XNEWVEC (char, out_len);
175 q = out_buffer;
176 saw_operand = false;
177 need_operand = false;
178 while (*p != '\0')
180 switch (*p)
182 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
183 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
184 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
185 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
186 case 'Y': case 'Z':
187 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
188 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
189 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
190 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
191 case 'y': case 'z':
192 case '_':
194 /* The start of an identifier. Technically we should also
195 worry about UTF-8 identifiers, but they are not a
196 problem for practical uses of -fdump-go-spec so we
197 don't worry about them. */
198 const char *start;
199 char *n;
200 struct macro_hash_value idval;
202 if (saw_operand)
203 goto unknown;
205 start = p;
206 while (ISALNUM (*p) || *p == '_')
207 ++p;
208 n = XALLOCAVEC (char, p - start + 1);
209 memcpy (n, start, p - start);
210 n[p - start] = '\0';
211 idval.name = n;
212 idval.value = NULL;
213 if (htab_find (macro_hash, &idval) == NULL)
215 /* This is a reference to a name which was not defined
216 as a macro. */
217 goto unknown;
220 *q++ = '_';
221 memcpy (q, start, p - start);
222 q += p - start;
224 saw_operand = true;
225 need_operand = false;
227 break;
229 case '.':
230 if (!ISDIGIT (p[1]))
231 goto unknown;
232 /* Fall through. */
233 case '0': case '1': case '2': case '3': case '4':
234 case '5': case '6': case '7': case '8': case '9':
236 const char *start;
237 bool is_hex;
239 start = p;
240 is_hex = false;
241 if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
243 p += 2;
244 is_hex = true;
246 while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
247 || (is_hex
248 && ((*p >= 'a' && *p <= 'f')
249 || (*p >= 'A' && *p <= 'F'))))
250 ++p;
251 memcpy (q, start, p - start);
252 q += p - start;
253 while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
254 || *p == 'f' || *p == 'F'
255 || *p == 'd' || *p == 'D')
257 /* Go doesn't use any of these trailing type
258 modifiers. */
259 ++p;
262 /* We'll pick up the exponent, if any, as an
263 expression. */
265 saw_operand = true;
266 need_operand = false;
268 break;
270 case ' ': case '\t':
271 *q++ = *p++;
272 break;
274 case '(':
275 /* Always OK, not part of an operand, presumed to start an
276 operand. */
277 *q++ = *p++;
278 saw_operand = false;
279 need_operand = false;
280 break;
282 case ')':
283 /* OK if we don't need an operand, and presumed to indicate
284 an operand. */
285 if (need_operand)
286 goto unknown;
287 *q++ = *p++;
288 saw_operand = true;
289 break;
291 case '+': case '-':
292 /* Always OK, but not part of an operand. */
293 *q++ = *p++;
294 saw_operand = false;
295 break;
297 case '*': case '/': case '%': case '|': case '&': case '^':
298 /* Must be a binary operator. */
299 if (!saw_operand)
300 goto unknown;
301 *q++ = *p++;
302 saw_operand = false;
303 need_operand = true;
304 break;
306 case '=':
307 *q++ = *p++;
308 if (*p != '=')
309 goto unknown;
310 /* Must be a binary operator. */
311 if (!saw_operand)
312 goto unknown;
313 *q++ = *p++;
314 saw_operand = false;
315 need_operand = true;
316 break;
318 case '!':
319 *q++ = *p++;
320 if (*p == '=')
322 /* Must be a binary operator. */
323 if (!saw_operand)
324 goto unknown;
325 *q++ = *p++;
326 saw_operand = false;
327 need_operand = true;
329 else
331 /* Must be a unary operator. */
332 if (saw_operand)
333 goto unknown;
334 need_operand = true;
336 break;
338 case '<': case '>':
339 /* Must be a binary operand, may be << or >> or <= or >=. */
340 if (!saw_operand)
341 goto unknown;
342 *q++ = *p++;
343 if (*p == *(p - 1) || *p == '=')
344 *q++ = *p++;
345 saw_operand = false;
346 need_operand = true;
347 break;
349 case '~':
350 /* Must be a unary operand, must be translated for Go. */
351 if (saw_operand)
352 goto unknown;
353 *q++ = '^';
354 p++;
355 need_operand = true;
356 break;
358 case '"':
359 case '\'':
361 char quote;
362 int count;
364 if (saw_operand)
365 goto unknown;
366 quote = *p;
367 *q++ = *p++;
368 count = 0;
369 while (*p != quote)
371 int c;
373 if (*p == '\0')
374 goto unknown;
376 ++count;
378 if (*p != '\\')
380 *q++ = *p++;
381 continue;
384 *q++ = *p++;
385 switch (*p)
387 case '0': case '1': case '2': case '3':
388 case '4': case '5': case '6': case '7':
389 c = 0;
390 while (*p >= '0' && *p <= '7')
392 *q++ = *p++;
393 ++c;
395 /* Go octal characters are always 3
396 digits. */
397 if (c != 3)
398 goto unknown;
399 break;
401 case 'x':
402 *q++ = *p++;
403 c = 0;
404 while (ISXDIGIT (*p))
406 *q++ = *p++;
407 ++c;
409 /* Go hex characters are always 2 digits. */
410 if (c != 2)
411 goto unknown;
412 break;
414 case 'a': case 'b': case 'f': case 'n': case 'r':
415 case 't': case 'v': case '\\': case '\'': case '"':
416 *q++ = *p++;
417 break;
419 default:
420 goto unknown;
424 *q++ = *p++;
426 if (quote == '\'' && count != 1)
427 goto unknown;
429 saw_operand = true;
430 need_operand = false;
432 break;
435 default:
436 goto unknown;
440 if (need_operand)
441 goto unknown;
443 gcc_assert ((size_t) (q - out_buffer) < out_len);
444 *q = '\0';
446 mhval->value = out_buffer;
448 if (slot == NULL)
450 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, INSERT);
451 gcc_assert (slot != NULL && *slot == NULL);
453 else
455 if (*slot != NULL)
456 macro_hash_del (*slot);
459 *slot = mhval;
461 return;
463 unknown:
464 fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
465 if (slot != NULL)
466 htab_clear_slot (macro_hash, slot);
467 XDELETEVEC (out_buffer);
468 XDELETEVEC (copy);
471 /* A macro undef. */
473 static void
474 go_undef (unsigned int lineno, const char *buffer)
476 struct macro_hash_value mhval;
477 void **slot;
479 real_debug_hooks->undef (lineno, buffer);
481 mhval.name = CONST_CAST (char *, buffer);
482 mhval.value = NULL;
483 slot = htab_find_slot (macro_hash, &mhval, NO_INSERT);
484 if (slot != NULL)
485 htab_clear_slot (macro_hash, slot);
488 /* A function or variable decl. */
490 static void
491 go_decl (tree decl)
493 if (!TREE_PUBLIC (decl)
494 || DECL_IS_BUILTIN (decl)
495 || DECL_NAME (decl) == NULL_TREE)
496 return;
497 vec_safe_push (queue, decl);
500 /* A function decl. */
502 static void
503 go_function_decl (tree decl)
505 real_debug_hooks->function_decl (decl);
506 go_decl (decl);
509 static void
510 go_early_global_decl (tree decl)
512 go_decl (decl);
513 real_debug_hooks->early_global_decl (decl);
516 /* A global variable decl. */
518 static void
519 go_late_global_decl (tree decl)
521 real_debug_hooks->late_global_decl (decl);
524 /* A type declaration. */
526 static void
527 go_type_decl (tree decl, int local)
529 real_debug_hooks->type_decl (decl, local);
531 if (local || DECL_IS_BUILTIN (decl))
532 return;
533 if (DECL_NAME (decl) == NULL_TREE
534 && (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE
535 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) != IDENTIFIER_NODE)
536 && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
537 return;
538 vec_safe_push (queue, decl);
541 /* A container for the data we pass around when generating information
542 at the end of the compilation. */
544 struct godump_container
546 /* DECLs that we have already seen. */
547 hash_set<tree> decls_seen;
549 /* Types which may potentially have to be defined as dummy
550 types. */
551 hash_set<const char *> pot_dummy_types;
553 /* Go keywords. */
554 htab_t keyword_hash;
556 /* Global type definitions. */
557 htab_t type_hash;
559 /* Invalid types. */
560 htab_t invalid_hash;
562 /* Obstack used to write out a type definition. */
563 struct obstack type_obstack;
566 /* Append an IDENTIFIER_NODE to OB. */
568 static void
569 go_append_string (struct obstack *ob, tree id)
571 obstack_grow (ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
574 /* Given an integer PRECISION in bits, returns a constant string that is the
575 matching go int or uint type (depending on the IS_UNSIGNED flag). Returns a
576 NULL pointer if there is no matching go type. */
578 static const char *
579 go_get_uinttype_for_precision (unsigned int precision, bool is_unsigned)
581 switch (precision)
583 case 8:
584 return is_unsigned ? "uint8" : "int8";
585 case 16:
586 return is_unsigned ? "uint16" : "int16";
587 case 32:
588 return is_unsigned ? "uint32" : "int32";
589 case 64:
590 return is_unsigned ? "uint64" : "int64";
591 default:
592 return NULL;
596 /* Append an artificial variable name with the suffix _INDEX to OB. Returns
597 INDEX + 1. */
599 static unsigned int
600 go_append_artificial_name (struct obstack *ob, unsigned int index)
602 char buf[100];
604 /* FIXME: identifier may not be unique. */
605 obstack_grow (ob, "Godump_", 7);
606 snprintf (buf, sizeof buf, "%u", index);
607 obstack_grow (ob, buf, strlen (buf));
609 return index + 1;
612 /* Append the variable name from DECL to OB. If the name is in the
613 KEYWORD_HASH, prepend an '_'. */
615 static void
616 go_append_decl_name (struct obstack *ob, tree decl, htab_t keyword_hash)
618 const char *var_name;
619 void **slot;
621 /* Start variable name with an underscore if a keyword. */
622 var_name = IDENTIFIER_POINTER (DECL_NAME (decl));
623 slot = htab_find_slot (keyword_hash, var_name, NO_INSERT);
624 if (slot != NULL)
625 obstack_1grow (ob, '_');
626 go_append_string (ob, DECL_NAME (decl));
629 /* Appends a byte array with the necessary number of elements and the name
630 "Godump_INDEX_pad" to pad from FROM_OFFSET to TO_OFFSET to OB assuming that
631 the next field is automatically aligned to ALIGN_UNITS. Returns INDEX + 1,
632 or INDEX if no padding had to be appended. The resulting offset where the
633 next field is allocated is returned through RET_OFFSET. */
635 static unsigned int
636 go_append_padding (struct obstack *ob, unsigned int from_offset,
637 unsigned int to_offset, unsigned int align_units,
638 unsigned int index, unsigned int *ret_offset)
640 if (from_offset % align_units > 0)
641 from_offset += align_units - (from_offset % align_units);
642 gcc_assert (to_offset >= from_offset);
643 if (to_offset > from_offset)
645 char buf[100];
647 index = go_append_artificial_name (ob, index);
648 snprintf (buf, sizeof buf, "_pad [%u]byte; ", to_offset - from_offset);
649 obstack_grow (ob, buf, strlen (buf));
651 *ret_offset = to_offset;
653 return index;
656 /* Appends an array of type TYPE_STRING with zero elements and the name
657 "Godump_INDEX_align" to OB. If TYPE_STRING is a null pointer, ERROR_STRING
658 is appended instead of the type. Returns INDEX + 1. */
660 static unsigned int
661 go_force_record_alignment (struct obstack *ob, const char *type_string,
662 unsigned int index, const char *error_string)
664 index = go_append_artificial_name (ob, index);
665 obstack_grow (ob, "_align ", 7);
666 if (type_string == NULL)
667 obstack_grow (ob, error_string, strlen (error_string));
668 else
670 obstack_grow (ob, "[0]", 3);
671 obstack_grow (ob, type_string, strlen (type_string));
673 obstack_grow (ob, "; ", 2);
675 return index;
678 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
679 USE_TYPE_NAME is true if we can simply use a type name here without
680 needing to define it. IS_FUNC_OK is true if we can output a func
681 type here; the "func" keyword will already have been added.
682 Return true if the type can be represented in Go, false otherwise.
683 P_ART_I is used for indexing artificial elements in nested structures and
684 should always be a NULL pointer when called, except by certain recursive
685 calls from go_format_type() itself. */
687 static bool
688 go_format_type (struct godump_container *container, tree type,
689 bool use_type_name, bool is_func_ok, unsigned int *p_art_i,
690 bool is_anon_record_or_union)
692 bool ret;
693 struct obstack *ob;
694 unsigned int art_i_dummy;
695 bool is_union = false;
697 if (p_art_i == NULL)
699 art_i_dummy = 0;
700 p_art_i = &art_i_dummy;
702 ret = true;
703 ob = &container->type_obstack;
705 if (TYPE_NAME (type) != NULL_TREE
706 && (container->decls_seen.contains (type)
707 || container->decls_seen.contains (TYPE_NAME (type)))
708 && (AGGREGATE_TYPE_P (type)
709 || POINTER_TYPE_P (type)
710 || TREE_CODE (type) == FUNCTION_TYPE))
712 tree name;
713 void **slot;
715 name = TYPE_IDENTIFIER (type);
717 slot = htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (name),
718 NO_INSERT);
719 if (slot != NULL)
720 ret = false;
722 obstack_1grow (ob, '_');
723 go_append_string (ob, name);
724 return ret;
727 container->decls_seen.add (type);
729 switch (TREE_CODE (type))
731 case ENUMERAL_TYPE:
732 obstack_grow (ob, "int", 3);
733 break;
735 case TYPE_DECL:
737 void **slot;
739 slot = htab_find_slot (container->invalid_hash,
740 IDENTIFIER_POINTER (DECL_NAME (type)),
741 NO_INSERT);
742 if (slot != NULL)
743 ret = false;
745 obstack_1grow (ob, '_');
746 go_append_string (ob, DECL_NAME (type));
748 break;
750 case INTEGER_TYPE:
752 const char *s;
753 char buf[100];
755 s = go_get_uinttype_for_precision (TYPE_PRECISION (type),
756 TYPE_UNSIGNED (type));
757 if (s == NULL)
759 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
760 TYPE_PRECISION (type),
761 TYPE_UNSIGNED (type) ? "u" : "");
762 s = buf;
763 ret = false;
765 obstack_grow (ob, s, strlen (s));
767 break;
769 case REAL_TYPE:
771 const char *s;
772 char buf[100];
774 switch (TYPE_PRECISION (type))
776 case 32:
777 s = "float32";
778 break;
779 case 64:
780 s = "float64";
781 break;
782 default:
783 snprintf (buf, sizeof buf, "INVALID-float-%u",
784 TYPE_PRECISION (type));
785 s = buf;
786 ret = false;
787 break;
789 obstack_grow (ob, s, strlen (s));
791 break;
793 case COMPLEX_TYPE:
795 const char *s;
796 char buf[100];
797 tree real_type;
799 real_type = TREE_TYPE (type);
800 if (TREE_CODE (real_type) == REAL_TYPE)
802 switch (TYPE_PRECISION (real_type))
804 case 32:
805 s = "complex64";
806 break;
807 case 64:
808 s = "complex128";
809 break;
810 default:
811 snprintf (buf, sizeof buf, "INVALID-complex-%u",
812 2 * TYPE_PRECISION (real_type));
813 s = buf;
814 ret = false;
815 break;
818 else
820 s = "INVALID-complex-non-real";
821 ret = false;
823 obstack_grow (ob, s, strlen (s));
825 break;
827 case BOOLEAN_TYPE:
828 obstack_grow (ob, "bool", 4);
829 break;
831 case POINTER_TYPE:
832 if (use_type_name
833 && TYPE_NAME (TREE_TYPE (type)) != NULL_TREE
834 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))
835 || (POINTER_TYPE_P (TREE_TYPE (type))
836 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type)))
837 == FUNCTION_TYPE))))
839 tree name;
840 void **slot;
842 name = TYPE_IDENTIFIER (TREE_TYPE (type));
844 slot = htab_find_slot (container->invalid_hash,
845 IDENTIFIER_POINTER (name), NO_INSERT);
846 if (slot != NULL)
847 ret = false;
849 obstack_grow (ob, "*_", 2);
850 go_append_string (ob, name);
852 /* The pointer here can be used without the struct or union
853 definition. So this struct or union is a potential dummy
854 type. */
855 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
856 container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
858 return ret;
860 if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
861 obstack_grow (ob, "func", 4);
862 else
863 obstack_1grow (ob, '*');
864 if (VOID_TYPE_P (TREE_TYPE (type)))
865 obstack_grow (ob, "byte", 4);
866 else
868 if (!go_format_type (container, TREE_TYPE (type), use_type_name,
869 true, NULL, false))
870 ret = false;
872 break;
874 case ARRAY_TYPE:
875 obstack_1grow (ob, '[');
876 if (TYPE_DOMAIN (type) != NULL_TREE
877 && TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
878 && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
879 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
880 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0
881 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
882 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
883 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
885 char buf[100];
887 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
888 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type))));
889 obstack_grow (ob, buf, strlen (buf));
891 else
892 obstack_1grow (ob, '0');
893 obstack_1grow (ob, ']');
894 if (!go_format_type (container, TREE_TYPE (type), use_type_name, false,
895 NULL, false))
896 ret = false;
897 break;
899 case UNION_TYPE:
900 is_union = true;
901 /* Fall through to RECORD_TYPE case. */
902 case RECORD_TYPE:
904 unsigned int prev_field_end;
905 unsigned int known_alignment;
906 tree field;
907 bool emitted_a_field;
909 /* FIXME: Why is this necessary? Without it we can get a core
910 dump on the s390x headers, or from a file containing simply
911 "typedef struct S T;". */
912 layout_type (type);
914 prev_field_end = 0;
915 known_alignment = 1;
916 /* Anonymous records and unions are flattened, i.e. they are not put
917 into "struct { ... }". */
918 if (!is_anon_record_or_union)
919 obstack_grow (ob, "struct { ", 9);
920 for (field = TYPE_FIELDS (type), emitted_a_field = false;
921 field != NULL_TREE;
922 field = TREE_CHAIN (field))
924 if (TREE_CODE (field) != FIELD_DECL)
925 continue;
926 if (DECL_BIT_FIELD (field))
927 /* Bit fields are replaced by padding. */
928 continue;
929 /* Only the first non-bitfield field is emitted for unions. */
930 if (!is_union || !emitted_a_field)
932 /* Emit the field. */
933 bool field_ok;
934 bool is_anon_substructure;
935 unsigned int decl_align_unit;
936 unsigned int decl_offset;
938 field_ok = true;
939 emitted_a_field = true;
940 is_anon_substructure =
941 (DECL_NAME (field) == NULL
942 && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
943 || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE));
944 /* Keep track of the alignment of named substructures, either
945 of the whole record, or the alignment of the emitted field
946 (for unions). */
947 decl_align_unit = DECL_ALIGN_UNIT (field);
948 if (!is_anon_substructure && decl_align_unit > known_alignment)
949 known_alignment = decl_align_unit;
950 /* Pad to start of field. */
951 decl_offset =
952 TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
953 + precision_to_units
954 (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)));
956 unsigned int align_unit;
958 /* For anonymous records and unions there is no automatic
959 structure alignment, so use 1 as the alignment. */
960 align_unit = (is_anon_substructure) ? 1 : decl_align_unit;
961 *p_art_i = go_append_padding
962 (ob, prev_field_end, decl_offset, align_unit, *p_art_i,
963 &prev_field_end);
965 if (DECL_SIZE_UNIT (field))
966 prev_field_end +=
967 TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
968 /* Emit the field name, but not for anonymous records and
969 unions. */
970 if (!is_anon_substructure)
972 if ((DECL_NAME (field) == NULL))
973 *p_art_i = go_append_artificial_name (ob, *p_art_i);
974 else
975 go_append_decl_name
976 (ob, field, container->keyword_hash);
977 obstack_1grow (ob, ' ');
979 /* Do not expand type if a record or union type or a function
980 pointer. */
981 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
982 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
983 || (POINTER_TYPE_P (TREE_TYPE (field))
984 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
985 == FUNCTION_TYPE))))
987 tree name;
988 void **slot;
990 name = TYPE_IDENTIFIER (TREE_TYPE (field));
992 slot = htab_find_slot (container->invalid_hash,
993 IDENTIFIER_POINTER (name),
994 NO_INSERT);
995 if (slot != NULL)
996 field_ok = false;
998 obstack_1grow (ob, '_');
999 go_append_string (ob, name);
1001 else
1003 if (!go_format_type (container, TREE_TYPE (field), true,
1004 false, p_art_i, is_anon_substructure))
1005 field_ok = false;
1007 if (!is_anon_substructure)
1008 obstack_grow (ob, "; ", 2);
1009 if (!field_ok)
1010 ret = false;
1013 /* Padding. */
1015 unsigned int align_unit;
1017 align_unit = (is_anon_record_or_union) ? 1 : TYPE_ALIGN_UNIT (type);
1018 *p_art_i = go_append_padding
1019 (ob, prev_field_end, TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type)),
1020 align_unit, *p_art_i, &prev_field_end);
1022 /* Alignment. */
1023 if (!is_anon_record_or_union
1024 && known_alignment < TYPE_ALIGN_UNIT (type))
1026 const char *s;
1027 char buf[100];
1029 /* Enforce proper record alignment. */
1030 s = go_get_uinttype_for_precision
1031 (TYPE_ALIGN (type), TYPE_UNSIGNED (type));
1032 if (s == NULL)
1034 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
1035 TYPE_ALIGN (type), TYPE_UNSIGNED (type) ? "u" : "");
1036 s = buf;
1037 ret = false;
1039 *p_art_i = go_force_record_alignment (ob, s, *p_art_i, buf);
1041 if (!is_anon_record_or_union)
1042 obstack_1grow (ob, '}');
1044 break;
1046 case FUNCTION_TYPE:
1048 tree arg_type;
1049 bool is_varargs;
1050 tree result;
1051 function_args_iterator iter;
1052 bool seen_arg;
1054 /* Go has no way to write a type which is a function but not a
1055 pointer to a function. */
1056 if (!is_func_ok)
1058 obstack_grow (ob, "func*", 5);
1059 ret = false;
1062 obstack_1grow (ob, '(');
1063 is_varargs = stdarg_p (type);
1064 seen_arg = false;
1065 FOREACH_FUNCTION_ARGS (type, arg_type, iter)
1067 if (VOID_TYPE_P (arg_type))
1068 break;
1069 if (seen_arg)
1070 obstack_grow (ob, ", ", 2);
1071 if (!go_format_type (container, arg_type, true, false, NULL, false))
1072 ret = false;
1073 seen_arg = true;
1075 if (is_varargs)
1077 if (prototype_p (type))
1078 obstack_grow (ob, ", ", 2);
1079 obstack_grow (ob, "...interface{}", 14);
1081 obstack_1grow (ob, ')');
1083 result = TREE_TYPE (type);
1084 if (!VOID_TYPE_P (result))
1086 obstack_1grow (ob, ' ');
1087 if (!go_format_type (container, result, use_type_name, false, NULL,
1088 false))
1089 ret = false;
1092 break;
1094 default:
1095 obstack_grow (ob, "INVALID-type", 12);
1096 ret = false;
1097 break;
1100 return ret;
1103 /* Output the type which was built on the type obstack, and then free
1104 it. */
1106 static void
1107 go_output_type (struct godump_container *container)
1109 struct obstack *ob;
1111 ob = &container->type_obstack;
1112 obstack_1grow (ob, '\0');
1113 fputs ((char *) obstack_base (ob), go_dump_file);
1114 obstack_free (ob, obstack_base (ob));
1117 /* Output a function declaration. */
1119 static void
1120 go_output_fndecl (struct godump_container *container, tree decl)
1122 if (!go_format_type (container, TREE_TYPE (decl), false, true, NULL, false))
1123 fprintf (go_dump_file, "// ");
1124 fprintf (go_dump_file, "func _%s ",
1125 IDENTIFIER_POINTER (DECL_NAME (decl)));
1126 go_output_type (container);
1127 fprintf (go_dump_file, " __asm__(\"%s\")\n",
1128 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
1131 /* Output a typedef or something like a struct definition. */
1133 static void
1134 go_output_typedef (struct godump_container *container, tree decl)
1136 /* If we have an enum type, output the enum constants
1137 separately. */
1138 if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
1139 && TYPE_SIZE (TREE_TYPE (decl)) != 0
1140 && !container->decls_seen.contains (TREE_TYPE (decl))
1141 && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
1142 || !container->decls_seen.contains
1143 (TYPE_CANONICAL (TREE_TYPE (decl)))))
1145 tree element;
1147 for (element = TYPE_VALUES (TREE_TYPE (decl));
1148 element != NULL_TREE;
1149 element = TREE_CHAIN (element))
1151 const char *name;
1152 struct macro_hash_value *mhval;
1153 void **slot;
1154 char buf[WIDE_INT_PRINT_BUFFER_SIZE];
1156 name = IDENTIFIER_POINTER (TREE_PURPOSE (element));
1158 /* Sometimes a name will be defined as both an enum constant
1159 and a macro. Avoid duplicate definition errors by
1160 treating enum constants as macros. */
1161 mhval = XNEW (struct macro_hash_value);
1162 mhval->name = xstrdup (name);
1163 mhval->value = NULL;
1164 slot = htab_find_slot (macro_hash, mhval, INSERT);
1165 if (*slot != NULL)
1166 macro_hash_del (*slot);
1168 if (tree_fits_shwi_p (TREE_VALUE (element)))
1169 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC,
1170 tree_to_shwi (TREE_VALUE (element)));
1171 else if (tree_fits_uhwi_p (TREE_VALUE (element)))
1172 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_UNSIGNED,
1173 tree_to_uhwi (TREE_VALUE (element)));
1174 else
1175 print_hex (element, buf);
1177 mhval->value = xstrdup (buf);
1178 *slot = mhval;
1180 container->decls_seen.add (TREE_TYPE (decl));
1181 if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
1182 container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl)));
1185 if (DECL_NAME (decl) != NULL_TREE)
1187 void **slot;
1188 const char *type;
1190 type = IDENTIFIER_POINTER (DECL_NAME (decl));
1191 /* If type defined already, skip. */
1192 slot = htab_find_slot (container->type_hash, type, INSERT);
1193 if (*slot != NULL)
1194 return;
1195 *slot = CONST_CAST (void *, (const void *) type);
1197 if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL,
1198 false))
1200 fprintf (go_dump_file, "// ");
1201 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1202 *slot = CONST_CAST (void *, (const void *) type);
1204 fprintf (go_dump_file, "type _%s ",
1205 IDENTIFIER_POINTER (DECL_NAME (decl)));
1206 go_output_type (container);
1208 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1210 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
1212 if (size > 0)
1213 fprintf (go_dump_file,
1214 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1215 IDENTIFIER_POINTER (DECL_NAME (decl)),
1216 size);
1219 container->decls_seen.add (decl);
1221 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1223 void **slot;
1224 const char *type;
1225 HOST_WIDE_INT size;
1227 type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
1228 /* If type defined already, skip. */
1229 slot = htab_find_slot (container->type_hash, type, INSERT);
1230 if (*slot != NULL)
1231 return;
1232 *slot = CONST_CAST (void *, (const void *) type);
1234 if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL,
1235 false))
1237 fprintf (go_dump_file, "// ");
1238 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1239 *slot = CONST_CAST (void *, (const void *) type);
1241 fprintf (go_dump_file, "type _%s ",
1242 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
1243 go_output_type (container);
1245 size = int_size_in_bytes (TREE_TYPE (decl));
1246 if (size > 0)
1247 fprintf (go_dump_file,
1248 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1249 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))),
1250 size);
1252 else
1253 return;
1255 fprintf (go_dump_file, "\n");
1258 /* Output a variable. */
1260 static void
1261 go_output_var (struct godump_container *container, tree decl)
1263 bool is_valid;
1264 tree type_name;
1265 tree id;
1267 if (container->decls_seen.contains (decl)
1268 || container->decls_seen.contains (DECL_NAME (decl)))
1269 return;
1270 container->decls_seen.add (decl);
1271 container->decls_seen.add (DECL_NAME (decl));
1273 type_name = TYPE_NAME (TREE_TYPE (decl));
1274 id = NULL_TREE;
1275 if (type_name != NULL_TREE && TREE_CODE (type_name) == IDENTIFIER_NODE)
1276 id = type_name;
1277 else if (type_name != NULL_TREE && TREE_CODE (type_name) == TYPE_DECL
1278 && DECL_SOURCE_LOCATION (type_name) != BUILTINS_LOCATION
1279 && DECL_NAME (type_name))
1280 id = DECL_NAME (type_name);
1281 if (id != NULL_TREE
1282 && (!htab_find_slot (container->type_hash, IDENTIFIER_POINTER (id),
1283 NO_INSERT)
1284 || htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (id),
1285 NO_INSERT)))
1286 id = NULL_TREE;
1287 if (id != NULL_TREE)
1289 struct obstack *ob;
1291 ob = &container->type_obstack;
1292 obstack_1grow (ob, '_');
1293 go_append_string (ob, id);
1294 is_valid = htab_find_slot (container->type_hash, IDENTIFIER_POINTER (id),
1295 NO_INSERT) != NULL;
1297 else
1298 is_valid = go_format_type (container, TREE_TYPE (decl), true, false, NULL,
1299 false);
1300 if (is_valid
1301 && htab_find_slot (container->type_hash,
1302 IDENTIFIER_POINTER (DECL_NAME (decl)),
1303 NO_INSERT) != NULL)
1305 /* There is already a type with this name, probably from a
1306 struct tag. Prefer the type to the variable. */
1307 is_valid = false;
1309 if (!is_valid)
1310 fprintf (go_dump_file, "// ");
1312 fprintf (go_dump_file, "var _%s ",
1313 IDENTIFIER_POINTER (DECL_NAME (decl)));
1314 go_output_type (container);
1315 fprintf (go_dump_file, "\n");
1317 /* Sometimes an extern variable is declared with an unknown struct
1318 type. */
1319 if (type_name != NULL_TREE && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1321 if (TREE_CODE (type_name) == IDENTIFIER_NODE)
1322 container->pot_dummy_types.add (IDENTIFIER_POINTER (type_name));
1323 else if (TREE_CODE (type_name) == TYPE_DECL)
1324 container->pot_dummy_types.add
1325 (IDENTIFIER_POINTER (DECL_NAME (type_name)));
1329 /* Output the final value of a preprocessor macro or enum constant.
1330 This is called via htab_traverse_noresize. */
1332 static int
1333 go_print_macro (void **slot, void *arg ATTRIBUTE_UNUSED)
1335 struct macro_hash_value *mhval = (struct macro_hash_value *) *slot;
1336 fprintf (go_dump_file, "const _%s = %s\n", mhval->name, mhval->value);
1337 return 1;
1340 /* Build a hash table with the Go keywords. */
1342 static const char * const keywords[] = {
1343 "__asm__", "break", "case", "chan", "const", "continue", "default",
1344 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1345 "import", "interface", "map", "package", "range", "return", "select",
1346 "struct", "switch", "type", "var"
1349 static void
1350 keyword_hash_init (struct godump_container *container)
1352 size_t i;
1353 size_t count = sizeof (keywords) / sizeof (keywords[0]);
1354 void **slot;
1356 for (i = 0; i < count; i++)
1358 slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
1359 *slot = CONST_CAST (void *, (const void *) keywords[i]);
1363 /* Traversing the pot_dummy_types and seeing which types are present
1364 in the global types hash table and creating dummy definitions if
1365 not found. This function is invoked by hash_set::traverse. */
1367 bool
1368 find_dummy_types (const char *const &ptr, godump_container *adata)
1370 struct godump_container *data = (struct godump_container *) adata;
1371 const char *type = (const char *) ptr;
1372 void **slot;
1373 void **islot;
1375 slot = htab_find_slot (data->type_hash, type, NO_INSERT);
1376 islot = htab_find_slot (data->invalid_hash, type, NO_INSERT);
1377 if (slot == NULL || islot != NULL)
1378 fprintf (go_dump_file, "type _%s struct {}\n", type);
1379 return true;
1382 /* Output symbols. */
1384 static void
1385 go_finish (const char *filename)
1387 struct godump_container container;
1388 unsigned int ix;
1389 tree decl;
1391 real_debug_hooks->finish (filename);
1393 container.type_hash = htab_create (100, htab_hash_string,
1394 string_hash_eq, NULL);
1395 container.invalid_hash = htab_create (10, htab_hash_string,
1396 string_hash_eq, NULL);
1397 container.keyword_hash = htab_create (50, htab_hash_string,
1398 string_hash_eq, NULL);
1399 obstack_init (&container.type_obstack);
1401 keyword_hash_init (&container);
1403 FOR_EACH_VEC_SAFE_ELT (queue, ix, decl)
1405 switch (TREE_CODE (decl))
1407 case FUNCTION_DECL:
1408 go_output_fndecl (&container, decl);
1409 break;
1411 case TYPE_DECL:
1412 go_output_typedef (&container, decl);
1413 break;
1415 case VAR_DECL:
1416 go_output_var (&container, decl);
1417 break;
1419 default:
1420 gcc_unreachable ();
1424 htab_traverse_noresize (macro_hash, go_print_macro, NULL);
1426 /* To emit dummy definitions. */
1427 container.pot_dummy_types.traverse<godump_container *, find_dummy_types>
1428 (&container);
1430 htab_delete (container.type_hash);
1431 htab_delete (container.invalid_hash);
1432 htab_delete (container.keyword_hash);
1433 obstack_free (&container.type_obstack, NULL);
1435 vec_free (queue);
1437 if (fclose (go_dump_file) != 0)
1438 error ("could not close Go dump file: %m");
1439 go_dump_file = NULL;
1442 /* Set up our hooks. */
1444 const struct gcc_debug_hooks *
1445 dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
1447 go_dump_file = fopen (filename, "w");
1448 if (go_dump_file == NULL)
1450 error ("could not open Go dump file %qs: %m", filename);
1451 return hooks;
1454 go_debug_hooks = *hooks;
1455 real_debug_hooks = hooks;
1457 go_debug_hooks.finish = go_finish;
1458 go_debug_hooks.define = go_define;
1459 go_debug_hooks.undef = go_undef;
1460 go_debug_hooks.function_decl = go_function_decl;
1461 go_debug_hooks.early_global_decl = go_early_global_decl;
1462 go_debug_hooks.late_global_decl = go_late_global_decl;
1463 go_debug_hooks.type_decl = go_type_decl;
1465 macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq,
1466 macro_hash_del);
1468 return &go_debug_hooks;
1471 #include "gt-godump.h"