summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binary-reader-ir.cc6
-rw-r--r--src/binary-reader-logging.cc8
-rw-r--r--src/binary-reader-logging.h2
-rw-r--r--src/binary-reader-nop.h2
-rw-r--r--src/binary-reader.cc16
-rw-r--r--src/binary-reader.h2
-rw-r--r--src/binary-writer.cc16
-rw-r--r--src/interp/binary-reader-interp.cc6
-rw-r--r--src/interp/interp-disassemble.cc1
-rw-r--r--src/interp/interp-trace.cc1
-rw-r--r--src/interp/interp.cc1
-rw-r--r--src/ir.h8
-rw-r--r--src/opcode.def1
-rw-r--r--src/type-checker.cc17
-rw-r--r--src/type-checker.h2
-rw-r--r--src/validator.cc4
-rw-r--r--src/wast-parser.cc13
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();
diff --git a/src/ir.h b/src/ir.h
index ac2f6cd4..44cda181 100644
--- a/src/ir.h
+++ b/src/ir.h
@@ -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();