diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/c-writer.cc | 48 | ||||
-rw-r--r-- | src/interp/binary-reader-interp.cc | 3 | ||||
-rw-r--r-- | src/ir.cc | 9 | ||||
-rw-r--r-- | src/shared-validator.cc | 22 | ||||
-rw-r--r-- | src/template/wasm2c.declarations.c | 17 | ||||
-rw-r--r-- | src/tools/spectest-interp.cc | 1 | ||||
-rw-r--r-- | src/validator.cc | 3 |
7 files changed, 76 insertions, 27 deletions
diff --git a/src/c-writer.cc b/src/c-writer.cc index 517cc80e..ed255d00 100644 --- a/src/c-writer.cc +++ b/src/c-writer.cc @@ -1510,8 +1510,18 @@ void CWriter::WriteElemInitializers() { continue; } - Write("static const wasm_elem_segment_expr_t elem_segment_exprs_", - GlobalName(elem_segment->name), "[] = ", OpenBrace()); + switch (elem_segment->elem_type) { + case Type::FuncRef: + Write("static const wasm_elem_segment_expr_t elem_segment_exprs_", + GlobalName(elem_segment->name), "[] = ", OpenBrace()); + break; + case Type::ExternRef: + Write("static const wasm_rt_externref_t elem_segment_exprs_", + GlobalName(elem_segment->name), "[] = ", OpenBrace()); + break; + default: + WABT_UNREACHABLE; + } for (const ExprList& elem_expr : elem_segment->elem_exprs) { assert(elem_expr.size() == 1); @@ -1531,10 +1541,14 @@ void CWriter::WriteElemInitializers() { } else { Write("0"); } - Write("}, ", Newline()); + Write("},", Newline()); } break; case ExprType::RefNull: - Write("{0, NULL, 0},", Newline()); + if (elem_segment->elem_type == Type::FuncRef) { + Write("{0, NULL, 0},", Newline()); + } else { + Write("NULL,", Newline()); + } break; default: WABT_UNREACHABLE; @@ -1565,13 +1579,13 @@ void CWriter::WriteElemInitializers() { const Table* table = module_->GetTable(elem_segment->table_var); - // TODO: Resolve whether nonempty externref-type element segments - // are permitted (WebAssembly/spec#1543) - if (table->elem_type != Type::FuncRef) { + if (table->elem_type != Type::FuncRef && + table->elem_type != Type::ExternRef) { WABT_UNREACHABLE; } - Write("funcref_table_init(", ExternalInstancePtr(table->name), ", "); + Write(GetReferenceTypeName(table->elem_type), "_table_init(", + ExternalInstancePtr(table->name), ", "); if (elem_segment->elem_exprs.empty()) { Write("NULL, 0, "); } else { @@ -1579,14 +1593,18 @@ void CWriter::WriteElemInitializers() { elem_segment->elem_exprs.size(), ", "); } WriteInitExpr(elem_segment->offset); - if (elem_segment->elem_exprs.empty()) { - // It's mandatory to handle the case of a zero-length elem segment - // (even in a module with no types). This must trap if the offset - // is out of bounds. - Write(", 0, 0, instance, NULL);", Newline()); + if (table->elem_type == Type::ExternRef) { + Write(", 0, ", elem_segment->elem_exprs.size(), ");", Newline()); } else { - Write(", 0, ", elem_segment->elem_exprs.size(), - ", instance, func_types);", Newline()); + if (elem_segment->elem_exprs.empty()) { + // It's mandatory to handle the case of a zero-length elem segment + // (even in a module with no types). This must trap if the offset + // is out of bounds. + Write(", 0, 0, instance, NULL);", Newline()); + } else { + Write(", 0, ", elem_segment->elem_exprs.size(), + ", instance, func_types);", Newline()); + } } } diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc index def91b64..42f4c013 100644 --- a/src/interp/binary-reader-interp.cc +++ b/src/interp/binary-reader-interp.cc @@ -727,10 +727,9 @@ Result BinaryReaderInterp::EndElemSegmentInitExpr(Index index) { } Result BinaryReaderInterp::OnElemSegmentElemType(Index index, Type elem_type) { - validator_.OnElemSegmentElemType(elem_type); ElemDesc& elem = module_.elems.back(); elem.type = elem_type; - return Result::Ok; + return validator_.OnElemSegmentElemType(GetLocation(), elem_type); } Result BinaryReaderInterp::OnElemSegmentElemExprCount(Index index, @@ -651,12 +651,10 @@ void Var::Destroy() { uint8_t ElemSegment::GetFlags(const Module* module) const { uint8_t flags = 0; - bool all_ref_func = elem_type == Type::FuncRef; - switch (kind) { case SegmentKind::Active: { Index table_index = module->GetTableIndex(table_var); - if (table_index != 0) { + if (elem_type != Type::FuncRef || table_index != 0) { flags |= SegExplicitIndex; } break; @@ -671,12 +669,13 @@ uint8_t ElemSegment::GetFlags(const Module* module) const { break; } - all_ref_func = - all_ref_func && + bool all_ref_func = + elem_type == Type::FuncRef && std::all_of(elem_exprs.begin(), elem_exprs.end(), [](const ExprList& elem_expr) { return elem_expr.front().type() == ExprType::RefFunc; }); + if (!all_ref_func) { flags |= SegUseElemExprs; } diff --git a/src/shared-validator.cc b/src/shared-validator.cc index efbd02f8..ec596cad 100644 --- a/src/shared-validator.cc +++ b/src/shared-validator.cc @@ -253,15 +253,27 @@ Result SharedValidator::OnElemSegment(const Location& loc, Var table_var, SegmentKind kind) { Result result = Result::Ok; + TableType table_type; if (kind == SegmentKind::Active) { - result |= CheckTableIndex(table_var); + result |= CheckTableIndex(table_var, &table_type); } - elems_.push_back(ElemType{Type::Void}); // Updated in OnElemSegmentElemType. + // Type gets set later in OnElemSegmentElemType. + elems_.push_back( + ElemType{Type::Void, kind == SegmentKind::Active, table_type.element}); return result; } -void SharedValidator::OnElemSegmentElemType(Type elem_type) { - elems_.back().element = elem_type; +Result SharedValidator::OnElemSegmentElemType(const Location& loc, + Type elem_type) { + Result result = Result::Ok; + auto& elem = elems_.back(); + if (elem.is_active) { + // Check that the type of the elem segment matches the table in which + // it is active. + result |= CheckType(loc, elem.table_type, elem_type, "elem segment"); + } + elem.element = elem_type; + return result; } Result SharedValidator::OnElemSegmentElemExpr_RefNull(const Location& loc, @@ -272,6 +284,8 @@ Result SharedValidator::OnElemSegmentElemExpr_RefNull(const Location& loc, Result SharedValidator::OnElemSegmentElemExpr_RefFunc(const Location& loc, Var func_var) { Result result = Result::Ok; + result |= + CheckType(loc, Type::FuncRef, elems_.back().element, "elem expression"); result |= CheckFuncIndex(func_var); declared_funcs_.insert(func_var.index()); return result; diff --git a/src/template/wasm2c.declarations.c b/src/template/wasm2c.declarations.c index 7d9d64ad..c262b277 100644 --- a/src/template/wasm2c.declarations.c +++ b/src/template/wasm2c.declarations.c @@ -494,6 +494,23 @@ static inline void funcref_table_init(wasm_rt_funcref_table_t* dest, } } +// Currently we only support initializing externref tables with ref.null. +static inline void externref_table_init(wasm_rt_externref_table_t* dest, + const wasm_rt_externref_t* src, + u32 src_size, + u32 dest_addr, + u32 src_addr, + u32 n) { + if (UNLIKELY(src_addr + (uint64_t)n > src_size)) + TRAP(OOB); + if (UNLIKELY(dest_addr + (uint64_t)n > dest->size)) + TRAP(OOB); + for (u32 i = 0; i < n; i++) { + const wasm_rt_externref_t* src_expr = &src[src_addr + i]; + dest->data[dest_addr + i] = *src_expr; + } +} + #define DEFINE_TABLE_COPY(type) \ static inline void type##_table_copy(wasm_rt_##type##_table_t* dest, \ const wasm_rt_##type##_table_t* src, \ diff --git a/src/tools/spectest-interp.cc b/src/tools/spectest-interp.cc index aae11347..5df00894 100644 --- a/src/tools/spectest-interp.cc +++ b/src/tools/spectest-interp.cc @@ -1226,6 +1226,7 @@ CommandRunner::CommandRunner() : store_(s_features) { } const print_funcs[] = { {"print", interp::FuncType{{}, {}}}, {"print_i32", interp::FuncType{{ValueType::I32}, {}}}, + {"print_i64", interp::FuncType{{ValueType::I64}, {}}}, {"print_f32", interp::FuncType{{ValueType::F32}, {}}}, {"print_f64", interp::FuncType{{ValueType::F64}, {}}}, {"print_i32_f32", interp::FuncType{{ValueType::I32, ValueType::F32}, {}}}, diff --git a/src/validator.cc b/src/validator.cc index f05018ab..c1ef6422 100644 --- a/src/validator.cc +++ b/src/validator.cc @@ -775,7 +775,8 @@ Result Validator::CheckModule() { result_ |= validator_.OnElemSegment(field.loc, f->elem_segment.table_var, f->elem_segment.kind); - validator_.OnElemSegmentElemType(f->elem_segment.elem_type); + result_ |= validator_.OnElemSegmentElemType(field.loc, + f->elem_segment.elem_type); // Init expr. if (f->elem_segment.offset.size()) { |