1 /* Output Go language descriptions of types.
2 Copyright (C) 2008-2015 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor <iant@google.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 /* This file is used during the build process to emit Go language
22 descriptions of declarations from C header files. It uses the
23 debug info hooks to emit the descriptions. The Go language
24 descriptions then become part of the Go runtime support
27 All global names are output with a leading underscore, so that they
28 are all hidden in Go. */
32 #include "coretypes.h"
33 #include "diagnostic-core.h"
40 #include "wide-int-print.h"
41 #include "stor-layout.h"
44 /* We dump this information from the debug hooks. This gives us a
45 stable and maintainable API to hook into. In order to work
46 correctly when -g is used, we build our own hooks structure which
47 wraps the hooks we need to change. */
49 /* Our debug hooks. This is initialized by dump_go_spec_init. */
51 static struct gcc_debug_hooks go_debug_hooks
;
53 /* The real debug hooks. */
55 static const struct gcc_debug_hooks
*real_debug_hooks
;
57 /* The file where we should write information. */
59 static FILE *go_dump_file
;
61 /* A queue of decls to output. */
63 static GTY(()) vec
<tree
, va_gc
> *queue
;
65 /* A hash table of macros we have seen. */
67 static htab_t macro_hash
;
69 /* The type of a value in macro_hash. */
71 struct macro_hash_value
73 /* The name stored in the hash table. */
75 /* The value of the macro. */
79 /* Returns the number of units necessary to represent an integer with the given
80 PRECISION (in bits). */
82 static inline unsigned int
83 precision_to_units (unsigned int precision
)
85 return (precision
+ BITS_PER_UNIT
- 1) / BITS_PER_UNIT
;
88 /* Calculate the hash value for an entry in the macro hash table. */
91 macro_hash_hashval (const void *val
)
93 const struct macro_hash_value
*mhval
= (const struct macro_hash_value
*) val
;
94 return htab_hash_string (mhval
->name
);
97 /* Compare values in the macro hash table for equality. */
100 macro_hash_eq (const void *v1
, const void *v2
)
102 const struct macro_hash_value
*mhv1
= (const struct macro_hash_value
*) v1
;
103 const struct macro_hash_value
*mhv2
= (const struct macro_hash_value
*) v2
;
104 return strcmp (mhv1
->name
, mhv2
->name
) == 0;
107 /* Free values deleted from the macro hash table. */
110 macro_hash_del (void *v
)
112 struct macro_hash_value
*mhv
= (struct macro_hash_value
*) v
;
113 XDELETEVEC (mhv
->name
);
114 XDELETEVEC (mhv
->value
);
118 /* For the string hash tables. */
121 string_hash_eq (const void *y1
, const void *y2
)
123 return strcmp ((const char *) y1
, (const char *) y2
) == 0;
126 /* A macro definition. */
129 go_define (unsigned int lineno
, const char *buffer
)
132 const char *name_end
;
138 struct macro_hash_value
*mhval
;
143 real_debug_hooks
->define (lineno
, buffer
);
145 /* Skip macro functions. */
146 for (p
= buffer
; *p
!= '\0' && *p
!= ' '; ++p
)
159 copy
= XNEWVEC (char, name_end
- buffer
+ 1);
160 memcpy (copy
, buffer
, name_end
- buffer
);
161 copy
[name_end
- buffer
] = '\0';
163 mhval
= XNEW (struct macro_hash_value
);
167 hashval
= htab_hash_string (copy
);
168 slot
= htab_find_slot_with_hash (macro_hash
, mhval
, hashval
, NO_INSERT
);
170 /* For simplicity, we force all names to be hidden by adding an
171 initial underscore, and let the user undo this as needed. */
172 out_len
= strlen (p
) * 2 + 1;
173 out_buffer
= XNEWVEC (char, out_len
);
176 need_operand
= false;
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':
186 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
187 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
188 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
189 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
193 /* The start of an identifier. Technically we should also
194 worry about UTF-8 identifiers, but they are not a
195 problem for practical uses of -fdump-go-spec so we
196 don't worry about them. */
199 struct macro_hash_value idval
;
205 while (ISALNUM (*p
) || *p
== '_')
207 n
= XALLOCAVEC (char, p
- start
+ 1);
208 memcpy (n
, start
, p
- start
);
212 if (htab_find (macro_hash
, &idval
) == NULL
)
214 /* This is a reference to a name which was not defined
220 memcpy (q
, start
, p
- start
);
224 need_operand
= false;
232 case '0': case '1': case '2': case '3': case '4':
233 case '5': case '6': case '7': case '8': case '9':
240 if (*p
== '0' && (p
[1] == 'x' || p
[1] == 'X'))
245 while (ISDIGIT (*p
) || *p
== '.' || *p
== 'e' || *p
== 'E'
247 && ((*p
>= 'a' && *p
<= 'f')
248 || (*p
>= 'A' && *p
<= 'F'))))
250 memcpy (q
, start
, p
- start
);
252 while (*p
== 'u' || *p
== 'U' || *p
== 'l' || *p
== 'L'
253 || *p
== 'f' || *p
== 'F'
254 || *p
== 'd' || *p
== 'D')
256 /* Go doesn't use any of these trailing type
261 /* We'll pick up the exponent, if any, as an
265 need_operand
= false;
274 /* Always OK, not part of an operand, presumed to start an
278 need_operand
= false;
282 /* OK if we don't need an operand, and presumed to indicate
291 /* Always OK, but not part of an operand. */
296 case '*': case '/': case '%': case '|': case '&': case '^':
297 /* Must be a binary operator. */
309 /* Must be a binary operator. */
321 /* Must be a binary operator. */
330 /* Must be a unary operator. */
338 /* Must be a binary operand, may be << or >> or <= or >=. */
342 if (*p
== *(p
- 1) || *p
== '=')
349 /* Must be a unary operand, must be translated for Go. */
386 case '0': case '1': case '2': case '3':
387 case '4': case '5': case '6': case '7':
389 while (*p
>= '0' && *p
<= '7')
394 /* Go octal characters are always 3
403 while (ISXDIGIT (*p
))
408 /* Go hex characters are always 2 digits. */
413 case 'a': case 'b': case 'f': case 'n': case 'r':
414 case 't': case 'v': case '\\': case '\'': case '"':
425 if (quote
== '\'' && count
!= 1)
429 need_operand
= false;
442 gcc_assert ((size_t) (q
- out_buffer
) < out_len
);
445 mhval
->value
= out_buffer
;
449 slot
= htab_find_slot_with_hash (macro_hash
, mhval
, hashval
, INSERT
);
450 gcc_assert (slot
!= NULL
&& *slot
== NULL
);
455 macro_hash_del (*slot
);
463 fprintf (go_dump_file
, "// unknowndefine %s\n", buffer
);
465 htab_clear_slot (macro_hash
, slot
);
466 XDELETEVEC (out_buffer
);
473 go_undef (unsigned int lineno
, const char *buffer
)
475 struct macro_hash_value mhval
;
478 real_debug_hooks
->undef (lineno
, buffer
);
480 mhval
.name
= CONST_CAST (char *, buffer
);
482 slot
= htab_find_slot (macro_hash
, &mhval
, NO_INSERT
);
484 htab_clear_slot (macro_hash
, slot
);
487 /* A function or variable decl. */
492 if (!TREE_PUBLIC (decl
)
493 || DECL_IS_BUILTIN (decl
)
494 || DECL_NAME (decl
) == NULL_TREE
)
496 vec_safe_push (queue
, decl
);
499 /* A function decl. */
502 go_function_decl (tree decl
)
504 real_debug_hooks
->function_decl (decl
);
509 go_early_global_decl (tree decl
)
512 real_debug_hooks
->early_global_decl (decl
);
515 /* A global variable decl. */
518 go_late_global_decl (tree decl
)
520 real_debug_hooks
->late_global_decl (decl
);
523 /* A type declaration. */
526 go_type_decl (tree decl
, int local
)
528 real_debug_hooks
->type_decl (decl
, local
);
530 if (local
|| DECL_IS_BUILTIN (decl
))
532 if (DECL_NAME (decl
) == NULL_TREE
533 && (TYPE_NAME (TREE_TYPE (decl
)) == NULL_TREE
534 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl
))) != IDENTIFIER_NODE
)
535 && TREE_CODE (TREE_TYPE (decl
)) != ENUMERAL_TYPE
)
537 vec_safe_push (queue
, decl
);
540 /* A container for the data we pass around when generating information
541 at the end of the compilation. */
543 struct godump_container
545 /* DECLs that we have already seen. */
546 hash_set
<tree
> decls_seen
;
548 /* Types which may potentially have to be defined as dummy
550 hash_set
<const char *> pot_dummy_types
;
555 /* Global type definitions. */
561 /* Obstack used to write out a type definition. */
562 struct obstack type_obstack
;
565 /* Append an IDENTIFIER_NODE to OB. */
568 go_append_string (struct obstack
*ob
, tree id
)
570 obstack_grow (ob
, IDENTIFIER_POINTER (id
), IDENTIFIER_LENGTH (id
));
573 /* Given an integer PRECISION in bits, returns a constant string that is the
574 matching go int or uint type (depending on the IS_UNSIGNED flag). Returns a
575 NULL pointer if there is no matching go type. */
578 go_get_uinttype_for_precision (unsigned int precision
, bool is_unsigned
)
583 return is_unsigned
? "uint8" : "int8";
585 return is_unsigned
? "uint16" : "int16";
587 return is_unsigned
? "uint32" : "int32";
589 return is_unsigned
? "uint64" : "int64";
595 /* Append an artificial variable name with the suffix _INDEX to OB. Returns
599 go_append_artificial_name (struct obstack
*ob
, unsigned int index
)
603 /* FIXME: identifier may not be unique. */
604 obstack_grow (ob
, "Godump_", 7);
605 snprintf (buf
, sizeof buf
, "%u", index
);
606 obstack_grow (ob
, buf
, strlen (buf
));
611 /* Append the variable name from DECL to OB. If the name is in the
612 KEYWORD_HASH, prepend an '_'. */
615 go_append_decl_name (struct obstack
*ob
, tree decl
, htab_t keyword_hash
)
617 const char *var_name
;
620 /* Start variable name with an underscore if a keyword. */
621 var_name
= IDENTIFIER_POINTER (DECL_NAME (decl
));
622 slot
= htab_find_slot (keyword_hash
, var_name
, NO_INSERT
);
624 obstack_1grow (ob
, '_');
625 go_append_string (ob
, DECL_NAME (decl
));
628 /* Appends a byte array with the necessary number of elements and the name
629 "Godump_INDEX_pad" to pad from FROM_OFFSET to TO_OFFSET to OB assuming that
630 the next field is automatically aligned to ALIGN_UNITS. Returns INDEX + 1,
631 or INDEX if no padding had to be appended. The resulting offset where the
632 next field is allocated is returned through RET_OFFSET. */
635 go_append_padding (struct obstack
*ob
, unsigned int from_offset
,
636 unsigned int to_offset
, unsigned int align_units
,
637 unsigned int index
, unsigned int *ret_offset
)
639 if (from_offset
% align_units
> 0)
640 from_offset
+= align_units
- (from_offset
% align_units
);
641 gcc_assert (to_offset
>= from_offset
);
642 if (to_offset
> from_offset
)
646 index
= go_append_artificial_name (ob
, index
);
647 snprintf (buf
, sizeof buf
, "_pad [%u]byte; ", to_offset
- from_offset
);
648 obstack_grow (ob
, buf
, strlen (buf
));
650 *ret_offset
= to_offset
;
655 /* Appends an array of type TYPE_STRING with zero elements and the name
656 "Godump_INDEX_align" to OB. If TYPE_STRING is a null pointer, ERROR_STRING
657 is appended instead of the type. Returns INDEX + 1. */
660 go_force_record_alignment (struct obstack
*ob
, const char *type_string
,
661 unsigned int index
, const char *error_string
)
663 index
= go_append_artificial_name (ob
, index
);
664 obstack_grow (ob
, "_align ", 7);
665 if (type_string
== NULL
)
666 obstack_grow (ob
, error_string
, strlen (error_string
));
669 obstack_grow (ob
, "[0]", 3);
670 obstack_grow (ob
, type_string
, strlen (type_string
));
672 obstack_grow (ob
, "; ", 2);
677 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
678 USE_TYPE_NAME is true if we can simply use a type name here without
679 needing to define it. IS_FUNC_OK is true if we can output a func
680 type here; the "func" keyword will already have been added.
681 Return true if the type can be represented in Go, false otherwise.
682 P_ART_I is used for indexing artificial elements in nested structures and
683 should always be a NULL pointer when called, except by certain recursive
684 calls from go_format_type() itself. */
687 go_format_type (struct godump_container
*container
, tree type
,
688 bool use_type_name
, bool is_func_ok
, unsigned int *p_art_i
,
689 bool is_anon_record_or_union
)
693 unsigned int art_i_dummy
;
694 bool is_union
= false;
699 p_art_i
= &art_i_dummy
;
702 ob
= &container
->type_obstack
;
704 if (TYPE_NAME (type
) != NULL_TREE
705 && (container
->decls_seen
.contains (type
)
706 || container
->decls_seen
.contains (TYPE_NAME (type
)))
707 && (AGGREGATE_TYPE_P (type
)
708 || POINTER_TYPE_P (type
)
709 || TREE_CODE (type
) == FUNCTION_TYPE
))
714 name
= TYPE_IDENTIFIER (type
);
716 slot
= htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (name
),
721 obstack_1grow (ob
, '_');
722 go_append_string (ob
, name
);
726 container
->decls_seen
.add (type
);
728 switch (TREE_CODE (type
))
731 obstack_grow (ob
, "int", 3);
738 slot
= htab_find_slot (container
->invalid_hash
,
739 IDENTIFIER_POINTER (DECL_NAME (type
)),
744 obstack_1grow (ob
, '_');
745 go_append_string (ob
, DECL_NAME (type
));
754 s
= go_get_uinttype_for_precision (TYPE_PRECISION (type
),
755 TYPE_UNSIGNED (type
));
758 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
759 TYPE_PRECISION (type
),
760 TYPE_UNSIGNED (type
) ? "u" : "");
764 obstack_grow (ob
, s
, strlen (s
));
773 switch (TYPE_PRECISION (type
))
782 snprintf (buf
, sizeof buf
, "INVALID-float-%u",
783 TYPE_PRECISION (type
));
788 obstack_grow (ob
, s
, strlen (s
));
798 real_type
= TREE_TYPE (type
);
799 if (TREE_CODE (real_type
) == REAL_TYPE
)
801 switch (TYPE_PRECISION (real_type
))
810 snprintf (buf
, sizeof buf
, "INVALID-complex-%u",
811 2 * TYPE_PRECISION (real_type
));
819 s
= "INVALID-complex-non-real";
822 obstack_grow (ob
, s
, strlen (s
));
827 obstack_grow (ob
, "bool", 4);
832 && TYPE_NAME (TREE_TYPE (type
)) != NULL_TREE
833 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
))
834 || (POINTER_TYPE_P (TREE_TYPE (type
))
835 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type
)))
841 name
= TYPE_IDENTIFIER (TREE_TYPE (type
));
843 slot
= htab_find_slot (container
->invalid_hash
,
844 IDENTIFIER_POINTER (name
), NO_INSERT
);
848 obstack_grow (ob
, "*_", 2);
849 go_append_string (ob
, name
);
851 /* The pointer here can be used without the struct or union
852 definition. So this struct or union is a potential dummy
854 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
)))
855 container
->pot_dummy_types
.add (IDENTIFIER_POINTER (name
));
859 if (TREE_CODE (TREE_TYPE (type
)) == FUNCTION_TYPE
)
860 obstack_grow (ob
, "func", 4);
862 obstack_1grow (ob
, '*');
863 if (VOID_TYPE_P (TREE_TYPE (type
)))
864 obstack_grow (ob
, "byte", 4);
867 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
,
874 obstack_1grow (ob
, '[');
875 if (TYPE_DOMAIN (type
) != NULL_TREE
876 && TREE_CODE (TYPE_DOMAIN (type
)) == INTEGER_TYPE
877 && TYPE_MIN_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
878 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
879 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == 0
880 && TYPE_MAX_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
881 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
882 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))))
886 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
"+1",
887 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))));
888 obstack_grow (ob
, buf
, strlen (buf
));
891 obstack_1grow (ob
, '0');
892 obstack_1grow (ob
, ']');
893 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
, false,
900 /* Fall through to RECORD_TYPE case. */
903 unsigned int prev_field_end
;
904 unsigned int known_alignment
;
906 bool emitted_a_field
;
908 /* FIXME: Why is this necessary? Without it we can get a core
909 dump on the s390x headers, or from a file containing simply
910 "typedef struct S T;". */
915 /* Anonymous records and unions are flattened, i.e. they are not put
916 into "struct { ... }". */
917 if (!is_anon_record_or_union
)
918 obstack_grow (ob
, "struct { ", 9);
919 for (field
= TYPE_FIELDS (type
), emitted_a_field
= false;
921 field
= TREE_CHAIN (field
))
923 if (TREE_CODE (field
) != FIELD_DECL
)
925 if (DECL_BIT_FIELD (field
))
926 /* Bit fields are replaced by padding. */
928 /* Only the first non-bitfield field is emitted for unions. */
929 if (!is_union
|| !emitted_a_field
)
931 /* Emit the field. */
933 bool is_anon_substructure
;
934 unsigned int decl_align_unit
;
935 unsigned int decl_offset
;
938 emitted_a_field
= true;
939 is_anon_substructure
=
940 (DECL_NAME (field
) == NULL
941 && (TREE_CODE (TREE_TYPE (field
)) == RECORD_TYPE
942 || TREE_CODE (TREE_TYPE (field
)) == UNION_TYPE
));
943 /* Keep track of the alignment of named substructures, either
944 of the whole record, or the alignment of the emitted field
946 decl_align_unit
= DECL_ALIGN_UNIT (field
);
947 if (!is_anon_substructure
&& decl_align_unit
> known_alignment
)
948 known_alignment
= decl_align_unit
;
949 /* Pad to start of field. */
951 TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field
))
953 (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field
)));
955 unsigned int align_unit
;
957 /* For anonymous records and unions there is no automatic
958 structure alignment, so use 1 as the alignment. */
959 align_unit
= (is_anon_substructure
) ? 1 : decl_align_unit
;
960 *p_art_i
= go_append_padding
961 (ob
, prev_field_end
, decl_offset
, align_unit
, *p_art_i
,
964 if (DECL_SIZE_UNIT (field
))
966 TREE_INT_CST_LOW (DECL_SIZE_UNIT (field
));
967 /* Emit the field name, but not for anonymous records and
969 if (!is_anon_substructure
)
971 if ((DECL_NAME (field
) == NULL
))
972 *p_art_i
= go_append_artificial_name (ob
, *p_art_i
);
975 (ob
, field
, container
->keyword_hash
);
976 obstack_1grow (ob
, ' ');
978 /* Do not expand type if a record or union type or a function
980 if (TYPE_NAME (TREE_TYPE (field
)) != NULL_TREE
981 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field
))
982 || (POINTER_TYPE_P (TREE_TYPE (field
))
983 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field
)))
989 name
= TYPE_IDENTIFIER (TREE_TYPE (field
));
991 slot
= htab_find_slot (container
->invalid_hash
,
992 IDENTIFIER_POINTER (name
),
997 obstack_1grow (ob
, '_');
998 go_append_string (ob
, name
);
1002 if (!go_format_type (container
, TREE_TYPE (field
), true,
1003 false, p_art_i
, is_anon_substructure
))
1006 if (!is_anon_substructure
)
1007 obstack_grow (ob
, "; ", 2);
1014 unsigned int align_unit
;
1016 align_unit
= (is_anon_record_or_union
) ? 1 : TYPE_ALIGN_UNIT (type
);
1017 *p_art_i
= go_append_padding
1018 (ob
, prev_field_end
, TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type
)),
1019 align_unit
, *p_art_i
, &prev_field_end
);
1022 if (!is_anon_record_or_union
1023 && known_alignment
< TYPE_ALIGN_UNIT (type
))
1028 /* Enforce proper record alignment. */
1029 s
= go_get_uinttype_for_precision
1030 (TYPE_ALIGN (type
), TYPE_UNSIGNED (type
));
1033 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
1034 TYPE_ALIGN (type
), TYPE_UNSIGNED (type
) ? "u" : "");
1038 *p_art_i
= go_force_record_alignment (ob
, s
, *p_art_i
, buf
);
1040 if (!is_anon_record_or_union
)
1041 obstack_1grow (ob
, '}');
1050 function_args_iterator iter
;
1053 /* Go has no way to write a type which is a function but not a
1054 pointer to a function. */
1057 obstack_grow (ob
, "func*", 5);
1061 obstack_1grow (ob
, '(');
1062 is_varargs
= stdarg_p (type
);
1064 FOREACH_FUNCTION_ARGS (type
, arg_type
, iter
)
1066 if (VOID_TYPE_P (arg_type
))
1069 obstack_grow (ob
, ", ", 2);
1070 if (!go_format_type (container
, arg_type
, true, false, NULL
, false))
1076 if (prototype_p (type
))
1077 obstack_grow (ob
, ", ", 2);
1078 obstack_grow (ob
, "...interface{}", 14);
1080 obstack_1grow (ob
, ')');
1082 result
= TREE_TYPE (type
);
1083 if (!VOID_TYPE_P (result
))
1085 obstack_1grow (ob
, ' ');
1086 if (!go_format_type (container
, result
, use_type_name
, false, NULL
,
1094 obstack_grow (ob
, "INVALID-type", 12);
1102 /* Output the type which was built on the type obstack, and then free
1106 go_output_type (struct godump_container
*container
)
1110 ob
= &container
->type_obstack
;
1111 obstack_1grow (ob
, '\0');
1112 fputs ((char *) obstack_base (ob
), go_dump_file
);
1113 obstack_free (ob
, obstack_base (ob
));
1116 /* Output a function declaration. */
1119 go_output_fndecl (struct godump_container
*container
, tree decl
)
1121 if (!go_format_type (container
, TREE_TYPE (decl
), false, true, NULL
, false))
1122 fprintf (go_dump_file
, "// ");
1123 fprintf (go_dump_file
, "func _%s ",
1124 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1125 go_output_type (container
);
1126 fprintf (go_dump_file
, " __asm__(\"%s\")\n",
1127 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
)));
1130 /* Output a typedef or something like a struct definition. */
1133 go_output_typedef (struct godump_container
*container
, tree decl
)
1135 /* If we have an enum type, output the enum constants
1137 if (TREE_CODE (TREE_TYPE (decl
)) == ENUMERAL_TYPE
1138 && TYPE_SIZE (TREE_TYPE (decl
)) != 0
1139 && !container
->decls_seen
.contains (TREE_TYPE (decl
))
1140 && (TYPE_CANONICAL (TREE_TYPE (decl
)) == NULL_TREE
1141 || !container
->decls_seen
.contains
1142 (TYPE_CANONICAL (TREE_TYPE (decl
)))))
1146 for (element
= TYPE_VALUES (TREE_TYPE (decl
));
1147 element
!= NULL_TREE
;
1148 element
= TREE_CHAIN (element
))
1151 struct macro_hash_value
*mhval
;
1153 char buf
[WIDE_INT_PRINT_BUFFER_SIZE
];
1155 name
= IDENTIFIER_POINTER (TREE_PURPOSE (element
));
1157 /* Sometimes a name will be defined as both an enum constant
1158 and a macro. Avoid duplicate definition errors by
1159 treating enum constants as macros. */
1160 mhval
= XNEW (struct macro_hash_value
);
1161 mhval
->name
= xstrdup (name
);
1162 mhval
->value
= NULL
;
1163 slot
= htab_find_slot (macro_hash
, mhval
, INSERT
);
1165 macro_hash_del (*slot
);
1167 if (tree_fits_shwi_p (TREE_VALUE (element
)))
1168 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
,
1169 tree_to_shwi (TREE_VALUE (element
)));
1170 else if (tree_fits_uhwi_p (TREE_VALUE (element
)))
1171 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_UNSIGNED
,
1172 tree_to_uhwi (TREE_VALUE (element
)));
1174 print_hex (element
, buf
);
1176 mhval
->value
= xstrdup (buf
);
1179 container
->decls_seen
.add (TREE_TYPE (decl
));
1180 if (TYPE_CANONICAL (TREE_TYPE (decl
)) != NULL_TREE
)
1181 container
->decls_seen
.add (TYPE_CANONICAL (TREE_TYPE (decl
)));
1184 if (DECL_NAME (decl
) != NULL_TREE
)
1189 type
= IDENTIFIER_POINTER (DECL_NAME (decl
));
1190 /* If type defined already, skip. */
1191 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1194 *slot
= CONST_CAST (void *, (const void *) type
);
1196 if (!go_format_type (container
, TREE_TYPE (decl
), false, false, NULL
,
1199 fprintf (go_dump_file
, "// ");
1200 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1201 *slot
= CONST_CAST (void *, (const void *) type
);
1203 fprintf (go_dump_file
, "type _%s ",
1204 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1205 go_output_type (container
);
1207 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1209 HOST_WIDE_INT size
= int_size_in_bytes (TREE_TYPE (decl
));
1212 fprintf (go_dump_file
,
1213 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1214 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1218 container
->decls_seen
.add (decl
);
1220 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1226 type
= IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl
))));
1227 /* If type defined already, skip. */
1228 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1231 *slot
= CONST_CAST (void *, (const void *) type
);
1233 if (!go_format_type (container
, TREE_TYPE (decl
), false, false, NULL
,
1236 fprintf (go_dump_file
, "// ");
1237 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1238 *slot
= CONST_CAST (void *, (const void *) type
);
1240 fprintf (go_dump_file
, "type _%s ",
1241 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))));
1242 go_output_type (container
);
1244 size
= int_size_in_bytes (TREE_TYPE (decl
));
1246 fprintf (go_dump_file
,
1247 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1248 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))),
1254 fprintf (go_dump_file
, "\n");
1257 /* Output a variable. */
1260 go_output_var (struct godump_container
*container
, tree decl
)
1266 if (container
->decls_seen
.contains (decl
)
1267 || container
->decls_seen
.contains (DECL_NAME (decl
)))
1269 container
->decls_seen
.add (decl
);
1270 container
->decls_seen
.add (DECL_NAME (decl
));
1272 type_name
= TYPE_NAME (TREE_TYPE (decl
));
1274 if (type_name
!= NULL_TREE
&& TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1276 else if (type_name
!= NULL_TREE
&& TREE_CODE (type_name
) == TYPE_DECL
1277 && DECL_SOURCE_LOCATION (type_name
) != BUILTINS_LOCATION
1278 && DECL_NAME (type_name
))
1279 id
= DECL_NAME (type_name
);
1281 && (!htab_find_slot (container
->type_hash
, IDENTIFIER_POINTER (id
),
1283 || htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (id
),
1286 if (id
!= NULL_TREE
)
1290 ob
= &container
->type_obstack
;
1291 obstack_1grow (ob
, '_');
1292 go_append_string (ob
, id
);
1293 is_valid
= htab_find_slot (container
->type_hash
, IDENTIFIER_POINTER (id
),
1297 is_valid
= go_format_type (container
, TREE_TYPE (decl
), true, false, NULL
,
1300 && htab_find_slot (container
->type_hash
,
1301 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1304 /* There is already a type with this name, probably from a
1305 struct tag. Prefer the type to the variable. */
1309 fprintf (go_dump_file
, "// ");
1311 fprintf (go_dump_file
, "var _%s ",
1312 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1313 go_output_type (container
);
1314 fprintf (go_dump_file
, "\n");
1316 /* Sometimes an extern variable is declared with an unknown struct
1318 if (type_name
!= NULL_TREE
&& RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1320 if (TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1321 container
->pot_dummy_types
.add (IDENTIFIER_POINTER (type_name
));
1322 else if (TREE_CODE (type_name
) == TYPE_DECL
)
1323 container
->pot_dummy_types
.add
1324 (IDENTIFIER_POINTER (DECL_NAME (type_name
)));
1328 /* Output the final value of a preprocessor macro or enum constant.
1329 This is called via htab_traverse_noresize. */
1332 go_print_macro (void **slot
, void *arg ATTRIBUTE_UNUSED
)
1334 struct macro_hash_value
*mhval
= (struct macro_hash_value
*) *slot
;
1335 fprintf (go_dump_file
, "const _%s = %s\n", mhval
->name
, mhval
->value
);
1339 /* Build a hash table with the Go keywords. */
1341 static const char * const keywords
[] = {
1342 "__asm__", "break", "case", "chan", "const", "continue", "default",
1343 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1344 "import", "interface", "map", "package", "range", "return", "select",
1345 "struct", "switch", "type", "var"
1349 keyword_hash_init (struct godump_container
*container
)
1352 size_t count
= sizeof (keywords
) / sizeof (keywords
[0]);
1355 for (i
= 0; i
< count
; i
++)
1357 slot
= htab_find_slot (container
->keyword_hash
, keywords
[i
], INSERT
);
1358 *slot
= CONST_CAST (void *, (const void *) keywords
[i
]);
1362 /* Traversing the pot_dummy_types and seeing which types are present
1363 in the global types hash table and creating dummy definitions if
1364 not found. This function is invoked by hash_set::traverse. */
1367 find_dummy_types (const char *const &ptr
, godump_container
*adata
)
1369 struct godump_container
*data
= (struct godump_container
*) adata
;
1370 const char *type
= (const char *) ptr
;
1374 slot
= htab_find_slot (data
->type_hash
, type
, NO_INSERT
);
1375 islot
= htab_find_slot (data
->invalid_hash
, type
, NO_INSERT
);
1376 if (slot
== NULL
|| islot
!= NULL
)
1377 fprintf (go_dump_file
, "type _%s struct {}\n", type
);
1381 /* Output symbols. */
1384 go_finish (const char *filename
)
1386 struct godump_container container
;
1390 real_debug_hooks
->finish (filename
);
1392 container
.type_hash
= htab_create (100, htab_hash_string
,
1393 string_hash_eq
, NULL
);
1394 container
.invalid_hash
= htab_create (10, htab_hash_string
,
1395 string_hash_eq
, NULL
);
1396 container
.keyword_hash
= htab_create (50, htab_hash_string
,
1397 string_hash_eq
, NULL
);
1398 obstack_init (&container
.type_obstack
);
1400 keyword_hash_init (&container
);
1402 FOR_EACH_VEC_SAFE_ELT (queue
, ix
, decl
)
1404 switch (TREE_CODE (decl
))
1407 go_output_fndecl (&container
, decl
);
1411 go_output_typedef (&container
, decl
);
1415 go_output_var (&container
, decl
);
1423 htab_traverse_noresize (macro_hash
, go_print_macro
, NULL
);
1425 /* To emit dummy definitions. */
1426 container
.pot_dummy_types
.traverse
<godump_container
*, find_dummy_types
>
1429 htab_delete (container
.type_hash
);
1430 htab_delete (container
.invalid_hash
);
1431 htab_delete (container
.keyword_hash
);
1432 obstack_free (&container
.type_obstack
, NULL
);
1436 if (fclose (go_dump_file
) != 0)
1437 error ("could not close Go dump file: %m");
1438 go_dump_file
= NULL
;
1441 /* Set up our hooks. */
1443 const struct gcc_debug_hooks
*
1444 dump_go_spec_init (const char *filename
, const struct gcc_debug_hooks
*hooks
)
1446 go_dump_file
= fopen (filename
, "w");
1447 if (go_dump_file
== NULL
)
1449 error ("could not open Go dump file %qs: %m", filename
);
1453 go_debug_hooks
= *hooks
;
1454 real_debug_hooks
= hooks
;
1456 go_debug_hooks
.finish
= go_finish
;
1457 go_debug_hooks
.define
= go_define
;
1458 go_debug_hooks
.undef
= go_undef
;
1459 go_debug_hooks
.function_decl
= go_function_decl
;
1460 go_debug_hooks
.early_global_decl
= go_early_global_decl
;
1461 go_debug_hooks
.late_global_decl
= go_late_global_decl
;
1462 go_debug_hooks
.type_decl
= go_type_decl
;
1464 macro_hash
= htab_create (100, macro_hash_hashval
, macro_hash_eq
,
1467 return &go_debug_hooks
;
1470 #include "gt-godump.h"