rs6000.c (output_vec_const_move): Handle little-endian code generation.
[gcc.git] / gcc / godump.c
1 /* Output Go language descriptions of types.
2 Copyright (C) 2008-2014 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor <iant@google.com>.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 /* This file is used during the build process to emit Go language
22 descriptions of declarations from C header files. It uses the
23 debug info hooks to emit the descriptions. The Go language
24 descriptions then become part of the Go runtime support
25 library.
26
27 All global names are output with a leading underscore, so that they
28 are all hidden in Go. */
29
30 #include "config.h"
31 #include "system.h"
32 #include "coretypes.h"
33 #include "diagnostic-core.h"
34 #include "tree.h"
35 #include "ggc.h"
36 #include "pointer-set.h"
37 #include "obstack.h"
38 #include "debug.h"
39 #include "wide-int-print.h"
40
41 /* We dump this information from the debug hooks. This gives us a
42 stable and maintainable API to hook into. In order to work
43 correctly when -g is used, we build our own hooks structure which
44 wraps the hooks we need to change. */
45
46 /* Our debug hooks. This is initialized by dump_go_spec_init. */
47
48 static struct gcc_debug_hooks go_debug_hooks;
49
50 /* The real debug hooks. */
51
52 static const struct gcc_debug_hooks *real_debug_hooks;
53
54 /* The file where we should write information. */
55
56 static FILE *go_dump_file;
57
58 /* A queue of decls to output. */
59
60 static GTY(()) vec<tree, va_gc> *queue;
61
62 /* A hash table of macros we have seen. */
63
64 static htab_t macro_hash;
65
66 /* The type of a value in macro_hash. */
67
68 struct macro_hash_value
69 {
70 /* The name stored in the hash table. */
71 char *name;
72 /* The value of the macro. */
73 char *value;
74 };
75
76 /* Calculate the hash value for an entry in the macro hash table. */
77
78 static hashval_t
79 macro_hash_hashval (const void *val)
80 {
81 const struct macro_hash_value *mhval = (const struct macro_hash_value *) val;
82 return htab_hash_string (mhval->name);
83 }
84
85 /* Compare values in the macro hash table for equality. */
86
87 static int
88 macro_hash_eq (const void *v1, const void *v2)
89 {
90 const struct macro_hash_value *mhv1 = (const struct macro_hash_value *) v1;
91 const struct macro_hash_value *mhv2 = (const struct macro_hash_value *) v2;
92 return strcmp (mhv1->name, mhv2->name) == 0;
93 }
94
95 /* Free values deleted from the macro hash table. */
96
97 static void
98 macro_hash_del (void *v)
99 {
100 struct macro_hash_value *mhv = (struct macro_hash_value *) v;
101 XDELETEVEC (mhv->name);
102 XDELETEVEC (mhv->value);
103 XDELETE (mhv);
104 }
105
106 /* For the string hash tables. */
107
108 static int
109 string_hash_eq (const void *y1, const void *y2)
110 {
111 return strcmp ((const char *) y1, (const char *) y2) == 0;
112 }
113
114 /* A macro definition. */
115
116 static void
117 go_define (unsigned int lineno, const char *buffer)
118 {
119 const char *p;
120 const char *name_end;
121 size_t out_len;
122 char *out_buffer;
123 char *q;
124 bool saw_operand;
125 bool need_operand;
126 struct macro_hash_value *mhval;
127 char *copy;
128 hashval_t hashval;
129 void **slot;
130
131 real_debug_hooks->define (lineno, buffer);
132
133 /* Skip macro functions. */
134 for (p = buffer; *p != '\0' && *p != ' '; ++p)
135 if (*p == '(')
136 return;
137
138 if (*p == '\0')
139 return;
140
141 name_end = p;
142
143 ++p;
144 if (*p == '\0')
145 return;
146
147 copy = XNEWVEC (char, name_end - buffer + 1);
148 memcpy (copy, buffer, name_end - buffer);
149 copy[name_end - buffer] = '\0';
150
151 mhval = XNEW (struct macro_hash_value);
152 mhval->name = copy;
153 mhval->value = NULL;
154
155 hashval = htab_hash_string (copy);
156 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, NO_INSERT);
157
158 /* For simplicity, we force all names to be hidden by adding an
159 initial underscore, and let the user undo this as needed. */
160 out_len = strlen (p) * 2 + 1;
161 out_buffer = XNEWVEC (char, out_len);
162 q = out_buffer;
163 saw_operand = false;
164 need_operand = false;
165 while (*p != '\0')
166 {
167 switch (*p)
168 {
169 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
170 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
171 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
172 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
173 case 'Y': case 'Z':
174 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
175 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
176 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
177 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
178 case 'y': case 'z':
179 case '_':
180 {
181 /* The start of an identifier. Technically we should also
182 worry about UTF-8 identifiers, but they are not a
183 problem for practical uses of -fdump-go-spec so we
184 don't worry about them. */
185 const char *start;
186 char *n;
187 struct macro_hash_value idval;
188
189 if (saw_operand)
190 goto unknown;
191
192 start = p;
193 while (ISALNUM (*p) || *p == '_')
194 ++p;
195 n = XALLOCAVEC (char, p - start + 1);
196 memcpy (n, start, p - start);
197 n[p - start] = '\0';
198 idval.name = n;
199 idval.value = NULL;
200 if (htab_find (macro_hash, &idval) == NULL)
201 {
202 /* This is a reference to a name which was not defined
203 as a macro. */
204 goto unknown;
205 }
206
207 *q++ = '_';
208 memcpy (q, start, p - start);
209 q += p - start;
210
211 saw_operand = true;
212 need_operand = false;
213 }
214 break;
215
216 case '.':
217 if (!ISDIGIT (p[1]))
218 goto unknown;
219 /* Fall through. */
220 case '0': case '1': case '2': case '3': case '4':
221 case '5': case '6': case '7': case '8': case '9':
222 {
223 const char *start;
224 bool is_hex;
225
226 start = p;
227 is_hex = false;
228 if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
229 {
230 p += 2;
231 is_hex = true;
232 }
233 while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
234 || (is_hex
235 && ((*p >= 'a' && *p <= 'f')
236 || (*p >= 'A' && *p <= 'F'))))
237 ++p;
238 memcpy (q, start, p - start);
239 q += p - start;
240 while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
241 || *p == 'f' || *p == 'F'
242 || *p == 'd' || *p == 'D')
243 {
244 /* Go doesn't use any of these trailing type
245 modifiers. */
246 ++p;
247 }
248
249 /* We'll pick up the exponent, if any, as an
250 expression. */
251
252 saw_operand = true;
253 need_operand = false;
254 }
255 break;
256
257 case ' ': case '\t':
258 *q++ = *p++;
259 break;
260
261 case '(':
262 /* Always OK, not part of an operand, presumed to start an
263 operand. */
264 *q++ = *p++;
265 saw_operand = false;
266 need_operand = false;
267 break;
268
269 case ')':
270 /* OK if we don't need an operand, and presumed to indicate
271 an operand. */
272 if (need_operand)
273 goto unknown;
274 *q++ = *p++;
275 saw_operand = true;
276 break;
277
278 case '+': case '-':
279 /* Always OK, but not part of an operand. */
280 *q++ = *p++;
281 saw_operand = false;
282 break;
283
284 case '*': case '/': case '%': case '|': case '&': case '^':
285 /* Must be a binary operator. */
286 if (!saw_operand)
287 goto unknown;
288 *q++ = *p++;
289 saw_operand = false;
290 need_operand = true;
291 break;
292
293 case '=':
294 *q++ = *p++;
295 if (*p != '=')
296 goto unknown;
297 /* Must be a binary operator. */
298 if (!saw_operand)
299 goto unknown;
300 *q++ = *p++;
301 saw_operand = false;
302 need_operand = true;
303 break;
304
305 case '!':
306 *q++ = *p++;
307 if (*p == '=')
308 {
309 /* Must be a binary operator. */
310 if (!saw_operand)
311 goto unknown;
312 *q++ = *p++;
313 saw_operand = false;
314 need_operand = true;
315 }
316 else
317 {
318 /* Must be a unary operator. */
319 if (saw_operand)
320 goto unknown;
321 need_operand = true;
322 }
323 break;
324
325 case '<': case '>':
326 /* Must be a binary operand, may be << or >> or <= or >=. */
327 if (!saw_operand)
328 goto unknown;
329 *q++ = *p++;
330 if (*p == *(p - 1) || *p == '=')
331 *q++ = *p++;
332 saw_operand = false;
333 need_operand = true;
334 break;
335
336 case '~':
337 /* Must be a unary operand, must be translated for Go. */
338 if (saw_operand)
339 goto unknown;
340 *q++ = '^';
341 p++;
342 need_operand = true;
343 break;
344
345 case '"':
346 case '\'':
347 {
348 char quote;
349 int count;
350
351 if (saw_operand)
352 goto unknown;
353 quote = *p;
354 *q++ = *p++;
355 count = 0;
356 while (*p != quote)
357 {
358 int c;
359
360 if (*p == '\0')
361 goto unknown;
362
363 ++count;
364
365 if (*p != '\\')
366 {
367 *q++ = *p++;
368 continue;
369 }
370
371 *q++ = *p++;
372 switch (*p)
373 {
374 case '0': case '1': case '2': case '3':
375 case '4': case '5': case '6': case '7':
376 c = 0;
377 while (*p >= '0' && *p <= '7')
378 {
379 *q++ = *p++;
380 ++c;
381 }
382 /* Go octal characters are always 3
383 digits. */
384 if (c != 3)
385 goto unknown;
386 break;
387
388 case 'x':
389 *q++ = *p++;
390 c = 0;
391 while (ISXDIGIT (*p))
392 {
393 *q++ = *p++;
394 ++c;
395 }
396 /* Go hex characters are always 2 digits. */
397 if (c != 2)
398 goto unknown;
399 break;
400
401 case 'a': case 'b': case 'f': case 'n': case 'r':
402 case 't': case 'v': case '\\': case '\'': case '"':
403 *q++ = *p++;
404 break;
405
406 default:
407 goto unknown;
408 }
409 }
410
411 *q++ = *p++;
412
413 if (quote == '\'' && count != 1)
414 goto unknown;
415
416 saw_operand = true;
417 need_operand = false;
418
419 break;
420 }
421
422 default:
423 goto unknown;
424 }
425 }
426
427 if (need_operand)
428 goto unknown;
429
430 gcc_assert ((size_t) (q - out_buffer) < out_len);
431 *q = '\0';
432
433 mhval->value = out_buffer;
434
435 if (slot == NULL)
436 {
437 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, INSERT);
438 gcc_assert (slot != NULL && *slot == NULL);
439 }
440 else
441 {
442 if (*slot != NULL)
443 macro_hash_del (*slot);
444 }
445
446 *slot = mhval;
447
448 return;
449
450 unknown:
451 fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
452 if (slot != NULL)
453 htab_clear_slot (macro_hash, slot);
454 XDELETEVEC (out_buffer);
455 XDELETEVEC (copy);
456 }
457
458 /* A macro undef. */
459
460 static void
461 go_undef (unsigned int lineno, const char *buffer)
462 {
463 struct macro_hash_value mhval;
464 void **slot;
465
466 real_debug_hooks->undef (lineno, buffer);
467
468 mhval.name = CONST_CAST (char *, buffer);
469 mhval.value = NULL;
470 slot = htab_find_slot (macro_hash, &mhval, NO_INSERT);
471 if (slot != NULL)
472 htab_clear_slot (macro_hash, slot);
473 }
474
475 /* A function or variable decl. */
476
477 static void
478 go_decl (tree decl)
479 {
480 if (!TREE_PUBLIC (decl)
481 || DECL_IS_BUILTIN (decl)
482 || DECL_NAME (decl) == NULL_TREE)
483 return;
484 vec_safe_push (queue, decl);
485 }
486
487 /* A function decl. */
488
489 static void
490 go_function_decl (tree decl)
491 {
492 real_debug_hooks->function_decl (decl);
493 go_decl (decl);
494 }
495
496 /* A global variable decl. */
497
498 static void
499 go_global_decl (tree decl)
500 {
501 real_debug_hooks->global_decl (decl);
502 go_decl (decl);
503 }
504
505 /* A type declaration. */
506
507 static void
508 go_type_decl (tree decl, int local)
509 {
510 real_debug_hooks->type_decl (decl, local);
511
512 if (local || DECL_IS_BUILTIN (decl))
513 return;
514 if (DECL_NAME (decl) == NULL_TREE
515 && (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE
516 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) != IDENTIFIER_NODE)
517 && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
518 return;
519 vec_safe_push (queue, decl);
520 }
521
522 /* A container for the data we pass around when generating information
523 at the end of the compilation. */
524
525 struct godump_container
526 {
527 /* DECLs that we have already seen. */
528 struct pointer_set_t *decls_seen;
529
530 /* Types which may potentially have to be defined as dummy
531 types. */
532 struct pointer_set_t *pot_dummy_types;
533
534 /* Go keywords. */
535 htab_t keyword_hash;
536
537 /* Global type definitions. */
538 htab_t type_hash;
539
540 /* Invalid types. */
541 htab_t invalid_hash;
542
543 /* Obstack used to write out a type definition. */
544 struct obstack type_obstack;
545 };
546
547 /* Append an IDENTIFIER_NODE to OB. */
548
549 static void
550 go_append_string (struct obstack *ob, tree id)
551 {
552 obstack_grow (ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
553 }
554
555 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
556 USE_TYPE_NAME is true if we can simply use a type name here without
557 needing to define it. IS_FUNC_OK is true if we can output a func
558 type here; the "func" keyword will already have been added. Return
559 true if the type can be represented in Go, false otherwise. */
560
561 static bool
562 go_format_type (struct godump_container *container, tree type,
563 bool use_type_name, bool is_func_ok)
564 {
565 bool ret;
566 struct obstack *ob;
567
568 ret = true;
569 ob = &container->type_obstack;
570
571 if (TYPE_NAME (type) != NULL_TREE
572 && (pointer_set_contains (container->decls_seen, type)
573 || pointer_set_contains (container->decls_seen, TYPE_NAME (type)))
574 && (AGGREGATE_TYPE_P (type)
575 || POINTER_TYPE_P (type)
576 || TREE_CODE (type) == FUNCTION_TYPE))
577 {
578 tree name;
579 void **slot;
580
581 name = TYPE_IDENTIFIER (type);
582
583 slot = htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (name),
584 NO_INSERT);
585 if (slot != NULL)
586 ret = false;
587
588 obstack_1grow (ob, '_');
589 go_append_string (ob, name);
590 return ret;
591 }
592
593 pointer_set_insert (container->decls_seen, type);
594
595 switch (TREE_CODE (type))
596 {
597 case ENUMERAL_TYPE:
598 obstack_grow (ob, "int", 3);
599 break;
600
601 case TYPE_DECL:
602 {
603 void **slot;
604
605 slot = htab_find_slot (container->invalid_hash,
606 IDENTIFIER_POINTER (DECL_NAME (type)),
607 NO_INSERT);
608 if (slot != NULL)
609 ret = false;
610
611 obstack_1grow (ob, '_');
612 go_append_string (ob, DECL_NAME (type));
613 }
614 break;
615
616 case INTEGER_TYPE:
617 {
618 const char *s;
619 char buf[100];
620
621 switch (TYPE_PRECISION (type))
622 {
623 case 8:
624 s = TYPE_UNSIGNED (type) ? "uint8" : "int8";
625 break;
626 case 16:
627 s = TYPE_UNSIGNED (type) ? "uint16" : "int16";
628 break;
629 case 32:
630 s = TYPE_UNSIGNED (type) ? "uint32" : "int32";
631 break;
632 case 64:
633 s = TYPE_UNSIGNED (type) ? "uint64" : "int64";
634 break;
635 default:
636 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
637 TYPE_PRECISION (type),
638 TYPE_UNSIGNED (type) ? "u" : "");
639 s = buf;
640 ret = false;
641 break;
642 }
643 obstack_grow (ob, s, strlen (s));
644 }
645 break;
646
647 case REAL_TYPE:
648 {
649 const char *s;
650 char buf[100];
651
652 switch (TYPE_PRECISION (type))
653 {
654 case 32:
655 s = "float32";
656 break;
657 case 64:
658 s = "float64";
659 break;
660 default:
661 snprintf (buf, sizeof buf, "INVALID-float-%u",
662 TYPE_PRECISION (type));
663 s = buf;
664 ret = false;
665 break;
666 }
667 obstack_grow (ob, s, strlen (s));
668 }
669 break;
670
671 case BOOLEAN_TYPE:
672 obstack_grow (ob, "bool", 4);
673 break;
674
675 case POINTER_TYPE:
676 if (use_type_name
677 && TYPE_NAME (TREE_TYPE (type)) != NULL_TREE
678 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))
679 || (POINTER_TYPE_P (TREE_TYPE (type))
680 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type)))
681 == FUNCTION_TYPE))))
682 {
683 tree name;
684 void **slot;
685
686 name = TYPE_IDENTIFIER (TREE_TYPE (type));
687
688 slot = htab_find_slot (container->invalid_hash,
689 IDENTIFIER_POINTER (name), NO_INSERT);
690 if (slot != NULL)
691 ret = false;
692
693 obstack_grow (ob, "*_", 2);
694 go_append_string (ob, name);
695
696 /* The pointer here can be used without the struct or union
697 definition. So this struct or union is a potential dummy
698 type. */
699 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
700 pointer_set_insert (container->pot_dummy_types,
701 IDENTIFIER_POINTER (name));
702
703 return ret;
704 }
705 if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
706 obstack_grow (ob, "func", 4);
707 else
708 obstack_1grow (ob, '*');
709 if (VOID_TYPE_P (TREE_TYPE (type)))
710 obstack_grow (ob, "byte", 4);
711 else
712 {
713 if (!go_format_type (container, TREE_TYPE (type), use_type_name,
714 true))
715 ret = false;
716 }
717 break;
718
719 case ARRAY_TYPE:
720 obstack_1grow (ob, '[');
721 if (TYPE_DOMAIN (type) != NULL_TREE
722 && TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
723 && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
724 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
725 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0
726 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
727 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
728 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
729 {
730 char buf[100];
731
732 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
733 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type))));
734 obstack_grow (ob, buf, strlen (buf));
735 }
736 obstack_1grow (ob, ']');
737 if (!go_format_type (container, TREE_TYPE (type), use_type_name, false))
738 ret = false;
739 break;
740
741 case UNION_TYPE:
742 case RECORD_TYPE:
743 {
744 tree field;
745 int i;
746
747 obstack_grow (ob, "struct { ", 9);
748 i = 0;
749 for (field = TYPE_FIELDS (type);
750 field != NULL_TREE;
751 field = TREE_CHAIN (field))
752 {
753 struct obstack hold_type_obstack;
754 bool field_ok;
755
756 if (TREE_CODE (type) == UNION_TYPE)
757 {
758 hold_type_obstack = container->type_obstack;
759 obstack_init (&container->type_obstack);
760 }
761
762 field_ok = true;
763
764 if (DECL_NAME (field) == NULL)
765 {
766 char buf[100];
767
768 obstack_grow (ob, "Godump_", 7);
769 snprintf (buf, sizeof buf, "%d", i);
770 obstack_grow (ob, buf, strlen (buf));
771 i++;
772 }
773 else
774 {
775 const char *var_name;
776 void **slot;
777
778 /* Start variable name with an underscore if a keyword. */
779 var_name = IDENTIFIER_POINTER (DECL_NAME (field));
780 slot = htab_find_slot (container->keyword_hash, var_name,
781 NO_INSERT);
782 if (slot != NULL)
783 obstack_1grow (ob, '_');
784 go_append_string (ob, DECL_NAME (field));
785 }
786 obstack_1grow (ob, ' ');
787 if (DECL_BIT_FIELD (field))
788 {
789 obstack_grow (ob, "INVALID-bit-field", 17);
790 field_ok = false;
791 }
792 else
793 {
794 /* Do not expand type if a record or union type or a
795 function pointer. */
796 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
797 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
798 || (POINTER_TYPE_P (TREE_TYPE (field))
799 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
800 == FUNCTION_TYPE))))
801 {
802 tree name;
803 void **slot;
804
805 name = TYPE_IDENTIFIER (TREE_TYPE (field));
806
807 slot = htab_find_slot (container->invalid_hash,
808 IDENTIFIER_POINTER (name),
809 NO_INSERT);
810 if (slot != NULL)
811 field_ok = false;
812
813 obstack_1grow (ob, '_');
814 go_append_string (ob, name);
815 }
816 else
817 {
818 if (!go_format_type (container, TREE_TYPE (field), true,
819 false))
820 field_ok = false;
821 }
822 }
823 obstack_grow (ob, "; ", 2);
824
825 /* Only output the first successful field of a union, and
826 hope for the best. */
827 if (TREE_CODE (type) == UNION_TYPE)
828 {
829 if (!field_ok && TREE_CHAIN (field) == NULL_TREE)
830 {
831 field_ok = true;
832 ret = false;
833 }
834 if (field_ok)
835 {
836 unsigned int sz;
837
838 sz = obstack_object_size (&container->type_obstack);
839 obstack_grow (&hold_type_obstack,
840 obstack_base (&container->type_obstack),
841 sz);
842 }
843 obstack_free (&container->type_obstack, NULL);
844 container->type_obstack = hold_type_obstack;
845 if (field_ok)
846 break;
847 }
848 else
849 {
850 if (!field_ok)
851 ret = false;
852 }
853 }
854 obstack_1grow (ob, '}');
855 }
856 break;
857
858 case FUNCTION_TYPE:
859 {
860 tree arg_type;
861 bool is_varargs;
862 tree result;
863 function_args_iterator iter;
864 bool seen_arg;
865
866 /* Go has no way to write a type which is a function but not a
867 pointer to a function. */
868 if (!is_func_ok)
869 {
870 obstack_grow (ob, "func*", 5);
871 ret = false;
872 }
873
874 obstack_1grow (ob, '(');
875 is_varargs = stdarg_p (type);
876 seen_arg = false;
877 FOREACH_FUNCTION_ARGS (type, arg_type, iter)
878 {
879 if (VOID_TYPE_P (arg_type))
880 break;
881 if (seen_arg)
882 obstack_grow (ob, ", ", 2);
883 if (!go_format_type (container, arg_type, true, false))
884 ret = false;
885 seen_arg = true;
886 }
887 if (is_varargs)
888 {
889 if (prototype_p (type))
890 obstack_grow (ob, ", ", 2);
891 obstack_grow (ob, "...interface{}", 14);
892 }
893 obstack_1grow (ob, ')');
894
895 result = TREE_TYPE (type);
896 if (!VOID_TYPE_P (result))
897 {
898 obstack_1grow (ob, ' ');
899 if (!go_format_type (container, result, use_type_name, false))
900 ret = false;
901 }
902 }
903 break;
904
905 default:
906 obstack_grow (ob, "INVALID-type", 12);
907 ret = false;
908 break;
909 }
910
911 return ret;
912 }
913
914 /* Output the type which was built on the type obstack, and then free
915 it. */
916
917 static void
918 go_output_type (struct godump_container *container)
919 {
920 struct obstack *ob;
921
922 ob = &container->type_obstack;
923 obstack_1grow (ob, '\0');
924 fputs (obstack_base (ob), go_dump_file);
925 obstack_free (ob, obstack_base (ob));
926 }
927
928 /* Output a function declaration. */
929
930 static void
931 go_output_fndecl (struct godump_container *container, tree decl)
932 {
933 if (!go_format_type (container, TREE_TYPE (decl), false, true))
934 fprintf (go_dump_file, "// ");
935 fprintf (go_dump_file, "func _%s ",
936 IDENTIFIER_POINTER (DECL_NAME (decl)));
937 go_output_type (container);
938 fprintf (go_dump_file, " __asm__(\"%s\")\n",
939 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
940 }
941
942 /* Output a typedef or something like a struct definition. */
943
944 static void
945 go_output_typedef (struct godump_container *container, tree decl)
946 {
947 /* If we have an enum type, output the enum constants
948 separately. */
949 if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
950 && TYPE_SIZE (TREE_TYPE (decl)) != 0
951 && !pointer_set_contains (container->decls_seen, TREE_TYPE (decl))
952 && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
953 || !pointer_set_contains (container->decls_seen,
954 TYPE_CANONICAL (TREE_TYPE (decl)))))
955 {
956 tree element;
957
958 for (element = TYPE_VALUES (TREE_TYPE (decl));
959 element != NULL_TREE;
960 element = TREE_CHAIN (element))
961 {
962 const char *name;
963 struct macro_hash_value *mhval;
964 void **slot;
965 char buf[WIDE_INT_PRINT_BUFFER_SIZE];
966
967 name = IDENTIFIER_POINTER (TREE_PURPOSE (element));
968
969 /* Sometimes a name will be defined as both an enum constant
970 and a macro. Avoid duplicate definition errors by
971 treating enum constants as macros. */
972 mhval = XNEW (struct macro_hash_value);
973 mhval->name = xstrdup (name);
974 mhval->value = NULL;
975 slot = htab_find_slot (macro_hash, mhval, INSERT);
976 if (*slot != NULL)
977 macro_hash_del (*slot);
978
979 if (tree_fits_shwi_p (TREE_VALUE (element)))
980 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC,
981 tree_to_shwi (TREE_VALUE (element)));
982 else if (tree_fits_uhwi_p (TREE_VALUE (element)))
983 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_UNSIGNED,
984 tree_to_uhwi (TREE_VALUE (element)));
985 else
986 print_hex (element, buf);
987
988 mhval->value = xstrdup (buf);
989 *slot = mhval;
990 }
991 pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
992 if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
993 pointer_set_insert (container->decls_seen,
994 TYPE_CANONICAL (TREE_TYPE (decl)));
995 }
996
997 if (DECL_NAME (decl) != NULL_TREE)
998 {
999 void **slot;
1000 const char *type;
1001
1002 type = IDENTIFIER_POINTER (DECL_NAME (decl));
1003 /* If type defined already, skip. */
1004 slot = htab_find_slot (container->type_hash, type, INSERT);
1005 if (*slot != NULL)
1006 return;
1007 *slot = CONST_CAST (void *, (const void *) type);
1008
1009 if (!go_format_type (container, TREE_TYPE (decl), false, false))
1010 {
1011 fprintf (go_dump_file, "// ");
1012 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1013 *slot = CONST_CAST (void *, (const void *) type);
1014 }
1015 fprintf (go_dump_file, "type _%s ",
1016 IDENTIFIER_POINTER (DECL_NAME (decl)));
1017 go_output_type (container);
1018
1019 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1020 {
1021 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
1022
1023 if (size > 0)
1024 fprintf (go_dump_file,
1025 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1026 IDENTIFIER_POINTER (DECL_NAME (decl)),
1027 size);
1028 }
1029
1030 pointer_set_insert (container->decls_seen, decl);
1031 }
1032 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1033 {
1034 void **slot;
1035 const char *type;
1036 HOST_WIDE_INT size;
1037
1038 type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
1039 /* If type defined already, skip. */
1040 slot = htab_find_slot (container->type_hash, type, INSERT);
1041 if (*slot != NULL)
1042 return;
1043 *slot = CONST_CAST (void *, (const void *) type);
1044
1045 if (!go_format_type (container, TREE_TYPE (decl), false, false))
1046 {
1047 fprintf (go_dump_file, "// ");
1048 slot = htab_find_slot (container->invalid_hash, type, INSERT);
1049 *slot = CONST_CAST (void *, (const void *) type);
1050 }
1051 fprintf (go_dump_file, "type _%s ",
1052 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
1053 go_output_type (container);
1054
1055 size = int_size_in_bytes (TREE_TYPE (decl));
1056 if (size > 0)
1057 fprintf (go_dump_file,
1058 "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1059 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))),
1060 size);
1061 }
1062 else
1063 return;
1064
1065 fprintf (go_dump_file, "\n");
1066 }
1067
1068 /* Output a variable. */
1069
1070 static void
1071 go_output_var (struct godump_container *container, tree decl)
1072 {
1073 bool is_valid;
1074
1075 if (pointer_set_contains (container->decls_seen, decl)
1076 || pointer_set_contains (container->decls_seen, DECL_NAME (decl)))
1077 return;
1078 pointer_set_insert (container->decls_seen, decl);
1079 pointer_set_insert (container->decls_seen, DECL_NAME (decl));
1080
1081 is_valid = go_format_type (container, TREE_TYPE (decl), true, false);
1082 if (is_valid
1083 && htab_find_slot (container->type_hash,
1084 IDENTIFIER_POINTER (DECL_NAME (decl)),
1085 NO_INSERT) != NULL)
1086 {
1087 /* There is already a type with this name, probably from a
1088 struct tag. Prefer the type to the variable. */
1089 is_valid = false;
1090 }
1091 if (!is_valid)
1092 fprintf (go_dump_file, "// ");
1093
1094 fprintf (go_dump_file, "var _%s ",
1095 IDENTIFIER_POINTER (DECL_NAME (decl)));
1096 go_output_type (container);
1097 fprintf (go_dump_file, "\n");
1098
1099 /* Sometimes an extern variable is declared with an unknown struct
1100 type. */
1101 if (TYPE_NAME (TREE_TYPE (decl)) != NULL_TREE
1102 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1103 {
1104 tree type_name = TYPE_NAME (TREE_TYPE (decl));
1105 if (TREE_CODE (type_name) == IDENTIFIER_NODE)
1106 pointer_set_insert (container->pot_dummy_types,
1107 IDENTIFIER_POINTER (type_name));
1108 else if (TREE_CODE (type_name) == TYPE_DECL)
1109 pointer_set_insert (container->pot_dummy_types,
1110 IDENTIFIER_POINTER (DECL_NAME (type_name)));
1111 }
1112 }
1113
1114 /* Output the final value of a preprocessor macro or enum constant.
1115 This is called via htab_traverse_noresize. */
1116
1117 static int
1118 go_print_macro (void **slot, void *arg ATTRIBUTE_UNUSED)
1119 {
1120 struct macro_hash_value *mhval = (struct macro_hash_value *) *slot;
1121 fprintf (go_dump_file, "const _%s = %s\n", mhval->name, mhval->value);
1122 return 1;
1123 }
1124
1125 /* Build a hash table with the Go keywords. */
1126
1127 static const char * const keywords[] = {
1128 "__asm__", "break", "case", "chan", "const", "continue", "default",
1129 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1130 "import", "interface", "map", "package", "range", "return", "select",
1131 "struct", "switch", "type", "var"
1132 };
1133
1134 static void
1135 keyword_hash_init (struct godump_container *container)
1136 {
1137 size_t i;
1138 size_t count = sizeof (keywords) / sizeof (keywords[0]);
1139 void **slot;
1140
1141 for (i = 0; i < count; i++)
1142 {
1143 slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
1144 *slot = CONST_CAST (void *, (const void *) keywords[i]);
1145 }
1146 }
1147
1148 /* Traversing the pot_dummy_types and seeing which types are present
1149 in the global types hash table and creating dummy definitions if
1150 not found. This function is invoked by pointer_set_traverse. */
1151
1152 static bool
1153 find_dummy_types (const void *ptr, void *adata)
1154 {
1155 struct godump_container *data = (struct godump_container *) adata;
1156 const char *type = (const char *) ptr;
1157 void **slot;
1158 void **islot;
1159
1160 slot = htab_find_slot (data->type_hash, type, NO_INSERT);
1161 islot = htab_find_slot (data->invalid_hash, type, NO_INSERT);
1162 if (slot == NULL || islot != NULL)
1163 fprintf (go_dump_file, "type _%s struct {}\n", type);
1164 return true;
1165 }
1166
1167 /* Output symbols. */
1168
1169 static void
1170 go_finish (const char *filename)
1171 {
1172 struct godump_container container;
1173 unsigned int ix;
1174 tree decl;
1175
1176 real_debug_hooks->finish (filename);
1177
1178 container.decls_seen = pointer_set_create ();
1179 container.pot_dummy_types = pointer_set_create ();
1180 container.type_hash = htab_create (100, htab_hash_string,
1181 string_hash_eq, NULL);
1182 container.invalid_hash = htab_create (10, htab_hash_string,
1183 string_hash_eq, NULL);
1184 container.keyword_hash = htab_create (50, htab_hash_string,
1185 string_hash_eq, NULL);
1186 obstack_init (&container.type_obstack);
1187
1188 keyword_hash_init (&container);
1189
1190 FOR_EACH_VEC_SAFE_ELT (queue, ix, decl)
1191 {
1192 switch (TREE_CODE (decl))
1193 {
1194 case FUNCTION_DECL:
1195 go_output_fndecl (&container, decl);
1196 break;
1197
1198 case TYPE_DECL:
1199 go_output_typedef (&container, decl);
1200 break;
1201
1202 case VAR_DECL:
1203 go_output_var (&container, decl);
1204 break;
1205
1206 default:
1207 gcc_unreachable ();
1208 }
1209 }
1210
1211 htab_traverse_noresize (macro_hash, go_print_macro, NULL);
1212
1213 /* To emit dummy definitions. */
1214 pointer_set_traverse (container.pot_dummy_types, find_dummy_types,
1215 (void *) &container);
1216
1217 pointer_set_destroy (container.decls_seen);
1218 pointer_set_destroy (container.pot_dummy_types);
1219 htab_delete (container.type_hash);
1220 htab_delete (container.invalid_hash);
1221 htab_delete (container.keyword_hash);
1222 obstack_free (&container.type_obstack, NULL);
1223
1224 vec_free (queue);
1225
1226 if (fclose (go_dump_file) != 0)
1227 error ("could not close Go dump file: %m");
1228 go_dump_file = NULL;
1229 }
1230
1231 /* Set up our hooks. */
1232
1233 const struct gcc_debug_hooks *
1234 dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
1235 {
1236 go_dump_file = fopen (filename, "w");
1237 if (go_dump_file == NULL)
1238 {
1239 error ("could not open Go dump file %qs: %m", filename);
1240 return hooks;
1241 }
1242
1243 go_debug_hooks = *hooks;
1244 real_debug_hooks = hooks;
1245
1246 go_debug_hooks.finish = go_finish;
1247 go_debug_hooks.define = go_define;
1248 go_debug_hooks.undef = go_undef;
1249 go_debug_hooks.function_decl = go_function_decl;
1250 go_debug_hooks.global_decl = go_global_decl;
1251 go_debug_hooks.type_decl = go_type_decl;
1252
1253 macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq,
1254 macro_hash_del);
1255
1256 return &go_debug_hooks;
1257 }
1258
1259 #include "gt-godump.h"