1 /* Output Go language descriptions of types.
2 Copyright (C) 2008-2014 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"
39 #include "wide-int-print.h"
40 #include "stor-layout.h"
43 /* We dump this information from the debug hooks. This gives us a
44 stable and maintainable API to hook into. In order to work
45 correctly when -g is used, we build our own hooks structure which
46 wraps the hooks we need to change. */
48 /* Our debug hooks. This is initialized by dump_go_spec_init. */
50 static struct gcc_debug_hooks go_debug_hooks
;
52 /* The real debug hooks. */
54 static const struct gcc_debug_hooks
*real_debug_hooks
;
56 /* The file where we should write information. */
58 static FILE *go_dump_file
;
60 /* A queue of decls to output. */
62 static GTY(()) vec
<tree
, va_gc
> *queue
;
64 /* A hash table of macros we have seen. */
66 static htab_t macro_hash
;
68 /* The type of a value in macro_hash. */
70 struct macro_hash_value
72 /* The name stored in the hash table. */
74 /* The value of the macro. */
78 /* Returns the number of units necessary to represent an integer with the given
79 PRECISION (in bits). */
81 static inline unsigned int
82 precision_to_units (unsigned int precision
)
84 return (precision
+ BITS_PER_UNIT
- 1) / BITS_PER_UNIT
;
87 /* Calculate the hash value for an entry in the macro hash table. */
90 macro_hash_hashval (const void *val
)
92 const struct macro_hash_value
*mhval
= (const struct macro_hash_value
*) val
;
93 return htab_hash_string (mhval
->name
);
96 /* Compare values in the macro hash table for equality. */
99 macro_hash_eq (const void *v1
, const void *v2
)
101 const struct macro_hash_value
*mhv1
= (const struct macro_hash_value
*) v1
;
102 const struct macro_hash_value
*mhv2
= (const struct macro_hash_value
*) v2
;
103 return strcmp (mhv1
->name
, mhv2
->name
) == 0;
106 /* Free values deleted from the macro hash table. */
109 macro_hash_del (void *v
)
111 struct macro_hash_value
*mhv
= (struct macro_hash_value
*) v
;
112 XDELETEVEC (mhv
->name
);
113 XDELETEVEC (mhv
->value
);
117 /* For the string hash tables. */
120 string_hash_eq (const void *y1
, const void *y2
)
122 return strcmp ((const char *) y1
, (const char *) y2
) == 0;
125 /* A macro definition. */
128 go_define (unsigned int lineno
, const char *buffer
)
131 const char *name_end
;
137 struct macro_hash_value
*mhval
;
142 real_debug_hooks
->define (lineno
, buffer
);
144 /* Skip macro functions. */
145 for (p
= buffer
; *p
!= '\0' && *p
!= ' '; ++p
)
158 copy
= XNEWVEC (char, name_end
- buffer
+ 1);
159 memcpy (copy
, buffer
, name_end
- buffer
);
160 copy
[name_end
- buffer
] = '\0';
162 mhval
= XNEW (struct macro_hash_value
);
166 hashval
= htab_hash_string (copy
);
167 slot
= htab_find_slot_with_hash (macro_hash
, mhval
, hashval
, NO_INSERT
);
169 /* For simplicity, we force all names to be hidden by adding an
170 initial underscore, and let the user undo this as needed. */
171 out_len
= strlen (p
) * 2 + 1;
172 out_buffer
= XNEWVEC (char, out_len
);
175 need_operand
= false;
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':
185 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
186 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
187 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
188 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
192 /* The start of an identifier. Technically we should also
193 worry about UTF-8 identifiers, but they are not a
194 problem for practical uses of -fdump-go-spec so we
195 don't worry about them. */
198 struct macro_hash_value idval
;
204 while (ISALNUM (*p
) || *p
== '_')
206 n
= XALLOCAVEC (char, p
- start
+ 1);
207 memcpy (n
, start
, p
- start
);
211 if (htab_find (macro_hash
, &idval
) == NULL
)
213 /* This is a reference to a name which was not defined
219 memcpy (q
, start
, p
- start
);
223 need_operand
= false;
231 case '0': case '1': case '2': case '3': case '4':
232 case '5': case '6': case '7': case '8': case '9':
239 if (*p
== '0' && (p
[1] == 'x' || p
[1] == 'X'))
244 while (ISDIGIT (*p
) || *p
== '.' || *p
== 'e' || *p
== 'E'
246 && ((*p
>= 'a' && *p
<= 'f')
247 || (*p
>= 'A' && *p
<= 'F'))))
249 memcpy (q
, start
, p
- start
);
251 while (*p
== 'u' || *p
== 'U' || *p
== 'l' || *p
== 'L'
252 || *p
== 'f' || *p
== 'F'
253 || *p
== 'd' || *p
== 'D')
255 /* Go doesn't use any of these trailing type
260 /* We'll pick up the exponent, if any, as an
264 need_operand
= false;
273 /* Always OK, not part of an operand, presumed to start an
277 need_operand
= false;
281 /* OK if we don't need an operand, and presumed to indicate
290 /* Always OK, but not part of an operand. */
295 case '*': case '/': case '%': case '|': case '&': case '^':
296 /* Must be a binary operator. */
308 /* Must be a binary operator. */
320 /* Must be a binary operator. */
329 /* Must be a unary operator. */
337 /* Must be a binary operand, may be << or >> or <= or >=. */
341 if (*p
== *(p
- 1) || *p
== '=')
348 /* Must be a unary operand, must be translated for Go. */
385 case '0': case '1': case '2': case '3':
386 case '4': case '5': case '6': case '7':
388 while (*p
>= '0' && *p
<= '7')
393 /* Go octal characters are always 3
402 while (ISXDIGIT (*p
))
407 /* Go hex characters are always 2 digits. */
412 case 'a': case 'b': case 'f': case 'n': case 'r':
413 case 't': case 'v': case '\\': case '\'': case '"':
424 if (quote
== '\'' && count
!= 1)
428 need_operand
= false;
441 gcc_assert ((size_t) (q
- out_buffer
) < out_len
);
444 mhval
->value
= out_buffer
;
448 slot
= htab_find_slot_with_hash (macro_hash
, mhval
, hashval
, INSERT
);
449 gcc_assert (slot
!= NULL
&& *slot
== NULL
);
454 macro_hash_del (*slot
);
462 fprintf (go_dump_file
, "// unknowndefine %s\n", buffer
);
464 htab_clear_slot (macro_hash
, slot
);
465 XDELETEVEC (out_buffer
);
472 go_undef (unsigned int lineno
, const char *buffer
)
474 struct macro_hash_value mhval
;
477 real_debug_hooks
->undef (lineno
, buffer
);
479 mhval
.name
= CONST_CAST (char *, buffer
);
481 slot
= htab_find_slot (macro_hash
, &mhval
, NO_INSERT
);
483 htab_clear_slot (macro_hash
, slot
);
486 /* A function or variable decl. */
491 if (!TREE_PUBLIC (decl
)
492 || DECL_IS_BUILTIN (decl
)
493 || DECL_NAME (decl
) == NULL_TREE
)
495 vec_safe_push (queue
, decl
);
498 /* A function decl. */
501 go_function_decl (tree decl
)
503 real_debug_hooks
->function_decl (decl
);
507 /* A global variable decl. */
510 go_global_decl (tree decl
)
512 real_debug_hooks
->global_decl (decl
);
516 /* A type declaration. */
519 go_type_decl (tree decl
, int local
)
521 real_debug_hooks
->type_decl (decl
, local
);
523 if (local
|| DECL_IS_BUILTIN (decl
))
525 if (DECL_NAME (decl
) == NULL_TREE
526 && (TYPE_NAME (TREE_TYPE (decl
)) == NULL_TREE
527 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl
))) != IDENTIFIER_NODE
)
528 && TREE_CODE (TREE_TYPE (decl
)) != ENUMERAL_TYPE
)
530 vec_safe_push (queue
, decl
);
533 /* A container for the data we pass around when generating information
534 at the end of the compilation. */
536 struct godump_container
538 /* DECLs that we have already seen. */
539 hash_set
<tree
> decls_seen
;
541 /* Types which may potentially have to be defined as dummy
543 hash_set
<const char *> pot_dummy_types
;
548 /* Global type definitions. */
554 /* Obstack used to write out a type definition. */
555 struct obstack type_obstack
;
558 /* Append an IDENTIFIER_NODE to OB. */
561 go_append_string (struct obstack
*ob
, tree id
)
563 obstack_grow (ob
, IDENTIFIER_POINTER (id
), IDENTIFIER_LENGTH (id
));
566 /* Given an integer PRECISION in bits, returns a constant string that is the
567 matching go int or uint type (depending on the IS_UNSIGNED flag). Returns a
568 NULL pointer if there is no matching go type. */
571 go_get_uinttype_for_precision (unsigned int precision
, bool is_unsigned
)
576 return is_unsigned
? "uint8" : "int8";
578 return is_unsigned
? "uint16" : "int16";
580 return is_unsigned
? "uint32" : "int32";
582 return is_unsigned
? "uint64" : "int64";
588 /* Append an artificial variable name with the suffix _INDEX to OB. Returns
592 go_append_artificial_name (struct obstack
*ob
, unsigned int index
)
596 /* FIXME: identifier may not be unique. */
597 obstack_grow (ob
, "Godump_", 7);
598 snprintf (buf
, sizeof buf
, "%u", index
);
599 obstack_grow (ob
, buf
, strlen (buf
));
604 /* Append the variable name from DECL to OB. If the name is in the
605 KEYWORD_HASH, prepend an '_'. */
608 go_append_decl_name (struct obstack
*ob
, tree decl
, htab_t keyword_hash
)
610 const char *var_name
;
613 /* Start variable name with an underscore if a keyword. */
614 var_name
= IDENTIFIER_POINTER (DECL_NAME (decl
));
615 slot
= htab_find_slot (keyword_hash
, var_name
, NO_INSERT
);
617 obstack_1grow (ob
, '_');
618 go_append_string (ob
, DECL_NAME (decl
));
621 /* Appends a byte array with the necessary number of elements and the name
622 "Godump_INDEX_pad" to pad from FROM_OFFSET to TO_OFFSET to OB assuming that
623 the next field is automatically aligned to ALIGN_UNITS. Returns INDEX + 1,
624 or INDEX if no padding had to be appended. The resulting offset where the
625 next field is allocated is returned through RET_OFFSET. */
628 go_append_padding (struct obstack
*ob
, unsigned int from_offset
,
629 unsigned int to_offset
, unsigned int align_units
,
630 unsigned int index
, unsigned int *ret_offset
)
632 if (from_offset
% align_units
> 0)
633 from_offset
+= align_units
- (from_offset
% align_units
);
634 gcc_assert (to_offset
>= from_offset
);
635 if (to_offset
> from_offset
)
639 index
= go_append_artificial_name (ob
, index
);
640 snprintf (buf
, sizeof buf
, "_pad [%u]byte; ", to_offset
- from_offset
);
641 obstack_grow (ob
, buf
, strlen (buf
));
643 *ret_offset
= to_offset
;
648 /* Appends an array of type TYPE_STRING with zero elements and the name
649 "Godump_INDEX_align" to OB. If TYPE_STRING is a null pointer, ERROR_STRING
650 is appended instead of the type. Returns INDEX + 1. */
653 go_force_record_alignment (struct obstack
*ob
, const char *type_string
,
654 unsigned int index
, const char *error_string
)
656 index
= go_append_artificial_name (ob
, index
);
657 obstack_grow (ob
, "_align ", 7);
658 if (type_string
== NULL
)
659 obstack_grow (ob
, error_string
, strlen (error_string
));
662 obstack_grow (ob
, "[0]", 3);
663 obstack_grow (ob
, type_string
, strlen (type_string
));
665 obstack_grow (ob
, "; ", 2);
670 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
671 USE_TYPE_NAME is true if we can simply use a type name here without
672 needing to define it. IS_FUNC_OK is true if we can output a func
673 type here; the "func" keyword will already have been added.
674 Return true if the type can be represented in Go, false otherwise.
675 P_ART_I is used for indexing artificial elements in nested structures and
676 should always be a NULL pointer when called, except by certain recursive
677 calls from go_format_type() itself. */
680 go_format_type (struct godump_container
*container
, tree type
,
681 bool use_type_name
, bool is_func_ok
, unsigned int *p_art_i
)
685 unsigned int art_i_dummy
;
690 p_art_i
= &art_i_dummy
;
693 ob
= &container
->type_obstack
;
695 if (TYPE_NAME (type
) != NULL_TREE
696 && (container
->decls_seen
.contains (type
)
697 || container
->decls_seen
.contains (TYPE_NAME (type
)))
698 && (AGGREGATE_TYPE_P (type
)
699 || POINTER_TYPE_P (type
)
700 || TREE_CODE (type
) == FUNCTION_TYPE
))
705 name
= TYPE_IDENTIFIER (type
);
707 slot
= htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (name
),
712 obstack_1grow (ob
, '_');
713 go_append_string (ob
, name
);
717 container
->decls_seen
.add (type
);
719 switch (TREE_CODE (type
))
722 obstack_grow (ob
, "int", 3);
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
));
745 s
= go_get_uinttype_for_precision (TYPE_PRECISION (type
),
746 TYPE_UNSIGNED (type
));
749 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
750 TYPE_PRECISION (type
),
751 TYPE_UNSIGNED (type
) ? "u" : "");
755 obstack_grow (ob
, s
, strlen (s
));
764 switch (TYPE_PRECISION (type
))
773 snprintf (buf
, sizeof buf
, "INVALID-float-%u",
774 TYPE_PRECISION (type
));
779 obstack_grow (ob
, s
, strlen (s
));
789 real_type
= TREE_TYPE (type
);
790 if (TREE_CODE (real_type
) == REAL_TYPE
)
792 switch (TYPE_PRECISION (real_type
))
801 snprintf (buf
, sizeof buf
, "INVALID-complex-%u",
802 2 * TYPE_PRECISION (real_type
));
810 s
= "INVALID-complex-non-real";
813 obstack_grow (ob
, s
, strlen (s
));
818 obstack_grow (ob
, "bool", 4);
823 && TYPE_NAME (TREE_TYPE (type
)) != NULL_TREE
824 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
))
825 || (POINTER_TYPE_P (TREE_TYPE (type
))
826 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type
)))
832 name
= TYPE_IDENTIFIER (TREE_TYPE (type
));
834 slot
= htab_find_slot (container
->invalid_hash
,
835 IDENTIFIER_POINTER (name
), NO_INSERT
);
839 obstack_grow (ob
, "*_", 2);
840 go_append_string (ob
, name
);
842 /* The pointer here can be used without the struct or union
843 definition. So this struct or union is a potential dummy
845 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
)))
846 container
->pot_dummy_types
.add (IDENTIFIER_POINTER (name
));
850 if (TREE_CODE (TREE_TYPE (type
)) == FUNCTION_TYPE
)
851 obstack_grow (ob
, "func", 4);
853 obstack_1grow (ob
, '*');
854 if (VOID_TYPE_P (TREE_TYPE (type
)))
855 obstack_grow (ob
, "byte", 4);
858 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
,
865 obstack_1grow (ob
, '[');
866 if (TYPE_DOMAIN (type
) != NULL_TREE
867 && TREE_CODE (TYPE_DOMAIN (type
)) == INTEGER_TYPE
868 && TYPE_MIN_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
869 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
870 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == 0
871 && TYPE_MAX_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
872 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
873 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))))
877 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
"+1",
878 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))));
879 obstack_grow (ob
, buf
, strlen (buf
));
882 obstack_1grow (ob
, '0');
883 obstack_1grow (ob
, ']');
884 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
, false,
891 unsigned int prev_field_end
;
892 unsigned int most_strict_known_alignment
;
895 /* FIXME: Why is this necessary? Without it we can get a core
896 dump on the s390x headers, or from a file containing simply
897 "typedef struct S T;". */
901 most_strict_known_alignment
= 1;
902 obstack_grow (ob
, "struct { ", 9);
903 for (field
= TYPE_FIELDS (type
);
905 field
= TREE_CHAIN (field
))
909 if (TREE_CODE (field
) != FIELD_DECL
)
912 if (DECL_BIT_FIELD (field
))
917 unsigned int decl_align_unit
;
918 unsigned int decl_offset
;
920 decl_align_unit
= DECL_ALIGN_UNIT (field
);
922 TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field
))
924 (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field
)));
925 if (decl_align_unit
> most_strict_known_alignment
)
926 most_strict_known_alignment
= decl_align_unit
;
927 *p_art_i
= go_append_padding
928 (ob
, prev_field_end
, decl_offset
, decl_align_unit
, *p_art_i
,
930 if (DECL_SIZE_UNIT (field
))
931 prev_field_end
+= TREE_INT_CST_LOW (DECL_SIZE_UNIT (field
));
933 if (DECL_NAME (field
) == NULL
)
934 *p_art_i
= go_append_artificial_name (ob
, *p_art_i
);
936 go_append_decl_name (ob
, field
, container
->keyword_hash
);
937 obstack_1grow (ob
, ' ');
939 /* Do not expand type if a record or union type or a
941 if (TYPE_NAME (TREE_TYPE (field
)) != NULL_TREE
942 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field
))
943 || (POINTER_TYPE_P (TREE_TYPE (field
))
944 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field
)))
950 name
= TYPE_IDENTIFIER (TREE_TYPE (field
));
952 slot
= htab_find_slot (container
->invalid_hash
,
953 IDENTIFIER_POINTER (name
),
958 obstack_1grow (ob
, '_');
959 go_append_string (ob
, name
);
963 if (!go_format_type (container
, TREE_TYPE (field
), true,
967 obstack_grow (ob
, "; ", 2);
972 /* Alignment and padding as necessary. */
974 unsigned int type_align_unit
;
976 type_align_unit
= TYPE_ALIGN_UNIT (type
);
978 *p_art_i
= go_append_padding
979 (ob
, prev_field_end
, TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type
)),
980 type_align_unit
, *p_art_i
, &prev_field_end
);
981 if (most_strict_known_alignment
< type_align_unit
)
986 /* Enforce proper record alignment. */
987 s
= go_get_uinttype_for_precision
988 (TYPE_ALIGN (type
), TYPE_UNSIGNED (type
));
991 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
992 TYPE_ALIGN (type
), TYPE_UNSIGNED (type
) ? "u" : "");
996 *p_art_i
= go_force_record_alignment (ob
, s
, *p_art_i
, buf
);
999 obstack_1grow (ob
, '}');
1006 unsigned int sz_units
;
1009 sz_units
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type
));
1010 s
= go_get_uinttype_for_precision (TYPE_ALIGN (type
), true);
1011 obstack_grow (ob
, "struct { ", 9);
1015 s
= "INVALID-union-alignment";
1016 obstack_grow (ob
, s
, strlen (s
));
1023 field
= TYPE_FIELDS (type
);
1024 /* Use the same index as the byte field's artificial name for
1026 if (field
!= NULL_TREE
&& DECL_NAME (field
) != NULL
)
1027 go_append_decl_name (ob
, field
, container
->keyword_hash
);
1029 *p_art_i
= go_append_artificial_name (ob
, *p_art_i
);
1030 snprintf (buf
, sizeof buf
, " [%u]byte; ", sz_units
);
1031 obstack_grow (ob
, buf
, strlen (buf
));
1032 if (TYPE_ALIGN_UNIT (type
) > 1)
1033 *p_art_i
= go_force_record_alignment (ob
, s
, *p_art_i
, NULL
);
1035 obstack_1grow (ob
, '}');
1044 function_args_iterator iter
;
1047 /* Go has no way to write a type which is a function but not a
1048 pointer to a function. */
1051 obstack_grow (ob
, "func*", 5);
1055 obstack_1grow (ob
, '(');
1056 is_varargs
= stdarg_p (type
);
1058 FOREACH_FUNCTION_ARGS (type
, arg_type
, iter
)
1060 if (VOID_TYPE_P (arg_type
))
1063 obstack_grow (ob
, ", ", 2);
1064 if (!go_format_type (container
, arg_type
, true, false, NULL
))
1070 if (prototype_p (type
))
1071 obstack_grow (ob
, ", ", 2);
1072 obstack_grow (ob
, "...interface{}", 14);
1074 obstack_1grow (ob
, ')');
1076 result
= TREE_TYPE (type
);
1077 if (!VOID_TYPE_P (result
))
1079 obstack_1grow (ob
, ' ');
1080 if (!go_format_type (container
, result
, use_type_name
, false, NULL
))
1087 obstack_grow (ob
, "INVALID-type", 12);
1095 /* Output the type which was built on the type obstack, and then free
1099 go_output_type (struct godump_container
*container
)
1103 ob
= &container
->type_obstack
;
1104 obstack_1grow (ob
, '\0');
1105 fputs ((char *) obstack_base (ob
), go_dump_file
);
1106 obstack_free (ob
, obstack_base (ob
));
1109 /* Output a function declaration. */
1112 go_output_fndecl (struct godump_container
*container
, tree decl
)
1114 if (!go_format_type (container
, TREE_TYPE (decl
), false, true, NULL
))
1115 fprintf (go_dump_file
, "// ");
1116 fprintf (go_dump_file
, "func _%s ",
1117 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1118 go_output_type (container
);
1119 fprintf (go_dump_file
, " __asm__(\"%s\")\n",
1120 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
)));
1123 /* Output a typedef or something like a struct definition. */
1126 go_output_typedef (struct godump_container
*container
, tree decl
)
1128 /* If we have an enum type, output the enum constants
1130 if (TREE_CODE (TREE_TYPE (decl
)) == ENUMERAL_TYPE
1131 && TYPE_SIZE (TREE_TYPE (decl
)) != 0
1132 && !container
->decls_seen
.contains (TREE_TYPE (decl
))
1133 && (TYPE_CANONICAL (TREE_TYPE (decl
)) == NULL_TREE
1134 || !container
->decls_seen
.contains
1135 (TYPE_CANONICAL (TREE_TYPE (decl
)))))
1139 for (element
= TYPE_VALUES (TREE_TYPE (decl
));
1140 element
!= NULL_TREE
;
1141 element
= TREE_CHAIN (element
))
1144 struct macro_hash_value
*mhval
;
1146 char buf
[WIDE_INT_PRINT_BUFFER_SIZE
];
1148 name
= IDENTIFIER_POINTER (TREE_PURPOSE (element
));
1150 /* Sometimes a name will be defined as both an enum constant
1151 and a macro. Avoid duplicate definition errors by
1152 treating enum constants as macros. */
1153 mhval
= XNEW (struct macro_hash_value
);
1154 mhval
->name
= xstrdup (name
);
1155 mhval
->value
= NULL
;
1156 slot
= htab_find_slot (macro_hash
, mhval
, INSERT
);
1158 macro_hash_del (*slot
);
1160 if (tree_fits_shwi_p (TREE_VALUE (element
)))
1161 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
,
1162 tree_to_shwi (TREE_VALUE (element
)));
1163 else if (tree_fits_uhwi_p (TREE_VALUE (element
)))
1164 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_UNSIGNED
,
1165 tree_to_uhwi (TREE_VALUE (element
)));
1167 print_hex (element
, buf
);
1169 mhval
->value
= xstrdup (buf
);
1172 container
->decls_seen
.add (TREE_TYPE (decl
));
1173 if (TYPE_CANONICAL (TREE_TYPE (decl
)) != NULL_TREE
)
1174 container
->decls_seen
.add (TYPE_CANONICAL (TREE_TYPE (decl
)));
1177 if (DECL_NAME (decl
) != NULL_TREE
)
1182 type
= IDENTIFIER_POINTER (DECL_NAME (decl
));
1183 /* If type defined already, skip. */
1184 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1187 *slot
= CONST_CAST (void *, (const void *) type
);
1189 if (!go_format_type (container
, TREE_TYPE (decl
), false, false, NULL
))
1191 fprintf (go_dump_file
, "// ");
1192 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1193 *slot
= CONST_CAST (void *, (const void *) type
);
1195 fprintf (go_dump_file
, "type _%s ",
1196 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1197 go_output_type (container
);
1199 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1201 HOST_WIDE_INT size
= int_size_in_bytes (TREE_TYPE (decl
));
1204 fprintf (go_dump_file
,
1205 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1206 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1210 container
->decls_seen
.add (decl
);
1212 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1218 type
= IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl
))));
1219 /* If type defined already, skip. */
1220 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1223 *slot
= CONST_CAST (void *, (const void *) type
);
1225 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
);
1290 && htab_find_slot (container
->type_hash
,
1291 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1294 /* There is already a type with this name, probably from a
1295 struct tag. Prefer the type to the variable. */
1299 fprintf (go_dump_file
, "// ");
1301 fprintf (go_dump_file
, "var _%s ",
1302 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1303 go_output_type (container
);
1304 fprintf (go_dump_file
, "\n");
1306 /* Sometimes an extern variable is declared with an unknown struct
1308 if (type_name
!= NULL_TREE
&& RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1310 if (TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1311 container
->pot_dummy_types
.add (IDENTIFIER_POINTER (type_name
));
1312 else if (TREE_CODE (type_name
) == TYPE_DECL
)
1313 container
->pot_dummy_types
.add
1314 (IDENTIFIER_POINTER (DECL_NAME (type_name
)));
1318 /* Output the final value of a preprocessor macro or enum constant.
1319 This is called via htab_traverse_noresize. */
1322 go_print_macro (void **slot
, void *arg ATTRIBUTE_UNUSED
)
1324 struct macro_hash_value
*mhval
= (struct macro_hash_value
*) *slot
;
1325 fprintf (go_dump_file
, "const _%s = %s\n", mhval
->name
, mhval
->value
);
1329 /* Build a hash table with the Go keywords. */
1331 static const char * const keywords
[] = {
1332 "__asm__", "break", "case", "chan", "const", "continue", "default",
1333 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1334 "import", "interface", "map", "package", "range", "return", "select",
1335 "struct", "switch", "type", "var"
1339 keyword_hash_init (struct godump_container
*container
)
1342 size_t count
= sizeof (keywords
) / sizeof (keywords
[0]);
1345 for (i
= 0; i
< count
; i
++)
1347 slot
= htab_find_slot (container
->keyword_hash
, keywords
[i
], INSERT
);
1348 *slot
= CONST_CAST (void *, (const void *) keywords
[i
]);
1352 /* Traversing the pot_dummy_types and seeing which types are present
1353 in the global types hash table and creating dummy definitions if
1354 not found. This function is invoked by hash_set::traverse. */
1357 find_dummy_types (const char *const &ptr
, godump_container
*adata
)
1359 struct godump_container
*data
= (struct godump_container
*) adata
;
1360 const char *type
= (const char *) ptr
;
1364 slot
= htab_find_slot (data
->type_hash
, type
, NO_INSERT
);
1365 islot
= htab_find_slot (data
->invalid_hash
, type
, NO_INSERT
);
1366 if (slot
== NULL
|| islot
!= NULL
)
1367 fprintf (go_dump_file
, "type _%s struct {}\n", type
);
1371 /* Output symbols. */
1374 go_finish (const char *filename
)
1376 struct godump_container container
;
1380 real_debug_hooks
->finish (filename
);
1382 container
.type_hash
= htab_create (100, htab_hash_string
,
1383 string_hash_eq
, NULL
);
1384 container
.invalid_hash
= htab_create (10, htab_hash_string
,
1385 string_hash_eq
, NULL
);
1386 container
.keyword_hash
= htab_create (50, htab_hash_string
,
1387 string_hash_eq
, NULL
);
1388 obstack_init (&container
.type_obstack
);
1390 keyword_hash_init (&container
);
1392 FOR_EACH_VEC_SAFE_ELT (queue
, ix
, decl
)
1394 switch (TREE_CODE (decl
))
1397 go_output_fndecl (&container
, decl
);
1401 go_output_typedef (&container
, decl
);
1405 go_output_var (&container
, decl
);
1413 htab_traverse_noresize (macro_hash
, go_print_macro
, NULL
);
1415 /* To emit dummy definitions. */
1416 container
.pot_dummy_types
.traverse
<godump_container
*, find_dummy_types
>
1419 htab_delete (container
.type_hash
);
1420 htab_delete (container
.invalid_hash
);
1421 htab_delete (container
.keyword_hash
);
1422 obstack_free (&container
.type_obstack
, NULL
);
1426 if (fclose (go_dump_file
) != 0)
1427 error ("could not close Go dump file: %m");
1428 go_dump_file
= NULL
;
1431 /* Set up our hooks. */
1433 const struct gcc_debug_hooks
*
1434 dump_go_spec_init (const char *filename
, const struct gcc_debug_hooks
*hooks
)
1436 go_dump_file
= fopen (filename
, "w");
1437 if (go_dump_file
== NULL
)
1439 error ("could not open Go dump file %qs: %m", filename
);
1443 go_debug_hooks
= *hooks
;
1444 real_debug_hooks
= hooks
;
1446 go_debug_hooks
.finish
= go_finish
;
1447 go_debug_hooks
.define
= go_define
;
1448 go_debug_hooks
.undef
= go_undef
;
1449 go_debug_hooks
.function_decl
= go_function_decl
;
1450 go_debug_hooks
.global_decl
= go_global_decl
;
1451 go_debug_hooks
.type_decl
= go_type_decl
;
1453 macro_hash
= htab_create (100, macro_hash_hashval
, macro_hash_eq
,
1456 return &go_debug_hooks
;
1459 #include "gt-godump.h"