1 /* Output Go language descriptions of types.
2 Copyright (C) 2008-2013 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
, va_gc
> *queue
;
61 /* A hash table of macros we have seen. */
63 static htab_t macro_hash
;
65 /* The type of a value in macro_hash. */
67 struct macro_hash_value
69 /* The name stored in the hash table. */
71 /* The value of the macro. */
75 /* Calculate the hash value for an entry in the macro hash table. */
78 macro_hash_hashval (const void *val
)
80 const struct macro_hash_value
*mhval
= (const struct macro_hash_value
*) val
;
81 return htab_hash_string (mhval
->name
);
84 /* Compare values in the macro hash table for equality. */
87 macro_hash_eq (const void *v1
, const void *v2
)
89 const struct macro_hash_value
*mhv1
= (const struct macro_hash_value
*) v1
;
90 const struct macro_hash_value
*mhv2
= (const struct macro_hash_value
*) v2
;
91 return strcmp (mhv1
->name
, mhv2
->name
) == 0;
94 /* Free values deleted from the macro hash table. */
97 macro_hash_del (void *v
)
99 struct macro_hash_value
*mhv
= (struct macro_hash_value
*) v
;
100 XDELETEVEC (mhv
->name
);
101 XDELETEVEC (mhv
->value
);
105 /* For the string hash tables. */
108 string_hash_eq (const void *y1
, const void *y2
)
110 return strcmp ((const char *) y1
, (const char *) y2
) == 0;
113 /* A macro definition. */
116 go_define (unsigned int lineno
, const char *buffer
)
119 const char *name_end
;
125 struct macro_hash_value
*mhval
;
130 real_debug_hooks
->define (lineno
, buffer
);
132 /* Skip macro functions. */
133 for (p
= buffer
; *p
!= '\0' && *p
!= ' '; ++p
)
146 copy
= XNEWVEC (char, name_end
- buffer
+ 1);
147 memcpy (copy
, buffer
, name_end
- buffer
);
148 copy
[name_end
- buffer
] = '\0';
150 mhval
= XNEW (struct macro_hash_value
);
154 hashval
= htab_hash_string (copy
);
155 slot
= htab_find_slot_with_hash (macro_hash
, mhval
, hashval
, NO_INSERT
);
157 /* For simplicity, we force all names to be hidden by adding an
158 initial underscore, and let the user undo this as needed. */
159 out_len
= strlen (p
) * 2 + 1;
160 out_buffer
= XNEWVEC (char, out_len
);
163 need_operand
= false;
168 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
169 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
170 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
171 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
173 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
174 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
175 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
176 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
180 /* The start of an identifier. Technically we should also
181 worry about UTF-8 identifiers, but they are not a
182 problem for practical uses of -fdump-go-spec so we
183 don't worry about them. */
186 struct macro_hash_value idval
;
192 while (ISALNUM (*p
) || *p
== '_')
194 n
= XALLOCAVEC (char, p
- start
+ 1);
195 memcpy (n
, start
, p
- start
);
199 if (htab_find (macro_hash
, &idval
) == NULL
)
201 /* This is a reference to a name which was not defined
207 memcpy (q
, start
, p
- start
);
211 need_operand
= false;
219 case '0': case '1': case '2': case '3': case '4':
220 case '5': case '6': case '7': case '8': case '9':
227 if (*p
== '0' && (p
[1] == 'x' || p
[1] == 'X'))
232 while (ISDIGIT (*p
) || *p
== '.' || *p
== 'e' || *p
== 'E'
234 && ((*p
>= 'a' && *p
<= 'f')
235 || (*p
>= 'A' && *p
<= 'F'))))
237 memcpy (q
, start
, p
- start
);
239 while (*p
== 'u' || *p
== 'U' || *p
== 'l' || *p
== 'L'
240 || *p
== 'f' || *p
== 'F'
241 || *p
== 'd' || *p
== 'D')
243 /* Go doesn't use any of these trailing type
248 /* We'll pick up the exponent, if any, as an
252 need_operand
= false;
261 /* Always OK, not part of an operand, presumed to start an
265 need_operand
= false;
269 /* OK if we don't need an operand, and presumed to indicate
278 /* Always OK, but not part of an operand. */
283 case '*': case '/': case '%': case '|': case '&': case '^':
284 /* Must be a binary operator. */
296 /* Must be a binary operator. */
308 /* Must be a binary operator. */
317 /* Must be a unary operator. */
325 /* Must be a binary operand, may be << or >> or <= or >=. */
329 if (*p
== *(p
- 1) || *p
== '=')
336 /* Must be a unary operand, must be translated for Go. */
373 case '0': case '1': case '2': case '3':
374 case '4': case '5': case '6': case '7':
376 while (*p
>= '0' && *p
<= '7')
381 /* Go octal characters are always 3
390 while (ISXDIGIT (*p
))
395 /* Go hex characters are always 2 digits. */
400 case 'a': case 'b': case 'f': case 'n': case 'r':
401 case 't': case 'v': case '\\': case '\'': case '"':
412 if (quote
== '\'' && count
!= 1)
416 need_operand
= false;
429 gcc_assert ((size_t) (q
- out_buffer
) < out_len
);
432 mhval
->value
= out_buffer
;
436 slot
= htab_find_slot_with_hash (macro_hash
, mhval
, hashval
, INSERT
);
437 gcc_assert (slot
!= NULL
&& *slot
== NULL
);
442 macro_hash_del (*slot
);
450 fprintf (go_dump_file
, "// unknowndefine %s\n", buffer
);
452 htab_clear_slot (macro_hash
, slot
);
453 XDELETEVEC (out_buffer
);
460 go_undef (unsigned int lineno
, const char *buffer
)
462 struct macro_hash_value mhval
;
465 real_debug_hooks
->undef (lineno
, buffer
);
467 mhval
.name
= CONST_CAST (char *, buffer
);
469 slot
= htab_find_slot (macro_hash
, &mhval
, NO_INSERT
);
471 htab_clear_slot (macro_hash
, slot
);
474 /* A function or variable decl. */
479 if (!TREE_PUBLIC (decl
)
480 || DECL_IS_BUILTIN (decl
)
481 || DECL_NAME (decl
) == NULL_TREE
)
483 vec_safe_push (queue
, decl
);
486 /* A function decl. */
489 go_function_decl (tree decl
)
491 real_debug_hooks
->function_decl (decl
);
495 /* A global variable decl. */
498 go_global_decl (tree decl
)
500 real_debug_hooks
->global_decl (decl
);
504 /* A type declaration. */
507 go_type_decl (tree decl
, int local
)
509 real_debug_hooks
->type_decl (decl
, local
);
511 if (local
|| DECL_IS_BUILTIN (decl
))
513 if (DECL_NAME (decl
) == NULL_TREE
514 && (TYPE_NAME (TREE_TYPE (decl
)) == NULL_TREE
515 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl
))) != IDENTIFIER_NODE
)
516 && TREE_CODE (TREE_TYPE (decl
)) != ENUMERAL_TYPE
)
518 vec_safe_push (queue
, decl
);
521 /* A container for the data we pass around when generating information
522 at the end of the compilation. */
524 struct godump_container
526 /* DECLs that we have already seen. */
527 struct pointer_set_t
*decls_seen
;
529 /* Types which may potentially have to be defined as dummy
531 struct pointer_set_t
*pot_dummy_types
;
536 /* Global type definitions. */
542 /* Obstack used to write out a type definition. */
543 struct obstack type_obstack
;
546 /* Append an IDENTIFIER_NODE to OB. */
549 go_append_string (struct obstack
*ob
, tree id
)
551 obstack_grow (ob
, IDENTIFIER_POINTER (id
), IDENTIFIER_LENGTH (id
));
554 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
555 USE_TYPE_NAME is true if we can simply use a type name here without
556 needing to define it. IS_FUNC_OK is true if we can output a func
557 type here; the "func" keyword will already have been added. Return
558 true if the type can be represented in Go, false otherwise. */
561 go_format_type (struct godump_container
*container
, tree type
,
562 bool use_type_name
, bool is_func_ok
)
568 ob
= &container
->type_obstack
;
570 if (TYPE_NAME (type
) != NULL_TREE
571 && (pointer_set_contains (container
->decls_seen
, type
)
572 || pointer_set_contains (container
->decls_seen
, TYPE_NAME (type
)))
573 && (AGGREGATE_TYPE_P (type
)
574 || POINTER_TYPE_P (type
)
575 || TREE_CODE (type
) == FUNCTION_TYPE
))
580 name
= TYPE_NAME (type
);
581 if (TREE_CODE (name
) == TYPE_DECL
)
582 name
= DECL_NAME (name
);
584 slot
= htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (name
),
589 obstack_1grow (ob
, '_');
590 go_append_string (ob
, name
);
594 pointer_set_insert (container
->decls_seen
, type
);
596 switch (TREE_CODE (type
))
599 obstack_grow (ob
, "int", 3);
606 slot
= htab_find_slot (container
->invalid_hash
,
607 IDENTIFIER_POINTER (DECL_NAME (type
)),
612 obstack_1grow (ob
, '_');
613 go_append_string (ob
, DECL_NAME (type
));
622 switch (TYPE_PRECISION (type
))
625 s
= TYPE_UNSIGNED (type
) ? "uint8" : "int8";
628 s
= TYPE_UNSIGNED (type
) ? "uint16" : "int16";
631 s
= TYPE_UNSIGNED (type
) ? "uint32" : "int32";
634 s
= TYPE_UNSIGNED (type
) ? "uint64" : "int64";
637 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
638 TYPE_PRECISION (type
),
639 TYPE_UNSIGNED (type
) ? "u" : "");
644 obstack_grow (ob
, s
, strlen (s
));
653 switch (TYPE_PRECISION (type
))
662 snprintf (buf
, sizeof buf
, "INVALID-float-%u",
663 TYPE_PRECISION (type
));
668 obstack_grow (ob
, s
, strlen (s
));
673 obstack_grow (ob
, "bool", 4);
678 && TYPE_NAME (TREE_TYPE (type
)) != NULL_TREE
679 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
))
680 || (POINTER_TYPE_P (TREE_TYPE (type
))
681 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type
)))
687 name
= TYPE_NAME (TREE_TYPE (type
));
688 if (TREE_CODE (name
) == TYPE_DECL
)
689 name
= DECL_NAME (name
);
691 slot
= htab_find_slot (container
->invalid_hash
,
692 IDENTIFIER_POINTER (name
), NO_INSERT
);
696 obstack_grow (ob
, "*_", 2);
697 go_append_string (ob
, name
);
699 /* The pointer here can be used without the struct or union
700 definition. So this struct or union is a potential dummy
702 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
)))
703 pointer_set_insert (container
->pot_dummy_types
,
704 IDENTIFIER_POINTER (name
));
708 if (TREE_CODE (TREE_TYPE (type
)) == FUNCTION_TYPE
)
709 obstack_grow (ob
, "func", 4);
711 obstack_1grow (ob
, '*');
712 if (VOID_TYPE_P (TREE_TYPE (type
)))
713 obstack_grow (ob
, "byte", 4);
716 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
,
723 obstack_1grow (ob
, '[');
724 if (TYPE_DOMAIN (type
) != NULL_TREE
725 && TREE_CODE (TYPE_DOMAIN (type
)) == INTEGER_TYPE
726 && TYPE_MIN_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
727 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
728 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == 0
729 && TYPE_MAX_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
730 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
731 && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type
)), 0))
735 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
"+1",
736 tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type
)), 0));
737 obstack_grow (ob
, buf
, strlen (buf
));
739 obstack_1grow (ob
, ']');
740 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
, false))
750 obstack_grow (ob
, "struct { ", 9);
752 for (field
= TYPE_FIELDS (type
);
754 field
= TREE_CHAIN (field
))
756 struct obstack hold_type_obstack
;
759 if (TREE_CODE (type
) == UNION_TYPE
)
761 hold_type_obstack
= container
->type_obstack
;
762 obstack_init (&container
->type_obstack
);
767 if (DECL_NAME (field
) == NULL
)
771 obstack_grow (ob
, "Godump_", 7);
772 snprintf (buf
, sizeof buf
, "%d", i
);
773 obstack_grow (ob
, buf
, strlen (buf
));
778 const char *var_name
;
781 /* Start variable name with an underscore if a keyword. */
782 var_name
= IDENTIFIER_POINTER (DECL_NAME (field
));
783 slot
= htab_find_slot (container
->keyword_hash
, var_name
,
786 obstack_1grow (ob
, '_');
787 go_append_string (ob
, DECL_NAME (field
));
789 obstack_1grow (ob
, ' ');
790 if (DECL_BIT_FIELD (field
))
792 obstack_grow (ob
, "INVALID-bit-field", 17);
797 /* Do not expand type if a record or union type or a
799 if (TYPE_NAME (TREE_TYPE (field
)) != NULL_TREE
800 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field
))
801 || (POINTER_TYPE_P (TREE_TYPE (field
))
802 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field
)))
808 name
= TYPE_NAME (TREE_TYPE (field
));
809 if (TREE_CODE (name
) == TYPE_DECL
)
810 name
= DECL_NAME (name
);
812 slot
= htab_find_slot (container
->invalid_hash
,
813 IDENTIFIER_POINTER (name
),
818 obstack_1grow (ob
, '_');
819 go_append_string (ob
, name
);
823 if (!go_format_type (container
, TREE_TYPE (field
), true,
828 obstack_grow (ob
, "; ", 2);
830 /* Only output the first successful field of a union, and
831 hope for the best. */
832 if (TREE_CODE (type
) == UNION_TYPE
)
834 if (!field_ok
&& TREE_CHAIN (field
) == NULL_TREE
)
843 sz
= obstack_object_size (&container
->type_obstack
);
844 obstack_grow (&hold_type_obstack
,
845 obstack_base (&container
->type_obstack
),
848 obstack_free (&container
->type_obstack
, NULL
);
849 container
->type_obstack
= hold_type_obstack
;
859 obstack_1grow (ob
, '}');
868 function_args_iterator iter
;
871 /* Go has no way to write a type which is a function but not a
872 pointer to a function. */
875 obstack_grow (ob
, "func*", 5);
879 obstack_1grow (ob
, '(');
880 is_varargs
= stdarg_p (type
);
882 FOREACH_FUNCTION_ARGS (type
, arg_type
, iter
)
884 if (VOID_TYPE_P (arg_type
))
887 obstack_grow (ob
, ", ", 2);
888 if (!go_format_type (container
, arg_type
, true, false))
894 if (prototype_p (type
))
895 obstack_grow (ob
, ", ", 2);
896 obstack_grow (ob
, "...interface{}", 14);
898 obstack_1grow (ob
, ')');
900 result
= TREE_TYPE (type
);
901 if (!VOID_TYPE_P (result
))
903 obstack_1grow (ob
, ' ');
904 if (!go_format_type (container
, result
, use_type_name
, false))
911 obstack_grow (ob
, "INVALID-type", 12);
919 /* Output the type which was built on the type obstack, and then free
923 go_output_type (struct godump_container
*container
)
927 ob
= &container
->type_obstack
;
928 obstack_1grow (ob
, '\0');
929 fputs (obstack_base (ob
), go_dump_file
);
930 obstack_free (ob
, obstack_base (ob
));
933 /* Output a function declaration. */
936 go_output_fndecl (struct godump_container
*container
, tree decl
)
938 if (!go_format_type (container
, TREE_TYPE (decl
), false, true))
939 fprintf (go_dump_file
, "// ");
940 fprintf (go_dump_file
, "func _%s ",
941 IDENTIFIER_POINTER (DECL_NAME (decl
)));
942 go_output_type (container
);
943 fprintf (go_dump_file
, " __asm__(\"%s\")\n",
944 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
)));
947 /* Output a typedef or something like a struct definition. */
950 go_output_typedef (struct godump_container
*container
, tree decl
)
952 /* If we have an enum type, output the enum constants
954 if (TREE_CODE (TREE_TYPE (decl
)) == ENUMERAL_TYPE
955 && TYPE_SIZE (TREE_TYPE (decl
)) != 0
956 && !pointer_set_contains (container
->decls_seen
, TREE_TYPE (decl
))
957 && (TYPE_CANONICAL (TREE_TYPE (decl
)) == NULL_TREE
958 || !pointer_set_contains (container
->decls_seen
,
959 TYPE_CANONICAL (TREE_TYPE (decl
)))))
963 for (element
= TYPE_VALUES (TREE_TYPE (decl
));
964 element
!= NULL_TREE
;
965 element
= TREE_CHAIN (element
))
968 struct macro_hash_value
*mhval
;
972 name
= IDENTIFIER_POINTER (TREE_PURPOSE (element
));
974 /* Sometimes a name will be defined as both an enum constant
975 and a macro. Avoid duplicate definition errors by
976 treating enum constants as macros. */
977 mhval
= XNEW (struct macro_hash_value
);
978 mhval
->name
= xstrdup (name
);
980 slot
= htab_find_slot (macro_hash
, mhval
, INSERT
);
982 macro_hash_del (*slot
);
984 if (host_integerp (TREE_VALUE (element
), 0))
985 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
,
986 tree_low_cst (TREE_VALUE (element
), 0));
987 else if (host_integerp (TREE_VALUE (element
), 1))
988 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_UNSIGNED
,
989 ((unsigned HOST_WIDE_INT
)
990 tree_low_cst (TREE_VALUE (element
), 1)));
992 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DOUBLE_HEX
,
993 ((unsigned HOST_WIDE_INT
)
994 TREE_INT_CST_HIGH (TREE_VALUE (element
))),
995 TREE_INT_CST_LOW (TREE_VALUE (element
)));
997 mhval
->value
= xstrdup (buf
);
1000 pointer_set_insert (container
->decls_seen
, TREE_TYPE (decl
));
1001 if (TYPE_CANONICAL (TREE_TYPE (decl
)) != NULL_TREE
)
1002 pointer_set_insert (container
->decls_seen
,
1003 TYPE_CANONICAL (TREE_TYPE (decl
)));
1006 if (DECL_NAME (decl
) != NULL_TREE
)
1011 type
= IDENTIFIER_POINTER (DECL_NAME (decl
));
1012 /* If type defined already, skip. */
1013 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1016 *slot
= CONST_CAST (void *, (const void *) type
);
1018 if (!go_format_type (container
, TREE_TYPE (decl
), false, false))
1020 fprintf (go_dump_file
, "// ");
1021 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1022 *slot
= CONST_CAST (void *, (const void *) type
);
1024 fprintf (go_dump_file
, "type _%s ",
1025 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1026 go_output_type (container
);
1028 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1030 HOST_WIDE_INT size
= int_size_in_bytes (TREE_TYPE (decl
));
1033 fprintf (go_dump_file
,
1034 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1035 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1039 pointer_set_insert (container
->decls_seen
, decl
);
1041 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1047 type
= IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl
))));
1048 /* If type defined already, skip. */
1049 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1052 *slot
= CONST_CAST (void *, (const void *) type
);
1054 if (!go_format_type (container
, TREE_TYPE (decl
), false, false))
1056 fprintf (go_dump_file
, "// ");
1057 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1058 *slot
= CONST_CAST (void *, (const void *) type
);
1060 fprintf (go_dump_file
, "type _%s ",
1061 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))));
1062 go_output_type (container
);
1064 size
= int_size_in_bytes (TREE_TYPE (decl
));
1066 fprintf (go_dump_file
,
1067 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1068 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))),
1074 fprintf (go_dump_file
, "\n");
1077 /* Output a variable. */
1080 go_output_var (struct godump_container
*container
, tree decl
)
1084 if (pointer_set_contains (container
->decls_seen
, decl
)
1085 || pointer_set_contains (container
->decls_seen
, DECL_NAME (decl
)))
1087 pointer_set_insert (container
->decls_seen
, decl
);
1088 pointer_set_insert (container
->decls_seen
, DECL_NAME (decl
));
1090 is_valid
= go_format_type (container
, TREE_TYPE (decl
), true, false);
1092 && htab_find_slot (container
->type_hash
,
1093 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1096 /* There is already a type with this name, probably from a
1097 struct tag. Prefer the type to the variable. */
1101 fprintf (go_dump_file
, "// ");
1103 fprintf (go_dump_file
, "var _%s ",
1104 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1105 go_output_type (container
);
1106 fprintf (go_dump_file
, "\n");
1108 /* Sometimes an extern variable is declared with an unknown struct
1110 if (TYPE_NAME (TREE_TYPE (decl
)) != NULL_TREE
1111 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1113 tree type_name
= TYPE_NAME (TREE_TYPE (decl
));
1114 if (TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1115 pointer_set_insert (container
->pot_dummy_types
,
1116 IDENTIFIER_POINTER (type_name
));
1117 else if (TREE_CODE (type_name
) == TYPE_DECL
)
1118 pointer_set_insert (container
->pot_dummy_types
,
1119 IDENTIFIER_POINTER (DECL_NAME (type_name
)));
1123 /* Output the final value of a preprocessor macro or enum constant.
1124 This is called via htab_traverse_noresize. */
1127 go_print_macro (void **slot
, void *arg ATTRIBUTE_UNUSED
)
1129 struct macro_hash_value
*mhval
= (struct macro_hash_value
*) *slot
;
1130 fprintf (go_dump_file
, "const _%s = %s\n", mhval
->name
, mhval
->value
);
1134 /* Build a hash table with the Go keywords. */
1136 static const char * const keywords
[] = {
1137 "__asm__", "break", "case", "chan", "const", "continue", "default",
1138 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1139 "import", "interface", "map", "package", "range", "return", "select",
1140 "struct", "switch", "type", "var"
1144 keyword_hash_init (struct godump_container
*container
)
1147 size_t count
= sizeof (keywords
) / sizeof (keywords
[0]);
1150 for (i
= 0; i
< count
; i
++)
1152 slot
= htab_find_slot (container
->keyword_hash
, keywords
[i
], INSERT
);
1153 *slot
= CONST_CAST (void *, (const void *) keywords
[i
]);
1157 /* Traversing the pot_dummy_types and seeing which types are present
1158 in the global types hash table and creating dummy definitions if
1159 not found. This function is invoked by pointer_set_traverse. */
1162 find_dummy_types (const void *ptr
, void *adata
)
1164 struct godump_container
*data
= (struct godump_container
*) adata
;
1165 const char *type
= (const char *) ptr
;
1169 slot
= htab_find_slot (data
->type_hash
, type
, NO_INSERT
);
1170 islot
= htab_find_slot (data
->invalid_hash
, type
, NO_INSERT
);
1171 if (slot
== NULL
|| islot
!= NULL
)
1172 fprintf (go_dump_file
, "type _%s struct {}\n", type
);
1176 /* Output symbols. */
1179 go_finish (const char *filename
)
1181 struct godump_container container
;
1185 real_debug_hooks
->finish (filename
);
1187 container
.decls_seen
= pointer_set_create ();
1188 container
.pot_dummy_types
= pointer_set_create ();
1189 container
.type_hash
= htab_create (100, htab_hash_string
,
1190 string_hash_eq
, NULL
);
1191 container
.invalid_hash
= htab_create (10, htab_hash_string
,
1192 string_hash_eq
, NULL
);
1193 container
.keyword_hash
= htab_create (50, htab_hash_string
,
1194 string_hash_eq
, NULL
);
1195 obstack_init (&container
.type_obstack
);
1197 keyword_hash_init (&container
);
1199 FOR_EACH_VEC_SAFE_ELT (queue
, ix
, decl
)
1201 switch (TREE_CODE (decl
))
1204 go_output_fndecl (&container
, decl
);
1208 go_output_typedef (&container
, decl
);
1212 go_output_var (&container
, decl
);
1220 htab_traverse_noresize (macro_hash
, go_print_macro
, NULL
);
1222 /* To emit dummy definitions. */
1223 pointer_set_traverse (container
.pot_dummy_types
, find_dummy_types
,
1224 (void *) &container
);
1226 pointer_set_destroy (container
.decls_seen
);
1227 pointer_set_destroy (container
.pot_dummy_types
);
1228 htab_delete (container
.type_hash
);
1229 htab_delete (container
.invalid_hash
);
1230 htab_delete (container
.keyword_hash
);
1231 obstack_free (&container
.type_obstack
, NULL
);
1235 if (fclose (go_dump_file
) != 0)
1236 error ("could not close Go dump file: %m");
1237 go_dump_file
= NULL
;
1240 /* Set up our hooks. */
1242 const struct gcc_debug_hooks
*
1243 dump_go_spec_init (const char *filename
, const struct gcc_debug_hooks
*hooks
)
1245 go_dump_file
= fopen (filename
, "w");
1246 if (go_dump_file
== NULL
)
1248 error ("could not open Go dump file %qs: %m", filename
);
1252 go_debug_hooks
= *hooks
;
1253 real_debug_hooks
= hooks
;
1255 go_debug_hooks
.finish
= go_finish
;
1256 go_debug_hooks
.define
= go_define
;
1257 go_debug_hooks
.undef
= go_undef
;
1258 go_debug_hooks
.function_decl
= go_function_decl
;
1259 go_debug_hooks
.global_decl
= go_global_decl
;
1260 go_debug_hooks
.type_decl
= go_type_decl
;
1262 macro_hash
= htab_create (100, macro_hash_hashval
, macro_hash_eq
,
1265 return &go_debug_hooks
;
1268 #include "gt-godump.h"