1 /* Output Go language descriptions of types.
2 Copyright (C) 2008-2022 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"
34 #include "diagnostic-core.h"
36 #include "stor-layout.h"
38 /* We dump this information from the debug hooks. This gives us a
39 stable and maintainable API to hook into. In order to work
40 correctly when -g is used, we build our own hooks structure which
41 wraps the hooks we need to change. */
43 /* Our debug hooks. This is initialized by dump_go_spec_init. */
45 static struct gcc_debug_hooks go_debug_hooks
;
47 /* The real debug hooks. */
49 static const struct gcc_debug_hooks
*real_debug_hooks
;
51 /* The file where we should write information. */
53 static FILE *go_dump_file
;
55 /* A queue of decls to output. */
57 static GTY(()) vec
<tree
, va_gc
> *queue
;
59 struct godump_str_hash
: string_hash
, ggc_remove
<const char *> {};
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 /* Returns the number of units necessary to represent an integer with the given
76 PRECISION (in bits). */
78 static inline unsigned int
79 precision_to_units (unsigned int precision
)
81 return (precision
+ BITS_PER_UNIT
- 1) / BITS_PER_UNIT
;
84 /* Calculate the hash value for an entry in the macro hash table. */
87 macro_hash_hashval (const void *val
)
89 const struct macro_hash_value
*mhval
= (const struct macro_hash_value
*) val
;
90 return htab_hash_string (mhval
->name
);
93 /* Compare values in the macro hash table for equality. */
96 macro_hash_eq (const void *v1
, const void *v2
)
98 const struct macro_hash_value
*mhv1
= (const struct macro_hash_value
*) v1
;
99 const struct macro_hash_value
*mhv2
= (const struct macro_hash_value
*) v2
;
100 return strcmp (mhv1
->name
, mhv2
->name
) == 0;
103 /* Free values deleted from the macro hash table. */
106 macro_hash_del (void *v
)
108 struct macro_hash_value
*mhv
= (struct macro_hash_value
*) v
;
109 XDELETEVEC (mhv
->name
);
110 XDELETEVEC (mhv
->value
);
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_UNDECLARED_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
);
497 go_early_global_decl (tree decl
)
500 if (TREE_CODE (decl
) != FUNCTION_DECL
|| DECL_STRUCT_FUNCTION (decl
) != NULL
)
501 real_debug_hooks
->early_global_decl (decl
);
504 /* A global variable decl. */
507 go_late_global_decl (tree decl
)
509 real_debug_hooks
->late_global_decl (decl
);
512 /* A type declaration. */
515 go_type_decl (tree decl
, int local
)
517 real_debug_hooks
->type_decl (decl
, local
);
519 if (local
|| DECL_IS_UNDECLARED_BUILTIN (decl
))
521 if (DECL_NAME (decl
) == NULL_TREE
522 && (TYPE_NAME (TREE_TYPE (decl
)) == NULL_TREE
523 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl
))) != IDENTIFIER_NODE
)
524 && TREE_CODE (TREE_TYPE (decl
)) != ENUMERAL_TYPE
)
526 vec_safe_push (queue
, decl
);
529 /* A container for the data we pass around when generating information
530 at the end of the compilation. */
532 class godump_container
535 /* DECLs that we have already seen. */
536 hash_set
<tree
> decls_seen
;
538 /* Types which may potentially have to be defined as dummy
540 hash_set
<const char *, false, godump_str_hash
> pot_dummy_types
;
545 /* Global type definitions. */
551 /* Obstack used to write out a type definition. */
552 struct obstack type_obstack
;
555 /* Append an IDENTIFIER_NODE to OB. */
558 go_append_string (struct obstack
*ob
, tree id
)
560 obstack_grow (ob
, IDENTIFIER_POINTER (id
), IDENTIFIER_LENGTH (id
));
563 /* Given an integer PRECISION in bits, returns a constant string that is the
564 matching go int or uint type (depending on the IS_UNSIGNED flag). Returns a
565 NULL pointer if there is no matching go type. */
568 go_get_uinttype_for_precision (unsigned int precision
, bool is_unsigned
)
573 return is_unsigned
? "uint8" : "int8";
575 return is_unsigned
? "uint16" : "int16";
577 return is_unsigned
? "uint32" : "int32";
579 return is_unsigned
? "uint64" : "int64";
585 /* Append an artificial variable name with the suffix _INDEX to OB. Returns
589 go_append_artificial_name (struct obstack
*ob
, unsigned int index
)
593 /* FIXME: identifier may not be unique. */
594 obstack_grow (ob
, "Godump_", 7);
595 snprintf (buf
, sizeof buf
, "%u", index
);
596 obstack_grow (ob
, buf
, strlen (buf
));
601 /* Append the variable name from DECL to OB. If the name is in the
602 KEYWORD_HASH, prepend an '_'. */
605 go_append_decl_name (struct obstack
*ob
, tree decl
, htab_t keyword_hash
)
607 const char *var_name
;
610 /* Start variable name with an underscore if a keyword. */
611 var_name
= IDENTIFIER_POINTER (DECL_NAME (decl
));
612 slot
= htab_find_slot (keyword_hash
, var_name
, NO_INSERT
);
614 obstack_1grow (ob
, '_');
615 go_append_string (ob
, DECL_NAME (decl
));
618 /* Appends a byte array with the necessary number of elements and the name
619 "Godump_INDEX_pad" to pad from FROM_OFFSET to TO_OFFSET to OB assuming that
620 the next field is automatically aligned to ALIGN_UNITS. Returns INDEX + 1,
621 or INDEX if no padding had to be appended. The resulting offset where the
622 next field is allocated is returned through RET_OFFSET. */
625 go_append_padding (struct obstack
*ob
, unsigned int from_offset
,
626 unsigned int to_offset
, unsigned int align_units
,
627 unsigned int index
, unsigned int *ret_offset
)
629 if (from_offset
% align_units
> 0)
630 from_offset
+= align_units
- (from_offset
% align_units
);
631 gcc_assert (to_offset
>= from_offset
);
632 if (to_offset
> from_offset
)
636 index
= go_append_artificial_name (ob
, index
);
637 snprintf (buf
, sizeof buf
, "_pad [%u]byte; ", to_offset
- from_offset
);
638 obstack_grow (ob
, buf
, strlen (buf
));
640 *ret_offset
= to_offset
;
645 /* Appends an array of type TYPE_STRING with zero elements and the name
646 "_" to OB. If TYPE_STRING is a null pointer, ERROR_STRING is appended
647 instead of the type. Returns INDEX + 1. */
650 go_force_record_alignment (struct obstack
*ob
, const char *type_string
,
651 unsigned int index
, const char *error_string
)
653 obstack_grow (ob
, "_ ", 2);
654 if (type_string
== NULL
)
655 obstack_grow (ob
, error_string
, strlen (error_string
));
658 obstack_grow (ob
, "[0]", 3);
659 obstack_grow (ob
, type_string
, strlen (type_string
));
661 obstack_grow (ob
, "; ", 2);
666 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
667 USE_TYPE_NAME is true if we can simply use a type name here without
668 needing to define it. IS_FUNC_OK is true if we can output a func
669 type here; the "func" keyword will already have been added.
670 Return true if the type can be represented in Go, false otherwise.
671 P_ART_I is used for indexing artificial elements in nested structures and
672 should always be a NULL pointer when called, except by certain recursive
673 calls from go_format_type() itself. */
676 go_format_type (class godump_container
*container
, tree type
,
677 bool use_type_name
, bool is_func_ok
, unsigned int *p_art_i
,
678 bool is_anon_record_or_union
)
682 unsigned int art_i_dummy
;
683 bool is_union
= false;
688 p_art_i
= &art_i_dummy
;
691 ob
= &container
->type_obstack
;
694 && TYPE_NAME (type
) != NULL_TREE
695 && (AGGREGATE_TYPE_P (type
)
696 || POINTER_TYPE_P (type
)
697 || TREE_CODE (type
) == FUNCTION_TYPE
))
702 /* References to complex builtin types cannot be translated to
704 if (DECL_P (TYPE_NAME (type
))
705 && DECL_IS_UNDECLARED_BUILTIN (TYPE_NAME (type
)))
708 name
= TYPE_IDENTIFIER (type
);
710 slot
= htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (name
),
715 /* References to incomplete structs are permitted in many
716 contexts, like behind a pointer or inside of a typedef. So
717 consider any referenced struct a potential dummy type. */
718 if (RECORD_OR_UNION_TYPE_P (type
))
719 container
->pot_dummy_types
.add (IDENTIFIER_POINTER (name
));
721 obstack_1grow (ob
, '_');
722 go_append_string (ob
, name
);
726 switch (TREE_CODE (type
))
732 slot
= htab_find_slot (container
->invalid_hash
,
733 IDENTIFIER_POINTER (DECL_NAME (type
)),
738 obstack_1grow (ob
, '_');
739 go_append_string (ob
, DECL_NAME (type
));
749 s
= go_get_uinttype_for_precision (TYPE_PRECISION (type
),
750 TYPE_UNSIGNED (type
));
753 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
754 TYPE_PRECISION (type
),
755 TYPE_UNSIGNED (type
) ? "u" : "");
759 obstack_grow (ob
, s
, strlen (s
));
768 switch (TYPE_PRECISION (type
))
777 snprintf (buf
, sizeof buf
, "INVALID-float-%u",
778 TYPE_PRECISION (type
));
783 obstack_grow (ob
, s
, strlen (s
));
793 real_type
= TREE_TYPE (type
);
794 if (TREE_CODE (real_type
) == REAL_TYPE
)
796 switch (TYPE_PRECISION (real_type
))
805 snprintf (buf
, sizeof buf
, "INVALID-complex-%u",
806 2 * TYPE_PRECISION (real_type
));
814 s
= "INVALID-complex-non-real";
817 obstack_grow (ob
, s
, strlen (s
));
822 obstack_grow (ob
, "bool", 4);
826 if (TREE_CODE (TREE_TYPE (type
)) == FUNCTION_TYPE
)
827 obstack_grow (ob
, "func", 4);
829 obstack_1grow (ob
, '*');
830 if (VOID_TYPE_P (TREE_TYPE (type
)))
831 obstack_grow (ob
, "byte", 4);
834 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
,
841 obstack_1grow (ob
, '[');
842 if (TYPE_DOMAIN (type
) != NULL_TREE
843 && TREE_CODE (TYPE_DOMAIN (type
)) == INTEGER_TYPE
844 && TYPE_MIN_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
845 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
846 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == 0
847 && TYPE_MAX_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
848 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
849 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))))
853 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
"+1",
854 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))));
855 obstack_grow (ob
, buf
, strlen (buf
));
858 obstack_1grow (ob
, '0');
859 obstack_1grow (ob
, ']');
860 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
, false,
867 /* Fall through to RECORD_TYPE case. */
871 unsigned int prev_field_end
;
872 unsigned int known_alignment
;
874 bool emitted_a_field
;
876 /* FIXME: Why is this necessary? Without it we can get a core
877 dump on the s390x headers, or from a file containing simply
878 "typedef struct S T;". */
883 /* Anonymous records and unions are flattened, i.e. they are not put
884 into "struct { ... }". */
885 if (!is_anon_record_or_union
)
886 obstack_grow (ob
, "struct { ", 9);
887 for (field
= TYPE_FIELDS (type
), emitted_a_field
= false;
889 field
= TREE_CHAIN (field
))
891 if (TREE_CODE (field
) != FIELD_DECL
)
893 if (DECL_BIT_FIELD (field
))
894 /* Bit fields are replaced by padding. */
896 /* Only the first non-bitfield field is emitted for unions. */
897 if (!is_union
|| !emitted_a_field
)
899 /* Emit the field. */
901 bool is_anon_substructure
;
902 unsigned int decl_align_unit
;
903 unsigned int decl_offset
;
906 emitted_a_field
= true;
907 is_anon_substructure
=
908 (DECL_NAME (field
) == NULL
909 && (TREE_CODE (TREE_TYPE (field
)) == RECORD_TYPE
910 || TREE_CODE (TREE_TYPE (field
)) == UNION_TYPE
));
911 /* Keep track of the alignment of named substructures, either
912 of the whole record, or the alignment of the emitted field
914 decl_align_unit
= DECL_ALIGN_UNIT (field
);
915 if (!is_anon_substructure
&& decl_align_unit
> known_alignment
)
916 known_alignment
= decl_align_unit
;
917 /* Pad to start of field. */
919 TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field
))
921 (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field
)));
923 unsigned int align_unit
;
925 /* For anonymous records and unions there is no automatic
926 structure alignment, so use 1 as the alignment. */
927 align_unit
= (is_anon_substructure
) ? 1 : decl_align_unit
;
928 *p_art_i
= go_append_padding
929 (ob
, prev_field_end
, decl_offset
, align_unit
, *p_art_i
,
932 if (DECL_SIZE_UNIT (field
))
934 TREE_INT_CST_LOW (DECL_SIZE_UNIT (field
));
935 /* Emit the field name, but not for anonymous records and
937 if (!is_anon_substructure
)
939 if (DECL_NAME (field
) == NULL
)
940 *p_art_i
= go_append_artificial_name (ob
, *p_art_i
);
943 (ob
, field
, container
->keyword_hash
);
944 obstack_1grow (ob
, ' ');
946 /* Do not expand type if a record or union type or a function
948 if (TYPE_NAME (TREE_TYPE (field
)) != NULL_TREE
949 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field
))
950 || (POINTER_TYPE_P (TREE_TYPE (field
))
951 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field
)))
957 name
= TYPE_IDENTIFIER (TREE_TYPE (field
));
959 slot
= htab_find_slot (container
->invalid_hash
,
960 IDENTIFIER_POINTER (name
),
965 obstack_1grow (ob
, '_');
966 go_append_string (ob
, name
);
970 if (!go_format_type (container
, TREE_TYPE (field
), true,
971 false, p_art_i
, is_anon_substructure
))
974 if (!is_anon_substructure
)
975 obstack_grow (ob
, "; ", 2);
981 *p_art_i
= go_append_padding (ob
, prev_field_end
,
982 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type
)),
983 1, *p_art_i
, &prev_field_end
);
985 if (!is_anon_record_or_union
986 && known_alignment
< TYPE_ALIGN_UNIT (type
))
991 /* Enforce proper record alignment. */
992 s
= go_get_uinttype_for_precision
993 (TYPE_ALIGN (type
), TYPE_UNSIGNED (type
));
996 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
997 TYPE_ALIGN (type
), TYPE_UNSIGNED (type
) ? "u" : "");
1001 *p_art_i
= go_force_record_alignment (ob
, s
, *p_art_i
, buf
);
1003 if (!is_anon_record_or_union
)
1004 obstack_1grow (ob
, '}');
1013 function_args_iterator iter
;
1016 /* Go has no way to write a type which is a function but not a
1017 pointer to a function. */
1020 obstack_grow (ob
, "func*", 5);
1024 obstack_1grow (ob
, '(');
1025 is_varargs
= stdarg_p (type
);
1027 FOREACH_FUNCTION_ARGS (type
, arg_type
, iter
)
1029 if (VOID_TYPE_P (arg_type
))
1032 obstack_grow (ob
, ", ", 2);
1033 if (!go_format_type (container
, arg_type
, true, false, NULL
, false))
1039 if (prototype_p (type
))
1040 obstack_grow (ob
, ", ", 2);
1041 obstack_grow (ob
, "...interface{}", 14);
1043 obstack_1grow (ob
, ')');
1045 result
= TREE_TYPE (type
);
1046 if (!VOID_TYPE_P (result
))
1048 obstack_1grow (ob
, ' ');
1049 if (!go_format_type (container
, result
, use_type_name
, false, NULL
,
1057 obstack_grow (ob
, "INVALID-type", 12);
1065 /* Output the type which was built on the type obstack, and then free
1069 go_output_type (class godump_container
*container
)
1073 ob
= &container
->type_obstack
;
1074 obstack_1grow (ob
, '\0');
1075 fputs ((char *) obstack_base (ob
), go_dump_file
);
1076 obstack_free (ob
, obstack_base (ob
));
1079 /* Output a function declaration. */
1082 go_output_fndecl (class godump_container
*container
, tree decl
)
1084 if (!go_format_type (container
, TREE_TYPE (decl
), true, true, NULL
, false))
1085 fprintf (go_dump_file
, "// ");
1086 fprintf (go_dump_file
, "func _%s ",
1087 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1088 go_output_type (container
);
1089 fprintf (go_dump_file
, " __asm__(\"%s\")\n",
1090 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
)));
1093 /* Output a typedef or something like a struct definition. */
1096 go_output_typedef (class godump_container
*container
, tree decl
)
1098 /* If we have an enum type, output the enum constants
1100 if (TREE_CODE (TREE_TYPE (decl
)) == ENUMERAL_TYPE
1101 && TYPE_SIZE (TREE_TYPE (decl
)) != 0
1102 && !container
->decls_seen
.contains (TREE_TYPE (decl
))
1103 && (TYPE_CANONICAL (TREE_TYPE (decl
)) == NULL_TREE
1104 || !container
->decls_seen
.contains
1105 (TYPE_CANONICAL (TREE_TYPE (decl
)))))
1109 for (element
= TYPE_VALUES (TREE_TYPE (decl
));
1110 element
!= NULL_TREE
;
1111 element
= TREE_CHAIN (element
))
1114 struct macro_hash_value
*mhval
;
1116 char buf
[WIDE_INT_PRINT_BUFFER_SIZE
];
1118 name
= IDENTIFIER_POINTER (TREE_PURPOSE (element
));
1120 /* Sometimes a name will be defined as both an enum constant
1121 and a macro. Avoid duplicate definition errors by
1122 treating enum constants as macros. */
1123 mhval
= XNEW (struct macro_hash_value
);
1124 mhval
->name
= xstrdup (name
);
1125 mhval
->value
= NULL
;
1126 slot
= htab_find_slot (macro_hash
, mhval
, INSERT
);
1128 macro_hash_del (*slot
);
1130 if (tree_fits_shwi_p (TREE_VALUE (element
)))
1131 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
,
1132 tree_to_shwi (TREE_VALUE (element
)));
1133 else if (tree_fits_uhwi_p (TREE_VALUE (element
)))
1134 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_UNSIGNED
,
1135 tree_to_uhwi (TREE_VALUE (element
)));
1137 print_hex (wi::to_wide (element
), buf
);
1139 mhval
->value
= xstrdup (buf
);
1142 container
->decls_seen
.add (TREE_TYPE (decl
));
1143 if (TYPE_CANONICAL (TREE_TYPE (decl
)) != NULL_TREE
)
1144 container
->decls_seen
.add (TYPE_CANONICAL (TREE_TYPE (decl
)));
1147 if (DECL_NAME (decl
) != NULL_TREE
)
1153 type
= IDENTIFIER_POINTER (DECL_NAME (decl
));
1154 original_type
= DECL_ORIGINAL_TYPE (decl
);
1155 if (original_type
== NULL_TREE
)
1156 original_type
= TREE_TYPE (decl
);
1158 /* Suppress typedefs where the type name matches the underlying
1159 struct/union/enum tag. This way we'll emit the struct definition
1160 instead of an invalid recursive type. */
1161 if (TYPE_IDENTIFIER (original_type
) != NULL
1162 && IDENTIFIER_POINTER (TYPE_IDENTIFIER (original_type
)) == type
)
1165 /* If type defined already, skip. */
1166 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1169 *slot
= CONST_CAST (void *, (const void *) type
);
1171 if (!go_format_type (container
, original_type
, true, false,
1174 fprintf (go_dump_file
, "// ");
1175 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1176 *slot
= CONST_CAST (void *, (const void *) type
);
1178 fprintf (go_dump_file
, "type _%s ",
1179 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1180 go_output_type (container
);
1182 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1184 HOST_WIDE_INT size
= int_size_in_bytes (TREE_TYPE (decl
));
1187 fprintf (go_dump_file
,
1188 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1189 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1193 container
->decls_seen
.add (decl
);
1195 else if ((RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
))
1196 || TREE_CODE (TREE_TYPE (decl
)) == ENUMERAL_TYPE
)
1197 && TYPE_NAME (TREE_TYPE (decl
)) != NULL
)
1203 type
= IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl
))));
1204 /* If type defined already, skip. */
1205 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1208 *slot
= CONST_CAST (void *, (const void *) type
);
1210 if (!go_format_type (container
, TREE_TYPE (decl
), false, false, NULL
,
1213 fprintf (go_dump_file
, "// ");
1214 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1215 *slot
= CONST_CAST (void *, (const void *) type
);
1217 fprintf (go_dump_file
, "type _%s ",
1218 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))));
1219 go_output_type (container
);
1221 size
= int_size_in_bytes (TREE_TYPE (decl
));
1223 fprintf (go_dump_file
,
1224 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1225 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))),
1231 fprintf (go_dump_file
, "\n");
1234 /* Output a variable. */
1237 go_output_var (class godump_container
*container
, tree decl
)
1243 if (container
->decls_seen
.contains (decl
)
1244 || container
->decls_seen
.contains (DECL_NAME (decl
)))
1246 container
->decls_seen
.add (decl
);
1247 container
->decls_seen
.add (DECL_NAME (decl
));
1249 type_name
= TYPE_NAME (TREE_TYPE (decl
));
1251 if (type_name
!= NULL_TREE
&& TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1253 else if (type_name
!= NULL_TREE
&& TREE_CODE (type_name
) == TYPE_DECL
1254 && DECL_SOURCE_LOCATION (type_name
) != BUILTINS_LOCATION
1255 && DECL_NAME (type_name
))
1256 id
= DECL_NAME (type_name
);
1258 && (!htab_find_slot (container
->type_hash
, IDENTIFIER_POINTER (id
),
1260 || htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (id
),
1263 if (id
!= NULL_TREE
)
1267 ob
= &container
->type_obstack
;
1268 obstack_1grow (ob
, '_');
1269 go_append_string (ob
, id
);
1270 is_valid
= htab_find_slot (container
->type_hash
, IDENTIFIER_POINTER (id
),
1274 is_valid
= go_format_type (container
, TREE_TYPE (decl
), true, false, NULL
,
1277 && htab_find_slot (container
->type_hash
,
1278 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1281 /* There is already a type with this name, probably from a
1282 struct tag. Prefer the type to the variable. */
1286 fprintf (go_dump_file
, "// ");
1288 fprintf (go_dump_file
, "var _%s ",
1289 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1290 go_output_type (container
);
1291 fprintf (go_dump_file
, "\n");
1293 /* Sometimes an extern variable is declared with an unknown struct
1295 if (type_name
!= NULL_TREE
&& RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1297 if (TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1298 container
->pot_dummy_types
.add (IDENTIFIER_POINTER (type_name
));
1299 else if (TREE_CODE (type_name
) == TYPE_DECL
)
1300 container
->pot_dummy_types
.add
1301 (IDENTIFIER_POINTER (DECL_NAME (type_name
)));
1305 /* Output the final value of a preprocessor macro or enum constant.
1306 This is called via htab_traverse_noresize. */
1309 go_print_macro (void **slot
, void *arg ATTRIBUTE_UNUSED
)
1311 struct macro_hash_value
*mhval
= (struct macro_hash_value
*) *slot
;
1312 fprintf (go_dump_file
, "const _%s = %s\n", mhval
->name
, mhval
->value
);
1316 /* Build a hash table with the Go keywords. */
1318 static const char * const keywords
[] = {
1319 "__asm__", "break", "case", "chan", "const", "continue", "default",
1320 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1321 "import", "interface", "map", "package", "range", "return", "select",
1322 "struct", "switch", "type", "var"
1326 keyword_hash_init (class godump_container
*container
)
1329 size_t count
= sizeof (keywords
) / sizeof (keywords
[0]);
1332 for (i
= 0; i
< count
; i
++)
1334 slot
= htab_find_slot (container
->keyword_hash
, keywords
[i
], INSERT
);
1335 *slot
= CONST_CAST (void *, (const void *) keywords
[i
]);
1339 /* Traversing the pot_dummy_types and seeing which types are present
1340 in the global types hash table and creating dummy definitions if
1341 not found. This function is invoked by hash_set::traverse. */
1344 find_dummy_types (const char *const &ptr
, godump_container
*adata
)
1346 class godump_container
*data
= (class godump_container
*) adata
;
1347 const char *type
= (const char *) ptr
;
1351 slot
= htab_find_slot (data
->type_hash
, type
, NO_INSERT
);
1352 islot
= htab_find_slot (data
->invalid_hash
, type
, NO_INSERT
);
1353 if (slot
== NULL
|| islot
!= NULL
)
1354 fprintf (go_dump_file
, "type _%s struct {}\n", type
);
1358 /* Output symbols. */
1361 go_finish (const char *filename
)
1363 class godump_container container
;
1367 real_debug_hooks
->finish (filename
);
1369 container
.type_hash
= htab_create (100, htab_hash_string
,
1370 htab_eq_string
, NULL
);
1371 container
.invalid_hash
= htab_create (10, htab_hash_string
,
1372 htab_eq_string
, NULL
);
1373 container
.keyword_hash
= htab_create (50, htab_hash_string
,
1374 htab_eq_string
, NULL
);
1375 obstack_init (&container
.type_obstack
);
1377 keyword_hash_init (&container
);
1379 FOR_EACH_VEC_SAFE_ELT (queue
, ix
, decl
)
1381 switch (TREE_CODE (decl
))
1384 go_output_fndecl (&container
, decl
);
1388 go_output_typedef (&container
, decl
);
1392 go_output_var (&container
, decl
);
1400 htab_traverse_noresize (macro_hash
, go_print_macro
, NULL
);
1402 /* To emit dummy definitions. */
1403 container
.pot_dummy_types
.traverse
<godump_container
*, find_dummy_types
>
1406 htab_delete (container
.type_hash
);
1407 htab_delete (container
.invalid_hash
);
1408 htab_delete (container
.keyword_hash
);
1409 obstack_free (&container
.type_obstack
, NULL
);
1413 if (fclose (go_dump_file
) != 0)
1414 error ("could not close Go dump file: %m");
1415 go_dump_file
= NULL
;
1418 /* Set up our hooks. */
1420 const struct gcc_debug_hooks
*
1421 dump_go_spec_init (const char *filename
, const struct gcc_debug_hooks
*hooks
)
1423 go_dump_file
= fopen (filename
, "w");
1424 if (go_dump_file
== NULL
)
1426 error ("could not open Go dump file %qs: %m", filename
);
1430 go_debug_hooks
= *hooks
;
1431 real_debug_hooks
= hooks
;
1433 go_debug_hooks
.finish
= go_finish
;
1434 go_debug_hooks
.define
= go_define
;
1435 go_debug_hooks
.undef
= go_undef
;
1436 go_debug_hooks
.function_decl
= go_function_decl
;
1437 go_debug_hooks
.early_global_decl
= go_early_global_decl
;
1438 go_debug_hooks
.late_global_decl
= go_late_global_decl
;
1439 go_debug_hooks
.type_decl
= go_type_decl
;
1441 macro_hash
= htab_create (100, macro_hash_hashval
, macro_hash_eq
,
1444 return &go_debug_hooks
;
1447 #include "gt-godump.h"