OSDN Git Service

remove TYPE_ARG_TYPES from godump.c
[pf3gnuchains/gcc-fork.git] / gcc / godump.c
1 /* Output Go language descriptions of types.
2    Copyright (C) 2008, 2009, 2010, 2011 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 "tree.h"
35 #include "ggc.h"
36 #include "pointer-set.h"
37 #include "obstack.h"
38 #include "debug.h"
39
40 /* We dump this information from the debug hooks.  This gives us a
41    stable and maintainable API to hook into.  In order to work
42    correctly when -g is used, we build our own hooks structure which
43    wraps the hooks we need to change.  */
44
45 /* Our debug hooks.  This is initialized by dump_go_spec_init.  */
46
47 static struct gcc_debug_hooks go_debug_hooks;
48
49 /* The real debug hooks.  */
50
51 static const struct gcc_debug_hooks *real_debug_hooks;
52
53 /* The file where we should write information.  */
54
55 static FILE *go_dump_file;
56
57 /* A queue of decls to output.  */
58
59 static GTY(()) VEC(tree,gc) *queue;
60
61 /* A hash table of macros we have seen.  */
62
63 static htab_t macro_hash;
64
65 /* For the hash tables.  */
66
67 static int
68 string_hash_eq (const void *y1, const void *y2)
69 {
70   return strcmp ((const char *) y1, (const char *) y2) == 0;
71 }
72
73 /* A macro definition.  */
74
75 static void
76 go_define (unsigned int lineno, const char *buffer)
77 {
78   const char *p;
79   const char *name_end;
80   char *out_buffer;
81   char *q;
82   bool saw_operand;
83   bool need_operand;
84   char *copy;
85   hashval_t hashval;
86   void **slot;
87
88   real_debug_hooks->define (lineno, buffer);
89
90   /* Skip macro functions.  */
91   for (p = buffer; *p != '\0' && *p != ' '; ++p)
92     if (*p == '(')
93       return;
94
95   if (*p == '\0')
96     return;
97
98   name_end = p;
99
100   ++p;
101   if (*p == '\0')
102     return;
103
104   copy = XNEWVEC (char, name_end - buffer + 1);
105   memcpy (copy, buffer, name_end - buffer);
106   copy[name_end - buffer] = '\0';
107
108   hashval = htab_hash_string (copy);
109   slot = htab_find_slot_with_hash (macro_hash, copy, hashval, NO_INSERT);
110   if (slot != NULL)
111     {
112       XDELETEVEC (copy);
113       return;
114     }
115
116   /* For simplicity, we force all names to be hidden by adding an
117      initial underscore, and let the user undo this as needed.  */
118   out_buffer = XNEWVEC (char, strlen (p) * 2 + 1);
119   q = out_buffer;
120   saw_operand = false;
121   need_operand = false;
122   while (*p != '\0')
123     {
124       switch (*p)
125         {
126         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
127         case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
128         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
129         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
130         case 'Y': case 'Z':
131         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
132         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
133         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
134         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
135         case 'y': case 'z':
136         case '_':
137           {
138             /* The start of an identifier.  Technically we should also
139                worry about UTF-8 identifiers, but they are not a
140                problem for practical uses of -fdump-go-spec so we
141                don't worry about them.  */
142             const char *start;
143             char *n;
144
145             if (saw_operand)
146               goto unknown;
147
148             start = p;
149             while (ISALNUM (*p) || *p == '_')
150               ++p;
151             n = XALLOCAVEC (char, p - start + 1);
152             memcpy (n, start, p - start);
153             n[p - start] = '\0';
154             slot = htab_find_slot (macro_hash, n, NO_INSERT);
155             if (slot == NULL || *slot == NULL)
156               {
157                 /* This is a reference to a name which was not defined
158                    as a macro.  */
159                 goto unknown;
160               }
161
162             *q++ = '_';
163             memcpy (q, start, p - start);
164             q += p - start;
165
166             saw_operand = true;
167             need_operand = false;
168           }
169           break;
170
171         case '.':
172           if (!ISDIGIT (p[1]))
173             goto unknown;
174           /* Fall through.  */
175         case '0': case '1': case '2': case '3': case '4':
176         case '5': case '6': case '7': case '8': case '9':
177           {
178             const char *start;
179             bool is_hex;
180
181             start = p;
182             is_hex = false;
183             if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
184               {
185                 p += 2;
186                 is_hex = true;
187               }
188             while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
189                    || (is_hex
190                        && ((*p >= 'a' && *p <= 'f')
191                            || (*p >= 'A' && *p <= 'F'))))
192               ++p;
193             memcpy (q, start, p - start);
194             q += p - start;
195             while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
196                    || *p == 'f' || *p == 'F'
197                    || *p == 'd' || *p == 'D')
198               {
199                 /* Go doesn't use any of these trailing type
200                    modifiers.  */
201                 ++p;
202               }
203
204             /* We'll pick up the exponent, if any, as an
205                expression.  */
206
207             saw_operand = true;
208             need_operand = false;
209           }
210           break;
211
212         case ' ': case '\t':
213           *q++ = *p++;
214           break;
215
216         case '(':
217           /* Always OK, not part of an operand, presumed to start an
218              operand.  */
219           *q++ = *p++;
220           saw_operand = false;
221           need_operand = false;
222           break;
223
224         case ')':
225           /* OK if we don't need an operand, and presumed to indicate
226              an operand.  */
227           if (need_operand)
228             goto unknown;
229           *q++ = *p++;
230           saw_operand = true;
231           break;
232
233         case '+': case '-':
234           /* Always OK, but not part of an operand.  */
235           *q++ = *p++;
236           saw_operand = false;
237           break;
238
239         case '*': case '/': case '%': case '|': case '&': case '^':
240           /* Must be a binary operator.  */
241           if (!saw_operand)
242             goto unknown;
243           *q++ = *p++;
244           saw_operand = false;
245           need_operand = true;
246           break;
247
248         case '=':
249           *q++ = *p++;
250           if (*p != '=')
251             goto unknown;
252           /* Must be a binary operator.  */
253           if (!saw_operand)
254             goto unknown;
255           *q++ = *p++;
256           saw_operand = false;
257           need_operand = true;
258           break;
259
260         case '!':
261           *q++ = *p++;
262           if (*p == '=')
263             {
264               /* Must be a binary operator.  */
265               if (!saw_operand)
266                 goto unknown;
267               *q++ = *p++;
268               saw_operand = false;
269               need_operand = true;
270             }
271           else
272             {
273               /* Must be a unary operator.  */
274               if (saw_operand)
275                 goto unknown;
276               need_operand = true;
277             }
278           break;
279
280         case '<': case '>':
281           /* Must be a binary operand, may be << or >> or <= or >=.  */
282           if (!saw_operand)
283             goto unknown;
284           *q++ = *p++;
285           if (*p == *(p - 1) || *p == '=')
286             *q++ = *p++;
287           saw_operand = false;
288           need_operand = true;
289           break;
290
291         case '~':
292           /* Must be a unary operand, must be translated for Go.  */
293           if (saw_operand)
294             goto unknown;
295           *q++ = '^';
296           p++;
297           need_operand = true;
298           break;
299
300         case '"':
301         case '\'':
302           {
303             char quote = *p;
304             *q++ = *p++;
305             while (*p != quote)
306               {
307                 int c;
308
309                 if (*p == '\0')
310                   goto unknown;
311
312                 if (*p != '\\')
313                   {
314                     *q++ = *p++;
315                     continue;
316                   }
317
318                 *q++ = *p++;
319                 switch (*p)
320                   {
321                   case '0': case '1': case '2': case '3':
322                   case '4': case '5': case '6': case '7':
323                     c = 0;
324                     while (*p >= '0' && *p <= '7')
325                       {
326                         *q++ = *p++;
327                         ++c;
328                       }
329                     /* Go octal characters are always 3
330                        digits.  */
331                     if (c != 3)
332                       goto unknown;
333                     break;
334
335                   case 'x':
336                     *q++ = *p++;
337                     c = 0;
338                     while (ISXDIGIT (*p))
339                       {
340                         *q++ = *p++;
341                         ++c;
342                       }
343                     /* Go hex characters are always 2 digits.  */
344                     if (c != 2)
345                       goto unknown;
346                     break;
347
348                   case 'a': case 'b': case 'f': case 'n': case 'r':
349                   case 't': case 'v': case '\\': case '\'': case '"':
350                     *q++ = *p++;
351                     break;
352
353                   default:
354                     goto unknown;
355                   }
356               }
357             *q++ = *p++;
358             break;
359           }
360
361         default:
362           goto unknown;
363         }
364     }
365
366   if (need_operand)
367     goto unknown;
368
369   *q = '\0';
370
371   slot = htab_find_slot_with_hash (macro_hash, copy, hashval, INSERT);
372   *slot = copy;
373
374   fprintf (go_dump_file, "const _%s = %s\n", copy, out_buffer);
375
376   XDELETEVEC (out_buffer);
377   return;
378
379  unknown:
380   fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
381   XDELETEVEC (out_buffer);
382   XDELETEVEC (copy);
383 }
384
385 /* A macro undef.  */
386
387 static void
388 go_undef (unsigned int lineno, const char *buffer)
389 {
390   void **slot;
391
392   real_debug_hooks->undef (lineno, buffer);
393
394   slot = htab_find_slot (macro_hash, buffer, NO_INSERT);
395   if (slot == NULL)
396     return;
397   fprintf (go_dump_file, "// undef _%s\n", buffer);
398   /* We don't delete the slot from the hash table because that will
399      cause a duplicate const definition.  */
400 }
401
402 /* A function or variable decl.  */
403
404 static void
405 go_decl (tree decl)
406 {
407   if (!TREE_PUBLIC (decl)
408       || DECL_IS_BUILTIN (decl)
409       || DECL_NAME (decl) == NULL_TREE)
410     return;
411   VEC_safe_push (tree, gc, queue, decl);
412 }
413
414 /* A function decl.  */
415
416 static void
417 go_function_decl (tree decl)
418 {
419   real_debug_hooks->function_decl (decl);
420   go_decl (decl);
421 }
422
423 /* A global variable decl.  */
424
425 static void
426 go_global_decl (tree decl)
427 {
428   real_debug_hooks->global_decl (decl);
429   go_decl (decl);
430 }
431
432 /* A type declaration.  */
433
434 static void
435 go_type_decl (tree decl, int local)
436 {
437   real_debug_hooks->type_decl (decl, local);
438
439   if (local || DECL_IS_BUILTIN (decl))
440     return;
441   if (DECL_NAME (decl) == NULL_TREE
442       && (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE
443           || TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) != IDENTIFIER_NODE)
444       && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
445     return;
446   VEC_safe_push (tree, gc, queue, decl);
447 }
448
449 /* A container for the data we pass around when generating information
450    at the end of the compilation.  */
451
452 struct godump_container
453 {
454   /* DECLs that we have already seen.  */
455   struct pointer_set_t *decls_seen;
456
457   /* Types which may potentially have to be defined as dummy
458      types.  */
459   struct pointer_set_t *pot_dummy_types;
460
461   /* Go keywords.  */
462   htab_t keyword_hash;
463
464   /* Global type definitions.  */
465   htab_t type_hash;
466
467   /* Obstack used to write out a type definition.  */
468   struct obstack type_obstack;
469 };
470
471 /* Append an IDENTIFIER_NODE to OB.  */
472
473 static void
474 go_append_string (struct obstack *ob, tree id)
475 {
476   obstack_grow (ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
477 }
478
479 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
480    USE_TYPE_NAME is true if we can simply use a type name here without
481    needing to define it.  IS_FUNC_OK is true if we can output a func
482    type here; the "func" keyword will already have been added.  Return
483    true if the type can be represented in Go, false otherwise.  */
484
485 static bool
486 go_format_type (struct godump_container *container, tree type,
487                 bool use_type_name, bool is_func_ok)
488 {
489   bool ret;
490   struct obstack *ob;
491
492   ret = true;
493   ob = &container->type_obstack;
494
495   if (TYPE_NAME (type) != NULL_TREE
496       && (pointer_set_contains (container->decls_seen, type)
497           || pointer_set_contains (container->decls_seen, TYPE_NAME (type)))
498       && (AGGREGATE_TYPE_P (type)
499           || POINTER_TYPE_P (type)
500           || TREE_CODE (type) == FUNCTION_TYPE))
501     {
502       tree name;
503
504       name = TYPE_NAME (type);
505       if (TREE_CODE (name) == IDENTIFIER_NODE)
506         {
507           obstack_1grow (ob, '_');
508           go_append_string (ob, name);
509           return ret;
510         }
511       else if (TREE_CODE (name) == TYPE_DECL)
512         {
513           obstack_1grow (ob, '_');
514           go_append_string (ob, DECL_NAME (name));
515           return ret;
516         }
517     }
518
519   pointer_set_insert (container->decls_seen, type);
520
521   switch (TREE_CODE (type))
522     {
523     case ENUMERAL_TYPE:
524       obstack_grow (ob, "int", 3);
525       break;
526
527     case TYPE_DECL:
528       obstack_1grow (ob, '_');
529       go_append_string (ob, DECL_NAME (type));
530       break;
531
532     case INTEGER_TYPE:
533       {
534         const char *s;
535         char buf[100];
536
537         switch (TYPE_PRECISION (type))
538           {
539           case 8:
540             s = TYPE_UNSIGNED (type) ? "uint8" : "int8";
541             break;
542           case 16:
543             s = TYPE_UNSIGNED (type) ? "uint16" : "int16";
544             break;
545           case 32:
546             s = TYPE_UNSIGNED (type) ? "uint32" : "int32";
547             break;
548           case 64:
549             s = TYPE_UNSIGNED (type) ? "uint64" : "int64";
550             break;
551           default:
552             snprintf (buf, sizeof buf, "INVALID-int-%u%s",
553                       TYPE_PRECISION (type),
554                       TYPE_UNSIGNED (type) ? "u" : "");
555             s = buf;
556             ret = false;
557             break;
558           }
559         obstack_grow (ob, s, strlen (s));
560       }
561       break;
562
563     case REAL_TYPE:
564       {
565         const char *s;
566         char buf[100];
567
568         switch (TYPE_PRECISION (type))
569           {
570           case 32:
571             s = "float32";
572             break;
573           case 64:
574             s = "float64";
575             break;
576           default:
577             snprintf (buf, sizeof buf, "INVALID-float-%u",
578                       TYPE_PRECISION (type));
579             s = buf;
580             ret = false;
581             break;
582           }
583         obstack_grow (ob, s, strlen (s));
584       }
585       break;
586
587     case BOOLEAN_TYPE:
588       obstack_grow (ob, "bool", 4);
589       break;
590
591     case POINTER_TYPE:
592       if (use_type_name
593           && TYPE_NAME (TREE_TYPE (type)) != NULL_TREE
594           && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))
595               || (POINTER_TYPE_P (TREE_TYPE (type))
596                   && (TREE_CODE (TREE_TYPE (TREE_TYPE (type)))
597                       == FUNCTION_TYPE))))
598         {
599           tree name;
600
601           name = TYPE_NAME (TREE_TYPE (type));
602           if (TREE_CODE (name) == IDENTIFIER_NODE)
603             {
604               obstack_grow (ob, "*_", 2);
605               go_append_string (ob, name);
606
607               /* The pointer here can be used without the struct or
608                  union definition.  So this struct or union is a a
609                  potential dummy type.  */
610               if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
611                 pointer_set_insert (container->pot_dummy_types,
612                                     IDENTIFIER_POINTER (name));
613
614               return ret;
615             }
616           else if (TREE_CODE (name) == TYPE_DECL)
617             {
618               obstack_grow (ob, "*_", 2);
619               go_append_string (ob, DECL_NAME (name));
620               if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
621                 pointer_set_insert (container->pot_dummy_types,
622                                     IDENTIFIER_POINTER (DECL_NAME (name)));
623               return ret;
624             }
625         }
626       if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
627         obstack_grow (ob, "func", 4);
628       else
629         obstack_1grow (ob, '*');
630       if (VOID_TYPE_P (TREE_TYPE (type)))
631         obstack_grow (ob, "byte", 4);
632       else
633         {
634           if (!go_format_type (container, TREE_TYPE (type), use_type_name,
635                                true))
636             ret = false;
637         }
638       break;
639
640     case ARRAY_TYPE:
641       obstack_1grow (ob, '[');
642       if (TYPE_DOMAIN (type) != NULL_TREE
643           && TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
644           && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
645           && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
646           && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0
647           && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
648           && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
649           && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0))
650         {
651           char buf[100];
652
653           snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
654                     tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0));
655           obstack_grow (ob, buf, strlen (buf));
656         }
657       obstack_1grow (ob, ']');
658       if (!go_format_type (container, TREE_TYPE (type), use_type_name, false))
659         ret = false;
660       break;
661
662     case UNION_TYPE:
663     case RECORD_TYPE:
664       {
665         tree field;
666         int i;
667
668         obstack_grow (ob, "struct { ", 9);
669         i = 0;
670         for (field = TYPE_FIELDS (type);
671              field != NULL_TREE;
672              field = TREE_CHAIN (field))
673           {
674             if (DECL_NAME (field) == NULL)
675               {
676                 char buf[100];
677
678                 obstack_grow (ob, "Godump_", 2);
679                 snprintf (buf, sizeof buf, "%d", i);
680                 obstack_grow (ob, buf, strlen (buf));
681                 i++;
682               }
683             else
684               {
685                 const char *var_name;
686                 void **slot;
687
688                 /* Start variable name with an underscore if a keyword.  */
689                 var_name = IDENTIFIER_POINTER (DECL_NAME (field));
690                 slot = htab_find_slot (container->keyword_hash, var_name,
691                                        NO_INSERT);
692                 if (slot != NULL)
693                   obstack_1grow (ob, '_');
694                 go_append_string (ob, DECL_NAME (field));
695               }
696             obstack_1grow (ob, ' ');
697             if (DECL_BIT_FIELD (field))
698               {
699                 obstack_grow (ob, "INVALID-bit-field", 17);
700                 ret = false;
701               }
702             else
703               {
704                 /* Do not expand type if a record or union type or a
705                    function pointer.  */
706                 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
707                     && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
708                         || (POINTER_TYPE_P (TREE_TYPE (field))
709                             && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
710                                 == FUNCTION_TYPE))))
711                   {
712                     tree name = TYPE_NAME (TREE_TYPE (field));
713                     if (TREE_CODE (name) == IDENTIFIER_NODE)
714                       {
715                         obstack_1grow (ob, '_');
716                         go_append_string (ob, name);
717                       }
718                     else if (TREE_CODE (name) == TYPE_DECL)
719                       {
720                         obstack_1grow (ob, '_');
721                         go_append_string (ob, DECL_NAME (name));
722                       }
723                   }
724                 else
725                   {
726                     if (!go_format_type (container, TREE_TYPE (field), true,
727                                          false))
728                       ret = false;
729                   }
730               }
731             obstack_grow (ob, "; ", 2);
732
733             /* Only output the first field of a union, and hope for
734                the best.  */
735             if (TREE_CODE (type) == UNION_TYPE)
736               break;
737           }
738         obstack_1grow (ob, '}');
739       }
740       break;
741
742     case FUNCTION_TYPE:
743       {
744         tree arg_type;
745         bool is_varargs;
746         tree result;
747         function_args_iterator iter;
748         bool seen_arg;
749
750         /* Go has no way to write a type which is a function but not a
751            pointer to a function.  */
752         if (!is_func_ok)
753           {
754             obstack_grow (ob, "func*", 5);
755             ret = false;
756           }
757
758         obstack_1grow (ob, '(');
759         is_varargs = stdarg_p (type);
760         seen_arg = false;
761         FOREACH_FUNCTION_ARGS (type, arg_type, iter)
762           {
763             if (VOID_TYPE_P (arg_type))
764               break;
765             if (seen_arg)
766               obstack_grow (ob, ", ", 2);
767             if (!go_format_type (container, arg_type, true, false))
768               ret = false;
769             seen_arg = true;
770           }
771         if (is_varargs)
772           {
773             if (prototype_p (type))
774               obstack_grow (ob, ", ", 2);
775             obstack_grow (ob, "...interface{}", 14);
776           }
777         obstack_1grow (ob, ')');
778
779         result = TREE_TYPE (type);
780         if (!VOID_TYPE_P (result))
781           {
782             obstack_1grow (ob, ' ');
783             if (!go_format_type (container, result, use_type_name, false))
784               ret = false;
785           }
786       }
787       break;
788
789     default:
790       obstack_grow (ob, "INVALID-type", 12);
791       ret = false;
792       break;
793     }
794
795   return ret;
796 }
797
798 /* Output the type which was built on the type obstack, and then free
799    it.  */
800
801 static void
802 go_output_type (struct godump_container *container)
803 {
804   struct obstack *ob;
805
806   ob = &container->type_obstack;
807   obstack_1grow (ob, '\0');
808   fputs (obstack_base (ob), go_dump_file);
809   obstack_free (ob, obstack_base (ob));
810 }
811
812 /* Output a function declaration.  */
813
814 static void
815 go_output_fndecl (struct godump_container *container, tree decl)
816 {
817   if (!go_format_type (container, TREE_TYPE (decl), false, true))
818     fprintf (go_dump_file, "// ");
819   fprintf (go_dump_file, "func _%s ",
820            IDENTIFIER_POINTER (DECL_NAME (decl)));
821   go_output_type (container);
822   fprintf (go_dump_file, " __asm__(\"%s\")\n",
823            IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
824 }
825
826 /* Output a typedef or something like a struct definition.  */
827
828 static void
829 go_output_typedef (struct godump_container *container, tree decl)
830 {
831   /* If we have an enum type, output the enum constants
832      separately.  */
833   if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
834       && TYPE_SIZE (TREE_TYPE (decl)) != 0
835       && !pointer_set_contains (container->decls_seen, TREE_TYPE (decl))
836       && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
837           || !pointer_set_contains (container->decls_seen,
838                                     TYPE_CANONICAL (TREE_TYPE (decl)))))
839     {
840       tree element;
841
842       for (element = TYPE_VALUES (TREE_TYPE (decl));
843            element != NULL_TREE;
844            element = TREE_CHAIN (element))
845         {
846           const char *name;
847           void **slot;
848
849           name = IDENTIFIER_POINTER (TREE_PURPOSE (element));
850
851           /* Sometimes a name will be defined as both an enum constant
852              and a macro.  Avoid duplicate definition errors by
853              treating enum constants as macros.  */
854           slot = htab_find_slot (macro_hash, name, INSERT);
855           if (*slot == NULL)
856             {
857               *slot = CONST_CAST (char *, name);
858               fprintf (go_dump_file,
859                        "const _%s = " HOST_WIDE_INT_PRINT_DEC "\n",
860                        name, tree_low_cst (TREE_VALUE (element), 0));
861             }
862         }
863       pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
864       if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
865         pointer_set_insert (container->decls_seen,
866                             TYPE_CANONICAL (TREE_TYPE (decl)));
867     }
868
869   if (DECL_NAME (decl) != NULL_TREE)
870     {
871       void **slot;
872       const char *type;
873
874       type = IDENTIFIER_POINTER (DECL_NAME (decl));
875       /* If type defined already, skip.  */
876       slot = htab_find_slot (container->type_hash, type, INSERT);
877       if (*slot != NULL)
878         return;
879       *slot = CONST_CAST (void *, (const void *) type);
880
881       if (!go_format_type (container, TREE_TYPE (decl), false, false))
882         fprintf (go_dump_file, "// ");
883       fprintf (go_dump_file, "type _%s ",
884                IDENTIFIER_POINTER (DECL_NAME (decl)));
885       go_output_type (container);
886       pointer_set_insert (container->decls_seen, decl);
887     }
888   else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
889     {
890        void **slot;
891        const char *type;
892
893        type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
894        /* If type defined already, skip.  */
895        slot = htab_find_slot (container->type_hash, type, INSERT);
896        if (*slot != NULL)
897          return;
898        *slot = CONST_CAST (void *, (const void *) type);
899
900        if (!go_format_type (container, TREE_TYPE (decl), false, false))
901          fprintf (go_dump_file, "// ");
902        fprintf (go_dump_file, "type _%s ",
903                IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
904        go_output_type (container);
905     }
906   else
907     return;
908
909   fprintf (go_dump_file, "\n");
910 }
911
912 /* Output a variable.  */
913
914 static void
915 go_output_var (struct godump_container *container, tree decl)
916 {
917   bool is_valid;
918
919   if (pointer_set_contains (container->decls_seen, decl)
920       || pointer_set_contains (container->decls_seen, DECL_NAME (decl)))
921     return;
922   pointer_set_insert (container->decls_seen, decl);
923   pointer_set_insert (container->decls_seen, DECL_NAME (decl));
924
925   is_valid = go_format_type (container, TREE_TYPE (decl), true, false);
926   if (is_valid
927       && htab_find_slot (container->type_hash,
928                          IDENTIFIER_POINTER (DECL_NAME (decl)),
929                          NO_INSERT) != NULL)
930     {
931       /* There is already a type with this name, probably from a
932          struct tag.  Prefer the type to the variable.  */
933       is_valid = false;
934     }
935   if (!is_valid)
936     fprintf (go_dump_file, "// ");
937
938   fprintf (go_dump_file, "var _%s ",
939            IDENTIFIER_POINTER (DECL_NAME (decl)));
940   go_output_type (container);
941   fprintf (go_dump_file, "\n");
942
943   /* Sometimes an extern variable is declared with an unknown struct
944      type.  */
945   if (TYPE_NAME (TREE_TYPE (decl)) != NULL_TREE
946       && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
947     {
948       tree type_name = TYPE_NAME (TREE_TYPE (decl));
949       if (TREE_CODE (type_name) == IDENTIFIER_NODE)
950         pointer_set_insert (container->pot_dummy_types,
951                             IDENTIFIER_POINTER (type_name));
952       else if (TREE_CODE (type_name) == TYPE_DECL)
953         pointer_set_insert (container->pot_dummy_types,
954                             IDENTIFIER_POINTER (DECL_NAME (type_name)));
955     }
956 }
957
958 /* Build a hash table with the Go keywords.  */
959
960 static const char * const keywords[] = {
961   "__asm__", "break", "case", "chan", "const", "continue", "default",
962   "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
963   "import", "interface", "map", "package", "range", "return", "select",
964   "struct", "switch", "type", "var"
965 };
966
967 static void
968 keyword_hash_init (struct godump_container *container)
969 {
970   size_t i;
971   size_t count = sizeof (keywords) / sizeof (keywords[0]);
972   void **slot;
973
974   for (i = 0; i < count; i++)
975     {
976       slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
977       *slot = CONST_CAST (void *, (const void *) keywords[i]);
978     }
979 }
980
981 /* Traversing the pot_dummy_types and seeing which types are present
982    in the global types hash table and creating dummy definitions if
983    not found.  This function is invoked by pointer_set_traverse.  */
984
985 static bool
986 find_dummy_types (const void *ptr, void *adata)
987 {
988   struct godump_container *data = (struct godump_container *) adata;
989   const char *type = (const char *) ptr;
990   void **slot;
991
992   slot = htab_find_slot (data->type_hash, type, NO_INSERT);
993   if (slot == NULL)
994     fprintf (go_dump_file, "type _%s struct {}\n", type);
995   return true;
996 }
997
998 /* Output symbols.  */
999
1000 static void
1001 go_finish (const char *filename)
1002 {
1003   struct godump_container container;
1004   unsigned int ix;
1005   tree decl;
1006
1007   real_debug_hooks->finish (filename);
1008
1009   container.decls_seen = pointer_set_create ();
1010   container.pot_dummy_types = pointer_set_create ();
1011   container.type_hash = htab_create (100, htab_hash_string,
1012                                      string_hash_eq, NULL);
1013   container.keyword_hash = htab_create (50, htab_hash_string,
1014                                         string_hash_eq, NULL);
1015   obstack_init (&container.type_obstack);
1016
1017   keyword_hash_init (&container);
1018
1019   FOR_EACH_VEC_ELT (tree, queue, ix, decl)
1020     {
1021       switch (TREE_CODE (decl))
1022         {
1023         case FUNCTION_DECL:
1024           go_output_fndecl (&container, decl);
1025           break;
1026
1027         case TYPE_DECL:
1028           go_output_typedef (&container, decl);
1029           break;
1030
1031         case VAR_DECL:
1032           go_output_var (&container, decl);
1033           break;
1034
1035         default:
1036           gcc_unreachable();
1037         }
1038     }
1039
1040   /* To emit dummy definitions.  */
1041   pointer_set_traverse (container.pot_dummy_types, find_dummy_types,
1042                         (void *) &container);
1043
1044   pointer_set_destroy (container.decls_seen);
1045   pointer_set_destroy (container.pot_dummy_types);
1046   htab_delete (container.type_hash);
1047   htab_delete (container.keyword_hash);
1048   obstack_free (&container.type_obstack, NULL);
1049
1050   queue = NULL;
1051
1052   if (fclose (go_dump_file) != 0)
1053     error ("could not close Go dump file: %m");
1054   go_dump_file = NULL;
1055 }
1056
1057 /* Set up our hooks.  */
1058
1059 const struct gcc_debug_hooks *
1060 dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
1061 {
1062   go_dump_file = fopen (filename, "w");
1063   if (go_dump_file == NULL)
1064     {
1065       error ("could not open Go dump file %qs: %m", filename);
1066       return hooks;
1067     }
1068
1069   go_debug_hooks = *hooks;
1070   real_debug_hooks = hooks;
1071
1072   go_debug_hooks.finish = go_finish;
1073   go_debug_hooks.define = go_define;
1074   go_debug_hooks.undef = go_undef;
1075   go_debug_hooks.function_decl = go_function_decl;
1076   go_debug_hooks.global_decl = go_global_decl;
1077   go_debug_hooks.type_decl = go_type_decl;
1078
1079   macro_hash = htab_create (100, htab_hash_string, string_hash_eq, NULL);
1080
1081   return &go_debug_hooks;
1082 }
1083
1084 #include "gt-godump.h"