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
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
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
27 All global names are output with a leading underscore, so that they
28 are all hidden in Go. */
32 #include "coretypes.h"
33 #include "diagnostic-core.h"
36 #include "pointer-set.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. */
68 string_hash_eq (const void *y1
, const void *y2
)
70 return strcmp ((const char *) y1
, (const char *) y2
) == 0;
73 /* A macro definition. */
76 go_define (unsigned int lineno
, const char *buffer
)
88 real_debug_hooks
->define (lineno
, buffer
);
90 /* Skip macro functions. */
91 for (p
= buffer
; *p
!= '\0' && *p
!= ' '; ++p
)
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
);
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);
121 need_operand
= false;
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':
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':
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. */
149 while (ISALNUM (*p
) || *p
== '_')
151 n
= XALLOCAVEC (char, p
- start
+ 1);
152 memcpy (n
, start
, p
- start
);
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
163 memcpy (q
, start
, p
- start
);
167 need_operand
= false;
175 case '0': case '1': case '2': case '3': case '4':
176 case '5': case '6': case '7': case '8': case '9':
183 if (*p
== '0' && (p
[1] == 'x' || p
[1] == 'X'))
188 while (ISDIGIT (*p
) || *p
== '.' || *p
== 'e' || *p
== 'E'
190 && ((*p
>= 'a' && *p
<= 'f')
191 || (*p
>= 'A' && *p
<= 'F'))))
193 memcpy (q
, start
, 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
204 /* We'll pick up the exponent, if any, as an
208 need_operand
= false;
217 /* Always OK, not part of an operand, presumed to start an
221 need_operand
= false;
225 /* OK if we don't need an operand, and presumed to indicate
234 /* Always OK, but not part of an operand. */
239 case '*': case '/': case '%': case '|': case '&': case '^':
240 /* Must be a binary operator. */
252 /* Must be a binary operator. */
264 /* Must be a binary operator. */
273 /* Must be a unary operator. */
281 /* Must be a binary operand, may be << or >> or <= or >=. */
285 if (*p
== *(p
- 1) || *p
== '=')
292 /* Must be a unary operand, must be translated for Go. */
329 case '0': case '1': case '2': case '3':
330 case '4': case '5': case '6': case '7':
332 while (*p
>= '0' && *p
<= '7')
337 /* Go octal characters are always 3
346 while (ISXDIGIT (*p
))
351 /* Go hex characters are always 2 digits. */
356 case 'a': case 'b': case 'f': case 'n': case 'r':
357 case 't': case 'v': case '\\': case '\'': case '"':
368 if (quote
== '\'' && count
!= 1)
372 need_operand
= false;
387 slot
= htab_find_slot_with_hash (macro_hash
, copy
, hashval
, INSERT
);
390 fprintf (go_dump_file
, "const _%s = %s\n", copy
, out_buffer
);
392 XDELETEVEC (out_buffer
);
396 fprintf (go_dump_file
, "// unknowndefine %s\n", buffer
);
397 XDELETEVEC (out_buffer
);
404 go_undef (unsigned int lineno
, const char *buffer
)
408 real_debug_hooks
->undef (lineno
, buffer
);
410 slot
= htab_find_slot (macro_hash
, buffer
, NO_INSERT
);
413 fprintf (go_dump_file
, "// undef _%s\n", buffer
);
414 /* We don't delete the slot from the hash table because that will
415 cause a duplicate const definition. */
418 /* A function or variable decl. */
423 if (!TREE_PUBLIC (decl
)
424 || DECL_IS_BUILTIN (decl
)
425 || DECL_NAME (decl
) == NULL_TREE
)
427 VEC_safe_push (tree
, gc
, queue
, decl
);
430 /* A function decl. */
433 go_function_decl (tree decl
)
435 real_debug_hooks
->function_decl (decl
);
439 /* A global variable decl. */
442 go_global_decl (tree decl
)
444 real_debug_hooks
->global_decl (decl
);
448 /* A type declaration. */
451 go_type_decl (tree decl
, int local
)
453 real_debug_hooks
->type_decl (decl
, local
);
455 if (local
|| DECL_IS_BUILTIN (decl
))
457 if (DECL_NAME (decl
) == NULL_TREE
458 && (TYPE_NAME (TREE_TYPE (decl
)) == NULL_TREE
459 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl
))) != IDENTIFIER_NODE
)
460 && TREE_CODE (TREE_TYPE (decl
)) != ENUMERAL_TYPE
)
462 VEC_safe_push (tree
, gc
, queue
, decl
);
465 /* A container for the data we pass around when generating information
466 at the end of the compilation. */
468 struct godump_container
470 /* DECLs that we have already seen. */
471 struct pointer_set_t
*decls_seen
;
473 /* Types which may potentially have to be defined as dummy
475 struct pointer_set_t
*pot_dummy_types
;
480 /* Global type definitions. */
486 /* Obstack used to write out a type definition. */
487 struct obstack type_obstack
;
490 /* Append an IDENTIFIER_NODE to OB. */
493 go_append_string (struct obstack
*ob
, tree id
)
495 obstack_grow (ob
, IDENTIFIER_POINTER (id
), IDENTIFIER_LENGTH (id
));
498 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
499 USE_TYPE_NAME is true if we can simply use a type name here without
500 needing to define it. IS_FUNC_OK is true if we can output a func
501 type here; the "func" keyword will already have been added. Return
502 true if the type can be represented in Go, false otherwise. */
505 go_format_type (struct godump_container
*container
, tree type
,
506 bool use_type_name
, bool is_func_ok
)
512 ob
= &container
->type_obstack
;
514 if (TYPE_NAME (type
) != NULL_TREE
515 && (pointer_set_contains (container
->decls_seen
, type
)
516 || pointer_set_contains (container
->decls_seen
, TYPE_NAME (type
)))
517 && (AGGREGATE_TYPE_P (type
)
518 || POINTER_TYPE_P (type
)
519 || TREE_CODE (type
) == FUNCTION_TYPE
))
524 name
= TYPE_NAME (type
);
525 if (TREE_CODE (name
) == TYPE_DECL
)
526 name
= DECL_NAME (name
);
528 slot
= htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (name
),
533 obstack_1grow (ob
, '_');
534 go_append_string (ob
, name
);
538 pointer_set_insert (container
->decls_seen
, type
);
540 switch (TREE_CODE (type
))
543 obstack_grow (ob
, "int", 3);
550 slot
= htab_find_slot (container
->invalid_hash
,
551 IDENTIFIER_POINTER (DECL_NAME (type
)),
556 obstack_1grow (ob
, '_');
557 go_append_string (ob
, DECL_NAME (type
));
566 switch (TYPE_PRECISION (type
))
569 s
= TYPE_UNSIGNED (type
) ? "uint8" : "int8";
572 s
= TYPE_UNSIGNED (type
) ? "uint16" : "int16";
575 s
= TYPE_UNSIGNED (type
) ? "uint32" : "int32";
578 s
= TYPE_UNSIGNED (type
) ? "uint64" : "int64";
581 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
582 TYPE_PRECISION (type
),
583 TYPE_UNSIGNED (type
) ? "u" : "");
588 obstack_grow (ob
, s
, strlen (s
));
597 switch (TYPE_PRECISION (type
))
606 snprintf (buf
, sizeof buf
, "INVALID-float-%u",
607 TYPE_PRECISION (type
));
612 obstack_grow (ob
, s
, strlen (s
));
617 obstack_grow (ob
, "bool", 4);
622 && TYPE_NAME (TREE_TYPE (type
)) != NULL_TREE
623 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
))
624 || (POINTER_TYPE_P (TREE_TYPE (type
))
625 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type
)))
631 name
= TYPE_NAME (TREE_TYPE (type
));
632 if (TREE_CODE (name
) == TYPE_DECL
)
633 name
= DECL_NAME (name
);
635 slot
= htab_find_slot (container
->invalid_hash
,
636 IDENTIFIER_POINTER (name
), NO_INSERT
);
640 obstack_grow (ob
, "*_", 2);
641 go_append_string (ob
, name
);
643 /* The pointer here can be used without the struct or union
644 definition. So this struct or union is a potential dummy
646 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
)))
647 pointer_set_insert (container
->pot_dummy_types
,
648 IDENTIFIER_POINTER (name
));
652 if (TREE_CODE (TREE_TYPE (type
)) == FUNCTION_TYPE
)
653 obstack_grow (ob
, "func", 4);
655 obstack_1grow (ob
, '*');
656 if (VOID_TYPE_P (TREE_TYPE (type
)))
657 obstack_grow (ob
, "byte", 4);
660 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
,
667 obstack_1grow (ob
, '[');
668 if (TYPE_DOMAIN (type
) != NULL_TREE
669 && TREE_CODE (TYPE_DOMAIN (type
)) == INTEGER_TYPE
670 && TYPE_MIN_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
671 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
672 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == 0
673 && TYPE_MAX_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
674 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
675 && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type
)), 0))
679 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
"+1",
680 tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type
)), 0));
681 obstack_grow (ob
, buf
, strlen (buf
));
683 obstack_1grow (ob
, ']');
684 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
, false))
694 obstack_grow (ob
, "struct { ", 9);
696 for (field
= TYPE_FIELDS (type
);
698 field
= TREE_CHAIN (field
))
700 struct obstack hold_type_obstack
;
703 if (TREE_CODE (type
) == UNION_TYPE
)
705 hold_type_obstack
= container
->type_obstack
;
706 obstack_init (&container
->type_obstack
);
711 if (DECL_NAME (field
) == NULL
)
715 obstack_grow (ob
, "Godump_", 7);
716 snprintf (buf
, sizeof buf
, "%d", i
);
717 obstack_grow (ob
, buf
, strlen (buf
));
722 const char *var_name
;
725 /* Start variable name with an underscore if a keyword. */
726 var_name
= IDENTIFIER_POINTER (DECL_NAME (field
));
727 slot
= htab_find_slot (container
->keyword_hash
, var_name
,
730 obstack_1grow (ob
, '_');
731 go_append_string (ob
, DECL_NAME (field
));
733 obstack_1grow (ob
, ' ');
734 if (DECL_BIT_FIELD (field
))
736 obstack_grow (ob
, "INVALID-bit-field", 17);
741 /* Do not expand type if a record or union type or a
743 if (TYPE_NAME (TREE_TYPE (field
)) != NULL_TREE
744 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field
))
745 || (POINTER_TYPE_P (TREE_TYPE (field
))
746 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field
)))
752 name
= TYPE_NAME (TREE_TYPE (field
));
753 if (TREE_CODE (name
) == TYPE_DECL
)
754 name
= DECL_NAME (name
);
756 slot
= htab_find_slot (container
->invalid_hash
,
757 IDENTIFIER_POINTER (name
),
762 obstack_1grow (ob
, '_');
763 go_append_string (ob
, name
);
767 if (!go_format_type (container
, TREE_TYPE (field
), true,
772 obstack_grow (ob
, "; ", 2);
774 /* Only output the first successful field of a union, and
775 hope for the best. */
776 if (TREE_CODE (type
) == UNION_TYPE
)
778 if (!field_ok
&& TREE_CHAIN (field
) == NULL_TREE
)
787 sz
= obstack_object_size (&container
->type_obstack
);
788 obstack_grow (&hold_type_obstack
,
789 obstack_base (&container
->type_obstack
),
792 obstack_free (&container
->type_obstack
, NULL
);
793 container
->type_obstack
= hold_type_obstack
;
803 obstack_1grow (ob
, '}');
812 function_args_iterator iter
;
815 /* Go has no way to write a type which is a function but not a
816 pointer to a function. */
819 obstack_grow (ob
, "func*", 5);
823 obstack_1grow (ob
, '(');
824 is_varargs
= stdarg_p (type
);
826 FOREACH_FUNCTION_ARGS (type
, arg_type
, iter
)
828 if (VOID_TYPE_P (arg_type
))
831 obstack_grow (ob
, ", ", 2);
832 if (!go_format_type (container
, arg_type
, true, false))
838 if (prototype_p (type
))
839 obstack_grow (ob
, ", ", 2);
840 obstack_grow (ob
, "...interface{}", 14);
842 obstack_1grow (ob
, ')');
844 result
= TREE_TYPE (type
);
845 if (!VOID_TYPE_P (result
))
847 obstack_1grow (ob
, ' ');
848 if (!go_format_type (container
, result
, use_type_name
, false))
855 obstack_grow (ob
, "INVALID-type", 12);
863 /* Output the type which was built on the type obstack, and then free
867 go_output_type (struct godump_container
*container
)
871 ob
= &container
->type_obstack
;
872 obstack_1grow (ob
, '\0');
873 fputs (obstack_base (ob
), go_dump_file
);
874 obstack_free (ob
, obstack_base (ob
));
877 /* Output a function declaration. */
880 go_output_fndecl (struct godump_container
*container
, tree decl
)
882 if (!go_format_type (container
, TREE_TYPE (decl
), false, true))
883 fprintf (go_dump_file
, "// ");
884 fprintf (go_dump_file
, "func _%s ",
885 IDENTIFIER_POINTER (DECL_NAME (decl
)));
886 go_output_type (container
);
887 fprintf (go_dump_file
, " __asm__(\"%s\")\n",
888 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
)));
891 /* Output a typedef or something like a struct definition. */
894 go_output_typedef (struct godump_container
*container
, tree decl
)
896 /* If we have an enum type, output the enum constants
898 if (TREE_CODE (TREE_TYPE (decl
)) == ENUMERAL_TYPE
899 && TYPE_SIZE (TREE_TYPE (decl
)) != 0
900 && !pointer_set_contains (container
->decls_seen
, TREE_TYPE (decl
))
901 && (TYPE_CANONICAL (TREE_TYPE (decl
)) == NULL_TREE
902 || !pointer_set_contains (container
->decls_seen
,
903 TYPE_CANONICAL (TREE_TYPE (decl
)))))
907 for (element
= TYPE_VALUES (TREE_TYPE (decl
));
908 element
!= NULL_TREE
;
909 element
= TREE_CHAIN (element
))
914 name
= IDENTIFIER_POINTER (TREE_PURPOSE (element
));
916 /* Sometimes a name will be defined as both an enum constant
917 and a macro. Avoid duplicate definition errors by
918 treating enum constants as macros. */
919 slot
= htab_find_slot (macro_hash
, name
, INSERT
);
922 *slot
= CONST_CAST (char *, name
);
923 fprintf (go_dump_file
,
924 "const _%s = " HOST_WIDE_INT_PRINT_DEC
"\n",
925 name
, tree_low_cst (TREE_VALUE (element
), 0));
928 pointer_set_insert (container
->decls_seen
, TREE_TYPE (decl
));
929 if (TYPE_CANONICAL (TREE_TYPE (decl
)) != NULL_TREE
)
930 pointer_set_insert (container
->decls_seen
,
931 TYPE_CANONICAL (TREE_TYPE (decl
)));
934 if (DECL_NAME (decl
) != NULL_TREE
)
939 type
= IDENTIFIER_POINTER (DECL_NAME (decl
));
940 /* If type defined already, skip. */
941 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
944 *slot
= CONST_CAST (void *, (const void *) type
);
946 if (!go_format_type (container
, TREE_TYPE (decl
), false, false))
948 fprintf (go_dump_file
, "// ");
949 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
950 *slot
= CONST_CAST (void *, (const void *) type
);
952 fprintf (go_dump_file
, "type _%s ",
953 IDENTIFIER_POINTER (DECL_NAME (decl
)));
954 go_output_type (container
);
955 pointer_set_insert (container
->decls_seen
, decl
);
957 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
962 type
= IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl
))));
963 /* If type defined already, skip. */
964 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
967 *slot
= CONST_CAST (void *, (const void *) type
);
969 if (!go_format_type (container
, TREE_TYPE (decl
), false, false))
971 fprintf (go_dump_file
, "// ");
972 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
973 *slot
= CONST_CAST (void *, (const void *) type
);
975 fprintf (go_dump_file
, "type _%s ",
976 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))));
977 go_output_type (container
);
982 fprintf (go_dump_file
, "\n");
985 /* Output a variable. */
988 go_output_var (struct godump_container
*container
, tree decl
)
992 if (pointer_set_contains (container
->decls_seen
, decl
)
993 || pointer_set_contains (container
->decls_seen
, DECL_NAME (decl
)))
995 pointer_set_insert (container
->decls_seen
, decl
);
996 pointer_set_insert (container
->decls_seen
, DECL_NAME (decl
));
998 is_valid
= go_format_type (container
, TREE_TYPE (decl
), true, false);
1000 && htab_find_slot (container
->type_hash
,
1001 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1004 /* There is already a type with this name, probably from a
1005 struct tag. Prefer the type to the variable. */
1009 fprintf (go_dump_file
, "// ");
1011 fprintf (go_dump_file
, "var _%s ",
1012 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1013 go_output_type (container
);
1014 fprintf (go_dump_file
, "\n");
1016 /* Sometimes an extern variable is declared with an unknown struct
1018 if (TYPE_NAME (TREE_TYPE (decl
)) != NULL_TREE
1019 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1021 tree type_name
= TYPE_NAME (TREE_TYPE (decl
));
1022 if (TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1023 pointer_set_insert (container
->pot_dummy_types
,
1024 IDENTIFIER_POINTER (type_name
));
1025 else if (TREE_CODE (type_name
) == TYPE_DECL
)
1026 pointer_set_insert (container
->pot_dummy_types
,
1027 IDENTIFIER_POINTER (DECL_NAME (type_name
)));
1031 /* Build a hash table with the Go keywords. */
1033 static const char * const keywords
[] = {
1034 "__asm__", "break", "case", "chan", "const", "continue", "default",
1035 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1036 "import", "interface", "map", "package", "range", "return", "select",
1037 "struct", "switch", "type", "var"
1041 keyword_hash_init (struct godump_container
*container
)
1044 size_t count
= sizeof (keywords
) / sizeof (keywords
[0]);
1047 for (i
= 0; i
< count
; i
++)
1049 slot
= htab_find_slot (container
->keyword_hash
, keywords
[i
], INSERT
);
1050 *slot
= CONST_CAST (void *, (const void *) keywords
[i
]);
1054 /* Traversing the pot_dummy_types and seeing which types are present
1055 in the global types hash table and creating dummy definitions if
1056 not found. This function is invoked by pointer_set_traverse. */
1059 find_dummy_types (const void *ptr
, void *adata
)
1061 struct godump_container
*data
= (struct godump_container
*) adata
;
1062 const char *type
= (const char *) ptr
;
1065 slot
= htab_find_slot (data
->type_hash
, type
, NO_INSERT
);
1067 fprintf (go_dump_file
, "type _%s struct {}\n", type
);
1071 /* Output symbols. */
1074 go_finish (const char *filename
)
1076 struct godump_container container
;
1080 real_debug_hooks
->finish (filename
);
1082 container
.decls_seen
= pointer_set_create ();
1083 container
.pot_dummy_types
= pointer_set_create ();
1084 container
.type_hash
= htab_create (100, htab_hash_string
,
1085 string_hash_eq
, NULL
);
1086 container
.invalid_hash
= htab_create (10, htab_hash_string
,
1087 string_hash_eq
, NULL
);
1088 container
.keyword_hash
= htab_create (50, htab_hash_string
,
1089 string_hash_eq
, NULL
);
1090 obstack_init (&container
.type_obstack
);
1092 keyword_hash_init (&container
);
1094 FOR_EACH_VEC_ELT (tree
, queue
, ix
, decl
)
1096 switch (TREE_CODE (decl
))
1099 go_output_fndecl (&container
, decl
);
1103 go_output_typedef (&container
, decl
);
1107 go_output_var (&container
, decl
);
1115 /* To emit dummy definitions. */
1116 pointer_set_traverse (container
.pot_dummy_types
, find_dummy_types
,
1117 (void *) &container
);
1119 pointer_set_destroy (container
.decls_seen
);
1120 pointer_set_destroy (container
.pot_dummy_types
);
1121 htab_delete (container
.type_hash
);
1122 htab_delete (container
.invalid_hash
);
1123 htab_delete (container
.keyword_hash
);
1124 obstack_free (&container
.type_obstack
, NULL
);
1128 if (fclose (go_dump_file
) != 0)
1129 error ("could not close Go dump file: %m");
1130 go_dump_file
= NULL
;
1133 /* Set up our hooks. */
1135 const struct gcc_debug_hooks
*
1136 dump_go_spec_init (const char *filename
, const struct gcc_debug_hooks
*hooks
)
1138 go_dump_file
= fopen (filename
, "w");
1139 if (go_dump_file
== NULL
)
1141 error ("could not open Go dump file %qs: %m", filename
);
1145 go_debug_hooks
= *hooks
;
1146 real_debug_hooks
= hooks
;
1148 go_debug_hooks
.finish
= go_finish
;
1149 go_debug_hooks
.define
= go_define
;
1150 go_debug_hooks
.undef
= go_undef
;
1151 go_debug_hooks
.function_decl
= go_function_decl
;
1152 go_debug_hooks
.global_decl
= go_global_decl
;
1153 go_debug_hooks
.type_decl
= go_type_decl
;
1155 macro_hash
= htab_create (100, htab_hash_string
, string_hash_eq
, NULL
);
1157 return &go_debug_hooks
;
1160 #include "gt-godump.h"