Daily bump.
[gcc.git] / gcc / godump.c
1 /* Output Go language descriptions of types.
2 Copyright (C) 2008-2021 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_UNDECLARED_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_UNDECLARED_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 (use_type_name
701 && TYPE_NAME (type) != NULL_TREE
702 && (AGGREGATE_TYPE_P (type)
703 || POINTER_TYPE_P (type)
704 || TREE_CODE (type) == FUNCTION_TYPE))
705 {
706 tree name;
707 void **slot;
708
709 /* References to complex builtin types cannot be translated to
710 Go. */
711 if (DECL_P (TYPE_NAME (type))
712 && DECL_IS_UNDECLARED_BUILTIN (TYPE_NAME (type)))
713 ret = false;
714
715 name = TYPE_IDENTIFIER (type);
716
717 slot = htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (name),
718 NO_INSERT);
719 if (slot != NULL)
720 ret = false;
721
722 /* References to incomplete structs are permitted in many
723 contexts, like behind a pointer or inside of a typedef. So
724 consider any referenced struct a potential dummy type. */
725 if (RECORD_OR_UNION_TYPE_P (type))
726 container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
727
728 obstack_1grow (ob, '_');
729 go_append_string (ob, name);
730 return ret;
731 }
732
733 switch (TREE_CODE (type))
734 {
735 case TYPE_DECL:
736 {
737 void **slot;
738
739 slot = htab_find_slot (container->invalid_hash,
740 IDENTIFIER_POINTER (DECL_NAME (type)),
741 NO_INSERT);
742 if (slot != NULL)
743 ret = false;
744
745 obstack_1grow (ob, '_');
746 go_append_string (ob, DECL_NAME (type));
747 }
748 break;
749
750 case ENUMERAL_TYPE:
751 case INTEGER_TYPE:
752 {
753 const char *s;
754 char buf[100];
755
756 s = go_get_uinttype_for_precision (TYPE_PRECISION (type),
757 TYPE_UNSIGNED (type));
758 if (s == NULL)
759 {
760 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
761 TYPE_PRECISION (type),
762 TYPE_UNSIGNED (type) ? "u" : "");
763 s = buf;
764 ret = false;
765 }
766 obstack_grow (ob, s, strlen (s));
767 }
768 break;
769
770 case REAL_TYPE:
771 {
772 const char *s;
773 char buf[100];
774
775 switch (TYPE_PRECISION (type))
776 {
777 case 32:
778 s = "float32";
779 break;
780 case 64:
781 s = "float64";
782 break;
783 default:
784 snprintf (buf, sizeof buf, "INVALID-float-%u",
785 TYPE_PRECISION (type));
786 s = buf;
787 ret = false;
788 break;
789 }
790 obstack_grow (ob, s, strlen (s));
791 }
792 break;
793
794 case COMPLEX_TYPE:
795 {
796 const char *s;
797 char buf[100];
798 tree real_type;
799
800 real_type = TREE_TYPE (type);
801 if (TREE_CODE (real_type) == REAL_TYPE)
802 {
803 switch (TYPE_PRECISION (real_type))
804 {
805 case 32:
806 s = "complex64";
807 break;
808 case 64:
809 s = "complex128";
810 break;
811 default:
812 snprintf (buf, sizeof buf, "INVALID-complex-%u",
813 2 * TYPE_PRECISION (real_type));
814 s = buf;
815 ret = false;
816 break;
817 }
818 }
819 else
820 {
821 s = "INVALID-complex-non-real";
822 ret = false;
823 }
824 obstack_grow (ob, s, strlen (s));
825 }
826 break;
827
828 case BOOLEAN_TYPE:
829 obstack_grow (ob, "bool", 4);
830 break;
831
832 case POINTER_TYPE:
833 if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
834 obstack_grow (ob, "func", 4);
835 else
836 obstack_1grow (ob, '*');
837 if (VOID_TYPE_P (TREE_TYPE (type)))
838 obstack_grow (ob, "byte", 4);
839 else
840 {
841 if (!go_format_type (container, TREE_TYPE (type), use_type_name,
842 true, NULL, false))
843 ret = false;
844 }
845 break;
846
847 case ARRAY_TYPE:
848 obstack_1grow (ob, '[');
849 if (TYPE_DOMAIN (type) != NULL_TREE
850 && TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
851 && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
852 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
853 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0
854 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
855 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
856 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
857 {
858 char buf[100];
859
860 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
861 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type))));
862 obstack_grow (ob, buf, strlen (buf));
863 }
864 else
865 obstack_1grow (ob, '0');
866 obstack_1grow (ob, ']');
867 if (!go_format_type (container, TREE_TYPE (type), use_type_name, false,
868 NULL, false))
869 ret = false;
870 break;
871
872 case UNION_TYPE:
873 is_union = true;
874 /* Fall through to RECORD_TYPE case. */
875 gcc_fallthrough ();
876 case RECORD_TYPE:
877 {
878 unsigned int prev_field_end;
879 unsigned int known_alignment;
880 tree field;
881 bool emitted_a_field;
882
883 /* FIXME: Why is this necessary? Without it we can get a core
884 dump on the s390x headers, or from a file containing simply
885 "typedef struct S T;". */
886 layout_type (type);
887
888 prev_field_end = 0;
889 known_alignment = 1;
890 /* Anonymous records and unions are flattened, i.e. they are not put
891 into "struct { ... }". */
892 if (!is_anon_record_or_union)
893 obstack_grow (ob, "struct { ", 9);
894 for (field = TYPE_FIELDS (type), emitted_a_field = false;
895 field != NULL_TREE;
896 field = TREE_CHAIN (field))
897 {
898 if (TREE_CODE (field) != FIELD_DECL)
899 continue;
900 if (DECL_BIT_FIELD (field))
901 /* Bit fields are replaced by padding. */
902 continue;
903 /* Only the first non-bitfield field is emitted for unions. */
904 if (!is_union || !emitted_a_field)
905 {
906 /* Emit the field. */
907 bool field_ok;
908 bool is_anon_substructure;
909 unsigned int decl_align_unit;
910 unsigned int decl_offset;
911
912 field_ok = true;
913 emitted_a_field = true;
914 is_anon_substructure =
915 (DECL_NAME (field) == NULL
916 && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
917 || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE));
918 /* Keep track of the alignment of named substructures, either
919 of the whole record, or the alignment of the emitted field
920 (for unions). */
921 decl_align_unit = DECL_ALIGN_UNIT (field);
922 if (!is_anon_substructure && decl_align_unit > known_alignment)
923 known_alignment = decl_align_unit;
924 /* Pad to start of field. */
925 decl_offset =
926 TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
927 + precision_to_units
928 (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)));
929 {
930 unsigned int align_unit;
931
932 /* For anonymous records and unions there is no automatic
933 structure alignment, so use 1 as the alignment. */
934 align_unit = (is_anon_substructure) ? 1 : decl_align_unit;
935 *p_art_i = go_append_padding
936 (ob, prev_field_end, decl_offset, align_unit, *p_art_i,
937 &prev_field_end);
938 }
939 if (DECL_SIZE_UNIT (field))
940 prev_field_end +=
941 TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
942 /* Emit the field name, but not for anonymous records and
943 unions. */
944 if (!is_anon_substructure)
945 {
946 if (DECL_NAME (field) == NULL)
947 *p_art_i = go_append_artificial_name (ob, *p_art_i);
948 else
949 go_append_decl_name
950 (ob, field, container->keyword_hash);
951 obstack_1grow (ob, ' ');
952 }
953 /* Do not expand type if a record or union type or a function
954 pointer. */
955 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
956 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
957 || (POINTER_TYPE_P (TREE_TYPE (field))
958 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
959 == FUNCTION_TYPE))))
960 {
961 tree name;
962 void **slot;
963
964 name = TYPE_IDENTIFIER (TREE_TYPE (field));
965
966 slot = htab_find_slot (container->invalid_hash,
967 IDENTIFIER_POINTER (name),
968 NO_INSERT);
969 if (slot != NULL)
970 field_ok = false;
971
972 obstack_1grow (ob, '_');
973 go_append_string (ob, name);
974 }
975 else
976 {
977 if (!go_format_type (container, TREE_TYPE (field), true,
978 false, p_art_i, is_anon_substructure))
979 field_ok = false;
980 }
981 if (!is_anon_substructure)
982 obstack_grow (ob, "; ", 2);
983 if (!field_ok)
984 ret = false;
985 }
986 }
987 /* Padding. */
988 *p_art_i = go_append_padding (ob, prev_field_end,
989 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type)),
990 1, *p_art_i, &prev_field_end);
991 /* Alignment. */
992 if (!is_anon_record_or_union
993 && known_alignment < TYPE_ALIGN_UNIT (type))
994 {
995 const char *s;
996 char buf[100];
997
998 /* Enforce proper record alignment. */
999 s = go_get_uinttype_for_precision
1000 (TYPE_ALIGN (type), TYPE_UNSIGNED (type));
1001 if (s == NULL)
1002 {
1003 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
1004 TYPE_ALIGN (type), TYPE_UNSIGNED (type) ? "u" : "");
1005 s = buf;
1006 ret = false;
1007 }
1008 *p_art_i = go_force_record_alignment (ob, s, *p_art_i, buf);
1009 }
1010 if (!is_anon_record_or_union)
1011 obstack_1grow (ob, '}');
1012 }
1013 break;
1014
1015 case FUNCTION_TYPE:
1016 {
1017 tree arg_type;
1018 bool is_varargs;
1019 tree result;
1020 function_args_iterator iter;
1021 bool seen_arg;
1022
1023 /* Go has no way to write a type which is a function but not a
1024 pointer to a function. */
1025 if (!is_func_ok)
1026 {
1027 obstack_grow (ob, "func*", 5);
1028 ret = false;
1029 }
1030
1031 obstack_1grow (ob, '(');
1032 is_varargs = stdarg_p (type);
1033 seen_arg = false;
1034 FOREACH_FUNCTION_ARGS (type, arg_type, iter)
1035 {
1036 if (VOID_TYPE_P (arg_type))
1037 break;
1038 if (seen_arg)
1039 obstack_grow (ob, ", ", 2);
1040 if (!go_format_type (container, arg_type, true, false, NULL, false))
1041 ret = false;
1042 seen_arg = true;
1043 }
1044 if (is_varargs)
1045 {
1046 if (prototype_p (type))
1047 obstack_grow (ob, ", ", 2);
1048 obstack_grow (ob, "...interface{}", 14);
1049 }
1050 obstack_1grow (ob, ')');
1051
1052 result = TREE_TYPE (type);
1053 if (!VOID_TYPE_P (result))
1054 {
1055 obstack_1grow (ob, ' ');
1056 if (!go_format_type (container, result, use_type_name, false, NULL,
1057 false))
1058 ret = false;
1059 }
1060 }
1061 break;
1062
1063 default:
1064 obstack_grow (ob, "INVALID-type", 12);
1065 ret = false;
1066 break;
1067 }
1068
1069 return ret;
1070 }
1071
1072 /* Output the type which was built on the type obstack, and then free
1073 it. */
1074
1075 static void
1076 go_output_type (class godump_container *container)
1077 {
1078 struct obstack *ob;
1079
1080 ob = &container->type_obstack;
1081 obstack_1grow (ob, '\0');
1082 fputs ((char *) obstack_base (ob), go_dump_file);
1083 obstack_free (ob, obstack_base (ob));
1084 }
1085
1086 /* Output a function declaration. */
1087
1088 static void
1089 go_output_fndecl (class godump_container *container, tree decl)
1090 {
1091 if (!go_format_type (container, TREE_TYPE (decl), true, true, NULL, false))
1092 fprintf (go_dump_file, "// ");
1093 fprintf (go_dump_file, "func _%s ",
1094 IDENTIFIER_POINTER (DECL_NAME (decl)));
1095 go_output_type (container);
1096 fprintf (go_dump_file, " __asm__(\"%s\")\n",
1097 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
1098 }
1099
1100 /* Output a typedef or something like a struct definition. */
1101
1102 static void
1103 go_output_typedef (class godump_container *container, tree decl)
1104 {
1105 /* If we have an enum type, output the enum constants
1106 separately. */
1107 if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
1108 && TYPE_SIZE (TREE_TYPE (decl)) != 0
1109 && !container->decls_seen.contains (TREE_TYPE (decl))
1110 && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
1111 || !container->decls_seen.contains
1112 (TYPE_CANONICAL (TREE_TYPE (decl)))))
1113 {
1114 tree element;
1115
1116 for (element = TYPE_VALUES (TREE_TYPE (decl));
1117 element != NULL_TREE;
1118 element = TREE_CHAIN (element))
1119 {
1120 const char *name;
1121 struct macro_hash_value *mhval;
1122 void **slot;
1123 char buf[WIDE_INT_PRINT_BUFFER_SIZE];
1124
1125 name = IDENTIFIER_POINTER (TREE_PURPOSE (element));
1126
1127 /* Sometimes a name will be defined as both an enum constant
1128 and a macro. Avoid duplicate definition errors by
1129 treating enum constants as macros. */
1130 mhval = XNEW (struct macro_hash_value);
1131 mhval->name = xstrdup (name);
1132 mhval->value = NULL;
1133 slot = htab_find_slot (macro_hash, mhval, INSERT);
1134 if (*slot != NULL)
1135 macro_hash_del (*slot);
1136
1137 if (tree_fits_shwi_p (TREE_VALUE (element)))
1138 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC,
1139 tree_to_shwi (TREE_VALUE (element)));
1140 else if (tree_fits_uhwi_p (TREE_VALUE (element)))
1141 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_UNSIGNED,
1142 tree_to_uhwi (TREE_VALUE (element)));
1143 else
1144 print_hex (wi::to_wide (element), buf);
1145
1146 mhval->value = xstrdup (buf);
1147 *slot = mhval;
1148 }
1149 container->decls_seen.add (TREE_TYPE (decl));
1150 if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
1151 container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl)));
1152 }
1153
1154 if (DECL_NAME (decl) != NULL_TREE)
1155 {
1156 void **slot;
1157 const char *type;
1158 tree original_type;
1159
1160 type = IDENTIFIER_POINTER (DECL_NAME (decl));
1161 original_type = DECL_ORIGINAL_TYPE (decl);
1162 if (original_type == NULL_TREE)
1163 original_type = TREE_TYPE (decl);
1164
1165 /* Suppress typedefs where the type name matches the underlying
1166 struct/union/enum tag. This way we'll emit the struct definition
1167 instead of an invalid recursive type. */
1168 if (TYPE_IDENTIFIER (original_type) != NULL
1169 && IDENTIFIER_POINTER (TYPE_IDENTIFIER (original_type)) == type)
1170 return;
1171
1172 /* If type defined already, skip. */
1173 slot = htab_find_slot (container->type_hash, type, INSERT);
1174 if (*slot != NULL)
1175 return;
1176 *slot = CONST_CAST (void *, (const void *) type);
1177
1178 if (!go_format_type (container, original_type, true, false,
1179 NULL, false))
1180 {
1181 fprintf (go_dump_file, "// ");
1182 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1183 *slot = CONST_CAST (void *, (const void *) type);
1184 }
1185 fprintf (go_dump_file, "type _%s ",
1186 IDENTIFIER_POINTER (DECL_NAME (decl)));
1187 go_output_type (container);
1188
1189 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1190 {
1191 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
1192
1193 if (size > 0)
1194 fprintf (go_dump_file,
1195 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1196 IDENTIFIER_POINTER (DECL_NAME (decl)),
1197 size);
1198 }
1199
1200 container->decls_seen.add (decl);
1201 }
1202 else if ((RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
1203 || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
1204 && TYPE_NAME (TREE_TYPE (decl)) != NULL)
1205 {
1206 void **slot;
1207 const char *type;
1208 HOST_WIDE_INT size;
1209
1210 type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
1211 /* If type defined already, skip. */
1212 slot = htab_find_slot (container->type_hash, type, INSERT);
1213 if (*slot != NULL)
1214 return;
1215 *slot = CONST_CAST (void *, (const void *) type);
1216
1217 if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL,
1218 false))
1219 {
1220 fprintf (go_dump_file, "// ");
1221 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1222 *slot = CONST_CAST (void *, (const void *) type);
1223 }
1224 fprintf (go_dump_file, "type _%s ",
1225 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
1226 go_output_type (container);
1227
1228 size = int_size_in_bytes (TREE_TYPE (decl));
1229 if (size > 0)
1230 fprintf (go_dump_file,
1231 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1232 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))),
1233 size);
1234 }
1235 else
1236 return;
1237
1238 fprintf (go_dump_file, "\n");
1239 }
1240
1241 /* Output a variable. */
1242
1243 static void
1244 go_output_var (class godump_container *container, tree decl)
1245 {
1246 bool is_valid;
1247 tree type_name;
1248 tree id;
1249
1250 if (container->decls_seen.contains (decl)
1251 || container->decls_seen.contains (DECL_NAME (decl)))
1252 return;
1253 container->decls_seen.add (decl);
1254 container->decls_seen.add (DECL_NAME (decl));
1255
1256 type_name = TYPE_NAME (TREE_TYPE (decl));
1257 id = NULL_TREE;
1258 if (type_name != NULL_TREE && TREE_CODE (type_name) == IDENTIFIER_NODE)
1259 id = type_name;
1260 else if (type_name != NULL_TREE && TREE_CODE (type_name) == TYPE_DECL
1261 && DECL_SOURCE_LOCATION (type_name) != BUILTINS_LOCATION
1262 && DECL_NAME (type_name))
1263 id = DECL_NAME (type_name);
1264 if (id != NULL_TREE
1265 && (!htab_find_slot (container->type_hash, IDENTIFIER_POINTER (id),
1266 NO_INSERT)
1267 || htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (id),
1268 NO_INSERT)))
1269 id = NULL_TREE;
1270 if (id != NULL_TREE)
1271 {
1272 struct obstack *ob;
1273
1274 ob = &container->type_obstack;
1275 obstack_1grow (ob, '_');
1276 go_append_string (ob, id);
1277 is_valid = htab_find_slot (container->type_hash, IDENTIFIER_POINTER (id),
1278 NO_INSERT) != NULL;
1279 }
1280 else
1281 is_valid = go_format_type (container, TREE_TYPE (decl), true, false, NULL,
1282 false);
1283 if (is_valid
1284 && htab_find_slot (container->type_hash,
1285 IDENTIFIER_POINTER (DECL_NAME (decl)),
1286 NO_INSERT) != NULL)
1287 {
1288 /* There is already a type with this name, probably from a
1289 struct tag. Prefer the type to the variable. */
1290 is_valid = false;
1291 }
1292 if (!is_valid)
1293 fprintf (go_dump_file, "// ");
1294
1295 fprintf (go_dump_file, "var _%s ",
1296 IDENTIFIER_POINTER (DECL_NAME (decl)));
1297 go_output_type (container);
1298 fprintf (go_dump_file, "\n");
1299
1300 /* Sometimes an extern variable is declared with an unknown struct
1301 type. */
1302 if (type_name != NULL_TREE && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1303 {
1304 if (TREE_CODE (type_name) == IDENTIFIER_NODE)
1305 container->pot_dummy_types.add (IDENTIFIER_POINTER (type_name));
1306 else if (TREE_CODE (type_name) == TYPE_DECL)
1307 container->pot_dummy_types.add
1308 (IDENTIFIER_POINTER (DECL_NAME (type_name)));
1309 }
1310 }
1311
1312 /* Output the final value of a preprocessor macro or enum constant.
1313 This is called via htab_traverse_noresize. */
1314
1315 static int
1316 go_print_macro (void **slot, void *arg ATTRIBUTE_UNUSED)
1317 {
1318 struct macro_hash_value *mhval = (struct macro_hash_value *) *slot;
1319 fprintf (go_dump_file, "const _%s = %s\n", mhval->name, mhval->value);
1320 return 1;
1321 }
1322
1323 /* Build a hash table with the Go keywords. */
1324
1325 static const char * const keywords[] = {
1326 "__asm__", "break", "case", "chan", "const", "continue", "default",
1327 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1328 "import", "interface", "map", "package", "range", "return", "select",
1329 "struct", "switch", "type", "var"
1330 };
1331
1332 static void
1333 keyword_hash_init (class godump_container *container)
1334 {
1335 size_t i;
1336 size_t count = sizeof (keywords) / sizeof (keywords[0]);
1337 void **slot;
1338
1339 for (i = 0; i < count; i++)
1340 {
1341 slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
1342 *slot = CONST_CAST (void *, (const void *) keywords[i]);
1343 }
1344 }
1345
1346 /* Traversing the pot_dummy_types and seeing which types are present
1347 in the global types hash table and creating dummy definitions if
1348 not found. This function is invoked by hash_set::traverse. */
1349
1350 bool
1351 find_dummy_types (const char *const &ptr, godump_container *adata)
1352 {
1353 class godump_container *data = (class godump_container *) adata;
1354 const char *type = (const char *) ptr;
1355 void **slot;
1356 void **islot;
1357
1358 slot = htab_find_slot (data->type_hash, type, NO_INSERT);
1359 islot = htab_find_slot (data->invalid_hash, type, NO_INSERT);
1360 if (slot == NULL || islot != NULL)
1361 fprintf (go_dump_file, "type _%s struct {}\n", type);
1362 return true;
1363 }
1364
1365 /* Output symbols. */
1366
1367 static void
1368 go_finish (const char *filename)
1369 {
1370 class godump_container container;
1371 unsigned int ix;
1372 tree decl;
1373
1374 real_debug_hooks->finish (filename);
1375
1376 container.type_hash = htab_create (100, htab_hash_string,
1377 string_hash_eq, NULL);
1378 container.invalid_hash = htab_create (10, htab_hash_string,
1379 string_hash_eq, NULL);
1380 container.keyword_hash = htab_create (50, htab_hash_string,
1381 string_hash_eq, NULL);
1382 obstack_init (&container.type_obstack);
1383
1384 keyword_hash_init (&container);
1385
1386 FOR_EACH_VEC_SAFE_ELT (queue, ix, decl)
1387 {
1388 switch (TREE_CODE (decl))
1389 {
1390 case FUNCTION_DECL:
1391 go_output_fndecl (&container, decl);
1392 break;
1393
1394 case TYPE_DECL:
1395 go_output_typedef (&container, decl);
1396 break;
1397
1398 case VAR_DECL:
1399 go_output_var (&container, decl);
1400 break;
1401
1402 default:
1403 gcc_unreachable ();
1404 }
1405 }
1406
1407 htab_traverse_noresize (macro_hash, go_print_macro, NULL);
1408
1409 /* To emit dummy definitions. */
1410 container.pot_dummy_types.traverse<godump_container *, find_dummy_types>
1411 (&container);
1412
1413 htab_delete (container.type_hash);
1414 htab_delete (container.invalid_hash);
1415 htab_delete (container.keyword_hash);
1416 obstack_free (&container.type_obstack, NULL);
1417
1418 vec_free (queue);
1419
1420 if (fclose (go_dump_file) != 0)
1421 error ("could not close Go dump file: %m");
1422 go_dump_file = NULL;
1423 }
1424
1425 /* Set up our hooks. */
1426
1427 const struct gcc_debug_hooks *
1428 dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
1429 {
1430 go_dump_file = fopen (filename, "w");
1431 if (go_dump_file == NULL)
1432 {
1433 error ("could not open Go dump file %qs: %m", filename);
1434 return hooks;
1435 }
1436
1437 go_debug_hooks = *hooks;
1438 real_debug_hooks = hooks;
1439
1440 go_debug_hooks.finish = go_finish;
1441 go_debug_hooks.define = go_define;
1442 go_debug_hooks.undef = go_undef;
1443 go_debug_hooks.function_decl = go_function_decl;
1444 go_debug_hooks.early_global_decl = go_early_global_decl;
1445 go_debug_hooks.late_global_decl = go_late_global_decl;
1446 go_debug_hooks.type_decl = go_type_decl;
1447
1448 macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq,
1449 macro_hash_del);
1450
1451 return &go_debug_hooks;
1452 }
1453
1454 #include "gt-godump.h"