1 /* Output Go language descriptions of types.
2 Copyright (C) 2008-2016 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 "wide-int-print.h"
35 #include "diagnostic-core.h"
37 #include "stor-layout.h"
39 /* We dump this information from the debug hooks. This gives us a
40 stable and maintainable API to hook into. In order to work
41 correctly when -g is used, we build our own hooks structure which
42 wraps the hooks we need to change. */
44 /* Our debug hooks. This is initialized by dump_go_spec_init. */
46 static struct gcc_debug_hooks go_debug_hooks
;
48 /* The real debug hooks. */
50 static const struct gcc_debug_hooks
*real_debug_hooks
;
52 /* The file where we should write information. */
54 static FILE *go_dump_file
;
56 /* A queue of decls to output. */
58 static GTY(()) vec
<tree
, va_gc
> *queue
;
60 /* A hash table of macros we have seen. */
62 static htab_t macro_hash
;
64 /* The type of a value in macro_hash. */
66 struct macro_hash_value
68 /* The name stored in the hash table. */
70 /* The value of the macro. */
74 /* Returns the number of units necessary to represent an integer with the given
75 PRECISION (in bits). */
77 static inline unsigned int
78 precision_to_units (unsigned int precision
)
80 return (precision
+ BITS_PER_UNIT
- 1) / BITS_PER_UNIT
;
83 /* Calculate the hash value for an entry in the macro hash table. */
86 macro_hash_hashval (const void *val
)
88 const struct macro_hash_value
*mhval
= (const struct macro_hash_value
*) val
;
89 return htab_hash_string (mhval
->name
);
92 /* Compare values in the macro hash table for equality. */
95 macro_hash_eq (const void *v1
, const void *v2
)
97 const struct macro_hash_value
*mhv1
= (const struct macro_hash_value
*) v1
;
98 const struct macro_hash_value
*mhv2
= (const struct macro_hash_value
*) v2
;
99 return strcmp (mhv1
->name
, mhv2
->name
) == 0;
102 /* Free values deleted from the macro hash table. */
105 macro_hash_del (void *v
)
107 struct macro_hash_value
*mhv
= (struct macro_hash_value
*) v
;
108 XDELETEVEC (mhv
->name
);
109 XDELETEVEC (mhv
->value
);
113 /* For the string hash tables. */
116 string_hash_eq (const void *y1
, const void *y2
)
118 return strcmp ((const char *) y1
, (const char *) y2
) == 0;
121 /* A macro definition. */
124 go_define (unsigned int lineno
, const char *buffer
)
127 const char *name_end
;
133 struct macro_hash_value
*mhval
;
138 real_debug_hooks
->define (lineno
, buffer
);
140 /* Skip macro functions. */
141 for (p
= buffer
; *p
!= '\0' && *p
!= ' '; ++p
)
154 copy
= XNEWVEC (char, name_end
- buffer
+ 1);
155 memcpy (copy
, buffer
, name_end
- buffer
);
156 copy
[name_end
- buffer
] = '\0';
158 mhval
= XNEW (struct macro_hash_value
);
162 hashval
= htab_hash_string (copy
);
163 slot
= htab_find_slot_with_hash (macro_hash
, mhval
, hashval
, NO_INSERT
);
165 /* For simplicity, we force all names to be hidden by adding an
166 initial underscore, and let the user undo this as needed. */
167 out_len
= strlen (p
) * 2 + 1;
168 out_buffer
= XNEWVEC (char, out_len
);
171 need_operand
= false;
176 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
177 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
178 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
179 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
181 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
182 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
183 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
184 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
188 /* The start of an identifier. Technically we should also
189 worry about UTF-8 identifiers, but they are not a
190 problem for practical uses of -fdump-go-spec so we
191 don't worry about them. */
194 struct macro_hash_value idval
;
200 while (ISALNUM (*p
) || *p
== '_')
202 n
= XALLOCAVEC (char, p
- start
+ 1);
203 memcpy (n
, start
, p
- start
);
207 if (htab_find (macro_hash
, &idval
) == NULL
)
209 /* This is a reference to a name which was not defined
215 memcpy (q
, start
, p
- start
);
219 need_operand
= false;
227 case '0': case '1': case '2': case '3': case '4':
228 case '5': case '6': case '7': case '8': case '9':
235 if (*p
== '0' && (p
[1] == 'x' || p
[1] == 'X'))
240 while (ISDIGIT (*p
) || *p
== '.' || *p
== 'e' || *p
== 'E'
242 && ((*p
>= 'a' && *p
<= 'f')
243 || (*p
>= 'A' && *p
<= 'F'))))
245 memcpy (q
, start
, p
- start
);
247 while (*p
== 'u' || *p
== 'U' || *p
== 'l' || *p
== 'L'
248 || *p
== 'f' || *p
== 'F'
249 || *p
== 'd' || *p
== 'D')
251 /* Go doesn't use any of these trailing type
256 /* We'll pick up the exponent, if any, as an
260 need_operand
= false;
269 /* Always OK, not part of an operand, presumed to start an
273 need_operand
= false;
277 /* OK if we don't need an operand, and presumed to indicate
286 /* Always OK, but not part of an operand. */
291 case '*': case '/': case '%': case '|': case '&': case '^':
292 /* Must be a binary operator. */
304 /* Must be a binary operator. */
316 /* Must be a binary operator. */
325 /* Must be a unary operator. */
333 /* Must be a binary operand, may be << or >> or <= or >=. */
337 if (*p
== *(p
- 1) || *p
== '=')
344 /* Must be a unary operand, must be translated for Go. */
381 case '0': case '1': case '2': case '3':
382 case '4': case '5': case '6': case '7':
384 while (*p
>= '0' && *p
<= '7')
389 /* Go octal characters are always 3
398 while (ISXDIGIT (*p
))
403 /* Go hex characters are always 2 digits. */
408 case 'a': case 'b': case 'f': case 'n': case 'r':
409 case 't': case 'v': case '\\': case '\'': case '"':
420 if (quote
== '\'' && count
!= 1)
424 need_operand
= false;
437 gcc_assert ((size_t) (q
- out_buffer
) < out_len
);
440 mhval
->value
= out_buffer
;
444 slot
= htab_find_slot_with_hash (macro_hash
, mhval
, hashval
, INSERT
);
445 gcc_assert (slot
!= NULL
&& *slot
== NULL
);
450 macro_hash_del (*slot
);
458 fprintf (go_dump_file
, "// unknowndefine %s\n", buffer
);
460 htab_clear_slot (macro_hash
, slot
);
461 XDELETEVEC (out_buffer
);
468 go_undef (unsigned int lineno
, const char *buffer
)
470 struct macro_hash_value mhval
;
473 real_debug_hooks
->undef (lineno
, buffer
);
475 mhval
.name
= CONST_CAST (char *, buffer
);
477 slot
= htab_find_slot (macro_hash
, &mhval
, NO_INSERT
);
479 htab_clear_slot (macro_hash
, slot
);
482 /* A function or variable decl. */
487 if (!TREE_PUBLIC (decl
)
488 || DECL_IS_BUILTIN (decl
)
489 || DECL_NAME (decl
) == NULL_TREE
)
491 vec_safe_push (queue
, decl
);
494 /* A function decl. */
497 go_function_decl (tree decl
)
499 real_debug_hooks
->function_decl (decl
);
504 go_early_global_decl (tree decl
)
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
))
726 obstack_grow (ob
, "int", 3);
733 slot
= htab_find_slot (container
->invalid_hash
,
734 IDENTIFIER_POINTER (DECL_NAME (type
)),
739 obstack_1grow (ob
, '_');
740 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);
827 && TYPE_NAME (TREE_TYPE (type
)) != NULL_TREE
828 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
))
829 || (POINTER_TYPE_P (TREE_TYPE (type
))
830 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type
)))
836 name
= TYPE_IDENTIFIER (TREE_TYPE (type
));
838 slot
= htab_find_slot (container
->invalid_hash
,
839 IDENTIFIER_POINTER (name
), NO_INSERT
);
843 obstack_grow (ob
, "*_", 2);
844 go_append_string (ob
, name
);
846 /* The pointer here can be used without the struct or union
847 definition. So this struct or union is a potential dummy
849 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
)))
850 container
->pot_dummy_types
.add (IDENTIFIER_POINTER (name
));
854 if (TREE_CODE (TREE_TYPE (type
)) == FUNCTION_TYPE
)
855 obstack_grow (ob
, "func", 4);
857 obstack_1grow (ob
, '*');
858 if (VOID_TYPE_P (TREE_TYPE (type
)))
859 obstack_grow (ob
, "byte", 4);
862 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
,
869 obstack_1grow (ob
, '[');
870 if (TYPE_DOMAIN (type
) != NULL_TREE
871 && TREE_CODE (TYPE_DOMAIN (type
)) == INTEGER_TYPE
872 && TYPE_MIN_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
873 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
874 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == 0
875 && TYPE_MAX_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
876 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
877 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))))
881 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
"+1",
882 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))));
883 obstack_grow (ob
, buf
, strlen (buf
));
886 obstack_1grow (ob
, '0');
887 obstack_1grow (ob
, ']');
888 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
, false,
895 /* Fall through to RECORD_TYPE case. */
899 unsigned int prev_field_end
;
900 unsigned int known_alignment
;
902 bool emitted_a_field
;
904 /* FIXME: Why is this necessary? Without it we can get a core
905 dump on the s390x headers, or from a file containing simply
906 "typedef struct S T;". */
911 /* Anonymous records and unions are flattened, i.e. they are not put
912 into "struct { ... }". */
913 if (!is_anon_record_or_union
)
914 obstack_grow (ob
, "struct { ", 9);
915 for (field
= TYPE_FIELDS (type
), emitted_a_field
= false;
917 field
= TREE_CHAIN (field
))
919 if (TREE_CODE (field
) != FIELD_DECL
)
921 if (DECL_BIT_FIELD (field
))
922 /* Bit fields are replaced by padding. */
924 /* Only the first non-bitfield field is emitted for unions. */
925 if (!is_union
|| !emitted_a_field
)
927 /* Emit the field. */
929 bool is_anon_substructure
;
930 unsigned int decl_align_unit
;
931 unsigned int decl_offset
;
934 emitted_a_field
= true;
935 is_anon_substructure
=
936 (DECL_NAME (field
) == NULL
937 && (TREE_CODE (TREE_TYPE (field
)) == RECORD_TYPE
938 || TREE_CODE (TREE_TYPE (field
)) == UNION_TYPE
));
939 /* Keep track of the alignment of named substructures, either
940 of the whole record, or the alignment of the emitted field
942 decl_align_unit
= DECL_ALIGN_UNIT (field
);
943 if (!is_anon_substructure
&& decl_align_unit
> known_alignment
)
944 known_alignment
= decl_align_unit
;
945 /* Pad to start of field. */
947 TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field
))
949 (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field
)));
951 unsigned int align_unit
;
953 /* For anonymous records and unions there is no automatic
954 structure alignment, so use 1 as the alignment. */
955 align_unit
= (is_anon_substructure
) ? 1 : decl_align_unit
;
956 *p_art_i
= go_append_padding
957 (ob
, prev_field_end
, decl_offset
, align_unit
, *p_art_i
,
960 if (DECL_SIZE_UNIT (field
))
962 TREE_INT_CST_LOW (DECL_SIZE_UNIT (field
));
963 /* Emit the field name, but not for anonymous records and
965 if (!is_anon_substructure
)
967 if ((DECL_NAME (field
) == NULL
))
968 *p_art_i
= go_append_artificial_name (ob
, *p_art_i
);
971 (ob
, field
, container
->keyword_hash
);
972 obstack_1grow (ob
, ' ');
974 /* Do not expand type if a record or union type or a function
976 if (TYPE_NAME (TREE_TYPE (field
)) != NULL_TREE
977 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field
))
978 || (POINTER_TYPE_P (TREE_TYPE (field
))
979 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field
)))
985 name
= TYPE_IDENTIFIER (TREE_TYPE (field
));
987 slot
= htab_find_slot (container
->invalid_hash
,
988 IDENTIFIER_POINTER (name
),
993 obstack_1grow (ob
, '_');
994 go_append_string (ob
, name
);
998 if (!go_format_type (container
, TREE_TYPE (field
), true,
999 false, p_art_i
, is_anon_substructure
))
1002 if (!is_anon_substructure
)
1003 obstack_grow (ob
, "; ", 2);
1009 *p_art_i
= go_append_padding (ob
, prev_field_end
,
1010 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type
)),
1011 1, *p_art_i
, &prev_field_end
);
1013 if (!is_anon_record_or_union
1014 && known_alignment
< TYPE_ALIGN_UNIT (type
))
1019 /* Enforce proper record alignment. */
1020 s
= go_get_uinttype_for_precision
1021 (TYPE_ALIGN (type
), TYPE_UNSIGNED (type
));
1024 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
1025 TYPE_ALIGN (type
), TYPE_UNSIGNED (type
) ? "u" : "");
1029 *p_art_i
= go_force_record_alignment (ob
, s
, *p_art_i
, buf
);
1031 if (!is_anon_record_or_union
)
1032 obstack_1grow (ob
, '}');
1041 function_args_iterator iter
;
1044 /* Go has no way to write a type which is a function but not a
1045 pointer to a function. */
1048 obstack_grow (ob
, "func*", 5);
1052 obstack_1grow (ob
, '(');
1053 is_varargs
= stdarg_p (type
);
1055 FOREACH_FUNCTION_ARGS (type
, arg_type
, iter
)
1057 if (VOID_TYPE_P (arg_type
))
1060 obstack_grow (ob
, ", ", 2);
1061 if (!go_format_type (container
, arg_type
, true, false, NULL
, false))
1067 if (prototype_p (type
))
1068 obstack_grow (ob
, ", ", 2);
1069 obstack_grow (ob
, "...interface{}", 14);
1071 obstack_1grow (ob
, ')');
1073 result
= TREE_TYPE (type
);
1074 if (!VOID_TYPE_P (result
))
1076 obstack_1grow (ob
, ' ');
1077 if (!go_format_type (container
, result
, use_type_name
, false, NULL
,
1085 obstack_grow (ob
, "INVALID-type", 12);
1093 /* Output the type which was built on the type obstack, and then free
1097 go_output_type (struct godump_container
*container
)
1101 ob
= &container
->type_obstack
;
1102 obstack_1grow (ob
, '\0');
1103 fputs ((char *) obstack_base (ob
), go_dump_file
);
1104 obstack_free (ob
, obstack_base (ob
));
1107 /* Output a function declaration. */
1110 go_output_fndecl (struct godump_container
*container
, tree decl
)
1112 if (!go_format_type (container
, TREE_TYPE (decl
), false, true, NULL
, false))
1113 fprintf (go_dump_file
, "// ");
1114 fprintf (go_dump_file
, "func _%s ",
1115 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1116 go_output_type (container
);
1117 fprintf (go_dump_file
, " __asm__(\"%s\")\n",
1118 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
)));
1121 /* Output a typedef or something like a struct definition. */
1124 go_output_typedef (struct godump_container
*container
, tree decl
)
1126 /* If we have an enum type, output the enum constants
1128 if (TREE_CODE (TREE_TYPE (decl
)) == ENUMERAL_TYPE
1129 && TYPE_SIZE (TREE_TYPE (decl
)) != 0
1130 && !container
->decls_seen
.contains (TREE_TYPE (decl
))
1131 && (TYPE_CANONICAL (TREE_TYPE (decl
)) == NULL_TREE
1132 || !container
->decls_seen
.contains
1133 (TYPE_CANONICAL (TREE_TYPE (decl
)))))
1137 for (element
= TYPE_VALUES (TREE_TYPE (decl
));
1138 element
!= NULL_TREE
;
1139 element
= TREE_CHAIN (element
))
1142 struct macro_hash_value
*mhval
;
1144 char buf
[WIDE_INT_PRINT_BUFFER_SIZE
];
1146 name
= IDENTIFIER_POINTER (TREE_PURPOSE (element
));
1148 /* Sometimes a name will be defined as both an enum constant
1149 and a macro. Avoid duplicate definition errors by
1150 treating enum constants as macros. */
1151 mhval
= XNEW (struct macro_hash_value
);
1152 mhval
->name
= xstrdup (name
);
1153 mhval
->value
= NULL
;
1154 slot
= htab_find_slot (macro_hash
, mhval
, INSERT
);
1156 macro_hash_del (*slot
);
1158 if (tree_fits_shwi_p (TREE_VALUE (element
)))
1159 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
,
1160 tree_to_shwi (TREE_VALUE (element
)));
1161 else if (tree_fits_uhwi_p (TREE_VALUE (element
)))
1162 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_UNSIGNED
,
1163 tree_to_uhwi (TREE_VALUE (element
)));
1165 print_hex (element
, buf
);
1167 mhval
->value
= xstrdup (buf
);
1170 container
->decls_seen
.add (TREE_TYPE (decl
));
1171 if (TYPE_CANONICAL (TREE_TYPE (decl
)) != NULL_TREE
)
1172 container
->decls_seen
.add (TYPE_CANONICAL (TREE_TYPE (decl
)));
1175 if (DECL_NAME (decl
) != NULL_TREE
)
1180 type
= IDENTIFIER_POINTER (DECL_NAME (decl
));
1181 /* If type defined already, skip. */
1182 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1185 *slot
= CONST_CAST (void *, (const void *) type
);
1187 if (!go_format_type (container
, TREE_TYPE (decl
), false, false, NULL
,
1190 fprintf (go_dump_file
, "// ");
1191 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1192 *slot
= CONST_CAST (void *, (const void *) type
);
1194 fprintf (go_dump_file
, "type _%s ",
1195 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1196 go_output_type (container
);
1198 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1200 HOST_WIDE_INT size
= int_size_in_bytes (TREE_TYPE (decl
));
1203 fprintf (go_dump_file
,
1204 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1205 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1209 container
->decls_seen
.add (decl
);
1211 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1217 type
= IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl
))));
1218 /* If type defined already, skip. */
1219 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1222 *slot
= CONST_CAST (void *, (const void *) type
);
1224 if (!go_format_type (container
, TREE_TYPE (decl
), false, false, NULL
,
1227 fprintf (go_dump_file
, "// ");
1228 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1229 *slot
= CONST_CAST (void *, (const void *) type
);
1231 fprintf (go_dump_file
, "type _%s ",
1232 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))));
1233 go_output_type (container
);
1235 size
= int_size_in_bytes (TREE_TYPE (decl
));
1237 fprintf (go_dump_file
,
1238 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1239 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))),
1245 fprintf (go_dump_file
, "\n");
1248 /* Output a variable. */
1251 go_output_var (struct godump_container
*container
, tree decl
)
1257 if (container
->decls_seen
.contains (decl
)
1258 || container
->decls_seen
.contains (DECL_NAME (decl
)))
1260 container
->decls_seen
.add (decl
);
1261 container
->decls_seen
.add (DECL_NAME (decl
));
1263 type_name
= TYPE_NAME (TREE_TYPE (decl
));
1265 if (type_name
!= NULL_TREE
&& TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1267 else if (type_name
!= NULL_TREE
&& TREE_CODE (type_name
) == TYPE_DECL
1268 && DECL_SOURCE_LOCATION (type_name
) != BUILTINS_LOCATION
1269 && DECL_NAME (type_name
))
1270 id
= DECL_NAME (type_name
);
1272 && (!htab_find_slot (container
->type_hash
, IDENTIFIER_POINTER (id
),
1274 || htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (id
),
1277 if (id
!= NULL_TREE
)
1281 ob
= &container
->type_obstack
;
1282 obstack_1grow (ob
, '_');
1283 go_append_string (ob
, id
);
1284 is_valid
= htab_find_slot (container
->type_hash
, IDENTIFIER_POINTER (id
),
1288 is_valid
= go_format_type (container
, TREE_TYPE (decl
), true, false, NULL
,
1291 && htab_find_slot (container
->type_hash
,
1292 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1295 /* There is already a type with this name, probably from a
1296 struct tag. Prefer the type to the variable. */
1300 fprintf (go_dump_file
, "// ");
1302 fprintf (go_dump_file
, "var _%s ",
1303 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1304 go_output_type (container
);
1305 fprintf (go_dump_file
, "\n");
1307 /* Sometimes an extern variable is declared with an unknown struct
1309 if (type_name
!= NULL_TREE
&& RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1311 if (TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1312 container
->pot_dummy_types
.add (IDENTIFIER_POINTER (type_name
));
1313 else if (TREE_CODE (type_name
) == TYPE_DECL
)
1314 container
->pot_dummy_types
.add
1315 (IDENTIFIER_POINTER (DECL_NAME (type_name
)));
1319 /* Output the final value of a preprocessor macro or enum constant.
1320 This is called via htab_traverse_noresize. */
1323 go_print_macro (void **slot
, void *arg ATTRIBUTE_UNUSED
)
1325 struct macro_hash_value
*mhval
= (struct macro_hash_value
*) *slot
;
1326 fprintf (go_dump_file
, "const _%s = %s\n", mhval
->name
, mhval
->value
);
1330 /* Build a hash table with the Go keywords. */
1332 static const char * const keywords
[] = {
1333 "__asm__", "break", "case", "chan", "const", "continue", "default",
1334 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1335 "import", "interface", "map", "package", "range", "return", "select",
1336 "struct", "switch", "type", "var"
1340 keyword_hash_init (struct godump_container
*container
)
1343 size_t count
= sizeof (keywords
) / sizeof (keywords
[0]);
1346 for (i
= 0; i
< count
; i
++)
1348 slot
= htab_find_slot (container
->keyword_hash
, keywords
[i
], INSERT
);
1349 *slot
= CONST_CAST (void *, (const void *) keywords
[i
]);
1353 /* Traversing the pot_dummy_types and seeing which types are present
1354 in the global types hash table and creating dummy definitions if
1355 not found. This function is invoked by hash_set::traverse. */
1358 find_dummy_types (const char *const &ptr
, godump_container
*adata
)
1360 struct godump_container
*data
= (struct godump_container
*) adata
;
1361 const char *type
= (const char *) ptr
;
1365 slot
= htab_find_slot (data
->type_hash
, type
, NO_INSERT
);
1366 islot
= htab_find_slot (data
->invalid_hash
, type
, NO_INSERT
);
1367 if (slot
== NULL
|| islot
!= NULL
)
1368 fprintf (go_dump_file
, "type _%s struct {}\n", type
);
1372 /* Output symbols. */
1375 go_finish (const char *filename
)
1377 struct godump_container container
;
1381 real_debug_hooks
->finish (filename
);
1383 container
.type_hash
= htab_create (100, htab_hash_string
,
1384 string_hash_eq
, NULL
);
1385 container
.invalid_hash
= htab_create (10, htab_hash_string
,
1386 string_hash_eq
, NULL
);
1387 container
.keyword_hash
= htab_create (50, htab_hash_string
,
1388 string_hash_eq
, NULL
);
1389 obstack_init (&container
.type_obstack
);
1391 keyword_hash_init (&container
);
1393 FOR_EACH_VEC_SAFE_ELT (queue
, ix
, decl
)
1395 switch (TREE_CODE (decl
))
1398 go_output_fndecl (&container
, decl
);
1402 go_output_typedef (&container
, decl
);
1406 go_output_var (&container
, decl
);
1414 htab_traverse_noresize (macro_hash
, go_print_macro
, NULL
);
1416 /* To emit dummy definitions. */
1417 container
.pot_dummy_types
.traverse
<godump_container
*, find_dummy_types
>
1420 htab_delete (container
.type_hash
);
1421 htab_delete (container
.invalid_hash
);
1422 htab_delete (container
.keyword_hash
);
1423 obstack_free (&container
.type_obstack
, NULL
);
1427 if (fclose (go_dump_file
) != 0)
1428 error ("could not close Go dump file: %m");
1429 go_dump_file
= NULL
;
1432 /* Set up our hooks. */
1434 const struct gcc_debug_hooks
*
1435 dump_go_spec_init (const char *filename
, const struct gcc_debug_hooks
*hooks
)
1437 go_dump_file
= fopen (filename
, "w");
1438 if (go_dump_file
== NULL
)
1440 error ("could not open Go dump file %qs: %m", filename
);
1444 go_debug_hooks
= *hooks
;
1445 real_debug_hooks
= hooks
;
1447 go_debug_hooks
.finish
= go_finish
;
1448 go_debug_hooks
.define
= go_define
;
1449 go_debug_hooks
.undef
= go_undef
;
1450 go_debug_hooks
.function_decl
= go_function_decl
;
1451 go_debug_hooks
.early_global_decl
= go_early_global_decl
;
1452 go_debug_hooks
.late_global_decl
= go_late_global_decl
;
1453 go_debug_hooks
.type_decl
= go_type_decl
;
1455 macro_hash
= htab_create (100, macro_hash_hashval
, macro_hash_eq
,
1458 return &go_debug_hooks
;
1461 #include "gt-godump.h"