Merge from mainline (165734:167278).
[official-gcc/graphite-test-results.git] / gcc / godump.c
blob662aa92284a62ff2117c50b63bb72a861adae793
1 /* Output Go language descriptions of types.
2 Copyright (C) 2008, 2009, 2010 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 char *copy;
83 hashval_t hashval;
84 void **slot;
86 real_debug_hooks->define (lineno, buffer);
88 /* Skip macro functions. */
89 for (p = buffer; *p != '\0' && *p != ' '; ++p)
90 if (*p == '(')
91 return;
93 if (*p == '\0')
94 return;
96 name_end = p;
98 ++p;
99 if (*p == '\0')
100 return;
102 copy = XNEWVEC (char, name_end - buffer + 1);
103 memcpy (copy, buffer, name_end - buffer);
104 copy[name_end - buffer] = '\0';
106 hashval = htab_hash_string (copy);
107 slot = htab_find_slot_with_hash (macro_hash, copy, hashval, NO_INSERT);
108 if (slot != NULL)
110 XDELETEVEC (copy);
111 return;
114 /* For simplicity, we force all names to be hidden by adding an
115 initial underscore, and let the user undo this as needed. */
116 out_buffer = XNEWVEC (char, strlen (p) * 2 + 1);
117 q = out_buffer;
118 while (*p != '\0')
120 if (ISALPHA (*p) || *p == '_')
122 const char *start;
123 char *n;
125 start = p;
126 while (ISALNUM (*p) || *p == '_')
127 ++p;
128 n = XALLOCAVEC (char, p - start + 1);
129 memcpy (n, start, p - start);
130 n[p - start] = '\0';
131 slot = htab_find_slot (macro_hash, n, NO_INSERT);
132 if (slot == NULL || *slot == NULL)
134 /* This is a reference to a name which was not defined
135 as a macro. */
136 fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
137 return;
140 *q++ = '_';
141 memcpy (q, start, p - start);
142 q += p - start;
144 else if (ISDIGIT (*p)
145 || (*p == '.' && ISDIGIT (p[1])))
147 const char *start;
148 bool is_hex;
150 start = p;
151 is_hex = false;
152 if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
154 p += 2;
155 is_hex = true;
157 while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
158 || (is_hex
159 && ((*p >= 'a' && *p <= 'f')
160 || (*p >= 'A' && *p <= 'F'))))
161 ++p;
162 memcpy (q, start, p - start);
163 q += p - start;
164 while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
165 || *p == 'f' || *p == 'F'
166 || *p == 'd' || *p == 'D')
168 /* Go doesn't use any of these trailing type
169 modifiers. */
170 ++p;
173 else if (ISSPACE (*p)
174 || *p == '+' || *p == '-'
175 || *p == '*' || *p == '/' || *p == '%'
176 || *p == '|' || *p == '&'
177 || *p == '>' || *p == '<'
178 || *p == '!'
179 || *p == '(' || *p == ')'
180 || *p == '"' || *p == '\'')
181 *q++ = *p++;
182 else
184 /* Something we don't recognize. */
185 fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
186 return;
189 *q = '\0';
191 slot = htab_find_slot_with_hash (macro_hash, copy, hashval, INSERT);
192 *slot = copy;
194 fprintf (go_dump_file, "const _%s = %s\n", copy, out_buffer);
196 XDELETEVEC (out_buffer);
199 /* A macro undef. */
201 static void
202 go_undef (unsigned int lineno, const char *buffer)
204 void **slot;
206 real_debug_hooks->undef (lineno, buffer);
208 slot = htab_find_slot (macro_hash, buffer, NO_INSERT);
209 if (slot == NULL)
210 return;
211 fprintf (go_dump_file, "// undef _%s\n", buffer);
212 /* We don't delete the slot from the hash table because that will
213 cause a duplicate const definition. */
216 /* A function or variable decl. */
218 static void
219 go_decl (tree decl)
221 if (!TREE_PUBLIC (decl)
222 || DECL_IS_BUILTIN (decl)
223 || DECL_NAME (decl) == NULL_TREE)
224 return;
225 VEC_safe_push (tree, gc, queue, decl);
228 /* A function decl. */
230 static void
231 go_function_decl (tree decl)
233 real_debug_hooks->function_decl (decl);
234 go_decl (decl);
237 /* A global variable decl. */
239 static void
240 go_global_decl (tree decl)
242 real_debug_hooks->global_decl (decl);
243 go_decl (decl);
246 /* A type declaration. */
248 static void
249 go_type_decl (tree decl, int local)
251 real_debug_hooks->type_decl (decl, local);
253 if (local || DECL_IS_BUILTIN (decl))
254 return;
255 if (DECL_NAME (decl) == NULL_TREE
256 && (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE
257 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) != IDENTIFIER_NODE)
258 && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
259 return;
260 VEC_safe_push (tree, gc, queue, decl);
263 /* A container for the data we pass around when generating information
264 at the end of the compilation. */
266 struct godump_container
268 /* DECLs that we have already seen. */
269 struct pointer_set_t *decls_seen;
271 /* Types which may potentially have to be defined as dummy
272 types. */
273 struct pointer_set_t *pot_dummy_types;
275 /* Go keywords. */
276 htab_t keyword_hash;
278 /* Global type definitions. */
279 htab_t type_hash;
281 /* Obstack used to write out a type definition. */
282 struct obstack type_obstack;
285 /* Append an IDENTIFIER_NODE to OB. */
287 static void
288 go_append_string (struct obstack *ob, tree id)
290 obstack_grow (ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
293 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
294 USE_TYPE_NAME is true if we can simply use a type name here without
295 needing to define it. IS_FUNC_OK is true if we can output a func
296 type here; the "func" keyword will already have been added. Return
297 true if the type can be represented in Go, false otherwise. */
299 static bool
300 go_format_type (struct godump_container *container, tree type,
301 bool use_type_name, bool is_func_ok)
303 bool ret;
304 struct obstack *ob;
306 ret = true;
307 ob = &container->type_obstack;
309 if (TYPE_NAME (type) != NULL_TREE
310 && (pointer_set_contains (container->decls_seen, type)
311 || pointer_set_contains (container->decls_seen, TYPE_NAME (type)))
312 && (AGGREGATE_TYPE_P (type)
313 || POINTER_TYPE_P (type)
314 || TREE_CODE (type) == FUNCTION_TYPE))
316 tree name;
318 name = TYPE_NAME (type);
319 if (TREE_CODE (name) == IDENTIFIER_NODE)
321 obstack_1grow (ob, '_');
322 go_append_string (ob, name);
323 return ret;
325 else if (TREE_CODE (name) == TYPE_DECL)
327 obstack_1grow (ob, '_');
328 go_append_string (ob, DECL_NAME (name));
329 return ret;
333 pointer_set_insert (container->decls_seen, type);
335 switch (TREE_CODE (type))
337 case ENUMERAL_TYPE:
338 obstack_grow (ob, "int", 3);
339 break;
341 case TYPE_DECL:
342 obstack_1grow (ob, '_');
343 go_append_string (ob, DECL_NAME (type));
344 break;
346 case INTEGER_TYPE:
348 const char *s;
349 char buf[100];
351 switch (TYPE_PRECISION (type))
353 case 8:
354 s = TYPE_UNSIGNED (type) ? "uint8" : "int8";
355 break;
356 case 16:
357 s = TYPE_UNSIGNED (type) ? "uint16" : "int16";
358 break;
359 case 32:
360 s = TYPE_UNSIGNED (type) ? "uint32" : "int32";
361 break;
362 case 64:
363 s = TYPE_UNSIGNED (type) ? "uint64" : "int64";
364 break;
365 default:
366 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
367 TYPE_PRECISION (type),
368 TYPE_UNSIGNED (type) ? "u" : "");
369 s = buf;
370 ret = false;
371 break;
373 obstack_grow (ob, s, strlen (s));
375 break;
377 case REAL_TYPE:
379 const char *s;
380 char buf[100];
382 switch (TYPE_PRECISION (type))
384 case 32:
385 s = "float32";
386 break;
387 case 64:
388 s = "float64";
389 break;
390 case 80:
391 s = "float80";
392 break;
393 default:
394 snprintf (buf, sizeof buf, "INVALID-float-%u",
395 TYPE_PRECISION (type));
396 s = buf;
397 ret = false;
398 break;
400 obstack_grow (ob, s, strlen (s));
402 break;
404 case BOOLEAN_TYPE:
405 obstack_grow (ob, "bool", 4);
406 break;
408 case POINTER_TYPE:
409 if (use_type_name
410 && TYPE_NAME (TREE_TYPE (type)) != NULL_TREE
411 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))
412 || (POINTER_TYPE_P (TREE_TYPE (type))
413 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type)))
414 == FUNCTION_TYPE))))
416 tree name;
418 name = TYPE_NAME (TREE_TYPE (type));
419 if (TREE_CODE (name) == IDENTIFIER_NODE)
421 obstack_grow (ob, "*_", 2);
422 go_append_string (ob, name);
424 /* The pointer here can be used without the struct or
425 union definition. So this struct or union is a a
426 potential dummy type. */
427 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
428 pointer_set_insert (container->pot_dummy_types,
429 IDENTIFIER_POINTER (name));
431 return ret;
433 else if (TREE_CODE (name) == TYPE_DECL)
435 obstack_grow (ob, "*_", 2);
436 go_append_string (ob, DECL_NAME (name));
437 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
438 pointer_set_insert (container->pot_dummy_types,
439 IDENTIFIER_POINTER (DECL_NAME (name)));
440 return ret;
443 if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
444 obstack_grow (ob, "func", 4);
445 else
446 obstack_1grow (ob, '*');
447 if (VOID_TYPE_P (TREE_TYPE (type)))
448 obstack_grow (ob, "byte", 4);
449 else
451 if (!go_format_type (container, TREE_TYPE (type), use_type_name,
452 true))
453 ret = false;
455 break;
457 case ARRAY_TYPE:
458 obstack_1grow (ob, '[');
459 if (TYPE_DOMAIN (type) != NULL_TREE
460 && TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
461 && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
462 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
463 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0
464 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
465 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
466 && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0))
468 char buf[100];
470 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
471 tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0));
472 obstack_grow (ob, buf, strlen (buf));
474 obstack_1grow (ob, ']');
475 if (!go_format_type (container, TREE_TYPE (type), use_type_name, false))
476 ret = false;
477 break;
479 case UNION_TYPE:
480 case RECORD_TYPE:
482 tree field;
483 int i;
485 obstack_grow (ob, "struct { ", 9);
486 i = 0;
487 for (field = TYPE_FIELDS (type);
488 field != NULL_TREE;
489 field = TREE_CHAIN (field))
491 if (DECL_NAME (field) == NULL)
493 char buf[100];
495 obstack_grow (ob, "_f", 2);
496 snprintf (buf, sizeof buf, "%d", i);
497 obstack_grow (ob, buf, strlen (buf));
498 i++;
500 else
502 const char *var_name;
503 void **slot;
505 /* Start variable name with an underscore if a keyword. */
506 var_name = IDENTIFIER_POINTER (DECL_NAME (field));
507 slot = htab_find_slot (container->keyword_hash, var_name,
508 NO_INSERT);
509 if (slot != NULL)
510 obstack_1grow (ob, '_');
511 go_append_string (ob, DECL_NAME (field));
513 obstack_1grow (ob, ' ');
514 if (DECL_BIT_FIELD (field))
516 obstack_grow (ob, "INVALID-bit-field", 17);
517 ret = false;
519 else
521 /* Do not expand type if a record or union type or a
522 function pointer. */
523 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
524 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
525 || (POINTER_TYPE_P (TREE_TYPE (field))
526 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
527 == FUNCTION_TYPE))))
529 tree name = TYPE_NAME (TREE_TYPE (field));
530 if (TREE_CODE (name) == IDENTIFIER_NODE)
532 obstack_1grow (ob, '_');
533 go_append_string (ob, name);
535 else if (TREE_CODE (name) == TYPE_DECL)
537 obstack_1grow (ob, '_');
538 go_append_string (ob, DECL_NAME (name));
541 else
543 if (!go_format_type (container, TREE_TYPE (field), true,
544 false))
545 ret = false;
548 obstack_grow (ob, "; ", 2);
550 /* Only output the first field of a union, and hope for
551 the best. */
552 if (TREE_CODE (type) == UNION_TYPE)
553 break;
555 obstack_1grow (ob, '}');
557 break;
559 case FUNCTION_TYPE:
561 tree args;
562 bool is_varargs;
563 tree result;
565 /* Go has no way to write a type which is a function but not a
566 pointer to a function. */
567 if (!is_func_ok)
569 obstack_grow (ob, "func*", 5);
570 ret = false;
573 obstack_1grow (ob, '(');
574 is_varargs = true;
575 for (args = TYPE_ARG_TYPES (type);
576 args != NULL_TREE;
577 args = TREE_CHAIN (args))
579 if (VOID_TYPE_P (TREE_VALUE (args)))
581 gcc_assert (TREE_CHAIN (args) == NULL);
582 is_varargs = false;
583 break;
585 if (args != TYPE_ARG_TYPES (type))
586 obstack_grow (ob, ", ", 2);
587 if (!go_format_type (container, TREE_VALUE (args), true, false))
588 ret = false;
590 if (is_varargs)
592 if (TYPE_ARG_TYPES (type) != NULL_TREE)
593 obstack_grow (ob, ", ", 2);
594 obstack_grow (ob, "...interface{}", 14);
596 obstack_1grow (ob, ')');
598 result = TREE_TYPE (type);
599 if (!VOID_TYPE_P (result))
601 obstack_1grow (ob, ' ');
602 if (!go_format_type (container, result, use_type_name, false))
603 ret = false;
606 break;
608 default:
609 obstack_grow (ob, "INVALID-type", 12);
610 ret = false;
611 break;
614 return ret;
617 /* Output the type which was built on the type obstack, and then free
618 it. */
620 static void
621 go_output_type (struct godump_container *container)
623 struct obstack *ob;
625 ob = &container->type_obstack;
626 obstack_1grow (ob, '\0');
627 fputs (obstack_base (ob), go_dump_file);
628 obstack_free (ob, obstack_base (ob));
631 /* Output a function declaration. */
633 static void
634 go_output_fndecl (struct godump_container *container, tree decl)
636 if (!go_format_type (container, TREE_TYPE (decl), false, true))
637 fprintf (go_dump_file, "// ");
638 fprintf (go_dump_file, "func _%s ",
639 IDENTIFIER_POINTER (DECL_NAME (decl)));
640 go_output_type (container);
641 fprintf (go_dump_file, " __asm__(\"%s\")\n",
642 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
645 /* Output a typedef or something like a struct definition. */
647 static void
648 go_output_typedef (struct godump_container *container, tree decl)
650 /* If we have an enum type, output the enum constants
651 separately. */
652 if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
653 && TYPE_SIZE (TREE_TYPE (decl)) != 0
654 && !pointer_set_contains (container->decls_seen, TREE_TYPE (decl))
655 && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
656 || !pointer_set_contains (container->decls_seen,
657 TYPE_CANONICAL (TREE_TYPE (decl)))))
659 tree element;
661 for (element = TYPE_VALUES (TREE_TYPE (decl));
662 element != NULL_TREE;
663 element = TREE_CHAIN (element))
664 fprintf (go_dump_file, "const _%s = " HOST_WIDE_INT_PRINT_DEC "\n",
665 IDENTIFIER_POINTER (TREE_PURPOSE (element)),
666 tree_low_cst (TREE_VALUE (element), 0));
667 pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
668 if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
669 pointer_set_insert (container->decls_seen,
670 TYPE_CANONICAL (TREE_TYPE (decl)));
673 if (DECL_NAME (decl) != NULL_TREE)
675 void **slot;
676 const char *type;
678 type = IDENTIFIER_POINTER (DECL_NAME (decl));
679 /* If type defined already, skip. */
680 slot = htab_find_slot (container->type_hash, type, INSERT);
681 if (*slot != NULL)
682 return;
683 *slot = CONST_CAST (void *, (const void *) type);
685 if (!go_format_type (container, TREE_TYPE (decl), false, false))
686 fprintf (go_dump_file, "// ");
687 fprintf (go_dump_file, "type _%s ",
688 IDENTIFIER_POINTER (DECL_NAME (decl)));
689 go_output_type (container);
690 pointer_set_insert (container->decls_seen, decl);
692 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
694 void **slot;
695 const char *type;
697 type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
698 /* If type defined already, skip. */
699 slot = htab_find_slot (container->type_hash, type, INSERT);
700 if (*slot != NULL)
701 return;
702 *slot = CONST_CAST (void *, (const void *) type);
704 if (!go_format_type (container, TREE_TYPE (decl), false, false))
705 fprintf (go_dump_file, "// ");
706 fprintf (go_dump_file, "type _%s ",
707 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
708 go_output_type (container);
710 else
711 return;
713 fprintf (go_dump_file, "\n");
716 /* Output a variable. */
718 static void
719 go_output_var (struct godump_container *container, tree decl)
721 if (pointer_set_contains (container->decls_seen, decl)
722 || pointer_set_contains (container->decls_seen, DECL_NAME (decl)))
723 return;
724 pointer_set_insert (container->decls_seen, decl);
725 pointer_set_insert (container->decls_seen, DECL_NAME (decl));
726 if (!go_format_type (container, TREE_TYPE (decl), true, false))
727 fprintf (go_dump_file, "// ");
728 fprintf (go_dump_file, "var _%s ",
729 IDENTIFIER_POINTER (DECL_NAME (decl)));
730 go_output_type (container);
731 fprintf (go_dump_file, "\n");
733 /* Sometimes an extern variable is declared with an unknown struct
734 type. */
735 if (TYPE_NAME (TREE_TYPE (decl)) != NULL_TREE
736 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
738 tree type_name = TYPE_NAME (TREE_TYPE (decl));
739 if (TREE_CODE (type_name) == IDENTIFIER_NODE)
740 pointer_set_insert (container->pot_dummy_types,
741 IDENTIFIER_POINTER (type_name));
742 else if (TREE_CODE (type_name) == TYPE_DECL)
743 pointer_set_insert (container->pot_dummy_types,
744 IDENTIFIER_POINTER (DECL_NAME (type_name)));
748 /* Build a hash table with the Go keywords. */
750 static const char * const keywords[] = {
751 "__asm__", "break", "case", "chan", "const", "continue", "default",
752 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
753 "import", "interface", "map", "package", "range", "return", "select",
754 "struct", "switch", "type", "var"
757 static void
758 keyword_hash_init (struct godump_container *container)
760 size_t i;
761 size_t count = sizeof (keywords) / sizeof (keywords[0]);
762 void **slot;
764 for (i = 0; i < count; i++)
766 slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
767 *slot = CONST_CAST (void *, (const void *) keywords[i]);
771 /* Traversing the pot_dummy_types and seeing which types are present
772 in the global types hash table and creating dummy definitions if
773 not found. This function is invoked by pointer_set_traverse. */
775 static bool
776 find_dummy_types (const void *ptr, void *adata)
778 struct godump_container *data = (struct godump_container *) adata;
779 const char *type = (const char *) ptr;
780 void **slot;
782 slot = htab_find_slot (data->type_hash, type, NO_INSERT);
783 if (slot == NULL)
784 fprintf (go_dump_file, "type _%s struct {}\n", type);
785 return true;
788 /* Output symbols. */
790 static void
791 go_finish (const char *filename)
793 struct godump_container container;
794 unsigned int ix;
795 tree decl;
797 real_debug_hooks->finish (filename);
799 container.decls_seen = pointer_set_create ();
800 container.pot_dummy_types = pointer_set_create ();
801 container.type_hash = htab_create (100, htab_hash_string,
802 string_hash_eq, NULL);
803 container.keyword_hash = htab_create (50, htab_hash_string,
804 string_hash_eq, NULL);
805 obstack_init (&container.type_obstack);
807 keyword_hash_init (&container);
809 FOR_EACH_VEC_ELT (tree, queue, ix, decl)
811 switch (TREE_CODE (decl))
813 case FUNCTION_DECL:
814 go_output_fndecl (&container, decl);
815 break;
817 case TYPE_DECL:
818 go_output_typedef (&container, decl);
819 break;
821 case VAR_DECL:
822 go_output_var (&container, decl);
823 break;
825 default:
826 gcc_unreachable();
830 /* To emit dummy definitions. */
831 pointer_set_traverse (container.pot_dummy_types, find_dummy_types,
832 (void *) &container);
834 pointer_set_destroy (container.decls_seen);
835 pointer_set_destroy (container.pot_dummy_types);
836 htab_delete (container.type_hash);
837 htab_delete (container.keyword_hash);
838 obstack_free (&container.type_obstack, NULL);
840 queue = NULL;
842 if (fclose (go_dump_file) != 0)
843 error ("could not close Go dump file: %m");
844 go_dump_file = NULL;
847 /* Set up our hooks. */
849 const struct gcc_debug_hooks *
850 dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
852 go_dump_file = fopen (filename, "w");
853 if (go_dump_file == NULL)
855 error ("could not open Go dump file %qs: %m", filename);
856 return hooks;
859 go_debug_hooks = *hooks;
860 real_debug_hooks = hooks;
862 go_debug_hooks.finish = go_finish;
863 go_debug_hooks.define = go_define;
864 go_debug_hooks.undef = go_undef;
865 go_debug_hooks.function_decl = go_function_decl;
866 go_debug_hooks.global_decl = go_global_decl;
867 go_debug_hooks.type_decl = go_type_decl;
869 macro_hash = htab_create (100, htab_hash_string, string_hash_eq, NULL);
871 return &go_debug_hooks;
874 #include "gt-godump.h"