Mercurial > hg > CbC > GCC_original
comparison gcc/godump.c @ 16:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | 561a7518be6b |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
15:561a7518be6b | 16:04ced10e8804 |
---|---|
1 /* Output Go language descriptions of types. | 1 /* Output Go language descriptions of types. |
2 Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. | 2 Copyright (C) 2008-2017 Free Software Foundation, Inc. |
3 Written by Ian Lance Taylor <iant@google.com>. | 3 Written by Ian Lance Taylor <iant@google.com>. |
4 | 4 |
5 This file is part of GCC. | 5 This file is part of GCC. |
6 | 6 |
7 GCC is free software; you can redistribute it and/or modify it under | 7 GCC is free software; you can redistribute it and/or modify it under |
28 are all hidden in Go. */ | 28 are all hidden in Go. */ |
29 | 29 |
30 #include "config.h" | 30 #include "config.h" |
31 #include "system.h" | 31 #include "system.h" |
32 #include "coretypes.h" | 32 #include "coretypes.h" |
33 #include "tree.h" | |
33 #include "diagnostic-core.h" | 34 #include "diagnostic-core.h" |
34 #include "tree.h" | |
35 #include "ggc.h" | |
36 #include "pointer-set.h" | |
37 #include "obstack.h" | |
38 #include "debug.h" | 35 #include "debug.h" |
36 #include "stor-layout.h" | |
39 | 37 |
40 /* We dump this information from the debug hooks. This gives us a | 38 /* We dump this information from the debug hooks. This gives us a |
41 stable and maintainable API to hook into. In order to work | 39 stable and maintainable API to hook into. In order to work |
42 correctly when -g is used, we build our own hooks structure which | 40 correctly when -g is used, we build our own hooks structure which |
43 wraps the hooks we need to change. */ | 41 wraps the hooks we need to change. */ |
54 | 52 |
55 static FILE *go_dump_file; | 53 static FILE *go_dump_file; |
56 | 54 |
57 /* A queue of decls to output. */ | 55 /* A queue of decls to output. */ |
58 | 56 |
59 static GTY(()) VEC(tree,gc) *queue; | 57 static GTY(()) vec<tree, va_gc> *queue; |
60 | 58 |
61 /* A hash table of macros we have seen. */ | 59 /* A hash table of macros we have seen. */ |
62 | 60 |
63 static htab_t macro_hash; | 61 static htab_t macro_hash; |
64 | 62 |
65 /* For the hash tables. */ | 63 /* The type of a value in macro_hash. */ |
64 | |
65 struct macro_hash_value | |
66 { | |
67 /* The name stored in the hash table. */ | |
68 char *name; | |
69 /* The value of the macro. */ | |
70 char *value; | |
71 }; | |
72 | |
73 /* Returns the number of units necessary to represent an integer with the given | |
74 PRECISION (in bits). */ | |
75 | |
76 static inline unsigned int | |
77 precision_to_units (unsigned int precision) | |
78 { | |
79 return (precision + BITS_PER_UNIT - 1) / BITS_PER_UNIT; | |
80 } | |
81 | |
82 /* Calculate the hash value for an entry in the macro hash table. */ | |
83 | |
84 static hashval_t | |
85 macro_hash_hashval (const void *val) | |
86 { | |
87 const struct macro_hash_value *mhval = (const struct macro_hash_value *) val; | |
88 return htab_hash_string (mhval->name); | |
89 } | |
90 | |
91 /* Compare values in the macro hash table for equality. */ | |
92 | |
93 static int | |
94 macro_hash_eq (const void *v1, const void *v2) | |
95 { | |
96 const struct macro_hash_value *mhv1 = (const struct macro_hash_value *) v1; | |
97 const struct macro_hash_value *mhv2 = (const struct macro_hash_value *) v2; | |
98 return strcmp (mhv1->name, mhv2->name) == 0; | |
99 } | |
100 | |
101 /* Free values deleted from the macro hash table. */ | |
102 | |
103 static void | |
104 macro_hash_del (void *v) | |
105 { | |
106 struct macro_hash_value *mhv = (struct macro_hash_value *) v; | |
107 XDELETEVEC (mhv->name); | |
108 XDELETEVEC (mhv->value); | |
109 XDELETE (mhv); | |
110 } | |
111 | |
112 /* For the string hash tables. */ | |
66 | 113 |
67 static int | 114 static int |
68 string_hash_eq (const void *y1, const void *y2) | 115 string_hash_eq (const void *y1, const void *y2) |
69 { | 116 { |
70 return strcmp ((const char *) y1, (const char *) y2) == 0; | 117 return strcmp ((const char *) y1, (const char *) y2) == 0; |
75 static void | 122 static void |
76 go_define (unsigned int lineno, const char *buffer) | 123 go_define (unsigned int lineno, const char *buffer) |
77 { | 124 { |
78 const char *p; | 125 const char *p; |
79 const char *name_end; | 126 const char *name_end; |
127 size_t out_len; | |
80 char *out_buffer; | 128 char *out_buffer; |
81 char *q; | 129 char *q; |
82 bool saw_operand; | 130 bool saw_operand; |
83 bool need_operand; | 131 bool need_operand; |
132 struct macro_hash_value *mhval; | |
84 char *copy; | 133 char *copy; |
85 hashval_t hashval; | 134 hashval_t hashval; |
86 void **slot; | 135 void **slot; |
87 | 136 |
88 real_debug_hooks->define (lineno, buffer); | 137 real_debug_hooks->define (lineno, buffer); |
103 | 152 |
104 copy = XNEWVEC (char, name_end - buffer + 1); | 153 copy = XNEWVEC (char, name_end - buffer + 1); |
105 memcpy (copy, buffer, name_end - buffer); | 154 memcpy (copy, buffer, name_end - buffer); |
106 copy[name_end - buffer] = '\0'; | 155 copy[name_end - buffer] = '\0'; |
107 | 156 |
157 mhval = XNEW (struct macro_hash_value); | |
158 mhval->name = copy; | |
159 mhval->value = NULL; | |
160 | |
108 hashval = htab_hash_string (copy); | 161 hashval = htab_hash_string (copy); |
109 slot = htab_find_slot_with_hash (macro_hash, copy, hashval, NO_INSERT); | 162 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, NO_INSERT); |
110 if (slot != NULL) | |
111 { | |
112 XDELETEVEC (copy); | |
113 return; | |
114 } | |
115 | 163 |
116 /* For simplicity, we force all names to be hidden by adding an | 164 /* For simplicity, we force all names to be hidden by adding an |
117 initial underscore, and let the user undo this as needed. */ | 165 initial underscore, and let the user undo this as needed. */ |
118 out_buffer = XNEWVEC (char, strlen (p) * 2 + 1); | 166 out_len = strlen (p) * 2 + 1; |
167 out_buffer = XNEWVEC (char, out_len); | |
119 q = out_buffer; | 168 q = out_buffer; |
120 saw_operand = false; | 169 saw_operand = false; |
121 need_operand = false; | 170 need_operand = false; |
122 while (*p != '\0') | 171 while (*p != '\0') |
123 { | 172 { |
139 worry about UTF-8 identifiers, but they are not a | 188 worry about UTF-8 identifiers, but they are not a |
140 problem for practical uses of -fdump-go-spec so we | 189 problem for practical uses of -fdump-go-spec so we |
141 don't worry about them. */ | 190 don't worry about them. */ |
142 const char *start; | 191 const char *start; |
143 char *n; | 192 char *n; |
193 struct macro_hash_value idval; | |
144 | 194 |
145 if (saw_operand) | 195 if (saw_operand) |
146 goto unknown; | 196 goto unknown; |
147 | 197 |
148 start = p; | 198 start = p; |
149 while (ISALNUM (*p) || *p == '_') | 199 while (ISALNUM (*p) || *p == '_') |
150 ++p; | 200 ++p; |
151 n = XALLOCAVEC (char, p - start + 1); | 201 n = XALLOCAVEC (char, p - start + 1); |
152 memcpy (n, start, p - start); | 202 memcpy (n, start, p - start); |
153 n[p - start] = '\0'; | 203 n[p - start] = '\0'; |
154 slot = htab_find_slot (macro_hash, n, NO_INSERT); | 204 idval.name = n; |
155 if (slot == NULL || *slot == NULL) | 205 idval.value = NULL; |
206 if (htab_find (macro_hash, &idval) == NULL) | |
156 { | 207 { |
157 /* This is a reference to a name which was not defined | 208 /* This is a reference to a name which was not defined |
158 as a macro. */ | 209 as a macro. */ |
159 goto unknown; | 210 goto unknown; |
160 } | 211 } |
298 break; | 349 break; |
299 | 350 |
300 case '"': | 351 case '"': |
301 case '\'': | 352 case '\'': |
302 { | 353 { |
303 char quote = *p; | 354 char quote; |
355 int count; | |
356 | |
357 if (saw_operand) | |
358 goto unknown; | |
359 quote = *p; | |
304 *q++ = *p++; | 360 *q++ = *p++; |
361 count = 0; | |
305 while (*p != quote) | 362 while (*p != quote) |
306 { | 363 { |
307 int c; | 364 int c; |
308 | 365 |
309 if (*p == '\0') | 366 if (*p == '\0') |
310 goto unknown; | 367 goto unknown; |
368 | |
369 ++count; | |
311 | 370 |
312 if (*p != '\\') | 371 if (*p != '\\') |
313 { | 372 { |
314 *q++ = *p++; | 373 *q++ = *p++; |
315 continue; | 374 continue; |
352 | 411 |
353 default: | 412 default: |
354 goto unknown; | 413 goto unknown; |
355 } | 414 } |
356 } | 415 } |
416 | |
357 *q++ = *p++; | 417 *q++ = *p++; |
418 | |
419 if (quote == '\'' && count != 1) | |
420 goto unknown; | |
421 | |
422 saw_operand = true; | |
423 need_operand = false; | |
424 | |
358 break; | 425 break; |
359 } | 426 } |
360 | 427 |
361 default: | 428 default: |
362 goto unknown; | 429 goto unknown; |
364 } | 431 } |
365 | 432 |
366 if (need_operand) | 433 if (need_operand) |
367 goto unknown; | 434 goto unknown; |
368 | 435 |
436 gcc_assert ((size_t) (q - out_buffer) < out_len); | |
369 *q = '\0'; | 437 *q = '\0'; |
370 | 438 |
371 slot = htab_find_slot_with_hash (macro_hash, copy, hashval, INSERT); | 439 mhval->value = out_buffer; |
372 *slot = copy; | 440 |
373 | 441 if (slot == NULL) |
374 fprintf (go_dump_file, "const _%s = %s\n", copy, out_buffer); | 442 { |
375 | 443 slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, INSERT); |
376 XDELETEVEC (out_buffer); | 444 gcc_assert (slot != NULL && *slot == NULL); |
445 } | |
446 else | |
447 { | |
448 if (*slot != NULL) | |
449 macro_hash_del (*slot); | |
450 } | |
451 | |
452 *slot = mhval; | |
453 | |
377 return; | 454 return; |
378 | 455 |
379 unknown: | 456 unknown: |
380 fprintf (go_dump_file, "// unknowndefine %s\n", buffer); | 457 fprintf (go_dump_file, "// unknowndefine %s\n", buffer); |
458 if (slot != NULL) | |
459 htab_clear_slot (macro_hash, slot); | |
381 XDELETEVEC (out_buffer); | 460 XDELETEVEC (out_buffer); |
382 XDELETEVEC (copy); | 461 XDELETEVEC (copy); |
383 } | 462 } |
384 | 463 |
385 /* A macro undef. */ | 464 /* A macro undef. */ |
386 | 465 |
387 static void | 466 static void |
388 go_undef (unsigned int lineno, const char *buffer) | 467 go_undef (unsigned int lineno, const char *buffer) |
389 { | 468 { |
469 struct macro_hash_value mhval; | |
390 void **slot; | 470 void **slot; |
391 | 471 |
392 real_debug_hooks->undef (lineno, buffer); | 472 real_debug_hooks->undef (lineno, buffer); |
393 | 473 |
394 slot = htab_find_slot (macro_hash, buffer, NO_INSERT); | 474 mhval.name = CONST_CAST (char *, buffer); |
395 if (slot == NULL) | 475 mhval.value = NULL; |
396 return; | 476 slot = htab_find_slot (macro_hash, &mhval, NO_INSERT); |
397 fprintf (go_dump_file, "// undef _%s\n", buffer); | 477 if (slot != NULL) |
398 /* We don't delete the slot from the hash table because that will | 478 htab_clear_slot (macro_hash, slot); |
399 cause a duplicate const definition. */ | |
400 } | 479 } |
401 | 480 |
402 /* A function or variable decl. */ | 481 /* A function or variable decl. */ |
403 | 482 |
404 static void | 483 static void |
406 { | 485 { |
407 if (!TREE_PUBLIC (decl) | 486 if (!TREE_PUBLIC (decl) |
408 || DECL_IS_BUILTIN (decl) | 487 || DECL_IS_BUILTIN (decl) |
409 || DECL_NAME (decl) == NULL_TREE) | 488 || DECL_NAME (decl) == NULL_TREE) |
410 return; | 489 return; |
411 VEC_safe_push (tree, gc, queue, decl); | 490 vec_safe_push (queue, decl); |
412 } | 491 } |
413 | 492 |
414 /* A function decl. */ | 493 /* A function decl. */ |
415 | 494 |
416 static void | 495 static void |
418 { | 497 { |
419 real_debug_hooks->function_decl (decl); | 498 real_debug_hooks->function_decl (decl); |
420 go_decl (decl); | 499 go_decl (decl); |
421 } | 500 } |
422 | 501 |
502 static void | |
503 go_early_global_decl (tree decl) | |
504 { | |
505 go_decl (decl); | |
506 if (TREE_CODE (decl) != FUNCTION_DECL || DECL_STRUCT_FUNCTION (decl) != NULL) | |
507 real_debug_hooks->early_global_decl (decl); | |
508 } | |
509 | |
423 /* A global variable decl. */ | 510 /* A global variable decl. */ |
424 | 511 |
425 static void | 512 static void |
426 go_global_decl (tree decl) | 513 go_late_global_decl (tree decl) |
427 { | 514 { |
428 real_debug_hooks->global_decl (decl); | 515 real_debug_hooks->late_global_decl (decl); |
429 go_decl (decl); | |
430 } | 516 } |
431 | 517 |
432 /* A type declaration. */ | 518 /* A type declaration. */ |
433 | 519 |
434 static void | 520 static void |
441 if (DECL_NAME (decl) == NULL_TREE | 527 if (DECL_NAME (decl) == NULL_TREE |
442 && (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE | 528 && (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE |
443 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) != IDENTIFIER_NODE) | 529 || TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) != IDENTIFIER_NODE) |
444 && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE) | 530 && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE) |
445 return; | 531 return; |
446 VEC_safe_push (tree, gc, queue, decl); | 532 vec_safe_push (queue, decl); |
447 } | 533 } |
448 | 534 |
449 /* A container for the data we pass around when generating information | 535 /* A container for the data we pass around when generating information |
450 at the end of the compilation. */ | 536 at the end of the compilation. */ |
451 | 537 |
452 struct godump_container | 538 struct godump_container |
453 { | 539 { |
454 /* DECLs that we have already seen. */ | 540 /* DECLs that we have already seen. */ |
455 struct pointer_set_t *decls_seen; | 541 hash_set<tree> decls_seen; |
456 | 542 |
457 /* Types which may potentially have to be defined as dummy | 543 /* Types which may potentially have to be defined as dummy |
458 types. */ | 544 types. */ |
459 struct pointer_set_t *pot_dummy_types; | 545 hash_set<const char *> pot_dummy_types; |
460 | 546 |
461 /* Go keywords. */ | 547 /* Go keywords. */ |
462 htab_t keyword_hash; | 548 htab_t keyword_hash; |
463 | 549 |
464 /* Global type definitions. */ | 550 /* Global type definitions. */ |
465 htab_t type_hash; | 551 htab_t type_hash; |
552 | |
553 /* Invalid types. */ | |
554 htab_t invalid_hash; | |
466 | 555 |
467 /* Obstack used to write out a type definition. */ | 556 /* Obstack used to write out a type definition. */ |
468 struct obstack type_obstack; | 557 struct obstack type_obstack; |
469 }; | 558 }; |
470 | 559 |
474 go_append_string (struct obstack *ob, tree id) | 563 go_append_string (struct obstack *ob, tree id) |
475 { | 564 { |
476 obstack_grow (ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id)); | 565 obstack_grow (ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id)); |
477 } | 566 } |
478 | 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 | |
479 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK. | 672 /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK. |
480 USE_TYPE_NAME is true if we can simply use a type name here without | 673 USE_TYPE_NAME is true if we can simply use a type name here without |
481 needing to define it. IS_FUNC_OK is true if we can output a func | 674 needing to define it. IS_FUNC_OK is true if we can output a func |
482 type here; the "func" keyword will already have been added. Return | 675 type here; the "func" keyword will already have been added. |
483 true if the type can be represented in Go, false otherwise. */ | 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. */ | |
484 | 680 |
485 static bool | 681 static bool |
486 go_format_type (struct godump_container *container, tree type, | 682 go_format_type (struct godump_container *container, tree type, |
487 bool use_type_name, bool is_func_ok) | 683 bool use_type_name, bool is_func_ok, unsigned int *p_art_i, |
684 bool is_anon_record_or_union) | |
488 { | 685 { |
489 bool ret; | 686 bool ret; |
490 struct obstack *ob; | 687 struct obstack *ob; |
491 | 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 } | |
492 ret = true; | 696 ret = true; |
493 ob = &container->type_obstack; | 697 ob = &container->type_obstack; |
494 | 698 |
495 if (TYPE_NAME (type) != NULL_TREE | 699 if (TYPE_NAME (type) != NULL_TREE |
496 && (pointer_set_contains (container->decls_seen, type) | 700 && (container->decls_seen.contains (type) |
497 || pointer_set_contains (container->decls_seen, TYPE_NAME (type))) | 701 || container->decls_seen.contains (TYPE_NAME (type))) |
498 && (AGGREGATE_TYPE_P (type) | 702 && (AGGREGATE_TYPE_P (type) |
499 || POINTER_TYPE_P (type) | 703 || POINTER_TYPE_P (type) |
500 || TREE_CODE (type) == FUNCTION_TYPE)) | 704 || TREE_CODE (type) == FUNCTION_TYPE)) |
501 { | 705 { |
502 tree name; | 706 tree name; |
503 | 707 void **slot; |
504 name = TYPE_NAME (type); | 708 |
505 if (TREE_CODE (name) == IDENTIFIER_NODE) | 709 name = TYPE_IDENTIFIER (type); |
506 { | 710 |
507 obstack_1grow (ob, '_'); | 711 slot = htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (name), |
508 go_append_string (ob, name); | 712 NO_INSERT); |
509 return ret; | 713 if (slot != NULL) |
510 } | 714 ret = false; |
511 else if (TREE_CODE (name) == TYPE_DECL) | 715 |
512 { | 716 obstack_1grow (ob, '_'); |
513 obstack_1grow (ob, '_'); | 717 go_append_string (ob, name); |
514 go_append_string (ob, DECL_NAME (name)); | 718 return ret; |
515 return ret; | 719 } |
516 } | 720 |
517 } | 721 container->decls_seen.add (type); |
518 | |
519 pointer_set_insert (container->decls_seen, type); | |
520 | 722 |
521 switch (TREE_CODE (type)) | 723 switch (TREE_CODE (type)) |
522 { | 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 | |
523 case ENUMERAL_TYPE: | 740 case ENUMERAL_TYPE: |
524 obstack_grow (ob, "int", 3); | |
525 break; | |
526 | |
527 case TYPE_DECL: | |
528 obstack_1grow (ob, '_'); | |
529 go_append_string (ob, DECL_NAME (type)); | |
530 break; | |
531 | |
532 case INTEGER_TYPE: | 741 case INTEGER_TYPE: |
533 { | 742 { |
534 const char *s; | 743 const char *s; |
535 char buf[100]; | 744 char buf[100]; |
536 | 745 |
537 switch (TYPE_PRECISION (type)) | 746 s = go_get_uinttype_for_precision (TYPE_PRECISION (type), |
747 TYPE_UNSIGNED (type)); | |
748 if (s == NULL) | |
538 { | 749 { |
539 case 8: | |
540 s = TYPE_UNSIGNED (type) ? "uint8" : "int8"; | |
541 break; | |
542 case 16: | |
543 s = TYPE_UNSIGNED (type) ? "uint16" : "int16"; | |
544 break; | |
545 case 32: | |
546 s = TYPE_UNSIGNED (type) ? "uint32" : "int32"; | |
547 break; | |
548 case 64: | |
549 s = TYPE_UNSIGNED (type) ? "uint64" : "int64"; | |
550 break; | |
551 default: | |
552 snprintf (buf, sizeof buf, "INVALID-int-%u%s", | 750 snprintf (buf, sizeof buf, "INVALID-int-%u%s", |
553 TYPE_PRECISION (type), | 751 TYPE_PRECISION (type), |
554 TYPE_UNSIGNED (type) ? "u" : ""); | 752 TYPE_UNSIGNED (type) ? "u" : ""); |
555 s = buf; | 753 s = buf; |
556 ret = false; | 754 ret = false; |
557 break; | |
558 } | 755 } |
559 obstack_grow (ob, s, strlen (s)); | 756 obstack_grow (ob, s, strlen (s)); |
560 } | 757 } |
561 break; | 758 break; |
562 | 759 |
582 } | 779 } |
583 obstack_grow (ob, s, strlen (s)); | 780 obstack_grow (ob, s, strlen (s)); |
584 } | 781 } |
585 break; | 782 break; |
586 | 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 | |
587 case BOOLEAN_TYPE: | 818 case BOOLEAN_TYPE: |
588 obstack_grow (ob, "bool", 4); | 819 obstack_grow (ob, "bool", 4); |
589 break; | 820 break; |
590 | 821 |
591 case POINTER_TYPE: | 822 case POINTER_TYPE: |
595 || (POINTER_TYPE_P (TREE_TYPE (type)) | 826 || (POINTER_TYPE_P (TREE_TYPE (type)) |
596 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type))) | 827 && (TREE_CODE (TREE_TYPE (TREE_TYPE (type))) |
597 == FUNCTION_TYPE)))) | 828 == FUNCTION_TYPE)))) |
598 { | 829 { |
599 tree name; | 830 tree name; |
600 | 831 void **slot; |
601 name = TYPE_NAME (TREE_TYPE (type)); | 832 |
602 if (TREE_CODE (name) == IDENTIFIER_NODE) | 833 name = TYPE_IDENTIFIER (TREE_TYPE (type)); |
603 { | 834 |
604 obstack_grow (ob, "*_", 2); | 835 slot = htab_find_slot (container->invalid_hash, |
605 go_append_string (ob, name); | 836 IDENTIFIER_POINTER (name), NO_INSERT); |
606 | 837 if (slot != NULL) |
607 /* The pointer here can be used without the struct or | 838 ret = false; |
608 union definition. So this struct or union is a a | 839 |
609 potential dummy type. */ | 840 obstack_grow (ob, "*_", 2); |
610 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))) | 841 go_append_string (ob, name); |
611 pointer_set_insert (container->pot_dummy_types, | 842 |
612 IDENTIFIER_POINTER (name)); | 843 /* The pointer here can be used without the struct or union |
613 | 844 definition. So this struct or union is a potential dummy |
614 return ret; | 845 type. */ |
615 } | 846 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))) |
616 else if (TREE_CODE (name) == TYPE_DECL) | 847 container->pot_dummy_types.add (IDENTIFIER_POINTER (name)); |
617 { | 848 |
618 obstack_grow (ob, "*_", 2); | 849 return ret; |
619 go_append_string (ob, DECL_NAME (name)); | |
620 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))) | |
621 pointer_set_insert (container->pot_dummy_types, | |
622 IDENTIFIER_POINTER (DECL_NAME (name))); | |
623 return ret; | |
624 } | |
625 } | 850 } |
626 if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) | 851 if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) |
627 obstack_grow (ob, "func", 4); | 852 obstack_grow (ob, "func", 4); |
628 else | 853 else |
629 obstack_1grow (ob, '*'); | 854 obstack_1grow (ob, '*'); |
630 if (VOID_TYPE_P (TREE_TYPE (type))) | 855 if (VOID_TYPE_P (TREE_TYPE (type))) |
631 obstack_grow (ob, "byte", 4); | 856 obstack_grow (ob, "byte", 4); |
632 else | 857 else |
633 { | 858 { |
634 if (!go_format_type (container, TREE_TYPE (type), use_type_name, | 859 if (!go_format_type (container, TREE_TYPE (type), use_type_name, |
635 true)) | 860 true, NULL, false)) |
636 ret = false; | 861 ret = false; |
637 } | 862 } |
638 break; | 863 break; |
639 | 864 |
640 case ARRAY_TYPE: | 865 case ARRAY_TYPE: |
644 && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE | 869 && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE |
645 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST | 870 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST |
646 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0 | 871 && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0 |
647 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE | 872 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE |
648 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST | 873 && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST |
649 && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0)) | 874 && tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))) |
650 { | 875 { |
651 char buf[100]; | 876 char buf[100]; |
652 | 877 |
653 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1", | 878 snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1", |
654 tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0)); | 879 tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))); |
655 obstack_grow (ob, buf, strlen (buf)); | 880 obstack_grow (ob, buf, strlen (buf)); |
656 } | 881 } |
882 else | |
883 obstack_1grow (ob, '0'); | |
657 obstack_1grow (ob, ']'); | 884 obstack_1grow (ob, ']'); |
658 if (!go_format_type (container, TREE_TYPE (type), use_type_name, false)) | 885 if (!go_format_type (container, TREE_TYPE (type), use_type_name, false, |
886 NULL, false)) | |
659 ret = false; | 887 ret = false; |
660 break; | 888 break; |
661 | 889 |
662 case UNION_TYPE: | 890 case UNION_TYPE: |
891 is_union = true; | |
892 /* Fall through to RECORD_TYPE case. */ | |
893 gcc_fallthrough (); | |
663 case RECORD_TYPE: | 894 case RECORD_TYPE: |
664 { | 895 { |
896 unsigned int prev_field_end; | |
897 unsigned int known_alignment; | |
665 tree field; | 898 tree field; |
666 int i; | 899 bool emitted_a_field; |
667 | 900 |
668 obstack_grow (ob, "struct { ", 9); | 901 /* FIXME: Why is this necessary? Without it we can get a core |
669 i = 0; | 902 dump on the s390x headers, or from a file containing simply |
670 for (field = TYPE_FIELDS (type); | 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; | |
671 field != NULL_TREE; | 913 field != NULL_TREE; |
672 field = TREE_CHAIN (field)) | 914 field = TREE_CHAIN (field)) |
673 { | 915 { |
674 if (DECL_NAME (field) == NULL) | 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) | |
675 { | 923 { |
676 char buf[100]; | 924 /* Emit the field. */ |
677 | 925 bool field_ok; |
678 obstack_grow (ob, "_f", 2); | 926 bool is_anon_substructure; |
679 snprintf (buf, sizeof buf, "%d", i); | 927 unsigned int decl_align_unit; |
680 obstack_grow (ob, buf, strlen (buf)); | 928 unsigned int decl_offset; |
681 i++; | 929 |
682 } | 930 field_ok = true; |
683 else | 931 emitted_a_field = true; |
684 { | 932 is_anon_substructure = |
685 const char *var_name; | 933 (DECL_NAME (field) == NULL |
686 void **slot; | 934 && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE |
687 | 935 || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)); |
688 /* Start variable name with an underscore if a keyword. */ | 936 /* Keep track of the alignment of named substructures, either |
689 var_name = IDENTIFIER_POINTER (DECL_NAME (field)); | 937 of the whole record, or the alignment of the emitted field |
690 slot = htab_find_slot (container->keyword_hash, var_name, | 938 (for unions). */ |
691 NO_INSERT); | 939 decl_align_unit = DECL_ALIGN_UNIT (field); |
692 if (slot != NULL) | 940 if (!is_anon_substructure && decl_align_unit > known_alignment) |
693 obstack_1grow (ob, '_'); | 941 known_alignment = decl_align_unit; |
694 go_append_string (ob, DECL_NAME (field)); | 942 /* Pad to start of field. */ |
695 } | 943 decl_offset = |
696 obstack_1grow (ob, ' '); | 944 TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field)) |
697 if (DECL_BIT_FIELD (field)) | 945 + precision_to_units |
698 { | 946 (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field))); |
699 obstack_grow (ob, "INVALID-bit-field", 17); | 947 { |
700 ret = false; | 948 unsigned int align_unit; |
701 } | 949 |
702 else | 950 /* For anonymous records and unions there is no automatic |
703 { | 951 structure alignment, so use 1 as the alignment. */ |
704 /* Do not expand type if a record or union type or a | 952 align_unit = (is_anon_substructure) ? 1 : decl_align_unit; |
705 function pointer. */ | 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. */ | |
706 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE | 973 if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE |
707 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field)) | 974 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field)) |
708 || (POINTER_TYPE_P (TREE_TYPE (field)) | 975 || (POINTER_TYPE_P (TREE_TYPE (field)) |
709 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field))) | 976 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field))) |
710 == FUNCTION_TYPE)))) | 977 == FUNCTION_TYPE)))) |
711 { | 978 { |
712 tree name = TYPE_NAME (TREE_TYPE (field)); | 979 tree name; |
713 if (TREE_CODE (name) == IDENTIFIER_NODE) | 980 void **slot; |
714 { | 981 |
715 obstack_1grow (ob, '_'); | 982 name = TYPE_IDENTIFIER (TREE_TYPE (field)); |
716 go_append_string (ob, name); | 983 |
717 } | 984 slot = htab_find_slot (container->invalid_hash, |
718 else if (TREE_CODE (name) == TYPE_DECL) | 985 IDENTIFIER_POINTER (name), |
719 { | 986 NO_INSERT); |
720 obstack_1grow (ob, '_'); | 987 if (slot != NULL) |
721 go_append_string (ob, DECL_NAME (name)); | 988 field_ok = false; |
722 } | 989 |
990 obstack_1grow (ob, '_'); | |
991 go_append_string (ob, name); | |
723 } | 992 } |
724 else | 993 else |
725 { | 994 { |
726 if (!go_format_type (container, TREE_TYPE (field), true, | 995 if (!go_format_type (container, TREE_TYPE (field), true, |
727 false)) | 996 false, p_art_i, is_anon_substructure)) |
728 ret = false; | 997 field_ok = false; |
729 } | 998 } |
730 } | 999 if (!is_anon_substructure) |
731 obstack_grow (ob, "; ", 2); | 1000 obstack_grow (ob, "; ", 2); |
732 | 1001 if (!field_ok) |
733 /* Only output the first field of a union, and hope for | 1002 ret = false; |
734 the best. */ | 1003 } |
735 if (TREE_CODE (type) == UNION_TYPE) | |
736 break; | |
737 } | 1004 } |
738 obstack_1grow (ob, '}'); | 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, '}'); | |
739 } | 1030 } |
740 break; | 1031 break; |
741 | 1032 |
742 case FUNCTION_TYPE: | 1033 case FUNCTION_TYPE: |
743 { | 1034 { |
744 tree args; | 1035 tree arg_type; |
745 bool is_varargs; | 1036 bool is_varargs; |
746 tree result; | 1037 tree result; |
1038 function_args_iterator iter; | |
1039 bool seen_arg; | |
747 | 1040 |
748 /* Go has no way to write a type which is a function but not a | 1041 /* Go has no way to write a type which is a function but not a |
749 pointer to a function. */ | 1042 pointer to a function. */ |
750 if (!is_func_ok) | 1043 if (!is_func_ok) |
751 { | 1044 { |
752 obstack_grow (ob, "func*", 5); | 1045 obstack_grow (ob, "func*", 5); |
753 ret = false; | 1046 ret = false; |
754 } | 1047 } |
755 | 1048 |
756 obstack_1grow (ob, '('); | 1049 obstack_1grow (ob, '('); |
757 is_varargs = true; | 1050 is_varargs = stdarg_p (type); |
758 for (args = TYPE_ARG_TYPES (type); | 1051 seen_arg = false; |
759 args != NULL_TREE; | 1052 FOREACH_FUNCTION_ARGS (type, arg_type, iter) |
760 args = TREE_CHAIN (args)) | |
761 { | 1053 { |
762 if (VOID_TYPE_P (TREE_VALUE (args))) | 1054 if (VOID_TYPE_P (arg_type)) |
763 { | 1055 break; |
764 gcc_assert (TREE_CHAIN (args) == NULL); | 1056 if (seen_arg) |
765 is_varargs = false; | |
766 break; | |
767 } | |
768 if (args != TYPE_ARG_TYPES (type)) | |
769 obstack_grow (ob, ", ", 2); | 1057 obstack_grow (ob, ", ", 2); |
770 if (!go_format_type (container, TREE_VALUE (args), true, false)) | 1058 if (!go_format_type (container, arg_type, true, false, NULL, false)) |
771 ret = false; | 1059 ret = false; |
1060 seen_arg = true; | |
772 } | 1061 } |
773 if (is_varargs) | 1062 if (is_varargs) |
774 { | 1063 { |
775 if (TYPE_ARG_TYPES (type) != NULL_TREE) | 1064 if (prototype_p (type)) |
776 obstack_grow (ob, ", ", 2); | 1065 obstack_grow (ob, ", ", 2); |
777 obstack_grow (ob, "...interface{}", 14); | 1066 obstack_grow (ob, "...interface{}", 14); |
778 } | 1067 } |
779 obstack_1grow (ob, ')'); | 1068 obstack_1grow (ob, ')'); |
780 | 1069 |
781 result = TREE_TYPE (type); | 1070 result = TREE_TYPE (type); |
782 if (!VOID_TYPE_P (result)) | 1071 if (!VOID_TYPE_P (result)) |
783 { | 1072 { |
784 obstack_1grow (ob, ' '); | 1073 obstack_1grow (ob, ' '); |
785 if (!go_format_type (container, result, use_type_name, false)) | 1074 if (!go_format_type (container, result, use_type_name, false, NULL, |
1075 false)) | |
786 ret = false; | 1076 ret = false; |
787 } | 1077 } |
788 } | 1078 } |
789 break; | 1079 break; |
790 | 1080 |
805 { | 1095 { |
806 struct obstack *ob; | 1096 struct obstack *ob; |
807 | 1097 |
808 ob = &container->type_obstack; | 1098 ob = &container->type_obstack; |
809 obstack_1grow (ob, '\0'); | 1099 obstack_1grow (ob, '\0'); |
810 fputs (obstack_base (ob), go_dump_file); | 1100 fputs ((char *) obstack_base (ob), go_dump_file); |
811 obstack_free (ob, obstack_base (ob)); | 1101 obstack_free (ob, obstack_base (ob)); |
812 } | 1102 } |
813 | 1103 |
814 /* Output a function declaration. */ | 1104 /* Output a function declaration. */ |
815 | 1105 |
816 static void | 1106 static void |
817 go_output_fndecl (struct godump_container *container, tree decl) | 1107 go_output_fndecl (struct godump_container *container, tree decl) |
818 { | 1108 { |
819 if (!go_format_type (container, TREE_TYPE (decl), false, true)) | 1109 if (!go_format_type (container, TREE_TYPE (decl), false, true, NULL, false)) |
820 fprintf (go_dump_file, "// "); | 1110 fprintf (go_dump_file, "// "); |
821 fprintf (go_dump_file, "func _%s ", | 1111 fprintf (go_dump_file, "func _%s ", |
822 IDENTIFIER_POINTER (DECL_NAME (decl))); | 1112 IDENTIFIER_POINTER (DECL_NAME (decl))); |
823 go_output_type (container); | 1113 go_output_type (container); |
824 fprintf (go_dump_file, " __asm__(\"%s\")\n", | 1114 fprintf (go_dump_file, " __asm__(\"%s\")\n", |
832 { | 1122 { |
833 /* If we have an enum type, output the enum constants | 1123 /* If we have an enum type, output the enum constants |
834 separately. */ | 1124 separately. */ |
835 if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE | 1125 if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE |
836 && TYPE_SIZE (TREE_TYPE (decl)) != 0 | 1126 && TYPE_SIZE (TREE_TYPE (decl)) != 0 |
837 && !pointer_set_contains (container->decls_seen, TREE_TYPE (decl)) | 1127 && !container->decls_seen.contains (TREE_TYPE (decl)) |
838 && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE | 1128 && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE |
839 || !pointer_set_contains (container->decls_seen, | 1129 || !container->decls_seen.contains |
840 TYPE_CANONICAL (TREE_TYPE (decl))))) | 1130 (TYPE_CANONICAL (TREE_TYPE (decl))))) |
841 { | 1131 { |
842 tree element; | 1132 tree element; |
843 | 1133 |
844 for (element = TYPE_VALUES (TREE_TYPE (decl)); | 1134 for (element = TYPE_VALUES (TREE_TYPE (decl)); |
845 element != NULL_TREE; | 1135 element != NULL_TREE; |
846 element = TREE_CHAIN (element)) | 1136 element = TREE_CHAIN (element)) |
847 fprintf (go_dump_file, "const _%s = " HOST_WIDE_INT_PRINT_DEC "\n", | 1137 { |
848 IDENTIFIER_POINTER (TREE_PURPOSE (element)), | 1138 const char *name; |
849 tree_low_cst (TREE_VALUE (element), 0)); | 1139 struct macro_hash_value *mhval; |
850 pointer_set_insert (container->decls_seen, TREE_TYPE (decl)); | 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 (wi::to_wide (element), buf); | |
1163 | |
1164 mhval->value = xstrdup (buf); | |
1165 *slot = mhval; | |
1166 } | |
1167 container->decls_seen.add (TREE_TYPE (decl)); | |
851 if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE) | 1168 if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE) |
852 pointer_set_insert (container->decls_seen, | 1169 container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl))); |
853 TYPE_CANONICAL (TREE_TYPE (decl))); | |
854 } | 1170 } |
855 | 1171 |
856 if (DECL_NAME (decl) != NULL_TREE) | 1172 if (DECL_NAME (decl) != NULL_TREE) |
857 { | 1173 { |
858 void **slot; | 1174 void **slot; |
863 slot = htab_find_slot (container->type_hash, type, INSERT); | 1179 slot = htab_find_slot (container->type_hash, type, INSERT); |
864 if (*slot != NULL) | 1180 if (*slot != NULL) |
865 return; | 1181 return; |
866 *slot = CONST_CAST (void *, (const void *) type); | 1182 *slot = CONST_CAST (void *, (const void *) type); |
867 | 1183 |
868 if (!go_format_type (container, TREE_TYPE (decl), false, false)) | 1184 if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL, |
869 fprintf (go_dump_file, "// "); | 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 } | |
870 fprintf (go_dump_file, "type _%s ", | 1191 fprintf (go_dump_file, "type _%s ", |
871 IDENTIFIER_POINTER (DECL_NAME (decl))); | 1192 IDENTIFIER_POINTER (DECL_NAME (decl))); |
872 go_output_type (container); | 1193 go_output_type (container); |
873 pointer_set_insert (container->decls_seen, decl); | 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); | |
874 } | 1207 } |
875 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))) | 1208 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))) |
876 { | 1209 { |
877 void **slot; | 1210 void **slot; |
878 const char *type; | 1211 const char *type; |
1212 HOST_WIDE_INT size; | |
879 | 1213 |
880 type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl)))); | 1214 type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl)))); |
881 /* If type defined already, skip. */ | 1215 /* If type defined already, skip. */ |
882 slot = htab_find_slot (container->type_hash, type, INSERT); | 1216 slot = htab_find_slot (container->type_hash, type, INSERT); |
883 if (*slot != NULL) | 1217 if (*slot != NULL) |
884 return; | 1218 return; |
885 *slot = CONST_CAST (void *, (const void *) type); | 1219 *slot = CONST_CAST (void *, (const void *) type); |
886 | 1220 |
887 if (!go_format_type (container, TREE_TYPE (decl), false, false)) | 1221 if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL, |
888 fprintf (go_dump_file, "// "); | 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 } | |
889 fprintf (go_dump_file, "type _%s ", | 1228 fprintf (go_dump_file, "type _%s ", |
890 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl)))); | 1229 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl)))); |
891 go_output_type (container); | 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); | |
892 } | 1238 } |
893 else | 1239 else |
894 return; | 1240 return; |
895 | 1241 |
896 fprintf (go_dump_file, "\n"); | 1242 fprintf (go_dump_file, "\n"); |
900 | 1246 |
901 static void | 1247 static void |
902 go_output_var (struct godump_container *container, tree decl) | 1248 go_output_var (struct godump_container *container, tree decl) |
903 { | 1249 { |
904 bool is_valid; | 1250 bool is_valid; |
905 | 1251 tree type_name; |
906 if (pointer_set_contains (container->decls_seen, decl) | 1252 tree id; |
907 || pointer_set_contains (container->decls_seen, DECL_NAME (decl))) | 1253 |
1254 if (container->decls_seen.contains (decl) | |
1255 || container->decls_seen.contains (DECL_NAME (decl))) | |
908 return; | 1256 return; |
909 pointer_set_insert (container->decls_seen, decl); | 1257 container->decls_seen.add (decl); |
910 pointer_set_insert (container->decls_seen, DECL_NAME (decl)); | 1258 container->decls_seen.add (DECL_NAME (decl)); |
911 | 1259 |
912 is_valid = go_format_type (container, TREE_TYPE (decl), true, false); | 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); | |
913 if (is_valid | 1287 if (is_valid |
914 && htab_find_slot (container->type_hash, | 1288 && htab_find_slot (container->type_hash, |
915 IDENTIFIER_POINTER (DECL_NAME (decl)), | 1289 IDENTIFIER_POINTER (DECL_NAME (decl)), |
916 NO_INSERT) != NULL) | 1290 NO_INSERT) != NULL) |
917 { | 1291 { |
927 go_output_type (container); | 1301 go_output_type (container); |
928 fprintf (go_dump_file, "\n"); | 1302 fprintf (go_dump_file, "\n"); |
929 | 1303 |
930 /* Sometimes an extern variable is declared with an unknown struct | 1304 /* Sometimes an extern variable is declared with an unknown struct |
931 type. */ | 1305 type. */ |
932 if (TYPE_NAME (TREE_TYPE (decl)) != NULL_TREE | 1306 if (type_name != NULL_TREE && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))) |
933 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))) | 1307 { |
934 { | |
935 tree type_name = TYPE_NAME (TREE_TYPE (decl)); | |
936 if (TREE_CODE (type_name) == IDENTIFIER_NODE) | 1308 if (TREE_CODE (type_name) == IDENTIFIER_NODE) |
937 pointer_set_insert (container->pot_dummy_types, | 1309 container->pot_dummy_types.add (IDENTIFIER_POINTER (type_name)); |
938 IDENTIFIER_POINTER (type_name)); | |
939 else if (TREE_CODE (type_name) == TYPE_DECL) | 1310 else if (TREE_CODE (type_name) == TYPE_DECL) |
940 pointer_set_insert (container->pot_dummy_types, | 1311 container->pot_dummy_types.add |
941 IDENTIFIER_POINTER (DECL_NAME (type_name))); | 1312 (IDENTIFIER_POINTER (DECL_NAME (type_name))); |
942 } | 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; | |
943 } | 1325 } |
944 | 1326 |
945 /* Build a hash table with the Go keywords. */ | 1327 /* Build a hash table with the Go keywords. */ |
946 | 1328 |
947 static const char * const keywords[] = { | 1329 static const char * const keywords[] = { |
965 } | 1347 } |
966 } | 1348 } |
967 | 1349 |
968 /* Traversing the pot_dummy_types and seeing which types are present | 1350 /* Traversing the pot_dummy_types and seeing which types are present |
969 in the global types hash table and creating dummy definitions if | 1351 in the global types hash table and creating dummy definitions if |
970 not found. This function is invoked by pointer_set_traverse. */ | 1352 not found. This function is invoked by hash_set::traverse. */ |
971 | 1353 |
972 static bool | 1354 bool |
973 find_dummy_types (const void *ptr, void *adata) | 1355 find_dummy_types (const char *const &ptr, godump_container *adata) |
974 { | 1356 { |
975 struct godump_container *data = (struct godump_container *) adata; | 1357 struct godump_container *data = (struct godump_container *) adata; |
976 const char *type = (const char *) ptr; | 1358 const char *type = (const char *) ptr; |
977 void **slot; | 1359 void **slot; |
1360 void **islot; | |
978 | 1361 |
979 slot = htab_find_slot (data->type_hash, type, NO_INSERT); | 1362 slot = htab_find_slot (data->type_hash, type, NO_INSERT); |
980 if (slot == NULL) | 1363 islot = htab_find_slot (data->invalid_hash, type, NO_INSERT); |
1364 if (slot == NULL || islot != NULL) | |
981 fprintf (go_dump_file, "type _%s struct {}\n", type); | 1365 fprintf (go_dump_file, "type _%s struct {}\n", type); |
982 return true; | 1366 return true; |
983 } | 1367 } |
984 | 1368 |
985 /* Output symbols. */ | 1369 /* Output symbols. */ |
991 unsigned int ix; | 1375 unsigned int ix; |
992 tree decl; | 1376 tree decl; |
993 | 1377 |
994 real_debug_hooks->finish (filename); | 1378 real_debug_hooks->finish (filename); |
995 | 1379 |
996 container.decls_seen = pointer_set_create (); | |
997 container.pot_dummy_types = pointer_set_create (); | |
998 container.type_hash = htab_create (100, htab_hash_string, | 1380 container.type_hash = htab_create (100, htab_hash_string, |
999 string_hash_eq, NULL); | 1381 string_hash_eq, NULL); |
1382 container.invalid_hash = htab_create (10, htab_hash_string, | |
1383 string_hash_eq, NULL); | |
1000 container.keyword_hash = htab_create (50, htab_hash_string, | 1384 container.keyword_hash = htab_create (50, htab_hash_string, |
1001 string_hash_eq, NULL); | 1385 string_hash_eq, NULL); |
1002 obstack_init (&container.type_obstack); | 1386 obstack_init (&container.type_obstack); |
1003 | 1387 |
1004 keyword_hash_init (&container); | 1388 keyword_hash_init (&container); |
1005 | 1389 |
1006 FOR_EACH_VEC_ELT (tree, queue, ix, decl) | 1390 FOR_EACH_VEC_SAFE_ELT (queue, ix, decl) |
1007 { | 1391 { |
1008 switch (TREE_CODE (decl)) | 1392 switch (TREE_CODE (decl)) |
1009 { | 1393 { |
1010 case FUNCTION_DECL: | 1394 case FUNCTION_DECL: |
1011 go_output_fndecl (&container, decl); | 1395 go_output_fndecl (&container, decl); |
1018 case VAR_DECL: | 1402 case VAR_DECL: |
1019 go_output_var (&container, decl); | 1403 go_output_var (&container, decl); |
1020 break; | 1404 break; |
1021 | 1405 |
1022 default: | 1406 default: |
1023 gcc_unreachable(); | 1407 gcc_unreachable (); |
1024 } | 1408 } |
1025 } | 1409 } |
1026 | 1410 |
1411 htab_traverse_noresize (macro_hash, go_print_macro, NULL); | |
1412 | |
1027 /* To emit dummy definitions. */ | 1413 /* To emit dummy definitions. */ |
1028 pointer_set_traverse (container.pot_dummy_types, find_dummy_types, | 1414 container.pot_dummy_types.traverse<godump_container *, find_dummy_types> |
1029 (void *) &container); | 1415 (&container); |
1030 | 1416 |
1031 pointer_set_destroy (container.decls_seen); | |
1032 pointer_set_destroy (container.pot_dummy_types); | |
1033 htab_delete (container.type_hash); | 1417 htab_delete (container.type_hash); |
1418 htab_delete (container.invalid_hash); | |
1034 htab_delete (container.keyword_hash); | 1419 htab_delete (container.keyword_hash); |
1035 obstack_free (&container.type_obstack, NULL); | 1420 obstack_free (&container.type_obstack, NULL); |
1036 | 1421 |
1037 queue = NULL; | 1422 vec_free (queue); |
1038 | 1423 |
1039 if (fclose (go_dump_file) != 0) | 1424 if (fclose (go_dump_file) != 0) |
1040 error ("could not close Go dump file: %m"); | 1425 error ("could not close Go dump file: %m"); |
1041 go_dump_file = NULL; | 1426 go_dump_file = NULL; |
1042 } | 1427 } |
1058 | 1443 |
1059 go_debug_hooks.finish = go_finish; | 1444 go_debug_hooks.finish = go_finish; |
1060 go_debug_hooks.define = go_define; | 1445 go_debug_hooks.define = go_define; |
1061 go_debug_hooks.undef = go_undef; | 1446 go_debug_hooks.undef = go_undef; |
1062 go_debug_hooks.function_decl = go_function_decl; | 1447 go_debug_hooks.function_decl = go_function_decl; |
1063 go_debug_hooks.global_decl = go_global_decl; | 1448 go_debug_hooks.early_global_decl = go_early_global_decl; |
1449 go_debug_hooks.late_global_decl = go_late_global_decl; | |
1064 go_debug_hooks.type_decl = go_type_decl; | 1450 go_debug_hooks.type_decl = go_type_decl; |
1065 | 1451 |
1066 macro_hash = htab_create (100, htab_hash_string, string_hash_eq, NULL); | 1452 macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq, |
1453 macro_hash_del); | |
1067 | 1454 |
1068 return &go_debug_hooks; | 1455 return &go_debug_hooks; |
1069 } | 1456 } |
1070 | 1457 |
1071 #include "gt-godump.h" | 1458 #include "gt-godump.h" |