|
32 | 32 | #include "wabt/intrusive-list.h" |
33 | 33 | #include "wabt/opcode.h" |
34 | 34 |
|
| 35 | +#include <optional> |
| 36 | + |
35 | 37 | namespace wabt { |
36 | 38 |
|
37 | 39 | struct Module; |
@@ -702,15 +704,90 @@ class CallIndirectExpr : public ExprMixin<ExprType::CallIndirect> { |
702 | 704 |
|
703 | 705 | class CodeMetadataExpr : public ExprMixin<ExprType::CodeMetadata> { |
704 | 706 | public: |
| 707 | + struct CallTarget { |
| 708 | + Var func; |
| 709 | + uint32_t frequency; |
| 710 | + }; |
| 711 | + struct CompilationPriority { |
| 712 | + uint32_t compilation_priority; |
| 713 | + std::optional<uint32_t> optimization_priority; |
| 714 | + }; |
| 715 | + struct InstructionFrequency { |
| 716 | + uint32_t frequency; |
| 717 | + }; |
| 718 | + enum class Type { |
| 719 | + Binary, |
| 720 | + CompilationHint, |
| 721 | + InstructionFrequency, |
| 722 | + CallTargets |
| 723 | + }; |
| 724 | + |
705 | 725 | explicit CodeMetadataExpr(std::string_view name, |
706 | 726 | std::vector<uint8_t> data, |
707 | 727 | const Location& loc = Location()) |
| 728 | + : ExprMixin<ExprType::CodeMetadata>(loc), name(name), type(Type::Binary) { |
| 729 | + new (&hint.data) std::vector<uint8_t>(std::move(data)); |
| 730 | + } |
| 731 | + |
| 732 | + explicit CodeMetadataExpr(std::string_view name, |
| 733 | + CompilationPriority compilation_priority, |
| 734 | + const Location& loc = Location()) |
| 735 | + : ExprMixin<ExprType::CodeMetadata>(loc), |
| 736 | + name(name), |
| 737 | + type(Type::CompilationHint) { |
| 738 | + new (&hint.compilation_priority) CompilationPriority(compilation_priority); |
| 739 | + } |
| 740 | + |
| 741 | + explicit CodeMetadataExpr(std::string_view name, |
| 742 | + InstructionFrequency instruction_frequency, |
| 743 | + const Location& loc = Location()) |
708 | 744 | : ExprMixin<ExprType::CodeMetadata>(loc), |
709 | | - name(std::move(name)), |
710 | | - data(std::move(data)) {} |
| 745 | + name(name), |
| 746 | + type(Type::InstructionFrequency) { |
| 747 | + new (&hint.instruction_frequency) |
| 748 | + InstructionFrequency(instruction_frequency); |
| 749 | + } |
| 750 | + |
| 751 | + explicit CodeMetadataExpr(std::string_view name, |
| 752 | + std::vector<CallTarget> targets, |
| 753 | + const Location& loc = Location()) |
| 754 | + : ExprMixin<ExprType::CodeMetadata>(loc), |
| 755 | + name(name), |
| 756 | + type(Type::CallTargets) { |
| 757 | + new (&hint.call_targets) std::vector<CallTarget>(std::move(targets)); |
| 758 | + } |
| 759 | + |
| 760 | + ~CodeMetadataExpr() override { |
| 761 | + switch (type) { |
| 762 | + case Type::Binary: |
| 763 | + hint.data.~vector(); |
| 764 | + break; |
| 765 | + case Type::CallTargets: |
| 766 | + hint.call_targets.~vector(); |
| 767 | + break; |
| 768 | + default: |
| 769 | + // CompilationHint and InstructionFrequency do not allocate memory.; |
| 770 | + break; |
| 771 | + } |
| 772 | + } |
| 773 | + |
| 774 | + bool is_function_annotation() const { return type == Type::CompilationHint; } |
| 775 | + |
| 776 | + // convert non-binary hints to binary |
| 777 | + std::vector<uint8_t> serialize(const Module&) const; |
711 | 778 |
|
712 | 779 | std::string_view name; |
713 | | - std::vector<uint8_t> data; |
| 780 | + Type type; |
| 781 | + |
| 782 | + private: |
| 783 | + union Hint { |
| 784 | + std::vector<uint8_t> data; |
| 785 | + CompilationPriority compilation_priority; |
| 786 | + InstructionFrequency instruction_frequency{}; |
| 787 | + std::vector<CallTarget> call_targets; |
| 788 | + Hint() {} |
| 789 | + ~Hint() {} |
| 790 | + } hint; |
714 | 791 | }; |
715 | 792 |
|
716 | 793 | class ReturnCallIndirectExpr : public ExprMixin<ExprType::ReturnCallIndirect> { |
|
0 commit comments