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>.
5 This file is part of GCC.
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
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
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/>. */
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
27 All global names are output with a leading underscore, so that they
28 are all hidden in Go. */
32 #include "coretypes.h"
33 #include "diagnostic-core.h"
36 #include "pointer-set.h"
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. */
45 /* Our debug hooks. This is initialized by dump_go_spec_init. */
47 static struct gcc_debug_hooks go_debug_hooks;
49 /* The real debug hooks. */
51 static const struct gcc_debug_hooks *real_debug_hooks;
53 /* The file where we should write information. */
55 static FILE *go_dump_file;
57 /* A queue of decls to output. */
59 static GTY(()) VEC(tree,gc) *queue;
61 /* A hash table of macros we have seen. */
63 static htab_t macro_hash;
65 /* For the hash tables. */
68 string_hash_eq (const void *y1, const void *y2)
70 return strcmp ((const char *) y1, (const char *) y2) == 0;
73 /* A macro definition. */
76 go_define (unsigned int lineno, const char *buffer)
88 real_debug_hooks->define (lineno, buffer);
90 /* Skip macro functions. */
91 for (p = buffer; *p != '\0' && *p != ' '; ++p)
104 copy = XNEWVEC (char, name_end - buffer + 1);
105 memcpy (copy, buffer, name_end - buffer);
106 copy[name_end - buffer] = '\0';
108 hashval = htab_hash_string (copy);
109 slot = htab_find_slot_with_hash (macro_hash, copy, hashval, NO_INSERT);
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);
121 need_operand = false;
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':
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':
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. */
146 while (ISALNUM (*p) || *p == '_')
148 n = XALLOCAVEC (char, p - start + 1);
149 memcpy (n, start, p - start);
151 slot = htab_find_slot (macro_hash, n, NO_INSERT);
152 if (slot == NULL || *slot == NULL)
154 /* This is a reference to a name which was not defined
160 memcpy (q, start, p - start);
164 need_operand = false;
172 case '0': case '1': case '2': case '3': case '4':
173 case '5': case '6': case '7': case '8': case '9':
180 if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
185 while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
187 && ((*p >= 'a' && *p <= 'f')
188 || (*p >= 'A' && *p <= 'F'))))
190 memcpy (q, start, p - start);
192 while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
193 || *p == 'f' || *p == 'F'
194 || *p == 'd' || *p == 'D')
196 /* Go doesn't use any of these trailing type
201 /* We'll pick up the exponent, if any, as an
205 need_operand = false;
214 /* Always OK, not part of an operand, presumed to start an
218 need_operand = false;
222 /* OK if we don't need an operand, and presumed to indicate
231 /* Always OK, but not part of an operand. */
236 case '*': case '/': case '%': case '|': case '&': case '^':
237 /* Must be a binary operator. */
249 /* Must be a binary operator. */
261 /* Must be a binary operator. */
270 /* Must be a unary operator. */
278 /* Must be a binary operand, may be << or >> or <= or >=. */
282 if (*p == *(p - 1) || *p == '=')
289 /* Must be a unary operand, must be translated for Go. */
318 case '0': case '1': case '2': case '3':
319 case '4': case '5': case '6': case '7':
321 while (*p >= '0' && *p <= '7')
326 /* Go octal characters are always 3
335 while (ISXDIGIT (*p))
340 /* Go hex characters are always 2 digits. */
345 case 'a': case 'b': case 'f': case 'n': case 'r':
346 case 't': case 'v': case '\\': case '\'': case '"':
368 slot = htab_find_slot_with_hash (macro_hash, copy, hashval, INSERT);
371 fprintf (go_dump_file, "const _%s = %s\n", copy, out_buffer);
373 XDELETEVEC (out_buffer);
377 fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
378 XDELETEVEC (out_buffer);
385 go_undef (unsigned int lineno, const char *buffer)
389 real_debug_hooks->undef (lineno, buffer);
391 slot = htab_find_slot (macro_hash, buffer, NO_INSERT);
394 fprintf (go_dump_file, "// undef _%s\n", buffer);
395 /* We don't delete the slot from the hash table because that will
396 cause a duplicate const definition. */
399 /* A function or variable decl. */
404 if (!TREE_PUBLIC (decl)
405 || DECL_IS_BUILTIN (decl)
406 || DECL_NAME (decl) == NULL_TREE)
408 VEC_safe_push (tree, gc, queue, decl);
411 /* A function decl. */
414 go_function_decl (tree decl)
416 real_debug_hooks->function_decl (decl);
420 /* A global variable decl. */
423 go_global_decl (tree decl)
425 real_debug_hooks->global_decl (decl);
429 /* A type declaration. */
432 go_type_decl (tree decl, int local)
434 real_debug_hooks->type_decl (decl, local);
436 if (local || DECL_IS_BUILTIN (decl))
438 if (DECL_NAME (decl) == NULL_TREE
439 && (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE
440 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) != IDENTIFIER_NODE)
441 && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
443 VEC_safe_push (tree, gc, queue, decl);
446 /* A container for the data we pass around when generating information
447 at the end of the compilation. */
449 struct godump_container
451 /* DECLs that we have already seen. */
452 struct pointer_set_t *decls_seen;
454 /* Types which may potentially have to be defined as dummy
456 struct pointer_set_t *pot_dummy_types;
461 /* Global type definitions. */
464 /* Obstack used to write out a type definition. */
465 struct obstack type_obstack;
468 /* Append an IDENTIFIER_NODE to OB. */
471 go_append_string (struct obstack *ob, tree id)
473 obstack_grow (ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
476 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
477 USE_TYPE_NAME is true if we can simply use a type name here without
478 needing to define it. IS_FUNC_OK is true if we can output a func
479 type here; the "func" keyword will already have been added. Return
480 true if the type can be represented in Go, false otherwise. */
483 go_format_type (struct godump_container *container, tree type,
484 bool use_type_name, bool is_func_ok)
490 ob = &container->type_obstack;
492 if (TYPE_NAME (type) != NULL_TREE
493 && (pointer_set_contains (container->decls_seen, type)
494 || pointer_set_contains (container->decls_seen, TYPE_NAME (type)))
495 && (AGGREGATE_TYPE_P (type)
496 || POINTER_TYPE_P (type)
497 || TREE_CODE (type) == FUNCTION_TYPE))
501 name = TYPE_NAME (type);
502 if (TREE_CODE (name) == IDENTIFIER_NODE)
504 obstack_1grow (ob, '_');
505 go_append_string (ob, name);
508 else if (TREE_CODE (name) == TYPE_DECL)
510 obstack_1grow (ob, '_');
511 go_append_string (ob, DECL_NAME (name));
516 pointer_set_insert (container->decls_seen, type);
518 switch (TREE_CODE (type))
521 obstack_grow (ob, "int", 3);
525 obstack_1grow (ob, '_');
526 go_append_string (ob, DECL_NAME (type));
534 switch (TYPE_PRECISION (type))
537 s = TYPE_UNSIGNED (type) ? "uint8" : "int8";
540 s = TYPE_UNSIGNED (type) ? "uint16" : "int16";
543 s = TYPE_UNSIGNED (type) ? "uint32" : "int32";
546 s = TYPE_UNSIGNED (type) ? "uint64" : "int64";
549 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
550 TYPE_PRECISION (type),
551 TYPE_UNSIGNED (type) ? "u" : "");
556 obstack_grow (ob, s, strlen (s));
565 switch (TYPE_PRECISION (type))
574 snprintf (buf, sizeof buf, "INVALID-float-%u",
575 TYPE_PRECISION (type));
580 obstack_grow (ob, s, strlen (s));
585 obstack_grow (ob, "bool", 4);
590 && TYPE_NAME (TREE_TYPE (type)) != NULL_TREE
591 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))
592 || (POINTER_TYPE_P (TREE_TYPE (type))
593 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type)))
598 name = TYPE_NAME (TREE_TYPE (type));
599 if (TREE_CODE (name) == IDENTIFIER_NODE)
601 obstack_grow (ob, "*_", 2);
602 go_append_string (ob, name);
604 /* The pointer here can be used without the struct or
605 union definition. So this struct or union is a a
606 potential dummy type. */
607 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
608 pointer_set_insert (container->pot_dummy_types,
609 IDENTIFIER_POINTER (name));
613 else if (TREE_CODE (name) == TYPE_DECL)
615 obstack_grow (ob, "*_", 2);
616 go_append_string (ob, DECL_NAME (name));
617 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
618 pointer_set_insert (container->pot_dummy_types,
619 IDENTIFIER_POINTER (DECL_NAME (name)));
623 if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
624 obstack_grow (ob, "func", 4);
626 obstack_1grow (ob, '*');
627 if (VOID_TYPE_P (TREE_TYPE (type)))
628 obstack_grow (ob, "byte", 4);
631 if (!go_format_type (container, TREE_TYPE (type), use_type_name,
638 obstack_1grow (ob, '[');
639 if (TYPE_DOMAIN (type) != NULL_TREE
640 && TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
641 && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
642 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
643 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0
644 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
645 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
646 && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0))
650 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
651 tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0));
652 obstack_grow (ob, buf, strlen (buf));
654 obstack_1grow (ob, ']');
655 if (!go_format_type (container, TREE_TYPE (type), use_type_name, false))
665 obstack_grow (ob, "struct { ", 9);
667 for (field = TYPE_FIELDS (type);
669 field = TREE_CHAIN (field))
671 if (DECL_NAME (field) == NULL)
675 obstack_grow (ob, "_f", 2);
676 snprintf (buf, sizeof buf, "%d", i);
677 obstack_grow (ob, buf, strlen (buf));
682 const char *var_name;
685 /* Start variable name with an underscore if a keyword. */
686 var_name = IDENTIFIER_POINTER (DECL_NAME (field));
687 slot = htab_find_slot (container->keyword_hash, var_name,
690 obstack_1grow (ob, '_');
691 go_append_string (ob, DECL_NAME (field));
693 obstack_1grow (ob, ' ');
694 if (DECL_BIT_FIELD (field))
696 obstack_grow (ob, "INVALID-bit-field", 17);
701 /* Do not expand type if a record or union type or a
703 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
704 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
705 || (POINTER_TYPE_P (TREE_TYPE (field))
706 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
709 tree name = TYPE_NAME (TREE_TYPE (field));
710 if (TREE_CODE (name) == IDENTIFIER_NODE)
712 obstack_1grow (ob, '_');
713 go_append_string (ob, name);
715 else if (TREE_CODE (name) == TYPE_DECL)
717 obstack_1grow (ob, '_');
718 go_append_string (ob, DECL_NAME (name));
723 if (!go_format_type (container, TREE_TYPE (field), true,
728 obstack_grow (ob, "; ", 2);
730 /* Only output the first field of a union, and hope for
732 if (TREE_CODE (type) == UNION_TYPE)
735 obstack_1grow (ob, '}');
745 /* Go has no way to write a type which is a function but not a
746 pointer to a function. */
749 obstack_grow (ob, "func*", 5);
753 obstack_1grow (ob, '(');
755 for (args = TYPE_ARG_TYPES (type);
757 args = TREE_CHAIN (args))
759 if (VOID_TYPE_P (TREE_VALUE (args)))
761 gcc_assert (TREE_CHAIN (args) == NULL);
765 if (args != TYPE_ARG_TYPES (type))
766 obstack_grow (ob, ", ", 2);
767 if (!go_format_type (container, TREE_VALUE (args), true, false))
772 if (TYPE_ARG_TYPES (type) != NULL_TREE)
773 obstack_grow (ob, ", ", 2);
774 obstack_grow (ob, "...interface{}", 14);
776 obstack_1grow (ob, ')');
778 result = TREE_TYPE (type);
779 if (!VOID_TYPE_P (result))
781 obstack_1grow (ob, ' ');
782 if (!go_format_type (container, result, use_type_name, false))
789 obstack_grow (ob, "INVALID-type", 12);
797 /* Output the type which was built on the type obstack, and then free
801 go_output_type (struct godump_container *container)
805 ob = &container->type_obstack;
806 obstack_1grow (ob, '\0');
807 fputs (obstack_base (ob), go_dump_file);
808 obstack_free (ob, obstack_base (ob));
811 /* Output a function declaration. */
814 go_output_fndecl (struct godump_container *container, tree decl)
816 if (!go_format_type (container, TREE_TYPE (decl), false, true))
817 fprintf (go_dump_file, "// ");
818 fprintf (go_dump_file, "func _%s ",
819 IDENTIFIER_POINTER (DECL_NAME (decl)));
820 go_output_type (container);
821 fprintf (go_dump_file, " __asm__(\"%s\")\n",
822 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
825 /* Output a typedef or something like a struct definition. */
828 go_output_typedef (struct godump_container *container, tree decl)
830 /* If we have an enum type, output the enum constants
832 if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
833 && TYPE_SIZE (TREE_TYPE (decl)) != 0
834 && !pointer_set_contains (container->decls_seen, TREE_TYPE (decl))
835 && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
836 || !pointer_set_contains (container->decls_seen,
837 TYPE_CANONICAL (TREE_TYPE (decl)))))
841 for (element = TYPE_VALUES (TREE_TYPE (decl));
842 element != NULL_TREE;
843 element = TREE_CHAIN (element))
844 fprintf (go_dump_file, "const _%s = " HOST_WIDE_INT_PRINT_DEC "\n",
845 IDENTIFIER_POINTER (TREE_PURPOSE (element)),
846 tree_low_cst (TREE_VALUE (element), 0));
847 pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
848 if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
849 pointer_set_insert (container->decls_seen,
850 TYPE_CANONICAL (TREE_TYPE (decl)));
853 if (DECL_NAME (decl) != NULL_TREE)
858 type = IDENTIFIER_POINTER (DECL_NAME (decl));
859 /* If type defined already, skip. */
860 slot = htab_find_slot (container->type_hash, type, INSERT);
863 *slot = CONST_CAST (void *, (const void *) type);
865 if (!go_format_type (container, TREE_TYPE (decl), false, false))
866 fprintf (go_dump_file, "// ");
867 fprintf (go_dump_file, "type _%s ",
868 IDENTIFIER_POINTER (DECL_NAME (decl)));
869 go_output_type (container);
870 pointer_set_insert (container->decls_seen, decl);
872 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
877 type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
878 /* If type defined already, skip. */
879 slot = htab_find_slot (container->type_hash, type, INSERT);
882 *slot = CONST_CAST (void *, (const void *) type);
884 if (!go_format_type (container, TREE_TYPE (decl), false, false))
885 fprintf (go_dump_file, "// ");
886 fprintf (go_dump_file, "type _%s ",
887 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
888 go_output_type (container);
893 fprintf (go_dump_file, "\n");
896 /* Output a variable. */
899 go_output_var (struct godump_container *container, tree decl)
903 if (pointer_set_contains (container->decls_seen, decl)
904 || pointer_set_contains (container->decls_seen, DECL_NAME (decl)))
906 pointer_set_insert (container->decls_seen, decl);
907 pointer_set_insert (container->decls_seen, DECL_NAME (decl));
909 is_valid = go_format_type (container, TREE_TYPE (decl), true, false);
911 && htab_find_slot (container->type_hash,
912 IDENTIFIER_POINTER (DECL_NAME (decl)),
915 /* There is already a type with this name, probably from a
916 struct tag. Prefer the type to the variable. */
920 fprintf (go_dump_file, "// ");
922 fprintf (go_dump_file, "var _%s ",
923 IDENTIFIER_POINTER (DECL_NAME (decl)));
924 go_output_type (container);
925 fprintf (go_dump_file, "\n");
927 /* Sometimes an extern variable is declared with an unknown struct
929 if (TYPE_NAME (TREE_TYPE (decl)) != NULL_TREE
930 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
932 tree type_name = TYPE_NAME (TREE_TYPE (decl));
933 if (TREE_CODE (type_name) == IDENTIFIER_NODE)
934 pointer_set_insert (container->pot_dummy_types,
935 IDENTIFIER_POINTER (type_name));
936 else if (TREE_CODE (type_name) == TYPE_DECL)
937 pointer_set_insert (container->pot_dummy_types,
938 IDENTIFIER_POINTER (DECL_NAME (type_name)));
942 /* Build a hash table with the Go keywords. */
944 static const char * const keywords[] = {
945 "__asm__", "break", "case", "chan", "const", "continue", "default",
946 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
947 "import", "interface", "map", "package", "range", "return", "select",
948 "struct", "switch", "type", "var"
952 keyword_hash_init (struct godump_container *container)
955 size_t count = sizeof (keywords) / sizeof (keywords[0]);
958 for (i = 0; i < count; i++)
960 slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
961 *slot = CONST_CAST (void *, (const void *) keywords[i]);
965 /* Traversing the pot_dummy_types and seeing which types are present
966 in the global types hash table and creating dummy definitions if
967 not found. This function is invoked by pointer_set_traverse. */
970 find_dummy_types (const void *ptr, void *adata)
972 struct godump_container *data = (struct godump_container *) adata;
973 const char *type = (const char *) ptr;
976 slot = htab_find_slot (data->type_hash, type, NO_INSERT);
978 fprintf (go_dump_file, "type _%s struct {}\n", type);
982 /* Output symbols. */
985 go_finish (const char *filename)
987 struct godump_container container;
991 real_debug_hooks->finish (filename);
993 container.decls_seen = pointer_set_create ();
994 container.pot_dummy_types = pointer_set_create ();
995 container.type_hash = htab_create (100, htab_hash_string,
996 string_hash_eq, NULL);
997 container.keyword_hash = htab_create (50, htab_hash_string,
998 string_hash_eq, NULL);
999 obstack_init (&container.type_obstack);
1001 keyword_hash_init (&container);
1003 FOR_EACH_VEC_ELT (tree, queue, ix, decl)
1005 switch (TREE_CODE (decl))
1008 go_output_fndecl (&container, decl);
1012 go_output_typedef (&container, decl);
1016 go_output_var (&container, decl);
1024 /* To emit dummy definitions. */
1025 pointer_set_traverse (container.pot_dummy_types, find_dummy_types,
1026 (void *) &container);
1028 pointer_set_destroy (container.decls_seen);
1029 pointer_set_destroy (container.pot_dummy_types);
1030 htab_delete (container.type_hash);
1031 htab_delete (container.keyword_hash);
1032 obstack_free (&container.type_obstack, NULL);
1036 if (fclose (go_dump_file) != 0)
1037 error ("could not close Go dump file: %m");
1038 go_dump_file = NULL;
1041 /* Set up our hooks. */
1043 const struct gcc_debug_hooks *
1044 dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
1046 go_dump_file = fopen (filename, "w");
1047 if (go_dump_file == NULL)
1049 error ("could not open Go dump file %qs: %m", filename);
1053 go_debug_hooks = *hooks;
1054 real_debug_hooks = hooks;
1056 go_debug_hooks.finish = go_finish;
1057 go_debug_hooks.define = go_define;
1058 go_debug_hooks.undef = go_undef;
1059 go_debug_hooks.function_decl = go_function_decl;
1060 go_debug_hooks.global_decl = go_global_decl;
1061 go_debug_hooks.type_decl = go_type_decl;
1063 macro_hash = htab_create (100, htab_hash_string, string_hash_eq, NULL);
1065 return &go_debug_hooks;
1068 #include "gt-godump.h"