Skip to content

Commit

Permalink
Add support for ref.test instruction
Browse files Browse the repository at this point in the history
Work in progress
  • Loading branch information
hoodmane committed Jan 13, 2025
1 parent ea193b4 commit dedde1b
Show file tree
Hide file tree
Showing 29 changed files with 1,295 additions and 1,165 deletions.
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

0 comments on commit dedde1b

Please sign in to comment.