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"
46 #include "wide-int-print.h"
47 #include "stor-layout.h"
50 /* We dump this information from the debug hooks. This gives us a
51 stable and maintainable API to hook into. In order to work
52 correctly when -g is used, we build our own hooks structure which
53 wraps the hooks we need to change. */
55 /* Our debug hooks. This is initialized by dump_go_spec_init. */
57 static struct gcc_debug_hooks go_debug_hooks
;
59 /* The real debug hooks. */
61 static const struct gcc_debug_hooks
*real_debug_hooks
;
63 /* The file where we should write information. */
65 static FILE *go_dump_file
;
67 /* A queue of decls to output. */
69 static GTY(()) vec
<tree
, va_gc
> *queue
;
71 /* A hash table of macros we have seen. */
73 static htab_t macro_hash
;
75 /* The type of a value in macro_hash. */
77 struct macro_hash_value
79 /* The name stored in the hash table. */
81 /* The value of the macro. */
85 /* Returns the number of units necessary to represent an integer with the given
86 PRECISION (in bits). */
88 static inline unsigned int
89 precision_to_units (unsigned int precision
)
91 return (precision
+ BITS_PER_UNIT
- 1) / BITS_PER_UNIT
;
94 /* Calculate the hash value for an entry in the macro hash table. */
97 macro_hash_hashval (const void *val
)
99 const struct macro_hash_value
*mhval
= (const struct macro_hash_value
*) val
;
100 return htab_hash_string (mhval
->name
);
103 /* Compare values in the macro hash table for equality. */
106 macro_hash_eq (const void *v1
, const void *v2
)
108 const struct macro_hash_value
*mhv1
= (const struct macro_hash_value
*) v1
;
109 const struct macro_hash_value
*mhv2
= (const struct macro_hash_value
*) v2
;
110 return strcmp (mhv1
->name
, mhv2
->name
) == 0;
113 /* Free values deleted from the macro hash table. */
116 macro_hash_del (void *v
)
118 struct macro_hash_value
*mhv
= (struct macro_hash_value
*) v
;
119 XDELETEVEC (mhv
->name
);
120 XDELETEVEC (mhv
->value
);
124 /* For the string hash tables. */
127 string_hash_eq (const void *y1
, const void *y2
)
129 return strcmp ((const char *) y1
, (const char *) y2
) == 0;
132 /* A macro definition. */
135 go_define (unsigned int lineno
, const char *buffer
)
138 const char *name_end
;
144 struct macro_hash_value
*mhval
;
149 real_debug_hooks
->define (lineno
, buffer
);
151 /* Skip macro functions. */
152 for (p
= buffer
; *p
!= '\0' && *p
!= ' '; ++p
)
165 copy
= XNEWVEC (char, name_end
- buffer
+ 1);
166 memcpy (copy
, buffer
, name_end
- buffer
);
167 copy
[name_end
- buffer
] = '\0';
169 mhval
= XNEW (struct macro_hash_value
);
173 hashval
= htab_hash_string (copy
);
174 slot
= htab_find_slot_with_hash (macro_hash
, mhval
, hashval
, NO_INSERT
);
176 /* For simplicity, we force all names to be hidden by adding an
177 initial underscore, and let the user undo this as needed. */
178 out_len
= strlen (p
) * 2 + 1;
179 out_buffer
= XNEWVEC (char, out_len
);
182 need_operand
= false;
187 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
188 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
189 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
190 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
192 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
193 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
194 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
195 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
199 /* The start of an identifier. Technically we should also
200 worry about UTF-8 identifiers, but they are not a
201 problem for practical uses of -fdump-go-spec so we
202 don't worry about them. */
205 struct macro_hash_value idval
;
211 while (ISALNUM (*p
) || *p
== '_')
213 n
= XALLOCAVEC (char, p
- start
+ 1);
214 memcpy (n
, start
, p
- start
);
218 if (htab_find (macro_hash
, &idval
) == NULL
)
220 /* This is a reference to a name which was not defined
226 memcpy (q
, start
, p
- start
);
230 need_operand
= false;
238 case '0': case '1': case '2': case '3': case '4':
239 case '5': case '6': case '7': case '8': case '9':
246 if (*p
== '0' && (p
[1] == 'x' || p
[1] == 'X'))
251 while (ISDIGIT (*p
) || *p
== '.' || *p
== 'e' || *p
== 'E'
253 && ((*p
>= 'a' && *p
<= 'f')
254 || (*p
>= 'A' && *p
<= 'F'))))
256 memcpy (q
, start
, p
- start
);
258 while (*p
== 'u' || *p
== 'U' || *p
== 'l' || *p
== 'L'
259 || *p
== 'f' || *p
== 'F'
260 || *p
== 'd' || *p
== 'D')
262 /* Go doesn't use any of these trailing type
267 /* We'll pick up the exponent, if any, as an
271 need_operand
= false;
280 /* Always OK, not part of an operand, presumed to start an
284 need_operand
= false;
288 /* OK if we don't need an operand, and presumed to indicate
297 /* Always OK, but not part of an operand. */
302 case '*': case '/': case '%': case '|': case '&': case '^':
303 /* Must be a binary operator. */
315 /* Must be a binary operator. */
327 /* Must be a binary operator. */
336 /* Must be a unary operator. */
344 /* Must be a binary operand, may be << or >> or <= or >=. */
348 if (*p
== *(p
- 1) || *p
== '=')
355 /* Must be a unary operand, must be translated for Go. */
392 case '0': case '1': case '2': case '3':
393 case '4': case '5': case '6': case '7':
395 while (*p
>= '0' && *p
<= '7')
400 /* Go octal characters are always 3
409 while (ISXDIGIT (*p
))
414 /* Go hex characters are always 2 digits. */
419 case 'a': case 'b': case 'f': case 'n': case 'r':
420 case 't': case 'v': case '\\': case '\'': case '"':
431 if (quote
== '\'' && count
!= 1)
435 need_operand
= false;
448 gcc_assert ((size_t) (q
- out_buffer
) < out_len
);
451 mhval
->value
= out_buffer
;
455 slot
= htab_find_slot_with_hash (macro_hash
, mhval
, hashval
, INSERT
);
456 gcc_assert (slot
!= NULL
&& *slot
== NULL
);
461 macro_hash_del (*slot
);
469 fprintf (go_dump_file
, "// unknowndefine %s\n", buffer
);
471 htab_clear_slot (macro_hash
, slot
);
472 XDELETEVEC (out_buffer
);
479 go_undef (unsigned int lineno
, const char *buffer
)
481 struct macro_hash_value mhval
;
484 real_debug_hooks
->undef (lineno
, buffer
);
486 mhval
.name
= CONST_CAST (char *, buffer
);
488 slot
= htab_find_slot (macro_hash
, &mhval
, NO_INSERT
);
490 htab_clear_slot (macro_hash
, slot
);
493 /* A function or variable decl. */
498 if (!TREE_PUBLIC (decl
)
499 || DECL_IS_BUILTIN (decl
)
500 || DECL_NAME (decl
) == NULL_TREE
)
502 vec_safe_push (queue
, decl
);
505 /* A function decl. */
508 go_function_decl (tree decl
)
510 real_debug_hooks
->function_decl (decl
);
515 go_early_global_decl (tree decl
)
518 real_debug_hooks
->early_global_decl (decl
);
521 /* A global variable decl. */
524 go_late_global_decl (tree decl
)
526 real_debug_hooks
->late_global_decl (decl
);
529 /* A type declaration. */
532 go_type_decl (tree decl
, int local
)
534 real_debug_hooks
->type_decl (decl
, local
);
536 if (local
|| DECL_IS_BUILTIN (decl
))
538 if (DECL_NAME (decl
) == NULL_TREE
539 && (TYPE_NAME (TREE_TYPE (decl
)) == NULL_TREE
540 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl
))) != IDENTIFIER_NODE
)
541 && TREE_CODE (TREE_TYPE (decl
)) != ENUMERAL_TYPE
)
543 vec_safe_push (queue
, decl
);
546 /* A container for the data we pass around when generating information
547 at the end of the compilation. */
549 struct godump_container
551 /* DECLs that we have already seen. */
552 hash_set
<tree
> decls_seen
;
554 /* Types which may potentially have to be defined as dummy
556 hash_set
<const char *> pot_dummy_types
;
561 /* Global type definitions. */
567 /* Obstack used to write out a type definition. */
568 struct obstack type_obstack
;
571 /* Append an IDENTIFIER_NODE to OB. */
574 go_append_string (struct obstack
*ob
, tree id
)
576 obstack_grow (ob
, IDENTIFIER_POINTER (id
), IDENTIFIER_LENGTH (id
));
579 /* Given an integer PRECISION in bits, returns a constant string that is the
580 matching go int or uint type (depending on the IS_UNSIGNED flag). Returns a
581 NULL pointer if there is no matching go type. */
584 go_get_uinttype_for_precision (unsigned int precision
, bool is_unsigned
)
589 return is_unsigned
? "uint8" : "int8";
591 return is_unsigned
? "uint16" : "int16";
593 return is_unsigned
? "uint32" : "int32";
595 return is_unsigned
? "uint64" : "int64";
601 /* Append an artificial variable name with the suffix _INDEX to OB. Returns
605 go_append_artificial_name (struct obstack
*ob
, unsigned int index
)
609 /* FIXME: identifier may not be unique. */
610 obstack_grow (ob
, "Godump_", 7);
611 snprintf (buf
, sizeof buf
, "%u", index
);
612 obstack_grow (ob
, buf
, strlen (buf
));
617 /* Append the variable name from DECL to OB. If the name is in the
618 KEYWORD_HASH, prepend an '_'. */
621 go_append_decl_name (struct obstack
*ob
, tree decl
, htab_t keyword_hash
)
623 const char *var_name
;
626 /* Start variable name with an underscore if a keyword. */
627 var_name
= IDENTIFIER_POINTER (DECL_NAME (decl
));
628 slot
= htab_find_slot (keyword_hash
, var_name
, NO_INSERT
);
630 obstack_1grow (ob
, '_');
631 go_append_string (ob
, DECL_NAME (decl
));
634 /* Appends a byte array with the necessary number of elements and the name
635 "Godump_INDEX_pad" to pad from FROM_OFFSET to TO_OFFSET to OB assuming that
636 the next field is automatically aligned to ALIGN_UNITS. Returns INDEX + 1,
637 or INDEX if no padding had to be appended. The resulting offset where the
638 next field is allocated is returned through RET_OFFSET. */
641 go_append_padding (struct obstack
*ob
, unsigned int from_offset
,
642 unsigned int to_offset
, unsigned int align_units
,
643 unsigned int index
, unsigned int *ret_offset
)
645 if (from_offset
% align_units
> 0)
646 from_offset
+= align_units
- (from_offset
% align_units
);
647 gcc_assert (to_offset
>= from_offset
);
648 if (to_offset
> from_offset
)
652 index
= go_append_artificial_name (ob
, index
);
653 snprintf (buf
, sizeof buf
, "_pad [%u]byte; ", to_offset
- from_offset
);
654 obstack_grow (ob
, buf
, strlen (buf
));
656 *ret_offset
= to_offset
;
661 /* Appends an array of type TYPE_STRING with zero elements and the name
662 "Godump_INDEX_align" to OB. If TYPE_STRING is a null pointer, ERROR_STRING
663 is appended instead of the type. Returns INDEX + 1. */
666 go_force_record_alignment (struct obstack
*ob
, const char *type_string
,
667 unsigned int index
, const char *error_string
)
669 index
= go_append_artificial_name (ob
, index
);
670 obstack_grow (ob
, "_align ", 7);
671 if (type_string
== NULL
)
672 obstack_grow (ob
, error_string
, strlen (error_string
));
675 obstack_grow (ob
, "[0]", 3);
676 obstack_grow (ob
, type_string
, strlen (type_string
));
678 obstack_grow (ob
, "; ", 2);
683 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
684 USE_TYPE_NAME is true if we can simply use a type name here without
685 needing to define it. IS_FUNC_OK is true if we can output a func
686 type here; the "func" keyword will already have been added.
687 Return true if the type can be represented in Go, false otherwise.
688 P_ART_I is used for indexing artificial elements in nested structures and
689 should always be a NULL pointer when called, except by certain recursive
690 calls from go_format_type() itself. */
693 go_format_type (struct godump_container
*container
, tree type
,
694 bool use_type_name
, bool is_func_ok
, unsigned int *p_art_i
,
695 bool is_anon_record_or_union
)
699 unsigned int art_i_dummy
;
700 bool is_union
= false;
705 p_art_i
= &art_i_dummy
;
708 ob
= &container
->type_obstack
;
710 if (TYPE_NAME (type
) != NULL_TREE
711 && (container
->decls_seen
.contains (type
)
712 || container
->decls_seen
.contains (TYPE_NAME (type
)))
713 && (AGGREGATE_TYPE_P (type
)
714 || POINTER_TYPE_P (type
)
715 || TREE_CODE (type
) == FUNCTION_TYPE
))
720 name
= TYPE_IDENTIFIER (type
);
722 slot
= htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (name
),
727 obstack_1grow (ob
, '_');
728 go_append_string (ob
, name
);
732 container
->decls_seen
.add (type
);
734 switch (TREE_CODE (type
))
737 obstack_grow (ob
, "int", 3);
744 slot
= htab_find_slot (container
->invalid_hash
,
745 IDENTIFIER_POINTER (DECL_NAME (type
)),
750 obstack_1grow (ob
, '_');
751 go_append_string (ob
, DECL_NAME (type
));
760 s
= go_get_uinttype_for_precision (TYPE_PRECISION (type
),
761 TYPE_UNSIGNED (type
));
764 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
765 TYPE_PRECISION (type
),
766 TYPE_UNSIGNED (type
) ? "u" : "");
770 obstack_grow (ob
, s
, strlen (s
));
779 switch (TYPE_PRECISION (type
))
788 snprintf (buf
, sizeof buf
, "INVALID-float-%u",
789 TYPE_PRECISION (type
));
794 obstack_grow (ob
, s
, strlen (s
));
804 real_type
= TREE_TYPE (type
);
805 if (TREE_CODE (real_type
) == REAL_TYPE
)
807 switch (TYPE_PRECISION (real_type
))
816 snprintf (buf
, sizeof buf
, "INVALID-complex-%u",
817 2 * TYPE_PRECISION (real_type
));
825 s
= "INVALID-complex-non-real";
828 obstack_grow (ob
, s
, strlen (s
));
833 obstack_grow (ob
, "bool", 4);
838 && TYPE_NAME (TREE_TYPE (type
)) != NULL_TREE
839 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
))
840 || (POINTER_TYPE_P (TREE_TYPE (type
))
841 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type
)))
847 name
= TYPE_IDENTIFIER (TREE_TYPE (type
));
849 slot
= htab_find_slot (container
->invalid_hash
,
850 IDENTIFIER_POINTER (name
), NO_INSERT
);
854 obstack_grow (ob
, "*_", 2);
855 go_append_string (ob
, name
);
857 /* The pointer here can be used without the struct or union
858 definition. So this struct or union is a potential dummy
860 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
)))
861 container
->pot_dummy_types
.add (IDENTIFIER_POINTER (name
));
865 if (TREE_CODE (TREE_TYPE (type
)) == FUNCTION_TYPE
)
866 obstack_grow (ob
, "func", 4);
868 obstack_1grow (ob
, '*');
869 if (VOID_TYPE_P (TREE_TYPE (type
)))
870 obstack_grow (ob
, "byte", 4);
873 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
,
880 obstack_1grow (ob
, '[');
881 if (TYPE_DOMAIN (type
) != NULL_TREE
882 && TREE_CODE (TYPE_DOMAIN (type
)) == INTEGER_TYPE
883 && TYPE_MIN_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
884 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
885 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == 0
886 && TYPE_MAX_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
887 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
888 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))))
892 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
"+1",
893 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))));
894 obstack_grow (ob
, buf
, strlen (buf
));
897 obstack_1grow (ob
, '0');
898 obstack_1grow (ob
, ']');
899 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
, false,
906 /* Fall through to RECORD_TYPE case. */
909 unsigned int prev_field_end
;
910 unsigned int known_alignment
;
912 bool emitted_a_field
;
914 /* FIXME: Why is this necessary? Without it we can get a core
915 dump on the s390x headers, or from a file containing simply
916 "typedef struct S T;". */
921 /* Anonymous records and unions are flattened, i.e. they are not put
922 into "struct { ... }". */
923 if (!is_anon_record_or_union
)
924 obstack_grow (ob
, "struct { ", 9);
925 for (field
= TYPE_FIELDS (type
), emitted_a_field
= false;
927 field
= TREE_CHAIN (field
))
929 if (TREE_CODE (field
) != FIELD_DECL
)
931 if (DECL_BIT_FIELD (field
))
932 /* Bit fields are replaced by padding. */
934 /* Only the first non-bitfield field is emitted for unions. */
935 if (!is_union
|| !emitted_a_field
)
937 /* Emit the field. */
939 bool is_anon_substructure
;
940 unsigned int decl_align_unit
;
941 unsigned int decl_offset
;
944 emitted_a_field
= true;
945 is_anon_substructure
=
946 (DECL_NAME (field
) == NULL
947 && (TREE_CODE (TREE_TYPE (field
)) == RECORD_TYPE
948 || TREE_CODE (TREE_TYPE (field
)) == UNION_TYPE
));
949 /* Keep track of the alignment of named substructures, either
950 of the whole record, or the alignment of the emitted field
952 decl_align_unit
= DECL_ALIGN_UNIT (field
);
953 if (!is_anon_substructure
&& decl_align_unit
> known_alignment
)
954 known_alignment
= decl_align_unit
;
955 /* Pad to start of field. */
957 TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field
))
959 (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field
)));
961 unsigned int align_unit
;
963 /* For anonymous records and unions there is no automatic
964 structure alignment, so use 1 as the alignment. */
965 align_unit
= (is_anon_substructure
) ? 1 : decl_align_unit
;
966 *p_art_i
= go_append_padding
967 (ob
, prev_field_end
, decl_offset
, align_unit
, *p_art_i
,
970 if (DECL_SIZE_UNIT (field
))
972 TREE_INT_CST_LOW (DECL_SIZE_UNIT (field
));
973 /* Emit the field name, but not for anonymous records and
975 if (!is_anon_substructure
)
977 if ((DECL_NAME (field
) == NULL
))
978 *p_art_i
= go_append_artificial_name (ob
, *p_art_i
);
981 (ob
, field
, container
->keyword_hash
);
982 obstack_1grow (ob
, ' ');
984 /* Do not expand type if a record or union type or a function
986 if (TYPE_NAME (TREE_TYPE (field
)) != NULL_TREE
987 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field
))
988 || (POINTER_TYPE_P (TREE_TYPE (field
))
989 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field
)))
995 name
= TYPE_IDENTIFIER (TREE_TYPE (field
));
997 slot
= htab_find_slot (container
->invalid_hash
,
998 IDENTIFIER_POINTER (name
),
1003 obstack_1grow (ob
, '_');
1004 go_append_string (ob
, name
);
1008 if (!go_format_type (container
, TREE_TYPE (field
), true,
1009 false, p_art_i
, is_anon_substructure
))
1012 if (!is_anon_substructure
)
1013 obstack_grow (ob
, "; ", 2);
1020 unsigned int align_unit
;
1022 align_unit
= (is_anon_record_or_union
) ? 1 : TYPE_ALIGN_UNIT (type
);
1023 *p_art_i
= go_append_padding
1024 (ob
, prev_field_end
, TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type
)),
1025 align_unit
, *p_art_i
, &prev_field_end
);
1028 if (!is_anon_record_or_union
1029 && known_alignment
< TYPE_ALIGN_UNIT (type
))
1034 /* Enforce proper record alignment. */
1035 s
= go_get_uinttype_for_precision
1036 (TYPE_ALIGN (type
), TYPE_UNSIGNED (type
));
1039 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
1040 TYPE_ALIGN (type
), TYPE_UNSIGNED (type
) ? "u" : "");
1044 *p_art_i
= go_force_record_alignment (ob
, s
, *p_art_i
, buf
);
1046 if (!is_anon_record_or_union
)
1047 obstack_1grow (ob
, '}');
1056 function_args_iterator iter
;
1059 /* Go has no way to write a type which is a function but not a
1060 pointer to a function. */
1063 obstack_grow (ob
, "func*", 5);
1067 obstack_1grow (ob
, '(');
1068 is_varargs
= stdarg_p (type
);
1070 FOREACH_FUNCTION_ARGS (type
, arg_type
, iter
)
1072 if (VOID_TYPE_P (arg_type
))
1075 obstack_grow (ob
, ", ", 2);
1076 if (!go_format_type (container
, arg_type
, true, false, NULL
, false))
1082 if (prototype_p (type
))
1083 obstack_grow (ob
, ", ", 2);
1084 obstack_grow (ob
, "...interface{}", 14);
1086 obstack_1grow (ob
, ')');
1088 result
= TREE_TYPE (type
);
1089 if (!VOID_TYPE_P (result
))
1091 obstack_1grow (ob
, ' ');
1092 if (!go_format_type (container
, result
, use_type_name
, false, NULL
,
1100 obstack_grow (ob
, "INVALID-type", 12);
1108 /* Output the type which was built on the type obstack, and then free
1112 go_output_type (struct godump_container
*container
)
1116 ob
= &container
->type_obstack
;
1117 obstack_1grow (ob
, '\0');
1118 fputs ((char *) obstack_base (ob
), go_dump_file
);
1119 obstack_free (ob
, obstack_base (ob
));
1122 /* Output a function declaration. */
1125 go_output_fndecl (struct godump_container
*container
, tree decl
)
1127 if (!go_format_type (container
, TREE_TYPE (decl
), false, true, NULL
, false))
1128 fprintf (go_dump_file
, "// ");
1129 fprintf (go_dump_file
, "func _%s ",
1130 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1131 go_output_type (container
);
1132 fprintf (go_dump_file
, " __asm__(\"%s\")\n",
1133 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
)));
1136 /* Output a typedef or something like a struct definition. */
1139 go_output_typedef (struct godump_container
*container
, tree decl
)
1141 /* If we have an enum type, output the enum constants
1143 if (TREE_CODE (TREE_TYPE (decl
)) == ENUMERAL_TYPE
1144 && TYPE_SIZE (TREE_TYPE (decl
)) != 0
1145 && !container
->decls_seen
.contains (TREE_TYPE (decl
))
1146 && (TYPE_CANONICAL (TREE_TYPE (decl
)) == NULL_TREE
1147 || !container
->decls_seen
.contains
1148 (TYPE_CANONICAL (TREE_TYPE (decl
)))))
1152 for (element
= TYPE_VALUES (TREE_TYPE (decl
));
1153 element
!= NULL_TREE
;
1154 element
= TREE_CHAIN (element
))
1157 struct macro_hash_value
*mhval
;
1159 char buf
[WIDE_INT_PRINT_BUFFER_SIZE
];
1161 name
= IDENTIFIER_POINTER (TREE_PURPOSE (element
));
1163 /* Sometimes a name will be defined as both an enum constant
1164 and a macro. Avoid duplicate definition errors by
1165 treating enum constants as macros. */
1166 mhval
= XNEW (struct macro_hash_value
);
1167 mhval
->name
= xstrdup (name
);
1168 mhval
->value
= NULL
;
1169 slot
= htab_find_slot (macro_hash
, mhval
, INSERT
);
1171 macro_hash_del (*slot
);
1173 if (tree_fits_shwi_p (TREE_VALUE (element
)))
1174 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
,
1175 tree_to_shwi (TREE_VALUE (element
)));
1176 else if (tree_fits_uhwi_p (TREE_VALUE (element
)))
1177 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_UNSIGNED
,
1178 tree_to_uhwi (TREE_VALUE (element
)));
1180 print_hex (element
, buf
);
1182 mhval
->value
= xstrdup (buf
);
1185 container
->decls_seen
.add (TREE_TYPE (decl
));
1186 if (TYPE_CANONICAL (TREE_TYPE (decl
)) != NULL_TREE
)
1187 container
->decls_seen
.add (TYPE_CANONICAL (TREE_TYPE (decl
)));
1190 if (DECL_NAME (decl
) != NULL_TREE
)
1195 type
= IDENTIFIER_POINTER (DECL_NAME (decl
));
1196 /* If type defined already, skip. */
1197 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1200 *slot
= CONST_CAST (void *, (const void *) type
);
1202 if (!go_format_type (container
, TREE_TYPE (decl
), false, false, NULL
,
1205 fprintf (go_dump_file
, "// ");
1206 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1207 *slot
= CONST_CAST (void *, (const void *) type
);
1209 fprintf (go_dump_file
, "type _%s ",
1210 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1211 go_output_type (container
);
1213 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1215 HOST_WIDE_INT size
= int_size_in_bytes (TREE_TYPE (decl
));
1218 fprintf (go_dump_file
,
1219 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1220 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1224 container
->decls_seen
.add (decl
);
1226 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1232 type
= IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl
))));
1233 /* If type defined already, skip. */
1234 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1237 *slot
= CONST_CAST (void *, (const void *) type
);
1239 if (!go_format_type (container
, TREE_TYPE (decl
), false, false, NULL
,
1242 fprintf (go_dump_file
, "// ");
1243 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1244 *slot
= CONST_CAST (void *, (const void *) type
);
1246 fprintf (go_dump_file
, "type _%s ",
1247 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))));
1248 go_output_type (container
);
1250 size
= int_size_in_bytes (TREE_TYPE (decl
));
1252 fprintf (go_dump_file
,
1253 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1254 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))),
1260 fprintf (go_dump_file
, "\n");
1263 /* Output a variable. */
1266 go_output_var (struct godump_container
*container
, tree decl
)
1272 if (container
->decls_seen
.contains (decl
)
1273 || container
->decls_seen
.contains (DECL_NAME (decl
)))
1275 container
->decls_seen
.add (decl
);
1276 container
->decls_seen
.add (DECL_NAME (decl
));
1278 type_name
= TYPE_NAME (TREE_TYPE (decl
));
1280 if (type_name
!= NULL_TREE
&& TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1282 else if (type_name
!= NULL_TREE
&& TREE_CODE (type_name
) == TYPE_DECL
1283 && DECL_SOURCE_LOCATION (type_name
) != BUILTINS_LOCATION
1284 && DECL_NAME (type_name
))
1285 id
= DECL_NAME (type_name
);
1287 && (!htab_find_slot (container
->type_hash
, IDENTIFIER_POINTER (id
),
1289 || htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (id
),
1292 if (id
!= NULL_TREE
)
1296 ob
= &container
->type_obstack
;
1297 obstack_1grow (ob
, '_');
1298 go_append_string (ob
, id
);
1299 is_valid
= htab_find_slot (container
->type_hash
, IDENTIFIER_POINTER (id
),
1303 is_valid
= go_format_type (container
, TREE_TYPE (decl
), true, false, NULL
,
1306 && htab_find_slot (container
->type_hash
,
1307 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1310 /* There is already a type with this name, probably from a
1311 struct tag. Prefer the type to the variable. */
1315 fprintf (go_dump_file
, "// ");
1317 fprintf (go_dump_file
, "var _%s ",
1318 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1319 go_output_type (container
);
1320 fprintf (go_dump_file
, "\n");
1322 /* Sometimes an extern variable is declared with an unknown struct
1324 if (type_name
!= NULL_TREE
&& RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1326 if (TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1327 container
->pot_dummy_types
.add (IDENTIFIER_POINTER (type_name
));
1328 else if (TREE_CODE (type_name
) == TYPE_DECL
)
1329 container
->pot_dummy_types
.add
1330 (IDENTIFIER_POINTER (DECL_NAME (type_name
)));
1334 /* Output the final value of a preprocessor macro or enum constant.
1335 This is called via htab_traverse_noresize. */
1338 go_print_macro (void **slot
, void *arg ATTRIBUTE_UNUSED
)
1340 struct macro_hash_value
*mhval
= (struct macro_hash_value
*) *slot
;
1341 fprintf (go_dump_file
, "const _%s = %s\n", mhval
->name
, mhval
->value
);
1345 /* Build a hash table with the Go keywords. */
1347 static const char * const keywords
[] = {
1348 "__asm__", "break", "case", "chan", "const", "continue", "default",
1349 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1350 "import", "interface", "map", "package", "range", "return", "select",
1351 "struct", "switch", "type", "var"
1355 keyword_hash_init (struct godump_container
*container
)
1358 size_t count
= sizeof (keywords
) / sizeof (keywords
[0]);
1361 for (i
= 0; i
< count
; i
++)
1363 slot
= htab_find_slot (container
->keyword_hash
, keywords
[i
], INSERT
);
1364 *slot
= CONST_CAST (void *, (const void *) keywords
[i
]);
1368 /* Traversing the pot_dummy_types and seeing which types are present
1369 in the global types hash table and creating dummy definitions if
1370 not found. This function is invoked by hash_set::traverse. */
1373 find_dummy_types (const char *const &ptr
, godump_container
*adata
)
1375 struct godump_container
*data
= (struct godump_container
*) adata
;
1376 const char *type
= (const char *) ptr
;
1380 slot
= htab_find_slot (data
->type_hash
, type
, NO_INSERT
);
1381 islot
= htab_find_slot (data
->invalid_hash
, type
, NO_INSERT
);
1382 if (slot
== NULL
|| islot
!= NULL
)
1383 fprintf (go_dump_file
, "type _%s struct {}\n", type
);
1387 /* Output symbols. */
1390 go_finish (const char *filename
)
1392 struct godump_container container
;
1396 real_debug_hooks
->finish (filename
);
1398 container
.type_hash
= htab_create (100, htab_hash_string
,
1399 string_hash_eq
, NULL
);
1400 container
.invalid_hash
= htab_create (10, htab_hash_string
,
1401 string_hash_eq
, NULL
);
1402 container
.keyword_hash
= htab_create (50, htab_hash_string
,
1403 string_hash_eq
, NULL
);
1404 obstack_init (&container
.type_obstack
);
1406 keyword_hash_init (&container
);
1408 FOR_EACH_VEC_SAFE_ELT (queue
, ix
, decl
)
1410 switch (TREE_CODE (decl
))
1413 go_output_fndecl (&container
, decl
);
1417 go_output_typedef (&container
, decl
);
1421 go_output_var (&container
, decl
);
1429 htab_traverse_noresize (macro_hash
, go_print_macro
, NULL
);
1431 /* To emit dummy definitions. */
1432 container
.pot_dummy_types
.traverse
<godump_container
*, find_dummy_types
>
1435 htab_delete (container
.type_hash
);
1436 htab_delete (container
.invalid_hash
);
1437 htab_delete (container
.keyword_hash
);
1438 obstack_free (&container
.type_obstack
, NULL
);
1442 if (fclose (go_dump_file
) != 0)
1443 error ("could not close Go dump file: %m");
1444 go_dump_file
= NULL
;
1447 /* Set up our hooks. */
1449 const struct gcc_debug_hooks
*
1450 dump_go_spec_init (const char *filename
, const struct gcc_debug_hooks
*hooks
)
1452 go_dump_file
= fopen (filename
, "w");
1453 if (go_dump_file
== NULL
)
1455 error ("could not open Go dump file %qs: %m", filename
);
1459 go_debug_hooks
= *hooks
;
1460 real_debug_hooks
= hooks
;
1462 go_debug_hooks
.finish
= go_finish
;
1463 go_debug_hooks
.define
= go_define
;
1464 go_debug_hooks
.undef
= go_undef
;
1465 go_debug_hooks
.function_decl
= go_function_decl
;
1466 go_debug_hooks
.early_global_decl
= go_early_global_decl
;
1467 go_debug_hooks
.late_global_decl
= go_late_global_decl
;
1468 go_debug_hooks
.type_decl
= go_type_decl
;
1470 macro_hash
= htab_create (100, macro_hash_hashval
, macro_hash_eq
,
1473 return &go_debug_hooks
;
1476 #include "gt-godump.h"