OSDN Git Service

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