| @@ -127,11 +127,21 @@ namespace · 126 unmodified lines |
| 127 | 127 | template<> |
| 128 | 128 | const type_t &type_table_t::resolve_table_index<type_t>(int32_t idx) const |
| 129 | 129 | { |
| 130 | | − const auto idx_local = idx & ~inner_type_table_mask; |
| 131 | | − if (0 > idx_local || idx_local >= inner_type_table.size()) |
| 132 | | − throw std::out_of_range{ "Invalid inner type table index" }; |
| 130 | + if ((static_cast<uint32_t>(idx) & inner_type_table_mask) != 0) |
| 131 | + { |
| 132 | + const auto idx_local = idx & ~inner_type_table_mask; |
| 133 | + if (0 > idx_local || idx_local >= inner_type_table.size()) |
| 134 | + throw std::out_of_range{ "Invalid inner type table index" }; |
| 135 | + |
| 136 | + return inner_type_table[idx_local]; |
| 137 | + } |
| 138 | + else |
| 139 | + { |
| 140 | + if (0 > idx || static_cast<uint32_t>(idx) >= types.size()) |
| 141 | + throw std::out_of_range{ "Invalid type table index" }; |
| 133 | 142 | |
| 134 | | − return inner_type_table[idx_local]; |
| 143 | + return types[idx]; |
| 144 | + } |
| 135 | 145 | } |
| 136 | 146 | |
| 137 | 147 | template<> |
| @@ -571,6 +581,114 @@ namespace · 433 unmodified lines |
| 571 | 581 | |
| 572 | 582 | namespace |
| 573 | 583 | { |
| 584 | + std::string to_string(const type_t &t, const type_table_t &tt) |
| 585 | + { |
| 586 | + switch (t.type_class) |
| 587 | + { |
| 588 | + case type_class_t::none: return "<none>"; |
| 589 | + case type_class_t::nil: return "nil"; |
| 590 | + case type_class_t::big: return "big"; |
| 591 | + case type_class_t::byte: return "byte"; |
| 592 | + case type_class_t::integer: return "int"; |
| 593 | + case type_class_t::real: return "real"; |
| 594 | + case type_class_t::string: return "string"; |
| 595 | + |
| 596 | + case type_class_t::poly: |
| 597 | + assert(false && "Not fully implemented"); |
| 598 | + return "poly<T>"; |
| 599 | + |
| 600 | + case type_class_t::array: |
| 601 | + return to_string(tt.resolve_table_index<type_t>(t.value_index_1), tt) + "[]"; |
| 602 | + case type_class_t::channel: |
| 603 | + return "chan of " + to_string(tt.resolve_table_index<type_t>(t.value_index_1), tt); |
| 604 | + case type_class_t::list: |
| 605 | + return "list of " + to_string(tt.resolve_table_index<type_t>(t.value_index_1), tt); |
| 606 | + case type_class_t::ref: |
| 607 | + return "ref " + to_string(tt.resolve_table_index<type_t>(t.value_index_1), tt); |
| 608 | + case type_class_t::type_index: |
| 609 | + return to_string(tt.resolve_table_index<type_t>(t.value_index_1), tt); |
| 610 | + |
| 611 | + case type_class_t::adt: |
| 612 | + case type_class_t::adt_pick: |
| 613 | + { |
| 614 | + const auto &adt = tt.resolve_table_index<name_source_size_t>(t.value_index_1); |
| 615 | + return adt.name; |
| 616 | + } |
| 617 | + case type_class_t::tuple: |
| 618 | + { |
| 619 | + const auto &tuple = tt.resolve_table_index<tuple_item_t>(t.value_index_1); |
| 620 | + |
| 621 | + std::stringstream ss; |
| 622 | + ss << '('; |
| 623 | + |
| 624 | + auto first = true; |
| 625 | + for (const auto &t_t : tuple.id_table) |
| 626 | + { |
| 627 | + if (!first) |
| 628 | + ss << ','; |
| 629 | + |
| 630 | + ss << to_string(t_t.type, tt); |
| 631 | + first = false; |
| 632 | + } |
| 633 | + |
| 634 | + ss << ')'; |
| 635 | + return ss.str(); |
| 636 | + } |
| 637 | + case type_class_t::module: |
| 638 | + return tt.resolve_table_index<std::string>(t.value_index_1); |
| 639 | + |
| 640 | + case type_class_t::function: |
| 641 | + { |
| 642 | + std::stringstream ss; |
| 643 | + ss << tt.resolve_table_index<std::string>(t.value_index_1) |
| 644 | + << ' ' |
| 645 | + << to_string(tt.resolve_table_index<type_t>(t.value_index_2), tt); |
| 646 | + |
| 647 | + return ss.str(); |
| 648 | + } |
| 649 | + |
| 650 | + default: |
| 651 | + throw std::runtime_error{ "Invalid type value" }; |
| 652 | + } |
| 653 | + } |
| 654 | + |
| 655 | + std::string to_string(const func_item_t &f, const type_table_t &tt, function_name_format_t fmt) |
| 656 | + { |
| 657 | + std::stringstream ss; |
| 658 | + |
| 659 | + if (util::has_flag(fmt, function_name_format_t::name)) |
| 660 | + ss << f.name; |
| 661 | + |
| 662 | + auto has_argument = false; |
| 663 | + if (util::has_flag(fmt, function_name_format_t::arguments)) |
| 664 | + { |
| 665 | + has_argument = true; |
| 666 | + ss << '('; |
| 667 | + |
| 668 | + auto first = true; |
| 669 | + for (const auto &at : f.args) |
| 670 | + { |
| 671 | + if (!first) |
| 672 | + ss << ','; |
| 673 | + |
| 674 | + ss << to_string(at.type, tt); |
| 675 | + first = false; |
| 676 | + } |
| 677 | + |
| 678 | + ss << ')'; |
| 679 | + } |
| 680 | + |
| 681 | + if (util::has_flag(fmt, function_name_format_t::return_type)) |
| 682 | + { |
| 683 | + if (has_argument) |
| 684 | + ss << ':'; |
| 685 | + |
| 686 | + ss << to_string(f.return_type, tt); |
| 687 | + } |
| 688 | + |
| 689 | + return ss.str(); |
| 690 | + } |
| 691 | + |
| 574 | 692 | class sbl_symbol_debug final : public symbol_debug_t |
| 575 | 693 | { |
| 576 | 694 | public: |
| @@ -632,12 +750,21 @@ namespace · 55 unmodified lines |
| 632 | 750 | return true; |
| 633 | 751 | } |
| 634 | 752 | |
| 635 | | − const std::string ¤t_function_name() const override |
| 753 | + std::string current_function_name(function_name_format_t f) const override |
| 636 | 754 | { |
| 637 | | − for (auto &e : _file->func_table) |
| 755 | + try |
| 756 | + { |
| 757 | + for (auto &e : _file->func_table) |
| 758 | + { |
| 759 | + if (e.entry_pc <= _current_pc && _current_pc <= e.limit_pc) |
| 760 | + return to_string(e, _file->type_table, f); |
| 761 | + } |
| 762 | + } |
| 763 | + catch (const std::exception &e) |
| 638 | 764 | { |
| 639 | | − if (e.entry_pc <= _current_pc && _current_pc <= e.limit_pc) |
| 640 | | − return e.name; |
| 765 | + // Avoid crashing during debugging |
| 766 | + assert(false && "The SBL file appears to be corrupt or inconsistent"); |
| 767 | + throw std::runtime_error{ e.what() }; |
| 641 | 768 | } |
| 642 | 769 | |
| 643 | 770 | throw std::runtime_error{ "Unknown function" }; |