Fix bootstrap/PR63632
[official-gcc.git] / gcc / godump.c
blob5e4b7fcb0e76977c04b740fce6ca272c638f7d25
1 /* Output Go language descriptions of types.
2 Copyright (C) 2008-2014 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 "tree.h"
35 #include "ggc.h"
36 #include "hash-set.h"
37 #include "obstack.h"
38 #include "debug.h"
39 #include "wide-int-print.h"
41 /* We dump this information from the debug hooks. This gives us a
42 stable and maintainable API to hook into. In order to work
43 correctly when -g is used, we build our own hooks structure which
44 wraps the hooks we need to change. */
46 /* Our debug hooks. This is initialized by dump_go_spec_init. */
48 static struct gcc_debug_hooks go_debug_hooks;
50 /* The real debug hooks. */
52 static const struct gcc_debug_hooks *real_debug_hooks;
54 /* The file where we should write information. */
56 static FILE *go_dump_file;
58 /* A queue of decls to output. */
60 static GTY(()) vec<tree, va_gc> *queue;
62 /* A hash table of macros we have seen. */
64 static htab_t macro_hash;
66 /* The type of a value in macro_hash. */
68 struct macro_hash_value
70 /* The name stored in the hash table. */
71 char *name;
72 /* The value of the macro. */
73 char *value;
76 /* Calculate the hash value for an entry in the macro hash table. */
78 static hashval_t
79 macro_hash_hashval (const void *val)
81 const struct macro_hash_value *mhval = (const struct macro_hash_value *) val;
82 return htab_hash_string (mhval->name);
85 /* Compare values in the macro hash table for equality. */
87 static int
88 macro_hash_eq (const void *v1, const void *v2)
90 const struct macro_hash_value *mhv1 = (const struct macro_hash_value *) v1;
91 const struct macro_hash_value *mhv2 = (const struct macro_hash_value *) v2;
92 return strcmp (mhv1->name, mhv2->name) == 0;
95 /* Free values deleted from the macro hash table. */
97 static void
98 macro_hash_del (void *v)
100 struct macro_hash_value *mhv = (struct macro_hash_value *) v;
101 XDELETEVEC (mhv->name);
102 XDELETEVEC (mhv->value);
103 XDELETE (mhv);
106 /* For the string hash tables. */
108 static int
109 string_hash_eq (const void *y1, const void *y2)
111 return strcmp ((const char *) y1, (const char *) y2) == 0;
114 /* A macro definition. */
116 static void
117 go_define (unsigned int lineno, const char *buffer)
119 const char *p;
120 const char *name_end;
121 size_t out_len;
122 char *out_buffer;
123 char *q;
124 bool saw_operand;
125 bool need_operand;
126 struct macro_hash_value *mhval;
127 char *copy;
128 hashval_t hashval;
129 void **slot;
131 real_debug_hooks->define (lineno, buffer);
133 /* Skip macro functions. */
134 for (p = buffer; *p != '\0' && *p != ' '; ++p)
135 if (*p == '(')
136 return;
138 if (*p == '\0')
139 return;
141 name_end = p;
143 ++p;
144 if (*p == '\0')
145 return;
147 copy = XNEWVEC (char, name_end - buffer + 1);
148 memcpy (copy, buffer, name_end - buffer);
149 copy[name_end - buffer] = '\0';
151 mhval = XNEW (struct macro_hash_value);
152 mhval->name = copy;
153 mhval->value = NULL;
155 hashval = htab_hash_string (copy);
156 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, NO_INSERT);
158 /* For simplicity, we force all names to be hidden by adding an
159 initial underscore, and let the user undo this as needed. */
160 out_len = strlen (p) * 2 + 1;
161 out_buffer = XNEWVEC (char, out_len);
162 q = out_buffer;
163 saw_operand = false;
164 need_operand = false;
165 while (*p != '\0')
167 switch (*p)
169 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
170 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
171 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
172 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
173 case 'Y': case 'Z':
174 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
175 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
176 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
177 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
178 case 'y': case 'z':
179 case '_':
181 /* The start of an identifier. Technically we should also
182 worry about UTF-8 identifiers, but they are not a
183 problem for practical uses of -fdump-go-spec so we
184 don't worry about them. */
185 const char *start;
186 char *n;
187 struct macro_hash_value idval;
189 if (saw_operand)
190 goto unknown;
192 start = p;
193 while (ISALNUM (*p) || *p == '_')
194 ++p;
195 n = XALLOCAVEC (char, p - start + 1);
196 memcpy (n, start, p - start);
197 n[p - start] = '\0';
198 idval.name = n;
199 idval.value = NULL;
200 if (htab_find (macro_hash, &idval) == NULL)
202 /* This is a reference to a name which was not defined
203 as a macro. */
204 goto unknown;
207 *q++ = '_';
208 memcpy (q, start, p - start);
209 q += p - start;
211 saw_operand = true;
212 need_operand = false;
214 break;
216 case '.':
217 if (!ISDIGIT (p[1]))
218 goto unknown;
219 /* Fall through. */
220 case '0': case '1': case '2': case '3': case '4':
221 case '5': case '6': case '7': case '8': case '9':
223 const char *start;
224 bool is_hex;
226 start = p;
227 is_hex = false;
228 if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
230 p += 2;
231 is_hex = true;
233 while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
234 || (is_hex
235 && ((*p >= 'a' && *p <= 'f')
236 || (*p >= 'A' && *p <= 'F'))))
237 ++p;
238 memcpy (q, start, p - start);
239 q += p - start;
240 while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
241 || *p == 'f' || *p == 'F'
242 || *p == 'd' || *p == 'D')
244 /* Go doesn't use any of these trailing type
245 modifiers. */
246 ++p;
249 /* We'll pick up the exponent, if any, as an
250 expression. */
252 saw_operand = true;
253 need_operand = false;
255 break;
257 case ' ': case '\t':
258 *q++ = *p++;
259 break;
261 case '(':
262 /* Always OK, not part of an operand, presumed to start an
263 operand. */
264 *q++ = *p++;
265 saw_operand = false;
266 need_operand = false;
267 break;
269 case ')':
270 /* OK if we don't need an operand, and presumed to indicate
271 an operand. */
272 if (need_operand)
273 goto unknown;
274 *q++ = *p++;
275 saw_operand = true;
276 break;
278 case '+': case '-':
279 /* Always OK, but not part of an operand. */
280 *q++ = *p++;
281 saw_operand = false;
282 break;
284 case '*': case '/': case '%': case '|': case '&': case '^':
285 /* Must be a binary operator. */
286 if (!saw_operand)
287 goto unknown;
288 *q++ = *p++;
289 saw_operand = false;
290 need_operand = true;
291 break;
293 case '=':
294 *q++ = *p++;
295 if (*p != '=')
296 goto unknown;
297 /* Must be a binary operator. */
298 if (!saw_operand)
299 goto unknown;
300 *q++ = *p++;
301 saw_operand = false;
302 need_operand = true;
303 break;
305 case '!':
306 *q++ = *p++;
307 if (*p == '=')
309 /* Must be a binary operator. */
310 if (!saw_operand)
311 goto unknown;
312 *q++ = *p++;
313 saw_operand = false;
314 need_operand = true;
316 else
318 /* Must be a unary operator. */
319 if (saw_operand)
320 goto unknown;
321 need_operand = true;
323 break;
325 case '<': case '>':
326 /* Must be a binary operand, may be << or >> or <= or >=. */
327 if (!saw_operand)
328 goto unknown;
329 *q++ = *p++;
330 if (*p == *(p - 1) || *p == '=')
331 *q++ = *p++;
332 saw_operand = false;
333 need_operand = true;
334 break;
336 case '~':
337 /* Must be a unary operand, must be translated for Go. */
338 if (saw_operand)
339 goto unknown;
340 *q++ = '^';
341 p++;
342 need_operand = true;
343 break;
345 case '"':
346 case '\'':
348 char quote;
349 int count;
351 if (saw_operand)
352 goto unknown;
353 quote = *p;
354 *q++ = *p++;
355 count = 0;
356 while (*p != quote)
358 int c;
360 if (*p == '\0')
361 goto unknown;
363 ++count;
365 if (*p != '\\')
367 *q++ = *p++;
368 continue;
371 *q++ = *p++;
372 switch (*p)
374 case '0': case '1': case '2': case '3':
375 case '4': case '5': case '6': case '7':
376 c = 0;
377 while (*p >= '0' && *p <= '7')
379 *q++ = *p++;
380 ++c;
382 /* Go octal characters are always 3
383 digits. */
384 if (c != 3)
385 goto unknown;
386 break;
388 case 'x':
389 *q++ = *p++;
390 c = 0;
391 while (ISXDIGIT (*p))
393 *q++ = *p++;
394 ++c;
396 /* Go hex characters are always 2 digits. */
397 if (c != 2)
398 goto unknown;
399 break;
401 case 'a': case 'b': case 'f': case 'n': case 'r':
402 case 't': case 'v': case '\\': case '\'': case '"':
403 *q++ = *p++;
404 break;
406 default:
407 goto unknown;
411 *q++ = *p++;
413 if (quote == '\'' && count != 1)
414 goto unknown;
416 saw_operand = true;
417 need_operand = false;
419 break;
422 default:
423 goto unknown;
427 if (need_operand)
428 goto unknown;
430 gcc_assert ((size_t) (q - out_buffer) < out_len);
431 *q = '\0';
433 mhval->value = out_buffer;
435 if (slot == NULL)
437 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, INSERT);
438 gcc_assert (slot != NULL && *slot == NULL);
440 else
442 if (*slot != NULL)
443 macro_hash_del (*slot);
446 *slot = mhval;
448 return;
450 unknown:
451 fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
452 if (slot != NULL)
453 htab_clear_slot (macro_hash, slot);
454 XDELETEVEC (out_buffer);
455 XDELETEVEC (copy);
458 /* A macro undef. */
460 static void
461 go_undef (unsigned int lineno, const char *buffer)
463 struct macro_hash_value mhval;
464 void **slot;
466 real_debug_hooks->undef (lineno, buffer);
468 mhval.name = CONST_CAST (char *, buffer);
469 mhval.value = NULL;
470 slot = htab_find_slot (macro_hash, &mhval, NO_INSERT);
471 if (slot != NULL)
472 htab_clear_slot (macro_hash, slot);
475 /* A function or variable decl. */
477 static void
478 go_decl (tree decl)
480 if (!TREE_PUBLIC (decl)
481 || DECL_IS_BUILTIN (decl)
482 || DECL_NAME (decl) == NULL_TREE)
483 return;
484 vec_safe_push (queue, decl);
487 /* A function decl. */
489 static void
490 go_function_decl (tree decl)
492 real_debug_hooks->function_decl (decl);
493 go_decl (decl);
496 /* A global variable decl. */
498 static void
499 go_global_decl (tree decl)
501 real_debug_hooks->global_decl (decl);
502 go_decl (decl);
505 /* A type declaration. */
507 static void
508 go_type_decl (tree decl, int local)
510 real_debug_hooks->type_decl (decl, local);
512 if (local || DECL_IS_BUILTIN (decl))
513 return;
514 if (DECL_NAME (decl) == NULL_TREE
515 && (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE
516 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) != IDENTIFIER_NODE)
517 && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
518 return;
519 vec_safe_push (queue, decl);
522 /* A container for the data we pass around when generating information
523 at the end of the compilation. */
525 struct godump_container
527 /* DECLs that we have already seen. */
528 hash_set<tree> decls_seen;
530 /* Types which may potentially have to be defined as dummy
531 types. */
532 hash_set<const char *> pot_dummy_types;
534 /* Go keywords. */
535 htab_t keyword_hash;
537 /* Global type definitions. */
538 htab_t type_hash;
540 /* Invalid types. */
541 htab_t invalid_hash;
543 /* Obstack used to write out a type definition. */
544 struct obstack type_obstack;
547 /* Append an IDENTIFIER_NODE to OB. */
549 static void
550 go_append_string (struct obstack *ob, tree id)
552 obstack_grow (ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
555 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
556 USE_TYPE_NAME is true if we can simply use a type name here without
557 needing to define it. IS_FUNC_OK is true if we can output a func
558 type here; the "func" keyword will already have been added. Return
559 true if the type can be represented in Go, false otherwise. */
561 static bool
562 go_format_type (struct godump_container *container, tree type,
563 bool use_type_name, bool is_func_ok)
565 bool ret;
566 struct obstack *ob;
568 ret = true;
569 ob = &container->type_obstack;
571 if (TYPE_NAME (type) != NULL_TREE
572 && (container->decls_seen.contains (type)
573 || container->decls_seen.contains (TYPE_NAME (type)))
574 && (AGGREGATE_TYPE_P (type)
575 || POINTER_TYPE_P (type)
576 || TREE_CODE (type) == FUNCTION_TYPE))
578 tree name;
579 void **slot;
581 name = TYPE_IDENTIFIER (type);
583 slot = htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (name),
584 NO_INSERT);
585 if (slot != NULL)
586 ret = false;
588 obstack_1grow (ob, '_');
589 go_append_string (ob, name);
590 return ret;
593 container->decls_seen.add (type);
595 switch (TREE_CODE (type))
597 case ENUMERAL_TYPE:
598 obstack_grow (ob, "int", 3);
599 break;
601 case TYPE_DECL:
603 void **slot;
605 slot = htab_find_slot (container->invalid_hash,
606 IDENTIFIER_POINTER (DECL_NAME (type)),
607 NO_INSERT);
608 if (slot != NULL)
609 ret = false;
611 obstack_1grow (ob, '_');
612 go_append_string (ob, DECL_NAME (type));
614 break;
616 case INTEGER_TYPE:
618 const char *s;
619 char buf[100];
621 switch (TYPE_PRECISION (type))
623 case 8:
624 s = TYPE_UNSIGNED (type) ? "uint8" : "int8";
625 break;
626 case 16:
627 s = TYPE_UNSIGNED (type) ? "uint16" : "int16";
628 break;
629 case 32:
630 s = TYPE_UNSIGNED (type) ? "uint32" : "int32";
631 break;
632 case 64:
633 s = TYPE_UNSIGNED (type) ? "uint64" : "int64";
634 break;
635 default:
636 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
637 TYPE_PRECISION (type),
638 TYPE_UNSIGNED (type) ? "u" : "");
639 s = buf;
640 ret = false;
641 break;
643 obstack_grow (ob, s, strlen (s));
645 break;
647 case REAL_TYPE:
649 const char *s;
650 char buf[100];
652 switch (TYPE_PRECISION (type))
654 case 32:
655 s = "float32";
656 break;
657 case 64:
658 s = "float64";
659 break;
660 default:
661 snprintf (buf, sizeof buf, "INVALID-float-%u",
662 TYPE_PRECISION (type));
663 s = buf;
664 ret = false;
665 break;
667 obstack_grow (ob, s, strlen (s));
669 break;
671 case BOOLEAN_TYPE:
672 obstack_grow (ob, "bool", 4);
673 break;
675 case POINTER_TYPE:
676 if (use_type_name
677 && TYPE_NAME (TREE_TYPE (type)) != NULL_TREE
678 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))
679 || (POINTER_TYPE_P (TREE_TYPE (type))
680 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type)))
681 == FUNCTION_TYPE))))
683 tree name;
684 void **slot;
686 name = TYPE_IDENTIFIER (TREE_TYPE (type));
688 slot = htab_find_slot (container->invalid_hash,
689 IDENTIFIER_POINTER (name), NO_INSERT);
690 if (slot != NULL)
691 ret = false;
693 obstack_grow (ob, "*_", 2);
694 go_append_string (ob, name);
696 /* The pointer here can be used without the struct or union
697 definition. So this struct or union is a potential dummy
698 type. */
699 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
700 container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
702 return ret;
704 if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
705 obstack_grow (ob, "func", 4);
706 else
707 obstack_1grow (ob, '*');
708 if (VOID_TYPE_P (TREE_TYPE (type)))
709 obstack_grow (ob, "byte", 4);
710 else
712 if (!go_format_type (container, TREE_TYPE (type), use_type_name,
713 true))
714 ret = false;
716 break;
718 case ARRAY_TYPE:
719 obstack_1grow (ob, '[');
720 if (TYPE_DOMAIN (type) != NULL_TREE
721 && TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
722 && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
723 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
724 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0
725 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
726 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
727 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
729 char buf[100];
731 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
732 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type))));
733 obstack_grow (ob, buf, strlen (buf));
735 obstack_1grow (ob, ']');
736 if (!go_format_type (container, TREE_TYPE (type), use_type_name, false))
737 ret = false;
738 break;
740 case UNION_TYPE:
741 case RECORD_TYPE:
743 tree field;
744 int i;
746 obstack_grow (ob, "struct { ", 9);
747 i = 0;
748 for (field = TYPE_FIELDS (type);
749 field != NULL_TREE;
750 field = TREE_CHAIN (field))
752 struct obstack hold_type_obstack;
753 bool field_ok;
755 if (TREE_CODE (type) == UNION_TYPE)
757 hold_type_obstack = container->type_obstack;
758 obstack_init (&container->type_obstack);
761 field_ok = true;
763 if (DECL_NAME (field) == NULL)
765 char buf[100];
767 obstack_grow (ob, "Godump_", 7);
768 snprintf (buf, sizeof buf, "%d", i);
769 obstack_grow (ob, buf, strlen (buf));
770 i++;
772 else
774 const char *var_name;
775 void **slot;
777 /* Start variable name with an underscore if a keyword. */
778 var_name = IDENTIFIER_POINTER (DECL_NAME (field));
779 slot = htab_find_slot (container->keyword_hash, var_name,
780 NO_INSERT);
781 if (slot != NULL)
782 obstack_1grow (ob, '_');
783 go_append_string (ob, DECL_NAME (field));
785 obstack_1grow (ob, ' ');
786 if (DECL_BIT_FIELD (field))
788 obstack_grow (ob, "INVALID-bit-field", 17);
789 field_ok = false;
791 else
793 /* Do not expand type if a record or union type or a
794 function pointer. */
795 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
796 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
797 || (POINTER_TYPE_P (TREE_TYPE (field))
798 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
799 == FUNCTION_TYPE))))
801 tree name;
802 void **slot;
804 name = TYPE_IDENTIFIER (TREE_TYPE (field));
806 slot = htab_find_slot (container->invalid_hash,
807 IDENTIFIER_POINTER (name),
808 NO_INSERT);
809 if (slot != NULL)
810 field_ok = false;
812 obstack_1grow (ob, '_');
813 go_append_string (ob, name);
815 else
817 if (!go_format_type (container, TREE_TYPE (field), true,
818 false))
819 field_ok = false;
822 obstack_grow (ob, "; ", 2);
824 /* Only output the first successful field of a union, and
825 hope for the best. */
826 if (TREE_CODE (type) == UNION_TYPE)
828 if (!field_ok && TREE_CHAIN (field) == NULL_TREE)
830 field_ok = true;
831 ret = false;
833 if (field_ok)
835 unsigned int sz;
837 sz = obstack_object_size (&container->type_obstack);
838 obstack_grow (&hold_type_obstack,
839 obstack_base (&container->type_obstack),
840 sz);
842 obstack_free (&container->type_obstack, NULL);
843 container->type_obstack = hold_type_obstack;
844 if (field_ok)
845 break;
847 else
849 if (!field_ok)
850 ret = false;
853 obstack_1grow (ob, '}');
855 break;
857 case FUNCTION_TYPE:
859 tree arg_type;
860 bool is_varargs;
861 tree result;
862 function_args_iterator iter;
863 bool seen_arg;
865 /* Go has no way to write a type which is a function but not a
866 pointer to a function. */
867 if (!is_func_ok)
869 obstack_grow (ob, "func*", 5);
870 ret = false;
873 obstack_1grow (ob, '(');
874 is_varargs = stdarg_p (type);
875 seen_arg = false;
876 FOREACH_FUNCTION_ARGS (type, arg_type, iter)
878 if (VOID_TYPE_P (arg_type))
879 break;
880 if (seen_arg)
881 obstack_grow (ob, ", ", 2);
882 if (!go_format_type (container, arg_type, true, false))
883 ret = false;
884 seen_arg = true;
886 if (is_varargs)
888 if (prototype_p (type))
889 obstack_grow (ob, ", ", 2);
890 obstack_grow (ob, "...interface{}", 14);
892 obstack_1grow (ob, ')');
894 result = TREE_TYPE (type);
895 if (!VOID_TYPE_P (result))
897 obstack_1grow (ob, ' ');
898 if (!go_format_type (container, result, use_type_name, false))
899 ret = false;
902 break;
904 default:
905 obstack_grow (ob, "INVALID-type", 12);
906 ret = false;
907 break;
910 return ret;
913 /* Output the type which was built on the type obstack, and then free
914 it. */
916 static void
917 go_output_type (struct godump_container *container)
919 struct obstack *ob;
921 ob = &container->type_obstack;
922 obstack_1grow (ob, '\0');
923 fputs ((char *) obstack_base (ob), go_dump_file);
924 obstack_free (ob, obstack_base (ob));
927 /* Output a function declaration. */
929 static void
930 go_output_fndecl (struct godump_container *container, tree decl)
932 if (!go_format_type (container, TREE_TYPE (decl), false, true))
933 fprintf (go_dump_file, "// ");
934 fprintf (go_dump_file, "func _%s ",
935 IDENTIFIER_POINTER (DECL_NAME (decl)));
936 go_output_type (container);
937 fprintf (go_dump_file, " __asm__(\"%s\")\n",
938 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
941 /* Output a typedef or something like a struct definition. */
943 static void
944 go_output_typedef (struct godump_container *container, tree decl)
946 /* If we have an enum type, output the enum constants
947 separately. */
948 if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
949 && TYPE_SIZE (TREE_TYPE (decl)) != 0
950 && !container->decls_seen.contains (TREE_TYPE (decl))
951 && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
952 || !container->decls_seen.contains
953 (TYPE_CANONICAL (TREE_TYPE (decl)))))
955 tree element;
957 for (element = TYPE_VALUES (TREE_TYPE (decl));
958 element != NULL_TREE;
959 element = TREE_CHAIN (element))
961 const char *name;
962 struct macro_hash_value *mhval;
963 void **slot;
964 char buf[WIDE_INT_PRINT_BUFFER_SIZE];
966 name = IDENTIFIER_POINTER (TREE_PURPOSE (element));
968 /* Sometimes a name will be defined as both an enum constant
969 and a macro. Avoid duplicate definition errors by
970 treating enum constants as macros. */
971 mhval = XNEW (struct macro_hash_value);
972 mhval->name = xstrdup (name);
973 mhval->value = NULL;
974 slot = htab_find_slot (macro_hash, mhval, INSERT);
975 if (*slot != NULL)
976 macro_hash_del (*slot);
978 if (tree_fits_shwi_p (TREE_VALUE (element)))
979 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC,
980 tree_to_shwi (TREE_VALUE (element)));
981 else if (tree_fits_uhwi_p (TREE_VALUE (element)))
982 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_UNSIGNED,
983 tree_to_uhwi (TREE_VALUE (element)));
984 else
985 print_hex (element, buf);
987 mhval->value = xstrdup (buf);
988 *slot = mhval;
990 container->decls_seen.add (TREE_TYPE (decl));
991 if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
992 container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl)));
995 if (DECL_NAME (decl) != NULL_TREE)
997 void **slot;
998 const char *type;
1000 type = IDENTIFIER_POINTER (DECL_NAME (decl));
1001 /* If type defined already, skip. */
1002 slot = htab_find_slot (container->type_hash, type, INSERT);
1003 if (*slot != NULL)
1004 return;
1005 *slot = CONST_CAST (void *, (const void *) type);
1007 if (!go_format_type (container, TREE_TYPE (decl), false, false))
1009 fprintf (go_dump_file, "// ");
1010 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1011 *slot = CONST_CAST (void *, (const void *) type);
1013 fprintf (go_dump_file, "type _%s ",
1014 IDENTIFIER_POINTER (DECL_NAME (decl)));
1015 go_output_type (container);
1017 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1019 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
1021 if (size > 0)
1022 fprintf (go_dump_file,
1023 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1024 IDENTIFIER_POINTER (DECL_NAME (decl)),
1025 size);
1028 container->decls_seen.add (decl);
1030 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1032 void **slot;
1033 const char *type;
1034 HOST_WIDE_INT size;
1036 type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
1037 /* If type defined already, skip. */
1038 slot = htab_find_slot (container->type_hash, type, INSERT);
1039 if (*slot != NULL)
1040 return;
1041 *slot = CONST_CAST (void *, (const void *) type);
1043 if (!go_format_type (container, TREE_TYPE (decl), false, false))
1045 fprintf (go_dump_file, "// ");
1046 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1047 *slot = CONST_CAST (void *, (const void *) type);
1049 fprintf (go_dump_file, "type _%s ",
1050 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
1051 go_output_type (container);
1053 size = int_size_in_bytes (TREE_TYPE (decl));
1054 if (size > 0)
1055 fprintf (go_dump_file,
1056 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1057 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))),
1058 size);
1060 else
1061 return;
1063 fprintf (go_dump_file, "\n");
1066 /* Output a variable. */
1068 static void
1069 go_output_var (struct godump_container *container, tree decl)
1071 bool is_valid;
1073 if (container->decls_seen.contains (decl)
1074 || container->decls_seen.contains (DECL_NAME (decl)))
1075 return;
1076 container->decls_seen.add (decl);
1077 container->decls_seen.add (DECL_NAME (decl));
1079 is_valid = go_format_type (container, TREE_TYPE (decl), true, false);
1080 if (is_valid
1081 && htab_find_slot (container->type_hash,
1082 IDENTIFIER_POINTER (DECL_NAME (decl)),
1083 NO_INSERT) != NULL)
1085 /* There is already a type with this name, probably from a
1086 struct tag. Prefer the type to the variable. */
1087 is_valid = false;
1089 if (!is_valid)
1090 fprintf (go_dump_file, "// ");
1092 fprintf (go_dump_file, "var _%s ",
1093 IDENTIFIER_POINTER (DECL_NAME (decl)));
1094 go_output_type (container);
1095 fprintf (go_dump_file, "\n");
1097 /* Sometimes an extern variable is declared with an unknown struct
1098 type. */
1099 if (TYPE_NAME (TREE_TYPE (decl)) != NULL_TREE
1100 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1102 tree type_name = TYPE_NAME (TREE_TYPE (decl));
1103 if (TREE_CODE (type_name) == IDENTIFIER_NODE)
1104 container->pot_dummy_types.add (IDENTIFIER_POINTER (type_name));
1105 else if (TREE_CODE (type_name) == TYPE_DECL)
1106 container->pot_dummy_types.add
1107 (IDENTIFIER_POINTER (DECL_NAME (type_name)));
1111 /* Output the final value of a preprocessor macro or enum constant.
1112 This is called via htab_traverse_noresize. */
1114 static int
1115 go_print_macro (void **slot, void *arg ATTRIBUTE_UNUSED)
1117 struct macro_hash_value *mhval = (struct macro_hash_value *) *slot;
1118 fprintf (go_dump_file, "const _%s = %s\n", mhval->name, mhval->value);
1119 return 1;
1122 /* Build a hash table with the Go keywords. */
1124 static const char * const keywords[] = {
1125 "__asm__", "break", "case", "chan", "const", "continue", "default",
1126 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1127 "import", "interface", "map", "package", "range", "return", "select",
1128 "struct", "switch", "type", "var"
1131 static void
1132 keyword_hash_init (struct godump_container *container)
1134 size_t i;
1135 size_t count = sizeof (keywords) / sizeof (keywords[0]);
1136 void **slot;
1138 for (i = 0; i < count; i++)
1140 slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
1141 *slot = CONST_CAST (void *, (const void *) keywords[i]);
1145 /* Traversing the pot_dummy_types and seeing which types are present
1146 in the global types hash table and creating dummy definitions if
1147 not found. This function is invoked by hash_set::traverse. */
1149 bool
1150 find_dummy_types (const char *const &ptr, godump_container *adata)
1152 struct godump_container *data = (struct godump_container *) adata;
1153 const char *type = (const char *) ptr;
1154 void **slot;
1155 void **islot;
1157 slot = htab_find_slot (data->type_hash, type, NO_INSERT);
1158 islot = htab_find_slot (data->invalid_hash, type, NO_INSERT);
1159 if (slot == NULL || islot != NULL)
1160 fprintf (go_dump_file, "type _%s struct {}\n", type);
1161 return true;
1164 /* Output symbols. */
1166 static void
1167 go_finish (const char *filename)
1169 struct godump_container container;
1170 unsigned int ix;
1171 tree decl;
1173 real_debug_hooks->finish (filename);
1175 container.type_hash = htab_create (100, htab_hash_string,
1176 string_hash_eq, NULL);
1177 container.invalid_hash = htab_create (10, htab_hash_string,
1178 string_hash_eq, NULL);
1179 container.keyword_hash = htab_create (50, htab_hash_string,
1180 string_hash_eq, NULL);
1181 obstack_init (&container.type_obstack);
1183 keyword_hash_init (&container);
1185 FOR_EACH_VEC_SAFE_ELT (queue, ix, decl)
1187 switch (TREE_CODE (decl))
1189 case FUNCTION_DECL:
1190 go_output_fndecl (&container, decl);
1191 break;
1193 case TYPE_DECL:
1194 go_output_typedef (&container, decl);
1195 break;
1197 case VAR_DECL:
1198 go_output_var (&container, decl);
1199 break;
1201 default:
1202 gcc_unreachable ();
1206 htab_traverse_noresize (macro_hash, go_print_macro, NULL);
1208 /* To emit dummy definitions. */
1209 container.pot_dummy_types.traverse<godump_container *, find_dummy_types>
1210 (&container);
1212 htab_delete (container.type_hash);
1213 htab_delete (container.invalid_hash);
1214 htab_delete (container.keyword_hash);
1215 obstack_free (&container.type_obstack, NULL);
1217 vec_free (queue);
1219 if (fclose (go_dump_file) != 0)
1220 error ("could not close Go dump file: %m");
1221 go_dump_file = NULL;
1224 /* Set up our hooks. */
1226 const struct gcc_debug_hooks *
1227 dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
1229 go_dump_file = fopen (filename, "w");
1230 if (go_dump_file == NULL)
1232 error ("could not open Go dump file %qs: %m", filename);
1233 return hooks;
1236 go_debug_hooks = *hooks;
1237 real_debug_hooks = hooks;
1239 go_debug_hooks.finish = go_finish;
1240 go_debug_hooks.define = go_define;
1241 go_debug_hooks.undef = go_undef;
1242 go_debug_hooks.function_decl = go_function_decl;
1243 go_debug_hooks.global_decl = go_global_decl;
1244 go_debug_hooks.type_decl = go_type_decl;
1246 macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq,
1247 macro_hash_del);
1249 return &go_debug_hooks;
1252 #include "gt-godump.h"