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