Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for ref.test instruction #2529

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/wabt/binary-reader-logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
Result OnRefFuncExpr(Index index) override;
Result OnRefNullExpr(Type type) override;
Result OnRefIsNullExpr() override;
Result OnRefTestExpr(Type type) override;
Result OnNopExpr() override;
Result OnRethrowExpr(Index depth) override;
Result OnReturnCallExpr(Index func_index) override;
Expand Down
1 change: 1 addition & 0 deletions include/wabt/binary-reader-nop.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
Result OnRefFuncExpr(Index func_index) override { return Result::Ok; }
Result OnRefNullExpr(Type type) override { return Result::Ok; }
Result OnRefIsNullExpr() override { return Result::Ok; }
Result OnRefTestExpr(Type type) override { return Result::Ok; }
Result OnNopExpr() override { return Result::Ok; }
Result OnRethrowExpr(Index depth) override { return Result::Ok; }
Result OnReturnCallExpr(Index sig_index) override { return Result::Ok; }
Expand Down
1 change: 1 addition & 0 deletions include/wabt/binary-reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ class BinaryReaderDelegate {
virtual Result OnRefFuncExpr(Index func_index) = 0;
virtual Result OnRefNullExpr(Type type) = 0;
virtual Result OnRefIsNullExpr() = 0;
virtual Result OnRefTestExpr(Type check_type) = 0;
virtual Result OnNopExpr() = 0;
virtual Result OnRethrowExpr(Index depth) = 0;
virtual Result OnReturnExpr() = 0;
Expand Down
2 changes: 2 additions & 0 deletions include/wabt/expr-visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ class ExprVisitor::Delegate {
virtual Result OnRefFuncExpr(RefFuncExpr*) = 0;
virtual Result OnRefNullExpr(RefNullExpr*) = 0;
virtual Result OnRefIsNullExpr(RefIsNullExpr*) = 0;
virtual Result OnRefTestExpr(RefTestExpr*) = 0;
virtual Result OnNopExpr(NopExpr*) = 0;
virtual Result OnReturnExpr(ReturnExpr*) = 0;
virtual Result OnReturnCallExpr(ReturnCallExpr*) = 0;
Expand Down Expand Up @@ -189,6 +190,7 @@ class ExprVisitor::DelegateNop : public ExprVisitor::Delegate {
Result OnRefFuncExpr(RefFuncExpr*) override { return Result::Ok; }
Result OnRefNullExpr(RefNullExpr*) override { return Result::Ok; }
Result OnRefIsNullExpr(RefIsNullExpr*) override { return Result::Ok; }
Result OnRefTestExpr(RefTestExpr*) override { return Result::Ok; }
Result OnNopExpr(NopExpr*) override { return Result::Ok; }
Result OnReturnExpr(ReturnExpr*) override { return Result::Ok; }
Result OnReturnCallExpr(ReturnCallExpr*) override { return Result::Ok; }
Expand Down
9 changes: 9 additions & 0 deletions include/wabt/ir.h
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ enum class ExprType {
RefIsNull,
RefFunc,
RefNull,
RefTest,
Rethrow,
Return,
ReturnCall,
Expand Down Expand Up @@ -553,6 +554,14 @@ class RefTypeExpr : public ExprMixin<TypeEnum> {
using RefNullExpr = RefTypeExpr<ExprType::RefNull>;
using RefIsNullExpr = ExprMixin<ExprType::RefIsNull>;

class RefTestExpr : public ExprMixin<ExprType::RefTest> {
public:
RefTestExpr(Var type, const Location& loc = Location())
: ExprMixin<ExprType::RefTest>(loc), type(type) {}

Var type;
};

template <ExprType TypeEnum>
class OpcodeExpr : public ExprMixin<TypeEnum> {
public:
Expand Down
1 change: 1 addition & 0 deletions include/wabt/opcode.def
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ WABT_OPCODE(___, I32, ___, I32, 0, 0xfc, 0x11, TableFill, "table.fill", "")
WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd0, RefNull, "ref.null", "")
WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd1, RefIsNull, "ref.is_null", "")
WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd2, RefFunc, "ref.func", "")
WABT_OPCODE(I32, ___, ___, ___, 0, 0xfb, 0x14, RefTest, "ref.test", "")

/* Simd opcodes */
WABT_OPCODE(V128, I32, ___, ___, 16, 0xfd, 0x00, V128Load, "v128.load", "")
Expand Down
5 changes: 3 additions & 2 deletions include/wabt/opcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,17 @@ struct Opcode {
Address GetAlignment(Address alignment) const;

static bool IsPrefixByte(uint8_t byte) {
return byte == kMathPrefix || byte == kThreadsPrefix || byte == kSimdPrefix;
return byte == kMathPrefix || byte == kThreadsPrefix || byte == kSimdPrefix || byte == kReferencePrefix;
}

bool IsEnabled(const Features& features) const;
bool IsInvalid() const { return enum_ >= Invalid; }

private:
static constexpr uint32_t kReferencePrefix = 0xfb;
static constexpr uint32_t kMathPrefix = 0xfc;
static constexpr uint32_t kThreadsPrefix = 0xfe;
static constexpr uint32_t kSimdPrefix = 0xfd;
static constexpr uint32_t kThreadsPrefix = 0xfe;

struct Info {
const char* name;
Expand Down
1 change: 1 addition & 0 deletions include/wabt/shared-validator.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ class SharedValidator {
Result OnRefFunc(const Location&, Var func_var);
Result OnRefIsNull(const Location&);
Result OnRefNull(const Location&, Type type);
Result OnRefTest(const Location&, Var type);
Result OnRethrow(const Location&, Var depth);
Result OnReturnCall(const Location&, Var func_var);
Result OnReturnCallIndirect(const Location&, Var sig_var, Var table_var);
Expand Down
1 change: 1 addition & 0 deletions include/wabt/token.def
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ WABT_TOKEN(RefExtern, "ref.extern")
WABT_TOKEN(RefFunc, "ref.func")
WABT_TOKEN(RefIsNull, "ref.is_null")
WABT_TOKEN(RefNull, "ref.null")
WABT_TOKEN(RefTest, "ref.test")
WABT_TOKEN(Rethrow, "rethrow")
WABT_TOKEN(ReturnCallIndirect, "return_call_indirect")
WABT_TOKEN(ReturnCall, "return_call")
Expand Down
1 change: 1 addition & 0 deletions include/wabt/type-checker.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ class TypeChecker {
Result OnRefFuncExpr(Index func_type, bool force_generic_funcref);
Result OnRefNullExpr(Type type);
Result OnRefIsNullExpr();
Result OnRefTestExpr();
Result OnRethrow(Index depth);
Result OnReturn();
Result OnSelect(const TypeVector& result_types);
Expand Down
6 changes: 6 additions & 0 deletions src/apply-names.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class NameApplier : public ExprVisitor::DelegateNop {
Result OnBrTableExpr(BrTableExpr*) override;
Result OnCallExpr(CallExpr*) override;
Result OnRefFuncExpr(RefFuncExpr*) override;
Result OnRefTestExpr(RefTestExpr*) override;
Result OnCallIndirectExpr(CallIndirectExpr*) override;
Result OnReturnCallExpr(ReturnCallExpr*) override;
Result OnReturnCallIndirectExpr(ReturnCallIndirectExpr*) override;
Expand Down Expand Up @@ -423,6 +424,11 @@ Result NameApplier::OnRefFuncExpr(RefFuncExpr* expr) {
return Result::Ok;
}

Result NameApplier::OnRefTestExpr(RefTestExpr* expr) {
CHECK_RESULT(UseNameForFuncTypeVar(&expr->type));
return Result::Ok;
}

Result NameApplier::OnCallIndirectExpr(CallIndirectExpr* expr) {
if (expr->decl.has_func_type) {
CHECK_RESULT(UseNameForFuncTypeVar(&expr->decl.type_var));
Expand Down
8 changes: 8 additions & 0 deletions src/binary-reader-ir.cc
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ class BinaryReaderIR : public BinaryReaderNop {
Result OnRefFuncExpr(Index func_index) override;
Result OnRefNullExpr(Type type) override;
Result OnRefIsNullExpr() override;
Result OnRefTestExpr(Type type) override;
Result OnNopExpr() override;
Result OnRethrowExpr(Index depth) override;
Result OnReturnExpr() override;
Expand Down Expand Up @@ -1160,6 +1161,13 @@ Result BinaryReaderIR::OnRefIsNullExpr() {
return AppendExpr(std::make_unique<RefIsNullExpr>());
}

Result BinaryReaderIR::OnRefTestExpr(Type type) {
assert(type.IsIndex());
Index type_index = type.GetIndex();
return AppendExpr(
std::make_unique<RefTestExpr>(Var(type_index, GetLocation())));
}

Result BinaryReaderIR::OnNopExpr() {
return AppendExpr(std::make_unique<NopExpr>());
}
Expand Down
1 change: 1 addition & 0 deletions src/binary-reader-logging.cc
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,7 @@ DEFINE_INDEX(OnTableSizeExpr)
DEFINE_INDEX_DESC(OnTableFillExpr, "table index")
DEFINE_INDEX(OnRefFuncExpr)
DEFINE_TYPE(OnRefNullExpr)
DEFINE_TYPE(OnRefTestExpr)
DEFINE0(OnRefIsNullExpr)
DEFINE0(OnNopExpr)
DEFINE_INDEX_DESC(OnRethrowExpr, "depth");
Expand Down
7 changes: 7 additions & 0 deletions src/binary-reader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1925,6 +1925,13 @@ Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) {
CALLBACK(OnOpcodeBare);
break;

case Opcode::RefTest:
Type type;
CHECK_RESULT(ReadType(&type, "ref.test type"));
CALLBACK(OnRefTestExpr, type);
CALLBACK(OnOpcodeBare);
break;

case Opcode::CallRef:
CALLBACK(OnCallRefExpr);
CALLBACK(OnOpcodeBare);
Expand Down
7 changes: 7 additions & 0 deletions src/binary-writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,13 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
WriteU32Leb128WithReloc(index, "function index", RelocType::FuncIndexLEB);
break;
}
case ExprType::RefTest: {
WriteOpcode(stream_, Opcode::RefTest);
WriteType(stream_,
module_->GetFuncTypeIndex(cast<RefTestExpr>(expr)->type),
"ref.test type");
break;
}
case ExprType::RefNull: {
WriteOpcode(stream_, Opcode::RefNull);
WriteType(stream_, cast<RefNullExpr>(expr)->type, "ref.null type");
Expand Down
1 change: 1 addition & 0 deletions src/c-writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4148,6 +4148,7 @@ void CWriter::Write(const ExprList& exprs) {
case ExprType::CallRef:
case ExprType::ThrowRef:
case ExprType::TryTable:
case ExprType::RefTest:
UNIMPLEMENTED("...");
break;
}
Expand Down
4 changes: 4 additions & 0 deletions src/expr-visitor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,10 @@ Result ExprVisitor::HandleDefaultState(Expr* expr) {
CHECK_RESULT(delegate_->OnRefIsNullExpr(cast<RefIsNullExpr>(expr)));
break;

case ExprType::RefTest:
CHECK_RESULT(delegate_->OnRefTestExpr(cast<RefTestExpr>(expr)));
break;

case ExprType::Nop:
CHECK_RESULT(delegate_->OnNopExpr(cast<NopExpr>(expr)));
break;
Expand Down
12 changes: 12 additions & 0 deletions src/interp/binary-reader-interp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ class BinaryReaderInterp : public BinaryReaderNop {
Result OnRefFuncExpr(Index func_index) override;
Result OnRefNullExpr(Type type) override;
Result OnRefIsNullExpr() override;
Result OnRefTestExpr(Type type) override;
Result OnNopExpr() override;
Result OnRethrowExpr(Index depth) override;
Result OnReturnExpr() override;
Expand Down Expand Up @@ -1393,6 +1394,17 @@ Result BinaryReaderInterp::OnRefIsNullExpr() {
return Result::Ok;
}

Result BinaryReaderInterp::OnRefTestExpr(Type type) {
int type_index = 0;
if (type.IsIndex()) {
type_index = type.GetIndex();
}
CHECK_RESULT(
validator_.OnRefTest(GetLocation(), Var(type_index, GetLocation())));
istream_.Emit(Opcode::RefTest);
return Result::Ok;
}

Result BinaryReaderInterp::OnNopExpr() {
CHECK_RESULT(validator_.OnNop(GetLocation()));
return Result::Ok;
Expand Down
1 change: 1 addition & 0 deletions src/interp/interp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1877,6 +1877,7 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) {
case O::MemoryAtomicNotify:
case O::MemoryAtomicWait32:
case O::MemoryAtomicWait64:
case O::RefTest:
return TRAP("not implemented");

case O::I32AtomicLoad: return DoAtomicLoad<u32>(instr, out_trap);
Expand Down
1 change: 1 addition & 0 deletions src/interp/istream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ Instr Istream::Read(Offset* offset) const {
case Opcode::LocalTee:
case Opcode::MemoryGrow:
case Opcode::TableGet:
case Opcode::RefTest:
// Index immediate, 1 operand.
instr.kind = InstrKind::Imm_Index_Op_1;
instr.imm_u32 = ReadAt<u32>(offset);
Expand Down
1 change: 1 addition & 0 deletions src/ir-util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ ModuleContext::Arities ModuleContext::GetExprArity(const Expr& expr) const {
case ExprType::RefIsNull:
case ExprType::LoadSplat:
case ExprType::LoadZero:
case ExprType::RefTest:
return {1, 1};

case ExprType::Drop:
Expand Down
1 change: 1 addition & 0 deletions src/ir.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const char* ExprTypeName[] = {
"RefIsNull",
"RefFunc",
"RefNull",
"RefTest",
"Rethrow",
"Return",
"ReturnCall",
Expand Down
1 change: 1 addition & 0 deletions src/lexer-keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ ref.extern, TokenType::RefExtern
ref.func, TokenType::RefFunc, Opcode::RefFunc
ref.is_null, TokenType::RefIsNull, Opcode::RefIsNull
ref.null, TokenType::RefNull, Opcode::RefNull
ref.test, TokenType::RefTest, Opcode::RefTest
register, TokenType::Register
result, TokenType::Result
rethrow, TokenType::Rethrow, Opcode::Rethrow
Expand Down
Loading
Loading