diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binary-reader-logging.cc | 1 | ||||
-rw-r--r-- | src/binary-reader-logging.h | 1 | ||||
-rw-r--r-- | src/binary-reader-nop.h | 3 | ||||
-rw-r--r-- | src/binary-reader-objdump.cc | 26 | ||||
-rw-r--r-- | src/binary-reader.cc | 7 | ||||
-rw-r--r-- | src/binary-reader.h | 1 | ||||
-rw-r--r-- | src/binary-writer-spec.cc | 22 | ||||
-rw-r--r-- | src/common.h | 10 | ||||
-rw-r--r-- | src/interp/binary-reader-interp.cc | 77 | ||||
-rw-r--r-- | src/interp/interp-disassemble.cc | 20 | ||||
-rw-r--r-- | src/interp/interp-trace.cc | 11 | ||||
-rw-r--r-- | src/interp/interp.cc | 32 | ||||
-rw-r--r-- | src/interp/interp.h | 47 | ||||
-rw-r--r-- | src/type-checker.cc | 54 | ||||
-rw-r--r-- | src/type-checker.h | 4 | ||||
-rw-r--r-- | src/validator.cc | 51 | ||||
-rw-r--r-- | src/wast-parser.cc | 36 |
17 files changed, 287 insertions, 116 deletions
diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc index 9a23337a..59421b75 100644 --- a/src/binary-reader-logging.cc +++ b/src/binary-reader-logging.cc @@ -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) diff --git a/src/binary-reader-logging.h b/src/binary-reader-logging.h index 901ef79a..d8bea6c2 100644 --- a/src/binary-reader-logging.h +++ b/src/binary-reader-logging.h @@ -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(); diff --git a/src/binary-reader-nop.h b/src/binary-reader-nop.h index eae1fc08..845411ac 100644 --- a/src/binary-reader-nop.h +++ b/src/binary-reader-nop.h @@ -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 diff --git a/src/binary-reader-objdump.cc b/src/binary-reader-objdump.cc index 69f3a2c9..25ce8b28 100644 --- a/src/binary-reader-objdump.cc +++ b/src/binary-reader-objdump.cc @@ -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; @@ -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, @@ -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)); } @@ -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; @@ -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; } @@ -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)); diff --git a/src/binary-reader.cc b/src/binary-reader.cc index 511f712c..bd2c039a 100644 --- a/src/binary-reader.cc +++ b/src/binary-reader.cc @@ -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; diff --git a/src/binary-reader.h b/src/binary-reader.h index 59d10655..6ad979e4 100644 --- a/src/binary-reader.h +++ b/src/binary-reader.h @@ -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; }; diff --git a/src/binary-writer-spec.cc b/src/binary-writer-spec.cc index 399d0e78..2c169426 100644 --- a/src/binary-writer-spec.cc +++ b/src/binary-writer-spec.cc @@ -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); @@ -224,7 +238,7 @@ void BinaryWriterSpec::WriteConst(const Const& const_) { } default: - assert(0); + WABT_UNREACHABLE; } json_stream_->Writef("}"); diff --git a/src/common.h b/src/common.h index 14db973f..bcd4c8d2 100644 --- a/src/common.h +++ b/src/common.h @@ -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: diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc index aea60c37..239e8b76 100644 --- a/src/interp/binary-reader-interp.cc +++ b/src/interp/binary-reader-interp.cc @@ -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) {} @@ -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; @@ -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); @@ -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, @@ -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); @@ -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, @@ -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; } @@ -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, @@ -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; } diff --git a/src/interp/interp-disassemble.cc b/src/interp/interp-disassemble.cc index ba232e92..75ef8708 100644 --- a/src/interp/interp-disassemble.cc +++ b/src/interp/interp-disassemble.cc @@ -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: @@ -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; } diff --git a/src/interp/interp-trace.cc b/src/interp/interp-trace.cc index 1d6bbb94..8acf0a1d 100644 --- a/src/interp/interp-trace.cc +++ b/src/interp/interp-trace.cc @@ -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: diff --git a/src/interp/interp.cc b/src/interp/interp.cc index f23f687d..1cfa333f 100644 --- a/src/interp/interp.cc +++ b/src/interp/interp.cc @@ -1126,8 +1126,7 @@ Result Thread::TableGet(const uint8_t** pc) { TRAP_MSG(TableAccessOutOfBounds, "table.get at %u >= max value %" PRIzx, index, table->size()); } - Ref ref = static_cast<Ref>(table->entries[index]); - return Push(ref); + return Push(table->entries[index]); } Result Thread::ElemDrop(const uint8_t** pc) { @@ -1486,7 +1485,7 @@ ValueTypeRep<R> IntEqz(ValueTypeRep<T> v_rep) { } ValueTypeRep<uint32_t> RefIsNull(ValueTypeRep<Ref> v_rep) { - return ToRep(v_rep.index == kInvalidIndex); + return ToRep(v_rep.kind == RefType::Null); } template <typename T> @@ -3596,10 +3595,24 @@ Result Thread::Run(int num_instructions) { CHECK_TRAP(Push(Ref{RefType::Null, kInvalidIndex})); break; - case Opcode::TableGrow: - case Opcode::TableSize: - WABT_UNREACHABLE; + case Opcode::TableGrow: { + Table* table = ReadTable(&pc); + uint32_t increment = Pop<uint32_t>(); + Ref ref = Pop<Ref>(); + uint32_t old_size = table->size(); + uint32_t max = table->limits.has_max ? table->limits.max : UINT32_MAX; + PUSH_NEG_1_AND_BREAK_IF(int64_t(old_size) + increment > max); + uint32_t new_size = old_size + increment; + table->resize(new_size, ref); + CHECK_TRAP(Push<uint32_t>(old_size)); break; + } + + case Opcode::TableSize: { + Table* table = ReadTable(&pc); + CHECK_TRAP(Push<uint32_t>(table->entries.size())); + break; + } case Opcode::MemoryInit: CHECK_TRAP(MemoryInit(&pc)); @@ -3709,6 +3722,10 @@ Result Executor::InitializeSegments(DefinedModule* module) { enum Pass { Check = 0, Init = 1 }; int pass = env_->features_.bulk_memory_enabled() ? Init : Check; + if (trace_stream_) { + trace_stream_->Writef(">>> initializing segments\n"); + } + for (; pass <= Init; ++pass) { for (const ElemSegmentInfo& info : module->active_elem_segments_) { uint32_t table_size = info.table->size(); @@ -3823,8 +3840,9 @@ void Executor::CopyResults(const FuncSignature* sig, TypedValues* out_results) { assert(expected_results == thread_.NumValues()); out_results->clear(); - for (size_t i = 0; i < expected_results; ++i) + for (size_t i = 0; i < expected_results; ++i) { out_results->emplace_back(sig->result_types[i], thread_.ValueAt(i)); + } } } // namespace interp diff --git a/src/interp/interp.h b/src/interp/interp.h index 0fdb812b..70f7b8c1 100644 --- a/src/interp/interp.h +++ b/src/interp/interp.h @@ -122,11 +122,16 @@ struct Ref { struct Table { explicit Table(Type elem_type, const Limits& limits) - : elem_type(elem_type), - limits(limits), - entries(limits.initial, {RefType::Null, kInvalidIndex}) {} + : elem_type(elem_type), limits(limits) { + resize(limits.initial, {RefType::Null, kInvalidIndex}); + } + size_t size() const { return entries.size(); } + void resize(size_t new_size, Ref init_elem) { + entries.resize(new_size, init_elem); + } + Type elem_type; Limits limits; std::vector<Ref> entries; @@ -206,30 +211,34 @@ struct TypedValue { TypedValue() {} explicit TypedValue(Type type) : type(type) {} TypedValue(Type basetype, const Value& value) : type(basetype), value(value) { - SetConcreteType(); + UpdateType(); } - void SetConcreteType() { - // Anyref is an abstract type. The actual type is stored in value. - if (type == Type::Anyref) { - switch (value.ref.kind) { - case RefType::Func: - type = Type::Funcref; - break; - case RefType::Null: - type = Type::Nullref; - break; - case RefType::Host: - type = Type::Hostref; - break; - } + void UpdateType() { + if (!IsRefType(type)) { + return; + } + + // For references types, the concrete type of TypedValue can change as it + // gets its value changed. For example assigning a RefType::Func value to + // an Anyref will cause type of the TypedValue to be changed into a Funcref. + switch (value.ref.kind) { + case RefType::Func: + type = Type::Funcref; + break; + case RefType::Host: + type = Type::Hostref; + break; + case RefType::Null: + type = Type::Nullref; + break; } } void SetZero() { ZeroMemory(value); } void set_ref(Ref x) { value.ref = x; - SetConcreteType(); + UpdateType(); } void set_i32(uint32_t x) { value.i32 = x; } void set_i64(uint64_t x) { value.i64 = x; } diff --git a/src/type-checker.cc b/src/type-checker.cc index cc7618d5..1fcd7f12 100644 --- a/src/type-checker.cc +++ b/src/type-checker.cc @@ -168,26 +168,32 @@ Result TypeChecker::CheckTypeStackEnd(const char* desc) { return result; } -static bool IsRefType(Type t) { - return t == Type::Anyref || t == Type::Funcref || t == Type::Nullref || - t == Type::Hostref; -} - -static bool IsNullableRefType(Type t) { - return t == Type::Anyref || t == Type::Funcref || t == Type::Hostref; +static bool IsSubtype(Type sub, Type super) { + if (super == sub) { + return true; + } + if (IsRefType(super) != IsRefType(sub)) { + return false; + } + if (super == Type::Anyref) { + return IsRefType(sub); + } + if (IsNullableRefType(super)) { + return sub == Type::Nullref; + } + return false; } Result TypeChecker::CheckType(Type actual, Type expected) { - if (expected == actual || expected == Type::Any || actual == Type::Any) { + if (expected == Type::Any || actual == Type::Any) { return Result::Ok; } - if (expected == Type::Anyref && IsRefType(actual)) { - return Result::Ok; - } - if (IsNullableRefType(expected) && actual == Type::Nullref) { - return Result::Ok; + + if (!IsSubtype(actual, expected)) { + return Result::Error; } - return Result::Error; + + return Result::Ok; } Result TypeChecker::CheckTypes(const TypeVector& actual, @@ -655,13 +661,13 @@ Result TypeChecker::OnTableSet(Type elem_type) { return PopAndCheck2Types(Type::I32, elem_type, "table.set"); } -Result TypeChecker::OnTableGrow(Index segment) { - Result result = PopAndCheck2Types(Type::Anyref, Type::I32, "table.grow"); +Result TypeChecker::OnTableGrow(Type elem_type) { + Result result = PopAndCheck2Types(elem_type, Type::I32, "table.grow"); PushType(Type::I32); return result; } -Result TypeChecker::OnTableSize(Index segment) { +Result TypeChecker::OnTableSize() { PushType(Type::I32); return Result::Ok; } @@ -706,13 +712,17 @@ Result TypeChecker::OnReturn() { Result TypeChecker::OnSelect() { Result result = Result::Ok; - Type type = Type::Any; + Type type1 = Type::Any; + Type type2 = Type::Any; + Type result_type = Type::Any; result |= PeekAndCheckType(0, Type::I32); - result |= PeekType(1, &type); - result |= PeekAndCheckType(2, type); - PrintStackIfFailed(result, "select", type, type, Type::I32); + result |= PeekType(1, &type1); + result |= PeekType(2, &type2); + result |= CheckType(type1, type2); + result_type = type1; + PrintStackIfFailed(result, "select", type1, type1, Type::I32); result |= DropTypes(3); - PushType(type); + PushType(result_type); return result; } diff --git a/src/type-checker.h b/src/type-checker.h index b345a2df..ae05b034 100644 --- a/src/type-checker.h +++ b/src/type-checker.h @@ -104,8 +104,8 @@ class TypeChecker { Result OnTableInit(Index, Index); Result OnTableGet(Type elem_type); Result OnTableSet(Type elem_type); - Result OnTableGrow(Index table_index); - Result OnTableSize(Index table_index); + Result OnTableGrow(Type elem_type); + Result OnTableSize(); Result OnRefFuncExpr(Index func_index); Result OnRefNullExpr(); Result OnRefIsNullExpr(); diff --git a/src/validator.cc b/src/validator.cc index 940a811b..78293ded 100644 --- a/src/validator.cc +++ b/src/validator.cc @@ -161,14 +161,10 @@ class Validator : public ExprVisitor::Delegate { const TypeVector& expected, const char* desc, const char* index_kind); - void CheckConstTypes(const Location* loc, - const TypeVector& actual, - const ConstVector& expected, - const char* desc); - void CheckConstType(const Location* loc, - Type actual, - const ConstVector& expected, - const char* desc); + void CheckResultTypes(const Location* loc, + const TypeVector& actual, + const TypeVector& expected, + const char* desc); void CheckAssertReturnNanType(const Location* loc, Type actual, const char* desc); @@ -448,13 +444,13 @@ void Validator::CheckTypes(const Location* loc, } } -void Validator::CheckConstTypes(const Location* loc, - const TypeVector& actual, - const ConstVector& expected, - const char* desc) { +void Validator::CheckResultTypes(const Location* loc, + const TypeVector& actual, + const TypeVector& expected, + const char* desc) { if (actual.size() == expected.size()) { for (size_t i = 0; i < actual.size(); ++i) { - CheckTypeIndex(loc, actual[i], expected[i].type, desc, i, "result"); + CheckTypeIndex(loc, actual[i], expected[i], desc, i, "result"); } } else { PrintError(loc, "expected %" PRIzd " results, got %" PRIzd, expected.size(), @@ -462,17 +458,6 @@ void Validator::CheckConstTypes(const Location* loc, } } -void Validator::CheckConstType(const Location* loc, - Type actual, - const ConstVector& expected, - const char* desc) { - TypeVector actual_types; - if (actual != Type::Void) { - actual_types.push_back(actual); - } - CheckConstTypes(loc, actual_types, expected, desc); -} - void Validator::CheckAssertReturnNanType(const Location* loc, Type actual, const char* desc) { @@ -822,16 +807,18 @@ Result Validator::OnTableSetExpr(TableSetExpr* expr) { } Result Validator::OnTableGrowExpr(TableGrowExpr* expr) { + const Table* table; + CheckTableVar(&expr->var, &table); expr_loc_ = &expr->loc; CheckHasTable(&expr->loc, Opcode::TableGrow, expr->var.index()); - typechecker_.OnTableGrow(expr->var.index()); + typechecker_.OnTableGrow(table->elem_type); return Result::Ok; } Result Validator::OnTableSizeExpr(TableSizeExpr* expr) { expr_loc_ = &expr->loc; CheckHasTable(&expr->loc, Opcode::TableSize, expr->var.index()); - typechecker_.OnTableSize(expr->var.index()); + typechecker_.OnTableSize(); return Result::Ok; } @@ -1523,15 +1510,19 @@ void Validator::CheckCommand(const Command* command) { auto* assert_return_command = cast<AssertReturnCommand>(command); const Action* action = assert_return_command->action.get(); ActionResult result = CheckAction(action); + // Here we take the concrete expected output types verify those actains + // the types that are the result of the action. + TypeVector actual_types; + for (auto ex : assert_return_command->expected) { + actual_types.push_back(ex.type); + } switch (result.kind) { case ActionResult::Kind::Types: - CheckConstTypes(&action->loc, *result.types, - assert_return_command->expected, "action"); + CheckResultTypes(&action->loc, actual_types, *result.types, "action"); break; case ActionResult::Kind::Type: - CheckConstType(&action->loc, result.type, - assert_return_command->expected, "action"); + CheckResultTypes(&action->loc, actual_types, {result.type}, "action"); break; case ActionResult::Kind::Error: diff --git a/src/wast-parser.cc b/src/wast-parser.cc index 02cc69ac..5d4f555f 100644 --- a/src/wast-parser.cc +++ b/src/wast-parser.cc @@ -672,6 +672,9 @@ Result WastParser::ParseValueType(Type* out_type) { is_enabled = options_->features.simd_enabled(); break; case Type::Anyref: + case Type::Funcref: + case Type::Hostref: + case Type::Exnref: is_enabled = options_->features.reference_types_enabled(); break; default: @@ -949,24 +952,33 @@ Result WastParser::ParseElemModuleField(Module* module) { // since there was only one table anyway. // With bulk-memory enabled this introduces a new name for the particualr // elem segment. - std::string segment_name; - ParseBindVarOpt(&segment_name); + std::string initial_name; + bool has_name = ParseBindVarOpt(&initial_name); + + std::string segment_name = initial_name; if (!options_->features.bulk_memory_enabled()) { segment_name = ""; } - auto field = MakeUnique<ElemSegmentModuleField>(loc, segment_name); // Optional table specifier - if (options_->features.bulk_memory_enabled() && - PeekMatchLpar(TokenType::Table)) { - field->elem_segment.flags |= SegExplicitIndex; - EXPECT(Lpar); - EXPECT(Table); - CHECK_RESULT(ParseVar(&field->elem_segment.table_var)); - EXPECT(Rpar); + if (options_->features.bulk_memory_enabled()) { + if (PeekMatchLpar(TokenType::Table)) { + field->elem_segment.flags |= SegExplicitIndex; + EXPECT(Lpar); + EXPECT(Table); + CHECK_RESULT(ParseVar(&field->elem_segment.table_var)); + EXPECT(Rpar); + } else { + ParseVarOpt(&field->elem_segment.table_var, Var(0, loc)); + } } else { - ParseVarOpt(&field->elem_segment.table_var, Var(0, loc)); + if (has_name) { + field->elem_segment.table_var = Var(initial_name, loc); + field->elem_segment.flags |= SegExplicitIndex; + } else { + ParseVarOpt(&field->elem_segment.table_var, Var(0, loc)); + } } if (ParseRefTypeOpt(&field->elem_segment.elem_type)) { @@ -2081,7 +2093,7 @@ Result WastParser::ParseHostRef(Const* const_) { uint64_t ref_bits; Result result = ParseInt64(s, end, &ref_bits, ParseIntType::UnsignedOnly); - const_->type = ref_bits ? Type::Anyref : Type::Nullref; + const_->type = Type::Hostref; const_->ref_bits = static_cast<uintptr_t>(ref_bits); if (Failed(result)) { |