]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/godump.c
Reorganise machmode.h headers
[thirdparty/gcc.git] / gcc / godump.c
CommitLineData
929d2a90 1/* Output Go language descriptions of types.
aad93da1 2 Copyright (C) 2008-2017 Free Software Foundation, Inc.
929d2a90 3 Written by Ian Lance Taylor <iant@google.com>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
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.
26
27 All global names are output with a leading underscore, so that they
28 are all hidden in Go. */
29
30#include "config.h"
31#include "system.h"
32#include "coretypes.h"
7c29e30e 33#include "tree.h"
7c29e30e 34#include "diagnostic-core.h"
7c29e30e 35#include "debug.h"
4d099c1c 36#include "stor-layout.h"
929d2a90 37
38/* We dump this information from the debug hooks. This gives us a
39 stable and maintainable API to hook into. In order to work
40 correctly when -g is used, we build our own hooks structure which
41 wraps the hooks we need to change. */
42
43/* Our debug hooks. This is initialized by dump_go_spec_init. */
44
45static struct gcc_debug_hooks go_debug_hooks;
46
47/* The real debug hooks. */
48
49static const struct gcc_debug_hooks *real_debug_hooks;
50
51/* The file where we should write information. */
52
53static FILE *go_dump_file;
54
55/* A queue of decls to output. */
56
f1f41a6c 57static GTY(()) vec<tree, va_gc> *queue;
929d2a90 58
59/* A hash table of macros we have seen. */
60
61static htab_t macro_hash;
62
62aab493 63/* The type of a value in macro_hash. */
64
65struct macro_hash_value
66{
67 /* The name stored in the hash table. */
68 char *name;
69 /* The value of the macro. */
70 char *value;
71};
72
4d099c1c 73/* Returns the number of units necessary to represent an integer with the given
74 PRECISION (in bits). */
75
76static inline unsigned int
77precision_to_units (unsigned int precision)
78{
79 return (precision + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
80}
81
62aab493 82/* Calculate the hash value for an entry in the macro hash table. */
83
84static hashval_t
85macro_hash_hashval (const void *val)
86{
87 const struct macro_hash_value *mhval = (const struct macro_hash_value *) val;
88 return htab_hash_string (mhval->name);
89}
90
91/* Compare values in the macro hash table for equality. */
92
93static int
94macro_hash_eq (const void *v1, const void *v2)
95{
96 const struct macro_hash_value *mhv1 = (const struct macro_hash_value *) v1;
97 const struct macro_hash_value *mhv2 = (const struct macro_hash_value *) v2;
98 return strcmp (mhv1->name, mhv2->name) == 0;
99}
100
101/* Free values deleted from the macro hash table. */
102
103static void
104macro_hash_del (void *v)
105{
106 struct macro_hash_value *mhv = (struct macro_hash_value *) v;
107 XDELETEVEC (mhv->name);
108 XDELETEVEC (mhv->value);
109 XDELETE (mhv);
110}
111
112/* For the string hash tables. */
929d2a90 113
114static int
115string_hash_eq (const void *y1, const void *y2)
116{
117 return strcmp ((const char *) y1, (const char *) y2) == 0;
118}
119
120/* A macro definition. */
121
122static void
123go_define (unsigned int lineno, const char *buffer)
124{
125 const char *p;
126 const char *name_end;
62aab493 127 size_t out_len;
929d2a90 128 char *out_buffer;
129 char *q;
509475fd 130 bool saw_operand;
131 bool need_operand;
62aab493 132 struct macro_hash_value *mhval;
929d2a90 133 char *copy;
134 hashval_t hashval;
135 void **slot;
136
137 real_debug_hooks->define (lineno, buffer);
138
139 /* Skip macro functions. */
140 for (p = buffer; *p != '\0' && *p != ' '; ++p)
141 if (*p == '(')
142 return;
143
144 if (*p == '\0')
145 return;
146
147 name_end = p;
148
149 ++p;
150 if (*p == '\0')
151 return;
152
153 copy = XNEWVEC (char, name_end - buffer + 1);
154 memcpy (copy, buffer, name_end - buffer);
155 copy[name_end - buffer] = '\0';
156
62aab493 157 mhval = XNEW (struct macro_hash_value);
158 mhval->name = copy;
159 mhval->value = NULL;
160
929d2a90 161 hashval = htab_hash_string (copy);
62aab493 162 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, NO_INSERT);
929d2a90 163
164 /* For simplicity, we force all names to be hidden by adding an
165 initial underscore, and let the user undo this as needed. */
62aab493 166 out_len = strlen (p) * 2 + 1;
167 out_buffer = XNEWVEC (char, out_len);
929d2a90 168 q = out_buffer;
509475fd 169 saw_operand = false;
170 need_operand = false;
929d2a90 171 while (*p != '\0')
172 {
509475fd 173 switch (*p)
929d2a90 174 {
509475fd 175 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
176 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
177 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
178 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
179 case 'Y': case 'Z':
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 '_':
186 {
187 /* The start of an identifier. Technically we should also
188 worry about UTF-8 identifiers, but they are not a
189 problem for practical uses of -fdump-go-spec so we
190 don't worry about them. */
191 const char *start;
192 char *n;
62aab493 193 struct macro_hash_value idval;
509475fd 194
826a8d9b 195 if (saw_operand)
196 goto unknown;
197
509475fd 198 start = p;
199 while (ISALNUM (*p) || *p == '_')
200 ++p;
201 n = XALLOCAVEC (char, p - start + 1);
202 memcpy (n, start, p - start);
203 n[p - start] = '\0';
62aab493 204 idval.name = n;
205 idval.value = NULL;
206 if (htab_find (macro_hash, &idval) == NULL)
509475fd 207 {
208 /* This is a reference to a name which was not defined
209 as a macro. */
210 goto unknown;
211 }
212
213 *q++ = '_';
214 memcpy (q, start, p - start);
215 q += p - start;
216
217 saw_operand = true;
218 need_operand = false;
219 }
220 break;
221
222 case '.':
223 if (!ISDIGIT (p[1]))
224 goto unknown;
225 /* Fall through. */
226 case '0': case '1': case '2': case '3': case '4':
227 case '5': case '6': case '7': case '8': case '9':
228 {
229 const char *start;
230 bool is_hex;
231
232 start = p;
233 is_hex = false;
234 if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
235 {
236 p += 2;
237 is_hex = true;
238 }
239 while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
240 || (is_hex
241 && ((*p >= 'a' && *p <= 'f')
242 || (*p >= 'A' && *p <= 'F'))))
243 ++p;
244 memcpy (q, start, p - start);
245 q += p - start;
246 while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
247 || *p == 'f' || *p == 'F'
248 || *p == 'd' || *p == 'D')
249 {
250 /* Go doesn't use any of these trailing type
251 modifiers. */
252 ++p;
253 }
254
255 /* We'll pick up the exponent, if any, as an
256 expression. */
257
258 saw_operand = true;
259 need_operand = false;
260 }
261 break;
262
263 case ' ': case '\t':
264 *q++ = *p++;
265 break;
266
267 case '(':
268 /* Always OK, not part of an operand, presumed to start an
269 operand. */
270 *q++ = *p++;
271 saw_operand = false;
272 need_operand = false;
273 break;
274
275 case ')':
276 /* OK if we don't need an operand, and presumed to indicate
277 an operand. */
278 if (need_operand)
279 goto unknown;
280 *q++ = *p++;
281 saw_operand = true;
282 break;
283
284 case '+': case '-':
285 /* Always OK, but not part of an operand. */
286 *q++ = *p++;
287 saw_operand = false;
288 break;
289
290 case '*': case '/': case '%': case '|': case '&': case '^':
291 /* Must be a binary operator. */
292 if (!saw_operand)
293 goto unknown;
294 *q++ = *p++;
295 saw_operand = false;
296 need_operand = true;
297 break;
298
299 case '=':
300 *q++ = *p++;
301 if (*p != '=')
302 goto unknown;
303 /* Must be a binary operator. */
304 if (!saw_operand)
305 goto unknown;
306 *q++ = *p++;
307 saw_operand = false;
308 need_operand = true;
309 break;
310
311 case '!':
312 *q++ = *p++;
313 if (*p == '=')
929d2a90 314 {
509475fd 315 /* Must be a binary operator. */
316 if (!saw_operand)
317 goto unknown;
318 *q++ = *p++;
319 saw_operand = false;
320 need_operand = true;
929d2a90 321 }
509475fd 322 else
929d2a90 323 {
509475fd 324 /* Must be a unary operator. */
325 if (saw_operand)
326 goto unknown;
327 need_operand = true;
929d2a90 328 }
509475fd 329 break;
330
331 case '<': case '>':
332 /* Must be a binary operand, may be << or >> or <= or >=. */
333 if (!saw_operand)
334 goto unknown;
335 *q++ = *p++;
336 if (*p == *(p - 1) || *p == '=')
337 *q++ = *p++;
338 saw_operand = false;
339 need_operand = true;
340 break;
341
342 case '~':
343 /* Must be a unary operand, must be translated for Go. */
344 if (saw_operand)
345 goto unknown;
346 *q++ = '^';
347 p++;
348 need_operand = true;
349 break;
350
351 case '"':
352 case '\'':
353 {
654a2463 354 char quote;
e8a63dfe 355 int count;
654a2463 356
357 if (saw_operand)
358 goto unknown;
359 quote = *p;
509475fd 360 *q++ = *p++;
e8a63dfe 361 count = 0;
509475fd 362 while (*p != quote)
363 {
364 int c;
365
366 if (*p == '\0')
367 goto unknown;
368
e8a63dfe 369 ++count;
370
509475fd 371 if (*p != '\\')
372 {
373 *q++ = *p++;
374 continue;
375 }
376
377 *q++ = *p++;
378 switch (*p)
379 {
380 case '0': case '1': case '2': case '3':
381 case '4': case '5': case '6': case '7':
382 c = 0;
383 while (*p >= '0' && *p <= '7')
384 {
385 *q++ = *p++;
386 ++c;
387 }
388 /* Go octal characters are always 3
389 digits. */
390 if (c != 3)
391 goto unknown;
392 break;
393
394 case 'x':
395 *q++ = *p++;
396 c = 0;
397 while (ISXDIGIT (*p))
398 {
399 *q++ = *p++;
400 ++c;
401 }
402 /* Go hex characters are always 2 digits. */
403 if (c != 2)
404 goto unknown;
405 break;
406
407 case 'a': case 'b': case 'f': case 'n': case 'r':
408 case 't': case 'v': case '\\': case '\'': case '"':
409 *q++ = *p++;
410 break;
411
412 default:
413 goto unknown;
414 }
415 }
e8a63dfe 416
509475fd 417 *q++ = *p++;
e8a63dfe 418
419 if (quote == '\'' && count != 1)
420 goto unknown;
421
422 saw_operand = true;
423 need_operand = false;
424
509475fd 425 break;
426 }
427
428 default:
429 goto unknown;
929d2a90 430 }
431 }
509475fd 432
433 if (need_operand)
434 goto unknown;
435
62aab493 436 gcc_assert ((size_t) (q - out_buffer) < out_len);
929d2a90 437 *q = '\0';
438
62aab493 439 mhval->value = out_buffer;
929d2a90 440
62aab493 441 if (slot == NULL)
442 {
443 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, INSERT);
444 gcc_assert (slot != NULL && *slot == NULL);
445 }
446 else
447 {
448 if (*slot != NULL)
449 macro_hash_del (*slot);
450 }
451
452 *slot = mhval;
929d2a90 453
509475fd 454 return;
455
456 unknown:
457 fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
62aab493 458 if (slot != NULL)
459 htab_clear_slot (macro_hash, slot);
509475fd 460 XDELETEVEC (out_buffer);
461 XDELETEVEC (copy);
929d2a90 462}
463
464/* A macro undef. */
465
466static void
467go_undef (unsigned int lineno, const char *buffer)
468{
62aab493 469 struct macro_hash_value mhval;
929d2a90 470 void **slot;
471
472 real_debug_hooks->undef (lineno, buffer);
473
62aab493 474 mhval.name = CONST_CAST (char *, buffer);
475 mhval.value = NULL;
476 slot = htab_find_slot (macro_hash, &mhval, NO_INSERT);
477 if (slot != NULL)
478 htab_clear_slot (macro_hash, slot);
929d2a90 479}
480
481/* A function or variable decl. */
482
483static void
484go_decl (tree decl)
485{
486 if (!TREE_PUBLIC (decl)
487 || DECL_IS_BUILTIN (decl)
488 || DECL_NAME (decl) == NULL_TREE)
489 return;
f1f41a6c 490 vec_safe_push (queue, decl);
929d2a90 491}
492
493/* A function decl. */
494
495static void
496go_function_decl (tree decl)
497{
498 real_debug_hooks->function_decl (decl);
499 go_decl (decl);
500}
501
3a1c9df2 502static void
503go_early_global_decl (tree decl)
504{
505 go_decl (decl);
288405ec 506 if (TREE_CODE (decl) != FUNCTION_DECL || DECL_STRUCT_FUNCTION (decl) != NULL)
507 real_debug_hooks->early_global_decl (decl);
3a1c9df2 508}
509
929d2a90 510/* A global variable decl. */
511
512static void
3a1c9df2 513go_late_global_decl (tree decl)
929d2a90 514{
3a1c9df2 515 real_debug_hooks->late_global_decl (decl);
929d2a90 516}
517
518/* A type declaration. */
519
520static void
521go_type_decl (tree decl, int local)
522{
523 real_debug_hooks->type_decl (decl, local);
524
525 if (local || DECL_IS_BUILTIN (decl))
526 return;
527 if (DECL_NAME (decl) == NULL_TREE
528 && (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE
529 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) != IDENTIFIER_NODE)
530 && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
531 return;
f1f41a6c 532 vec_safe_push (queue, decl);
929d2a90 533}
534
535/* A container for the data we pass around when generating information
536 at the end of the compilation. */
537
538struct godump_container
539{
540 /* DECLs that we have already seen. */
431205b7 541 hash_set<tree> decls_seen;
929d2a90 542
543 /* Types which may potentially have to be defined as dummy
544 types. */
431205b7 545 hash_set<const char *> pot_dummy_types;
929d2a90 546
547 /* Go keywords. */
548 htab_t keyword_hash;
549
550 /* Global type definitions. */
551 htab_t type_hash;
552
4eac1d96 553 /* Invalid types. */
554 htab_t invalid_hash;
555
929d2a90 556 /* Obstack used to write out a type definition. */
557 struct obstack type_obstack;
558};
559
560/* Append an IDENTIFIER_NODE to OB. */
561
562static void
563go_append_string (struct obstack *ob, tree id)
564{
565 obstack_grow (ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
566}
567
4d099c1c 568/* Given an integer PRECISION in bits, returns a constant string that is the
569 matching go int or uint type (depending on the IS_UNSIGNED flag). Returns a
570 NULL pointer if there is no matching go type. */
571
572static const char *
573go_get_uinttype_for_precision (unsigned int precision, bool is_unsigned)
574{
575 switch (precision)
576 {
577 case 8:
578 return is_unsigned ? "uint8" : "int8";
579 case 16:
580 return is_unsigned ? "uint16" : "int16";
581 case 32:
582 return is_unsigned ? "uint32" : "int32";
583 case 64:
584 return is_unsigned ? "uint64" : "int64";
585 default:
586 return NULL;
587 }
588}
589
590/* Append an artificial variable name with the suffix _INDEX to OB. Returns
591 INDEX + 1. */
592
593static unsigned int
594go_append_artificial_name (struct obstack *ob, unsigned int index)
595{
596 char buf[100];
597
598 /* FIXME: identifier may not be unique. */
599 obstack_grow (ob, "Godump_", 7);
600 snprintf (buf, sizeof buf, "%u", index);
601 obstack_grow (ob, buf, strlen (buf));
602
603 return index + 1;
604}
605
606/* Append the variable name from DECL to OB. If the name is in the
607 KEYWORD_HASH, prepend an '_'. */
608
609static void
610go_append_decl_name (struct obstack *ob, tree decl, htab_t keyword_hash)
611{
612 const char *var_name;
613 void **slot;
614
615 /* Start variable name with an underscore if a keyword. */
616 var_name = IDENTIFIER_POINTER (DECL_NAME (decl));
617 slot = htab_find_slot (keyword_hash, var_name, NO_INSERT);
618 if (slot != NULL)
619 obstack_1grow (ob, '_');
620 go_append_string (ob, DECL_NAME (decl));
621}
622
623/* Appends a byte array with the necessary number of elements and the name
624 "Godump_INDEX_pad" to pad from FROM_OFFSET to TO_OFFSET to OB assuming that
625 the next field is automatically aligned to ALIGN_UNITS. Returns INDEX + 1,
626 or INDEX if no padding had to be appended. The resulting offset where the
627 next field is allocated is returned through RET_OFFSET. */
628
629static unsigned int
630go_append_padding (struct obstack *ob, unsigned int from_offset,
631 unsigned int to_offset, unsigned int align_units,
632 unsigned int index, unsigned int *ret_offset)
633{
634 if (from_offset % align_units > 0)
635 from_offset += align_units - (from_offset % align_units);
636 gcc_assert (to_offset >= from_offset);
637 if (to_offset > from_offset)
638 {
639 char buf[100];
640
641 index = go_append_artificial_name (ob, index);
642 snprintf (buf, sizeof buf, "_pad [%u]byte; ", to_offset - from_offset);
643 obstack_grow (ob, buf, strlen (buf));
644 }
645 *ret_offset = to_offset;
646
647 return index;
648}
649
650/* Appends an array of type TYPE_STRING with zero elements and the name
651 "Godump_INDEX_align" to OB. If TYPE_STRING is a null pointer, ERROR_STRING
652 is appended instead of the type. Returns INDEX + 1. */
653
654static unsigned int
655go_force_record_alignment (struct obstack *ob, const char *type_string,
656 unsigned int index, const char *error_string)
657{
658 index = go_append_artificial_name (ob, index);
659 obstack_grow (ob, "_align ", 7);
660 if (type_string == NULL)
661 obstack_grow (ob, error_string, strlen (error_string));
662 else
663 {
664 obstack_grow (ob, "[0]", 3);
665 obstack_grow (ob, type_string, strlen (type_string));
666 }
667 obstack_grow (ob, "; ", 2);
668
669 return index;
670}
671
929d2a90 672/* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
673 USE_TYPE_NAME is true if we can simply use a type name here without
674 needing to define it. IS_FUNC_OK is true if we can output a func
4d099c1c 675 type here; the "func" keyword will already have been added.
676 Return true if the type can be represented in Go, false otherwise.
677 P_ART_I is used for indexing artificial elements in nested structures and
678 should always be a NULL pointer when called, except by certain recursive
679 calls from go_format_type() itself. */
929d2a90 680
681static bool
682go_format_type (struct godump_container *container, tree type,
59c8d9ee 683 bool use_type_name, bool is_func_ok, unsigned int *p_art_i,
684 bool is_anon_record_or_union)
929d2a90 685{
686 bool ret;
687 struct obstack *ob;
4d099c1c 688 unsigned int art_i_dummy;
59c8d9ee 689 bool is_union = false;
929d2a90 690
4d099c1c 691 if (p_art_i == NULL)
692 {
693 art_i_dummy = 0;
694 p_art_i = &art_i_dummy;
695 }
929d2a90 696 ret = true;
697 ob = &container->type_obstack;
698
699 if (TYPE_NAME (type) != NULL_TREE
431205b7 700 && (container->decls_seen.contains (type)
701 || container->decls_seen.contains (TYPE_NAME (type)))
929d2a90 702 && (AGGREGATE_TYPE_P (type)
703 || POINTER_TYPE_P (type)
704 || TREE_CODE (type) == FUNCTION_TYPE))
705 {
706 tree name;
4eac1d96 707 void **slot;
929d2a90 708
48dcce25 709 name = TYPE_IDENTIFIER (type);
4eac1d96 710
711 slot = htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (name),
712 NO_INSERT);
713 if (slot != NULL)
714 ret = false;
715
716 obstack_1grow (ob, '_');
717 go_append_string (ob, name);
718 return ret;
929d2a90 719 }
720
431205b7 721 container->decls_seen.add (type);
929d2a90 722
723 switch (TREE_CODE (type))
724 {
929d2a90 725 case TYPE_DECL:
24cb5f0e 726 {
727 void **slot;
728
729 slot = htab_find_slot (container->invalid_hash,
730 IDENTIFIER_POINTER (DECL_NAME (type)),
731 NO_INSERT);
732 if (slot != NULL)
733 ret = false;
734
735 obstack_1grow (ob, '_');
736 go_append_string (ob, DECL_NAME (type));
737 }
929d2a90 738 break;
739
cd0c7c8e 740 case ENUMERAL_TYPE:
929d2a90 741 case INTEGER_TYPE:
742 {
743 const char *s;
744 char buf[100];
745
4d099c1c 746 s = go_get_uinttype_for_precision (TYPE_PRECISION (type),
747 TYPE_UNSIGNED (type));
748 if (s == NULL)
929d2a90 749 {
929d2a90 750 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
751 TYPE_PRECISION (type),
752 TYPE_UNSIGNED (type) ? "u" : "");
753 s = buf;
754 ret = false;
929d2a90 755 }
756 obstack_grow (ob, s, strlen (s));
757 }
758 break;
759
760 case REAL_TYPE:
761 {
762 const char *s;
763 char buf[100];
764
765 switch (TYPE_PRECISION (type))
766 {
767 case 32:
768 s = "float32";
769 break;
770 case 64:
771 s = "float64";
772 break;
929d2a90 773 default:
774 snprintf (buf, sizeof buf, "INVALID-float-%u",
775 TYPE_PRECISION (type));
776 s = buf;
777 ret = false;
778 break;
779 }
780 obstack_grow (ob, s, strlen (s));
781 }
782 break;
783
36c50a5f 784 case COMPLEX_TYPE:
785 {
786 const char *s;
787 char buf[100];
788 tree real_type;
789
790 real_type = TREE_TYPE (type);
791 if (TREE_CODE (real_type) == REAL_TYPE)
792 {
793 switch (TYPE_PRECISION (real_type))
794 {
795 case 32:
796 s = "complex64";
797 break;
798 case 64:
799 s = "complex128";
800 break;
801 default:
802 snprintf (buf, sizeof buf, "INVALID-complex-%u",
803 2 * TYPE_PRECISION (real_type));
804 s = buf;
805 ret = false;
806 break;
807 }
808 }
809 else
810 {
811 s = "INVALID-complex-non-real";
812 ret = false;
813 }
814 obstack_grow (ob, s, strlen (s));
815 }
816 break;
817
929d2a90 818 case BOOLEAN_TYPE:
819 obstack_grow (ob, "bool", 4);
820 break;
821
822 case POINTER_TYPE:
823 if (use_type_name
824 && TYPE_NAME (TREE_TYPE (type)) != NULL_TREE
825 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))
826 || (POINTER_TYPE_P (TREE_TYPE (type))
827 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type)))
828 == FUNCTION_TYPE))))
829 {
830 tree name;
24cb5f0e 831 void **slot;
929d2a90 832
48dcce25 833 name = TYPE_IDENTIFIER (TREE_TYPE (type));
929d2a90 834
24cb5f0e 835 slot = htab_find_slot (container->invalid_hash,
836 IDENTIFIER_POINTER (name), NO_INSERT);
837 if (slot != NULL)
838 ret = false;
929d2a90 839
24cb5f0e 840 obstack_grow (ob, "*_", 2);
841 go_append_string (ob, name);
842
843 /* The pointer here can be used without the struct or union
844 definition. So this struct or union is a potential dummy
845 type. */
846 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
431205b7 847 container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
24cb5f0e 848
849 return ret;
929d2a90 850 }
851 if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
852 obstack_grow (ob, "func", 4);
853 else
854 obstack_1grow (ob, '*');
855 if (VOID_TYPE_P (TREE_TYPE (type)))
856 obstack_grow (ob, "byte", 4);
857 else
858 {
859 if (!go_format_type (container, TREE_TYPE (type), use_type_name,
59c8d9ee 860 true, NULL, false))
929d2a90 861 ret = false;
862 }
863 break;
864
865 case ARRAY_TYPE:
866 obstack_1grow (ob, '[');
867 if (TYPE_DOMAIN (type) != NULL_TREE
868 && TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
869 && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
870 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
871 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0
872 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
873 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
e913b5cd 874 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
929d2a90 875 {
876 char buf[100];
877
878 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
e913b5cd 879 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type))));
929d2a90 880 obstack_grow (ob, buf, strlen (buf));
881 }
4d099c1c 882 else
883 obstack_1grow (ob, '0');
929d2a90 884 obstack_1grow (ob, ']');
4d099c1c 885 if (!go_format_type (container, TREE_TYPE (type), use_type_name, false,
59c8d9ee 886 NULL, false))
929d2a90 887 ret = false;
888 break;
889
59c8d9ee 890 case UNION_TYPE:
891 is_union = true;
892 /* Fall through to RECORD_TYPE case. */
3c77f69c 893 gcc_fallthrough ();
929d2a90 894 case RECORD_TYPE:
895 {
4d099c1c 896 unsigned int prev_field_end;
59c8d9ee 897 unsigned int known_alignment;
929d2a90 898 tree field;
59c8d9ee 899 bool emitted_a_field;
929d2a90 900
4d099c1c 901 /* FIXME: Why is this necessary? Without it we can get a core
902 dump on the s390x headers, or from a file containing simply
903 "typedef struct S T;". */
904 layout_type (type);
905
906 prev_field_end = 0;
59c8d9ee 907 known_alignment = 1;
908 /* Anonymous records and unions are flattened, i.e. they are not put
909 into "struct { ... }". */
910 if (!is_anon_record_or_union)
911 obstack_grow (ob, "struct { ", 9);
912 for (field = TYPE_FIELDS (type), emitted_a_field = false;
929d2a90 913 field != NULL_TREE;
914 field = TREE_CHAIN (field))
915 {
4d099c1c 916 if (TREE_CODE (field) != FIELD_DECL)
917 continue;
929d2a90 918 if (DECL_BIT_FIELD (field))
59c8d9ee 919 /* Bit fields are replaced by padding. */
4d099c1c 920 continue;
59c8d9ee 921 /* Only the first non-bitfield field is emitted for unions. */
922 if (!is_union || !emitted_a_field)
923 {
924 /* Emit the field. */
925 bool field_ok;
926 bool is_anon_substructure;
927 unsigned int decl_align_unit;
928 unsigned int decl_offset;
929
930 field_ok = true;
931 emitted_a_field = true;
932 is_anon_substructure =
933 (DECL_NAME (field) == NULL
934 && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
935 || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE));
936 /* Keep track of the alignment of named substructures, either
937 of the whole record, or the alignment of the emitted field
938 (for unions). */
939 decl_align_unit = DECL_ALIGN_UNIT (field);
940 if (!is_anon_substructure && decl_align_unit > known_alignment)
941 known_alignment = decl_align_unit;
942 /* Pad to start of field. */
943 decl_offset =
944 TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
945 + precision_to_units
946 (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)));
4d099c1c 947 {
59c8d9ee 948 unsigned int align_unit;
949
950 /* For anonymous records and unions there is no automatic
951 structure alignment, so use 1 as the alignment. */
952 align_unit = (is_anon_substructure) ? 1 : decl_align_unit;
4d099c1c 953 *p_art_i = go_append_padding
59c8d9ee 954 (ob, prev_field_end, decl_offset, align_unit, *p_art_i,
4d099c1c 955 &prev_field_end);
4d099c1c 956 }
59c8d9ee 957 if (DECL_SIZE_UNIT (field))
958 prev_field_end +=
959 TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
960 /* Emit the field name, but not for anonymous records and
961 unions. */
962 if (!is_anon_substructure)
963 {
964 if ((DECL_NAME (field) == NULL))
965 *p_art_i = go_append_artificial_name (ob, *p_art_i);
966 else
967 go_append_decl_name
968 (ob, field, container->keyword_hash);
969 obstack_1grow (ob, ' ');
970 }
971 /* Do not expand type if a record or union type or a function
972 pointer. */
929d2a90 973 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
974 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
975 || (POINTER_TYPE_P (TREE_TYPE (field))
976 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
59c8d9ee 977 == FUNCTION_TYPE))))
929d2a90 978 {
24cb5f0e 979 tree name;
980 void **slot;
981
48dcce25 982 name = TYPE_IDENTIFIER (TREE_TYPE (field));
24cb5f0e 983
984 slot = htab_find_slot (container->invalid_hash,
985 IDENTIFIER_POINTER (name),
986 NO_INSERT);
987 if (slot != NULL)
85bd2ab6 988 field_ok = false;
24cb5f0e 989
990 obstack_1grow (ob, '_');
991 go_append_string (ob, name);
929d2a90 992 }
993 else
994 {
995 if (!go_format_type (container, TREE_TYPE (field), true,
59c8d9ee 996 false, p_art_i, is_anon_substructure))
85bd2ab6 997 field_ok = false;
929d2a90 998 }
59c8d9ee 999 if (!is_anon_substructure)
1000 obstack_grow (ob, "; ", 2);
1001 if (!field_ok)
1002 ret = false;
1003 }
4d099c1c 1004 }
59c8d9ee 1005 /* Padding. */
1e1cf719 1006 *p_art_i = go_append_padding (ob, prev_field_end,
1007 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type)),
1008 1, *p_art_i, &prev_field_end);
59c8d9ee 1009 /* Alignment. */
1010 if (!is_anon_record_or_union
1011 && known_alignment < TYPE_ALIGN_UNIT (type))
4d099c1c 1012 {
1013 const char *s;
1014 char buf[100];
929d2a90 1015
4d099c1c 1016 /* Enforce proper record alignment. */
1017 s = go_get_uinttype_for_precision
1018 (TYPE_ALIGN (type), TYPE_UNSIGNED (type));
1019 if (s == NULL)
85bd2ab6 1020 {
4d099c1c 1021 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
1022 TYPE_ALIGN (type), TYPE_UNSIGNED (type) ? "u" : "");
1023 s = buf;
1024 ret = false;
85bd2ab6 1025 }
4d099c1c 1026 *p_art_i = go_force_record_alignment (ob, s, *p_art_i, buf);
1027 }
59c8d9ee 1028 if (!is_anon_record_or_union)
1029 obstack_1grow (ob, '}');
4d099c1c 1030 }
59c8d9ee 1031 break;
929d2a90 1032
1033 case FUNCTION_TYPE:
1034 {
f2af597c 1035 tree arg_type;
929d2a90 1036 bool is_varargs;
1037 tree result;
f2af597c 1038 function_args_iterator iter;
1039 bool seen_arg;
929d2a90 1040
1041 /* Go has no way to write a type which is a function but not a
1042 pointer to a function. */
1043 if (!is_func_ok)
1044 {
1045 obstack_grow (ob, "func*", 5);
1046 ret = false;
1047 }
1048
1049 obstack_1grow (ob, '(');
f2af597c 1050 is_varargs = stdarg_p (type);
1051 seen_arg = false;
1052 FOREACH_FUNCTION_ARGS (type, arg_type, iter)
929d2a90 1053 {
f2af597c 1054 if (VOID_TYPE_P (arg_type))
1055 break;
1056 if (seen_arg)
929d2a90 1057 obstack_grow (ob, ", ", 2);
59c8d9ee 1058 if (!go_format_type (container, arg_type, true, false, NULL, false))
929d2a90 1059 ret = false;
f2af597c 1060 seen_arg = true;
929d2a90 1061 }
1062 if (is_varargs)
1063 {
f2af597c 1064 if (prototype_p (type))
929d2a90 1065 obstack_grow (ob, ", ", 2);
1066 obstack_grow (ob, "...interface{}", 14);
1067 }
1068 obstack_1grow (ob, ')');
1069
1070 result = TREE_TYPE (type);
1071 if (!VOID_TYPE_P (result))
1072 {
1073 obstack_1grow (ob, ' ');
59c8d9ee 1074 if (!go_format_type (container, result, use_type_name, false, NULL,
1075 false))
929d2a90 1076 ret = false;
1077 }
1078 }
1079 break;
1080
1081 default:
1082 obstack_grow (ob, "INVALID-type", 12);
1083 ret = false;
1084 break;
1085 }
1086
1087 return ret;
1088}
1089
1090/* Output the type which was built on the type obstack, and then free
1091 it. */
1092
1093static void
1094go_output_type (struct godump_container *container)
1095{
1096 struct obstack *ob;
1097
1098 ob = &container->type_obstack;
1099 obstack_1grow (ob, '\0');
cc0a8c77 1100 fputs ((char *) obstack_base (ob), go_dump_file);
929d2a90 1101 obstack_free (ob, obstack_base (ob));
1102}
1103
1104/* Output a function declaration. */
1105
1106static void
1107go_output_fndecl (struct godump_container *container, tree decl)
1108{
59c8d9ee 1109 if (!go_format_type (container, TREE_TYPE (decl), false, true, NULL, false))
929d2a90 1110 fprintf (go_dump_file, "// ");
1111 fprintf (go_dump_file, "func _%s ",
1112 IDENTIFIER_POINTER (DECL_NAME (decl)));
1113 go_output_type (container);
1114 fprintf (go_dump_file, " __asm__(\"%s\")\n",
1115 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
1116}
1117
1118/* Output a typedef or something like a struct definition. */
1119
1120static void
1121go_output_typedef (struct godump_container *container, tree decl)
1122{
1123 /* If we have an enum type, output the enum constants
1124 separately. */
1125 if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
1126 && TYPE_SIZE (TREE_TYPE (decl)) != 0
431205b7 1127 && !container->decls_seen.contains (TREE_TYPE (decl))
929d2a90 1128 && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
431205b7 1129 || !container->decls_seen.contains
1130 (TYPE_CANONICAL (TREE_TYPE (decl)))))
929d2a90 1131 {
1132 tree element;
1133
1134 for (element = TYPE_VALUES (TREE_TYPE (decl));
1135 element != NULL_TREE;
1136 element = TREE_CHAIN (element))
32874486 1137 {
1138 const char *name;
62aab493 1139 struct macro_hash_value *mhval;
32874486 1140 void **slot;
e913b5cd 1141 char buf[WIDE_INT_PRINT_BUFFER_SIZE];
32874486 1142
1143 name = IDENTIFIER_POINTER (TREE_PURPOSE (element));
1144
1145 /* Sometimes a name will be defined as both an enum constant
1146 and a macro. Avoid duplicate definition errors by
1147 treating enum constants as macros. */
62aab493 1148 mhval = XNEW (struct macro_hash_value);
1149 mhval->name = xstrdup (name);
1150 mhval->value = NULL;
1151 slot = htab_find_slot (macro_hash, mhval, INSERT);
1152 if (*slot != NULL)
1153 macro_hash_del (*slot);
1154
e913b5cd 1155 if (tree_fits_shwi_p (TREE_VALUE (element)))
62aab493 1156 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC,
e913b5cd 1157 tree_to_shwi (TREE_VALUE (element)));
1158 else if (tree_fits_uhwi_p (TREE_VALUE (element)))
62aab493 1159 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_UNSIGNED,
aa59f000 1160 tree_to_uhwi (TREE_VALUE (element)));
62aab493 1161 else
6da74b21 1162 print_hex (element, buf);
62aab493 1163
1164 mhval->value = xstrdup (buf);
1165 *slot = mhval;
32874486 1166 }
431205b7 1167 container->decls_seen.add (TREE_TYPE (decl));
929d2a90 1168 if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
431205b7 1169 container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl)));
929d2a90 1170 }
1171
1172 if (DECL_NAME (decl) != NULL_TREE)
1173 {
1174 void **slot;
1175 const char *type;
1176
1177 type = IDENTIFIER_POINTER (DECL_NAME (decl));
1178 /* If type defined already, skip. */
1179 slot = htab_find_slot (container->type_hash, type, INSERT);
1180 if (*slot != NULL)
1181 return;
1182 *slot = CONST_CAST (void *, (const void *) type);
1183
59c8d9ee 1184 if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL,
1185 false))
4eac1d96 1186 {
1187 fprintf (go_dump_file, "// ");
1188 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1189 *slot = CONST_CAST (void *, (const void *) type);
1190 }
929d2a90 1191 fprintf (go_dump_file, "type _%s ",
1192 IDENTIFIER_POINTER (DECL_NAME (decl)));
1193 go_output_type (container);
5150d596 1194
1195 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1196 {
1197 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
1198
1199 if (size > 0)
1200 fprintf (go_dump_file,
1201 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1202 IDENTIFIER_POINTER (DECL_NAME (decl)),
1203 size);
1204 }
1205
431205b7 1206 container->decls_seen.add (decl);
929d2a90 1207 }
1208 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1209 {
1210 void **slot;
1211 const char *type;
5150d596 1212 HOST_WIDE_INT size;
929d2a90 1213
1214 type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
1215 /* If type defined already, skip. */
1216 slot = htab_find_slot (container->type_hash, type, INSERT);
1217 if (*slot != NULL)
1218 return;
1219 *slot = CONST_CAST (void *, (const void *) type);
1220
59c8d9ee 1221 if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL,
1222 false))
4eac1d96 1223 {
1224 fprintf (go_dump_file, "// ");
1225 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1226 *slot = CONST_CAST (void *, (const void *) type);
1227 }
929d2a90 1228 fprintf (go_dump_file, "type _%s ",
1229 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
1230 go_output_type (container);
5150d596 1231
1232 size = int_size_in_bytes (TREE_TYPE (decl));
1233 if (size > 0)
1234 fprintf (go_dump_file,
1235 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1236 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))),
1237 size);
929d2a90 1238 }
1239 else
1240 return;
1241
1242 fprintf (go_dump_file, "\n");
1243}
1244
1245/* Output a variable. */
1246
1247static void
1248go_output_var (struct godump_container *container, tree decl)
1249{
3c6b311d 1250 bool is_valid;
4d099c1c 1251 tree type_name;
1252 tree id;
3c6b311d 1253
431205b7 1254 if (container->decls_seen.contains (decl)
1255 || container->decls_seen.contains (DECL_NAME (decl)))
929d2a90 1256 return;
431205b7 1257 container->decls_seen.add (decl);
1258 container->decls_seen.add (DECL_NAME (decl));
3c6b311d 1259
4d099c1c 1260 type_name = TYPE_NAME (TREE_TYPE (decl));
1261 id = NULL_TREE;
1262 if (type_name != NULL_TREE && TREE_CODE (type_name) == IDENTIFIER_NODE)
1263 id = type_name;
1264 else if (type_name != NULL_TREE && TREE_CODE (type_name) == TYPE_DECL
1265 && DECL_SOURCE_LOCATION (type_name) != BUILTINS_LOCATION
1266 && DECL_NAME (type_name))
1267 id = DECL_NAME (type_name);
1268 if (id != NULL_TREE
1269 && (!htab_find_slot (container->type_hash, IDENTIFIER_POINTER (id),
1270 NO_INSERT)
1271 || htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (id),
1272 NO_INSERT)))
1273 id = NULL_TREE;
1274 if (id != NULL_TREE)
1275 {
1276 struct obstack *ob;
1277
1278 ob = &container->type_obstack;
1279 obstack_1grow (ob, '_');
1280 go_append_string (ob, id);
1281 is_valid = htab_find_slot (container->type_hash, IDENTIFIER_POINTER (id),
1282 NO_INSERT) != NULL;
1283 }
1284 else
59c8d9ee 1285 is_valid = go_format_type (container, TREE_TYPE (decl), true, false, NULL,
1286 false);
3c6b311d 1287 if (is_valid
1288 && htab_find_slot (container->type_hash,
1289 IDENTIFIER_POINTER (DECL_NAME (decl)),
1290 NO_INSERT) != NULL)
1291 {
1292 /* There is already a type with this name, probably from a
1293 struct tag. Prefer the type to the variable. */
1294 is_valid = false;
1295 }
1296 if (!is_valid)
929d2a90 1297 fprintf (go_dump_file, "// ");
3c6b311d 1298
929d2a90 1299 fprintf (go_dump_file, "var _%s ",
1300 IDENTIFIER_POINTER (DECL_NAME (decl)));
1301 go_output_type (container);
1302 fprintf (go_dump_file, "\n");
1303
1304 /* Sometimes an extern variable is declared with an unknown struct
1305 type. */
4d099c1c 1306 if (type_name != NULL_TREE && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
929d2a90 1307 {
929d2a90 1308 if (TREE_CODE (type_name) == IDENTIFIER_NODE)
431205b7 1309 container->pot_dummy_types.add (IDENTIFIER_POINTER (type_name));
929d2a90 1310 else if (TREE_CODE (type_name) == TYPE_DECL)
431205b7 1311 container->pot_dummy_types.add
1312 (IDENTIFIER_POINTER (DECL_NAME (type_name)));
929d2a90 1313 }
1314}
1315
62aab493 1316/* Output the final value of a preprocessor macro or enum constant.
1317 This is called via htab_traverse_noresize. */
1318
1319static int
1320go_print_macro (void **slot, void *arg ATTRIBUTE_UNUSED)
1321{
1322 struct macro_hash_value *mhval = (struct macro_hash_value *) *slot;
1323 fprintf (go_dump_file, "const _%s = %s\n", mhval->name, mhval->value);
1324 return 1;
1325}
1326
929d2a90 1327/* Build a hash table with the Go keywords. */
1328
1329static const char * const keywords[] = {
1330 "__asm__", "break", "case", "chan", "const", "continue", "default",
1331 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1332 "import", "interface", "map", "package", "range", "return", "select",
1333 "struct", "switch", "type", "var"
1334};
1335
1336static void
1337keyword_hash_init (struct godump_container *container)
1338{
1339 size_t i;
1340 size_t count = sizeof (keywords) / sizeof (keywords[0]);
1341 void **slot;
1342
1343 for (i = 0; i < count; i++)
1344 {
1345 slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
1346 *slot = CONST_CAST (void *, (const void *) keywords[i]);
1347 }
1348}
1349
1350/* Traversing the pot_dummy_types and seeing which types are present
1351 in the global types hash table and creating dummy definitions if
431205b7 1352 not found. This function is invoked by hash_set::traverse. */
929d2a90 1353
431205b7 1354bool
1355find_dummy_types (const char *const &ptr, godump_container *adata)
929d2a90 1356{
1357 struct godump_container *data = (struct godump_container *) adata;
1358 const char *type = (const char *) ptr;
1359 void **slot;
9591058e 1360 void **islot;
929d2a90 1361
1362 slot = htab_find_slot (data->type_hash, type, NO_INSERT);
9591058e 1363 islot = htab_find_slot (data->invalid_hash, type, NO_INSERT);
1364 if (slot == NULL || islot != NULL)
929d2a90 1365 fprintf (go_dump_file, "type _%s struct {}\n", type);
1366 return true;
1367}
1368
1369/* Output symbols. */
1370
1371static void
1372go_finish (const char *filename)
1373{
1374 struct godump_container container;
1375 unsigned int ix;
1376 tree decl;
1377
1378 real_debug_hooks->finish (filename);
1379
929d2a90 1380 container.type_hash = htab_create (100, htab_hash_string,
1381 string_hash_eq, NULL);
4eac1d96 1382 container.invalid_hash = htab_create (10, htab_hash_string,
1383 string_hash_eq, NULL);
929d2a90 1384 container.keyword_hash = htab_create (50, htab_hash_string,
1385 string_hash_eq, NULL);
1386 obstack_init (&container.type_obstack);
1387
1388 keyword_hash_init (&container);
1389
f1f41a6c 1390 FOR_EACH_VEC_SAFE_ELT (queue, ix, decl)
929d2a90 1391 {
1392 switch (TREE_CODE (decl))
1393 {
1394 case FUNCTION_DECL:
1395 go_output_fndecl (&container, decl);
1396 break;
1397
1398 case TYPE_DECL:
1399 go_output_typedef (&container, decl);
1400 break;
1401
1402 case VAR_DECL:
1403 go_output_var (&container, decl);
1404 break;
1405
1406 default:
9af5ce0c 1407 gcc_unreachable ();
929d2a90 1408 }
1409 }
1410
62aab493 1411 htab_traverse_noresize (macro_hash, go_print_macro, NULL);
1412
929d2a90 1413 /* To emit dummy definitions. */
431205b7 1414 container.pot_dummy_types.traverse<godump_container *, find_dummy_types>
1415 (&container);
929d2a90 1416
929d2a90 1417 htab_delete (container.type_hash);
4eac1d96 1418 htab_delete (container.invalid_hash);
929d2a90 1419 htab_delete (container.keyword_hash);
1420 obstack_free (&container.type_obstack, NULL);
1421
f1f41a6c 1422 vec_free (queue);
929d2a90 1423
1424 if (fclose (go_dump_file) != 0)
1425 error ("could not close Go dump file: %m");
1426 go_dump_file = NULL;
1427}
1428
1429/* Set up our hooks. */
1430
1431const struct gcc_debug_hooks *
1432dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
1433{
1434 go_dump_file = fopen (filename, "w");
1435 if (go_dump_file == NULL)
1436 {
1437 error ("could not open Go dump file %qs: %m", filename);
1438 return hooks;
1439 }
1440
1441 go_debug_hooks = *hooks;
1442 real_debug_hooks = hooks;
1443
1444 go_debug_hooks.finish = go_finish;
1445 go_debug_hooks.define = go_define;
1446 go_debug_hooks.undef = go_undef;
1447 go_debug_hooks.function_decl = go_function_decl;
3a1c9df2 1448 go_debug_hooks.early_global_decl = go_early_global_decl;
1449 go_debug_hooks.late_global_decl = go_late_global_decl;
929d2a90 1450 go_debug_hooks.type_decl = go_type_decl;
1451
62aab493 1452 macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq,
1453 macro_hash_del);
929d2a90 1454
1455 return &go_debug_hooks;
1456}
1457
1458#include "gt-godump.h"