Validate constant expression. See "include/validator/validator.h".
| 855 | |
| 856 | // Validate constant expression. See "include/validator/validator.h". |
| 857 | Expect<void> Validator::validateConstExpr(AST::InstrView Instrs, |
| 858 | Span<const ValType> Returns) { |
| 859 | for (auto &Instr : Instrs) { |
| 860 | // Only these instructions are accepted. |
| 861 | switch (Instr.getOpCode()) { |
| 862 | case OpCode::Global__get: { |
| 863 | // For the initialization case, global indices must be imported globals. |
| 864 | auto GlobIdx = Instr.getTargetIndex(); |
| 865 | uint32_t ValidGlobalSize = Checker.getNumImportGlobals(); |
| 866 | if (Conf.hasProposal(Proposal::FunctionReferences)) { |
| 867 | ValidGlobalSize = static_cast<uint32_t>(Checker.getGlobals().size()); |
| 868 | } |
| 869 | if (GlobIdx >= ValidGlobalSize) { |
| 870 | spdlog::error(ErrCode::Value::InvalidGlobalIdx); |
| 871 | spdlog::error(ErrInfo::InfoForbidIndex(ErrInfo::IndexCategory::Global, |
| 872 | GlobIdx, ValidGlobalSize)); |
| 873 | spdlog::error( |
| 874 | ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); |
| 875 | return Unexpect(ErrCode::Value::InvalidGlobalIdx); |
| 876 | } |
| 877 | if (Checker.getGlobals()[GlobIdx].second != ValMut::Const) { |
| 878 | spdlog::error(ErrCode::Value::ConstExprRequired); |
| 879 | spdlog::error( |
| 880 | ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); |
| 881 | return Unexpect(ErrCode::Value::ConstExprRequired); |
| 882 | } |
| 883 | break; |
| 884 | } |
| 885 | case OpCode::Ref__func: { |
| 886 | // In a const expression, add the reference to the context. |
| 887 | auto FuncIdx = Instr.getTargetIndex(); |
| 888 | if (FuncIdx >= Checker.getFunctions().size()) { |
| 889 | // Function index out of range. |
| 890 | spdlog::error(ErrCode::Value::InvalidFuncIdx); |
| 891 | spdlog::error(ErrInfo::InfoForbidIndex( |
| 892 | ErrInfo::IndexCategory::Function, FuncIdx, |
| 893 | static_cast<uint32_t>(Checker.getFunctions().size()))); |
| 894 | spdlog::error( |
| 895 | ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); |
| 896 | return Unexpect(ErrCode::Value::InvalidFuncIdx); |
| 897 | } |
| 898 | Checker.addRef(Instr.getTargetIndex()); |
| 899 | break; |
| 900 | } |
| 901 | case OpCode::I32__const: |
| 902 | case OpCode::I64__const: |
| 903 | case OpCode::F32__const: |
| 904 | case OpCode::F64__const: |
| 905 | case OpCode::Ref__null: |
| 906 | case OpCode::V128__const: |
| 907 | case OpCode::End: |
| 908 | case OpCode::Struct__new: |
| 909 | case OpCode::Struct__new_default: |
| 910 | case OpCode::Array__new: |
| 911 | case OpCode::Array__new_default: |
| 912 | case OpCode::Array__new_fixed: |
| 913 | case OpCode::Any__convert_extern: |
| 914 | case OpCode::Extern__convert_any: |
nothing calls this directly
no test coverage detected