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