diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binary-reader-ir.cc | 6 | ||||
-rw-r--r-- | src/binary-reader-logging.cc | 8 | ||||
-rw-r--r-- | src/binary-reader-logging.h | 2 | ||||
-rw-r--r-- | src/binary-reader-nop.h | 2 | ||||
-rw-r--r-- | src/binary-reader.cc | 16 | ||||
-rw-r--r-- | src/binary-reader.h | 2 | ||||
-rw-r--r-- | src/binary-writer.cc | 16 | ||||
-rw-r--r-- | src/interp/binary-reader-interp.cc | 6 | ||||
-rw-r--r-- | src/interp/interp-disassemble.cc | 1 | ||||
-rw-r--r-- | src/interp/interp-trace.cc | 1 | ||||
-rw-r--r-- | src/interp/interp.cc | 1 | ||||
-rw-r--r-- | src/ir.h | 8 | ||||
-rw-r--r-- | src/opcode.def | 1 | ||||
-rw-r--r-- | src/type-checker.cc | 17 | ||||
-rw-r--r-- | src/type-checker.h | 2 | ||||
-rw-r--r-- | src/validator.cc | 4 | ||||
-rw-r--r-- | src/wast-parser.cc | 13 |
17 files changed, 82 insertions, 24 deletions
diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc index bef31833..8f8526f1 100644 --- a/src/binary-reader-ir.cc +++ b/src/binary-reader-ir.cc @@ -186,7 +186,7 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnNopExpr() override; Result OnRethrowExpr() override; Result OnReturnExpr() override; - Result OnSelectExpr() override; + Result OnSelectExpr(Type result_type) override; Result OnStoreExpr(Opcode opcode, uint32_t alignment_log2, Address offset) override; @@ -914,8 +914,8 @@ Result BinaryReaderIR::OnReturnExpr() { return AppendExpr(MakeUnique<ReturnExpr>()); } -Result BinaryReaderIR::OnSelectExpr() { - return AppendExpr(MakeUnique<SelectExpr>()); +Result BinaryReaderIR::OnSelectExpr(Type result_type) { + return AppendExpr(MakeUnique<SelectExpr>(TypeVector{result_type})); } Result BinaryReaderIR::OnGlobalSetExpr(Index global_index) { diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc index 1d784828..98e503b6 100644 --- a/src/binary-reader-logging.cc +++ b/src/binary-reader-logging.cc @@ -78,7 +78,7 @@ void BinaryReaderLogging::WriteIndent() { void BinaryReaderLogging::LogType(Type type) { if (IsTypeIndex(type)) { - LOGF_NOINDENT("funcidx[%d]", static_cast<int>(type)); + LOGF_NOINDENT("typeidx[%d]", static_cast<int>(type)); } else { LOGF_NOINDENT("%s", GetTypeName(type)); } @@ -343,6 +343,11 @@ Result BinaryReaderLogging::OnLoopExpr(Type sig_type) { return reader_->OnLoopExpr(sig_type); } +Result BinaryReaderLogging::OnSelectExpr(Type return_type) { + LOGF("OnSelectExpr(return_type: %s)\n", GetTypeName(return_type)); + return reader_->OnSelectExpr(return_type); +} + Result BinaryReaderLogging::OnTryExpr(Type sig_type) { LOGF("OnTryExpr(sig: "); LogType(sig_type); @@ -742,7 +747,6 @@ DEFINE_INDEX_DESC(OnReturnCallExpr, "func_index") DEFINE_INDEX_INDEX(OnReturnCallIndirectExpr, "sig_index", "table_index") DEFINE0(OnReturnExpr) -DEFINE0(OnSelectExpr) DEFINE_LOAD_STORE_OPCODE(OnLoadSplatExpr); DEFINE_LOAD_STORE_OPCODE(OnStoreExpr); DEFINE_INDEX_DESC(OnThrowExpr, "event_index") diff --git a/src/binary-reader-logging.h b/src/binary-reader-logging.h index 237f353b..9e12d434 100644 --- a/src/binary-reader-logging.h +++ b/src/binary-reader-logging.h @@ -204,7 +204,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Result OnReturnCallExpr(Index func_index) override; Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) override; Result OnReturnExpr() override; - Result OnSelectExpr() override; + Result OnSelectExpr(Type result_type) override; Result OnStoreExpr(Opcode opcode, uint32_t alignment_log2, Address offset) override; diff --git a/src/binary-reader-nop.h b/src/binary-reader-nop.h index e34cb669..2426103d 100644 --- a/src/binary-reader-nop.h +++ b/src/binary-reader-nop.h @@ -272,7 +272,7 @@ class BinaryReaderNop : public BinaryReaderDelegate { Result OnReturnCallExpr(Index sig_index) override { return Result::Ok; } Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) override { return Result::Ok; } Result OnReturnExpr() override { return Result::Ok; } - Result OnSelectExpr() override { return Result::Ok; } + Result OnSelectExpr(Type result_type) override { return Result::Ok; } Result OnStoreExpr(Opcode opcode, uint32_t alignment_log2, Address offset) override { diff --git a/src/binary-reader.cc b/src/binary-reader.cc index 146d6516..67161515 100644 --- a/src/binary-reader.cc +++ b/src/binary-reader.cc @@ -636,8 +636,22 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) { CALLBACK0(OnOpcodeBare); break; + case Opcode::SelectT: { + Index count; + CHECK_RESULT(ReadCount(&count, "num result types")); + if (count != 1) { + PrintError("invalid arity in select instrcution: %u", count); + return Result::Error; + } + Type result_type; + CHECK_RESULT(ReadType(&result_type, "select result type")); + CALLBACK(OnSelectExpr, result_type); + CALLBACK0(OnOpcodeBare); + break; + } + case Opcode::Select: - CALLBACK0(OnSelectExpr); + CALLBACK(OnSelectExpr, Type::Any); CALLBACK0(OnOpcodeBare); break; diff --git a/src/binary-reader.h b/src/binary-reader.h index 08eced85..b5f97a8f 100644 --- a/src/binary-reader.h +++ b/src/binary-reader.h @@ -261,7 +261,7 @@ class BinaryReaderDelegate { virtual Result OnReturnCallExpr(Index func_index) = 0; virtual Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) = 0; - virtual Result OnSelectExpr() = 0; + virtual Result OnSelectExpr(Type result_type) = 0; virtual Result OnStoreExpr(Opcode opcode, uint32_t alignment_log2, Address offset) = 0; diff --git a/src/binary-writer.cc b/src/binary-writer.cc index 409d385b..b0828723 100644 --- a/src/binary-writer.cc +++ b/src/binary-writer.cc @@ -678,9 +678,21 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { case ExprType::Return: WriteOpcode(stream_, Opcode::Return); break; - case ExprType::Select: - WriteOpcode(stream_, Opcode::Select); + case ExprType::Select: { + auto* select_expr = cast<SelectExpr>(expr); + if (select_expr->result_type.size() == 1 && + select_expr->result_type[0] == Type::Any) { + WriteOpcode(stream_, Opcode::Select); + } else { + WriteOpcode(stream_, Opcode::SelectT); + WriteU32Leb128(stream_, select_expr->result_type.size(), + "num result types"); + for (Type t : select_expr->result_type) { + WriteType(stream_, t, "result type"); + } + } break; + } case ExprType::Store: WriteLoadStoreExpr<StoreExpr>(func, expr, "store offset"); break; diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc index 4d5b9e29..74d4b9ef 100644 --- a/src/interp/binary-reader-interp.cc +++ b/src/interp/binary-reader-interp.cc @@ -186,7 +186,7 @@ class BinaryReaderInterp : public BinaryReaderNop { wabt::Result OnRefIsNullExpr() override; wabt::Result OnNopExpr() override; wabt::Result OnReturnExpr() override; - wabt::Result OnSelectExpr() override; + wabt::Result OnSelectExpr(Type result_type) override; wabt::Result OnStoreExpr(wabt::Opcode opcode, uint32_t alignment_log2, Address offset) override; @@ -1816,8 +1816,8 @@ wabt::Result BinaryReaderInterp::OnReturnExpr() { return wabt::Result::Ok; } -wabt::Result BinaryReaderInterp::OnSelectExpr() { - CHECK_RESULT(typechecker_.OnSelect()); +wabt::Result BinaryReaderInterp::OnSelectExpr(Type result_type) { + CHECK_RESULT(typechecker_.OnSelect(result_type)); CHECK_RESULT(EmitOpcode(Opcode::Select)); return wabt::Result::Ok; } diff --git a/src/interp/interp-disassemble.cc b/src/interp/interp-disassemble.cc index 7890bfcc..251393b0 100644 --- a/src/interp/interp-disassemble.cc +++ b/src/interp/interp-disassemble.cc @@ -43,6 +43,7 @@ void Environment::Disassemble(Stream* stream, assert(!opcode.IsInvalid()); switch (opcode) { case Opcode::Select: + case Opcode::SelectT: case Opcode::V128BitSelect: stream->Writef("%s %%[-3], %%[-2], %%[-1]\n", opcode.GetName()); break; diff --git a/src/interp/interp-trace.cc b/src/interp/interp-trace.cc index ec2211fe..a9952cdf 100644 --- a/src/interp/interp-trace.cc +++ b/src/interp/interp-trace.cc @@ -34,6 +34,7 @@ void Thread::Trace(Stream* stream) { assert(!opcode.IsInvalid()); switch (opcode) { case Opcode::Select: + case Opcode::SelectT: // TODO(binji): We don't know the type here so we can't display the value // to the user. This used to display the full 64-bit value, but that // will potentially display garbage if the value is 32-bit. diff --git a/src/interp/interp.cc b/src/interp/interp.cc index 82a53c1d..7608b7e5 100644 --- a/src/interp/interp.cc +++ b/src/interp/interp.cc @@ -1805,6 +1805,7 @@ Result Thread::Run(int num_instructions) { Opcode opcode = ReadOpcode(&pc); assert(!opcode.IsInvalid()); switch (opcode) { + case Opcode::SelectT: case Opcode::Select: { uint32_t cond = Pop<uint32_t>(); Value false_ = Pop(); @@ -274,7 +274,6 @@ typedef ExprMixin<ExprType::MemoryFill> MemoryFillExpr; typedef ExprMixin<ExprType::Nop> NopExpr; typedef ExprMixin<ExprType::Rethrow> RethrowExpr; typedef ExprMixin<ExprType::Return> ReturnExpr; -typedef ExprMixin<ExprType::Select> SelectExpr; typedef ExprMixin<ExprType::Unreachable> UnreachableExpr; typedef ExprMixin<ExprType::RefNull> RefNullExpr; typedef ExprMixin<ExprType::RefIsNull> RefIsNullExpr; @@ -342,6 +341,13 @@ typedef VarExpr<ExprType::TableGrow> TableGrowExpr; typedef VarExpr<ExprType::TableSize> TableSizeExpr; typedef VarExpr<ExprType::TableFill> TableFillExpr; +class SelectExpr : public ExprMixin<ExprType::Select> { + public: + SelectExpr(TypeVector type, const Location& loc = Location()) + : ExprMixin<ExprType::Select>(loc), result_type(type) {} + TypeVector result_type; +}; + class TableInitExpr : public ExprMixin<ExprType::TableInit> { public: TableInitExpr(const Var& segment_index, diff --git a/src/opcode.def b/src/opcode.def index 7686370f..96df5f5a 100644 --- a/src/opcode.def +++ b/src/opcode.def @@ -57,6 +57,7 @@ WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x12, ReturnCall, "return_call", " WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x13, ReturnCallIndirect, "return_call_indirect", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x1a, Drop, "drop", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x1b, Select, "select", "") +WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x1c, SelectT, "select", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x20, LocalGet, "local.get", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x21, LocalSet, "local.set", "") WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x22, LocalTee, "local.tee", "") diff --git a/src/type-checker.cc b/src/type-checker.cc index db30e49f..5cd9330a 100644 --- a/src/type-checker.cc +++ b/src/type-checker.cc @@ -714,7 +714,7 @@ Result TypeChecker::OnReturn() { return result; } -Result TypeChecker::OnSelect() { +Result TypeChecker::OnSelect(Type expected) { Result result = Result::Ok; Type type1 = Type::Any; Type type2 = Type::Any; @@ -722,9 +722,18 @@ Result TypeChecker::OnSelect() { result |= PeekAndCheckType(0, Type::I32); result |= PeekType(1, &type1); result |= PeekType(2, &type2); - result |= CheckType(type1, type2); - result_type = type1; - PrintStackIfFailed(result, "select", type1, type1, Type::I32); + if (expected == Type::Any) { + if (IsRefType(type1) || IsRefType(type2)) { + result = Result::Error; + } else { + result |= CheckType(type1, type2); + result_type = type1; + } + } else { + result |= CheckType(type1, expected); + result |= CheckType(type2, expected); + } + PrintStackIfFailed(result, "select", result_type, result_type, Type::I32); result |= DropTypes(3); PushType(result_type); return result; diff --git a/src/type-checker.h b/src/type-checker.h index 45c6dcdc..49f1de83 100644 --- a/src/type-checker.h +++ b/src/type-checker.h @@ -112,7 +112,7 @@ class TypeChecker { Result OnRefIsNullExpr(); Result OnRethrow(); Result OnReturn(); - Result OnSelect(); + Result OnSelect(Type expected); Result OnSimdLaneOp(Opcode, uint64_t); Result OnSimdShuffleOp(Opcode, v128); Result OnStore(Opcode); diff --git a/src/validator.cc b/src/validator.cc index 388863cd..d8ac6666 100644 --- a/src/validator.cc +++ b/src/validator.cc @@ -885,8 +885,8 @@ Result Validator::OnReturnCallIndirectExpr(ReturnCallIndirectExpr* expr) { Result Validator::OnSelectExpr(SelectExpr* expr) { expr_loc_ = &expr->loc; - typechecker_.OnSelect(); - return Result::Ok; + assert(expr->result_type.size()); + return typechecker_.OnSelect(expr->result_type[0]); } Result Validator::OnStoreExpr(StoreExpr* expr) { diff --git a/src/wast-parser.cc b/src/wast-parser.cc index 3a1042da..635b1b3a 100644 --- a/src/wast-parser.cc +++ b/src/wast-parser.cc @@ -1533,10 +1533,19 @@ Result WastParser::ParsePlainInstr(std::unique_ptr<Expr>* out_expr) { out_expr->reset(new DropExpr(loc)); break; - case TokenType::Select: + case TokenType::Select: { Consume(); - out_expr->reset(new SelectExpr(loc)); + TypeVector result; + if (options_->features.reference_types_enabled() && + MatchLpar(TokenType::Result)) { + CHECK_RESULT(ParseValueTypeList(&result)); + EXPECT(Rpar); + } else { + result.push_back(Type::Any); + } + out_expr->reset(new SelectExpr(result, loc)); break; + } case TokenType::Br: Consume(); |