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 "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, va_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
macro_hash_hashval(const void * val)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
macro_hash_eq(const void * v1,const void * v2)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
macro_hash_del(void * v)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
string_hash_eq(const void * y1,const void * y2)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
go_define(unsigned int lineno,const char * buffer)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
go_undef(unsigned int lineno,const char * buffer)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
go_decl(tree decl)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 (queue, decl);
484 }
485 
486 /* A function decl.  */
487 
488 static void
go_function_decl(tree decl)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
go_global_decl(tree decl)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
go_type_decl(tree decl,int local)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 (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
go_append_string(struct obstack * ob,tree id)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
go_format_type(struct godump_container * container,tree type,bool use_type_name,bool is_func_ok)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 	  && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
732 	{
733 	  char buf[100];
734 
735 	  snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
736 		    tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type))));
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
go_output_type(struct godump_container * container)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
go_output_fndecl(struct godump_container * container,tree decl)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
go_output_typedef(struct godump_container * container,tree decl)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 (tree_fits_shwi_p (TREE_VALUE (element)))
985 	    snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC,
986 		     tree_to_shwi (TREE_VALUE (element)));
987 	  else if (tree_fits_uhwi_p (TREE_VALUE (element)))
988 	    snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_UNSIGNED,
989 		      tree_to_uhwi (TREE_VALUE (element)));
990 	  else
991 	    snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
992 		     ((unsigned HOST_WIDE_INT)
993 		      TREE_INT_CST_HIGH (TREE_VALUE (element))),
994 		     TREE_INT_CST_LOW (TREE_VALUE (element)));
995 
996 	  mhval->value = xstrdup (buf);
997 	  *slot = mhval;
998 	}
999       pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
1000       if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
1001 	pointer_set_insert (container->decls_seen,
1002 			    TYPE_CANONICAL (TREE_TYPE (decl)));
1003     }
1004 
1005   if (DECL_NAME (decl) != NULL_TREE)
1006     {
1007       void **slot;
1008       const char *type;
1009 
1010       type = IDENTIFIER_POINTER (DECL_NAME (decl));
1011       /* If type defined already, skip.  */
1012       slot = htab_find_slot (container->type_hash, type, INSERT);
1013       if (*slot != NULL)
1014 	return;
1015       *slot = CONST_CAST (void *, (const void *) type);
1016 
1017       if (!go_format_type (container, TREE_TYPE (decl), false, false))
1018 	{
1019 	  fprintf (go_dump_file, "// ");
1020 	  slot = htab_find_slot (container->invalid_hash, type, INSERT);
1021 	  *slot = CONST_CAST (void *, (const void *) type);
1022 	}
1023       fprintf (go_dump_file, "type _%s ",
1024 	       IDENTIFIER_POINTER (DECL_NAME (decl)));
1025       go_output_type (container);
1026 
1027       if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1028 	{
1029 	  HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
1030 
1031 	  if (size > 0)
1032 	    fprintf (go_dump_file,
1033 		     "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1034 		     IDENTIFIER_POINTER (DECL_NAME (decl)),
1035 		     size);
1036 	}
1037 
1038       pointer_set_insert (container->decls_seen, decl);
1039     }
1040   else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1041     {
1042        void **slot;
1043        const char *type;
1044        HOST_WIDE_INT size;
1045 
1046        type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
1047        /* If type defined already, skip.  */
1048        slot = htab_find_slot (container->type_hash, type, INSERT);
1049        if (*slot != NULL)
1050          return;
1051        *slot = CONST_CAST (void *, (const void *) type);
1052 
1053        if (!go_format_type (container, TREE_TYPE (decl), false, false))
1054 	 {
1055 	   fprintf (go_dump_file, "// ");
1056 	   slot = htab_find_slot (container->invalid_hash, type, INSERT);
1057 	   *slot = CONST_CAST (void *, (const void *) type);
1058 	 }
1059        fprintf (go_dump_file, "type _%s ",
1060 	       IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
1061        go_output_type (container);
1062 
1063        size = int_size_in_bytes (TREE_TYPE (decl));
1064        if (size > 0)
1065 	 fprintf (go_dump_file,
1066 		  "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1067 		  IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))),
1068 		  size);
1069     }
1070   else
1071     return;
1072 
1073   fprintf (go_dump_file, "\n");
1074 }
1075 
1076 /* Output a variable.  */
1077 
1078 static void
go_output_var(struct godump_container * container,tree decl)1079 go_output_var (struct godump_container *container, tree decl)
1080 {
1081   bool is_valid;
1082 
1083   if (pointer_set_contains (container->decls_seen, decl)
1084       || pointer_set_contains (container->decls_seen, DECL_NAME (decl)))
1085     return;
1086   pointer_set_insert (container->decls_seen, decl);
1087   pointer_set_insert (container->decls_seen, DECL_NAME (decl));
1088 
1089   is_valid = go_format_type (container, TREE_TYPE (decl), true, false);
1090   if (is_valid
1091       && htab_find_slot (container->type_hash,
1092 			 IDENTIFIER_POINTER (DECL_NAME (decl)),
1093 			 NO_INSERT) != NULL)
1094     {
1095       /* There is already a type with this name, probably from a
1096 	 struct tag.  Prefer the type to the variable.  */
1097       is_valid = false;
1098     }
1099   if (!is_valid)
1100     fprintf (go_dump_file, "// ");
1101 
1102   fprintf (go_dump_file, "var _%s ",
1103 	   IDENTIFIER_POINTER (DECL_NAME (decl)));
1104   go_output_type (container);
1105   fprintf (go_dump_file, "\n");
1106 
1107   /* Sometimes an extern variable is declared with an unknown struct
1108      type.  */
1109   if (TYPE_NAME (TREE_TYPE (decl)) != NULL_TREE
1110       && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1111     {
1112       tree type_name = TYPE_NAME (TREE_TYPE (decl));
1113       if (TREE_CODE (type_name) == IDENTIFIER_NODE)
1114 	pointer_set_insert (container->pot_dummy_types,
1115 			    IDENTIFIER_POINTER (type_name));
1116       else if (TREE_CODE (type_name) == TYPE_DECL)
1117 	pointer_set_insert (container->pot_dummy_types,
1118 			    IDENTIFIER_POINTER (DECL_NAME (type_name)));
1119     }
1120 }
1121 
1122 /* Output the final value of a preprocessor macro or enum constant.
1123    This is called via htab_traverse_noresize.  */
1124 
1125 static int
go_print_macro(void ** slot,void * arg ATTRIBUTE_UNUSED)1126 go_print_macro (void **slot, void *arg ATTRIBUTE_UNUSED)
1127 {
1128   struct macro_hash_value *mhval = (struct macro_hash_value *) *slot;
1129   fprintf (go_dump_file, "const _%s = %s\n", mhval->name, mhval->value);
1130   return 1;
1131 }
1132 
1133 /* Build a hash table with the Go keywords.  */
1134 
1135 static const char * const keywords[] = {
1136   "__asm__", "break", "case", "chan", "const", "continue", "default",
1137   "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1138   "import", "interface", "map", "package", "range", "return", "select",
1139   "struct", "switch", "type", "var"
1140 };
1141 
1142 static void
keyword_hash_init(struct godump_container * container)1143 keyword_hash_init (struct godump_container *container)
1144 {
1145   size_t i;
1146   size_t count = sizeof (keywords) / sizeof (keywords[0]);
1147   void **slot;
1148 
1149   for (i = 0; i < count; i++)
1150     {
1151       slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
1152       *slot = CONST_CAST (void *, (const void *) keywords[i]);
1153     }
1154 }
1155 
1156 /* Traversing the pot_dummy_types and seeing which types are present
1157    in the global types hash table and creating dummy definitions if
1158    not found.  This function is invoked by pointer_set_traverse.  */
1159 
1160 static bool
find_dummy_types(const void * ptr,void * adata)1161 find_dummy_types (const void *ptr, void *adata)
1162 {
1163   struct godump_container *data = (struct godump_container *) adata;
1164   const char *type = (const char *) ptr;
1165   void **slot;
1166   void **islot;
1167 
1168   slot = htab_find_slot (data->type_hash, type, NO_INSERT);
1169   islot = htab_find_slot (data->invalid_hash, type, NO_INSERT);
1170   if (slot == NULL || islot != NULL)
1171     fprintf (go_dump_file, "type _%s struct {}\n", type);
1172   return true;
1173 }
1174 
1175 /* Output symbols.  */
1176 
1177 static void
go_finish(const char * filename)1178 go_finish (const char *filename)
1179 {
1180   struct godump_container container;
1181   unsigned int ix;
1182   tree decl;
1183 
1184   real_debug_hooks->finish (filename);
1185 
1186   container.decls_seen = pointer_set_create ();
1187   container.pot_dummy_types = pointer_set_create ();
1188   container.type_hash = htab_create (100, htab_hash_string,
1189                                      string_hash_eq, NULL);
1190   container.invalid_hash = htab_create (10, htab_hash_string,
1191 					string_hash_eq, NULL);
1192   container.keyword_hash = htab_create (50, htab_hash_string,
1193                                         string_hash_eq, NULL);
1194   obstack_init (&container.type_obstack);
1195 
1196   keyword_hash_init (&container);
1197 
1198   FOR_EACH_VEC_SAFE_ELT (queue, ix, decl)
1199     {
1200       switch (TREE_CODE (decl))
1201 	{
1202 	case FUNCTION_DECL:
1203 	  go_output_fndecl (&container, decl);
1204 	  break;
1205 
1206 	case TYPE_DECL:
1207 	  go_output_typedef (&container, decl);
1208 	  break;
1209 
1210 	case VAR_DECL:
1211 	  go_output_var (&container, decl);
1212 	  break;
1213 
1214 	default:
1215 	  gcc_unreachable ();
1216 	}
1217     }
1218 
1219   htab_traverse_noresize (macro_hash, go_print_macro, NULL);
1220 
1221   /* To emit dummy definitions.  */
1222   pointer_set_traverse (container.pot_dummy_types, find_dummy_types,
1223                         (void *) &container);
1224 
1225   pointer_set_destroy (container.decls_seen);
1226   pointer_set_destroy (container.pot_dummy_types);
1227   htab_delete (container.type_hash);
1228   htab_delete (container.invalid_hash);
1229   htab_delete (container.keyword_hash);
1230   obstack_free (&container.type_obstack, NULL);
1231 
1232   vec_free (queue);
1233 
1234   if (fclose (go_dump_file) != 0)
1235     error ("could not close Go dump file: %m");
1236   go_dump_file = NULL;
1237 }
1238 
1239 /* Set up our hooks.  */
1240 
1241 const struct gcc_debug_hooks *
dump_go_spec_init(const char * filename,const struct gcc_debug_hooks * hooks)1242 dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
1243 {
1244   go_dump_file = fopen (filename, "w");
1245   if (go_dump_file == NULL)
1246     {
1247       error ("could not open Go dump file %qs: %m", filename);
1248       return hooks;
1249     }
1250 
1251   go_debug_hooks = *hooks;
1252   real_debug_hooks = hooks;
1253 
1254   go_debug_hooks.finish = go_finish;
1255   go_debug_hooks.define = go_define;
1256   go_debug_hooks.undef = go_undef;
1257   go_debug_hooks.function_decl = go_function_decl;
1258   go_debug_hooks.global_decl = go_global_decl;
1259   go_debug_hooks.type_decl = go_type_decl;
1260 
1261   macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq,
1262 			    macro_hash_del);
1263 
1264   return &go_debug_hooks;
1265 }
1266 
1267 #include "gt-godump.h"
1268