summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rw-r--r--src/feature.def1
-rw-r--r--src/interp/binary-reader-interp.cc109
-rw-r--r--src/interp/interp.cc59
-rw-r--r--src/interp/interp.h38
-rw-r--r--src/shared-validator.cc20
-rw-r--r--src/shared-validator.h1
-rw-r--r--src/test-interp.cc8
-rw-r--r--test/help/spectest-interp.txt1
-rw-r--r--test/help/wasm-interp.txt1
-rw-r--r--test/help/wasm-opcodecnt.txt1
-rw-r--r--test/help/wasm-validate.txt1
-rw-r--r--test/help/wasm2wat.txt1
-rw-r--r--test/help/wast2json.txt1
-rw-r--r--test/help/wat-desugar.txt1
-rw-r--r--test/help/wat2wasm.txt1
-rw-r--r--test/spec/extended-const/data.txt63
-rw-r--r--test/spec/extended-const/elem.txt68
-rw-r--r--test/spec/extended-const/global.txt141
-rwxr-xr-xtest/update-spec-tests.py4
20 files changed, 373 insertions, 148 deletions
diff --git a/README.md b/README.md
index 154d0b81..f41bd5bd 100644
--- a/README.md
+++ b/README.md
@@ -59,6 +59,7 @@ Wabt has been compiled to JavaScript via emscripten. Some of the functionality i
| [annotations][] | `--enable-annotations` | | | ✓ | | |
| [memory64][] | `--enable-memory64` | | | | | |
| [multi-memory][] | `--enable-multi-memory` | | ✓ | ✓ | ✓ | ✓ |
+| [extended-const][] | `--enable-extended-const` | | | | | |
[exception handling]: https://github.com/WebAssembly/exception-handling
[mutable globals]: https://github.com/WebAssembly/mutable-global
diff --git a/src/feature.def b/src/feature.def
index cecab3e6..63f920df 100644
--- a/src/feature.def
+++ b/src/feature.def
@@ -37,3 +37,4 @@ WABT_FEATURE(annotations, "annotations", false, "Custom an
WABT_FEATURE(gc, "gc", false, "Garbage collection")
WABT_FEATURE(memory64, "memory64", false, "64-bit memory")
WABT_FEATURE(multi_memory, "multi-memory", false, "Multi-memory")
+WABT_FEATURE(extended_const, "extended-const", false, "Extended constant expressions")
diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc
index 62803fc7..47a2d256 100644
--- a/src/interp/binary-reader-interp.cc
+++ b/src/interp/binary-reader-interp.cc
@@ -78,8 +78,6 @@ class BinaryReaderInterp : public BinaryReaderNop {
Errors* errors,
const Features& features);
- ValueType GetType(InitExpr);
-
// Implement BinaryReader.
bool OnError(const Error&) override;
@@ -301,7 +299,7 @@ class BinaryReaderInterp : public BinaryReaderNop {
Index keep_extra,
Index* out_drop_count,
Index* out_keep_count);
- Result BeginInitExpr(Type type);
+ Result BeginInitExpr(Type type, FuncDesc* init_func);
Result EndInitExpr();
void EmitBr(Index depth,
@@ -326,8 +324,6 @@ class BinaryReaderInterp : public BinaryReaderNop {
FixupMap depth_fixups_;
FixupMap func_fixups_;
- bool reading_init_expr_ = false;
- InitExpr init_expr_;
u32 local_decl_count_;
u32 local_count_;
@@ -619,37 +615,37 @@ Result BinaryReaderInterp::OnGlobalCount(Index count) {
Result BinaryReaderInterp::BeginGlobal(Index index, Type type, bool mutable_) {
CHECK_RESULT(validator_.OnGlobal(GetLocation(), type, mutable_));
GlobalType global_type{type, ToMutability(mutable_)};
- module_.globals.push_back(GlobalDesc{global_type, InitExpr{}});
+ FuncDesc init_func{FuncType{{}, {type}}, {}, Istream::kInvalidOffset, {}};
+ module_.globals.push_back(GlobalDesc{global_type, init_func});
global_types_.push_back(global_type);
- init_expr_.kind = InitExprKind::None;
return Result::Ok;
}
Result BinaryReaderInterp::BeginGlobalInitExpr(Index index) {
- GlobalType type = global_types_[index];
- return BeginInitExpr(type.type);
+ GlobalDesc& global = module_.globals.back();
+ return BeginInitExpr(global.type.type, &global.init_func);
}
Result BinaryReaderInterp::EndInitExpr() {
- assert(reading_init_expr_);
- reading_init_expr_ = false;
+ FixupTopLabel();
CHECK_RESULT(validator_.EndInitExpr());
+ istream_.Emit(Opcode::Return);
+ PopLabel();
return Result::Ok;
}
-Result BinaryReaderInterp::BeginInitExpr(Type type) {
- assert(!reading_init_expr_);
- reading_init_expr_ = true;
- init_expr_.kind = InitExprKind::None;
+Result BinaryReaderInterp::BeginInitExpr(Type type, FuncDesc* func) {
+ label_stack_.clear();
+ func_ = func;
+ func_->code_offset = istream_.end();
CHECK_RESULT(validator_.BeginInitExpr(GetLocation(), type));
+ // Push implicit init func label (equivalent to return).
+ PushLabel(LabelKind::Try, Istream::kInvalidOffset, Istream::kInvalidOffset);
return Result::Ok;
}
Result BinaryReaderInterp::EndGlobalInitExpr(Index index) {
- CHECK_RESULT(EndInitExpr());
- GlobalDesc& global = module_.globals.back();
- global.init = init_expr_;
- return Result::Ok;
+ return EndInitExpr();
}
Result BinaryReaderInterp::OnTagCount(Index count) {
@@ -702,24 +698,20 @@ Result BinaryReaderInterp::BeginElemSegment(Index index,
auto mode = ToSegmentMode(flags);
CHECK_RESULT(validator_.OnElemSegment(GetLocation(), Var(table_index), mode));
- ElemDesc desc;
- desc.type = ValueType::Void; // Initialized later in OnElemSegmentElemType.
- desc.mode = mode;
- desc.table_index = table_index;
+ FuncDesc init_func{
+ FuncType{{}, {ValueType::I32}}, {}, Istream::kInvalidOffset, {}};
+ ElemDesc desc{{}, ValueType::Void, mode, table_index, init_func};
module_.elems.push_back(desc);
- init_expr_.kind = InitExprKind::None;
return Result::Ok;
}
Result BinaryReaderInterp::BeginElemSegmentInitExpr(Index index) {
- return BeginInitExpr(Type::I32);
+ ElemDesc& elem = module_.elems.back();
+ return BeginInitExpr(Type::I32, &elem.init_func);
}
Result BinaryReaderInterp::EndElemSegmentInitExpr(Index index) {
- CHECK_RESULT(EndInitExpr());
- ElemDesc& elem = module_.elems.back();
- elem.offset = init_expr_;
- return Result::Ok;
+ return EndInitExpr();
}
Result BinaryReaderInterp::OnElemSegmentElemType(Index index, Type elem_type) {
@@ -761,14 +753,12 @@ Result BinaryReaderInterp::OnDataCount(Index count) {
Result BinaryReaderInterp::BeginDataSegmentInitExpr(Index index) {
MemoryType t = memory_types_[0];
- return BeginInitExpr(t.limits.is_64 ? Type::I64 : Type::I32);
+ DataDesc& data = module_.datas.back();
+ return BeginInitExpr(t.limits.is_64 ? Type::I64 : Type::I32, &data.init_func);
}
Result BinaryReaderInterp::EndDataSegmentInitExpr(Index index) {
- CHECK_RESULT(EndInitExpr());
- DataDesc& data = module_.datas.back();
- data.offset = init_expr_;
- return Result::Ok;
+ return EndInitExpr();
}
Result BinaryReaderInterp::BeginDataSegment(Index index,
@@ -778,11 +768,10 @@ Result BinaryReaderInterp::BeginDataSegment(Index index,
CHECK_RESULT(
validator_.OnDataSegment(GetLocation(), Var(memory_index), mode));
- DataDesc desc;
- desc.mode = mode;
- desc.memory_index = memory_index;
+ FuncDesc init_func{
+ FuncType{{}, {ValueType::I32}}, {}, Istream::kInvalidOffset, {}};
+ DataDesc desc{{}, mode, memory_index, init_func};
module_.datas.push_back(desc);
- init_expr_.kind = InitExprKind::None;
return Result::Ok;
}
@@ -873,7 +862,7 @@ Index BinaryReaderInterp::num_func_imports() const {
}
Result BinaryReaderInterp::OnOpcode(Opcode opcode) {
- if ((func_ == nullptr || label_stack_.empty()) && !reading_init_expr_) {
+ if (func_ == nullptr || label_stack_.empty()) {
PrintError("Unexpected instruction after end of function");
return Result::Error;
}
@@ -1021,7 +1010,7 @@ Result BinaryReaderInterp::OnElseExpr() {
}
Result BinaryReaderInterp::OnEndExpr() {
- if (reading_init_expr_ || label_stack_.size() == 1) {
+ if (label_stack_.size() == 1) {
return Result::Ok;
}
SharedValidator::Label* label;
@@ -1188,66 +1177,36 @@ Result BinaryReaderInterp::OnDropExpr() {
Result BinaryReaderInterp::OnI32ConstExpr(uint32_t value) {
CHECK_RESULT(validator_.OnConst(GetLocation(), Type::I32));
- if (reading_init_expr_) {
- init_expr_.kind = InitExprKind::I32;
- init_expr_.i32_ = value;
- return Result::Ok;
- }
istream_.Emit(Opcode::I32Const, value);
return Result::Ok;
}
Result BinaryReaderInterp::OnI64ConstExpr(uint64_t value) {
CHECK_RESULT(validator_.OnConst(GetLocation(), Type::I64));
- if (reading_init_expr_) {
- init_expr_.kind = InitExprKind::I64;
- init_expr_.i64_ = value;
- return Result::Ok;
- }
istream_.Emit(Opcode::I64Const, value);
return Result::Ok;
}
Result BinaryReaderInterp::OnF32ConstExpr(uint32_t value_bits) {
CHECK_RESULT(validator_.OnConst(GetLocation(), Type::F32));
- if (reading_init_expr_) {
- init_expr_.kind = InitExprKind::F32;
- init_expr_.f32_ = Bitcast<f32>(value_bits);
- return Result::Ok;
- }
istream_.Emit(Opcode::F32Const, value_bits);
return Result::Ok;
}
Result BinaryReaderInterp::OnF64ConstExpr(uint64_t value_bits) {
CHECK_RESULT(validator_.OnConst(GetLocation(), Type::F64));
- if (reading_init_expr_) {
- init_expr_.kind = InitExprKind::F64;
- init_expr_.f64_ = Bitcast<f64>(value_bits);
- return Result::Ok;
- }
istream_.Emit(Opcode::F64Const, value_bits);
return Result::Ok;
}
Result BinaryReaderInterp::OnV128ConstExpr(v128 value_bits) {
CHECK_RESULT(validator_.OnConst(GetLocation(), Type::V128));
- if (reading_init_expr_) {
- init_expr_.kind = InitExprKind::V128;
- init_expr_.v128_ = Bitcast<v128>(value_bits);
- return Result::Ok;
- }
istream_.Emit(Opcode::V128Const, value_bits);
return Result::Ok;
}
Result BinaryReaderInterp::OnGlobalGetExpr(Index global_index) {
CHECK_RESULT(validator_.OnGlobalGet(GetLocation(), Var(global_index)));
- if (reading_init_expr_) {
- init_expr_.kind = InitExprKind::GlobalGet;
- init_expr_.index_ = global_index;
- return Result::Ok;
- }
istream_.Emit(Opcode::GlobalGet, global_index);
return Result::Ok;
}
@@ -1339,22 +1298,12 @@ Result BinaryReaderInterp::OnTableFillExpr(Index table_index) {
Result BinaryReaderInterp::OnRefFuncExpr(Index func_index) {
CHECK_RESULT(validator_.OnRefFunc(GetLocation(), Var(func_index)));
- if (reading_init_expr_) {
- init_expr_.kind = InitExprKind::RefFunc;
- init_expr_.index_ = func_index;
- return Result::Ok;
- }
istream_.Emit(Opcode::RefFunc, func_index);
return Result::Ok;
}
Result BinaryReaderInterp::OnRefNullExpr(Type type) {
CHECK_RESULT(validator_.OnRefNull(GetLocation(), type));
- if (reading_init_expr_) {
- init_expr_.kind = InitExprKind::RefNull;
- init_expr_.type_ = type;
- return Result::Ok;
- }
istream_.Emit(Opcode::RefNull);
return Result::Ok;
}
diff --git a/src/interp/interp.cc b/src/interp/interp.cc
index 4c38b2e1..b4f8403e 100644
--- a/src/interp/interp.cc
+++ b/src/interp/interp.cc
@@ -632,31 +632,18 @@ Result Memory::Copy(Memory& dst,
return Result::Error;
}
-Value Instance::ResolveInitExpr(Store& store, InitExpr init) {
- Value result;
- switch (init.kind) {
- case InitExprKind::I32: result.Set(init.i32_); break;
- case InitExprKind::I64: result.Set(init.i64_); break;
- case InitExprKind::F32: result.Set(init.f32_); break;
- case InitExprKind::F64: result.Set(init.f64_); break;
- case InitExprKind::V128: result.Set(init.v128_); break;
- case InitExprKind::GlobalGet: {
- Global::Ptr global{store, globals_[init.index_]};
- result = global->Get();
- break;
- }
- case InitExprKind::RefFunc: {
- result.Set(funcs_[init.index_]);
- break;
- }
- case InitExprKind::RefNull:
- result.Set(Ref::Null);
- break;
-
- case InitExprKind::None:
- WABT_UNREACHABLE;
+Result Instance::CallInitFunc(Store& store,
+ const Ref func_ref,
+ Value* result,
+ Trap::Ptr* out_trap) {
+ Values results;
+ Func::Ptr func{store, func_ref};
+ if (Failed(func->Call(store, {}, results, out_trap))) {
+ return Result::Error;
}
- return result;
+ assert(results.size() == 1);
+ *result = results[0];
+ return Result::Ok;
}
//// Global ////
@@ -811,9 +798,12 @@ Instance::Ptr Instance::Instantiate(Store& store,
// Globals.
for (auto&& desc : mod->desc().globals) {
- inst->globals_.push_back(
- Global::New(store, desc.type, inst->ResolveInitExpr(store, desc.init))
- .ref());
+ Value value;
+ Ref func_ref = DefinedFunc::New(store, inst.ref(), desc.init_func).ref();
+ if (Failed(inst->CallInitFunc(store, func_ref, &value, out_trap))) {
+ return {};
+ }
+ inst->globals_.push_back(Global::New(store, desc.type, value).ref());
}
// Tags.
@@ -858,7 +848,13 @@ Instance::Ptr Instance::Instantiate(Store& store,
if (desc.mode == SegmentMode::Active) {
Result result;
Table::Ptr table{store, inst->tables_[desc.table_index]};
- u32 offset = inst->ResolveInitExpr(store, desc.offset).Get<u32>();
+ Value value;
+ Ref func_ref =
+ DefinedFunc::New(store, inst.ref(), desc.init_func).ref();
+ if (Failed(inst->CallInitFunc(store, func_ref, &value, out_trap))) {
+ return {};
+ }
+ u32 offset = value.Get<u32>();
if (pass == Check) {
result = table->IsValidRange(offset, segment.size()) ? Result::Ok
: Result::Error;
@@ -888,7 +884,12 @@ Instance::Ptr Instance::Instantiate(Store& store,
if (desc.mode == SegmentMode::Active) {
Result result;
Memory::Ptr memory{store, inst->memories_[desc.memory_index]};
- Value offset_op = inst->ResolveInitExpr(store, desc.offset);
+ Value offset_op;
+ Ref func_ref =
+ DefinedFunc::New(store, inst.ref(), desc.init_func).ref();
+ if (Failed(inst->CallInitFunc(store, func_ref, &offset_op, out_trap))) {
+ return {};
+ }
u64 offset = memory->type().limits.is_64 ? offset_op.Get<u64>()
: offset_op.Get<u32>();
if (pass == Check) {
diff --git a/src/interp/interp.h b/src/interp/interp.h
index aa397f04..a3fee5f4 100644
--- a/src/interp/interp.h
+++ b/src/interp/interp.h
@@ -98,31 +98,6 @@ const std::string GetName(ValueType);
const char* GetName(ExternKind);
const char* GetName(ObjectKind);
-enum class InitExprKind {
- None,
- I32,
- I64,
- F32,
- F64,
- V128,
- GlobalGet,
- RefNull,
- RefFunc
-};
-
-struct InitExpr {
- InitExprKind kind;
- union {
- u32 i32_;
- u64 i64_;
- f32 f32_;
- f64 f64_;
- v128 v128_;
- Index index_;
- Type type_;
- };
-};
-
struct Ref {
static const Ref Null;
@@ -341,7 +316,7 @@ struct FuncDesc {
FuncType type;
std::vector<LocalDesc> locals;
- u32 code_offset;
+ u32 code_offset; // Istream offset.
std::vector<HandlerDesc> handlers;
};
@@ -355,7 +330,7 @@ struct MemoryDesc {
struct GlobalDesc {
GlobalType type;
- InitExpr init;
+ FuncDesc init_func;
};
struct TagDesc {
@@ -375,7 +350,7 @@ struct DataDesc {
Buffer data;
SegmentMode mode;
Index memory_index;
- InitExpr offset;
+ FuncDesc init_func;
};
struct ElemExpr {
@@ -388,7 +363,7 @@ struct ElemDesc {
ValueType type;
SegmentMode mode;
Index table_index;
- InitExpr offset;
+ FuncDesc init_func;
};
struct ModuleDesc {
@@ -1069,7 +1044,10 @@ class Instance : public Object {
explicit Instance(Store&, Ref module);
void Mark(Store&) override;
- Value ResolveInitExpr(Store&, InitExpr);
+ Result CallInitFunc(Store&,
+ const Ref func_ref,
+ Value* result,
+ Trap::Ptr* out_trap);
Ref module_;
RefVec imports_;
diff --git a/src/shared-validator.cc b/src/shared-validator.cc
index 8932012e..68630182 100644
--- a/src/shared-validator.cc
+++ b/src/shared-validator.cc
@@ -519,11 +519,21 @@ Result SharedValidator::CheckAtomicAlign(const Location& loc,
return Result::Ok;
}
-static bool ValidInitOpcode(Opcode opcode) {
- return opcode == Opcode::GlobalGet || opcode == Opcode::I32Const ||
- opcode == Opcode::I64Const || opcode == Opcode::F32Const ||
- opcode == Opcode::F64Const || opcode == Opcode::RefFunc ||
- opcode == Opcode::RefNull;
+bool SharedValidator::ValidInitOpcode(Opcode opcode) const {
+ if (opcode == Opcode::GlobalGet || opcode == Opcode::I32Const ||
+ opcode == Opcode::I64Const || opcode == Opcode::F32Const ||
+ opcode == Opcode::F64Const || opcode == Opcode::RefFunc ||
+ opcode == Opcode::RefNull) {
+ return true;
+ }
+ if (options_.features.extended_const_enabled()) {
+ if (opcode == Opcode::I32Mul || opcode == Opcode::I64Mul ||
+ opcode == Opcode::I32Sub || opcode == Opcode::I64Sub ||
+ opcode == Opcode::I32Add || opcode == Opcode::I64Add) {
+ return true;
+ }
+ }
+ return false;
}
Result SharedValidator::CheckInstr(Opcode opcode, const Location& loc) {
diff --git a/src/shared-validator.h b/src/shared-validator.h
index c84503ec..33fe09ba 100644
--- a/src/shared-validator.h
+++ b/src/shared-validator.h
@@ -244,6 +244,7 @@ class SharedValidator {
Index end;
};
+ bool ValidInitOpcode(Opcode opcode) const;
Result CheckInstr(Opcode opcode, const Location& loc);
Result CheckType(const Location&,
Type actual,
diff --git a/src/test-interp.cc b/src/test-interp.cc
index 1ba6b0b1..93a524c6 100644
--- a/src/test-interp.cc
+++ b/src/test-interp.cc
@@ -680,11 +680,13 @@ TEST_F(InterpGCTest, Collect_InstanceExport) {
});
Instantiate();
auto after_new = store_.object_count();
- EXPECT_EQ(before_new + 6, after_new); // module, instance, f, t, m, g
+ EXPECT_EQ(before_new + 7,
+ after_new); // module, instance, f, t, m, g, g-init-func
- // Instance keeps all exports alive.
+ // Instance keeps all exports alive, except the init func which can be
+ // collected once its has been run
store_.Collect();
- EXPECT_EQ(after_new, store_.object_count());
+ EXPECT_EQ(after_new - 1, store_.object_count());
}
// TODO: Test for Thread keeping references alive as locals/params/stack values.
diff --git a/test/help/spectest-interp.txt b/test/help/spectest-interp.txt
index c9e13728..225a3938 100644
--- a/test/help/spectest-interp.txt
+++ b/test/help/spectest-interp.txt
@@ -28,6 +28,7 @@ options:
--enable-gc Enable Garbage collection
--enable-memory64 Enable 64-bit memory
--enable-multi-memory Enable Multi-memory
+ --enable-extended-const Enable Extended constant expressions
--enable-all Enable all features
-V, --value-stack-size=SIZE Size in elements of the value stack
-C, --call-stack-size=SIZE Size in elements of the call stack
diff --git a/test/help/wasm-interp.txt b/test/help/wasm-interp.txt
index 26c401e9..efbe0409 100644
--- a/test/help/wasm-interp.txt
+++ b/test/help/wasm-interp.txt
@@ -39,6 +39,7 @@ options:
--enable-gc Enable Garbage collection
--enable-memory64 Enable 64-bit memory
--enable-multi-memory Enable Multi-memory
+ --enable-extended-const Enable Extended constant expressions
--enable-all Enable all features
-V, --value-stack-size=SIZE Size in elements of the value stack
-C, --call-stack-size=SIZE Size in elements of the call stack
diff --git a/test/help/wasm-opcodecnt.txt b/test/help/wasm-opcodecnt.txt
index 43096ecb..eff83b99 100644
--- a/test/help/wasm-opcodecnt.txt
+++ b/test/help/wasm-opcodecnt.txt
@@ -29,6 +29,7 @@ options:
--enable-gc Enable Garbage collection
--enable-memory64 Enable 64-bit memory
--enable-multi-memory Enable Multi-memory
+ --enable-extended-const Enable Extended constant expressions
--enable-all Enable all features
-o, --output=FILENAME Output file for the opcode counts, by default use stdout
-c, --cutoff=N Cutoff for reporting counts less than N
diff --git a/test/help/wasm-validate.txt b/test/help/wasm-validate.txt
index bc124d85..3f76d737 100644
--- a/test/help/wasm-validate.txt
+++ b/test/help/wasm-validate.txt
@@ -28,6 +28,7 @@ options:
--enable-gc Enable Garbage collection
--enable-memory64 Enable 64-bit memory
--enable-multi-memory Enable Multi-memory
+ --enable-extended-const Enable Extended constant expressions
--enable-all Enable all features
--no-debug-names Ignore debug names in the binary file
--ignore-custom-section-errors Ignore errors in custom sections
diff --git a/test/help/wasm2wat.txt b/test/help/wasm2wat.txt
index f0788fdf..29155532 100644
--- a/test/help/wasm2wat.txt
+++ b/test/help/wasm2wat.txt
@@ -34,6 +34,7 @@ options:
--enable-gc Enable Garbage collection
--enable-memory64 Enable 64-bit memory
--enable-multi-memory Enable Multi-memory
+ --enable-extended-const Enable Extended constant expressions
--enable-all Enable all features
--inline-exports Write all exports inline
--inline-imports Write all imports inline
diff --git a/test/help/wast2json.txt b/test/help/wast2json.txt
index 2482279f..90278883 100644
--- a/test/help/wast2json.txt
+++ b/test/help/wast2json.txt
@@ -31,6 +31,7 @@ options:
--enable-gc Enable Garbage collection
--enable-memory64 Enable 64-bit memory
--enable-multi-memory Enable Multi-memory
+ --enable-extended-const Enable Extended constant expressions
--enable-all Enable all features
-o, --output=FILE output JSON file
-r, --relocatable Create a relocatable wasm binary (suitable for linking with e.g. lld)
diff --git a/test/help/wat-desugar.txt b/test/help/wat-desugar.txt
index e3ecbd26..38f6356c 100644
--- a/test/help/wat-desugar.txt
+++ b/test/help/wat-desugar.txt
@@ -38,6 +38,7 @@ options:
--enable-gc Enable Garbage collection
--enable-memory64 Enable 64-bit memory
--enable-multi-memory Enable Multi-memory
+ --enable-extended-const Enable Extended constant expressions
--enable-all Enable all features
--generate-names Give auto-generated names to non-named functions, types, etc.
;;; STDOUT ;;)
diff --git a/test/help/wat2wasm.txt b/test/help/wat2wasm.txt
index 0f018a0c..71ff482c 100644
--- a/test/help/wat2wasm.txt
+++ b/test/help/wat2wasm.txt
@@ -38,6 +38,7 @@ options:
--enable-gc Enable Garbage collection
--enable-memory64 Enable 64-bit memory
--enable-multi-memory Enable Multi-memory
+ --enable-extended-const Enable Extended constant expressions
--enable-all Enable all features
-o, --output=FILE output wasm binary file
-r, --relocatable Create a relocatable wasm binary (suitable for linking with e.g. lld)
diff --git a/test/spec/extended-const/data.txt b/test/spec/extended-const/data.txt
new file mode 100644
index 00000000..1479beaa
--- /dev/null
+++ b/test/spec/extended-const/data.txt
@@ -0,0 +1,63 @@
+;;; TOOL: run-interp-spec
+;;; STDIN_FILE: third_party/testsuite/proposals/extended-const/data.wast
+;;; ARGS*: --enable-extended-const
+(;; STDOUT ;;;
+out/test/spec/extended-const/data.wast:325: assert_invalid passed:
+ 0000000: error: memory variable out of range: 0 (max 0)
+ 000000c: error: BeginDataSegment callback failed
+out/test/spec/extended-const/data.wast:333: assert_invalid passed:
+ 0000000: error: memory variable out of range: 1 (max 1)
+ 0000012: error: BeginDataSegment callback failed
+out/test/spec/extended-const/data.wast:346: assert_invalid passed:
+ 0000000: error: memory variable out of range: 0 (max 0)
+ 000000c: error: BeginDataSegment callback failed
+out/test/spec/extended-const/data.wast:357: assert_invalid passed:
+ 0000000: error: memory variable out of range: 1 (max 0)
+ 000000d: error: BeginDataSegment callback failed
+out/test/spec/extended-const/data.wast:369: assert_invalid passed:
+ 0000000: error: memory variable out of range: 1 (max 1)
+ 0000012: error: BeginDataSegment callback failed
+out/test/spec/extended-const/data.wast:391: assert_invalid passed:
+ 0000000: error: memory variable out of range: 1 (max 0)
+ 000000d: error: BeginDataSegment callback failed
+out/test/spec/extended-const/data.wast:410: assert_invalid passed:
+ out/test/spec/extended-const/data/data.49.wasm:0000013: error: type mismatch in initializer expression, expected [i32] but got [i64]
+ 0000014: error: EndDataSegmentInitExpr callback failed
+out/test/spec/extended-const/data.wast:418: assert_invalid passed:
+ out/test/spec/extended-const/data/data.50.wasm:0000013: error: type mismatch in initializer expression, expected [i32] but got [funcref]
+ 0000014: error: EndDataSegmentInitExpr callback failed
+out/test/spec/extended-const/data.wast:426: assert_invalid passed:
+ out/test/spec/extended-const/data/data.51.wasm:0000011: error: type mismatch in initializer expression, expected [i32] but got []
+ 0000012: error: EndDataSegmentInitExpr callback failed
+out/test/spec/extended-const/data.wast:434: assert_invalid passed:
+ out/test/spec/extended-const/data/data.52.wasm:0000015: error: type mismatch at end of initializer expression, expected [] but got [i32]
+ 0000016: error: EndDataSegmentInitExpr callback failed
+out/test/spec/extended-const/data.wast:442: assert_invalid passed:
+ out/test/spec/extended-const/data/data.53.wasm:000002b: error: type mismatch at end of initializer expression, expected [] but got [i32]
+ 000002c: error: EndDataSegmentInitExpr callback failed
+out/test/spec/extended-const/data.wast:451: assert_invalid passed:
+ out/test/spec/extended-const/data/data.54.wasm:000002b: error: type mismatch at end of initializer expression, expected [] but got [i32]
+ 000002c: error: EndDataSegmentInitExpr callback failed
+out/test/spec/extended-const/data.wast:460: assert_invalid passed:
+ out/test/spec/extended-const/data/data.55.wasm:0000014: error: invalid initializer: instruction not valid in initializer expression: i32.ctz
+ 0000014: error: OnUnaryExpr callback failed
+out/test/spec/extended-const/data.wast:468: assert_invalid passed:
+ out/test/spec/extended-const/data/data.56.wasm:0000012: error: invalid initializer: instruction not valid in initializer expression: nop
+ 0000012: error: OnNopExpr callback failed
+out/test/spec/extended-const/data.wast:476: assert_invalid passed:
+ out/test/spec/extended-const/data/data.57.wasm:0000012: error: invalid initializer: instruction not valid in initializer expression: nop
+ 0000012: error: OnNopExpr callback failed
+out/test/spec/extended-const/data.wast:484: assert_invalid passed:
+ out/test/spec/extended-const/data/data.58.wasm:0000014: error: invalid initializer: instruction not valid in initializer expression: nop
+ 0000014: error: OnNopExpr callback failed
+out/test/spec/extended-const/data.wast:498: assert_invalid passed:
+ 0000000: error: global variable out of range: 0 (max 0)
+ 0000013: error: OnGlobalGetExpr callback failed
+out/test/spec/extended-const/data.wast:506: assert_invalid passed:
+ 0000000: error: global variable out of range: 1 (max 1)
+ 0000029: error: OnGlobalGetExpr callback failed
+out/test/spec/extended-const/data.wast:515: assert_invalid passed:
+ out/test/spec/extended-const/data/data.61.wasm:000002d: error: initializer expression cannot reference a mutable global
+ 000002d: error: OnGlobalGetExpr callback failed
+33/33 tests passed.
+;;; STDOUT ;;)
diff --git a/test/spec/extended-const/elem.txt b/test/spec/extended-const/elem.txt
new file mode 100644
index 00000000..51e40d59
--- /dev/null
+++ b/test/spec/extended-const/elem.txt
@@ -0,0 +1,68 @@
+;;; TOOL: run-interp-spec
+;;; STDIN_FILE: third_party/testsuite/proposals/extended-const/elem.wast
+;;; ARGS*: --enable-extended-const
+(;; STDOUT ;;;
+out/test/spec/extended-const/elem.wast:321: assert_trap passed: out of bounds table access: table.init out of bounds
+out/test/spec/extended-const/elem.wast:331: assert_trap passed: out of bounds table access: table.init out of bounds
+out/test/spec/extended-const/elem.wast:336: assert_invalid passed:
+ 0000000: error: table variable out of range: 0 (max 0)
+ 0000016: error: BeginElemSegment callback failed
+out/test/spec/extended-const/elem.wast:346: assert_invalid passed:
+ out/test/spec/extended-const/elem/elem.34.wasm:0000014: error: type mismatch in initializer expression, expected [i32] but got [i64]
+ 0000015: error: EndElemSegmentInitExpr callback failed
+out/test/spec/extended-const/elem.wast:354: assert_invalid passed:
+ out/test/spec/extended-const/elem/elem.35.wasm:0000014: error: type mismatch in initializer expression, expected [i32] but got [funcref]
+ 0000015: error: EndElemSegmentInitExpr callback failed
+out/test/spec/extended-const/elem.wast:362: assert_invalid passed:
+ out/test/spec/extended-const/elem/elem.36.wasm:0000012: error: type mismatch in initializer expression, expected [i32] but got []
+ 0000013: error: EndElemSegmentInitExpr callback failed
+out/test/spec/extended-const/elem.wast:370: assert_invalid passed:
+ out/test/spec/extended-const/elem/elem.37.wasm:0000016: error: type mismatch at end of initializer expression, expected [] but got [i32]
+ 0000017: error: EndElemSegmentInitExpr callback failed
+out/test/spec/extended-const/elem.wast:378: assert_invalid passed:
+ out/test/spec/extended-const/elem/elem.38.wasm:000002c: error: type mismatch at end of initializer expression, expected [] but got [i32]
+ 000002d: error: EndElemSegmentInitExpr callback failed
+out/test/spec/extended-const/elem.wast:387: assert_invalid passed:
+ out/test/spec/extended-const/elem/elem.39.wasm:000002c: error: type mismatch at end of initializer expression, expected [] but got [i32]
+ 000002d: error: EndElemSegmentInitExpr callback failed
+out/test/spec/extended-const/elem.wast:397: assert_invalid passed:
+ out/test/spec/extended-const/elem/elem.40.wasm:0000015: error: invalid initializer: instruction not valid in initializer expression: i32.ctz
+ 0000015: error: OnUnaryExpr callback failed
+out/test/spec/extended-const/elem.wast:405: assert_invalid passed:
+ out/test/spec/extended-const/elem/elem.41.wasm:0000013: error: invalid initializer: instruction not valid in initializer expression: nop
+ 0000013: error: OnNopExpr callback failed
+out/test/spec/extended-const/elem.wast:413: assert_invalid passed:
+ out/test/spec/extended-const/elem/elem.42.wasm:0000013: error: invalid initializer: instruction not valid in initializer expression: nop
+ 0000013: error: OnNopExpr callback failed
+out/test/spec/extended-const/elem.wast:421: assert_invalid passed:
+ out/test/spec/extended-const/elem/elem.43.wasm:0000015: error: invalid initializer: instruction not valid in initializer expression: nop
+ 0000015: error: OnNopExpr callback failed
+out/test/spec/extended-const/elem.wast:435: assert_invalid passed:
+ 0000000: error: global variable out of range: 0 (max 0)
+ 0000014: error: OnGlobalGetExpr callback failed
+out/test/spec/extended-const/elem.wast:443: assert_invalid passed:
+ 0000000: error: global variable out of range: 1 (max 1)
+ 000002a: error: OnGlobalGetExpr callback failed
+out/test/spec/extended-const/elem.wast:452: assert_invalid passed:
+ out/test/spec/extended-const/elem/elem.46.wasm:000002e: error: initializer expression cannot reference a mutable global
+ 000002e: error: OnGlobalGetExpr callback failed
+out/test/spec/extended-const/elem.wast:463: assert_invalid passed:
+ out/test/spec/extended-const/elem/elem.47.wasm:0000018: error: type mismatch at elem expression. got externref, expected funcref
+ 0000018: error: OnElemSegmentElemExpr_RefNull callback failed
+out/test/spec/extended-const/elem.wast:471: assert_invalid passed:
+ 0000019: error: expected END opcode after element expression
+out/test/spec/extended-const/elem.wast:479: assert_invalid passed:
+ 0000017: error: expected ref.null or ref.func in passive element segment
+ 0000018: error: expected END opcode after element expression
+out/test/spec/extended-const/elem.wast:487: assert_invalid passed:
+ 0000017: error: expected ref.null or ref.func in passive element segment
+ 0000018: error: expected END opcode after element expression
+out/test/spec/extended-const/elem.wast:495: assert_invalid passed:
+ 0000022: error: expected ref.null or ref.func in passive element segment
+ 0000023: error: expected END opcode after element expression
+out/test/spec/extended-const/elem.wast:504: assert_invalid passed:
+ 0000022: error: expected ref.null or ref.func in passive element segment
+ 0000023: error: expected END opcode after element expression
+out/test/spec/extended-const/elem.wast:562: assert_trap passed: uninitialized table element
+47/47 tests passed.
+;;; STDOUT ;;)
diff --git a/test/spec/extended-const/global.txt b/test/spec/extended-const/global.txt
new file mode 100644
index 00000000..83d7ec54
--- /dev/null
+++ b/test/spec/extended-const/global.txt
@@ -0,0 +1,141 @@
+;;; TOOL: run-interp-spec
+;;; STDIN_FILE: third_party/testsuite/proposals/extended-const/global.wast
+;;; ARGS*: --enable-extended-const
+(;; STDOUT ;;;
+out/test/spec/extended-const/global.wast:263: assert_trap passed: undefined table index
+out/test/spec/extended-const/global.wast:285: assert_invalid passed:
+ out/test/spec/extended-const/global/global.1.wasm:0000029: error: can't global.set on immutable global at index 0.
+ 0000029: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:290: assert_invalid passed:
+ out/test/spec/extended-const/global/global.2.wasm:0000035: error: can't global.set on immutable global at index 0.
+ 0000035: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:299: assert_invalid passed:
+ out/test/spec/extended-const/global/global.5.wasm:0000013: error: invalid initializer: instruction not valid in initializer expression: f32.neg
+ 0000013: error: OnUnaryExpr callback failed
+out/test/spec/extended-const/global.wast:304: assert_invalid passed:
+ out/test/spec/extended-const/global/global.6.wasm:000000f: error: invalid initializer: instruction not valid in initializer expression: local.get
+ 000000f: error: OnLocalGetExpr callback failed
+out/test/spec/extended-const/global.wast:309: assert_invalid passed:
+ out/test/spec/extended-const/global/global.7.wasm:0000013: error: invalid initializer: instruction not valid in initializer expression: f32.neg
+ 0000013: error: OnUnaryExpr callback failed
+out/test/spec/extended-const/global.wast:314: assert_invalid passed:
+ out/test/spec/extended-const/global/global.8.wasm:0000010: error: invalid initializer: instruction not valid in initializer expression: nop
+ 0000010: error: OnNopExpr callback failed
+out/test/spec/extended-const/global.wast:319: assert_invalid passed:
+ out/test/spec/extended-const/global/global.9.wasm:0000010: error: invalid initializer: instruction not valid in initializer expression: i32.ctz
+ 0000010: error: OnUnaryExpr callback failed
+out/test/spec/extended-const/global.wast:324: assert_invalid passed:
+ out/test/spec/extended-const/global/global.10.wasm:000000e: error: invalid initializer: instruction not valid in initializer expression: nop
+ 000000e: error: OnNopExpr callback failed
+out/test/spec/extended-const/global.wast:329: assert_invalid passed:
+ out/test/spec/extended-const/global/global.11.wasm:0000012: error: type mismatch in initializer expression, expected [i32] but got [f32]
+ 0000013: error: EndGlobalInitExpr callback failed
+out/test/spec/extended-const/global.wast:334: assert_invalid passed:
+ out/test/spec/extended-const/global/global.12.wasm:0000011: error: type mismatch at end of initializer expression, expected [] but got [i32]
+ 0000012: error: EndGlobalInitExpr callback failed
+out/test/spec/extended-const/global.wast:339: assert_invalid passed:
+ out/test/spec/extended-const/global/global.13.wasm:000000d: error: type mismatch in initializer expression, expected [i32] but got []
+ 000000e: error: EndGlobalInitExpr callback failed
+out/test/spec/extended-const/global.wast:344: assert_invalid passed:
+ out/test/spec/extended-const/global/global.14.wasm:0000017: error: type mismatch in initializer expression, expected [funcref] but got [externref]
+ 0000018: error: EndGlobalInitExpr callback failed
+out/test/spec/extended-const/global.wast:349: assert_invalid passed:
+ out/test/spec/extended-const/global/global.15.wasm:0000027: error: type mismatch at end of initializer expression, expected [] but got [i32]
+ 0000028: error: EndGlobalInitExpr callback failed
+out/test/spec/extended-const/global.wast:354: assert_invalid passed:
+ out/test/spec/extended-const/global/global.16.wasm:0000027: error: type mismatch at end of initializer expression, expected [] but got [i32]
+ 0000028: error: EndGlobalInitExpr callback failed
+out/test/spec/extended-const/global.wast:359: assert_invalid passed:
+ 0000000: error: initializer expression can only reference an imported global
+ 000000f: error: OnGlobalGetExpr callback failed
+out/test/spec/extended-const/global.wast:364: assert_invalid passed:
+ 0000000: error: global variable out of range: 1 (max 1)
+ 000000f: error: OnGlobalGetExpr callback failed
+out/test/spec/extended-const/global.wast:369: assert_invalid passed:
+ 0000000: error: global variable out of range: 2 (max 2)
+ 0000025: error: OnGlobalGetExpr callback failed
+out/test/spec/extended-const/global.wast:374: assert_invalid passed:
+ out/test/spec/extended-const/global/global.20.wasm:0000029: error: initializer expression cannot reference a mutable global
+ 0000029: error: OnGlobalGetExpr callback failed
+out/test/spec/extended-const/global.wast:382: assert_malformed passed:
+ 0000026: error: global mutability must be 0 or 1
+out/test/spec/extended-const/global.wast:395: assert_malformed passed:
+ 0000026: error: global mutability must be 0 or 1
+out/test/spec/extended-const/global.wast:412: assert_malformed passed:
+ 0000011: error: global mutability must be 0 or 1
+out/test/spec/extended-const/global.wast:424: assert_malformed passed:
+ 0000011: error: global mutability must be 0 or 1
+out/test/spec/extended-const/global.wast:438: assert_invalid passed:
+ 0000000: error: global variable out of range: 0 (max 0)
+ 000001a: error: OnGlobalGetExpr callback failed
+out/test/spec/extended-const/global.wast:443: assert_invalid passed:
+ 0000000: error: global variable out of range: 1 (max 1)
+ 0000022: error: OnGlobalGetExpr callback failed
+out/test/spec/extended-const/global.wast:451: assert_invalid passed:
+ 0000000: error: global variable out of range: 1 (max 1)
+ 0000034: error: OnGlobalGetExpr callback failed
+out/test/spec/extended-const/global.wast:459: assert_invalid passed:
+ 0000000: error: global variable out of range: 2 (max 2)
+ 000003c: error: OnGlobalGetExpr callback failed
+out/test/spec/extended-const/global.wast:469: assert_invalid passed:
+ 0000000: error: global variable out of range: 0 (max 0)
+ 000001b: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:474: assert_invalid passed:
+ 0000000: error: global variable out of range: 1 (max 1)
+ 0000023: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:482: assert_invalid passed:
+ 0000000: error: global variable out of range: 1 (max 1)
+ 0000035: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:490: assert_invalid passed:
+ 0000000: error: global variable out of range: 2 (max 2)
+ 000003d: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:500: assert_invalid passed:
+ out/test/spec/extended-const/global/global.35.wasm:0000021: error: type mismatch in global.set, expected [i32] but got []
+ 0000021: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:509: assert_invalid passed:
+ out/test/spec/extended-const/global/global.36.wasm:0000025: error: type mismatch in global.set, expected [i32] but got []
+ 0000025: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:519: assert_invalid passed:
+ out/test/spec/extended-const/global/global.37.wasm:0000025: error: type mismatch in global.set, expected [i32] but got []
+ 0000025: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:529: assert_invalid passed:
+ out/test/spec/extended-const/global/global.38.wasm:0000027: error: type mismatch in global.set, expected [i32] but got []
+ 0000027: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:539: assert_invalid passed:
+ out/test/spec/extended-const/global/global.39.wasm:000002a: error: type mismatch in global.set, expected [i32] but got []
+ 000002a: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:549: assert_invalid passed:
+ out/test/spec/extended-const/global/global.40.wasm:0000025: error: type mismatch in global.set, expected [i32] but got []
+ 0000025: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:559: assert_invalid passed:
+ out/test/spec/extended-const/global/global.41.wasm:0000025: error: type mismatch in global.set, expected [i32] but got []
+ 0000025: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:569: assert_invalid passed:
+ out/test/spec/extended-const/global/global.42.wasm:0000025: error: type mismatch in global.set, expected [i32] but got []
+ 0000025: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:579: assert_invalid passed:
+ out/test/spec/extended-const/global/global.43.wasm:0000021: error: type mismatch in global.set, expected [i32] but got []
+ 0000021: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:588: assert_invalid passed:
+ out/test/spec/extended-const/global/global.44.wasm:0000021: error: type mismatch in global.set, expected [i32] but got []
+ 0000021: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:597: assert_invalid passed:
+ out/test/spec/extended-const/global/global.45.wasm:0000027: error: type mismatch in global.set, expected [i32] but got []
+ 0000027: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:607: assert_invalid passed:
+ out/test/spec/extended-const/global/global.46.wasm:000003e: error: type mismatch in global.set, expected [i32] but got []
+ 000003e: error: OnGlobalSetExpr callback failed
+out/test/spec/extended-const/global.wast:625: assert_malformed passed:
+ out/test/spec/extended-const/global/global.47.wat:1:33: error: redefinition of global "$foo"
+ (global $foo i32 (i32.const 0))(global $foo i32 (i32.const 0))
+ ^^^^^^
+out/test/spec/extended-const/global.wast:629: assert_malformed passed:
+ out/test/spec/extended-const/global/global.48.wat:1:34: error: redefinition of global "$foo"
+ (import "" "" (global $foo i32))(global $foo i32 (i32.const 0))
+ ^^^^^^
+out/test/spec/extended-const/global.wast:633: assert_malformed passed:
+ out/test/spec/extended-const/global/global.49.wat:1:34: error: redefinition of global "$foo"
+ (import "" "" (global $foo i32))(import "" "" (global $foo i32))
+ ^^^^^^
+107/107 tests passed.
+;;; STDOUT ;;)
diff --git a/test/update-spec-tests.py b/test/update-spec-tests.py
index eddc41b4..16423f27 100755
--- a/test/update-spec-tests.py
+++ b/test/update-spec-tests.py
@@ -91,7 +91,8 @@ def main(args):
flags = {
'memory64': '--enable-memory64',
'multi-memory': '--enable-multi-memory',
- 'exception-handling': '--enable-exceptions'
+ 'exception-handling': '--enable-exceptions',
+ 'extended-const': '--enable-extended-const',
}
unimplemented = set([
@@ -100,6 +101,7 @@ def main(args):
'function-references',
'threads',
'annotations',
+ 'exception-handling',
'extended-const',
])