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