1 /* Output Go language descriptions of types.
2 Copyright (C) 2008-2019 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 struct godump_container
540 /* DECLs that we have already seen. */
541 hash_set
<tree
> decls_seen
;
543 /* Types which may potentially have to be defined as dummy
545 hash_set
<const char *> pot_dummy_types
;
550 /* Global type definitions. */
556 /* Obstack used to write out a type definition. */
557 struct obstack type_obstack
;
560 /* Append an IDENTIFIER_NODE to OB. */
563 go_append_string (struct obstack
*ob
, tree id
)
565 obstack_grow (ob
, IDENTIFIER_POINTER (id
), IDENTIFIER_LENGTH (id
));
568 /* Given an integer PRECISION in bits, returns a constant string that is the
569 matching go int or uint type (depending on the IS_UNSIGNED flag). Returns a
570 NULL pointer if there is no matching go type. */
573 go_get_uinttype_for_precision (unsigned int precision
, bool is_unsigned
)
578 return is_unsigned
? "uint8" : "int8";
580 return is_unsigned
? "uint16" : "int16";
582 return is_unsigned
? "uint32" : "int32";
584 return is_unsigned
? "uint64" : "int64";
590 /* Append an artificial variable name with the suffix _INDEX to OB. Returns
594 go_append_artificial_name (struct obstack
*ob
, unsigned int index
)
598 /* FIXME: identifier may not be unique. */
599 obstack_grow (ob
, "Godump_", 7);
600 snprintf (buf
, sizeof buf
, "%u", index
);
601 obstack_grow (ob
, buf
, strlen (buf
));
606 /* Append the variable name from DECL to OB. If the name is in the
607 KEYWORD_HASH, prepend an '_'. */
610 go_append_decl_name (struct obstack
*ob
, tree decl
, htab_t keyword_hash
)
612 const char *var_name
;
615 /* Start variable name with an underscore if a keyword. */
616 var_name
= IDENTIFIER_POINTER (DECL_NAME (decl
));
617 slot
= htab_find_slot (keyword_hash
, var_name
, NO_INSERT
);
619 obstack_1grow (ob
, '_');
620 go_append_string (ob
, DECL_NAME (decl
));
623 /* Appends a byte array with the necessary number of elements and the name
624 "Godump_INDEX_pad" to pad from FROM_OFFSET to TO_OFFSET to OB assuming that
625 the next field is automatically aligned to ALIGN_UNITS. Returns INDEX + 1,
626 or INDEX if no padding had to be appended. The resulting offset where the
627 next field is allocated is returned through RET_OFFSET. */
630 go_append_padding (struct obstack
*ob
, unsigned int from_offset
,
631 unsigned int to_offset
, unsigned int align_units
,
632 unsigned int index
, unsigned int *ret_offset
)
634 if (from_offset
% align_units
> 0)
635 from_offset
+= align_units
- (from_offset
% align_units
);
636 gcc_assert (to_offset
>= from_offset
);
637 if (to_offset
> from_offset
)
641 index
= go_append_artificial_name (ob
, index
);
642 snprintf (buf
, sizeof buf
, "_pad [%u]byte; ", to_offset
- from_offset
);
643 obstack_grow (ob
, buf
, strlen (buf
));
645 *ret_offset
= to_offset
;
650 /* Appends an array of type TYPE_STRING with zero elements and the name
651 "Godump_INDEX_align" to OB. If TYPE_STRING is a null pointer, ERROR_STRING
652 is appended instead of the type. Returns INDEX + 1. */
655 go_force_record_alignment (struct obstack
*ob
, const char *type_string
,
656 unsigned int index
, const char *error_string
)
658 index
= go_append_artificial_name (ob
, index
);
659 obstack_grow (ob
, "_align ", 7);
660 if (type_string
== NULL
)
661 obstack_grow (ob
, error_string
, strlen (error_string
));
664 obstack_grow (ob
, "[0]", 3);
665 obstack_grow (ob
, type_string
, strlen (type_string
));
667 obstack_grow (ob
, "; ", 2);
672 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
673 USE_TYPE_NAME is true if we can simply use a type name here without
674 needing to define it. IS_FUNC_OK is true if we can output a func
675 type here; the "func" keyword will already have been added.
676 Return true if the type can be represented in Go, false otherwise.
677 P_ART_I is used for indexing artificial elements in nested structures and
678 should always be a NULL pointer when called, except by certain recursive
679 calls from go_format_type() itself. */
682 go_format_type (struct godump_container
*container
, tree type
,
683 bool use_type_name
, bool is_func_ok
, unsigned int *p_art_i
,
684 bool is_anon_record_or_union
)
688 unsigned int art_i_dummy
;
689 bool is_union
= false;
694 p_art_i
= &art_i_dummy
;
697 ob
= &container
->type_obstack
;
699 if (TYPE_NAME (type
) != NULL_TREE
700 && (container
->decls_seen
.contains (type
)
701 || container
->decls_seen
.contains (TYPE_NAME (type
)))
702 && (AGGREGATE_TYPE_P (type
)
703 || POINTER_TYPE_P (type
)
704 || TREE_CODE (type
) == FUNCTION_TYPE
))
709 name
= TYPE_IDENTIFIER (type
);
711 slot
= htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (name
),
716 obstack_1grow (ob
, '_');
717 go_append_string (ob
, name
);
721 container
->decls_seen
.add (type
);
723 switch (TREE_CODE (type
))
729 slot
= htab_find_slot (container
->invalid_hash
,
730 IDENTIFIER_POINTER (DECL_NAME (type
)),
735 obstack_1grow (ob
, '_');
736 go_append_string (ob
, DECL_NAME (type
));
746 s
= go_get_uinttype_for_precision (TYPE_PRECISION (type
),
747 TYPE_UNSIGNED (type
));
750 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
751 TYPE_PRECISION (type
),
752 TYPE_UNSIGNED (type
) ? "u" : "");
756 obstack_grow (ob
, s
, strlen (s
));
765 switch (TYPE_PRECISION (type
))
774 snprintf (buf
, sizeof buf
, "INVALID-float-%u",
775 TYPE_PRECISION (type
));
780 obstack_grow (ob
, s
, strlen (s
));
790 real_type
= TREE_TYPE (type
);
791 if (TREE_CODE (real_type
) == REAL_TYPE
)
793 switch (TYPE_PRECISION (real_type
))
802 snprintf (buf
, sizeof buf
, "INVALID-complex-%u",
803 2 * TYPE_PRECISION (real_type
));
811 s
= "INVALID-complex-non-real";
814 obstack_grow (ob
, s
, strlen (s
));
819 obstack_grow (ob
, "bool", 4);
824 && TYPE_NAME (TREE_TYPE (type
)) != NULL_TREE
825 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
))
826 || (POINTER_TYPE_P (TREE_TYPE (type
))
827 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type
)))
833 name
= TYPE_IDENTIFIER (TREE_TYPE (type
));
835 slot
= htab_find_slot (container
->invalid_hash
,
836 IDENTIFIER_POINTER (name
), NO_INSERT
);
840 obstack_grow (ob
, "*_", 2);
841 go_append_string (ob
, name
);
843 /* The pointer here can be used without the struct or union
844 definition. So this struct or union is a potential dummy
846 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
)))
847 container
->pot_dummy_types
.add (IDENTIFIER_POINTER (name
));
851 if (TREE_CODE (TREE_TYPE (type
)) == FUNCTION_TYPE
)
852 obstack_grow (ob
, "func", 4);
854 obstack_1grow (ob
, '*');
855 if (VOID_TYPE_P (TREE_TYPE (type
)))
856 obstack_grow (ob
, "byte", 4);
859 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
,
866 obstack_1grow (ob
, '[');
867 if (TYPE_DOMAIN (type
) != NULL_TREE
868 && TREE_CODE (TYPE_DOMAIN (type
)) == INTEGER_TYPE
869 && TYPE_MIN_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
870 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
871 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == 0
872 && TYPE_MAX_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
873 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
874 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))))
878 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
"+1",
879 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))));
880 obstack_grow (ob
, buf
, strlen (buf
));
883 obstack_1grow (ob
, '0');
884 obstack_1grow (ob
, ']');
885 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
, false,
892 /* Fall through to RECORD_TYPE case. */
896 unsigned int prev_field_end
;
897 unsigned int known_alignment
;
899 bool emitted_a_field
;
901 /* FIXME: Why is this necessary? Without it we can get a core
902 dump on the s390x headers, or from a file containing simply
903 "typedef struct S T;". */
908 /* Anonymous records and unions are flattened, i.e. they are not put
909 into "struct { ... }". */
910 if (!is_anon_record_or_union
)
911 obstack_grow (ob
, "struct { ", 9);
912 for (field
= TYPE_FIELDS (type
), emitted_a_field
= false;
914 field
= TREE_CHAIN (field
))
916 if (TREE_CODE (field
) != FIELD_DECL
)
918 if (DECL_BIT_FIELD (field
))
919 /* Bit fields are replaced by padding. */
921 /* Only the first non-bitfield field is emitted for unions. */
922 if (!is_union
|| !emitted_a_field
)
924 /* Emit the field. */
926 bool is_anon_substructure
;
927 unsigned int decl_align_unit
;
928 unsigned int decl_offset
;
931 emitted_a_field
= true;
932 is_anon_substructure
=
933 (DECL_NAME (field
) == NULL
934 && (TREE_CODE (TREE_TYPE (field
)) == RECORD_TYPE
935 || TREE_CODE (TREE_TYPE (field
)) == UNION_TYPE
));
936 /* Keep track of the alignment of named substructures, either
937 of the whole record, or the alignment of the emitted field
939 decl_align_unit
= DECL_ALIGN_UNIT (field
);
940 if (!is_anon_substructure
&& decl_align_unit
> known_alignment
)
941 known_alignment
= decl_align_unit
;
942 /* Pad to start of field. */
944 TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field
))
946 (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field
)));
948 unsigned int align_unit
;
950 /* For anonymous records and unions there is no automatic
951 structure alignment, so use 1 as the alignment. */
952 align_unit
= (is_anon_substructure
) ? 1 : decl_align_unit
;
953 *p_art_i
= go_append_padding
954 (ob
, prev_field_end
, decl_offset
, align_unit
, *p_art_i
,
957 if (DECL_SIZE_UNIT (field
))
959 TREE_INT_CST_LOW (DECL_SIZE_UNIT (field
));
960 /* Emit the field name, but not for anonymous records and
962 if (!is_anon_substructure
)
964 if (DECL_NAME (field
) == NULL
)
965 *p_art_i
= go_append_artificial_name (ob
, *p_art_i
);
968 (ob
, field
, container
->keyword_hash
);
969 obstack_1grow (ob
, ' ');
971 /* Do not expand type if a record or union type or a function
973 if (TYPE_NAME (TREE_TYPE (field
)) != NULL_TREE
974 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field
))
975 || (POINTER_TYPE_P (TREE_TYPE (field
))
976 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field
)))
982 name
= TYPE_IDENTIFIER (TREE_TYPE (field
));
984 slot
= htab_find_slot (container
->invalid_hash
,
985 IDENTIFIER_POINTER (name
),
990 obstack_1grow (ob
, '_');
991 go_append_string (ob
, name
);
995 if (!go_format_type (container
, TREE_TYPE (field
), true,
996 false, p_art_i
, is_anon_substructure
))
999 if (!is_anon_substructure
)
1000 obstack_grow (ob
, "; ", 2);
1006 *p_art_i
= go_append_padding (ob
, prev_field_end
,
1007 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type
)),
1008 1, *p_art_i
, &prev_field_end
);
1010 if (!is_anon_record_or_union
1011 && known_alignment
< TYPE_ALIGN_UNIT (type
))
1016 /* Enforce proper record alignment. */
1017 s
= go_get_uinttype_for_precision
1018 (TYPE_ALIGN (type
), TYPE_UNSIGNED (type
));
1021 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
1022 TYPE_ALIGN (type
), TYPE_UNSIGNED (type
) ? "u" : "");
1026 *p_art_i
= go_force_record_alignment (ob
, s
, *p_art_i
, buf
);
1028 if (!is_anon_record_or_union
)
1029 obstack_1grow (ob
, '}');
1038 function_args_iterator iter
;
1041 /* Go has no way to write a type which is a function but not a
1042 pointer to a function. */
1045 obstack_grow (ob
, "func*", 5);
1049 obstack_1grow (ob
, '(');
1050 is_varargs
= stdarg_p (type
);
1052 FOREACH_FUNCTION_ARGS (type
, arg_type
, iter
)
1054 if (VOID_TYPE_P (arg_type
))
1057 obstack_grow (ob
, ", ", 2);
1058 if (!go_format_type (container
, arg_type
, true, false, NULL
, false))
1064 if (prototype_p (type
))
1065 obstack_grow (ob
, ", ", 2);
1066 obstack_grow (ob
, "...interface{}", 14);
1068 obstack_1grow (ob
, ')');
1070 result
= TREE_TYPE (type
);
1071 if (!VOID_TYPE_P (result
))
1073 obstack_1grow (ob
, ' ');
1074 if (!go_format_type (container
, result
, use_type_name
, false, NULL
,
1082 obstack_grow (ob
, "INVALID-type", 12);
1090 /* Output the type which was built on the type obstack, and then free
1094 go_output_type (struct godump_container
*container
)
1098 ob
= &container
->type_obstack
;
1099 obstack_1grow (ob
, '\0');
1100 fputs ((char *) obstack_base (ob
), go_dump_file
);
1101 obstack_free (ob
, obstack_base (ob
));
1104 /* Output a function declaration. */
1107 go_output_fndecl (struct godump_container
*container
, tree decl
)
1109 if (!go_format_type (container
, TREE_TYPE (decl
), false, true, NULL
, false))
1110 fprintf (go_dump_file
, "// ");
1111 fprintf (go_dump_file
, "func _%s ",
1112 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1113 go_output_type (container
);
1114 fprintf (go_dump_file
, " __asm__(\"%s\")\n",
1115 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
)));
1118 /* Output a typedef or something like a struct definition. */
1121 go_output_typedef (struct godump_container
*container
, tree decl
)
1123 /* If we have an enum type, output the enum constants
1125 if (TREE_CODE (TREE_TYPE (decl
)) == ENUMERAL_TYPE
1126 && TYPE_SIZE (TREE_TYPE (decl
)) != 0
1127 && !container
->decls_seen
.contains (TREE_TYPE (decl
))
1128 && (TYPE_CANONICAL (TREE_TYPE (decl
)) == NULL_TREE
1129 || !container
->decls_seen
.contains
1130 (TYPE_CANONICAL (TREE_TYPE (decl
)))))
1134 for (element
= TYPE_VALUES (TREE_TYPE (decl
));
1135 element
!= NULL_TREE
;
1136 element
= TREE_CHAIN (element
))
1139 struct macro_hash_value
*mhval
;
1141 char buf
[WIDE_INT_PRINT_BUFFER_SIZE
];
1143 name
= IDENTIFIER_POINTER (TREE_PURPOSE (element
));
1145 /* Sometimes a name will be defined as both an enum constant
1146 and a macro. Avoid duplicate definition errors by
1147 treating enum constants as macros. */
1148 mhval
= XNEW (struct macro_hash_value
);
1149 mhval
->name
= xstrdup (name
);
1150 mhval
->value
= NULL
;
1151 slot
= htab_find_slot (macro_hash
, mhval
, INSERT
);
1153 macro_hash_del (*slot
);
1155 if (tree_fits_shwi_p (TREE_VALUE (element
)))
1156 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
,
1157 tree_to_shwi (TREE_VALUE (element
)));
1158 else if (tree_fits_uhwi_p (TREE_VALUE (element
)))
1159 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_UNSIGNED
,
1160 tree_to_uhwi (TREE_VALUE (element
)));
1162 print_hex (wi::to_wide (element
), buf
);
1164 mhval
->value
= xstrdup (buf
);
1167 container
->decls_seen
.add (TREE_TYPE (decl
));
1168 if (TYPE_CANONICAL (TREE_TYPE (decl
)) != NULL_TREE
)
1169 container
->decls_seen
.add (TYPE_CANONICAL (TREE_TYPE (decl
)));
1172 if (DECL_NAME (decl
) != NULL_TREE
)
1177 type
= IDENTIFIER_POINTER (DECL_NAME (decl
));
1178 /* If type defined already, skip. */
1179 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1182 *slot
= CONST_CAST (void *, (const void *) type
);
1184 if (!go_format_type (container
, TREE_TYPE (decl
), true, false, NULL
,
1187 fprintf (go_dump_file
, "// ");
1188 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1189 *slot
= CONST_CAST (void *, (const void *) type
);
1191 fprintf (go_dump_file
, "type _%s ",
1192 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1193 go_output_type (container
);
1195 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1197 HOST_WIDE_INT size
= int_size_in_bytes (TREE_TYPE (decl
));
1200 fprintf (go_dump_file
,
1201 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1202 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1206 container
->decls_seen
.add (decl
);
1208 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1214 type
= IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl
))));
1215 /* If type defined already, skip. */
1216 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1219 *slot
= CONST_CAST (void *, (const void *) type
);
1221 if (!go_format_type (container
, TREE_TYPE (decl
), false, false, NULL
,
1224 fprintf (go_dump_file
, "// ");
1225 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1226 *slot
= CONST_CAST (void *, (const void *) type
);
1228 fprintf (go_dump_file
, "type _%s ",
1229 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))));
1230 go_output_type (container
);
1232 size
= int_size_in_bytes (TREE_TYPE (decl
));
1234 fprintf (go_dump_file
,
1235 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1236 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))),
1242 fprintf (go_dump_file
, "\n");
1245 /* Output a variable. */
1248 go_output_var (struct godump_container
*container
, tree decl
)
1254 if (container
->decls_seen
.contains (decl
)
1255 || container
->decls_seen
.contains (DECL_NAME (decl
)))
1257 container
->decls_seen
.add (decl
);
1258 container
->decls_seen
.add (DECL_NAME (decl
));
1260 type_name
= TYPE_NAME (TREE_TYPE (decl
));
1262 if (type_name
!= NULL_TREE
&& TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1264 else if (type_name
!= NULL_TREE
&& TREE_CODE (type_name
) == TYPE_DECL
1265 && DECL_SOURCE_LOCATION (type_name
) != BUILTINS_LOCATION
1266 && DECL_NAME (type_name
))
1267 id
= DECL_NAME (type_name
);
1269 && (!htab_find_slot (container
->type_hash
, IDENTIFIER_POINTER (id
),
1271 || htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (id
),
1274 if (id
!= NULL_TREE
)
1278 ob
= &container
->type_obstack
;
1279 obstack_1grow (ob
, '_');
1280 go_append_string (ob
, id
);
1281 is_valid
= htab_find_slot (container
->type_hash
, IDENTIFIER_POINTER (id
),
1285 is_valid
= go_format_type (container
, TREE_TYPE (decl
), true, false, NULL
,
1288 && htab_find_slot (container
->type_hash
,
1289 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1292 /* There is already a type with this name, probably from a
1293 struct tag. Prefer the type to the variable. */
1297 fprintf (go_dump_file
, "// ");
1299 fprintf (go_dump_file
, "var _%s ",
1300 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1301 go_output_type (container
);
1302 fprintf (go_dump_file
, "\n");
1304 /* Sometimes an extern variable is declared with an unknown struct
1306 if (type_name
!= NULL_TREE
&& RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1308 if (TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1309 container
->pot_dummy_types
.add (IDENTIFIER_POINTER (type_name
));
1310 else if (TREE_CODE (type_name
) == TYPE_DECL
)
1311 container
->pot_dummy_types
.add
1312 (IDENTIFIER_POINTER (DECL_NAME (type_name
)));
1316 /* Output the final value of a preprocessor macro or enum constant.
1317 This is called via htab_traverse_noresize. */
1320 go_print_macro (void **slot
, void *arg ATTRIBUTE_UNUSED
)
1322 struct macro_hash_value
*mhval
= (struct macro_hash_value
*) *slot
;
1323 fprintf (go_dump_file
, "const _%s = %s\n", mhval
->name
, mhval
->value
);
1327 /* Build a hash table with the Go keywords. */
1329 static const char * const keywords
[] = {
1330 "__asm__", "break", "case", "chan", "const", "continue", "default",
1331 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1332 "import", "interface", "map", "package", "range", "return", "select",
1333 "struct", "switch", "type", "var"
1337 keyword_hash_init (struct godump_container
*container
)
1340 size_t count
= sizeof (keywords
) / sizeof (keywords
[0]);
1343 for (i
= 0; i
< count
; i
++)
1345 slot
= htab_find_slot (container
->keyword_hash
, keywords
[i
], INSERT
);
1346 *slot
= CONST_CAST (void *, (const void *) keywords
[i
]);
1350 /* Traversing the pot_dummy_types and seeing which types are present
1351 in the global types hash table and creating dummy definitions if
1352 not found. This function is invoked by hash_set::traverse. */
1355 find_dummy_types (const char *const &ptr
, godump_container
*adata
)
1357 struct godump_container
*data
= (struct godump_container
*) adata
;
1358 const char *type
= (const char *) ptr
;
1362 slot
= htab_find_slot (data
->type_hash
, type
, NO_INSERT
);
1363 islot
= htab_find_slot (data
->invalid_hash
, type
, NO_INSERT
);
1364 if (slot
== NULL
|| islot
!= NULL
)
1365 fprintf (go_dump_file
, "type _%s struct {}\n", type
);
1369 /* Output symbols. */
1372 go_finish (const char *filename
)
1374 struct godump_container container
;
1378 real_debug_hooks
->finish (filename
);
1380 container
.type_hash
= htab_create (100, htab_hash_string
,
1381 string_hash_eq
, NULL
);
1382 container
.invalid_hash
= htab_create (10, htab_hash_string
,
1383 string_hash_eq
, NULL
);
1384 container
.keyword_hash
= htab_create (50, htab_hash_string
,
1385 string_hash_eq
, NULL
);
1386 obstack_init (&container
.type_obstack
);
1388 keyword_hash_init (&container
);
1390 FOR_EACH_VEC_SAFE_ELT (queue
, ix
, decl
)
1392 switch (TREE_CODE (decl
))
1395 go_output_fndecl (&container
, decl
);
1399 go_output_typedef (&container
, decl
);
1403 go_output_var (&container
, decl
);
1411 htab_traverse_noresize (macro_hash
, go_print_macro
, NULL
);
1413 /* To emit dummy definitions. */
1414 container
.pot_dummy_types
.traverse
<godump_container
*, find_dummy_types
>
1417 htab_delete (container
.type_hash
);
1418 htab_delete (container
.invalid_hash
);
1419 htab_delete (container
.keyword_hash
);
1420 obstack_free (&container
.type_obstack
, NULL
);
1424 if (fclose (go_dump_file
) != 0)
1425 error ("could not close Go dump file: %m");
1426 go_dump_file
= NULL
;
1429 /* Set up our hooks. */
1431 const struct gcc_debug_hooks
*
1432 dump_go_spec_init (const char *filename
, const struct gcc_debug_hooks
*hooks
)
1434 go_dump_file
= fopen (filename
, "w");
1435 if (go_dump_file
== NULL
)
1437 error ("could not open Go dump file %qs: %m", filename
);
1441 go_debug_hooks
= *hooks
;
1442 real_debug_hooks
= hooks
;
1444 go_debug_hooks
.finish
= go_finish
;
1445 go_debug_hooks
.define
= go_define
;
1446 go_debug_hooks
.undef
= go_undef
;
1447 go_debug_hooks
.function_decl
= go_function_decl
;
1448 go_debug_hooks
.early_global_decl
= go_early_global_decl
;
1449 go_debug_hooks
.late_global_decl
= go_late_global_decl
;
1450 go_debug_hooks
.type_decl
= go_type_decl
;
1452 macro_hash
= htab_create (100, macro_hash_hashval
, macro_hash_eq
,
1455 return &go_debug_hooks
;
1458 #include "gt-godump.h"