Optimize powerpc*-*-linux* e500 hardfp/soft-fp use.
[official-gcc.git] / gcc / godump.c
blob7a0566485f6fbc132d72478357a19525ba5406bd
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
10 version.
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
15 for more details.
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
25 library.
27 All global names are output with a leading underscore, so that they
28 are all hidden in Go. */
30 #include "config.h"
31 #include "system.h"
32 #include "coretypes.h"
33 #include "diagnostic-core.h"
34 #include "tree.h"
35 #include "ggc.h"
36 #include "hash-set.h"
37 #include "obstack.h"
38 #include "debug.h"
39 #include "wide-int-print.h"
40 #include "stor-layout.h"
41 #include "defaults.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. */
73 char *name;
74 /* The value of the macro. */
75 char *value;
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. */
89 static hashval_t
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. */
98 static int
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. */
108 static void
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);
114 XDELETE (mhv);
117 /* For the string hash tables. */
119 static int
120 string_hash_eq (const void *y1, const void *y2)
122 return strcmp ((const char *) y1, (const char *) y2) == 0;
125 /* A macro definition. */
127 static void
128 go_define (unsigned int lineno, const char *buffer)
130 const char *p;
131 const char *name_end;
132 size_t out_len;
133 char *out_buffer;
134 char *q;
135 bool saw_operand;
136 bool need_operand;
137 struct macro_hash_value *mhval;
138 char *copy;
139 hashval_t hashval;
140 void **slot;
142 real_debug_hooks->define (lineno, buffer);
144 /* Skip macro functions. */
145 for (p = buffer; *p != '\0' && *p != ' '; ++p)
146 if (*p == '(')
147 return;
149 if (*p == '\0')
150 return;
152 name_end = p;
154 ++p;
155 if (*p == '\0')
156 return;
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);
163 mhval->name = copy;
164 mhval->value = NULL;
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);
173 q = out_buffer;
174 saw_operand = false;
175 need_operand = false;
176 while (*p != '\0')
178 switch (*p)
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':
184 case 'Y': case 'Z':
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':
189 case 'y': case 'z':
190 case '_':
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. */
196 const char *start;
197 char *n;
198 struct macro_hash_value idval;
200 if (saw_operand)
201 goto unknown;
203 start = p;
204 while (ISALNUM (*p) || *p == '_')
205 ++p;
206 n = XALLOCAVEC (char, p - start + 1);
207 memcpy (n, start, p - start);
208 n[p - start] = '\0';
209 idval.name = n;
210 idval.value = NULL;
211 if (htab_find (macro_hash, &idval) == NULL)
213 /* This is a reference to a name which was not defined
214 as a macro. */
215 goto unknown;
218 *q++ = '_';
219 memcpy (q, start, p - start);
220 q += p - start;
222 saw_operand = true;
223 need_operand = false;
225 break;
227 case '.':
228 if (!ISDIGIT (p[1]))
229 goto unknown;
230 /* Fall through. */
231 case '0': case '1': case '2': case '3': case '4':
232 case '5': case '6': case '7': case '8': case '9':
234 const char *start;
235 bool is_hex;
237 start = p;
238 is_hex = false;
239 if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
241 p += 2;
242 is_hex = true;
244 while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
245 || (is_hex
246 && ((*p >= 'a' && *p <= 'f')
247 || (*p >= 'A' && *p <= 'F'))))
248 ++p;
249 memcpy (q, start, p - start);
250 q += 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
256 modifiers. */
257 ++p;
260 /* We'll pick up the exponent, if any, as an
261 expression. */
263 saw_operand = true;
264 need_operand = false;
266 break;
268 case ' ': case '\t':
269 *q++ = *p++;
270 break;
272 case '(':
273 /* Always OK, not part of an operand, presumed to start an
274 operand. */
275 *q++ = *p++;
276 saw_operand = false;
277 need_operand = false;
278 break;
280 case ')':
281 /* OK if we don't need an operand, and presumed to indicate
282 an operand. */
283 if (need_operand)
284 goto unknown;
285 *q++ = *p++;
286 saw_operand = true;
287 break;
289 case '+': case '-':
290 /* Always OK, but not part of an operand. */
291 *q++ = *p++;
292 saw_operand = false;
293 break;
295 case '*': case '/': case '%': case '|': case '&': case '^':
296 /* Must be a binary operator. */
297 if (!saw_operand)
298 goto unknown;
299 *q++ = *p++;
300 saw_operand = false;
301 need_operand = true;
302 break;
304 case '=':
305 *q++ = *p++;
306 if (*p != '=')
307 goto unknown;
308 /* Must be a binary operator. */
309 if (!saw_operand)
310 goto unknown;
311 *q++ = *p++;
312 saw_operand = false;
313 need_operand = true;
314 break;
316 case '!':
317 *q++ = *p++;
318 if (*p == '=')
320 /* Must be a binary operator. */
321 if (!saw_operand)
322 goto unknown;
323 *q++ = *p++;
324 saw_operand = false;
325 need_operand = true;
327 else
329 /* Must be a unary operator. */
330 if (saw_operand)
331 goto unknown;
332 need_operand = true;
334 break;
336 case '<': case '>':
337 /* Must be a binary operand, may be << or >> or <= or >=. */
338 if (!saw_operand)
339 goto unknown;
340 *q++ = *p++;
341 if (*p == *(p - 1) || *p == '=')
342 *q++ = *p++;
343 saw_operand = false;
344 need_operand = true;
345 break;
347 case '~':
348 /* Must be a unary operand, must be translated for Go. */
349 if (saw_operand)
350 goto unknown;
351 *q++ = '^';
352 p++;
353 need_operand = true;
354 break;
356 case '"':
357 case '\'':
359 char quote;
360 int count;
362 if (saw_operand)
363 goto unknown;
364 quote = *p;
365 *q++ = *p++;
366 count = 0;
367 while (*p != quote)
369 int c;
371 if (*p == '\0')
372 goto unknown;
374 ++count;
376 if (*p != '\\')
378 *q++ = *p++;
379 continue;
382 *q++ = *p++;
383 switch (*p)
385 case '0': case '1': case '2': case '3':
386 case '4': case '5': case '6': case '7':
387 c = 0;
388 while (*p >= '0' && *p <= '7')
390 *q++ = *p++;
391 ++c;
393 /* Go octal characters are always 3
394 digits. */
395 if (c != 3)
396 goto unknown;
397 break;
399 case 'x':
400 *q++ = *p++;
401 c = 0;
402 while (ISXDIGIT (*p))
404 *q++ = *p++;
405 ++c;
407 /* Go hex characters are always 2 digits. */
408 if (c != 2)
409 goto unknown;
410 break;
412 case 'a': case 'b': case 'f': case 'n': case 'r':
413 case 't': case 'v': case '\\': case '\'': case '"':
414 *q++ = *p++;
415 break;
417 default:
418 goto unknown;
422 *q++ = *p++;
424 if (quote == '\'' && count != 1)
425 goto unknown;
427 saw_operand = true;
428 need_operand = false;
430 break;
433 default:
434 goto unknown;
438 if (need_operand)
439 goto unknown;
441 gcc_assert ((size_t) (q - out_buffer) < out_len);
442 *q = '\0';
444 mhval->value = out_buffer;
446 if (slot == NULL)
448 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, INSERT);
449 gcc_assert (slot != NULL && *slot == NULL);
451 else
453 if (*slot != NULL)
454 macro_hash_del (*slot);
457 *slot = mhval;
459 return;
461 unknown:
462 fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
463 if (slot != NULL)
464 htab_clear_slot (macro_hash, slot);
465 XDELETEVEC (out_buffer);
466 XDELETEVEC (copy);
469 /* A macro undef. */
471 static void
472 go_undef (unsigned int lineno, const char *buffer)
474 struct macro_hash_value mhval;
475 void **slot;
477 real_debug_hooks->undef (lineno, buffer);
479 mhval.name = CONST_CAST (char *, buffer);
480 mhval.value = NULL;
481 slot = htab_find_slot (macro_hash, &mhval, NO_INSERT);
482 if (slot != NULL)
483 htab_clear_slot (macro_hash, slot);
486 /* A function or variable decl. */
488 static void
489 go_decl (tree decl)
491 if (!TREE_PUBLIC (decl)
492 || DECL_IS_BUILTIN (decl)
493 || DECL_NAME (decl) == NULL_TREE)
494 return;
495 vec_safe_push (queue, decl);
498 /* A function decl. */
500 static void
501 go_function_decl (tree decl)
503 real_debug_hooks->function_decl (decl);
504 go_decl (decl);
507 /* A global variable decl. */
509 static void
510 go_global_decl (tree decl)
512 real_debug_hooks->global_decl (decl);
513 go_decl (decl);
516 /* A type declaration. */
518 static void
519 go_type_decl (tree decl, int local)
521 real_debug_hooks->type_decl (decl, local);
523 if (local || DECL_IS_BUILTIN (decl))
524 return;
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)
529 return;
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
542 types. */
543 hash_set<const char *> pot_dummy_types;
545 /* Go keywords. */
546 htab_t keyword_hash;
548 /* Global type definitions. */
549 htab_t type_hash;
551 /* Invalid types. */
552 htab_t invalid_hash;
554 /* Obstack used to write out a type definition. */
555 struct obstack type_obstack;
558 /* Append an IDENTIFIER_NODE to OB. */
560 static void
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. */
570 static const char *
571 go_get_uinttype_for_precision (unsigned int precision, bool is_unsigned)
573 switch (precision)
575 case 8:
576 return is_unsigned ? "uint8" : "int8";
577 case 16:
578 return is_unsigned ? "uint16" : "int16";
579 case 32:
580 return is_unsigned ? "uint32" : "int32";
581 case 64:
582 return is_unsigned ? "uint64" : "int64";
583 default:
584 return NULL;
588 /* Append an artificial variable name with the suffix _INDEX to OB. Returns
589 INDEX + 1. */
591 static unsigned int
592 go_append_artificial_name (struct obstack *ob, unsigned int index)
594 char buf[100];
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));
601 return index + 1;
604 /* Append the variable name from DECL to OB. If the name is in the
605 KEYWORD_HASH, prepend an '_'. */
607 static void
608 go_append_decl_name (struct obstack *ob, tree decl, htab_t keyword_hash)
610 const char *var_name;
611 void **slot;
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);
616 if (slot != NULL)
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. */
627 static unsigned int
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)
637 char buf[100];
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;
645 return index;
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. */
652 static unsigned int
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));
660 else
662 obstack_grow (ob, "[0]", 3);
663 obstack_grow (ob, type_string, strlen (type_string));
665 obstack_grow (ob, "; ", 2);
667 return index;
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. */
679 static bool
680 go_format_type (struct godump_container *container, tree type,
681 bool use_type_name, bool is_func_ok, unsigned int *p_art_i)
683 bool ret;
684 struct obstack *ob;
685 unsigned int art_i_dummy;
687 if (p_art_i == NULL)
689 art_i_dummy = 0;
690 p_art_i = &art_i_dummy;
692 ret = true;
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))
702 tree name;
703 void **slot;
705 name = TYPE_IDENTIFIER (type);
707 slot = htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (name),
708 NO_INSERT);
709 if (slot != NULL)
710 ret = false;
712 obstack_1grow (ob, '_');
713 go_append_string (ob, name);
714 return ret;
717 container->decls_seen.add (type);
719 switch (TREE_CODE (type))
721 case ENUMERAL_TYPE:
722 obstack_grow (ob, "int", 3);
723 break;
725 case TYPE_DECL:
727 void **slot;
729 slot = htab_find_slot (container->invalid_hash,
730 IDENTIFIER_POINTER (DECL_NAME (type)),
731 NO_INSERT);
732 if (slot != NULL)
733 ret = false;
735 obstack_1grow (ob, '_');
736 go_append_string (ob, DECL_NAME (type));
738 break;
740 case INTEGER_TYPE:
742 const char *s;
743 char buf[100];
745 s = go_get_uinttype_for_precision (TYPE_PRECISION (type),
746 TYPE_UNSIGNED (type));
747 if (s == NULL)
749 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
750 TYPE_PRECISION (type),
751 TYPE_UNSIGNED (type) ? "u" : "");
752 s = buf;
753 ret = false;
755 obstack_grow (ob, s, strlen (s));
757 break;
759 case REAL_TYPE:
761 const char *s;
762 char buf[100];
764 switch (TYPE_PRECISION (type))
766 case 32:
767 s = "float32";
768 break;
769 case 64:
770 s = "float64";
771 break;
772 default:
773 snprintf (buf, sizeof buf, "INVALID-float-%u",
774 TYPE_PRECISION (type));
775 s = buf;
776 ret = false;
777 break;
779 obstack_grow (ob, s, strlen (s));
781 break;
783 case BOOLEAN_TYPE:
784 obstack_grow (ob, "bool", 4);
785 break;
787 case POINTER_TYPE:
788 if (use_type_name
789 && TYPE_NAME (TREE_TYPE (type)) != NULL_TREE
790 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))
791 || (POINTER_TYPE_P (TREE_TYPE (type))
792 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type)))
793 == FUNCTION_TYPE))))
795 tree name;
796 void **slot;
798 name = TYPE_IDENTIFIER (TREE_TYPE (type));
800 slot = htab_find_slot (container->invalid_hash,
801 IDENTIFIER_POINTER (name), NO_INSERT);
802 if (slot != NULL)
803 ret = false;
805 obstack_grow (ob, "*_", 2);
806 go_append_string (ob, name);
808 /* The pointer here can be used without the struct or union
809 definition. So this struct or union is a potential dummy
810 type. */
811 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
812 container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
814 return ret;
816 if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
817 obstack_grow (ob, "func", 4);
818 else
819 obstack_1grow (ob, '*');
820 if (VOID_TYPE_P (TREE_TYPE (type)))
821 obstack_grow (ob, "byte", 4);
822 else
824 if (!go_format_type (container, TREE_TYPE (type), use_type_name,
825 true, NULL))
826 ret = false;
828 break;
830 case ARRAY_TYPE:
831 obstack_1grow (ob, '[');
832 if (TYPE_DOMAIN (type) != NULL_TREE
833 && TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
834 && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
835 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
836 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0
837 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
838 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
839 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
841 char buf[100];
843 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
844 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type))));
845 obstack_grow (ob, buf, strlen (buf));
847 else
848 obstack_1grow (ob, '0');
849 obstack_1grow (ob, ']');
850 if (!go_format_type (container, TREE_TYPE (type), use_type_name, false,
851 NULL))
852 ret = false;
853 break;
855 case RECORD_TYPE:
857 unsigned int prev_field_end;
858 unsigned int most_strict_known_alignment;
859 tree field;
861 /* FIXME: Why is this necessary? Without it we can get a core
862 dump on the s390x headers, or from a file containing simply
863 "typedef struct S T;". */
864 layout_type (type);
866 prev_field_end = 0;
867 most_strict_known_alignment = 1;
868 obstack_grow (ob, "struct { ", 9);
869 for (field = TYPE_FIELDS (type);
870 field != NULL_TREE;
871 field = TREE_CHAIN (field))
873 bool field_ok;
875 if (TREE_CODE (field) != FIELD_DECL)
876 continue;
877 field_ok = true;
878 if (DECL_BIT_FIELD (field))
879 continue;
880 else
883 unsigned int decl_align_unit;
884 unsigned int decl_offset;
886 decl_align_unit = DECL_ALIGN_UNIT (field);
887 decl_offset =
888 TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
889 + precision_to_units
890 (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)));
891 if (decl_align_unit > most_strict_known_alignment)
892 most_strict_known_alignment = decl_align_unit;
893 *p_art_i = go_append_padding
894 (ob, prev_field_end, decl_offset, decl_align_unit, *p_art_i,
895 &prev_field_end);
896 if (DECL_SIZE_UNIT (field))
897 prev_field_end += TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
899 if (DECL_NAME (field) == NULL)
900 *p_art_i = go_append_artificial_name (ob, *p_art_i);
901 else
902 go_append_decl_name (ob, field, container->keyword_hash);
903 obstack_1grow (ob, ' ');
905 /* Do not expand type if a record or union type or a
906 function pointer. */
907 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
908 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
909 || (POINTER_TYPE_P (TREE_TYPE (field))
910 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
911 == FUNCTION_TYPE))))
913 tree name;
914 void **slot;
916 name = TYPE_IDENTIFIER (TREE_TYPE (field));
918 slot = htab_find_slot (container->invalid_hash,
919 IDENTIFIER_POINTER (name),
920 NO_INSERT);
921 if (slot != NULL)
922 field_ok = false;
924 obstack_1grow (ob, '_');
925 go_append_string (ob, name);
927 else
929 if (!go_format_type (container, TREE_TYPE (field), true,
930 false, p_art_i))
931 field_ok = false;
933 obstack_grow (ob, "; ", 2);
935 if (!field_ok)
936 ret = false;
938 /* Alignment and padding as necessary. */
940 unsigned int type_align_unit;
942 type_align_unit = TYPE_ALIGN_UNIT (type);
943 /* Padding. */
944 *p_art_i = go_append_padding
945 (ob, prev_field_end, TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type)),
946 type_align_unit, *p_art_i, &prev_field_end);
947 if (most_strict_known_alignment < type_align_unit)
949 const char *s;
950 char buf[100];
952 /* Enforce proper record alignment. */
953 s = go_get_uinttype_for_precision
954 (TYPE_ALIGN (type), TYPE_UNSIGNED (type));
955 if (s == NULL)
957 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
958 TYPE_ALIGN (type), TYPE_UNSIGNED (type) ? "u" : "");
959 s = buf;
960 ret = false;
962 *p_art_i = go_force_record_alignment (ob, s, *p_art_i, buf);
965 obstack_1grow (ob, '}');
967 break;
969 case UNION_TYPE:
971 const char *s;
972 unsigned int sz_units;
974 layout_type (type);
975 sz_units = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
976 s = go_get_uinttype_for_precision (TYPE_ALIGN (type), true);
977 obstack_grow (ob, "struct { ", 9);
978 if (s == NULL)
980 ret = false;
981 s = "INVALID-union-alignment";
982 obstack_grow (ob, s, strlen (s));
984 else
986 char buf[100];
987 tree field;
989 field = TYPE_FIELDS (type);
990 /* Use the same index as the byte field's artificial name for
991 padding. */
992 if (field != NULL_TREE && DECL_NAME (field) != NULL)
993 go_append_decl_name (ob, field, container->keyword_hash);
994 else
995 *p_art_i = go_append_artificial_name (ob, *p_art_i);
996 snprintf (buf, sizeof buf, " [%u]byte; ", sz_units);
997 obstack_grow (ob, buf, strlen (buf));
998 if (TYPE_ALIGN_UNIT (type) > 1)
999 *p_art_i = go_force_record_alignment (ob, s, *p_art_i, NULL);
1001 obstack_1grow (ob, '}');
1003 break;
1005 case FUNCTION_TYPE:
1007 tree arg_type;
1008 bool is_varargs;
1009 tree result;
1010 function_args_iterator iter;
1011 bool seen_arg;
1013 /* Go has no way to write a type which is a function but not a
1014 pointer to a function. */
1015 if (!is_func_ok)
1017 obstack_grow (ob, "func*", 5);
1018 ret = false;
1021 obstack_1grow (ob, '(');
1022 is_varargs = stdarg_p (type);
1023 seen_arg = false;
1024 FOREACH_FUNCTION_ARGS (type, arg_type, iter)
1026 if (VOID_TYPE_P (arg_type))
1027 break;
1028 if (seen_arg)
1029 obstack_grow (ob, ", ", 2);
1030 if (!go_format_type (container, arg_type, true, false, NULL))
1031 ret = false;
1032 seen_arg = true;
1034 if (is_varargs)
1036 if (prototype_p (type))
1037 obstack_grow (ob, ", ", 2);
1038 obstack_grow (ob, "...interface{}", 14);
1040 obstack_1grow (ob, ')');
1042 result = TREE_TYPE (type);
1043 if (!VOID_TYPE_P (result))
1045 obstack_1grow (ob, ' ');
1046 if (!go_format_type (container, result, use_type_name, false, NULL))
1047 ret = false;
1050 break;
1052 default:
1053 obstack_grow (ob, "INVALID-type", 12);
1054 ret = false;
1055 break;
1058 return ret;
1061 /* Output the type which was built on the type obstack, and then free
1062 it. */
1064 static void
1065 go_output_type (struct godump_container *container)
1067 struct obstack *ob;
1069 ob = &container->type_obstack;
1070 obstack_1grow (ob, '\0');
1071 fputs ((char *) obstack_base (ob), go_dump_file);
1072 obstack_free (ob, obstack_base (ob));
1075 /* Output a function declaration. */
1077 static void
1078 go_output_fndecl (struct godump_container *container, tree decl)
1080 if (!go_format_type (container, TREE_TYPE (decl), false, true, NULL))
1081 fprintf (go_dump_file, "// ");
1082 fprintf (go_dump_file, "func _%s ",
1083 IDENTIFIER_POINTER (DECL_NAME (decl)));
1084 go_output_type (container);
1085 fprintf (go_dump_file, " __asm__(\"%s\")\n",
1086 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
1089 /* Output a typedef or something like a struct definition. */
1091 static void
1092 go_output_typedef (struct godump_container *container, tree decl)
1094 /* If we have an enum type, output the enum constants
1095 separately. */
1096 if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
1097 && TYPE_SIZE (TREE_TYPE (decl)) != 0
1098 && !container->decls_seen.contains (TREE_TYPE (decl))
1099 && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
1100 || !container->decls_seen.contains
1101 (TYPE_CANONICAL (TREE_TYPE (decl)))))
1103 tree element;
1105 for (element = TYPE_VALUES (TREE_TYPE (decl));
1106 element != NULL_TREE;
1107 element = TREE_CHAIN (element))
1109 const char *name;
1110 struct macro_hash_value *mhval;
1111 void **slot;
1112 char buf[WIDE_INT_PRINT_BUFFER_SIZE];
1114 name = IDENTIFIER_POINTER (TREE_PURPOSE (element));
1116 /* Sometimes a name will be defined as both an enum constant
1117 and a macro. Avoid duplicate definition errors by
1118 treating enum constants as macros. */
1119 mhval = XNEW (struct macro_hash_value);
1120 mhval->name = xstrdup (name);
1121 mhval->value = NULL;
1122 slot = htab_find_slot (macro_hash, mhval, INSERT);
1123 if (*slot != NULL)
1124 macro_hash_del (*slot);
1126 if (tree_fits_shwi_p (TREE_VALUE (element)))
1127 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC,
1128 tree_to_shwi (TREE_VALUE (element)));
1129 else if (tree_fits_uhwi_p (TREE_VALUE (element)))
1130 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_UNSIGNED,
1131 tree_to_uhwi (TREE_VALUE (element)));
1132 else
1133 print_hex (element, buf);
1135 mhval->value = xstrdup (buf);
1136 *slot = mhval;
1138 container->decls_seen.add (TREE_TYPE (decl));
1139 if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
1140 container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl)));
1143 if (DECL_NAME (decl) != NULL_TREE)
1145 void **slot;
1146 const char *type;
1148 type = IDENTIFIER_POINTER (DECL_NAME (decl));
1149 /* If type defined already, skip. */
1150 slot = htab_find_slot (container->type_hash, type, INSERT);
1151 if (*slot != NULL)
1152 return;
1153 *slot = CONST_CAST (void *, (const void *) type);
1155 if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL))
1157 fprintf (go_dump_file, "// ");
1158 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1159 *slot = CONST_CAST (void *, (const void *) type);
1161 fprintf (go_dump_file, "type _%s ",
1162 IDENTIFIER_POINTER (DECL_NAME (decl)));
1163 go_output_type (container);
1165 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1167 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
1169 if (size > 0)
1170 fprintf (go_dump_file,
1171 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1172 IDENTIFIER_POINTER (DECL_NAME (decl)),
1173 size);
1176 container->decls_seen.add (decl);
1178 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1180 void **slot;
1181 const char *type;
1182 HOST_WIDE_INT size;
1184 type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
1185 /* If type defined already, skip. */
1186 slot = htab_find_slot (container->type_hash, type, INSERT);
1187 if (*slot != NULL)
1188 return;
1189 *slot = CONST_CAST (void *, (const void *) type);
1191 if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL))
1193 fprintf (go_dump_file, "// ");
1194 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1195 *slot = CONST_CAST (void *, (const void *) type);
1197 fprintf (go_dump_file, "type _%s ",
1198 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
1199 go_output_type (container);
1201 size = int_size_in_bytes (TREE_TYPE (decl));
1202 if (size > 0)
1203 fprintf (go_dump_file,
1204 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1205 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))),
1206 size);
1208 else
1209 return;
1211 fprintf (go_dump_file, "\n");
1214 /* Output a variable. */
1216 static void
1217 go_output_var (struct godump_container *container, tree decl)
1219 bool is_valid;
1220 tree type_name;
1221 tree id;
1223 if (container->decls_seen.contains (decl)
1224 || container->decls_seen.contains (DECL_NAME (decl)))
1225 return;
1226 container->decls_seen.add (decl);
1227 container->decls_seen.add (DECL_NAME (decl));
1229 type_name = TYPE_NAME (TREE_TYPE (decl));
1230 id = NULL_TREE;
1231 if (type_name != NULL_TREE && TREE_CODE (type_name) == IDENTIFIER_NODE)
1232 id = type_name;
1233 else if (type_name != NULL_TREE && TREE_CODE (type_name) == TYPE_DECL
1234 && DECL_SOURCE_LOCATION (type_name) != BUILTINS_LOCATION
1235 && DECL_NAME (type_name))
1236 id = DECL_NAME (type_name);
1237 if (id != NULL_TREE
1238 && (!htab_find_slot (container->type_hash, IDENTIFIER_POINTER (id),
1239 NO_INSERT)
1240 || htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (id),
1241 NO_INSERT)))
1242 id = NULL_TREE;
1243 if (id != NULL_TREE)
1245 struct obstack *ob;
1247 ob = &container->type_obstack;
1248 obstack_1grow (ob, '_');
1249 go_append_string (ob, id);
1250 is_valid = htab_find_slot (container->type_hash, IDENTIFIER_POINTER (id),
1251 NO_INSERT) != NULL;
1253 else
1254 is_valid = go_format_type (container, TREE_TYPE (decl), true, false, NULL);
1255 if (is_valid
1256 && htab_find_slot (container->type_hash,
1257 IDENTIFIER_POINTER (DECL_NAME (decl)),
1258 NO_INSERT) != NULL)
1260 /* There is already a type with this name, probably from a
1261 struct tag. Prefer the type to the variable. */
1262 is_valid = false;
1264 if (!is_valid)
1265 fprintf (go_dump_file, "// ");
1267 fprintf (go_dump_file, "var _%s ",
1268 IDENTIFIER_POINTER (DECL_NAME (decl)));
1269 go_output_type (container);
1270 fprintf (go_dump_file, "\n");
1272 /* Sometimes an extern variable is declared with an unknown struct
1273 type. */
1274 if (type_name != NULL_TREE && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1276 if (TREE_CODE (type_name) == IDENTIFIER_NODE)
1277 container->pot_dummy_types.add (IDENTIFIER_POINTER (type_name));
1278 else if (TREE_CODE (type_name) == TYPE_DECL)
1279 container->pot_dummy_types.add
1280 (IDENTIFIER_POINTER (DECL_NAME (type_name)));
1284 /* Output the final value of a preprocessor macro or enum constant.
1285 This is called via htab_traverse_noresize. */
1287 static int
1288 go_print_macro (void **slot, void *arg ATTRIBUTE_UNUSED)
1290 struct macro_hash_value *mhval = (struct macro_hash_value *) *slot;
1291 fprintf (go_dump_file, "const _%s = %s\n", mhval->name, mhval->value);
1292 return 1;
1295 /* Build a hash table with the Go keywords. */
1297 static const char * const keywords[] = {
1298 "__asm__", "break", "case", "chan", "const", "continue", "default",
1299 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1300 "import", "interface", "map", "package", "range", "return", "select",
1301 "struct", "switch", "type", "var"
1304 static void
1305 keyword_hash_init (struct godump_container *container)
1307 size_t i;
1308 size_t count = sizeof (keywords) / sizeof (keywords[0]);
1309 void **slot;
1311 for (i = 0; i < count; i++)
1313 slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
1314 *slot = CONST_CAST (void *, (const void *) keywords[i]);
1318 /* Traversing the pot_dummy_types and seeing which types are present
1319 in the global types hash table and creating dummy definitions if
1320 not found. This function is invoked by hash_set::traverse. */
1322 bool
1323 find_dummy_types (const char *const &ptr, godump_container *adata)
1325 struct godump_container *data = (struct godump_container *) adata;
1326 const char *type = (const char *) ptr;
1327 void **slot;
1328 void **islot;
1330 slot = htab_find_slot (data->type_hash, type, NO_INSERT);
1331 islot = htab_find_slot (data->invalid_hash, type, NO_INSERT);
1332 if (slot == NULL || islot != NULL)
1333 fprintf (go_dump_file, "type _%s struct {}\n", type);
1334 return true;
1337 /* Output symbols. */
1339 static void
1340 go_finish (const char *filename)
1342 struct godump_container container;
1343 unsigned int ix;
1344 tree decl;
1346 real_debug_hooks->finish (filename);
1348 container.type_hash = htab_create (100, htab_hash_string,
1349 string_hash_eq, NULL);
1350 container.invalid_hash = htab_create (10, htab_hash_string,
1351 string_hash_eq, NULL);
1352 container.keyword_hash = htab_create (50, htab_hash_string,
1353 string_hash_eq, NULL);
1354 obstack_init (&container.type_obstack);
1356 keyword_hash_init (&container);
1358 FOR_EACH_VEC_SAFE_ELT (queue, ix, decl)
1360 switch (TREE_CODE (decl))
1362 case FUNCTION_DECL:
1363 go_output_fndecl (&container, decl);
1364 break;
1366 case TYPE_DECL:
1367 go_output_typedef (&container, decl);
1368 break;
1370 case VAR_DECL:
1371 go_output_var (&container, decl);
1372 break;
1374 default:
1375 gcc_unreachable ();
1379 htab_traverse_noresize (macro_hash, go_print_macro, NULL);
1381 /* To emit dummy definitions. */
1382 container.pot_dummy_types.traverse<godump_container *, find_dummy_types>
1383 (&container);
1385 htab_delete (container.type_hash);
1386 htab_delete (container.invalid_hash);
1387 htab_delete (container.keyword_hash);
1388 obstack_free (&container.type_obstack, NULL);
1390 vec_free (queue);
1392 if (fclose (go_dump_file) != 0)
1393 error ("could not close Go dump file: %m");
1394 go_dump_file = NULL;
1397 /* Set up our hooks. */
1399 const struct gcc_debug_hooks *
1400 dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
1402 go_dump_file = fopen (filename, "w");
1403 if (go_dump_file == NULL)
1405 error ("could not open Go dump file %qs: %m", filename);
1406 return hooks;
1409 go_debug_hooks = *hooks;
1410 real_debug_hooks = hooks;
1412 go_debug_hooks.finish = go_finish;
1413 go_debug_hooks.define = go_define;
1414 go_debug_hooks.undef = go_undef;
1415 go_debug_hooks.function_decl = go_function_decl;
1416 go_debug_hooks.global_decl = go_global_decl;
1417 go_debug_hooks.type_decl = go_type_decl;
1419 macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq,
1420 macro_hash_del);
1422 return &go_debug_hooks;
1425 #include "gt-godump.h"