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