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