Skip to content

Commit

Permalink
reference-types: Add reference-types spec tests (WebAssembly#1225)
Browse files Browse the repository at this point in the history
This change adds most of the tests from the reference-types proposal.
There are two tests that require new instructions (`table.fill` and
`select_t`) which will be followup changes.

See: WebAssembly#1223
  • Loading branch information
sbc100 committed Nov 26, 2019
1 parent af2b445 commit 3130ab8
Show file tree
Hide file tree
Showing 33 changed files with 1,167 additions and 158 deletions.
1 change: 1 addition & 0 deletions src/binary-reader-logging.cc
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,7 @@ DEFINE_END(EndRelocSection)

DEFINE_INDEX_INDEX(OnInitExprGlobalGetExpr, "index", "global_index")
DEFINE_INDEX(OnInitExprRefNull)
DEFINE_INDEX_INDEX(OnInitExprRefFunc, "index", "func_index")

DEFINE_BEGIN(BeginDylinkSection)
DEFINE_INDEX(OnDylinkNeededCount)
Expand Down
1 change: 1 addition & 0 deletions src/binary-reader-logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
Result OnInitExprI32ConstExpr(Index index, uint32_t value) override;
Result OnInitExprI64ConstExpr(Index index, uint64_t value) override;
Result OnInitExprRefNull(Index index) override;
Result OnInitExprRefFunc(Index index, Index func_index) override;

private:
void Indent();
Expand Down
3 changes: 3 additions & 0 deletions src/binary-reader-nop.h
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,9 @@ class BinaryReaderNop : public BinaryReaderDelegate {
Result OnInitExprRefNull(Index index) override {
return Result::Ok;
}
Result OnInitExprRefFunc(Index index, Index func_index) override {
return Result::Ok;
}
};

} // namespace wabt
Expand Down
26 changes: 22 additions & 4 deletions src/binary-reader-objdump.cc
Original file line number Diff line number Diff line change
Expand Up @@ -689,13 +689,14 @@ enum class InitExprType {
F64,
V128,
Global,
FuncRef,
NullRef,
};

struct InitExpr {
InitExprType type;
union {
Index global;
Index index;
uint32_t i32;
uint32_t f32;
uint64_t i64;
Expand Down Expand Up @@ -829,6 +830,7 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase {
Result OnInitExprI32ConstExpr(Index index, uint32_t value) override;
Result OnInitExprI64ConstExpr(Index index, uint64_t value) override;
Result OnInitExprRefNull(Index index) override;
Result OnInitExprRefFunc(Index index, Index func_index) override;

Result OnDylinkInfo(uint32_t mem_size,
uint32_t mem_align_log2,
Expand Down Expand Up @@ -1326,8 +1328,17 @@ void BinaryReaderObjdump::PrintInitExpr(const InitExpr& expr) {
break;
}
case InitExprType::Global: {
PrintDetails(" - init global=%" PRIindex, expr.value.global);
string_view name = GetGlobalName(expr.value.global);
PrintDetails(" - init global=%" PRIindex, expr.value.index);
string_view name = GetGlobalName(expr.value.index);
if (!name.empty()) {
PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
}
PrintDetails("\n");
break;
}
case InitExprType::FuncRef: {
PrintDetails(" - init ref.func:%" PRIindex, expr.value.index);
string_view name = GetFunctionName(expr.value.index);
if (!name.empty()) {
PrintDetails(" <" PRIstringview ">", WABT_PRINTF_STRING_VIEW_ARG(name));
}
Expand All @@ -1354,6 +1365,7 @@ static Result InitExprToConstOffset(const InitExpr& expr,
case InitExprType::F32:
case InitExprType::F64:
case InitExprType::V128:
case InitExprType::FuncRef:
case InitExprType::NullRef:
fprintf(stderr, "Segment/Elem offset must be an i32 init expr");
return Result::Error;
Expand Down Expand Up @@ -1405,7 +1417,7 @@ Result BinaryReaderObjdump::OnInitExprGlobalGetExpr(Index index,
Index global_index) {
InitExpr expr;
expr.type = InitExprType::Global;
expr.value.global = global_index;
expr.value.index = global_index;
HandleInitExpr(expr);
return Result::Ok;
}
Expand Down Expand Up @@ -1435,6 +1447,12 @@ Result BinaryReaderObjdump::OnInitExprRefNull(Index index) {
return Result::Ok;
}

Result BinaryReaderObjdump::OnInitExprRefFunc(Index index, Index func_index) {
InitExpr expr{InitExprType::FuncRef, {func_index}};
HandleInitExpr(expr);
return Result::Ok;
}

Result BinaryReaderObjdump::OnModuleName(string_view name) {
PrintDetails(" - module <" PRIstringview ">\n",
WABT_PRINTF_STRING_VIEW_ARG(name));
Expand Down
7 changes: 7 additions & 0 deletions src/binary-reader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,13 @@ Result BinaryReader::ReadInitExpr(Index index, bool require_i32) {
CALLBACK(OnInitExprRefNull, index);
break;

case Opcode::RefFunc: {
Index func_index;
CHECK_RESULT(ReadIndex(&func_index, "init_expr ref.func index"));
CALLBACK(OnInitExprRefFunc, index, func_index);
break;
}

case Opcode::End:
return Result::Ok;

Expand Down
1 change: 1 addition & 0 deletions src/binary-reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ class BinaryReaderDelegate {
virtual Result OnInitExprI32ConstExpr(Index index, uint32_t value) = 0;
virtual Result OnInitExprI64ConstExpr(Index index, uint64_t value) = 0;
virtual Result OnInitExprRefNull(Index index) = 0;
virtual Result OnInitExprRefFunc(Index index, Index func_index) = 0;

const State* state = nullptr;
};
Expand Down
22 changes: 18 additions & 4 deletions src/binary-writer-spec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,23 @@ void BinaryWriterSpec::WriteConst(const Const& const_) {
}

case Type::Nullref:
case Type::Funcref:
case Type::Anyref: {
WriteString("ref");
WriteString("nullref");
WriteSeparator();
WriteKey("value");
json_stream_->Writef("\"0\"");
break;

case Type::Funcref: {
WriteString("funcref");
WriteSeparator();
WriteKey("value");
int64_t ref_bits = static_cast<int64_t>(const_.ref_bits);
json_stream_->Writef("\"%" PRIu64 "\"", ref_bits);
break;
}

case Type::Hostref: {
WriteString("hostref");
WriteSeparator();
WriteKey("value");
int64_t ref_bits = static_cast<int64_t>(const_.ref_bits);
Expand All @@ -224,7 +238,7 @@ void BinaryWriterSpec::WriteConst(const Const& const_) {
}

default:
assert(0);
WABT_UNREACHABLE;
}

json_stream_->Writef("}");
Expand Down
10 changes: 10 additions & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,16 @@ static WABT_INLINE const char* GetSymbolTypeName(SymbolType type) {

/* type */

static WABT_INLINE bool IsRefType(Type t) {
return t == Type::Anyref || t == Type::Funcref || t == Type::Nullref ||
t == Type::Hostref;
}

static WABT_INLINE bool IsNullableRefType(Type t) {
/* Currently all reftypes are nullable */
return IsRefType(t);
}

static WABT_INLINE const char* GetTypeName(Type type) {
switch (type) {
case Type::I32:
Expand Down
77 changes: 64 additions & 13 deletions src/interp/binary-reader-interp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ struct Label {
IstreamOffset fixup_offset;
};

struct GlobalType {
Type type;
bool mutable_;
};

Label::Label(IstreamOffset offset, IstreamOffset fixup_offset)
: offset(offset), fixup_offset(fixup_offset) {}

Expand Down Expand Up @@ -189,6 +194,8 @@ class BinaryReaderInterp : public BinaryReaderNop {
wabt::Result OnTableCopyExpr(Index dst_index, Index src_index) override;
wabt::Result OnTableGetExpr(Index table_index) override;
wabt::Result OnTableSetExpr(Index table_index) override;
wabt::Result OnTableGrowExpr(Index table_index) override;
wabt::Result OnTableSizeExpr(Index table_index) override;
wabt::Result OnElemDropExpr(Index segment_index) override;
wabt::Result OnTableInitExpr(Index segment_index, Index table_index) override;
wabt::Result OnTernaryExpr(wabt::Opcode opcode) override;
Expand Down Expand Up @@ -229,6 +236,7 @@ class BinaryReaderInterp : public BinaryReaderNop {
wabt::Result OnInitExprI32ConstExpr(Index index, uint32_t value) override;
wabt::Result OnInitExprI64ConstExpr(Index index, uint64_t value) override;
wabt::Result OnInitExprRefNull(Index index) override;
wabt::Result OnInitExprRefFunc(Index index, Index func_index) override;

private:
Label* GetLabel(Index depth);
Expand Down Expand Up @@ -291,6 +299,8 @@ class BinaryReaderInterp : public BinaryReaderNop {

wabt::Result CheckLocal(Index local_index);
wabt::Result CheckGlobal(Index global_index);
wabt::Result CheckGlobalType(GlobalType actual,
GlobalType expected);
wabt::Result CheckDataSegment(Index data_segment_index);
wabt::Result CheckElemSegment(Index elem_segment_index);
wabt::Result CheckImportKind(string_view module,
Expand Down Expand Up @@ -815,6 +825,12 @@ wabt::Result BinaryReaderInterp::OnImportTable(Index import_index,
CHECK_RESULT(CheckImportKind(module_name, field_name, ExternalKind::Table, export_->kind));

Table* table = env_->GetTable(export_->index);
if (elem_type != table->elem_type) {
PrintError("type mismatch in imported table, expected %s but got %s.",
GetTypeName(elem_type), GetTypeName(table->elem_type));
return wabt::Result::Error;
}

CHECK_RESULT(CheckImportLimits(elem_limits, &table->limits));

table_index_mapping_.push_back(export_->index);
Expand Down Expand Up @@ -845,6 +861,27 @@ wabt::Result BinaryReaderInterp::OnImportMemory(Index import_index,
return wabt::Result::Ok;
}

wabt::Result BinaryReaderInterp::CheckGlobalType(GlobalType actual,
GlobalType expected) {
if (actual.mutable_ != expected.mutable_) {
const char* kMutableNames[] = {"immutable", "mutable"};
PrintError(
"mutability mismatch in imported global, expected %s but got %s.",
kMutableNames[actual.mutable_], kMutableNames[expected.mutable_]);
return wabt::Result::Error;
}

if (actual.type == expected.type ||
(!expected.mutable_ &&
Succeeded(typechecker_.CheckType(actual.type, expected.type)))) {
return wabt::Result::Ok;
}

PrintError("type mismatch in imported global, expected %s but got %s.",
GetTypeName(expected.type), GetTypeName(actual.type));
return wabt::Result::Error;
}

wabt::Result BinaryReaderInterp::OnImportGlobal(Index import_index,
string_view module_name,
string_view field_name,
Expand All @@ -856,21 +893,14 @@ wabt::Result BinaryReaderInterp::OnImportGlobal(Index import_index,

Export* export_;
CHECK_RESULT(GetModuleExport(import_module, field_name, &export_));
CHECK_RESULT(CheckImportKind(module_name, field_name, ExternalKind::Global, export_->kind));
CHECK_RESULT(CheckImportKind(module_name, field_name, ExternalKind::Global,
export_->kind));

Global* exported_global = env_->GetGlobal(export_->index);
if (Failed(typechecker_.CheckType(type, exported_global->typed_value.type))) {
PrintError("type mismatch in imported global, expected %s but got %s.",
GetTypeName(exported_global->typed_value.type),
GetTypeName(type));
return wabt::Result::Error;
}
GlobalType expected = {type, mutable_};
GlobalType actual = {exported_global->type, exported_global->mutable_};

if (exported_global->mutable_ != mutable_) {
const char* kMutableNames[] = {"immutable", "mutable"};
PrintError(
"mutability mismatch in imported global, expected %s but got %s.",
kMutableNames[exported_global->mutable_], kMutableNames[mutable_]);
if (Failed(CheckGlobalType(actual, expected))) {
return wabt::Result::Error;
}

Expand Down Expand Up @@ -999,6 +1029,12 @@ wabt::Result BinaryReaderInterp::OnInitExprRefNull(Index index) {
return wabt::Result::Ok;
}

wabt::Result BinaryReaderInterp::OnInitExprRefFunc(Index index, Index func_index) {
init_expr_value_.type = Type::Funcref;
init_expr_value_.set_ref({RefType::Func, TranslateFuncIndexToEnv(func_index)});
return wabt::Result::Ok;
}

wabt::Result BinaryReaderInterp::OnExport(Index index,
ExternalKind kind,
Index item_index,
Expand Down Expand Up @@ -1724,10 +1760,25 @@ wabt::Result BinaryReaderInterp::OnMemorySizeExpr() {
return wabt::Result::Ok;
}

wabt::Result BinaryReaderInterp::OnTableGrowExpr(Index table_index) {
Table* table = GetTableByModuleIndex(table_index);
CHECK_RESULT(typechecker_.OnTableGrow(table->elem_type));
CHECK_RESULT(EmitOpcode(Opcode::TableGrow));
CHECK_RESULT(EmitI32(TranslateTableIndexToEnv(table_index)));
return wabt::Result::Ok;
}

wabt::Result BinaryReaderInterp::OnTableSizeExpr(Index table_index) {
CHECK_RESULT(typechecker_.OnTableSize());
CHECK_RESULT(EmitOpcode(Opcode::TableSize));
CHECK_RESULT(EmitI32(TranslateTableIndexToEnv(table_index)));
return wabt::Result::Ok;
}

wabt::Result BinaryReaderInterp::OnRefFuncExpr(Index func_index) {
CHECK_RESULT(typechecker_.OnRefFuncExpr(func_index));
CHECK_RESULT(EmitOpcode(Opcode::RefFunc));
CHECK_RESULT(EmitI32(func_index));
CHECK_RESULT(EmitI32(TranslateFuncIndexToEnv(func_index)));
return wabt::Result::Ok;
}

Expand Down
20 changes: 18 additions & 2 deletions src/interp/interp-disassemble.cc
Original file line number Diff line number Diff line change
Expand Up @@ -586,13 +586,28 @@ void Environment::Disassemble(Stream* stream,
}

case Opcode::TableGet:
stream->Writef("%s %u %%[-1]\n", opcode.GetName(), ReadU32(&pc));
break;

case Opcode::TableSet:
stream->Writef("%s $%u %%[-1] %%[-2]\n", opcode.GetName(), ReadU32(&pc));
break;

case Opcode::TableGrow:
case Opcode::TableSize:
stream->Writef("%s %u\n", opcode.GetName(), ReadU32(&pc));
break;

case Opcode::RefNull:
case Opcode::RefIsNull:
stream->Writef("%s\n", opcode.GetName());
break;

case Opcode::RefFunc:
WABT_UNREACHABLE;
stream->Writef("%s $%u\n", opcode.GetName(), ReadU32(&pc));
break;

case Opcode::RefIsNull:
stream->Writef("%s %%[-1]\n", opcode.GetName());
break;

case Opcode::MemoryInit:
Expand Down Expand Up @@ -634,6 +649,7 @@ void Environment::Disassemble(Stream* stream,
case Opcode::Rethrow:
case Opcode::Throw:
case Opcode::Try:
fprintf(stderr, "unknown opcode: %#x\n", static_cast<uint32_t>(opcode));
WABT_UNREACHABLE;
break;
}
Expand Down
11 changes: 10 additions & 1 deletion src/interp/interp-trace.cc
Original file line number Diff line number Diff line change
Expand Up @@ -699,10 +699,19 @@ void Thread::Trace(Stream* stream) {
case Opcode::TableSet:
case Opcode::TableGrow:
case Opcode::TableSize:

case Opcode::RefNull:
stream->Writef("%s\n", opcode.GetName());
break;

case Opcode::RefIsNull:
stream->Writef("%s %s:%08x\n", opcode.GetName(),
RefTypeToString(Pick(1).ref.kind).c_str(),
Pick(1).ref.index);
break;

case Opcode::RefFunc:
WABT_UNREACHABLE;
stream->Writef("%s $%u\n", opcode.GetName(), ReadU32At(pc));
break;

case Opcode::MemoryInit:
Expand Down
Loading

0 comments on commit 3130ab8

Please sign in to comment.