* config/i386/i386-features.c
[gcc.git] / gcc / godump.c
1 /* Output Go language descriptions of types.
2 Copyright (C) 2008-2019 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"