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