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. */
325 case '0': case '1': case '2': case '3':
326 case '4': case '5': case '6': case '7':
328 while (*p
>= '0' && *p
<= '7')
333 /* Go octal characters are always 3
342 while (ISXDIGIT (*p
))
347 /* Go hex characters are always 2 digits. */
352 case 'a': case 'b': case 'f': case 'n': case 'r':
353 case 't': case 'v': case '\\': case '\'': case '"':
375 slot
= htab_find_slot_with_hash (macro_hash
, copy
, hashval
, INSERT
);
378 fprintf (go_dump_file
, "const _%s = %s\n", copy
, out_buffer
);
380 XDELETEVEC (out_buffer
);
384 fprintf (go_dump_file
, "// unknowndefine %s\n", buffer
);
385 XDELETEVEC (out_buffer
);
392 go_undef (unsigned int lineno
, const char *buffer
)
396 real_debug_hooks
->undef (lineno
, buffer
);
398 slot
= htab_find_slot (macro_hash
, buffer
, NO_INSERT
);
401 fprintf (go_dump_file
, "// undef _%s\n", buffer
);
402 /* We don't delete the slot from the hash table because that will
403 cause a duplicate const definition. */
406 /* A function or variable decl. */
411 if (!TREE_PUBLIC (decl
)
412 || DECL_IS_BUILTIN (decl
)
413 || DECL_NAME (decl
) == NULL_TREE
)
415 VEC_safe_push (tree
, gc
, queue
, decl
);
418 /* A function decl. */
421 go_function_decl (tree decl
)
423 real_debug_hooks
->function_decl (decl
);
427 /* A global variable decl. */
430 go_global_decl (tree decl
)
432 real_debug_hooks
->global_decl (decl
);
436 /* A type declaration. */
439 go_type_decl (tree decl
, int local
)
441 real_debug_hooks
->type_decl (decl
, local
);
443 if (local
|| DECL_IS_BUILTIN (decl
))
445 if (DECL_NAME (decl
) == NULL_TREE
446 && (TYPE_NAME (TREE_TYPE (decl
)) == NULL_TREE
447 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl
))) != IDENTIFIER_NODE
)
448 && TREE_CODE (TREE_TYPE (decl
)) != ENUMERAL_TYPE
)
450 VEC_safe_push (tree
, gc
, queue
, decl
);
453 /* A container for the data we pass around when generating information
454 at the end of the compilation. */
456 struct godump_container
458 /* DECLs that we have already seen. */
459 struct pointer_set_t
*decls_seen
;
461 /* Types which may potentially have to be defined as dummy
463 struct pointer_set_t
*pot_dummy_types
;
468 /* Global type definitions. */
474 /* Obstack used to write out a type definition. */
475 struct obstack type_obstack
;
478 /* Append an IDENTIFIER_NODE to OB. */
481 go_append_string (struct obstack
*ob
, tree id
)
483 obstack_grow (ob
, IDENTIFIER_POINTER (id
), IDENTIFIER_LENGTH (id
));
486 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
487 USE_TYPE_NAME is true if we can simply use a type name here without
488 needing to define it. IS_FUNC_OK is true if we can output a func
489 type here; the "func" keyword will already have been added. Return
490 true if the type can be represented in Go, false otherwise. */
493 go_format_type (struct godump_container
*container
, tree type
,
494 bool use_type_name
, bool is_func_ok
)
500 ob
= &container
->type_obstack
;
502 if (TYPE_NAME (type
) != NULL_TREE
503 && (pointer_set_contains (container
->decls_seen
, type
)
504 || pointer_set_contains (container
->decls_seen
, TYPE_NAME (type
)))
505 && (AGGREGATE_TYPE_P (type
)
506 || POINTER_TYPE_P (type
)
507 || TREE_CODE (type
) == FUNCTION_TYPE
))
512 name
= TYPE_NAME (type
);
513 if (TREE_CODE (name
) == TYPE_DECL
)
514 name
= DECL_NAME (name
);
516 slot
= htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (name
),
521 obstack_1grow (ob
, '_');
522 go_append_string (ob
, name
);
526 pointer_set_insert (container
->decls_seen
, type
);
528 switch (TREE_CODE (type
))
531 obstack_grow (ob
, "int", 3);
535 obstack_1grow (ob
, '_');
536 go_append_string (ob
, DECL_NAME (type
));
544 switch (TYPE_PRECISION (type
))
547 s
= TYPE_UNSIGNED (type
) ? "uint8" : "int8";
550 s
= TYPE_UNSIGNED (type
) ? "uint16" : "int16";
553 s
= TYPE_UNSIGNED (type
) ? "uint32" : "int32";
556 s
= TYPE_UNSIGNED (type
) ? "uint64" : "int64";
559 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
560 TYPE_PRECISION (type
),
561 TYPE_UNSIGNED (type
) ? "u" : "");
566 obstack_grow (ob
, s
, strlen (s
));
575 switch (TYPE_PRECISION (type
))
584 snprintf (buf
, sizeof buf
, "INVALID-float-%u",
585 TYPE_PRECISION (type
));
590 obstack_grow (ob
, s
, strlen (s
));
595 obstack_grow (ob
, "bool", 4);
600 && TYPE_NAME (TREE_TYPE (type
)) != NULL_TREE
601 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
))
602 || (POINTER_TYPE_P (TREE_TYPE (type
))
603 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type
)))
608 name
= TYPE_NAME (TREE_TYPE (type
));
609 if (TREE_CODE (name
) == IDENTIFIER_NODE
)
611 obstack_grow (ob
, "*_", 2);
612 go_append_string (ob
, name
);
614 /* The pointer here can be used without the struct or
615 union definition. So this struct or union is a a
616 potential dummy type. */
617 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
)))
618 pointer_set_insert (container
->pot_dummy_types
,
619 IDENTIFIER_POINTER (name
));
623 else if (TREE_CODE (name
) == TYPE_DECL
)
625 obstack_grow (ob
, "*_", 2);
626 go_append_string (ob
, DECL_NAME (name
));
627 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
)))
628 pointer_set_insert (container
->pot_dummy_types
,
629 IDENTIFIER_POINTER (DECL_NAME (name
)));
633 if (TREE_CODE (TREE_TYPE (type
)) == FUNCTION_TYPE
)
634 obstack_grow (ob
, "func", 4);
636 obstack_1grow (ob
, '*');
637 if (VOID_TYPE_P (TREE_TYPE (type
)))
638 obstack_grow (ob
, "byte", 4);
641 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
,
648 obstack_1grow (ob
, '[');
649 if (TYPE_DOMAIN (type
) != NULL_TREE
650 && TREE_CODE (TYPE_DOMAIN (type
)) == INTEGER_TYPE
651 && TYPE_MIN_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
652 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
653 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == 0
654 && TYPE_MAX_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
655 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
656 && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type
)), 0))
660 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
"+1",
661 tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type
)), 0));
662 obstack_grow (ob
, buf
, strlen (buf
));
664 obstack_1grow (ob
, ']');
665 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
, false))
675 obstack_grow (ob
, "struct { ", 9);
677 for (field
= TYPE_FIELDS (type
);
679 field
= TREE_CHAIN (field
))
681 if (DECL_NAME (field
) == NULL
)
685 obstack_grow (ob
, "Godump_", 2);
686 snprintf (buf
, sizeof buf
, "%d", i
);
687 obstack_grow (ob
, buf
, strlen (buf
));
692 const char *var_name
;
695 /* Start variable name with an underscore if a keyword. */
696 var_name
= IDENTIFIER_POINTER (DECL_NAME (field
));
697 slot
= htab_find_slot (container
->keyword_hash
, var_name
,
700 obstack_1grow (ob
, '_');
701 go_append_string (ob
, DECL_NAME (field
));
703 obstack_1grow (ob
, ' ');
704 if (DECL_BIT_FIELD (field
))
706 obstack_grow (ob
, "INVALID-bit-field", 17);
711 /* Do not expand type if a record or union type or a
713 if (TYPE_NAME (TREE_TYPE (field
)) != NULL_TREE
714 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field
))
715 || (POINTER_TYPE_P (TREE_TYPE (field
))
716 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field
)))
719 tree name
= TYPE_NAME (TREE_TYPE (field
));
720 if (TREE_CODE (name
) == IDENTIFIER_NODE
)
722 obstack_1grow (ob
, '_');
723 go_append_string (ob
, name
);
725 else if (TREE_CODE (name
) == TYPE_DECL
)
727 obstack_1grow (ob
, '_');
728 go_append_string (ob
, DECL_NAME (name
));
733 if (!go_format_type (container
, TREE_TYPE (field
), true,
738 obstack_grow (ob
, "; ", 2);
740 /* Only output the first field of a union, and hope for
742 if (TREE_CODE (type
) == UNION_TYPE
)
745 obstack_1grow (ob
, '}');
754 function_args_iterator iter
;
757 /* Go has no way to write a type which is a function but not a
758 pointer to a function. */
761 obstack_grow (ob
, "func*", 5);
765 obstack_1grow (ob
, '(');
766 is_varargs
= stdarg_p (type
);
768 FOREACH_FUNCTION_ARGS (type
, arg_type
, iter
)
770 if (VOID_TYPE_P (arg_type
))
773 obstack_grow (ob
, ", ", 2);
774 if (!go_format_type (container
, arg_type
, true, false))
780 if (prototype_p (type
))
781 obstack_grow (ob
, ", ", 2);
782 obstack_grow (ob
, "...interface{}", 14);
784 obstack_1grow (ob
, ')');
786 result
= TREE_TYPE (type
);
787 if (!VOID_TYPE_P (result
))
789 obstack_1grow (ob
, ' ');
790 if (!go_format_type (container
, result
, use_type_name
, false))
797 obstack_grow (ob
, "INVALID-type", 12);
805 /* Output the type which was built on the type obstack, and then free
809 go_output_type (struct godump_container
*container
)
813 ob
= &container
->type_obstack
;
814 obstack_1grow (ob
, '\0');
815 fputs (obstack_base (ob
), go_dump_file
);
816 obstack_free (ob
, obstack_base (ob
));
819 /* Output a function declaration. */
822 go_output_fndecl (struct godump_container
*container
, tree decl
)
824 if (!go_format_type (container
, TREE_TYPE (decl
), false, true))
825 fprintf (go_dump_file
, "// ");
826 fprintf (go_dump_file
, "func _%s ",
827 IDENTIFIER_POINTER (DECL_NAME (decl
)));
828 go_output_type (container
);
829 fprintf (go_dump_file
, " __asm__(\"%s\")\n",
830 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
)));
833 /* Output a typedef or something like a struct definition. */
836 go_output_typedef (struct godump_container
*container
, tree decl
)
838 /* If we have an enum type, output the enum constants
840 if (TREE_CODE (TREE_TYPE (decl
)) == ENUMERAL_TYPE
841 && TYPE_SIZE (TREE_TYPE (decl
)) != 0
842 && !pointer_set_contains (container
->decls_seen
, TREE_TYPE (decl
))
843 && (TYPE_CANONICAL (TREE_TYPE (decl
)) == NULL_TREE
844 || !pointer_set_contains (container
->decls_seen
,
845 TYPE_CANONICAL (TREE_TYPE (decl
)))))
849 for (element
= TYPE_VALUES (TREE_TYPE (decl
));
850 element
!= NULL_TREE
;
851 element
= TREE_CHAIN (element
))
856 name
= IDENTIFIER_POINTER (TREE_PURPOSE (element
));
858 /* Sometimes a name will be defined as both an enum constant
859 and a macro. Avoid duplicate definition errors by
860 treating enum constants as macros. */
861 slot
= htab_find_slot (macro_hash
, name
, INSERT
);
864 *slot
= CONST_CAST (char *, name
);
865 fprintf (go_dump_file
,
866 "const _%s = " HOST_WIDE_INT_PRINT_DEC
"\n",
867 name
, tree_low_cst (TREE_VALUE (element
), 0));
870 pointer_set_insert (container
->decls_seen
, TREE_TYPE (decl
));
871 if (TYPE_CANONICAL (TREE_TYPE (decl
)) != NULL_TREE
)
872 pointer_set_insert (container
->decls_seen
,
873 TYPE_CANONICAL (TREE_TYPE (decl
)));
876 if (DECL_NAME (decl
) != NULL_TREE
)
881 type
= IDENTIFIER_POINTER (DECL_NAME (decl
));
882 /* If type defined already, skip. */
883 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
886 *slot
= CONST_CAST (void *, (const void *) type
);
888 if (!go_format_type (container
, TREE_TYPE (decl
), false, false))
890 fprintf (go_dump_file
, "// ");
891 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
892 *slot
= CONST_CAST (void *, (const void *) type
);
894 fprintf (go_dump_file
, "type _%s ",
895 IDENTIFIER_POINTER (DECL_NAME (decl
)));
896 go_output_type (container
);
897 pointer_set_insert (container
->decls_seen
, decl
);
899 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
904 type
= IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl
))));
905 /* If type defined already, skip. */
906 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
909 *slot
= CONST_CAST (void *, (const void *) type
);
911 if (!go_format_type (container
, TREE_TYPE (decl
), false, false))
913 fprintf (go_dump_file
, "// ");
914 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
915 *slot
= CONST_CAST (void *, (const void *) type
);
917 fprintf (go_dump_file
, "type _%s ",
918 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))));
919 go_output_type (container
);
924 fprintf (go_dump_file
, "\n");
927 /* Output a variable. */
930 go_output_var (struct godump_container
*container
, tree decl
)
934 if (pointer_set_contains (container
->decls_seen
, decl
)
935 || pointer_set_contains (container
->decls_seen
, DECL_NAME (decl
)))
937 pointer_set_insert (container
->decls_seen
, decl
);
938 pointer_set_insert (container
->decls_seen
, DECL_NAME (decl
));
940 is_valid
= go_format_type (container
, TREE_TYPE (decl
), true, false);
942 && htab_find_slot (container
->type_hash
,
943 IDENTIFIER_POINTER (DECL_NAME (decl
)),
946 /* There is already a type with this name, probably from a
947 struct tag. Prefer the type to the variable. */
951 fprintf (go_dump_file
, "// ");
953 fprintf (go_dump_file
, "var _%s ",
954 IDENTIFIER_POINTER (DECL_NAME (decl
)));
955 go_output_type (container
);
956 fprintf (go_dump_file
, "\n");
958 /* Sometimes an extern variable is declared with an unknown struct
960 if (TYPE_NAME (TREE_TYPE (decl
)) != NULL_TREE
961 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
963 tree type_name
= TYPE_NAME (TREE_TYPE (decl
));
964 if (TREE_CODE (type_name
) == IDENTIFIER_NODE
)
965 pointer_set_insert (container
->pot_dummy_types
,
966 IDENTIFIER_POINTER (type_name
));
967 else if (TREE_CODE (type_name
) == TYPE_DECL
)
968 pointer_set_insert (container
->pot_dummy_types
,
969 IDENTIFIER_POINTER (DECL_NAME (type_name
)));
973 /* Build a hash table with the Go keywords. */
975 static const char * const keywords
[] = {
976 "__asm__", "break", "case", "chan", "const", "continue", "default",
977 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
978 "import", "interface", "map", "package", "range", "return", "select",
979 "struct", "switch", "type", "var"
983 keyword_hash_init (struct godump_container
*container
)
986 size_t count
= sizeof (keywords
) / sizeof (keywords
[0]);
989 for (i
= 0; i
< count
; i
++)
991 slot
= htab_find_slot (container
->keyword_hash
, keywords
[i
], INSERT
);
992 *slot
= CONST_CAST (void *, (const void *) keywords
[i
]);
996 /* Traversing the pot_dummy_types and seeing which types are present
997 in the global types hash table and creating dummy definitions if
998 not found. This function is invoked by pointer_set_traverse. */
1001 find_dummy_types (const void *ptr
, void *adata
)
1003 struct godump_container
*data
= (struct godump_container
*) adata
;
1004 const char *type
= (const char *) ptr
;
1007 slot
= htab_find_slot (data
->type_hash
, type
, NO_INSERT
);
1009 fprintf (go_dump_file
, "type _%s struct {}\n", type
);
1013 /* Output symbols. */
1016 go_finish (const char *filename
)
1018 struct godump_container container
;
1022 real_debug_hooks
->finish (filename
);
1024 container
.decls_seen
= pointer_set_create ();
1025 container
.pot_dummy_types
= pointer_set_create ();
1026 container
.type_hash
= htab_create (100, htab_hash_string
,
1027 string_hash_eq
, NULL
);
1028 container
.invalid_hash
= htab_create (10, htab_hash_string
,
1029 string_hash_eq
, NULL
);
1030 container
.keyword_hash
= htab_create (50, htab_hash_string
,
1031 string_hash_eq
, NULL
);
1032 obstack_init (&container
.type_obstack
);
1034 keyword_hash_init (&container
);
1036 FOR_EACH_VEC_ELT (tree
, queue
, ix
, decl
)
1038 switch (TREE_CODE (decl
))
1041 go_output_fndecl (&container
, decl
);
1045 go_output_typedef (&container
, decl
);
1049 go_output_var (&container
, decl
);
1057 /* To emit dummy definitions. */
1058 pointer_set_traverse (container
.pot_dummy_types
, find_dummy_types
,
1059 (void *) &container
);
1061 pointer_set_destroy (container
.decls_seen
);
1062 pointer_set_destroy (container
.pot_dummy_types
);
1063 htab_delete (container
.type_hash
);
1064 htab_delete (container
.invalid_hash
);
1065 htab_delete (container
.keyword_hash
);
1066 obstack_free (&container
.type_obstack
, NULL
);
1070 if (fclose (go_dump_file
) != 0)
1071 error ("could not close Go dump file: %m");
1072 go_dump_file
= NULL
;
1075 /* Set up our hooks. */
1077 const struct gcc_debug_hooks
*
1078 dump_go_spec_init (const char *filename
, const struct gcc_debug_hooks
*hooks
)
1080 go_dump_file
= fopen (filename
, "w");
1081 if (go_dump_file
== NULL
)
1083 error ("could not open Go dump file %qs: %m", filename
);
1087 go_debug_hooks
= *hooks
;
1088 real_debug_hooks
= hooks
;
1090 go_debug_hooks
.finish
= go_finish
;
1091 go_debug_hooks
.define
= go_define
;
1092 go_debug_hooks
.undef
= go_undef
;
1093 go_debug_hooks
.function_decl
= go_function_decl
;
1094 go_debug_hooks
.global_decl
= go_global_decl
;
1095 go_debug_hooks
.type_decl
= go_type_decl
;
1097 macro_hash
= htab_create (100, htab_hash_string
, string_hash_eq
, NULL
);
1099 return &go_debug_hooks
;
1102 #include "gt-godump.h"