2011-05-13 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / gcc / godump.c
blob1ef5e1722921458f367730d05093a4886f5e59ed
1 /* Output Go language descriptions of types.
2 Copyright (C) 2008, 2009, 2010, 2011 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 "pointer-set.h"
37 #include "obstack.h"
38 #include "debug.h"
40 /* We dump this information from the debug hooks. This gives us a
41 stable and maintainable API to hook into. In order to work
42 correctly when -g is used, we build our own hooks structure which
43 wraps the hooks we need to change. */
45 /* Our debug hooks. This is initialized by dump_go_spec_init. */
47 static struct gcc_debug_hooks go_debug_hooks;
49 /* The real debug hooks. */
51 static const struct gcc_debug_hooks *real_debug_hooks;
53 /* The file where we should write information. */
55 static FILE *go_dump_file;
57 /* A queue of decls to output. */
59 static GTY(()) VEC(tree,gc) *queue;
61 /* A hash table of macros we have seen. */
63 static htab_t macro_hash;
65 /* For the hash tables. */
67 static int
68 string_hash_eq (const void *y1, const void *y2)
70 return strcmp ((const char *) y1, (const char *) y2) == 0;
73 /* A macro definition. */
75 static void
76 go_define (unsigned int lineno, const char *buffer)
78 const char *p;
79 const char *name_end;
80 char *out_buffer;
81 char *q;
82 bool saw_operand;
83 bool need_operand;
84 char *copy;
85 hashval_t hashval;
86 void **slot;
88 real_debug_hooks->define (lineno, buffer);
90 /* Skip macro functions. */
91 for (p = buffer; *p != '\0' && *p != ' '; ++p)
92 if (*p == '(')
93 return;
95 if (*p == '\0')
96 return;
98 name_end = p;
100 ++p;
101 if (*p == '\0')
102 return;
104 copy = XNEWVEC (char, name_end - buffer + 1);
105 memcpy (copy, buffer, name_end - buffer);
106 copy[name_end - buffer] = '\0';
108 hashval = htab_hash_string (copy);
109 slot = htab_find_slot_with_hash (macro_hash, copy, hashval, NO_INSERT);
110 if (slot != NULL)
112 XDELETEVEC (copy);
113 return;
116 /* For simplicity, we force all names to be hidden by adding an
117 initial underscore, and let the user undo this as needed. */
118 out_buffer = XNEWVEC (char, strlen (p) * 2 + 1);
119 q = out_buffer;
120 saw_operand = false;
121 need_operand = false;
122 while (*p != '\0')
124 switch (*p)
126 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
127 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
128 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
129 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
130 case 'Y': case 'Z':
131 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
132 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
133 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
134 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
135 case 'y': case 'z':
136 case '_':
138 /* The start of an identifier. Technically we should also
139 worry about UTF-8 identifiers, but they are not a
140 problem for practical uses of -fdump-go-spec so we
141 don't worry about them. */
142 const char *start;
143 char *n;
145 if (saw_operand)
146 goto unknown;
148 start = p;
149 while (ISALNUM (*p) || *p == '_')
150 ++p;
151 n = XALLOCAVEC (char, p - start + 1);
152 memcpy (n, start, p - start);
153 n[p - start] = '\0';
154 slot = htab_find_slot (macro_hash, n, NO_INSERT);
155 if (slot == NULL || *slot == NULL)
157 /* This is a reference to a name which was not defined
158 as a macro. */
159 goto unknown;
162 *q++ = '_';
163 memcpy (q, start, p - start);
164 q += p - start;
166 saw_operand = true;
167 need_operand = false;
169 break;
171 case '.':
172 if (!ISDIGIT (p[1]))
173 goto unknown;
174 /* Fall through. */
175 case '0': case '1': case '2': case '3': case '4':
176 case '5': case '6': case '7': case '8': case '9':
178 const char *start;
179 bool is_hex;
181 start = p;
182 is_hex = false;
183 if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
185 p += 2;
186 is_hex = true;
188 while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
189 || (is_hex
190 && ((*p >= 'a' && *p <= 'f')
191 || (*p >= 'A' && *p <= 'F'))))
192 ++p;
193 memcpy (q, start, p - start);
194 q += p - start;
195 while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
196 || *p == 'f' || *p == 'F'
197 || *p == 'd' || *p == 'D')
199 /* Go doesn't use any of these trailing type
200 modifiers. */
201 ++p;
204 /* We'll pick up the exponent, if any, as an
205 expression. */
207 saw_operand = true;
208 need_operand = false;
210 break;
212 case ' ': case '\t':
213 *q++ = *p++;
214 break;
216 case '(':
217 /* Always OK, not part of an operand, presumed to start an
218 operand. */
219 *q++ = *p++;
220 saw_operand = false;
221 need_operand = false;
222 break;
224 case ')':
225 /* OK if we don't need an operand, and presumed to indicate
226 an operand. */
227 if (need_operand)
228 goto unknown;
229 *q++ = *p++;
230 saw_operand = true;
231 break;
233 case '+': case '-':
234 /* Always OK, but not part of an operand. */
235 *q++ = *p++;
236 saw_operand = false;
237 break;
239 case '*': case '/': case '%': case '|': case '&': case '^':
240 /* Must be a binary operator. */
241 if (!saw_operand)
242 goto unknown;
243 *q++ = *p++;
244 saw_operand = false;
245 need_operand = true;
246 break;
248 case '=':
249 *q++ = *p++;
250 if (*p != '=')
251 goto unknown;
252 /* Must be a binary operator. */
253 if (!saw_operand)
254 goto unknown;
255 *q++ = *p++;
256 saw_operand = false;
257 need_operand = true;
258 break;
260 case '!':
261 *q++ = *p++;
262 if (*p == '=')
264 /* Must be a binary operator. */
265 if (!saw_operand)
266 goto unknown;
267 *q++ = *p++;
268 saw_operand = false;
269 need_operand = true;
271 else
273 /* Must be a unary operator. */
274 if (saw_operand)
275 goto unknown;
276 need_operand = true;
278 break;
280 case '<': case '>':
281 /* Must be a binary operand, may be << or >> or <= or >=. */
282 if (!saw_operand)
283 goto unknown;
284 *q++ = *p++;
285 if (*p == *(p - 1) || *p == '=')
286 *q++ = *p++;
287 saw_operand = false;
288 need_operand = true;
289 break;
291 case '~':
292 /* Must be a unary operand, must be translated for Go. */
293 if (saw_operand)
294 goto unknown;
295 *q++ = '^';
296 p++;
297 need_operand = true;
298 break;
300 case '"':
301 case '\'':
303 char quote = *p;
304 *q++ = *p++;
305 while (*p != quote)
307 int c;
309 if (*p == '\0')
310 goto unknown;
312 if (*p != '\\')
314 *q++ = *p++;
315 continue;
318 *q++ = *p++;
319 switch (*p)
321 case '0': case '1': case '2': case '3':
322 case '4': case '5': case '6': case '7':
323 c = 0;
324 while (*p >= '0' && *p <= '7')
326 *q++ = *p++;
327 ++c;
329 /* Go octal characters are always 3
330 digits. */
331 if (c != 3)
332 goto unknown;
333 break;
335 case 'x':
336 *q++ = *p++;
337 c = 0;
338 while (ISXDIGIT (*p))
340 *q++ = *p++;
341 ++c;
343 /* Go hex characters are always 2 digits. */
344 if (c != 2)
345 goto unknown;
346 break;
348 case 'a': case 'b': case 'f': case 'n': case 'r':
349 case 't': case 'v': case '\\': case '\'': case '"':
350 *q++ = *p++;
351 break;
353 default:
354 goto unknown;
357 *q++ = *p++;
358 break;
361 default:
362 goto unknown;
366 if (need_operand)
367 goto unknown;
369 *q = '\0';
371 slot = htab_find_slot_with_hash (macro_hash, copy, hashval, INSERT);
372 *slot = copy;
374 fprintf (go_dump_file, "const _%s = %s\n", copy, out_buffer);
376 XDELETEVEC (out_buffer);
377 return;
379 unknown:
380 fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
381 XDELETEVEC (out_buffer);
382 XDELETEVEC (copy);
385 /* A macro undef. */
387 static void
388 go_undef (unsigned int lineno, const char *buffer)
390 void **slot;
392 real_debug_hooks->undef (lineno, buffer);
394 slot = htab_find_slot (macro_hash, buffer, NO_INSERT);
395 if (slot == NULL)
396 return;
397 fprintf (go_dump_file, "// undef _%s\n", buffer);
398 /* We don't delete the slot from the hash table because that will
399 cause a duplicate const definition. */
402 /* A function or variable decl. */
404 static void
405 go_decl (tree decl)
407 if (!TREE_PUBLIC (decl)
408 || DECL_IS_BUILTIN (decl)
409 || DECL_NAME (decl) == NULL_TREE)
410 return;
411 VEC_safe_push (tree, gc, queue, decl);
414 /* A function decl. */
416 static void
417 go_function_decl (tree decl)
419 real_debug_hooks->function_decl (decl);
420 go_decl (decl);
423 /* A global variable decl. */
425 static void
426 go_global_decl (tree decl)
428 real_debug_hooks->global_decl (decl);
429 go_decl (decl);
432 /* A type declaration. */
434 static void
435 go_type_decl (tree decl, int local)
437 real_debug_hooks->type_decl (decl, local);
439 if (local || DECL_IS_BUILTIN (decl))
440 return;
441 if (DECL_NAME (decl) == NULL_TREE
442 && (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE
443 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) != IDENTIFIER_NODE)
444 && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
445 return;
446 VEC_safe_push (tree, gc, queue, decl);
449 /* A container for the data we pass around when generating information
450 at the end of the compilation. */
452 struct godump_container
454 /* DECLs that we have already seen. */
455 struct pointer_set_t *decls_seen;
457 /* Types which may potentially have to be defined as dummy
458 types. */
459 struct pointer_set_t *pot_dummy_types;
461 /* Go keywords. */
462 htab_t keyword_hash;
464 /* Global type definitions. */
465 htab_t type_hash;
467 /* Obstack used to write out a type definition. */
468 struct obstack type_obstack;
471 /* Append an IDENTIFIER_NODE to OB. */
473 static void
474 go_append_string (struct obstack *ob, tree id)
476 obstack_grow (ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
479 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
480 USE_TYPE_NAME is true if we can simply use a type name here without
481 needing to define it. IS_FUNC_OK is true if we can output a func
482 type here; the "func" keyword will already have been added. Return
483 true if the type can be represented in Go, false otherwise. */
485 static bool
486 go_format_type (struct godump_container *container, tree type,
487 bool use_type_name, bool is_func_ok)
489 bool ret;
490 struct obstack *ob;
492 ret = true;
493 ob = &container->type_obstack;
495 if (TYPE_NAME (type) != NULL_TREE
496 && (pointer_set_contains (container->decls_seen, type)
497 || pointer_set_contains (container->decls_seen, TYPE_NAME (type)))
498 && (AGGREGATE_TYPE_P (type)
499 || POINTER_TYPE_P (type)
500 || TREE_CODE (type) == FUNCTION_TYPE))
502 tree name;
504 name = TYPE_NAME (type);
505 if (TREE_CODE (name) == IDENTIFIER_NODE)
507 obstack_1grow (ob, '_');
508 go_append_string (ob, name);
509 return ret;
511 else if (TREE_CODE (name) == TYPE_DECL)
513 obstack_1grow (ob, '_');
514 go_append_string (ob, DECL_NAME (name));
515 return ret;
519 pointer_set_insert (container->decls_seen, type);
521 switch (TREE_CODE (type))
523 case ENUMERAL_TYPE:
524 obstack_grow (ob, "int", 3);
525 break;
527 case TYPE_DECL:
528 obstack_1grow (ob, '_');
529 go_append_string (ob, DECL_NAME (type));
530 break;
532 case INTEGER_TYPE:
534 const char *s;
535 char buf[100];
537 switch (TYPE_PRECISION (type))
539 case 8:
540 s = TYPE_UNSIGNED (type) ? "uint8" : "int8";
541 break;
542 case 16:
543 s = TYPE_UNSIGNED (type) ? "uint16" : "int16";
544 break;
545 case 32:
546 s = TYPE_UNSIGNED (type) ? "uint32" : "int32";
547 break;
548 case 64:
549 s = TYPE_UNSIGNED (type) ? "uint64" : "int64";
550 break;
551 default:
552 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
553 TYPE_PRECISION (type),
554 TYPE_UNSIGNED (type) ? "u" : "");
555 s = buf;
556 ret = false;
557 break;
559 obstack_grow (ob, s, strlen (s));
561 break;
563 case REAL_TYPE:
565 const char *s;
566 char buf[100];
568 switch (TYPE_PRECISION (type))
570 case 32:
571 s = "float32";
572 break;
573 case 64:
574 s = "float64";
575 break;
576 default:
577 snprintf (buf, sizeof buf, "INVALID-float-%u",
578 TYPE_PRECISION (type));
579 s = buf;
580 ret = false;
581 break;
583 obstack_grow (ob, s, strlen (s));
585 break;
587 case BOOLEAN_TYPE:
588 obstack_grow (ob, "bool", 4);
589 break;
591 case POINTER_TYPE:
592 if (use_type_name
593 && TYPE_NAME (TREE_TYPE (type)) != NULL_TREE
594 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))
595 || (POINTER_TYPE_P (TREE_TYPE (type))
596 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type)))
597 == FUNCTION_TYPE))))
599 tree name;
601 name = TYPE_NAME (TREE_TYPE (type));
602 if (TREE_CODE (name) == IDENTIFIER_NODE)
604 obstack_grow (ob, "*_", 2);
605 go_append_string (ob, name);
607 /* The pointer here can be used without the struct or
608 union definition. So this struct or union is a a
609 potential dummy type. */
610 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
611 pointer_set_insert (container->pot_dummy_types,
612 IDENTIFIER_POINTER (name));
614 return ret;
616 else if (TREE_CODE (name) == TYPE_DECL)
618 obstack_grow (ob, "*_", 2);
619 go_append_string (ob, DECL_NAME (name));
620 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
621 pointer_set_insert (container->pot_dummy_types,
622 IDENTIFIER_POINTER (DECL_NAME (name)));
623 return ret;
626 if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
627 obstack_grow (ob, "func", 4);
628 else
629 obstack_1grow (ob, '*');
630 if (VOID_TYPE_P (TREE_TYPE (type)))
631 obstack_grow (ob, "byte", 4);
632 else
634 if (!go_format_type (container, TREE_TYPE (type), use_type_name,
635 true))
636 ret = false;
638 break;
640 case ARRAY_TYPE:
641 obstack_1grow (ob, '[');
642 if (TYPE_DOMAIN (type) != NULL_TREE
643 && TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
644 && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
645 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
646 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0
647 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
648 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
649 && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0))
651 char buf[100];
653 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
654 tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0));
655 obstack_grow (ob, buf, strlen (buf));
657 obstack_1grow (ob, ']');
658 if (!go_format_type (container, TREE_TYPE (type), use_type_name, false))
659 ret = false;
660 break;
662 case UNION_TYPE:
663 case RECORD_TYPE:
665 tree field;
666 int i;
668 obstack_grow (ob, "struct { ", 9);
669 i = 0;
670 for (field = TYPE_FIELDS (type);
671 field != NULL_TREE;
672 field = TREE_CHAIN (field))
674 if (DECL_NAME (field) == NULL)
676 char buf[100];
678 obstack_grow (ob, "Godump_", 2);
679 snprintf (buf, sizeof buf, "%d", i);
680 obstack_grow (ob, buf, strlen (buf));
681 i++;
683 else
685 const char *var_name;
686 void **slot;
688 /* Start variable name with an underscore if a keyword. */
689 var_name = IDENTIFIER_POINTER (DECL_NAME (field));
690 slot = htab_find_slot (container->keyword_hash, var_name,
691 NO_INSERT);
692 if (slot != NULL)
693 obstack_1grow (ob, '_');
694 go_append_string (ob, DECL_NAME (field));
696 obstack_1grow (ob, ' ');
697 if (DECL_BIT_FIELD (field))
699 obstack_grow (ob, "INVALID-bit-field", 17);
700 ret = false;
702 else
704 /* Do not expand type if a record or union type or a
705 function pointer. */
706 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
707 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
708 || (POINTER_TYPE_P (TREE_TYPE (field))
709 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
710 == FUNCTION_TYPE))))
712 tree name = TYPE_NAME (TREE_TYPE (field));
713 if (TREE_CODE (name) == IDENTIFIER_NODE)
715 obstack_1grow (ob, '_');
716 go_append_string (ob, name);
718 else if (TREE_CODE (name) == TYPE_DECL)
720 obstack_1grow (ob, '_');
721 go_append_string (ob, DECL_NAME (name));
724 else
726 if (!go_format_type (container, TREE_TYPE (field), true,
727 false))
728 ret = false;
731 obstack_grow (ob, "; ", 2);
733 /* Only output the first field of a union, and hope for
734 the best. */
735 if (TREE_CODE (type) == UNION_TYPE)
736 break;
738 obstack_1grow (ob, '}');
740 break;
742 case FUNCTION_TYPE:
744 tree arg_type;
745 bool is_varargs;
746 tree result;
747 function_args_iterator iter;
748 bool seen_arg;
750 /* Go has no way to write a type which is a function but not a
751 pointer to a function. */
752 if (!is_func_ok)
754 obstack_grow (ob, "func*", 5);
755 ret = false;
758 obstack_1grow (ob, '(');
759 is_varargs = stdarg_p (type);
760 seen_arg = false;
761 FOREACH_FUNCTION_ARGS (type, arg_type, iter)
763 if (VOID_TYPE_P (arg_type))
764 break;
765 if (seen_arg)
766 obstack_grow (ob, ", ", 2);
767 if (!go_format_type (container, arg_type, true, false))
768 ret = false;
769 seen_arg = true;
771 if (is_varargs)
773 if (prototype_p (type))
774 obstack_grow (ob, ", ", 2);
775 obstack_grow (ob, "...interface{}", 14);
777 obstack_1grow (ob, ')');
779 result = TREE_TYPE (type);
780 if (!VOID_TYPE_P (result))
782 obstack_1grow (ob, ' ');
783 if (!go_format_type (container, result, use_type_name, false))
784 ret = false;
787 break;
789 default:
790 obstack_grow (ob, "INVALID-type", 12);
791 ret = false;
792 break;
795 return ret;
798 /* Output the type which was built on the type obstack, and then free
799 it. */
801 static void
802 go_output_type (struct godump_container *container)
804 struct obstack *ob;
806 ob = &container->type_obstack;
807 obstack_1grow (ob, '\0');
808 fputs (obstack_base (ob), go_dump_file);
809 obstack_free (ob, obstack_base (ob));
812 /* Output a function declaration. */
814 static void
815 go_output_fndecl (struct godump_container *container, tree decl)
817 if (!go_format_type (container, TREE_TYPE (decl), false, true))
818 fprintf (go_dump_file, "// ");
819 fprintf (go_dump_file, "func _%s ",
820 IDENTIFIER_POINTER (DECL_NAME (decl)));
821 go_output_type (container);
822 fprintf (go_dump_file, " __asm__(\"%s\")\n",
823 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
826 /* Output a typedef or something like a struct definition. */
828 static void
829 go_output_typedef (struct godump_container *container, tree decl)
831 /* If we have an enum type, output the enum constants
832 separately. */
833 if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
834 && TYPE_SIZE (TREE_TYPE (decl)) != 0
835 && !pointer_set_contains (container->decls_seen, TREE_TYPE (decl))
836 && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
837 || !pointer_set_contains (container->decls_seen,
838 TYPE_CANONICAL (TREE_TYPE (decl)))))
840 tree element;
842 for (element = TYPE_VALUES (TREE_TYPE (decl));
843 element != NULL_TREE;
844 element = TREE_CHAIN (element))
846 const char *name;
847 void **slot;
849 name = IDENTIFIER_POINTER (TREE_PURPOSE (element));
851 /* Sometimes a name will be defined as both an enum constant
852 and a macro. Avoid duplicate definition errors by
853 treating enum constants as macros. */
854 slot = htab_find_slot (macro_hash, name, INSERT);
855 if (*slot == NULL)
857 *slot = CONST_CAST (char *, name);
858 fprintf (go_dump_file,
859 "const _%s = " HOST_WIDE_INT_PRINT_DEC "\n",
860 name, tree_low_cst (TREE_VALUE (element), 0));
863 pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
864 if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
865 pointer_set_insert (container->decls_seen,
866 TYPE_CANONICAL (TREE_TYPE (decl)));
869 if (DECL_NAME (decl) != NULL_TREE)
871 void **slot;
872 const char *type;
874 type = IDENTIFIER_POINTER (DECL_NAME (decl));
875 /* If type defined already, skip. */
876 slot = htab_find_slot (container->type_hash, type, INSERT);
877 if (*slot != NULL)
878 return;
879 *slot = CONST_CAST (void *, (const void *) type);
881 if (!go_format_type (container, TREE_TYPE (decl), false, false))
882 fprintf (go_dump_file, "// ");
883 fprintf (go_dump_file, "type _%s ",
884 IDENTIFIER_POINTER (DECL_NAME (decl)));
885 go_output_type (container);
886 pointer_set_insert (container->decls_seen, decl);
888 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
890 void **slot;
891 const char *type;
893 type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
894 /* If type defined already, skip. */
895 slot = htab_find_slot (container->type_hash, type, INSERT);
896 if (*slot != NULL)
897 return;
898 *slot = CONST_CAST (void *, (const void *) type);
900 if (!go_format_type (container, TREE_TYPE (decl), false, false))
901 fprintf (go_dump_file, "// ");
902 fprintf (go_dump_file, "type _%s ",
903 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
904 go_output_type (container);
906 else
907 return;
909 fprintf (go_dump_file, "\n");
912 /* Output a variable. */
914 static void
915 go_output_var (struct godump_container *container, tree decl)
917 bool is_valid;
919 if (pointer_set_contains (container->decls_seen, decl)
920 || pointer_set_contains (container->decls_seen, DECL_NAME (decl)))
921 return;
922 pointer_set_insert (container->decls_seen, decl);
923 pointer_set_insert (container->decls_seen, DECL_NAME (decl));
925 is_valid = go_format_type (container, TREE_TYPE (decl), true, false);
926 if (is_valid
927 && htab_find_slot (container->type_hash,
928 IDENTIFIER_POINTER (DECL_NAME (decl)),
929 NO_INSERT) != NULL)
931 /* There is already a type with this name, probably from a
932 struct tag. Prefer the type to the variable. */
933 is_valid = false;
935 if (!is_valid)
936 fprintf (go_dump_file, "// ");
938 fprintf (go_dump_file, "var _%s ",
939 IDENTIFIER_POINTER (DECL_NAME (decl)));
940 go_output_type (container);
941 fprintf (go_dump_file, "\n");
943 /* Sometimes an extern variable is declared with an unknown struct
944 type. */
945 if (TYPE_NAME (TREE_TYPE (decl)) != NULL_TREE
946 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
948 tree type_name = TYPE_NAME (TREE_TYPE (decl));
949 if (TREE_CODE (type_name) == IDENTIFIER_NODE)
950 pointer_set_insert (container->pot_dummy_types,
951 IDENTIFIER_POINTER (type_name));
952 else if (TREE_CODE (type_name) == TYPE_DECL)
953 pointer_set_insert (container->pot_dummy_types,
954 IDENTIFIER_POINTER (DECL_NAME (type_name)));
958 /* Build a hash table with the Go keywords. */
960 static const char * const keywords[] = {
961 "__asm__", "break", "case", "chan", "const", "continue", "default",
962 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
963 "import", "interface", "map", "package", "range", "return", "select",
964 "struct", "switch", "type", "var"
967 static void
968 keyword_hash_init (struct godump_container *container)
970 size_t i;
971 size_t count = sizeof (keywords) / sizeof (keywords[0]);
972 void **slot;
974 for (i = 0; i < count; i++)
976 slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
977 *slot = CONST_CAST (void *, (const void *) keywords[i]);
981 /* Traversing the pot_dummy_types and seeing which types are present
982 in the global types hash table and creating dummy definitions if
983 not found. This function is invoked by pointer_set_traverse. */
985 static bool
986 find_dummy_types (const void *ptr, void *adata)
988 struct godump_container *data = (struct godump_container *) adata;
989 const char *type = (const char *) ptr;
990 void **slot;
992 slot = htab_find_slot (data->type_hash, type, NO_INSERT);
993 if (slot == NULL)
994 fprintf (go_dump_file, "type _%s struct {}\n", type);
995 return true;
998 /* Output symbols. */
1000 static void
1001 go_finish (const char *filename)
1003 struct godump_container container;
1004 unsigned int ix;
1005 tree decl;
1007 real_debug_hooks->finish (filename);
1009 container.decls_seen = pointer_set_create ();
1010 container.pot_dummy_types = pointer_set_create ();
1011 container.type_hash = htab_create (100, htab_hash_string,
1012 string_hash_eq, NULL);
1013 container.keyword_hash = htab_create (50, htab_hash_string,
1014 string_hash_eq, NULL);
1015 obstack_init (&container.type_obstack);
1017 keyword_hash_init (&container);
1019 FOR_EACH_VEC_ELT (tree, queue, ix, decl)
1021 switch (TREE_CODE (decl))
1023 case FUNCTION_DECL:
1024 go_output_fndecl (&container, decl);
1025 break;
1027 case TYPE_DECL:
1028 go_output_typedef (&container, decl);
1029 break;
1031 case VAR_DECL:
1032 go_output_var (&container, decl);
1033 break;
1035 default:
1036 gcc_unreachable();
1040 /* To emit dummy definitions. */
1041 pointer_set_traverse (container.pot_dummy_types, find_dummy_types,
1042 (void *) &container);
1044 pointer_set_destroy (container.decls_seen);
1045 pointer_set_destroy (container.pot_dummy_types);
1046 htab_delete (container.type_hash);
1047 htab_delete (container.keyword_hash);
1048 obstack_free (&container.type_obstack, NULL);
1050 queue = NULL;
1052 if (fclose (go_dump_file) != 0)
1053 error ("could not close Go dump file: %m");
1054 go_dump_file = NULL;
1057 /* Set up our hooks. */
1059 const struct gcc_debug_hooks *
1060 dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
1062 go_dump_file = fopen (filename, "w");
1063 if (go_dump_file == NULL)
1065 error ("could not open Go dump file %qs: %m", filename);
1066 return hooks;
1069 go_debug_hooks = *hooks;
1070 real_debug_hooks = hooks;
1072 go_debug_hooks.finish = go_finish;
1073 go_debug_hooks.define = go_define;
1074 go_debug_hooks.undef = go_undef;
1075 go_debug_hooks.function_decl = go_function_decl;
1076 go_debug_hooks.global_decl = go_global_decl;
1077 go_debug_hooks.type_decl = go_type_decl;
1079 macro_hash = htab_create (100, htab_hash_string, string_hash_eq, NULL);
1081 return &go_debug_hooks;
1084 #include "gt-godump.h"