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. */
149 while (ISALNUM (*p) || *p == '_')
151 n = XALLOCAVEC (char, p - start + 1);
152 memcpy (n, start, p - start);
154 slot = htab_find_slot (macro_hash, n, NO_INSERT);
155 if (slot == NULL || *slot == NULL)
157 /* This is a reference to a name which was not defined
163 memcpy (q, start, p - start);
167 need_operand = false;
175 case '0': case '1': case '2': case '3': case '4':
176 case '5': case '6': case '7': case '8': case '9':
183 if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
188 while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
190 && ((*p >= 'a' && *p <= 'f')
191 || (*p >= 'A' && *p <= 'F'))))
193 memcpy (q, start, p - start);
195 while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
196 || *p == 'f' || *p == 'F'
197 || *p == 'd' || *p == 'D')
199 /* Go doesn't use any of these trailing type
204 /* We'll pick up the exponent, if any, as an
208 need_operand = false;
217 /* Always OK, not part of an operand, presumed to start an
221 need_operand = false;
225 /* OK if we don't need an operand, and presumed to indicate
234 /* Always OK, but not part of an operand. */
239 case '*': case '/': case '%': case '|': case '&': case '^':
240 /* Must be a binary operator. */
252 /* Must be a binary operator. */
264 /* Must be a binary operator. */
273 /* Must be a unary operator. */
281 /* Must be a binary operand, may be << or >> or <= or >=. */
285 if (*p == *(p - 1) || *p == '=')
292 /* Must be a unary operand, must be translated for Go. */
321 case '0': case '1': case '2': case '3':
322 case '4': case '5': case '6': case '7':
324 while (*p >= '0' && *p <= '7')
329 /* Go octal characters are always 3
338 while (ISXDIGIT (*p))
343 /* Go hex characters are always 2 digits. */
348 case 'a': case 'b': case 'f': case 'n': case 'r':
349 case 't': case 'v': case '\\': case '\'': case '"':
371 slot = htab_find_slot_with_hash (macro_hash, copy, hashval, INSERT);
374 fprintf (go_dump_file, "const _%s = %s\n", copy, out_buffer);
376 XDELETEVEC (out_buffer);
380 fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
381 XDELETEVEC (out_buffer);
388 go_undef (unsigned int lineno, const char *buffer)
392 real_debug_hooks->undef (lineno, buffer);
394 slot = htab_find_slot (macro_hash, buffer, NO_INSERT);
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. */
402 /* A function or variable decl. */
407 if (!TREE_PUBLIC (decl)
408 || DECL_IS_BUILTIN (decl)
409 || DECL_NAME (decl) == NULL_TREE)
411 VEC_safe_push (tree, gc, queue, decl);
414 /* A function decl. */
417 go_function_decl (tree decl)
419 real_debug_hooks->function_decl (decl);
423 /* A global variable decl. */
426 go_global_decl (tree decl)
428 real_debug_hooks->global_decl (decl);
432 /* A type declaration. */
435 go_type_decl (tree decl, int local)
437 real_debug_hooks->type_decl (decl, local);
439 if (local || DECL_IS_BUILTIN (decl))
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)
446 VEC_safe_push (tree, gc, queue, decl);
449 /* A container for the data we pass around when generating information
450 at the end of the compilation. */
452 struct godump_container
454 /* DECLs that we have already seen. */
455 struct pointer_set_t *decls_seen;
457 /* Types which may potentially have to be defined as dummy
459 struct pointer_set_t *pot_dummy_types;
464 /* Global type definitions. */
470 /* Obstack used to write out a type definition. */
471 struct obstack type_obstack;
474 /* Append an IDENTIFIER_NODE to OB. */
477 go_append_string (struct obstack *ob, tree id)
479 obstack_grow (ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
482 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
483 USE_TYPE_NAME is true if we can simply use a type name here without
484 needing to define it. IS_FUNC_OK is true if we can output a func
485 type here; the "func" keyword will already have been added. Return
486 true if the type can be represented in Go, false otherwise. */
489 go_format_type (struct godump_container *container, tree type,
490 bool use_type_name, bool is_func_ok)
496 ob = &container->type_obstack;
498 if (TYPE_NAME (type) != NULL_TREE
499 && (pointer_set_contains (container->decls_seen, type)
500 || pointer_set_contains (container->decls_seen, TYPE_NAME (type)))
501 && (AGGREGATE_TYPE_P (type)
502 || POINTER_TYPE_P (type)
503 || TREE_CODE (type) == FUNCTION_TYPE))
508 name = TYPE_NAME (type);
509 if (TREE_CODE (name) == TYPE_DECL)
510 name = DECL_NAME (name);
512 slot = htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (name),
517 obstack_1grow (ob, '_');
518 go_append_string (ob, name);
522 pointer_set_insert (container->decls_seen, type);
524 switch (TREE_CODE (type))
527 obstack_grow (ob, "int", 3);
531 obstack_1grow (ob, '_');
532 go_append_string (ob, DECL_NAME (type));
540 switch (TYPE_PRECISION (type))
543 s = TYPE_UNSIGNED (type) ? "uint8" : "int8";
546 s = TYPE_UNSIGNED (type) ? "uint16" : "int16";
549 s = TYPE_UNSIGNED (type) ? "uint32" : "int32";
552 s = TYPE_UNSIGNED (type) ? "uint64" : "int64";
555 snprintf (buf, sizeof buf, "INVALID-int-%u%s",
556 TYPE_PRECISION (type),
557 TYPE_UNSIGNED (type) ? "u" : "");
562 obstack_grow (ob, s, strlen (s));
571 switch (TYPE_PRECISION (type))
580 snprintf (buf, sizeof buf, "INVALID-float-%u",
581 TYPE_PRECISION (type));
586 obstack_grow (ob, s, strlen (s));
591 obstack_grow (ob, "bool", 4);
596 && TYPE_NAME (TREE_TYPE (type)) != NULL_TREE
597 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))
598 || (POINTER_TYPE_P (TREE_TYPE (type))
599 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type)))
604 name = TYPE_NAME (TREE_TYPE (type));
605 if (TREE_CODE (name) == IDENTIFIER_NODE)
607 obstack_grow (ob, "*_", 2);
608 go_append_string (ob, name);
610 /* The pointer here can be used without the struct or
611 union definition. So this struct or union is a a
612 potential dummy type. */
613 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
614 pointer_set_insert (container->pot_dummy_types,
615 IDENTIFIER_POINTER (name));
619 else if (TREE_CODE (name) == TYPE_DECL)
621 obstack_grow (ob, "*_", 2);
622 go_append_string (ob, DECL_NAME (name));
623 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
624 pointer_set_insert (container->pot_dummy_types,
625 IDENTIFIER_POINTER (DECL_NAME (name)));
629 if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
630 obstack_grow (ob, "func", 4);
632 obstack_1grow (ob, '*');
633 if (VOID_TYPE_P (TREE_TYPE (type)))
634 obstack_grow (ob, "byte", 4);
637 if (!go_format_type (container, TREE_TYPE (type), use_type_name,
644 obstack_1grow (ob, '[');
645 if (TYPE_DOMAIN (type) != NULL_TREE
646 && TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
647 && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
648 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
649 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0
650 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
651 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
652 && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0))
656 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
657 tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0));
658 obstack_grow (ob, buf, strlen (buf));
660 obstack_1grow (ob, ']');
661 if (!go_format_type (container, TREE_TYPE (type), use_type_name, false))
671 obstack_grow (ob, "struct { ", 9);
673 for (field = TYPE_FIELDS (type);
675 field = TREE_CHAIN (field))
677 if (DECL_NAME (field) == NULL)
681 obstack_grow (ob, "Godump_", 2);
682 snprintf (buf, sizeof buf, "%d", i);
683 obstack_grow (ob, buf, strlen (buf));
688 const char *var_name;
691 /* Start variable name with an underscore if a keyword. */
692 var_name = IDENTIFIER_POINTER (DECL_NAME (field));
693 slot = htab_find_slot (container->keyword_hash, var_name,
696 obstack_1grow (ob, '_');
697 go_append_string (ob, DECL_NAME (field));
699 obstack_1grow (ob, ' ');
700 if (DECL_BIT_FIELD (field))
702 obstack_grow (ob, "INVALID-bit-field", 17);
707 /* Do not expand type if a record or union type or a
709 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
710 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
711 || (POINTER_TYPE_P (TREE_TYPE (field))
712 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
715 tree name = TYPE_NAME (TREE_TYPE (field));
716 if (TREE_CODE (name) == IDENTIFIER_NODE)
718 obstack_1grow (ob, '_');
719 go_append_string (ob, name);
721 else if (TREE_CODE (name) == TYPE_DECL)
723 obstack_1grow (ob, '_');
724 go_append_string (ob, DECL_NAME (name));
729 if (!go_format_type (container, TREE_TYPE (field), true,
734 obstack_grow (ob, "; ", 2);
736 /* Only output the first field of a union, and hope for
738 if (TREE_CODE (type) == UNION_TYPE)
741 obstack_1grow (ob, '}');
750 function_args_iterator iter;
753 /* Go has no way to write a type which is a function but not a
754 pointer to a function. */
757 obstack_grow (ob, "func*", 5);
761 obstack_1grow (ob, '(');
762 is_varargs = stdarg_p (type);
764 FOREACH_FUNCTION_ARGS (type, arg_type, iter)
766 if (VOID_TYPE_P (arg_type))
769 obstack_grow (ob, ", ", 2);
770 if (!go_format_type (container, arg_type, true, false))
776 if (prototype_p (type))
777 obstack_grow (ob, ", ", 2);
778 obstack_grow (ob, "...interface{}", 14);
780 obstack_1grow (ob, ')');
782 result = TREE_TYPE (type);
783 if (!VOID_TYPE_P (result))
785 obstack_1grow (ob, ' ');
786 if (!go_format_type (container, result, use_type_name, false))
793 obstack_grow (ob, "INVALID-type", 12);
801 /* Output the type which was built on the type obstack, and then free
805 go_output_type (struct godump_container *container)
809 ob = &container->type_obstack;
810 obstack_1grow (ob, '\0');
811 fputs (obstack_base (ob), go_dump_file);
812 obstack_free (ob, obstack_base (ob));
815 /* Output a function declaration. */
818 go_output_fndecl (struct godump_container *container, tree decl)
820 if (!go_format_type (container, TREE_TYPE (decl), false, true))
821 fprintf (go_dump_file, "// ");
822 fprintf (go_dump_file, "func _%s ",
823 IDENTIFIER_POINTER (DECL_NAME (decl)));
824 go_output_type (container);
825 fprintf (go_dump_file, " __asm__(\"%s\")\n",
826 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
829 /* Output a typedef or something like a struct definition. */
832 go_output_typedef (struct godump_container *container, tree decl)
834 /* If we have an enum type, output the enum constants
836 if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
837 && TYPE_SIZE (TREE_TYPE (decl)) != 0
838 && !pointer_set_contains (container->decls_seen, TREE_TYPE (decl))
839 && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
840 || !pointer_set_contains (container->decls_seen,
841 TYPE_CANONICAL (TREE_TYPE (decl)))))
845 for (element = TYPE_VALUES (TREE_TYPE (decl));
846 element != NULL_TREE;
847 element = TREE_CHAIN (element))
852 name = IDENTIFIER_POINTER (TREE_PURPOSE (element));
854 /* Sometimes a name will be defined as both an enum constant
855 and a macro. Avoid duplicate definition errors by
856 treating enum constants as macros. */
857 slot = htab_find_slot (macro_hash, name, INSERT);
860 *slot = CONST_CAST (char *, name);
861 fprintf (go_dump_file,
862 "const _%s = " HOST_WIDE_INT_PRINT_DEC "\n",
863 name, tree_low_cst (TREE_VALUE (element), 0));
866 pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
867 if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
868 pointer_set_insert (container->decls_seen,
869 TYPE_CANONICAL (TREE_TYPE (decl)));
872 if (DECL_NAME (decl) != NULL_TREE)
877 type = IDENTIFIER_POINTER (DECL_NAME (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))
886 fprintf (go_dump_file, "// ");
887 slot = htab_find_slot (container->invalid_hash, type, INSERT);
888 *slot = CONST_CAST (void *, (const void *) type);
890 fprintf (go_dump_file, "type _%s ",
891 IDENTIFIER_POINTER (DECL_NAME (decl)));
892 go_output_type (container);
893 pointer_set_insert (container->decls_seen, decl);
895 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
900 type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
901 /* If type defined already, skip. */
902 slot = htab_find_slot (container->type_hash, type, INSERT);
905 *slot = CONST_CAST (void *, (const void *) type);
907 if (!go_format_type (container, TREE_TYPE (decl), false, false))
909 fprintf (go_dump_file, "// ");
910 slot = htab_find_slot (container->invalid_hash, type, INSERT);
911 *slot = CONST_CAST (void *, (const void *) type);
913 fprintf (go_dump_file, "type _%s ",
914 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
915 go_output_type (container);
920 fprintf (go_dump_file, "\n");
923 /* Output a variable. */
926 go_output_var (struct godump_container *container, tree decl)
930 if (pointer_set_contains (container->decls_seen, decl)
931 || pointer_set_contains (container->decls_seen, DECL_NAME (decl)))
933 pointer_set_insert (container->decls_seen, decl);
934 pointer_set_insert (container->decls_seen, DECL_NAME (decl));
936 is_valid = go_format_type (container, TREE_TYPE (decl), true, false);
938 && htab_find_slot (container->type_hash,
939 IDENTIFIER_POINTER (DECL_NAME (decl)),
942 /* There is already a type with this name, probably from a
943 struct tag. Prefer the type to the variable. */
947 fprintf (go_dump_file, "// ");
949 fprintf (go_dump_file, "var _%s ",
950 IDENTIFIER_POINTER (DECL_NAME (decl)));
951 go_output_type (container);
952 fprintf (go_dump_file, "\n");
954 /* Sometimes an extern variable is declared with an unknown struct
956 if (TYPE_NAME (TREE_TYPE (decl)) != NULL_TREE
957 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
959 tree type_name = TYPE_NAME (TREE_TYPE (decl));
960 if (TREE_CODE (type_name) == IDENTIFIER_NODE)
961 pointer_set_insert (container->pot_dummy_types,
962 IDENTIFIER_POINTER (type_name));
963 else if (TREE_CODE (type_name) == TYPE_DECL)
964 pointer_set_insert (container->pot_dummy_types,
965 IDENTIFIER_POINTER (DECL_NAME (type_name)));
969 /* Build a hash table with the Go keywords. */
971 static const char * const keywords[] = {
972 "__asm__", "break", "case", "chan", "const", "continue", "default",
973 "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
974 "import", "interface", "map", "package", "range", "return", "select",
975 "struct", "switch", "type", "var"
979 keyword_hash_init (struct godump_container *container)
982 size_t count = sizeof (keywords) / sizeof (keywords[0]);
985 for (i = 0; i < count; i++)
987 slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
988 *slot = CONST_CAST (void *, (const void *) keywords[i]);
992 /* Traversing the pot_dummy_types and seeing which types are present
993 in the global types hash table and creating dummy definitions if
994 not found. This function is invoked by pointer_set_traverse. */
997 find_dummy_types (const void *ptr, void *adata)
999 struct godump_container *data = (struct godump_container *) adata;
1000 const char *type = (const char *) ptr;
1003 slot = htab_find_slot (data->type_hash, type, NO_INSERT);
1005 fprintf (go_dump_file, "type _%s struct {}\n", type);
1009 /* Output symbols. */
1012 go_finish (const char *filename)
1014 struct godump_container container;
1018 real_debug_hooks->finish (filename);
1020 container.decls_seen = pointer_set_create ();
1021 container.pot_dummy_types = pointer_set_create ();
1022 container.type_hash = htab_create (100, htab_hash_string,
1023 string_hash_eq, NULL);
1024 container.invalid_hash = htab_create (10, htab_hash_string,
1025 string_hash_eq, NULL);
1026 container.keyword_hash = htab_create (50, htab_hash_string,
1027 string_hash_eq, NULL);
1028 obstack_init (&container.type_obstack);
1030 keyword_hash_init (&container);
1032 FOR_EACH_VEC_ELT (tree, queue, ix, decl)
1034 switch (TREE_CODE (decl))
1037 go_output_fndecl (&container, decl);
1041 go_output_typedef (&container, decl);
1045 go_output_var (&container, decl);
1053 /* To emit dummy definitions. */
1054 pointer_set_traverse (container.pot_dummy_types, find_dummy_types,
1055 (void *) &container);
1057 pointer_set_destroy (container.decls_seen);
1058 pointer_set_destroy (container.pot_dummy_types);
1059 htab_delete (container.type_hash);
1060 htab_delete (container.invalid_hash);
1061 htab_delete (container.keyword_hash);
1062 obstack_free (&container.type_obstack, NULL);
1066 if (fclose (go_dump_file) != 0)
1067 error ("could not close Go dump file: %m");
1068 go_dump_file = NULL;
1071 /* Set up our hooks. */
1073 const struct gcc_debug_hooks *
1074 dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
1076 go_dump_file = fopen (filename, "w");
1077 if (go_dump_file == NULL)
1079 error ("could not open Go dump file %qs: %m", filename);
1083 go_debug_hooks = *hooks;
1084 real_debug_hooks = hooks;
1086 go_debug_hooks.finish = go_finish;
1087 go_debug_hooks.define = go_define;
1088 go_debug_hooks.undef = go_undef;
1089 go_debug_hooks.function_decl = go_function_decl;
1090 go_debug_hooks.global_decl = go_global_decl;
1091 go_debug_hooks.type_decl = go_type_decl;
1093 macro_hash = htab_create (100, htab_hash_string, string_hash_eq, NULL);
1095 return &go_debug_hooks;
1098 #include "gt-godump.h"