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
, "const _%s = ", name
);
924 if (host_integerp (TREE_VALUE (element
), 0))
925 fprintf (go_dump_file
, HOST_WIDE_INT_PRINT_DEC
,
926 tree_low_cst (TREE_VALUE (element
), 0));
927 else if (host_integerp (TREE_VALUE (element
), 1))
928 fprintf (go_dump_file
, HOST_WIDE_INT_PRINT_UNSIGNED
,
929 ((unsigned HOST_WIDE_INT
)
930 tree_low_cst (TREE_VALUE (element
), 1)));
932 fprintf (go_dump_file
, HOST_WIDE_INT_PRINT_DOUBLE_HEX
,
933 ((unsigned HOST_WIDE_INT
)
934 TREE_INT_CST_HIGH (TREE_VALUE (element
))),
935 TREE_INT_CST_LOW (TREE_VALUE (element
)));
936 fprintf (go_dump_file
, "\n");
939 pointer_set_insert (container
->decls_seen
, TREE_TYPE (decl
));
940 if (TYPE_CANONICAL (TREE_TYPE (decl
)) != NULL_TREE
)
941 pointer_set_insert (container
->decls_seen
,
942 TYPE_CANONICAL (TREE_TYPE (decl
)));
945 if (DECL_NAME (decl
) != NULL_TREE
)
950 type
= IDENTIFIER_POINTER (DECL_NAME (decl
));
951 /* If type defined already, skip. */
952 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
955 *slot
= CONST_CAST (void *, (const void *) type
);
957 if (!go_format_type (container
, TREE_TYPE (decl
), false, false))
959 fprintf (go_dump_file
, "// ");
960 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
961 *slot
= CONST_CAST (void *, (const void *) type
);
963 fprintf (go_dump_file
, "type _%s ",
964 IDENTIFIER_POINTER (DECL_NAME (decl
)));
965 go_output_type (container
);
966 pointer_set_insert (container
->decls_seen
, decl
);
968 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
973 type
= IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl
))));
974 /* If type defined already, skip. */
975 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
978 *slot
= CONST_CAST (void *, (const void *) type
);
980 if (!go_format_type (container
, TREE_TYPE (decl
), false, false))
982 fprintf (go_dump_file
, "// ");
983 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
984 *slot
= CONST_CAST (void *, (const void *) type
);
986 fprintf (go_dump_file
, "type _%s ",
987 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))));
988 go_output_type (container
);
993 fprintf (go_dump_file
, "\n");
996 /* Output a variable. */
999 go_output_var (struct godump_container
*container
, tree decl
)
1003 if (pointer_set_contains (container
->decls_seen
, decl
)
1004 || pointer_set_contains (container
->decls_seen
, DECL_NAME (decl
)))
1006 pointer_set_insert (container
->decls_seen
, decl
);
1007 pointer_set_insert (container
->decls_seen
, DECL_NAME (decl
));
1009 is_valid
= go_format_type (container
, TREE_TYPE (decl
), true, false);
1011 && htab_find_slot (container
->type_hash
,
1012 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1015 /* There is already a type with this name, probably from a
1016 struct tag. Prefer the type to the variable. */
1020 fprintf (go_dump_file
, "// ");
1022 fprintf (go_dump_file
, "var _%s ",
1023 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1024 go_output_type (container
);
1025 fprintf (go_dump_file
, "\n");
1027 /* Sometimes an extern variable is declared with an unknown struct
1029 if (TYPE_NAME (TREE_TYPE (decl
)) != NULL_TREE
1030 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1032 tree type_name
= TYPE_NAME (TREE_TYPE (decl
));
1033 if (TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1034 pointer_set_insert (container
->pot_dummy_types
,
1035 IDENTIFIER_POINTER (type_name
));
1036 else if (TREE_CODE (type_name
) == TYPE_DECL
)
1037 pointer_set_insert (container
->pot_dummy_types
,
1038 IDENTIFIER_POINTER (DECL_NAME (type_name
)));
1042 /* Build a hash table with the Go keywords. */
1044 static const char * const keywords
[] = {
1045 "__asm__", "break", "case", "chan", "const", "continue", "default",
1046 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1047 "import", "interface", "map", "package", "range", "return", "select",
1048 "struct", "switch", "type", "var"
1052 keyword_hash_init (struct godump_container
*container
)
1055 size_t count
= sizeof (keywords
) / sizeof (keywords
[0]);
1058 for (i
= 0; i
< count
; i
++)
1060 slot
= htab_find_slot (container
->keyword_hash
, keywords
[i
], INSERT
);
1061 *slot
= CONST_CAST (void *, (const void *) keywords
[i
]);
1065 /* Traversing the pot_dummy_types and seeing which types are present
1066 in the global types hash table and creating dummy definitions if
1067 not found. This function is invoked by pointer_set_traverse. */
1070 find_dummy_types (const void *ptr
, void *adata
)
1072 struct godump_container
*data
= (struct godump_container
*) adata
;
1073 const char *type
= (const char *) ptr
;
1076 slot
= htab_find_slot (data
->type_hash
, type
, NO_INSERT
);
1078 fprintf (go_dump_file
, "type _%s struct {}\n", type
);
1082 /* Output symbols. */
1085 go_finish (const char *filename
)
1087 struct godump_container container
;
1091 real_debug_hooks
->finish (filename
);
1093 container
.decls_seen
= pointer_set_create ();
1094 container
.pot_dummy_types
= pointer_set_create ();
1095 container
.type_hash
= htab_create (100, htab_hash_string
,
1096 string_hash_eq
, NULL
);
1097 container
.invalid_hash
= htab_create (10, htab_hash_string
,
1098 string_hash_eq
, NULL
);
1099 container
.keyword_hash
= htab_create (50, htab_hash_string
,
1100 string_hash_eq
, NULL
);
1101 obstack_init (&container
.type_obstack
);
1103 keyword_hash_init (&container
);
1105 FOR_EACH_VEC_ELT (tree
, queue
, ix
, decl
)
1107 switch (TREE_CODE (decl
))
1110 go_output_fndecl (&container
, decl
);
1114 go_output_typedef (&container
, decl
);
1118 go_output_var (&container
, decl
);
1126 /* To emit dummy definitions. */
1127 pointer_set_traverse (container
.pot_dummy_types
, find_dummy_types
,
1128 (void *) &container
);
1130 pointer_set_destroy (container
.decls_seen
);
1131 pointer_set_destroy (container
.pot_dummy_types
);
1132 htab_delete (container
.type_hash
);
1133 htab_delete (container
.invalid_hash
);
1134 htab_delete (container
.keyword_hash
);
1135 obstack_free (&container
.type_obstack
, NULL
);
1139 if (fclose (go_dump_file
) != 0)
1140 error ("could not close Go dump file: %m");
1141 go_dump_file
= NULL
;
1144 /* Set up our hooks. */
1146 const struct gcc_debug_hooks
*
1147 dump_go_spec_init (const char *filename
, const struct gcc_debug_hooks
*hooks
)
1149 go_dump_file
= fopen (filename
, "w");
1150 if (go_dump_file
== NULL
)
1152 error ("could not open Go dump file %qs: %m", filename
);
1156 go_debug_hooks
= *hooks
;
1157 real_debug_hooks
= hooks
;
1159 go_debug_hooks
.finish
= go_finish
;
1160 go_debug_hooks
.define
= go_define
;
1161 go_debug_hooks
.undef
= go_undef
;
1162 go_debug_hooks
.function_decl
= go_function_decl
;
1163 go_debug_hooks
.global_decl
= go_global_decl
;
1164 go_debug_hooks
.type_decl
= go_type_decl
;
1166 macro_hash
= htab_create (100, htab_hash_string
, string_hash_eq
, NULL
);
1168 return &go_debug_hooks
;
1171 #include "gt-godump.h"