1 /* Output Go language descriptions of types.
2 Copyright (C) 2008-2020 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 /* A hash table of macros we have seen. */
61 static htab_t macro_hash
;
63 /* The type of a value in macro_hash. */
65 struct macro_hash_value
67 /* The name stored in the hash table. */
69 /* The value of the macro. */
73 /* Returns the number of units necessary to represent an integer with the given
74 PRECISION (in bits). */
76 static inline unsigned int
77 precision_to_units (unsigned int precision
)
79 return (precision
+ BITS_PER_UNIT
- 1) / BITS_PER_UNIT
;
82 /* Calculate the hash value for an entry in the macro hash table. */
85 macro_hash_hashval (const void *val
)
87 const struct macro_hash_value
*mhval
= (const struct macro_hash_value
*) val
;
88 return htab_hash_string (mhval
->name
);
91 /* Compare values in the macro hash table for equality. */
94 macro_hash_eq (const void *v1
, const void *v2
)
96 const struct macro_hash_value
*mhv1
= (const struct macro_hash_value
*) v1
;
97 const struct macro_hash_value
*mhv2
= (const struct macro_hash_value
*) v2
;
98 return strcmp (mhv1
->name
, mhv2
->name
) == 0;
101 /* Free values deleted from the macro hash table. */
104 macro_hash_del (void *v
)
106 struct macro_hash_value
*mhv
= (struct macro_hash_value
*) v
;
107 XDELETEVEC (mhv
->name
);
108 XDELETEVEC (mhv
->value
);
112 /* For the string hash tables. */
115 string_hash_eq (const void *y1
, const void *y2
)
117 return strcmp ((const char *) y1
, (const char *) y2
) == 0;
120 /* A macro definition. */
123 go_define (unsigned int lineno
, const char *buffer
)
126 const char *name_end
;
132 struct macro_hash_value
*mhval
;
137 real_debug_hooks
->define (lineno
, buffer
);
139 /* Skip macro functions. */
140 for (p
= buffer
; *p
!= '\0' && *p
!= ' '; ++p
)
153 copy
= XNEWVEC (char, name_end
- buffer
+ 1);
154 memcpy (copy
, buffer
, name_end
- buffer
);
155 copy
[name_end
- buffer
] = '\0';
157 mhval
= XNEW (struct macro_hash_value
);
161 hashval
= htab_hash_string (copy
);
162 slot
= htab_find_slot_with_hash (macro_hash
, mhval
, hashval
, NO_INSERT
);
164 /* For simplicity, we force all names to be hidden by adding an
165 initial underscore, and let the user undo this as needed. */
166 out_len
= strlen (p
) * 2 + 1;
167 out_buffer
= XNEWVEC (char, out_len
);
170 need_operand
= false;
175 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
176 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
177 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
178 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
180 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
181 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
182 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
183 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
187 /* The start of an identifier. Technically we should also
188 worry about UTF-8 identifiers, but they are not a
189 problem for practical uses of -fdump-go-spec so we
190 don't worry about them. */
193 struct macro_hash_value idval
;
199 while (ISALNUM (*p
) || *p
== '_')
201 n
= XALLOCAVEC (char, p
- start
+ 1);
202 memcpy (n
, start
, p
- start
);
206 if (htab_find (macro_hash
, &idval
) == NULL
)
208 /* This is a reference to a name which was not defined
214 memcpy (q
, start
, p
- start
);
218 need_operand
= false;
226 case '0': case '1': case '2': case '3': case '4':
227 case '5': case '6': case '7': case '8': case '9':
234 if (*p
== '0' && (p
[1] == 'x' || p
[1] == 'X'))
239 while (ISDIGIT (*p
) || *p
== '.' || *p
== 'e' || *p
== 'E'
241 && ((*p
>= 'a' && *p
<= 'f')
242 || (*p
>= 'A' && *p
<= 'F'))))
244 memcpy (q
, start
, p
- start
);
246 while (*p
== 'u' || *p
== 'U' || *p
== 'l' || *p
== 'L'
247 || *p
== 'f' || *p
== 'F'
248 || *p
== 'd' || *p
== 'D')
250 /* Go doesn't use any of these trailing type
255 /* We'll pick up the exponent, if any, as an
259 need_operand
= false;
268 /* Always OK, not part of an operand, presumed to start an
272 need_operand
= false;
276 /* OK if we don't need an operand, and presumed to indicate
285 /* Always OK, but not part of an operand. */
290 case '*': case '/': case '%': case '|': case '&': case '^':
291 /* Must be a binary operator. */
303 /* Must be a binary operator. */
315 /* Must be a binary operator. */
324 /* Must be a unary operator. */
332 /* Must be a binary operand, may be << or >> or <= or >=. */
336 if (*p
== *(p
- 1) || *p
== '=')
343 /* Must be a unary operand, must be translated for Go. */
380 case '0': case '1': case '2': case '3':
381 case '4': case '5': case '6': case '7':
383 while (*p
>= '0' && *p
<= '7')
388 /* Go octal characters are always 3
397 while (ISXDIGIT (*p
))
402 /* Go hex characters are always 2 digits. */
407 case 'a': case 'b': case 'f': case 'n': case 'r':
408 case 't': case 'v': case '\\': case '\'': case '"':
419 if (quote
== '\'' && count
!= 1)
423 need_operand
= false;
436 gcc_assert ((size_t) (q
- out_buffer
) < out_len
);
439 mhval
->value
= out_buffer
;
443 slot
= htab_find_slot_with_hash (macro_hash
, mhval
, hashval
, INSERT
);
444 gcc_assert (slot
!= NULL
&& *slot
== NULL
);
449 macro_hash_del (*slot
);
457 fprintf (go_dump_file
, "// unknowndefine %s\n", buffer
);
459 htab_clear_slot (macro_hash
, slot
);
460 XDELETEVEC (out_buffer
);
467 go_undef (unsigned int lineno
, const char *buffer
)
469 struct macro_hash_value mhval
;
472 real_debug_hooks
->undef (lineno
, buffer
);
474 mhval
.name
= CONST_CAST (char *, buffer
);
476 slot
= htab_find_slot (macro_hash
, &mhval
, NO_INSERT
);
478 htab_clear_slot (macro_hash
, slot
);
481 /* A function or variable decl. */
486 if (!TREE_PUBLIC (decl
)
487 || DECL_IS_BUILTIN (decl
)
488 || DECL_NAME (decl
) == NULL_TREE
)
490 vec_safe_push (queue
, decl
);
493 /* A function decl. */
496 go_function_decl (tree decl
)
498 real_debug_hooks
->function_decl (decl
);
503 go_early_global_decl (tree decl
)
506 if (TREE_CODE (decl
) != FUNCTION_DECL
|| DECL_STRUCT_FUNCTION (decl
) != NULL
)
507 real_debug_hooks
->early_global_decl (decl
);
510 /* A global variable decl. */
513 go_late_global_decl (tree decl
)
515 real_debug_hooks
->late_global_decl (decl
);
518 /* A type declaration. */
521 go_type_decl (tree decl
, int local
)
523 real_debug_hooks
->type_decl (decl
, local
);
525 if (local
|| DECL_IS_BUILTIN (decl
))
527 if (DECL_NAME (decl
) == NULL_TREE
528 && (TYPE_NAME (TREE_TYPE (decl
)) == NULL_TREE
529 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl
))) != IDENTIFIER_NODE
)
530 && TREE_CODE (TREE_TYPE (decl
)) != ENUMERAL_TYPE
)
532 vec_safe_push (queue
, decl
);
535 /* A container for the data we pass around when generating information
536 at the end of the compilation. */
538 class godump_container
541 /* DECLs that we have already seen. */
542 hash_set
<tree
> decls_seen
;
544 /* Types which may potentially have to be defined as dummy
546 hash_set
<const char *> pot_dummy_types
;
551 /* Global type definitions. */
557 /* Obstack used to write out a type definition. */
558 struct obstack type_obstack
;
561 /* Append an IDENTIFIER_NODE to OB. */
564 go_append_string (struct obstack
*ob
, tree id
)
566 obstack_grow (ob
, IDENTIFIER_POINTER (id
), IDENTIFIER_LENGTH (id
));
569 /* Given an integer PRECISION in bits, returns a constant string that is the
570 matching go int or uint type (depending on the IS_UNSIGNED flag). Returns a
571 NULL pointer if there is no matching go type. */
574 go_get_uinttype_for_precision (unsigned int precision
, bool is_unsigned
)
579 return is_unsigned
? "uint8" : "int8";
581 return is_unsigned
? "uint16" : "int16";
583 return is_unsigned
? "uint32" : "int32";
585 return is_unsigned
? "uint64" : "int64";
591 /* Append an artificial variable name with the suffix _INDEX to OB. Returns
595 go_append_artificial_name (struct obstack
*ob
, unsigned int index
)
599 /* FIXME: identifier may not be unique. */
600 obstack_grow (ob
, "Godump_", 7);
601 snprintf (buf
, sizeof buf
, "%u", index
);
602 obstack_grow (ob
, buf
, strlen (buf
));
607 /* Append the variable name from DECL to OB. If the name is in the
608 KEYWORD_HASH, prepend an '_'. */
611 go_append_decl_name (struct obstack
*ob
, tree decl
, htab_t keyword_hash
)
613 const char *var_name
;
616 /* Start variable name with an underscore if a keyword. */
617 var_name
= IDENTIFIER_POINTER (DECL_NAME (decl
));
618 slot
= htab_find_slot (keyword_hash
, var_name
, NO_INSERT
);
620 obstack_1grow (ob
, '_');
621 go_append_string (ob
, DECL_NAME (decl
));
624 /* Appends a byte array with the necessary number of elements and the name
625 "Godump_INDEX_pad" to pad from FROM_OFFSET to TO_OFFSET to OB assuming that
626 the next field is automatically aligned to ALIGN_UNITS. Returns INDEX + 1,
627 or INDEX if no padding had to be appended. The resulting offset where the
628 next field is allocated is returned through RET_OFFSET. */
631 go_append_padding (struct obstack
*ob
, unsigned int from_offset
,
632 unsigned int to_offset
, unsigned int align_units
,
633 unsigned int index
, unsigned int *ret_offset
)
635 if (from_offset
% align_units
> 0)
636 from_offset
+= align_units
- (from_offset
% align_units
);
637 gcc_assert (to_offset
>= from_offset
);
638 if (to_offset
> from_offset
)
642 index
= go_append_artificial_name (ob
, index
);
643 snprintf (buf
, sizeof buf
, "_pad [%u]byte; ", to_offset
- from_offset
);
644 obstack_grow (ob
, buf
, strlen (buf
));
646 *ret_offset
= to_offset
;
651 /* Appends an array of type TYPE_STRING with zero elements and the name
652 "Godump_INDEX_align" to OB. If TYPE_STRING is a null pointer, ERROR_STRING
653 is appended instead of the type. Returns INDEX + 1. */
656 go_force_record_alignment (struct obstack
*ob
, const char *type_string
,
657 unsigned int index
, const char *error_string
)
659 index
= go_append_artificial_name (ob
, index
);
660 obstack_grow (ob
, "_align ", 7);
661 if (type_string
== NULL
)
662 obstack_grow (ob
, error_string
, strlen (error_string
));
665 obstack_grow (ob
, "[0]", 3);
666 obstack_grow (ob
, type_string
, strlen (type_string
));
668 obstack_grow (ob
, "; ", 2);
673 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
674 USE_TYPE_NAME is true if we can simply use a type name here without
675 needing to define it. IS_FUNC_OK is true if we can output a func
676 type here; the "func" keyword will already have been added.
677 Return true if the type can be represented in Go, false otherwise.
678 P_ART_I is used for indexing artificial elements in nested structures and
679 should always be a NULL pointer when called, except by certain recursive
680 calls from go_format_type() itself. */
683 go_format_type (class godump_container
*container
, tree type
,
684 bool use_type_name
, bool is_func_ok
, unsigned int *p_art_i
,
685 bool is_anon_record_or_union
)
689 unsigned int art_i_dummy
;
690 bool is_union
= false;
695 p_art_i
= &art_i_dummy
;
698 ob
= &container
->type_obstack
;
700 if (TYPE_NAME (type
) != NULL_TREE
701 && (container
->decls_seen
.contains (type
)
702 || container
->decls_seen
.contains (TYPE_NAME (type
)))
703 && (AGGREGATE_TYPE_P (type
)
704 || POINTER_TYPE_P (type
)
705 || TREE_CODE (type
) == FUNCTION_TYPE
))
710 name
= TYPE_IDENTIFIER (type
);
712 slot
= htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (name
),
717 obstack_1grow (ob
, '_');
718 go_append_string (ob
, name
);
722 container
->decls_seen
.add (type
);
724 switch (TREE_CODE (type
))
730 slot
= htab_find_slot (container
->invalid_hash
,
731 IDENTIFIER_POINTER (DECL_NAME (type
)),
736 obstack_1grow (ob
, '_');
737 go_append_string (ob
, DECL_NAME (type
));
747 s
= go_get_uinttype_for_precision (TYPE_PRECISION (type
),
748 TYPE_UNSIGNED (type
));
751 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
752 TYPE_PRECISION (type
),
753 TYPE_UNSIGNED (type
) ? "u" : "");
757 obstack_grow (ob
, s
, strlen (s
));
766 switch (TYPE_PRECISION (type
))
775 snprintf (buf
, sizeof buf
, "INVALID-float-%u",
776 TYPE_PRECISION (type
));
781 obstack_grow (ob
, s
, strlen (s
));
791 real_type
= TREE_TYPE (type
);
792 if (TREE_CODE (real_type
) == REAL_TYPE
)
794 switch (TYPE_PRECISION (real_type
))
803 snprintf (buf
, sizeof buf
, "INVALID-complex-%u",
804 2 * TYPE_PRECISION (real_type
));
812 s
= "INVALID-complex-non-real";
815 obstack_grow (ob
, s
, strlen (s
));
820 obstack_grow (ob
, "bool", 4);
825 && TYPE_NAME (TREE_TYPE (type
)) != NULL_TREE
826 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
))
827 || (POINTER_TYPE_P (TREE_TYPE (type
))
828 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type
)))
834 name
= TYPE_IDENTIFIER (TREE_TYPE (type
));
836 slot
= htab_find_slot (container
->invalid_hash
,
837 IDENTIFIER_POINTER (name
), NO_INSERT
);
841 obstack_grow (ob
, "*_", 2);
842 go_append_string (ob
, name
);
844 /* The pointer here can be used without the struct or union
845 definition. So this struct or union is a potential dummy
847 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
)))
848 container
->pot_dummy_types
.add (IDENTIFIER_POINTER (name
));
852 if (TREE_CODE (TREE_TYPE (type
)) == FUNCTION_TYPE
)
853 obstack_grow (ob
, "func", 4);
855 obstack_1grow (ob
, '*');
856 if (VOID_TYPE_P (TREE_TYPE (type
)))
857 obstack_grow (ob
, "byte", 4);
860 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
,
867 obstack_1grow (ob
, '[');
868 if (TYPE_DOMAIN (type
) != NULL_TREE
869 && TREE_CODE (TYPE_DOMAIN (type
)) == INTEGER_TYPE
870 && TYPE_MIN_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
871 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
872 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == 0
873 && TYPE_MAX_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
874 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
875 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))))
879 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
"+1",
880 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))));
881 obstack_grow (ob
, buf
, strlen (buf
));
884 obstack_1grow (ob
, '0');
885 obstack_1grow (ob
, ']');
886 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
, false,
893 /* Fall through to RECORD_TYPE case. */
897 unsigned int prev_field_end
;
898 unsigned int known_alignment
;
900 bool emitted_a_field
;
902 /* FIXME: Why is this necessary? Without it we can get a core
903 dump on the s390x headers, or from a file containing simply
904 "typedef struct S T;". */
909 /* Anonymous records and unions are flattened, i.e. they are not put
910 into "struct { ... }". */
911 if (!is_anon_record_or_union
)
912 obstack_grow (ob
, "struct { ", 9);
913 for (field
= TYPE_FIELDS (type
), emitted_a_field
= false;
915 field
= TREE_CHAIN (field
))
917 if (TREE_CODE (field
) != FIELD_DECL
)
919 if (DECL_BIT_FIELD (field
))
920 /* Bit fields are replaced by padding. */
922 /* Only the first non-bitfield field is emitted for unions. */
923 if (!is_union
|| !emitted_a_field
)
925 /* Emit the field. */
927 bool is_anon_substructure
;
928 unsigned int decl_align_unit
;
929 unsigned int decl_offset
;
932 emitted_a_field
= true;
933 is_anon_substructure
=
934 (DECL_NAME (field
) == NULL
935 && (TREE_CODE (TREE_TYPE (field
)) == RECORD_TYPE
936 || TREE_CODE (TREE_TYPE (field
)) == UNION_TYPE
));
937 /* Keep track of the alignment of named substructures, either
938 of the whole record, or the alignment of the emitted field
940 decl_align_unit
= DECL_ALIGN_UNIT (field
);
941 if (!is_anon_substructure
&& decl_align_unit
> known_alignment
)
942 known_alignment
= decl_align_unit
;
943 /* Pad to start of field. */
945 TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field
))
947 (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field
)));
949 unsigned int align_unit
;
951 /* For anonymous records and unions there is no automatic
952 structure alignment, so use 1 as the alignment. */
953 align_unit
= (is_anon_substructure
) ? 1 : decl_align_unit
;
954 *p_art_i
= go_append_padding
955 (ob
, prev_field_end
, decl_offset
, align_unit
, *p_art_i
,
958 if (DECL_SIZE_UNIT (field
))
960 TREE_INT_CST_LOW (DECL_SIZE_UNIT (field
));
961 /* Emit the field name, but not for anonymous records and
963 if (!is_anon_substructure
)
965 if (DECL_NAME (field
) == NULL
)
966 *p_art_i
= go_append_artificial_name (ob
, *p_art_i
);
969 (ob
, field
, container
->keyword_hash
);
970 obstack_1grow (ob
, ' ');
972 /* Do not expand type if a record or union type or a function
974 if (TYPE_NAME (TREE_TYPE (field
)) != NULL_TREE
975 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field
))
976 || (POINTER_TYPE_P (TREE_TYPE (field
))
977 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field
)))
983 name
= TYPE_IDENTIFIER (TREE_TYPE (field
));
985 slot
= htab_find_slot (container
->invalid_hash
,
986 IDENTIFIER_POINTER (name
),
991 obstack_1grow (ob
, '_');
992 go_append_string (ob
, name
);
996 if (!go_format_type (container
, TREE_TYPE (field
), true,
997 false, p_art_i
, is_anon_substructure
))
1000 if (!is_anon_substructure
)
1001 obstack_grow (ob
, "; ", 2);
1007 *p_art_i
= go_append_padding (ob
, prev_field_end
,
1008 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type
)),
1009 1, *p_art_i
, &prev_field_end
);
1011 if (!is_anon_record_or_union
1012 && known_alignment
< TYPE_ALIGN_UNIT (type
))
1017 /* Enforce proper record alignment. */
1018 s
= go_get_uinttype_for_precision
1019 (TYPE_ALIGN (type
), TYPE_UNSIGNED (type
));
1022 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
1023 TYPE_ALIGN (type
), TYPE_UNSIGNED (type
) ? "u" : "");
1027 *p_art_i
= go_force_record_alignment (ob
, s
, *p_art_i
, buf
);
1029 if (!is_anon_record_or_union
)
1030 obstack_1grow (ob
, '}');
1039 function_args_iterator iter
;
1042 /* Go has no way to write a type which is a function but not a
1043 pointer to a function. */
1046 obstack_grow (ob
, "func*", 5);
1050 obstack_1grow (ob
, '(');
1051 is_varargs
= stdarg_p (type
);
1053 FOREACH_FUNCTION_ARGS (type
, arg_type
, iter
)
1055 if (VOID_TYPE_P (arg_type
))
1058 obstack_grow (ob
, ", ", 2);
1059 if (!go_format_type (container
, arg_type
, true, false, NULL
, false))
1065 if (prototype_p (type
))
1066 obstack_grow (ob
, ", ", 2);
1067 obstack_grow (ob
, "...interface{}", 14);
1069 obstack_1grow (ob
, ')');
1071 result
= TREE_TYPE (type
);
1072 if (!VOID_TYPE_P (result
))
1074 obstack_1grow (ob
, ' ');
1075 if (!go_format_type (container
, result
, use_type_name
, false, NULL
,
1083 obstack_grow (ob
, "INVALID-type", 12);
1091 /* Output the type which was built on the type obstack, and then free
1095 go_output_type (class godump_container
*container
)
1099 ob
= &container
->type_obstack
;
1100 obstack_1grow (ob
, '\0');
1101 fputs ((char *) obstack_base (ob
), go_dump_file
);
1102 obstack_free (ob
, obstack_base (ob
));
1105 /* Output a function declaration. */
1108 go_output_fndecl (class godump_container
*container
, tree decl
)
1110 if (!go_format_type (container
, TREE_TYPE (decl
), false, true, NULL
, false))
1111 fprintf (go_dump_file
, "// ");
1112 fprintf (go_dump_file
, "func _%s ",
1113 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1114 go_output_type (container
);
1115 fprintf (go_dump_file
, " __asm__(\"%s\")\n",
1116 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
)));
1119 /* Output a typedef or something like a struct definition. */
1122 go_output_typedef (class godump_container
*container
, tree decl
)
1124 /* If we have an enum type, output the enum constants
1126 if (TREE_CODE (TREE_TYPE (decl
)) == ENUMERAL_TYPE
1127 && TYPE_SIZE (TREE_TYPE (decl
)) != 0
1128 && !container
->decls_seen
.contains (TREE_TYPE (decl
))
1129 && (TYPE_CANONICAL (TREE_TYPE (decl
)) == NULL_TREE
1130 || !container
->decls_seen
.contains
1131 (TYPE_CANONICAL (TREE_TYPE (decl
)))))
1135 for (element
= TYPE_VALUES (TREE_TYPE (decl
));
1136 element
!= NULL_TREE
;
1137 element
= TREE_CHAIN (element
))
1140 struct macro_hash_value
*mhval
;
1142 char buf
[WIDE_INT_PRINT_BUFFER_SIZE
];
1144 name
= IDENTIFIER_POINTER (TREE_PURPOSE (element
));
1146 /* Sometimes a name will be defined as both an enum constant
1147 and a macro. Avoid duplicate definition errors by
1148 treating enum constants as macros. */
1149 mhval
= XNEW (struct macro_hash_value
);
1150 mhval
->name
= xstrdup (name
);
1151 mhval
->value
= NULL
;
1152 slot
= htab_find_slot (macro_hash
, mhval
, INSERT
);
1154 macro_hash_del (*slot
);
1156 if (tree_fits_shwi_p (TREE_VALUE (element
)))
1157 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
,
1158 tree_to_shwi (TREE_VALUE (element
)));
1159 else if (tree_fits_uhwi_p (TREE_VALUE (element
)))
1160 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_UNSIGNED
,
1161 tree_to_uhwi (TREE_VALUE (element
)));
1163 print_hex (wi::to_wide (element
), buf
);
1165 mhval
->value
= xstrdup (buf
);
1168 container
->decls_seen
.add (TREE_TYPE (decl
));
1169 if (TYPE_CANONICAL (TREE_TYPE (decl
)) != NULL_TREE
)
1170 container
->decls_seen
.add (TYPE_CANONICAL (TREE_TYPE (decl
)));
1173 if (DECL_NAME (decl
) != NULL_TREE
)
1178 type
= IDENTIFIER_POINTER (DECL_NAME (decl
));
1179 /* If type defined already, skip. */
1180 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1183 *slot
= CONST_CAST (void *, (const void *) type
);
1185 if (!go_format_type (container
, TREE_TYPE (decl
), true, false, NULL
,
1188 fprintf (go_dump_file
, "// ");
1189 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1190 *slot
= CONST_CAST (void *, (const void *) type
);
1192 fprintf (go_dump_file
, "type _%s ",
1193 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1194 go_output_type (container
);
1196 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1198 HOST_WIDE_INT size
= int_size_in_bytes (TREE_TYPE (decl
));
1201 fprintf (go_dump_file
,
1202 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1203 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1207 container
->decls_seen
.add (decl
);
1209 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1215 type
= IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl
))));
1216 /* If type defined already, skip. */
1217 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1220 *slot
= CONST_CAST (void *, (const void *) type
);
1222 if (!go_format_type (container
, TREE_TYPE (decl
), false, false, NULL
,
1225 fprintf (go_dump_file
, "// ");
1226 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1227 *slot
= CONST_CAST (void *, (const void *) type
);
1229 fprintf (go_dump_file
, "type _%s ",
1230 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))));
1231 go_output_type (container
);
1233 size
= int_size_in_bytes (TREE_TYPE (decl
));
1235 fprintf (go_dump_file
,
1236 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1237 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))),
1243 fprintf (go_dump_file
, "\n");
1246 /* Output a variable. */
1249 go_output_var (class godump_container
*container
, tree decl
)
1255 if (container
->decls_seen
.contains (decl
)
1256 || container
->decls_seen
.contains (DECL_NAME (decl
)))
1258 container
->decls_seen
.add (decl
);
1259 container
->decls_seen
.add (DECL_NAME (decl
));
1261 type_name
= TYPE_NAME (TREE_TYPE (decl
));
1263 if (type_name
!= NULL_TREE
&& TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1265 else if (type_name
!= NULL_TREE
&& TREE_CODE (type_name
) == TYPE_DECL
1266 && DECL_SOURCE_LOCATION (type_name
) != BUILTINS_LOCATION
1267 && DECL_NAME (type_name
))
1268 id
= DECL_NAME (type_name
);
1270 && (!htab_find_slot (container
->type_hash
, IDENTIFIER_POINTER (id
),
1272 || htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (id
),
1275 if (id
!= NULL_TREE
)
1279 ob
= &container
->type_obstack
;
1280 obstack_1grow (ob
, '_');
1281 go_append_string (ob
, id
);
1282 is_valid
= htab_find_slot (container
->type_hash
, IDENTIFIER_POINTER (id
),
1286 is_valid
= go_format_type (container
, TREE_TYPE (decl
), true, false, NULL
,
1289 && htab_find_slot (container
->type_hash
,
1290 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1293 /* There is already a type with this name, probably from a
1294 struct tag. Prefer the type to the variable. */
1298 fprintf (go_dump_file
, "// ");
1300 fprintf (go_dump_file
, "var _%s ",
1301 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1302 go_output_type (container
);
1303 fprintf (go_dump_file
, "\n");
1305 /* Sometimes an extern variable is declared with an unknown struct
1307 if (type_name
!= NULL_TREE
&& RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1309 if (TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1310 container
->pot_dummy_types
.add (IDENTIFIER_POINTER (type_name
));
1311 else if (TREE_CODE (type_name
) == TYPE_DECL
)
1312 container
->pot_dummy_types
.add
1313 (IDENTIFIER_POINTER (DECL_NAME (type_name
)));
1317 /* Output the final value of a preprocessor macro or enum constant.
1318 This is called via htab_traverse_noresize. */
1321 go_print_macro (void **slot
, void *arg ATTRIBUTE_UNUSED
)
1323 struct macro_hash_value
*mhval
= (struct macro_hash_value
*) *slot
;
1324 fprintf (go_dump_file
, "const _%s = %s\n", mhval
->name
, mhval
->value
);
1328 /* Build a hash table with the Go keywords. */
1330 static const char * const keywords
[] = {
1331 "__asm__", "break", "case", "chan", "const", "continue", "default",
1332 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1333 "import", "interface", "map", "package", "range", "return", "select",
1334 "struct", "switch", "type", "var"
1338 keyword_hash_init (class godump_container
*container
)
1341 size_t count
= sizeof (keywords
) / sizeof (keywords
[0]);
1344 for (i
= 0; i
< count
; i
++)
1346 slot
= htab_find_slot (container
->keyword_hash
, keywords
[i
], INSERT
);
1347 *slot
= CONST_CAST (void *, (const void *) keywords
[i
]);
1351 /* Traversing the pot_dummy_types and seeing which types are present
1352 in the global types hash table and creating dummy definitions if
1353 not found. This function is invoked by hash_set::traverse. */
1356 find_dummy_types (const char *const &ptr
, godump_container
*adata
)
1358 class godump_container
*data
= (class godump_container
*) adata
;
1359 const char *type
= (const char *) ptr
;
1363 slot
= htab_find_slot (data
->type_hash
, type
, NO_INSERT
);
1364 islot
= htab_find_slot (data
->invalid_hash
, type
, NO_INSERT
);
1365 if (slot
== NULL
|| islot
!= NULL
)
1366 fprintf (go_dump_file
, "type _%s struct {}\n", type
);
1370 /* Output symbols. */
1373 go_finish (const char *filename
)
1375 class godump_container container
;
1379 real_debug_hooks
->finish (filename
);
1381 container
.type_hash
= htab_create (100, htab_hash_string
,
1382 string_hash_eq
, NULL
);
1383 container
.invalid_hash
= htab_create (10, htab_hash_string
,
1384 string_hash_eq
, NULL
);
1385 container
.keyword_hash
= htab_create (50, htab_hash_string
,
1386 string_hash_eq
, NULL
);
1387 obstack_init (&container
.type_obstack
);
1389 keyword_hash_init (&container
);
1391 FOR_EACH_VEC_SAFE_ELT (queue
, ix
, decl
)
1393 switch (TREE_CODE (decl
))
1396 go_output_fndecl (&container
, decl
);
1400 go_output_typedef (&container
, decl
);
1404 go_output_var (&container
, decl
);
1412 htab_traverse_noresize (macro_hash
, go_print_macro
, NULL
);
1414 /* To emit dummy definitions. */
1415 container
.pot_dummy_types
.traverse
<godump_container
*, find_dummy_types
>
1418 htab_delete (container
.type_hash
);
1419 htab_delete (container
.invalid_hash
);
1420 htab_delete (container
.keyword_hash
);
1421 obstack_free (&container
.type_obstack
, NULL
);
1425 if (fclose (go_dump_file
) != 0)
1426 error ("could not close Go dump file: %m");
1427 go_dump_file
= NULL
;
1430 /* Set up our hooks. */
1432 const struct gcc_debug_hooks
*
1433 dump_go_spec_init (const char *filename
, const struct gcc_debug_hooks
*hooks
)
1435 go_dump_file
= fopen (filename
, "w");
1436 if (go_dump_file
== NULL
)
1438 error ("could not open Go dump file %qs: %m", filename
);
1442 go_debug_hooks
= *hooks
;
1443 real_debug_hooks
= hooks
;
1445 go_debug_hooks
.finish
= go_finish
;
1446 go_debug_hooks
.define
= go_define
;
1447 go_debug_hooks
.undef
= go_undef
;
1448 go_debug_hooks
.function_decl
= go_function_decl
;
1449 go_debug_hooks
.early_global_decl
= go_early_global_decl
;
1450 go_debug_hooks
.late_global_decl
= go_late_global_decl
;
1451 go_debug_hooks
.type_decl
= go_type_decl
;
1453 macro_hash
= htab_create (100, macro_hash_hashval
, macro_hash_eq
,
1456 return &go_debug_hooks
;
1459 #include "gt-godump.h"