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"
41 #include "wide-int-print.h"
42 #include "stor-layout.h"
45 /* We dump this information from the debug hooks. This gives us a
46 stable and maintainable API to hook into. In order to work
47 correctly when -g is used, we build our own hooks structure which
48 wraps the hooks we need to change. */
50 /* Our debug hooks. This is initialized by dump_go_spec_init. */
52 static struct gcc_debug_hooks go_debug_hooks
;
54 /* The real debug hooks. */
56 static const struct gcc_debug_hooks
*real_debug_hooks
;
58 /* The file where we should write information. */
60 static FILE *go_dump_file
;
62 /* A queue of decls to output. */
64 static GTY(()) vec
<tree
, va_gc
> *queue
;
66 /* A hash table of macros we have seen. */
68 static htab_t macro_hash
;
70 /* The type of a value in macro_hash. */
72 struct macro_hash_value
74 /* The name stored in the hash table. */
76 /* The value of the macro. */
80 /* Returns the number of units necessary to represent an integer with the given
81 PRECISION (in bits). */
83 static inline unsigned int
84 precision_to_units (unsigned int precision
)
86 return (precision
+ BITS_PER_UNIT
- 1) / BITS_PER_UNIT
;
89 /* Calculate the hash value for an entry in the macro hash table. */
92 macro_hash_hashval (const void *val
)
94 const struct macro_hash_value
*mhval
= (const struct macro_hash_value
*) val
;
95 return htab_hash_string (mhval
->name
);
98 /* Compare values in the macro hash table for equality. */
101 macro_hash_eq (const void *v1
, const void *v2
)
103 const struct macro_hash_value
*mhv1
= (const struct macro_hash_value
*) v1
;
104 const struct macro_hash_value
*mhv2
= (const struct macro_hash_value
*) v2
;
105 return strcmp (mhv1
->name
, mhv2
->name
) == 0;
108 /* Free values deleted from the macro hash table. */
111 macro_hash_del (void *v
)
113 struct macro_hash_value
*mhv
= (struct macro_hash_value
*) v
;
114 XDELETEVEC (mhv
->name
);
115 XDELETEVEC (mhv
->value
);
119 /* For the string hash tables. */
122 string_hash_eq (const void *y1
, const void *y2
)
124 return strcmp ((const char *) y1
, (const char *) y2
) == 0;
127 /* A macro definition. */
130 go_define (unsigned int lineno
, const char *buffer
)
133 const char *name_end
;
139 struct macro_hash_value
*mhval
;
144 real_debug_hooks
->define (lineno
, buffer
);
146 /* Skip macro functions. */
147 for (p
= buffer
; *p
!= '\0' && *p
!= ' '; ++p
)
160 copy
= XNEWVEC (char, name_end
- buffer
+ 1);
161 memcpy (copy
, buffer
, name_end
- buffer
);
162 copy
[name_end
- buffer
] = '\0';
164 mhval
= XNEW (struct macro_hash_value
);
168 hashval
= htab_hash_string (copy
);
169 slot
= htab_find_slot_with_hash (macro_hash
, mhval
, hashval
, NO_INSERT
);
171 /* For simplicity, we force all names to be hidden by adding an
172 initial underscore, and let the user undo this as needed. */
173 out_len
= strlen (p
) * 2 + 1;
174 out_buffer
= XNEWVEC (char, out_len
);
177 need_operand
= false;
182 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
183 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
184 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
185 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
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':
194 /* The start of an identifier. Technically we should also
195 worry about UTF-8 identifiers, but they are not a
196 problem for practical uses of -fdump-go-spec so we
197 don't worry about them. */
200 struct macro_hash_value idval
;
206 while (ISALNUM (*p
) || *p
== '_')
208 n
= XALLOCAVEC (char, p
- start
+ 1);
209 memcpy (n
, start
, p
- start
);
213 if (htab_find (macro_hash
, &idval
) == NULL
)
215 /* This is a reference to a name which was not defined
221 memcpy (q
, start
, p
- start
);
225 need_operand
= false;
233 case '0': case '1': case '2': case '3': case '4':
234 case '5': case '6': case '7': case '8': case '9':
241 if (*p
== '0' && (p
[1] == 'x' || p
[1] == 'X'))
246 while (ISDIGIT (*p
) || *p
== '.' || *p
== 'e' || *p
== 'E'
248 && ((*p
>= 'a' && *p
<= 'f')
249 || (*p
>= 'A' && *p
<= 'F'))))
251 memcpy (q
, start
, p
- start
);
253 while (*p
== 'u' || *p
== 'U' || *p
== 'l' || *p
== 'L'
254 || *p
== 'f' || *p
== 'F'
255 || *p
== 'd' || *p
== 'D')
257 /* Go doesn't use any of these trailing type
262 /* We'll pick up the exponent, if any, as an
266 need_operand
= false;
275 /* Always OK, not part of an operand, presumed to start an
279 need_operand
= false;
283 /* OK if we don't need an operand, and presumed to indicate
292 /* Always OK, but not part of an operand. */
297 case '*': case '/': case '%': case '|': case '&': case '^':
298 /* Must be a binary operator. */
310 /* Must be a binary operator. */
322 /* Must be a binary operator. */
331 /* Must be a unary operator. */
339 /* Must be a binary operand, may be << or >> or <= or >=. */
343 if (*p
== *(p
- 1) || *p
== '=')
350 /* Must be a unary operand, must be translated for Go. */
387 case '0': case '1': case '2': case '3':
388 case '4': case '5': case '6': case '7':
390 while (*p
>= '0' && *p
<= '7')
395 /* Go octal characters are always 3
404 while (ISXDIGIT (*p
))
409 /* Go hex characters are always 2 digits. */
414 case 'a': case 'b': case 'f': case 'n': case 'r':
415 case 't': case 'v': case '\\': case '\'': case '"':
426 if (quote
== '\'' && count
!= 1)
430 need_operand
= false;
443 gcc_assert ((size_t) (q
- out_buffer
) < out_len
);
446 mhval
->value
= out_buffer
;
450 slot
= htab_find_slot_with_hash (macro_hash
, mhval
, hashval
, INSERT
);
451 gcc_assert (slot
!= NULL
&& *slot
== NULL
);
456 macro_hash_del (*slot
);
464 fprintf (go_dump_file
, "// unknowndefine %s\n", buffer
);
466 htab_clear_slot (macro_hash
, slot
);
467 XDELETEVEC (out_buffer
);
474 go_undef (unsigned int lineno
, const char *buffer
)
476 struct macro_hash_value mhval
;
479 real_debug_hooks
->undef (lineno
, buffer
);
481 mhval
.name
= CONST_CAST (char *, buffer
);
483 slot
= htab_find_slot (macro_hash
, &mhval
, NO_INSERT
);
485 htab_clear_slot (macro_hash
, slot
);
488 /* A function or variable decl. */
493 if (!TREE_PUBLIC (decl
)
494 || DECL_IS_BUILTIN (decl
)
495 || DECL_NAME (decl
) == NULL_TREE
)
497 vec_safe_push (queue
, decl
);
500 /* A function decl. */
503 go_function_decl (tree decl
)
505 real_debug_hooks
->function_decl (decl
);
510 go_early_global_decl (tree decl
)
513 real_debug_hooks
->early_global_decl (decl
);
516 /* A global variable decl. */
519 go_late_global_decl (tree decl
)
521 real_debug_hooks
->late_global_decl (decl
);
524 /* A type declaration. */
527 go_type_decl (tree decl
, int local
)
529 real_debug_hooks
->type_decl (decl
, local
);
531 if (local
|| DECL_IS_BUILTIN (decl
))
533 if (DECL_NAME (decl
) == NULL_TREE
534 && (TYPE_NAME (TREE_TYPE (decl
)) == NULL_TREE
535 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl
))) != IDENTIFIER_NODE
)
536 && TREE_CODE (TREE_TYPE (decl
)) != ENUMERAL_TYPE
)
538 vec_safe_push (queue
, decl
);
541 /* A container for the data we pass around when generating information
542 at the end of the compilation. */
544 struct godump_container
546 /* DECLs that we have already seen. */
547 hash_set
<tree
> decls_seen
;
549 /* Types which may potentially have to be defined as dummy
551 hash_set
<const char *> pot_dummy_types
;
556 /* Global type definitions. */
562 /* Obstack used to write out a type definition. */
563 struct obstack type_obstack
;
566 /* Append an IDENTIFIER_NODE to OB. */
569 go_append_string (struct obstack
*ob
, tree id
)
571 obstack_grow (ob
, IDENTIFIER_POINTER (id
), IDENTIFIER_LENGTH (id
));
574 /* Given an integer PRECISION in bits, returns a constant string that is the
575 matching go int or uint type (depending on the IS_UNSIGNED flag). Returns a
576 NULL pointer if there is no matching go type. */
579 go_get_uinttype_for_precision (unsigned int precision
, bool is_unsigned
)
584 return is_unsigned
? "uint8" : "int8";
586 return is_unsigned
? "uint16" : "int16";
588 return is_unsigned
? "uint32" : "int32";
590 return is_unsigned
? "uint64" : "int64";
596 /* Append an artificial variable name with the suffix _INDEX to OB. Returns
600 go_append_artificial_name (struct obstack
*ob
, unsigned int index
)
604 /* FIXME: identifier may not be unique. */
605 obstack_grow (ob
, "Godump_", 7);
606 snprintf (buf
, sizeof buf
, "%u", index
);
607 obstack_grow (ob
, buf
, strlen (buf
));
612 /* Append the variable name from DECL to OB. If the name is in the
613 KEYWORD_HASH, prepend an '_'. */
616 go_append_decl_name (struct obstack
*ob
, tree decl
, htab_t keyword_hash
)
618 const char *var_name
;
621 /* Start variable name with an underscore if a keyword. */
622 var_name
= IDENTIFIER_POINTER (DECL_NAME (decl
));
623 slot
= htab_find_slot (keyword_hash
, var_name
, NO_INSERT
);
625 obstack_1grow (ob
, '_');
626 go_append_string (ob
, DECL_NAME (decl
));
629 /* Appends a byte array with the necessary number of elements and the name
630 "Godump_INDEX_pad" to pad from FROM_OFFSET to TO_OFFSET to OB assuming that
631 the next field is automatically aligned to ALIGN_UNITS. Returns INDEX + 1,
632 or INDEX if no padding had to be appended. The resulting offset where the
633 next field is allocated is returned through RET_OFFSET. */
636 go_append_padding (struct obstack
*ob
, unsigned int from_offset
,
637 unsigned int to_offset
, unsigned int align_units
,
638 unsigned int index
, unsigned int *ret_offset
)
640 if (from_offset
% align_units
> 0)
641 from_offset
+= align_units
- (from_offset
% align_units
);
642 gcc_assert (to_offset
>= from_offset
);
643 if (to_offset
> from_offset
)
647 index
= go_append_artificial_name (ob
, index
);
648 snprintf (buf
, sizeof buf
, "_pad [%u]byte; ", to_offset
- from_offset
);
649 obstack_grow (ob
, buf
, strlen (buf
));
651 *ret_offset
= to_offset
;
656 /* Appends an array of type TYPE_STRING with zero elements and the name
657 "Godump_INDEX_align" to OB. If TYPE_STRING is a null pointer, ERROR_STRING
658 is appended instead of the type. Returns INDEX + 1. */
661 go_force_record_alignment (struct obstack
*ob
, const char *type_string
,
662 unsigned int index
, const char *error_string
)
664 index
= go_append_artificial_name (ob
, index
);
665 obstack_grow (ob
, "_align ", 7);
666 if (type_string
== NULL
)
667 obstack_grow (ob
, error_string
, strlen (error_string
));
670 obstack_grow (ob
, "[0]", 3);
671 obstack_grow (ob
, type_string
, strlen (type_string
));
673 obstack_grow (ob
, "; ", 2);
678 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
679 USE_TYPE_NAME is true if we can simply use a type name here without
680 needing to define it. IS_FUNC_OK is true if we can output a func
681 type here; the "func" keyword will already have been added.
682 Return true if the type can be represented in Go, false otherwise.
683 P_ART_I is used for indexing artificial elements in nested structures and
684 should always be a NULL pointer when called, except by certain recursive
685 calls from go_format_type() itself. */
688 go_format_type (struct godump_container
*container
, tree type
,
689 bool use_type_name
, bool is_func_ok
, unsigned int *p_art_i
,
690 bool is_anon_record_or_union
)
694 unsigned int art_i_dummy
;
695 bool is_union
= false;
700 p_art_i
= &art_i_dummy
;
703 ob
= &container
->type_obstack
;
705 if (TYPE_NAME (type
) != NULL_TREE
706 && (container
->decls_seen
.contains (type
)
707 || container
->decls_seen
.contains (TYPE_NAME (type
)))
708 && (AGGREGATE_TYPE_P (type
)
709 || POINTER_TYPE_P (type
)
710 || TREE_CODE (type
) == FUNCTION_TYPE
))
715 name
= TYPE_IDENTIFIER (type
);
717 slot
= htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (name
),
722 obstack_1grow (ob
, '_');
723 go_append_string (ob
, name
);
727 container
->decls_seen
.add (type
);
729 switch (TREE_CODE (type
))
732 obstack_grow (ob
, "int", 3);
739 slot
= htab_find_slot (container
->invalid_hash
,
740 IDENTIFIER_POINTER (DECL_NAME (type
)),
745 obstack_1grow (ob
, '_');
746 go_append_string (ob
, DECL_NAME (type
));
755 s
= go_get_uinttype_for_precision (TYPE_PRECISION (type
),
756 TYPE_UNSIGNED (type
));
759 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
760 TYPE_PRECISION (type
),
761 TYPE_UNSIGNED (type
) ? "u" : "");
765 obstack_grow (ob
, s
, strlen (s
));
774 switch (TYPE_PRECISION (type
))
783 snprintf (buf
, sizeof buf
, "INVALID-float-%u",
784 TYPE_PRECISION (type
));
789 obstack_grow (ob
, s
, strlen (s
));
799 real_type
= TREE_TYPE (type
);
800 if (TREE_CODE (real_type
) == REAL_TYPE
)
802 switch (TYPE_PRECISION (real_type
))
811 snprintf (buf
, sizeof buf
, "INVALID-complex-%u",
812 2 * TYPE_PRECISION (real_type
));
820 s
= "INVALID-complex-non-real";
823 obstack_grow (ob
, s
, strlen (s
));
828 obstack_grow (ob
, "bool", 4);
833 && TYPE_NAME (TREE_TYPE (type
)) != NULL_TREE
834 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
))
835 || (POINTER_TYPE_P (TREE_TYPE (type
))
836 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type
)))
842 name
= TYPE_IDENTIFIER (TREE_TYPE (type
));
844 slot
= htab_find_slot (container
->invalid_hash
,
845 IDENTIFIER_POINTER (name
), NO_INSERT
);
849 obstack_grow (ob
, "*_", 2);
850 go_append_string (ob
, name
);
852 /* The pointer here can be used without the struct or union
853 definition. So this struct or union is a potential dummy
855 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type
)))
856 container
->pot_dummy_types
.add (IDENTIFIER_POINTER (name
));
860 if (TREE_CODE (TREE_TYPE (type
)) == FUNCTION_TYPE
)
861 obstack_grow (ob
, "func", 4);
863 obstack_1grow (ob
, '*');
864 if (VOID_TYPE_P (TREE_TYPE (type
)))
865 obstack_grow (ob
, "byte", 4);
868 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
,
875 obstack_1grow (ob
, '[');
876 if (TYPE_DOMAIN (type
) != NULL_TREE
877 && TREE_CODE (TYPE_DOMAIN (type
)) == INTEGER_TYPE
878 && TYPE_MIN_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
879 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
880 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type
))) == 0
881 && TYPE_MAX_VALUE (TYPE_DOMAIN (type
)) != NULL_TREE
882 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))) == INTEGER_CST
883 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))))
887 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
"+1",
888 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type
))));
889 obstack_grow (ob
, buf
, strlen (buf
));
892 obstack_1grow (ob
, '0');
893 obstack_1grow (ob
, ']');
894 if (!go_format_type (container
, TREE_TYPE (type
), use_type_name
, false,
901 /* Fall through to RECORD_TYPE case. */
904 unsigned int prev_field_end
;
905 unsigned int known_alignment
;
907 bool emitted_a_field
;
909 /* FIXME: Why is this necessary? Without it we can get a core
910 dump on the s390x headers, or from a file containing simply
911 "typedef struct S T;". */
916 /* Anonymous records and unions are flattened, i.e. they are not put
917 into "struct { ... }". */
918 if (!is_anon_record_or_union
)
919 obstack_grow (ob
, "struct { ", 9);
920 for (field
= TYPE_FIELDS (type
), emitted_a_field
= false;
922 field
= TREE_CHAIN (field
))
924 if (TREE_CODE (field
) != FIELD_DECL
)
926 if (DECL_BIT_FIELD (field
))
927 /* Bit fields are replaced by padding. */
929 /* Only the first non-bitfield field is emitted for unions. */
930 if (!is_union
|| !emitted_a_field
)
932 /* Emit the field. */
934 bool is_anon_substructure
;
935 unsigned int decl_align_unit
;
936 unsigned int decl_offset
;
939 emitted_a_field
= true;
940 is_anon_substructure
=
941 (DECL_NAME (field
) == NULL
942 && (TREE_CODE (TREE_TYPE (field
)) == RECORD_TYPE
943 || TREE_CODE (TREE_TYPE (field
)) == UNION_TYPE
));
944 /* Keep track of the alignment of named substructures, either
945 of the whole record, or the alignment of the emitted field
947 decl_align_unit
= DECL_ALIGN_UNIT (field
);
948 if (!is_anon_substructure
&& decl_align_unit
> known_alignment
)
949 known_alignment
= decl_align_unit
;
950 /* Pad to start of field. */
952 TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field
))
954 (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field
)));
956 unsigned int align_unit
;
958 /* For anonymous records and unions there is no automatic
959 structure alignment, so use 1 as the alignment. */
960 align_unit
= (is_anon_substructure
) ? 1 : decl_align_unit
;
961 *p_art_i
= go_append_padding
962 (ob
, prev_field_end
, decl_offset
, align_unit
, *p_art_i
,
965 if (DECL_SIZE_UNIT (field
))
967 TREE_INT_CST_LOW (DECL_SIZE_UNIT (field
));
968 /* Emit the field name, but not for anonymous records and
970 if (!is_anon_substructure
)
972 if ((DECL_NAME (field
) == NULL
))
973 *p_art_i
= go_append_artificial_name (ob
, *p_art_i
);
976 (ob
, field
, container
->keyword_hash
);
977 obstack_1grow (ob
, ' ');
979 /* Do not expand type if a record or union type or a function
981 if (TYPE_NAME (TREE_TYPE (field
)) != NULL_TREE
982 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field
))
983 || (POINTER_TYPE_P (TREE_TYPE (field
))
984 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field
)))
990 name
= TYPE_IDENTIFIER (TREE_TYPE (field
));
992 slot
= htab_find_slot (container
->invalid_hash
,
993 IDENTIFIER_POINTER (name
),
998 obstack_1grow (ob
, '_');
999 go_append_string (ob
, name
);
1003 if (!go_format_type (container
, TREE_TYPE (field
), true,
1004 false, p_art_i
, is_anon_substructure
))
1007 if (!is_anon_substructure
)
1008 obstack_grow (ob
, "; ", 2);
1015 unsigned int align_unit
;
1017 align_unit
= (is_anon_record_or_union
) ? 1 : TYPE_ALIGN_UNIT (type
);
1018 *p_art_i
= go_append_padding
1019 (ob
, prev_field_end
, TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type
)),
1020 align_unit
, *p_art_i
, &prev_field_end
);
1023 if (!is_anon_record_or_union
1024 && known_alignment
< TYPE_ALIGN_UNIT (type
))
1029 /* Enforce proper record alignment. */
1030 s
= go_get_uinttype_for_precision
1031 (TYPE_ALIGN (type
), TYPE_UNSIGNED (type
));
1034 snprintf (buf
, sizeof buf
, "INVALID-int-%u%s",
1035 TYPE_ALIGN (type
), TYPE_UNSIGNED (type
) ? "u" : "");
1039 *p_art_i
= go_force_record_alignment (ob
, s
, *p_art_i
, buf
);
1041 if (!is_anon_record_or_union
)
1042 obstack_1grow (ob
, '}');
1051 function_args_iterator iter
;
1054 /* Go has no way to write a type which is a function but not a
1055 pointer to a function. */
1058 obstack_grow (ob
, "func*", 5);
1062 obstack_1grow (ob
, '(');
1063 is_varargs
= stdarg_p (type
);
1065 FOREACH_FUNCTION_ARGS (type
, arg_type
, iter
)
1067 if (VOID_TYPE_P (arg_type
))
1070 obstack_grow (ob
, ", ", 2);
1071 if (!go_format_type (container
, arg_type
, true, false, NULL
, false))
1077 if (prototype_p (type
))
1078 obstack_grow (ob
, ", ", 2);
1079 obstack_grow (ob
, "...interface{}", 14);
1081 obstack_1grow (ob
, ')');
1083 result
= TREE_TYPE (type
);
1084 if (!VOID_TYPE_P (result
))
1086 obstack_1grow (ob
, ' ');
1087 if (!go_format_type (container
, result
, use_type_name
, false, NULL
,
1095 obstack_grow (ob
, "INVALID-type", 12);
1103 /* Output the type which was built on the type obstack, and then free
1107 go_output_type (struct godump_container
*container
)
1111 ob
= &container
->type_obstack
;
1112 obstack_1grow (ob
, '\0');
1113 fputs ((char *) obstack_base (ob
), go_dump_file
);
1114 obstack_free (ob
, obstack_base (ob
));
1117 /* Output a function declaration. */
1120 go_output_fndecl (struct godump_container
*container
, tree decl
)
1122 if (!go_format_type (container
, TREE_TYPE (decl
), false, true, NULL
, false))
1123 fprintf (go_dump_file
, "// ");
1124 fprintf (go_dump_file
, "func _%s ",
1125 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1126 go_output_type (container
);
1127 fprintf (go_dump_file
, " __asm__(\"%s\")\n",
1128 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
)));
1131 /* Output a typedef or something like a struct definition. */
1134 go_output_typedef (struct godump_container
*container
, tree decl
)
1136 /* If we have an enum type, output the enum constants
1138 if (TREE_CODE (TREE_TYPE (decl
)) == ENUMERAL_TYPE
1139 && TYPE_SIZE (TREE_TYPE (decl
)) != 0
1140 && !container
->decls_seen
.contains (TREE_TYPE (decl
))
1141 && (TYPE_CANONICAL (TREE_TYPE (decl
)) == NULL_TREE
1142 || !container
->decls_seen
.contains
1143 (TYPE_CANONICAL (TREE_TYPE (decl
)))))
1147 for (element
= TYPE_VALUES (TREE_TYPE (decl
));
1148 element
!= NULL_TREE
;
1149 element
= TREE_CHAIN (element
))
1152 struct macro_hash_value
*mhval
;
1154 char buf
[WIDE_INT_PRINT_BUFFER_SIZE
];
1156 name
= IDENTIFIER_POINTER (TREE_PURPOSE (element
));
1158 /* Sometimes a name will be defined as both an enum constant
1159 and a macro. Avoid duplicate definition errors by
1160 treating enum constants as macros. */
1161 mhval
= XNEW (struct macro_hash_value
);
1162 mhval
->name
= xstrdup (name
);
1163 mhval
->value
= NULL
;
1164 slot
= htab_find_slot (macro_hash
, mhval
, INSERT
);
1166 macro_hash_del (*slot
);
1168 if (tree_fits_shwi_p (TREE_VALUE (element
)))
1169 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_DEC
,
1170 tree_to_shwi (TREE_VALUE (element
)));
1171 else if (tree_fits_uhwi_p (TREE_VALUE (element
)))
1172 snprintf (buf
, sizeof buf
, HOST_WIDE_INT_PRINT_UNSIGNED
,
1173 tree_to_uhwi (TREE_VALUE (element
)));
1175 print_hex (element
, buf
);
1177 mhval
->value
= xstrdup (buf
);
1180 container
->decls_seen
.add (TREE_TYPE (decl
));
1181 if (TYPE_CANONICAL (TREE_TYPE (decl
)) != NULL_TREE
)
1182 container
->decls_seen
.add (TYPE_CANONICAL (TREE_TYPE (decl
)));
1185 if (DECL_NAME (decl
) != NULL_TREE
)
1190 type
= IDENTIFIER_POINTER (DECL_NAME (decl
));
1191 /* If type defined already, skip. */
1192 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1195 *slot
= CONST_CAST (void *, (const void *) type
);
1197 if (!go_format_type (container
, TREE_TYPE (decl
), false, false, NULL
,
1200 fprintf (go_dump_file
, "// ");
1201 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1202 *slot
= CONST_CAST (void *, (const void *) type
);
1204 fprintf (go_dump_file
, "type _%s ",
1205 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1206 go_output_type (container
);
1208 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1210 HOST_WIDE_INT size
= int_size_in_bytes (TREE_TYPE (decl
));
1213 fprintf (go_dump_file
,
1214 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1215 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1219 container
->decls_seen
.add (decl
);
1221 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1227 type
= IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl
))));
1228 /* If type defined already, skip. */
1229 slot
= htab_find_slot (container
->type_hash
, type
, INSERT
);
1232 *slot
= CONST_CAST (void *, (const void *) type
);
1234 if (!go_format_type (container
, TREE_TYPE (decl
), false, false, NULL
,
1237 fprintf (go_dump_file
, "// ");
1238 slot
= htab_find_slot (container
->invalid_hash
, type
, INSERT
);
1239 *slot
= CONST_CAST (void *, (const void *) type
);
1241 fprintf (go_dump_file
, "type _%s ",
1242 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))));
1243 go_output_type (container
);
1245 size
= int_size_in_bytes (TREE_TYPE (decl
));
1247 fprintf (go_dump_file
,
1248 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC
,
1249 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl
))),
1255 fprintf (go_dump_file
, "\n");
1258 /* Output a variable. */
1261 go_output_var (struct godump_container
*container
, tree decl
)
1267 if (container
->decls_seen
.contains (decl
)
1268 || container
->decls_seen
.contains (DECL_NAME (decl
)))
1270 container
->decls_seen
.add (decl
);
1271 container
->decls_seen
.add (DECL_NAME (decl
));
1273 type_name
= TYPE_NAME (TREE_TYPE (decl
));
1275 if (type_name
!= NULL_TREE
&& TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1277 else if (type_name
!= NULL_TREE
&& TREE_CODE (type_name
) == TYPE_DECL
1278 && DECL_SOURCE_LOCATION (type_name
) != BUILTINS_LOCATION
1279 && DECL_NAME (type_name
))
1280 id
= DECL_NAME (type_name
);
1282 && (!htab_find_slot (container
->type_hash
, IDENTIFIER_POINTER (id
),
1284 || htab_find_slot (container
->invalid_hash
, IDENTIFIER_POINTER (id
),
1287 if (id
!= NULL_TREE
)
1291 ob
= &container
->type_obstack
;
1292 obstack_1grow (ob
, '_');
1293 go_append_string (ob
, id
);
1294 is_valid
= htab_find_slot (container
->type_hash
, IDENTIFIER_POINTER (id
),
1298 is_valid
= go_format_type (container
, TREE_TYPE (decl
), true, false, NULL
,
1301 && htab_find_slot (container
->type_hash
,
1302 IDENTIFIER_POINTER (DECL_NAME (decl
)),
1305 /* There is already a type with this name, probably from a
1306 struct tag. Prefer the type to the variable. */
1310 fprintf (go_dump_file
, "// ");
1312 fprintf (go_dump_file
, "var _%s ",
1313 IDENTIFIER_POINTER (DECL_NAME (decl
)));
1314 go_output_type (container
);
1315 fprintf (go_dump_file
, "\n");
1317 /* Sometimes an extern variable is declared with an unknown struct
1319 if (type_name
!= NULL_TREE
&& RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl
)))
1321 if (TREE_CODE (type_name
) == IDENTIFIER_NODE
)
1322 container
->pot_dummy_types
.add (IDENTIFIER_POINTER (type_name
));
1323 else if (TREE_CODE (type_name
) == TYPE_DECL
)
1324 container
->pot_dummy_types
.add
1325 (IDENTIFIER_POINTER (DECL_NAME (type_name
)));
1329 /* Output the final value of a preprocessor macro or enum constant.
1330 This is called via htab_traverse_noresize. */
1333 go_print_macro (void **slot
, void *arg ATTRIBUTE_UNUSED
)
1335 struct macro_hash_value
*mhval
= (struct macro_hash_value
*) *slot
;
1336 fprintf (go_dump_file
, "const _%s = %s\n", mhval
->name
, mhval
->value
);
1340 /* Build a hash table with the Go keywords. */
1342 static const char * const keywords
[] = {
1343 "__asm__", "break", "case", "chan", "const", "continue", "default",
1344 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1345 "import", "interface", "map", "package", "range", "return", "select",
1346 "struct", "switch", "type", "var"
1350 keyword_hash_init (struct godump_container
*container
)
1353 size_t count
= sizeof (keywords
) / sizeof (keywords
[0]);
1356 for (i
= 0; i
< count
; i
++)
1358 slot
= htab_find_slot (container
->keyword_hash
, keywords
[i
], INSERT
);
1359 *slot
= CONST_CAST (void *, (const void *) keywords
[i
]);
1363 /* Traversing the pot_dummy_types and seeing which types are present
1364 in the global types hash table and creating dummy definitions if
1365 not found. This function is invoked by hash_set::traverse. */
1368 find_dummy_types (const char *const &ptr
, godump_container
*adata
)
1370 struct godump_container
*data
= (struct godump_container
*) adata
;
1371 const char *type
= (const char *) ptr
;
1375 slot
= htab_find_slot (data
->type_hash
, type
, NO_INSERT
);
1376 islot
= htab_find_slot (data
->invalid_hash
, type
, NO_INSERT
);
1377 if (slot
== NULL
|| islot
!= NULL
)
1378 fprintf (go_dump_file
, "type _%s struct {}\n", type
);
1382 /* Output symbols. */
1385 go_finish (const char *filename
)
1387 struct godump_container container
;
1391 real_debug_hooks
->finish (filename
);
1393 container
.type_hash
= htab_create (100, htab_hash_string
,
1394 string_hash_eq
, NULL
);
1395 container
.invalid_hash
= htab_create (10, htab_hash_string
,
1396 string_hash_eq
, NULL
);
1397 container
.keyword_hash
= htab_create (50, htab_hash_string
,
1398 string_hash_eq
, NULL
);
1399 obstack_init (&container
.type_obstack
);
1401 keyword_hash_init (&container
);
1403 FOR_EACH_VEC_SAFE_ELT (queue
, ix
, decl
)
1405 switch (TREE_CODE (decl
))
1408 go_output_fndecl (&container
, decl
);
1412 go_output_typedef (&container
, decl
);
1416 go_output_var (&container
, decl
);
1424 htab_traverse_noresize (macro_hash
, go_print_macro
, NULL
);
1426 /* To emit dummy definitions. */
1427 container
.pot_dummy_types
.traverse
<godump_container
*, find_dummy_types
>
1430 htab_delete (container
.type_hash
);
1431 htab_delete (container
.invalid_hash
);
1432 htab_delete (container
.keyword_hash
);
1433 obstack_free (&container
.type_obstack
, NULL
);
1437 if (fclose (go_dump_file
) != 0)
1438 error ("could not close Go dump file: %m");
1439 go_dump_file
= NULL
;
1442 /* Set up our hooks. */
1444 const struct gcc_debug_hooks
*
1445 dump_go_spec_init (const char *filename
, const struct gcc_debug_hooks
*hooks
)
1447 go_dump_file
= fopen (filename
, "w");
1448 if (go_dump_file
== NULL
)
1450 error ("could not open Go dump file %qs: %m", filename
);
1454 go_debug_hooks
= *hooks
;
1455 real_debug_hooks
= hooks
;
1457 go_debug_hooks
.finish
= go_finish
;
1458 go_debug_hooks
.define
= go_define
;
1459 go_debug_hooks
.undef
= go_undef
;
1460 go_debug_hooks
.function_decl
= go_function_decl
;
1461 go_debug_hooks
.early_global_decl
= go_early_global_decl
;
1462 go_debug_hooks
.late_global_decl
= go_late_global_decl
;
1463 go_debug_hooks
.type_decl
= go_type_decl
;
1465 macro_hash
= htab_create (100, macro_hash_hashval
, macro_hash_eq
,
1468 return &go_debug_hooks
;
1471 #include "gt-godump.h"