summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2022-11-13 10:14:36 -0800
committerGitHub <noreply@github.com>2022-11-13 18:14:36 +0000
commit0ec54cbdd782b894d9872058dad60f1ee6bd6e44 (patch)
tree28f5d781841995da833cf736a6e685fb1dd7c1f2 /src
parenta3c6ec4364f87f72c58bce85ab0d3bd0289505f0 (diff)
downloadwabt-0ec54cbdd782b894d9872058dad60f1ee6bd6e44.tar.gz
wabt-0ec54cbdd782b894d9872058dad60f1ee6bd6e44.tar.bz2
wabt-0ec54cbdd782b894d9872058dad60f1ee6bd6e44.zip
Update testsuite (#2054)
As well as the testsuite update there are two notable changes that come with it here. These can both be split out an landed first if it makes sense. 1. wasm2c now supports element sections containing externref. Currently only the null reference is supported. 2. element segments no longer use funcref as the default element type but instead, unless explicitly included in the binary, the element type defaults to the type of the table in which the segment is active. Fixes: #1612 #2022
Diffstat (limited to 'src')
-rw-r--r--src/c-writer.cc48
-rw-r--r--src/interp/binary-reader-interp.cc3
-rw-r--r--src/ir.cc9
-rw-r--r--src/shared-validator.cc22
-rw-r--r--src/template/wasm2c.declarations.c17
-rw-r--r--src/tools/spectest-interp.cc1
-rw-r--r--src/validator.cc3
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,
diff --git a/src/ir.cc b/src/ir.cc
index 12263ce7..88db7d5f 100644
--- a/src/ir.cc
+++ b/src/ir.cc
@@ -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()) {