1 /* Output Go language descriptions of types.
2 Copyright (C) 2008-2014 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"
39 #include "wide-int-print.h"
41 /* We dump this information from the debug hooks. This gives us a
42 stable and maintainable API to hook into. In order to work
43 correctly when -g is used, we build our own hooks structure which
44 wraps the hooks we need to change. */
46 /* Our debug hooks. This is initialized by dump_go_spec_init. */
48 static struct gcc_debug_hooks go_debug_hooks
;
50 /* The real debug hooks. */
52 static const struct gcc_debug_hooks
*real_debug_hooks
;
54 /* The file where we should write information. */
56 static FILE *go_dump_file
;
58 /* A queue of decls to output. */
60 static GTY(()) vec
<tree
, va_gc
> *queue
;
62 /* A hash table of macros we have seen. */
64 static htab_t macro_hash
;
66 /* The type of a value in macro_hash. */
68 struct macro_hash_value
70 /* The name stored in the hash table. */
72 /* The value of the macro. */
76 /* Calculate the hash value for an entry in the macro hash table. */
79 macro_hash_hashval (const void *val
)
81 const struct macro_hash_value
*mhval
= (const struct macro_hash_value
*) val
;
82 return htab_hash_string (mhval
->name
);
85 /* Compare values in the macro hash table for equality. */
88 macro_hash_eq (const void *v1
, const void *v2
)
90 const struct macro_hash_value
*mhv1
= (const struct macro_hash_value
*) v1
;
91 const struct macro_hash_value
*mhv2
= (const struct macro_hash_value
*) v2
;
92 return strcmp (mhv1
->name
, mhv2
->name
) == 0;
95 /* Free values deleted from the macro hash table. */
98 macro_hash_del (void *v
)
100 struct macro_hash_value
*mhv
= (struct macro_hash_value
*) v
;
101 XDELETEVEC (mhv
->name
);
102 XDELETEVEC (mhv
->value
);
106 /* For the string hash tables. */
109 string_hash_eq (const void *y1
, const void *y2
)
111 return strcmp ((const char *) y1
, (const char *) y2
) == 0;
114 /* A macro definition. */
117 go_define (unsigned int lineno
, const char *buffer
)
120 const char *name_end
;
126 struct macro_hash_value
*mhval
;
131 real_debug_hooks
->define (lineno
, buffer
);
133 /* Skip macro functions. */
134 for (p
= buffer
; *p
!= '\0' && *p
!= ' '; ++p
)
147 copy
= XNEWVEC (char, name_end
- buffer
+ 1);
148 memcpy (copy
, buffer
, name_end
- buffer
);
149 copy
[name_end
- buffer
] = '\0';
151 mhval
= XNEW (struct macro_hash_value
);
155 hashval
= htab_hash_string (copy
);
156 slot
= htab_find_slot_with_hash (macro_hash
, mhval
, hashval
, NO_INSERT
);
158 /* For simplicity, we force all names to be hidden by adding an
159 initial underscore, and let the user undo this as needed. */
160 out_len
= strlen (p
) * 2 + 1;
161 out_buffer
= XNEWVEC (char, out_len
);
164 need_operand
= false;
169 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
170 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
171 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
172 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
174 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
175 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
176 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
177 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
181 /* The start of an identifier. Technically we should also
182 worry about UTF-8 identifiers, but they are not a
183 problem for practical uses of -fdump-go-spec so we
184 don't worry about them. */
187 struct macro_hash_value idval
;
193 while (ISALNUM (*p
) || *p
== '_')
195 n
= XALLOCAVEC (char, p
- start
+ 1);
196 memcpy (n
, start
, p
- start
);
200 if (htab_find (macro_hash
, &idval
) == NULL
)
202 /* This is a reference to a name which was not defined
208 memcpy (q
, start
, p
- start
);
212 need_operand
= false;
220 case '0': case '1': case '2': case '3': case '4':
221 case '5': case '6': case '7': case '8': case '9':
228 if (*p
== '0' && (p
[1] == 'x' || p
[1] == 'X'))
233 while (ISDIGIT (*p
) || *p
== '.' || *p
== 'e' || *p
== 'E'
235 && ((*p
>= 'a' && *p
<= 'f')
236 || (*p
>= 'A' && *p
<= 'F'))))
238 memcpy (q
, start
, p
- start
);
240 while (*p
== 'u' || *p
== 'U' || *p
== 'l' || *p
== 'L'
241 || *p
== 'f' || *p
== 'F'
242 || *p
== 'd' || *p
== 'D')
244 /* Go doesn't use any of these trailing type
249 /* We'll pick up the exponent, if any, as an
253 need_operand
= false;
262 /* Always OK, not part of an operand, presumed to start an
266 need_operand
= false;
270 /* OK if we don't need an operand, and presumed to indicate
279 /* Always OK, but not part of an operand. */
284 case '*': case '/': case '%': case '|': case '&': case '^':
285 /* Must be a binary operator. */
297 /* Must be a binary operator. */
309 /* Must be a binary operator. */
318 /* Must be a unary operator. */
326 /* Must be a binary operand, may be << or >> or <= or >=. */
330 if (*p
== *(p
- 1) || *p
== '=')
337 /* Must be a unary operand, must be translated for Go. */
374 case '0': case '1': case '2': case '3':
375 case '4': case '5': case '6': case '7':
377 while (*p
>= '0' && *p
<= '7')
382 /* Go octal characters are always 3
391 while (ISXDIGIT (*p
))
396 /* Go hex characters are always 2 digits. */
401 case 'a': case 'b': case 'f': case 'n': case 'r':
402 case 't': case 'v': case '\\': case '\'': case '"':
413 if (quote
== '\'' && count
!= 1)
417 need_operand
= false;
430 gcc_assert ((size_t) (q
- out_buffer
) < out_len
);
433 mhval
->value
= out_buffer
;
437 slot
= htab_find_slot_with_hash (macro_hash
, mhval
, hashval
, INSERT
);
438 gcc_assert (slot
!= NULL
&& *slot
== NULL
);
443 macro_hash_del (*slot
);
451 fprintf (go_dump_file
, "// unknowndefine %s\n", buffer
);
453 htab_clear_slot (macro_hash
, slot
);
454 XDELETEVEC (out_buffer
);
461 go_undef (unsigned int lineno
, const char *buffer
)
463 struct macro_hash_value mhval
;
466 real_debug_hooks
->undef (lineno
, buffer
);
468 mhval
.name
= CONST_CAST (char *, buffer
);
470 slot
= htab_find_slot (macro_hash
, &mhval
, NO_INSERT
);
472 htab_clear_slot (macro_hash
, slot
);
475 /* A function or variable decl. */
480 if (!TREE_PUBLIC (decl
)
481 || DECL_IS_BUILTIN (decl
)
482 || DECL_NAME (decl
) == NULL_TREE
)
484 vec_safe_push (queue
, decl
);
487 /* A function decl. */
490 go_function_decl (tree decl
)
492 real_debug_hooks
->function_decl (decl
);
496 /* A global variable decl. */
499 go_global_decl (tree decl
)
501 real_debug_hooks
->global_decl (decl
);
505 /* A type declaration. */
508 go_type_decl (tree decl
, int local
)
510 real_debug_hooks
->type_decl (decl
, local
);
512 if (local
|| DECL_IS_BUILTIN (decl
))
514 if (DECL_NAME (decl
) == NULL_TREE
515 && (TYPE_NAME (TREE_TYPE (decl
)) == NULL_TREE
516 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl
))) != IDENTIFIER_NODE
)
517 && TREE_CODE (TREE_TYPE (decl
)) != ENUMERAL_TYPE
)
519 vec_safe_push (queue
, decl
);
522 /* A container for the data we pass around when generating information
523 at the end of the compilation. */
525 struct godump_container
527 /* DECLs that we have already seen. */
528 struct pointer_set_t
*decls_seen
;
530 /* Types which may potentially have to be defined as dummy
532 struct pointer_set_t
*pot_dummy_types
;
537 /* Global type definitions. */
543 /* Obstack used to write out a type definition. */
544 struct obstack type_obstack
;
547 /* Append an IDENTIFIER_NODE to OB. */
550 go_append_string (struct obstack
*ob
, tree id
)
552 obstack_grow (ob
, IDENTIFIER_POINTER (id
), IDENTIFIER_LENGTH (id
));
555 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
556 USE_TYPE_NAME is true if we can simply use a type name here without
557 needing to define it. IS_FUNC_OK is true if we can output a func
558 type here; the "func" keyword will already have been added. Return
559 true if the type can be represented in Go, false otherwise. */
562 go_format_type (struct godump_container
*container
, tree type
,
563 bool use_type_name
, bool is_func_ok
)
569 ob
= &container
->type_obstack
;
571 if (TYPE_NAME (type
) != NULL_TREE
572 && (pointer_set_contains (container
->decls_seen
, type
)
573 || pointer_set_contains (container
->decls_seen
, TYPE_NAME (type
)))
574 && (AGGREGATE_TYPE_P (type
)
575 || POINTER_TYPE_P (type
)
576 || TREE_CODE (type
) == FUNCTION_TYPE
))
581 name
= TYPE_IDENTIFIER (type
);
583 slot
= htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (name
),
588 obstack_1grow (ob
, '_');
589 go_append_string (ob
, name
);
593 pointer_set_insert (container
->decls_seen
, type
);
595 switch (TREE_CODE (type
))
598 obstack_grow (ob
, "int", 3);
605 slot
= htab_find_slot (container
->invalid_hash
,
606 IDENTIFIER_POINTER (DECL_NAME (type
)),
611 obstack_1grow (ob
, '_');
612 go_append_string (ob
, DECL_NAME (type
));
621 switch (TYPE_PRECISION (type
))
624 s
= TYPE_UNSIGNED (type
) ? "uint8" : "int8";
627 s
= TYPE_UNSIGNED (type
) ? "uint16" : "int16";
630 s
= TYPE_UNSIGNED (type
) ? "uint32" : "int32";
633 s
= TYPE_UNSIGNED (type
) ? "uint64" : "int64";
636 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
637 TYPE_PRECISION (type
),
638 TYPE_UNSIGNED (type
) ? "u" : "");
643 obstack_grow (ob
, s
, strlen (s
));
652 switch (TYPE_PRECISION (type
))
661 snprintf (buf
, sizeof buf
, "INVALID-float-%u",
662 TYPE_PRECISION (type
));
667 obstack_grow (ob
, s
, strlen (s
));
672 obstack_grow (ob
, "bool", 4);
677 && TYPE_NAME (TREE_TYPE (type
)) != NULL_TREE
678 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
))
679 || (POINTER_TYPE_P (TREE_TYPE (type
))
680 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type
)))
686 name
= TYPE_IDENTIFIER (TREE_TYPE (type
));
688 slot
= htab_find_slot (container
->invalid_hash
,
689 IDENTIFIER_POINTER (name
), NO_INSERT
);
693 obstack_grow (ob
, "*_", 2);
694 go_append_string (ob
, name
);
696 /* The pointer here can be used without the struct or union
697 definition. So this struct or union is a potential dummy
699 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
)))
700 pointer_set_insert (container
->pot_dummy_types
,
701 IDENTIFIER_POINTER (name
));
705 if (TREE_CODE (TREE_TYPE (type
)) == FUNCTION_TYPE
)
706 obstack_grow (ob
, "func", 4);
708 obstack_1grow (ob
, '*');
709 if (VOID_TYPE_P (TREE_TYPE (type
)))
710 obstack_grow (ob
, "byte", 4);
713 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
,
720 obstack_1grow (ob
, '[');
721 if (TYPE_DOMAIN (type
) != NULL_TREE
722 && TREE_CODE (TYPE_DOMAIN (type
)) == INTEGER_TYPE
723 && TYPE_MIN_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
724 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
725 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == 0
726 && TYPE_MAX_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
727 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
728 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))))
732 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
"+1",
733 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))));
734 obstack_grow (ob
, buf
, strlen (buf
));
736 obstack_1grow (ob
, ']');
737 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
, false))
747 obstack_grow (ob
, "struct { ", 9);
749 for (field
= TYPE_FIELDS (type
);
751 field
= TREE_CHAIN (field
))
753 struct obstack hold_type_obstack
;
756 if (TREE_CODE (type
) == UNION_TYPE
)
758 hold_type_obstack
= container
->type_obstack
;
759 obstack_init (&container
->type_obstack
);
764 if (DECL_NAME (field
) == NULL
)
768 obstack_grow (ob
, "Godump_", 7);
769 snprintf (buf
, sizeof buf
, "%d", i
);
770 obstack_grow (ob
, buf
, strlen (buf
));
775 const char *var_name
;
778 /* Start variable name with an underscore if a keyword. */
779 var_name
= IDENTIFIER_POINTER (DECL_NAME (field
));
780 slot
= htab_find_slot (container
->keyword_hash
, var_name
,
783 obstack_1grow (ob
, '_');
784 go_append_string (ob
, DECL_NAME (field
));
786 obstack_1grow (ob
, ' ');
787 if (DECL_BIT_FIELD (field
))
789 obstack_grow (ob
, "INVALID-bit-field", 17);
794 /* Do not expand type if a record or union type or a
796 if (TYPE_NAME (TREE_TYPE (field
)) != NULL_TREE
797 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field
))
798 || (POINTER_TYPE_P (TREE_TYPE (field
))
799 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field
)))
805 name
= TYPE_IDENTIFIER (TREE_TYPE (field
));
807 slot
= htab_find_slot (container
->invalid_hash
,
808 IDENTIFIER_POINTER (name
),
813 obstack_1grow (ob
, '_');
814 go_append_string (ob
, name
);
818 if (!go_format_type (container
, TREE_TYPE (field
), true,
823 obstack_grow (ob
, "; ", 2);
825 /* Only output the first successful field of a union, and
826 hope for the best. */
827 if (TREE_CODE (type
) == UNION_TYPE
)
829 if (!field_ok
&& TREE_CHAIN (field
) == NULL_TREE
)
838 sz
= obstack_object_size (&container
->type_obstack
);
839 obstack_grow (&hold_type_obstack
,
840 obstack_base (&container
->type_obstack
),
843 obstack_free (&container
->type_obstack
, NULL
);
844 container
->type_obstack
= hold_type_obstack
;
854 obstack_1grow (ob
, '}');
863 function_args_iterator iter
;
866 /* Go has no way to write a type which is a function but not a
867 pointer to a function. */
870 obstack_grow (ob
, "func*", 5);
874 obstack_1grow (ob
, '(');
875 is_varargs
= stdarg_p (type
);
877 FOREACH_FUNCTION_ARGS (type
, arg_type
, iter
)
879 if (VOID_TYPE_P (arg_type
))
882 obstack_grow (ob
, ", ", 2);
883 if (!go_format_type (container
, arg_type
, true, false))
889 if (prototype_p (type
))
890 obstack_grow (ob
, ", ", 2);
891 obstack_grow (ob
, "...interface{}", 14);
893 obstack_1grow (ob
, ')');
895 result
= TREE_TYPE (type
);
896 if (!VOID_TYPE_P (result
))
898 obstack_1grow (ob
, ' ');
899 if (!go_format_type (container
, result
, use_type_name
, false))
906 obstack_grow (ob
, "INVALID-type", 12);
914 /* Output the type which was built on the type obstack, and then free
918 go_output_type (struct godump_container
*container
)
922 ob
= &container
->type_obstack
;
923 obstack_1grow (ob
, '\0');
924 fputs (obstack_base (ob
), go_dump_file
);
925 obstack_free (ob
, obstack_base (ob
));
928 /* Output a function declaration. */
931 go_output_fndecl (struct godump_container
*container
, tree decl
)
933 if (!go_format_type (container
, TREE_TYPE (decl
), false, true))
934 fprintf (go_dump_file
, "// ");
935 fprintf (go_dump_file
, "func _%s ",
936 IDENTIFIER_POINTER (DECL_NAME (decl
)));
937 go_output_type (container
);
938 fprintf (go_dump_file
, " __asm__(\"%s\")\n",
939 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
)));
942 /* Output a typedef or something like a struct definition. */
945 go_output_typedef (struct godump_container
*container
, tree decl
)
947 /* If we have an enum type, output the enum constants
949 if (TREE_CODE (TREE_TYPE (decl
)) == ENUMERAL_TYPE
950 && TYPE_SIZE (TREE_TYPE (decl
)) != 0
951 && !pointer_set_contains (container
->decls_seen
, TREE_TYPE (decl
))
952 && (TYPE_CANONICAL (TREE_TYPE (decl
)) == NULL_TREE
953 || !pointer_set_contains (container
->decls_seen
,
954 TYPE_CANONICAL (TREE_TYPE (decl
)))))
958 for (element
= TYPE_VALUES (TREE_TYPE (decl
));
959 element
!= NULL_TREE
;
960 element
= TREE_CHAIN (element
))
963 struct macro_hash_value
*mhval
;
965 char buf
[WIDE_INT_PRINT_BUFFER_SIZE
];
967 name
= IDENTIFIER_POINTER (TREE_PURPOSE (element
));
969 /* Sometimes a name will be defined as both an enum constant
970 and a macro. Avoid duplicate definition errors by
971 treating enum constants as macros. */
972 mhval
= XNEW (struct macro_hash_value
);
973 mhval
->name
= xstrdup (name
);
975 slot
= htab_find_slot (macro_hash
, mhval
, INSERT
);
977 macro_hash_del (*slot
);
979 if (tree_fits_shwi_p (TREE_VALUE (element
)))
980 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
,
981 tree_to_shwi (TREE_VALUE (element
)));
982 else if (tree_fits_uhwi_p (TREE_VALUE (element
)))
983 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_UNSIGNED
,
984 tree_to_uhwi (TREE_VALUE (element
)));
986 print_hex (element
, buf
);
988 mhval
->value
= xstrdup (buf
);
991 pointer_set_insert (container
->decls_seen
, TREE_TYPE (decl
));
992 if (TYPE_CANONICAL (TREE_TYPE (decl
)) != NULL_TREE
)
993 pointer_set_insert (container
->decls_seen
,
994 TYPE_CANONICAL (TREE_TYPE (decl
)));
997 if (DECL_NAME (decl
) != NULL_TREE
)
1002 type
= IDENTIFIER_POINTER (DECL_NAME (decl
));
1003 /* If type defined already, skip. */
1004 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1007 *slot
= CONST_CAST (void *, (const void *) type
);
1009 if (!go_format_type (container
, TREE_TYPE (decl
), false, false))
1011 fprintf (go_dump_file
, "// ");
1012 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1013 *slot
= CONST_CAST (void *, (const void *) type
);
1015 fprintf (go_dump_file
, "type _%s ",
1016 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1017 go_output_type (container
);
1019 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1021 HOST_WIDE_INT size
= int_size_in_bytes (TREE_TYPE (decl
));
1024 fprintf (go_dump_file
,
1025 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1026 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1030 pointer_set_insert (container
->decls_seen
, decl
);
1032 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1038 type
= IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl
))));
1039 /* If type defined already, skip. */
1040 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1043 *slot
= CONST_CAST (void *, (const void *) type
);
1045 if (!go_format_type (container
, TREE_TYPE (decl
), false, false))
1047 fprintf (go_dump_file
, "// ");
1048 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1049 *slot
= CONST_CAST (void *, (const void *) type
);
1051 fprintf (go_dump_file
, "type _%s ",
1052 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))));
1053 go_output_type (container
);
1055 size
= int_size_in_bytes (TREE_TYPE (decl
));
1057 fprintf (go_dump_file
,
1058 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1059 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))),
1065 fprintf (go_dump_file
, "\n");
1068 /* Output a variable. */
1071 go_output_var (struct godump_container
*container
, tree decl
)
1075 if (pointer_set_contains (container
->decls_seen
, decl
)
1076 || pointer_set_contains (container
->decls_seen
, DECL_NAME (decl
)))
1078 pointer_set_insert (container
->decls_seen
, decl
);
1079 pointer_set_insert (container
->decls_seen
, DECL_NAME (decl
));
1081 is_valid
= go_format_type (container
, TREE_TYPE (decl
), true, false);
1083 && htab_find_slot (container
->type_hash
,
1084 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1087 /* There is already a type with this name, probably from a
1088 struct tag. Prefer the type to the variable. */
1092 fprintf (go_dump_file
, "// ");
1094 fprintf (go_dump_file
, "var _%s ",
1095 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1096 go_output_type (container
);
1097 fprintf (go_dump_file
, "\n");
1099 /* Sometimes an extern variable is declared with an unknown struct
1101 if (TYPE_NAME (TREE_TYPE (decl
)) != NULL_TREE
1102 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1104 tree type_name
= TYPE_NAME (TREE_TYPE (decl
));
1105 if (TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1106 pointer_set_insert (container
->pot_dummy_types
,
1107 IDENTIFIER_POINTER (type_name
));
1108 else if (TREE_CODE (type_name
) == TYPE_DECL
)
1109 pointer_set_insert (container
->pot_dummy_types
,
1110 IDENTIFIER_POINTER (DECL_NAME (type_name
)));
1114 /* Output the final value of a preprocessor macro or enum constant.
1115 This is called via htab_traverse_noresize. */
1118 go_print_macro (void **slot
, void *arg ATTRIBUTE_UNUSED
)
1120 struct macro_hash_value
*mhval
= (struct macro_hash_value
*) *slot
;
1121 fprintf (go_dump_file
, "const _%s = %s\n", mhval
->name
, mhval
->value
);
1125 /* Build a hash table with the Go keywords. */
1127 static const char * const keywords
[] = {
1128 "__asm__", "break", "case", "chan", "const", "continue", "default",
1129 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1130 "import", "interface", "map", "package", "range", "return", "select",
1131 "struct", "switch", "type", "var"
1135 keyword_hash_init (struct godump_container
*container
)
1138 size_t count
= sizeof (keywords
) / sizeof (keywords
[0]);
1141 for (i
= 0; i
< count
; i
++)
1143 slot
= htab_find_slot (container
->keyword_hash
, keywords
[i
], INSERT
);
1144 *slot
= CONST_CAST (void *, (const void *) keywords
[i
]);
1148 /* Traversing the pot_dummy_types and seeing which types are present
1149 in the global types hash table and creating dummy definitions if
1150 not found. This function is invoked by pointer_set_traverse. */
1153 find_dummy_types (const void *ptr
, void *adata
)
1155 struct godump_container
*data
= (struct godump_container
*) adata
;
1156 const char *type
= (const char *) ptr
;
1160 slot
= htab_find_slot (data
->type_hash
, type
, NO_INSERT
);
1161 islot
= htab_find_slot (data
->invalid_hash
, type
, NO_INSERT
);
1162 if (slot
== NULL
|| islot
!= NULL
)
1163 fprintf (go_dump_file
, "type _%s struct {}\n", type
);
1167 /* Output symbols. */
1170 go_finish (const char *filename
)
1172 struct godump_container container
;
1176 real_debug_hooks
->finish (filename
);
1178 container
.decls_seen
= pointer_set_create ();
1179 container
.pot_dummy_types
= pointer_set_create ();
1180 container
.type_hash
= htab_create (100, htab_hash_string
,
1181 string_hash_eq
, NULL
);
1182 container
.invalid_hash
= htab_create (10, htab_hash_string
,
1183 string_hash_eq
, NULL
);
1184 container
.keyword_hash
= htab_create (50, htab_hash_string
,
1185 string_hash_eq
, NULL
);
1186 obstack_init (&container
.type_obstack
);
1188 keyword_hash_init (&container
);
1190 FOR_EACH_VEC_SAFE_ELT (queue
, ix
, decl
)
1192 switch (TREE_CODE (decl
))
1195 go_output_fndecl (&container
, decl
);
1199 go_output_typedef (&container
, decl
);
1203 go_output_var (&container
, decl
);
1211 htab_traverse_noresize (macro_hash
, go_print_macro
, NULL
);
1213 /* To emit dummy definitions. */
1214 pointer_set_traverse (container
.pot_dummy_types
, find_dummy_types
,
1215 (void *) &container
);
1217 pointer_set_destroy (container
.decls_seen
);
1218 pointer_set_destroy (container
.pot_dummy_types
);
1219 htab_delete (container
.type_hash
);
1220 htab_delete (container
.invalid_hash
);
1221 htab_delete (container
.keyword_hash
);
1222 obstack_free (&container
.type_obstack
, NULL
);
1226 if (fclose (go_dump_file
) != 0)
1227 error ("could not close Go dump file: %m");
1228 go_dump_file
= NULL
;
1231 /* Set up our hooks. */
1233 const struct gcc_debug_hooks
*
1234 dump_go_spec_init (const char *filename
, const struct gcc_debug_hooks
*hooks
)
1236 go_dump_file
= fopen (filename
, "w");
1237 if (go_dump_file
== NULL
)
1239 error ("could not open Go dump file %qs: %m", filename
);
1243 go_debug_hooks
= *hooks
;
1244 real_debug_hooks
= hooks
;
1246 go_debug_hooks
.finish
= go_finish
;
1247 go_debug_hooks
.define
= go_define
;
1248 go_debug_hooks
.undef
= go_undef
;
1249 go_debug_hooks
.function_decl
= go_function_decl
;
1250 go_debug_hooks
.global_decl
= go_global_decl
;
1251 go_debug_hooks
.type_decl
= go_type_decl
;
1253 macro_hash
= htab_create (100, macro_hash_hashval
, macro_hash_eq
,
1256 return &go_debug_hooks
;
1259 #include "gt-godump.h"