pt.c (build_non_dependent_expr): Don't check null_ptr_cst_p, do call maybe_constant_v...
[gcc.git] / gcc / godump.c
1 /* Output Go language descriptions of types.
2 Copyright (C) 2008, 2009, 2010, 2011 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
40 /* We dump this information from the debug hooks. This gives us a
41 stable and maintainable API to hook into. In order to work
42 correctly when -g is used, we build our own hooks structure which
43 wraps the hooks we need to change. */
44
45 /* Our debug hooks. This is initialized by dump_go_spec_init. */
46
47 static struct gcc_debug_hooks go_debug_hooks;
48
49 /* The real debug hooks. */
50
51 static const struct gcc_debug_hooks *real_debug_hooks;
52
53 /* The file where we should write information. */
54
55 static FILE *go_dump_file;
56
57 /* A queue of decls to output. */
58
59 static GTY(()) VEC(tree,gc) *queue;
60
61 /* A hash table of macros we have seen. */
62
63 static htab_t macro_hash;
64
65 /* For the hash tables. */
66
67 static int
68 string_hash_eq (const void *y1, const void *y2)
69 {
70 return strcmp ((const char *) y1, (const char *) y2) == 0;
71 }
72
73 /* A macro definition. */
74
75 static void
76 go_define (unsigned int lineno, const char *buffer)
77 {
78 const char *p;
79 const char *name_end;
80 char *out_buffer;
81 char *q;
82 bool saw_operand;
83 bool need_operand;
84 char *copy;
85 hashval_t hashval;
86 void **slot;
87
88 real_debug_hooks->define (lineno, buffer);
89
90 /* Skip macro functions. */
91 for (p = buffer; *p != '\0' && *p != ' '; ++p)
92 if (*p == '(')
93 return;
94
95 if (*p == '\0')
96 return;
97
98 name_end = p;
99
100 ++p;
101 if (*p == '\0')
102 return;
103
104 copy = XNEWVEC (char, name_end - buffer + 1);
105 memcpy (copy, buffer, name_end - buffer);
106 copy[name_end - buffer] = '\0';
107
108 hashval = htab_hash_string (copy);
109 slot = htab_find_slot_with_hash (macro_hash, copy, hashval, NO_INSERT);
110 if (slot != NULL)
111 {
112 XDELETEVEC (copy);
113 return;
114 }
115
116 /* For simplicity, we force all names to be hidden by adding an
117 initial underscore, and let the user undo this as needed. */
118 out_buffer = XNEWVEC (char, strlen (p) * 2 + 1);
119 q = out_buffer;
120 saw_operand = false;
121 need_operand = false;
122 while (*p != '\0')
123 {
124 switch (*p)
125 {
126 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
127 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
128 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
129 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
130 case 'Y': case 'Z':
131 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
132 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
133 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
134 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
135 case 'y': case 'z':
136 case '_':
137 {
138 /* The start of an identifier. Technically we should also
139 worry about UTF-8 identifiers, but they are not a
140 problem for practical uses of -fdump-go-spec so we
141 don't worry about them. */
142 const char *start;
143 char *n;
144
145 if (saw_operand)
146 goto unknown;
147
148 start = p;
149 while (ISALNUM (*p) || *p == '_')
150 ++p;
151 n = XALLOCAVEC (char, p - start + 1);
152 memcpy (n, start, p - start);
153 n[p - start] = '\0';
154 slot = htab_find_slot (macro_hash, n, NO_INSERT);
155 if (slot == NULL || *slot == NULL)
156 {
157 /* This is a reference to a name which was not defined
158 as a macro. */
159 goto unknown;
160 }
161
162 *q++ = '_';
163 memcpy (q, start, p - start);
164 q += p - start;
165
166 saw_operand = true;
167 need_operand = false;
168 }
169 break;
170
171 case '.':
172 if (!ISDIGIT (p[1]))
173 goto unknown;
174 /* Fall through. */
175 case '0': case '1': case '2': case '3': case '4':
176 case '5': case '6': case '7': case '8': case '9':
177 {
178 const char *start;
179 bool is_hex;
180
181 start = p;
182 is_hex = false;
183 if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
184 {
185 p += 2;
186 is_hex = true;
187 }
188 while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
189 || (is_hex
190 && ((*p >= 'a' && *p <= 'f')
191 || (*p >= 'A' && *p <= 'F'))))
192 ++p;
193 memcpy (q, start, p - start);
194 q += p - start;
195 while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
196 || *p == 'f' || *p == 'F'
197 || *p == 'd' || *p == 'D')
198 {
199 /* Go doesn't use any of these trailing type
200 modifiers. */
201 ++p;
202 }
203
204 /* We'll pick up the exponent, if any, as an
205 expression. */
206
207 saw_operand = true;
208 need_operand = false;
209 }
210 break;
211
212 case ' ': case '\t':
213 *q++ = *p++;
214 break;
215
216 case '(':
217 /* Always OK, not part of an operand, presumed to start an
218 operand. */
219 *q++ = *p++;
220 saw_operand = false;
221 need_operand = false;
222 break;
223
224 case ')':
225 /* OK if we don't need an operand, and presumed to indicate
226 an operand. */
227 if (need_operand)
228 goto unknown;
229 *q++ = *p++;
230 saw_operand = true;
231 break;
232
233 case '+': case '-':
234 /* Always OK, but not part of an operand. */
235 *q++ = *p++;
236 saw_operand = false;
237 break;
238
239 case '*': case '/': case '%': case '|': case '&': case '^':
240 /* Must be a binary operator. */
241 if (!saw_operand)
242 goto unknown;
243 *q++ = *p++;
244 saw_operand = false;
245 need_operand = true;
246 break;
247
248 case '=':
249 *q++ = *p++;
250 if (*p != '=')
251 goto unknown;
252 /* Must be a binary operator. */
253 if (!saw_operand)
254 goto unknown;
255 *q++ = *p++;
256 saw_operand = false;
257 need_operand = true;
258 break;
259
260 case '!':
261 *q++ = *p++;
262 if (*p == '=')
263 {
264 /* Must be a binary operator. */
265 if (!saw_operand)
266 goto unknown;
267 *q++ = *p++;
268 saw_operand = false;
269 need_operand = true;
270 }
271 else
272 {
273 /* Must be a unary operator. */
274 if (saw_operand)
275 goto unknown;
276 need_operand = true;
277 }
278 break;
279
280 case '<': case '>':
281 /* Must be a binary operand, may be << or >> or <= or >=. */
282 if (!saw_operand)
283 goto unknown;
284 *q++ = *p++;
285 if (*p == *(p - 1) || *p == '=')
286 *q++ = *p++;
287 saw_operand = false;
288 need_operand = true;
289 break;
290
291 case '~':
292 /* Must be a unary operand, must be translated for Go. */
293 if (saw_operand)
294 goto unknown;
295 *q++ = '^';
296 p++;
297 need_operand = true;
298 break;
299
300 case '"':
301 case '\'':
302 {
303 char quote = *p;
304 *q++ = *p++;
305 while (*p != quote)
306 {
307 int c;
308
309 if (*p == '\0')
310 goto unknown;
311
312 if (*p != '\\')
313 {
314 *q++ = *p++;
315 continue;
316 }
317
318 *q++ = *p++;
319 switch (*p)
320 {
321 case '0': case '1': case '2': case '3':
322 case '4': case '5': case '6': case '7':
323 c = 0;
324 while (*p >= '0' && *p <= '7')
325 {
326 *q++ = *p++;
327 ++c;
328 }
329 /* Go octal characters are always 3
330 digits. */
331 if (c != 3)
332 goto unknown;
333 break;
334
335 case 'x':
336 *q++ = *p++;
337 c = 0;
338 while (ISXDIGIT (*p))
339 {
340 *q++ = *p++;
341 ++c;
342 }
343 /* Go hex characters are always 2 digits. */
344 if (c != 2)
345 goto unknown;
346 break;
347
348 case 'a': case 'b': case 'f': case 'n': case 'r':
349 case 't': case 'v': case '\\': case '\'': case '"':
350 *q++ = *p++;
351 break;
352
353 default:
354 goto unknown;
355 }
356 }
357 *q++ = *p++;
358 break;
359 }
360
361 default:
362 goto unknown;
363 }
364 }
365
366 if (need_operand)
367 goto unknown;
368
369 *q = '\0';
370
371 slot = htab_find_slot_with_hash (macro_hash, copy, hashval, INSERT);
372 *slot = copy;
373
374 fprintf (go_dump_file, "const _%s = %s\n", copy, out_buffer);
375
376 XDELETEVEC (out_buffer);
377 return;
378
379 unknown:
380 fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
381 XDELETEVEC (out_buffer);
382 XDELETEVEC (copy);
383 }
384
385 /* A macro undef. */
386
387 static void
388 go_undef (unsigned int lineno, const char *buffer)
389 {
390 void **slot;
391
392 real_debug_hooks->undef (lineno, buffer);
393
394 slot = htab_find_slot (macro_hash, buffer, NO_INSERT);
395 if (slot == NULL)
396 return;
397 fprintf (go_dump_file, "// undef _%s\n", buffer);
398 /* We don't delete the slot from the hash table because that will
399 cause a duplicate const definition. */
400 }
401
402 /* A function or variable decl. */
403
404 static void
405 go_decl (tree decl)
406 {
407 if (!TREE_PUBLIC (decl)
408 || DECL_IS_BUILTIN (decl)
409 || DECL_NAME (decl) == NULL_TREE)
410 return;
411 VEC_safe_push (tree, gc, queue, decl);
412 }
413
414 /* A function decl. */
415
416 static void
417 go_function_decl (tree decl)
418 {
419 real_debug_hooks->function_decl (decl);
420 go_decl (decl);
421 }
422
423 /* A global variable decl. */
424
425 static void
426 go_global_decl (tree decl)
427 {
428 real_debug_hooks->global_decl (decl);
429 go_decl (decl);
430 }
431
432 /* A type declaration. */
433
434 static void
435 go_type_decl (tree decl, int local)
436 {
437 real_debug_hooks->type_decl (decl, local);
438
439 if (local || DECL_IS_BUILTIN (decl))
440 return;
441 if (DECL_NAME (decl) == NULL_TREE
442 && (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE
443 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) != IDENTIFIER_NODE)
444 && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
445 return;
446 VEC_safe_push (tree, gc, queue, decl);
447 }
448
449 /* A container for the data we pass around when generating information
450 at the end of the compilation. */
451
452 struct godump_container
453 {
454 /* DECLs that we have already seen. */
455 struct pointer_set_t *decls_seen;
456
457 /* Types which may potentially have to be defined as dummy
458 types. */
459 struct pointer_set_t *pot_dummy_types;
460
461 /* Go keywords. */
462 htab_t keyword_hash;
463
464 /* Global type definitions. */
465 htab_t type_hash;
466
467 /* Obstack used to write out a type definition. */
468 struct obstack type_obstack;
469 };
470
471 /* Append an IDENTIFIER_NODE to OB. */
472
473 static void
474 go_append_string (struct obstack *ob, tree id)
475 {
476 obstack_grow (ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
477 }
478
479 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
480 USE_TYPE_NAME is true if we can simply use a type name here without
481 needing to define it. IS_FUNC_OK is true if we can output a func
482 type here; the "func" keyword will already have been added. Return
483 true if the type can be represented in Go, false otherwise. */
484
485 static bool
486 go_format_type (struct godump_container *container, tree type,
487 bool use_type_name, bool is_func_ok)
488 {
489 bool ret;
490 struct obstack *ob;
491
492 ret = true;
493 ob = &container->type_obstack;
494
495 if (TYPE_NAME (type) != NULL_TREE
496 && (pointer_set_contains (container->decls_seen, type)
497 || pointer_set_contains (container->decls_seen, TYPE_NAME (type)))
498 && (AGGREGATE_TYPE_P (type)
499 || POINTER_TYPE_P (type)
500 || TREE_CODE (type) == FUNCTION_TYPE))
501 {
502 tree name;
503
504 name = TYPE_NAME (type);
505 if (TREE_CODE (name) == IDENTIFIER_NODE)
506 {
507 obstack_1grow (ob, '_');
508 go_append_string (ob, name);
509 return ret;
510 }
511 else if (TREE_CODE (name) == TYPE_DECL)
512 {
513 obstack_1grow (ob, '_');
514 go_append_string (ob, DECL_NAME (name));
515 return ret;
516 }
517 }
518
519 pointer_set_insert (container->decls_seen, type);
520
521 switch (TREE_CODE (type))
522 {
523 case ENUMERAL_TYPE:
524 obstack_grow (ob, "int", 3);
525 break;
526
527 case TYPE_DECL:
528 obstack_1grow (ob, '_');
529 go_append_string (ob, DECL_NAME (type));
530 break;
531
532 case INTEGER_TYPE:
533 {
534 const char *s;
535 char buf[100];
536
537 switch (TYPE_PRECISION (type))
538 {
539 case 8:
540 s = TYPE_UNSIGNED (type) ? "uint8" : "int8";
541 break;
542 case 16:
543 s = TYPE_UNSIGNED (type) ? "uint16" : "int16";
544 break;
545 case 32:
546 s = TYPE_UNSIGNED (type) ? "uint32" : "int32";
547 break;
548 case 64:
549 s = TYPE_UNSIGNED (type) ? "uint64" : "int64";
550 break;
551 default:
552 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
553 TYPE_PRECISION (type),
554 TYPE_UNSIGNED (type) ? "u" : "");
555 s = buf;
556 ret = false;
557 break;
558 }
559 obstack_grow (ob, s, strlen (s));
560 }
561 break;
562
563 case REAL_TYPE:
564 {
565 const char *s;
566 char buf[100];
567
568 switch (TYPE_PRECISION (type))
569 {
570 case 32:
571 s = "float32";
572 break;
573 case 64:
574 s = "float64";
575 break;
576 default:
577 snprintf (buf, sizeof buf, "INVALID-float-%u",
578 TYPE_PRECISION (type));
579 s = buf;
580 ret = false;
581 break;
582 }
583 obstack_grow (ob, s, strlen (s));
584 }
585 break;
586
587 case BOOLEAN_TYPE:
588 obstack_grow (ob, "bool", 4);
589 break;
590
591 case POINTER_TYPE:
592 if (use_type_name
593 && TYPE_NAME (TREE_TYPE (type)) != NULL_TREE
594 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))
595 || (POINTER_TYPE_P (TREE_TYPE (type))
596 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type)))
597 == FUNCTION_TYPE))))
598 {
599 tree name;
600
601 name = TYPE_NAME (TREE_TYPE (type));
602 if (TREE_CODE (name) == IDENTIFIER_NODE)
603 {
604 obstack_grow (ob, "*_", 2);
605 go_append_string (ob, name);
606
607 /* The pointer here can be used without the struct or
608 union definition. So this struct or union is a a
609 potential dummy type. */
610 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
611 pointer_set_insert (container->pot_dummy_types,
612 IDENTIFIER_POINTER (name));
613
614 return ret;
615 }
616 else if (TREE_CODE (name) == TYPE_DECL)
617 {
618 obstack_grow (ob, "*_", 2);
619 go_append_string (ob, DECL_NAME (name));
620 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
621 pointer_set_insert (container->pot_dummy_types,
622 IDENTIFIER_POINTER (DECL_NAME (name)));
623 return ret;
624 }
625 }
626 if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
627 obstack_grow (ob, "func", 4);
628 else
629 obstack_1grow (ob, '*');
630 if (VOID_TYPE_P (TREE_TYPE (type)))
631 obstack_grow (ob, "byte", 4);
632 else
633 {
634 if (!go_format_type (container, TREE_TYPE (type), use_type_name,
635 true))
636 ret = false;
637 }
638 break;
639
640 case ARRAY_TYPE:
641 obstack_1grow (ob, '[');
642 if (TYPE_DOMAIN (type) != NULL_TREE
643 && TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
644 && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
645 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
646 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0
647 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
648 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
649 && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0))
650 {
651 char buf[100];
652
653 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
654 tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0));
655 obstack_grow (ob, buf, strlen (buf));
656 }
657 obstack_1grow (ob, ']');
658 if (!go_format_type (container, TREE_TYPE (type), use_type_name, false))
659 ret = false;
660 break;
661
662 case UNION_TYPE:
663 case RECORD_TYPE:
664 {
665 tree field;
666 int i;
667
668 obstack_grow (ob, "struct { ", 9);
669 i = 0;
670 for (field = TYPE_FIELDS (type);
671 field != NULL_TREE;
672 field = TREE_CHAIN (field))
673 {
674 if (DECL_NAME (field) == NULL)
675 {
676 char buf[100];
677
678 obstack_grow (ob, "Godump_", 2);
679 snprintf (buf, sizeof buf, "%d", i);
680 obstack_grow (ob, buf, strlen (buf));
681 i++;
682 }
683 else
684 {
685 const char *var_name;
686 void **slot;
687
688 /* Start variable name with an underscore if a keyword. */
689 var_name = IDENTIFIER_POINTER (DECL_NAME (field));
690 slot = htab_find_slot (container->keyword_hash, var_name,
691 NO_INSERT);
692 if (slot != NULL)
693 obstack_1grow (ob, '_');
694 go_append_string (ob, DECL_NAME (field));
695 }
696 obstack_1grow (ob, ' ');
697 if (DECL_BIT_FIELD (field))
698 {
699 obstack_grow (ob, "INVALID-bit-field", 17);
700 ret = false;
701 }
702 else
703 {
704 /* Do not expand type if a record or union type or a
705 function pointer. */
706 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
707 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
708 || (POINTER_TYPE_P (TREE_TYPE (field))
709 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
710 == FUNCTION_TYPE))))
711 {
712 tree name = TYPE_NAME (TREE_TYPE (field));
713 if (TREE_CODE (name) == IDENTIFIER_NODE)
714 {
715 obstack_1grow (ob, '_');
716 go_append_string (ob, name);
717 }
718 else if (TREE_CODE (name) == TYPE_DECL)
719 {
720 obstack_1grow (ob, '_');
721 go_append_string (ob, DECL_NAME (name));
722 }
723 }
724 else
725 {
726 if (!go_format_type (container, TREE_TYPE (field), true,
727 false))
728 ret = false;
729 }
730 }
731 obstack_grow (ob, "; ", 2);
732
733 /* Only output the first field of a union, and hope for
734 the best. */
735 if (TREE_CODE (type) == UNION_TYPE)
736 break;
737 }
738 obstack_1grow (ob, '}');
739 }
740 break;
741
742 case FUNCTION_TYPE:
743 {
744 tree args;
745 bool is_varargs;
746 tree result;
747
748 /* Go has no way to write a type which is a function but not a
749 pointer to a function. */
750 if (!is_func_ok)
751 {
752 obstack_grow (ob, "func*", 5);
753 ret = false;
754 }
755
756 obstack_1grow (ob, '(');
757 is_varargs = true;
758 for (args = TYPE_ARG_TYPES (type);
759 args != NULL_TREE;
760 args = TREE_CHAIN (args))
761 {
762 if (VOID_TYPE_P (TREE_VALUE (args)))
763 {
764 gcc_assert (TREE_CHAIN (args) == NULL);
765 is_varargs = false;
766 break;
767 }
768 if (args != TYPE_ARG_TYPES (type))
769 obstack_grow (ob, ", ", 2);
770 if (!go_format_type (container, TREE_VALUE (args), true, false))
771 ret = false;
772 }
773 if (is_varargs)
774 {
775 if (TYPE_ARG_TYPES (type) != NULL_TREE)
776 obstack_grow (ob, ", ", 2);
777 obstack_grow (ob, "...interface{}", 14);
778 }
779 obstack_1grow (ob, ')');
780
781 result = TREE_TYPE (type);
782 if (!VOID_TYPE_P (result))
783 {
784 obstack_1grow (ob, ' ');
785 if (!go_format_type (container, result, use_type_name, false))
786 ret = false;
787 }
788 }
789 break;
790
791 default:
792 obstack_grow (ob, "INVALID-type", 12);
793 ret = false;
794 break;
795 }
796
797 return ret;
798 }
799
800 /* Output the type which was built on the type obstack, and then free
801 it. */
802
803 static void
804 go_output_type (struct godump_container *container)
805 {
806 struct obstack *ob;
807
808 ob = &container->type_obstack;
809 obstack_1grow (ob, '\0');
810 fputs (obstack_base (ob), go_dump_file);
811 obstack_free (ob, obstack_base (ob));
812 }
813
814 /* Output a function declaration. */
815
816 static void
817 go_output_fndecl (struct godump_container *container, tree decl)
818 {
819 if (!go_format_type (container, TREE_TYPE (decl), false, true))
820 fprintf (go_dump_file, "// ");
821 fprintf (go_dump_file, "func _%s ",
822 IDENTIFIER_POINTER (DECL_NAME (decl)));
823 go_output_type (container);
824 fprintf (go_dump_file, " __asm__(\"%s\")\n",
825 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
826 }
827
828 /* Output a typedef or something like a struct definition. */
829
830 static void
831 go_output_typedef (struct godump_container *container, tree decl)
832 {
833 /* If we have an enum type, output the enum constants
834 separately. */
835 if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
836 && TYPE_SIZE (TREE_TYPE (decl)) != 0
837 && !pointer_set_contains (container->decls_seen, TREE_TYPE (decl))
838 && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
839 || !pointer_set_contains (container->decls_seen,
840 TYPE_CANONICAL (TREE_TYPE (decl)))))
841 {
842 tree element;
843
844 for (element = TYPE_VALUES (TREE_TYPE (decl));
845 element != NULL_TREE;
846 element = TREE_CHAIN (element))
847 fprintf (go_dump_file, "const _%s = " HOST_WIDE_INT_PRINT_DEC "\n",
848 IDENTIFIER_POINTER (TREE_PURPOSE (element)),
849 tree_low_cst (TREE_VALUE (element), 0));
850 pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
851 if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
852 pointer_set_insert (container->decls_seen,
853 TYPE_CANONICAL (TREE_TYPE (decl)));
854 }
855
856 if (DECL_NAME (decl) != NULL_TREE)
857 {
858 void **slot;
859 const char *type;
860
861 type = IDENTIFIER_POINTER (DECL_NAME (decl));
862 /* If type defined already, skip. */
863 slot = htab_find_slot (container->type_hash, type, INSERT);
864 if (*slot != NULL)
865 return;
866 *slot = CONST_CAST (void *, (const void *) type);
867
868 if (!go_format_type (container, TREE_TYPE (decl), false, false))
869 fprintf (go_dump_file, "// ");
870 fprintf (go_dump_file, "type _%s ",
871 IDENTIFIER_POINTER (DECL_NAME (decl)));
872 go_output_type (container);
873 pointer_set_insert (container->decls_seen, decl);
874 }
875 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
876 {
877 void **slot;
878 const char *type;
879
880 type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
881 /* If type defined already, skip. */
882 slot = htab_find_slot (container->type_hash, type, INSERT);
883 if (*slot != NULL)
884 return;
885 *slot = CONST_CAST (void *, (const void *) type);
886
887 if (!go_format_type (container, TREE_TYPE (decl), false, false))
888 fprintf (go_dump_file, "// ");
889 fprintf (go_dump_file, "type _%s ",
890 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
891 go_output_type (container);
892 }
893 else
894 return;
895
896 fprintf (go_dump_file, "\n");
897 }
898
899 /* Output a variable. */
900
901 static void
902 go_output_var (struct godump_container *container, tree decl)
903 {
904 bool is_valid;
905
906 if (pointer_set_contains (container->decls_seen, decl)
907 || pointer_set_contains (container->decls_seen, DECL_NAME (decl)))
908 return;
909 pointer_set_insert (container->decls_seen, decl);
910 pointer_set_insert (container->decls_seen, DECL_NAME (decl));
911
912 is_valid = go_format_type (container, TREE_TYPE (decl), true, false);
913 if (is_valid
914 && htab_find_slot (container->type_hash,
915 IDENTIFIER_POINTER (DECL_NAME (decl)),
916 NO_INSERT) != NULL)
917 {
918 /* There is already a type with this name, probably from a
919 struct tag. Prefer the type to the variable. */
920 is_valid = false;
921 }
922 if (!is_valid)
923 fprintf (go_dump_file, "// ");
924
925 fprintf (go_dump_file, "var _%s ",
926 IDENTIFIER_POINTER (DECL_NAME (decl)));
927 go_output_type (container);
928 fprintf (go_dump_file, "\n");
929
930 /* Sometimes an extern variable is declared with an unknown struct
931 type. */
932 if (TYPE_NAME (TREE_TYPE (decl)) != NULL_TREE
933 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
934 {
935 tree type_name = TYPE_NAME (TREE_TYPE (decl));
936 if (TREE_CODE (type_name) == IDENTIFIER_NODE)
937 pointer_set_insert (container->pot_dummy_types,
938 IDENTIFIER_POINTER (type_name));
939 else if (TREE_CODE (type_name) == TYPE_DECL)
940 pointer_set_insert (container->pot_dummy_types,
941 IDENTIFIER_POINTER (DECL_NAME (type_name)));
942 }
943 }
944
945 /* Build a hash table with the Go keywords. */
946
947 static const char * const keywords[] = {
948 "__asm__", "break", "case", "chan", "const", "continue", "default",
949 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
950 "import", "interface", "map", "package", "range", "return", "select",
951 "struct", "switch", "type", "var"
952 };
953
954 static void
955 keyword_hash_init (struct godump_container *container)
956 {
957 size_t i;
958 size_t count = sizeof (keywords) / sizeof (keywords[0]);
959 void **slot;
960
961 for (i = 0; i < count; i++)
962 {
963 slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
964 *slot = CONST_CAST (void *, (const void *) keywords[i]);
965 }
966 }
967
968 /* Traversing the pot_dummy_types and seeing which types are present
969 in the global types hash table and creating dummy definitions if
970 not found. This function is invoked by pointer_set_traverse. */
971
972 static bool
973 find_dummy_types (const void *ptr, void *adata)
974 {
975 struct godump_container *data = (struct godump_container *) adata;
976 const char *type = (const char *) ptr;
977 void **slot;
978
979 slot = htab_find_slot (data->type_hash, type, NO_INSERT);
980 if (slot == NULL)
981 fprintf (go_dump_file, "type _%s struct {}\n", type);
982 return true;
983 }
984
985 /* Output symbols. */
986
987 static void
988 go_finish (const char *filename)
989 {
990 struct godump_container container;
991 unsigned int ix;
992 tree decl;
993
994 real_debug_hooks->finish (filename);
995
996 container.decls_seen = pointer_set_create ();
997 container.pot_dummy_types = pointer_set_create ();
998 container.type_hash = htab_create (100, htab_hash_string,
999 string_hash_eq, NULL);
1000 container.keyword_hash = htab_create (50, htab_hash_string,
1001 string_hash_eq, NULL);
1002 obstack_init (&container.type_obstack);
1003
1004 keyword_hash_init (&container);
1005
1006 FOR_EACH_VEC_ELT (tree, queue, ix, decl)
1007 {
1008 switch (TREE_CODE (decl))
1009 {
1010 case FUNCTION_DECL:
1011 go_output_fndecl (&container, decl);
1012 break;
1013
1014 case TYPE_DECL:
1015 go_output_typedef (&container, decl);
1016 break;
1017
1018 case VAR_DECL:
1019 go_output_var (&container, decl);
1020 break;
1021
1022 default:
1023 gcc_unreachable();
1024 }
1025 }
1026
1027 /* To emit dummy definitions. */
1028 pointer_set_traverse (container.pot_dummy_types, find_dummy_types,
1029 (void *) &container);
1030
1031 pointer_set_destroy (container.decls_seen);
1032 pointer_set_destroy (container.pot_dummy_types);
1033 htab_delete (container.type_hash);
1034 htab_delete (container.keyword_hash);
1035 obstack_free (&container.type_obstack, NULL);
1036
1037 queue = NULL;
1038
1039 if (fclose (go_dump_file) != 0)
1040 error ("could not close Go dump file: %m");
1041 go_dump_file = NULL;
1042 }
1043
1044 /* Set up our hooks. */
1045
1046 const struct gcc_debug_hooks *
1047 dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
1048 {
1049 go_dump_file = fopen (filename, "w");
1050 if (go_dump_file == NULL)
1051 {
1052 error ("could not open Go dump file %qs: %m", filename);
1053 return hooks;
1054 }
1055
1056 go_debug_hooks = *hooks;
1057 real_debug_hooks = hooks;
1058
1059 go_debug_hooks.finish = go_finish;
1060 go_debug_hooks.define = go_define;
1061 go_debug_hooks.undef = go_undef;
1062 go_debug_hooks.function_decl = go_function_decl;
1063 go_debug_hooks.global_decl = go_global_decl;
1064 go_debug_hooks.type_decl = go_type_decl;
1065
1066 macro_hash = htab_create (100, htab_hash_string, string_hash_eq, NULL);
1067
1068 return &go_debug_hooks;
1069 }
1070
1071 #include "gt-godump.h"