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