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