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