summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
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()) {