summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcheck.py28
-rw-r--r--scripts/test/shared.py1
-rw-r--r--scripts/test/support.py2
-rw-r--r--src/tools/wasm-shell.cpp31
-rw-r--r--src/wasm-interpreter.h21
-rw-r--r--test/spec/imports.wast151
6 files changed, 171 insertions, 63 deletions
diff --git a/check.py b/check.py
index 14103805c..f1994a791 100755
--- a/check.py
+++ b/check.py
@@ -230,6 +230,8 @@ def run_spec_tests():
if 'exports.wast' in base: # FIXME
continue
+ run_spec_test(wast)
+
# check binary format. here we can verify execution of the final
# result, no need for an output verification
# some wast files cannot be split:
@@ -241,21 +243,21 @@ def run_spec_tests():
if base not in ['comments.wast', 'ref_null.wast', 'ref_is_null.wast', 'ref_func.wast', 'old_select.wast']:
split_num = 0
actual = ''
- for module, asserts in support.split_wast(wast):
- print(' testing split module', split_num)
- split_num += 1
- support.write_wast('split.wast', module, asserts)
- run_spec_test('split.wast') # before binary stuff - just check it's still ok split out
- run_opt_test('split.wast') # also that our optimizer doesn't break on it
- result_wast = shared.binary_format_check('split.wast', verify_final_result=False, original_wast=wast)
- # add the asserts, and verify that the test still passes
- open(result_wast, 'a').write('\n' + '\n'.join(asserts))
- actual += run_spec_test(result_wast)
+ with open('spec.wast', 'w') as transformed_spec_file:
+ for module, asserts in support.split_wast(wast):
+ print(' testing split module', split_num)
+ split_num += 1
+ support.write_wast('split.wast', module, asserts)
+ run_opt_test('split.wast') # also that our optimizer doesn't break on it
+ result_wast_file = shared.binary_format_check('split.wast', verify_final_result=False, original_wast=wast)
+ with open(result_wast_file) as f:
+ result_wast = f.read()
+ # add the asserts, and verify that the test still passes
+ transformed_spec_file.write(result_wast + '\n' + '\n'.join(asserts))
+
# compare all the outputs to the expected output
+ actual = run_spec_test('spec.wast')
check_expected(actual, os.path.join(shared.get_test_dir('spec'), 'expected-output', base + '.log'))
- else:
- # handle unsplittable wast files
- run_spec_test(wast)
def run_validator_tests():
diff --git a/scripts/test/shared.py b/scripts/test/shared.py
index 54c7c861d..d3af99455 100644
--- a/scripts/test/shared.py
+++ b/scripts/test/shared.py
@@ -424,7 +424,6 @@ SPEC_TESTS_TO_SKIP = [
'utf8-invalid-encoding.wast',
# 'register' command
- 'imports.wast',
'linking.wast',
# Misc. unsupported constructs
diff --git a/scripts/test/support.py b/scripts/test/support.py
index a4a61fc22..7313169fa 100644
--- a/scripts/test/support.py
+++ b/scripts/test/support.py
@@ -145,7 +145,7 @@ def split_wast(wastFile):
ret += [(chunk, [])]
elif chunk.startswith('(assert_invalid'):
continue
- elif chunk.startswith(('(assert', '(invoke')):
+ elif chunk.startswith(('(assert', '(invoke', '(register')):
# ret may be empty if there are some asserts before the first
# module. in that case these are asserts *without* a module, which
# are valid (they may check something that doesn't refer to a module
diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp
index a2d35f444..c6815c92d 100644
--- a/src/tools/wasm-shell.cpp
+++ b/src/tools/wasm-shell.cpp
@@ -81,9 +81,9 @@ struct ShellOptions : public Options {
class Shell {
protected:
- std::map<Name, std::unique_ptr<Module>> modules;
- std::map<Name, std::unique_ptr<SExpressionWasmBuilder>> builders;
- std::map<Name, std::unique_ptr<ShellExternalInterface>> interfaces;
+ std::map<Name, std::shared_ptr<Module>> modules;
+ std::map<Name, std::shared_ptr<SExpressionWasmBuilder>> builders;
+ std::map<Name, std::shared_ptr<ShellExternalInterface>> interfaces;
std::map<Name, std::shared_ptr<ModuleInstance>> instances;
// used for imports
std::map<Name, std::shared_ptr<ModuleInstance>> linkedInstances;
@@ -92,7 +92,7 @@ protected:
void instantiate(Module* wasm) {
auto tempInterface =
- wasm::make_unique<ShellExternalInterface>(linkedInstances);
+ std::make_shared<ShellExternalInterface>(linkedInstances);
auto tempInstance = std::make_shared<ModuleInstance>(
*wasm, tempInterface.get(), linkedInstances);
interfaces[wasm->name].swap(tempInterface);
@@ -123,12 +123,12 @@ protected:
Colors::green(std::cerr);
std::cerr << "BUILDING MODULE [line: " << s.line << "]\n";
Colors::normal(std::cerr);
- auto module = wasm::make_unique<Module>();
+ auto module = std::make_shared<Module>();
auto builder =
- wasm::make_unique<SExpressionWasmBuilder>(*module, s, IRProfile::Normal);
+ std::make_shared<SExpressionWasmBuilder>(*module, s, IRProfile::Normal);
auto moduleName = module->name;
lastModule = module->name;
- builders[moduleName].swap(builder);
+ builders[moduleName] = builder;
modules[moduleName].swap(module);
modules[moduleName]->features = FeatureSet::All;
bool valid = WasmValidator().validate(*modules[moduleName]);
@@ -150,15 +150,12 @@ protected:
auto name = s[1]->str();
linkedInstances[name] = instance;
- // swap to the new name in all maps
- modules[name].swap(modules[lastModule]);
- modules.erase(lastModule);
- builders[name].swap(builders[lastModule]);
- builders.erase(lastModule);
- interfaces[name].swap(interfaces[lastModule]);
- interfaces.erase(lastModule);
- instances[name].swap(instances[lastModule]);
- instances.erase(lastModule);
+ // we copy pointers as a registered module's name might still be used
+ // in an assertion or invoke command.
+ modules[name] = modules[lastModule];
+ builders[name] = builders[lastModule];
+ interfaces[name] = interfaces[lastModule];
+ instances[name] = instances[lastModule];
Colors::green(std::cerr);
std::cerr << "REGISTER MODULE INSTANCE AS \"" << name.c_str()
@@ -316,7 +313,7 @@ protected:
// TODO: spectest module is considered deprecated by the spec. Remove when
// is actually removed from the spec test.
void buildSpectestModule() {
- auto spectest = std::make_unique<Module>();
+ auto spectest = std::make_shared<Module>();
spectest->name = "spectest";
Builder builder(*spectest);
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 8c772a96e..844716f95 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -2422,23 +2422,24 @@ private:
protected:
// Returns the instance that defines the memory used by this one.
SubType* getMemoryInstance() {
- if (instance.wasm.memory.imported()) {
- return instance.linkedInstances.at(instance.wasm.memory.module).get();
- } else {
- return static_cast<SubType*>(&instance);
+ auto* inst = instance.self();
+ while (inst->wasm.memory.imported()) {
+ inst = inst->linkedInstances.at(inst->wasm.memory.module).get();
}
+ return inst;
}
// Returns a reference to the current value of a potentially imported global
Literals& getGlobal(Name name) {
- auto* global = instance.wasm.getGlobal(name);
- if (global->imported()) {
- auto inst = instance.linkedInstances.at(global->module);
+ auto* inst = instance.self();
+ auto* global = inst->wasm.getGlobal(name);
+ while (global->imported()) {
+ inst = inst->linkedInstances.at(global->module).get();
Export* globalExport = inst->wasm.getExport(global->base);
- return inst->globals[globalExport->value];
- } else {
- return instance.globals[name];
+ global = inst->wasm.getGlobal(globalExport->value);
}
+
+ return inst->globals[global->name];
}
public:
diff --git a/test/spec/imports.wast b/test/spec/imports.wast
index c39ae8dd3..43ffedaee 100644
--- a/test/spec/imports.wast
+++ b/test/spec/imports.wast
@@ -10,9 +10,13 @@
(func (export "func-i64->i64") (param i64) (result i64) (local.get 0))
(global (export "global-i32") i32 (i32.const 55))
(global (export "global-f32") f32 (f32.const 44))
+ ;;; FIXME: Exporting a mutable global is currently not supported. Make mutable
+ ;;; when support is added.
+ (global (export "global-mut-i64") i64 (i64.const 66))
(table (export "table-10-inf") 10 funcref)
- ;; (table (export "table-10-20") 10 20 funcref)
+ (table (export "table-10-20") 10 20 funcref)
(memory (export "memory-2-inf") 2)
+ ;; Multiple memories are not yet supported
;; (memory (export "memory-2-4") 2 4)
)
@@ -43,10 +47,13 @@
(func (export "p1") (import "spectest" "print_i32") (param i32))
(func $p (export "p2") (import "spectest" "print_i32") (param i32))
- (func (export "p3") (export "p4") (import "spectest" "print_i32") (param i32))
+ (func (import "spectest" "print_i32") (param i32))
(func (export "p5") (import "spectest" "print_i32") (type 0))
(func (export "p6") (import "spectest" "print_i32") (type 0) (param i32) (result))
+ ;; (export "p3" (func $print_i32))
+ ;; (export "p4" (func $print_i32))
+
(import "spectest" "print_i32" (func (type $forward)))
(func (import "spectest" "print_i32") (type $forward))
(type $forward (func (param i32)))
@@ -95,6 +102,26 @@
"unknown type"
)
+;; Export sharing name with import
+(module
+ (import "spectest" "print_i32" (func $imported_print (param i32)))
+ (func (export "print_i32") (param $i i32)
+ (call $imported_print (local.get $i))
+ )
+)
+
+(assert_return (invoke "print_i32" (i32.const 13)))
+
+;; Export sharing name with import
+(module
+ (import "spectest" "print_i32" (func $imported_print (param i32)))
+ (func (export "print_i32") (param $i i32) (param $j i32) (result i32)
+ (i32.add (local.get $i) (local.get $j))
+ )
+)
+
+(assert_return (invoke "print_i32" (i32.const 5) (i32.const 11)) (i32.const 16))
+
(module (import "test" "func" (func)))
(module (import "test" "func-i32" (func (param i32))))
(module (import "test" "func-f32" (func (param f32))))
@@ -230,6 +257,7 @@
(module (import "test" "global-i32" (global i32)))
(module (import "test" "global-f32" (global f32)))
+(module (import "test" "global-mut-i64" (global (mut i64))))
(assert_unlinkable
(module (import "test" "unknown" (global i32)))
@@ -241,6 +269,55 @@
)
(assert_unlinkable
+ (module (import "test" "global-i32" (global i64)))
+ "incompatible import type"
+)
+(assert_unlinkable
+ (module (import "test" "global-i32" (global f32)))
+ "incompatible import type"
+)
+(assert_unlinkable
+ (module (import "test" "global-i32" (global f64)))
+ "incompatible import type"
+)
+(assert_unlinkable
+ (module (import "test" "global-i32" (global (mut i32))))
+ "incompatible import type"
+)
+(assert_unlinkable
+ (module (import "test" "global-f32" (global i32)))
+ "incompatible import type"
+)
+(assert_unlinkable
+ (module (import "test" "global-f32" (global i64)))
+ "incompatible import type"
+)
+(assert_unlinkable
+ (module (import "test" "global-f32" (global f64)))
+ "incompatible import type"
+)
+(assert_unlinkable
+ (module (import "test" "global-f32" (global (mut f32))))
+ "incompatible import type"
+)
+(assert_unlinkable
+ (module (import "test" "global-mut-i64" (global (mut i32))))
+ "incompatible import type"
+)
+(assert_unlinkable
+ (module (import "test" "global-mut-i64" (global (mut f32))))
+ "incompatible import type"
+)
+(assert_unlinkable
+ (module (import "test" "global-mut-i64" (global (mut f64))))
+ "incompatible import type"
+)
+(assert_unlinkable
+ (module (import "test" "global-mut-i64" (global i64)))
+ "incompatible import type"
+)
+
+(assert_unlinkable
(module (import "test" "func" (global i32)))
"incompatible import type"
)
@@ -270,11 +347,11 @@
(module
(type (func (result i32)))
- (import "spectest" "table" (table 10 20 funcref))
- (elem (i32.const 1) $f $g)
+ (import "spectest" "table" (table $tab 10 20 funcref))
+ (elem (table $tab) (i32.const 1) func $f $g)
(func (export "call") (param i32) (result i32)
- (call_indirect (type 0) (local.get 0))
+ (call_indirect $tab (type 0) (local.get 0))
)
(func $f (result i32) (i32.const 11))
(func $g (result i32) (i32.const 22))
@@ -289,11 +366,11 @@
(module
(type (func (result i32)))
- (table (import "spectest" "table") 10 20 funcref)
- (elem (i32.const 1) $f $g)
+ (table $tab (import "spectest" "table") 10 20 funcref)
+ (elem (table $tab) (i32.const 1) func $f $g)
(func (export "call") (param i32) (result i32)
- (call_indirect (type 0) (local.get 0))
+ (call_indirect $tab (type 0) (local.get 0))
)
(func $f (result i32) (i32.const 11))
(func $g (result i32) (i32.const 22))
@@ -306,22 +383,25 @@
(assert_trap (invoke "call" (i32.const 100)) "undefined element")
-(assert_invalid
- (module (import "" "" (table 10 funcref)) (import "" "" (table 10 funcref)))
- "multiple tables"
-)
-(assert_invalid
- (module (import "" "" (table 10 funcref)) (table 10 funcref))
- "multiple tables"
-)
-(assert_invalid
- (module (table 10 funcref) (table 10 funcref))
- "multiple tables"
+(module
+ (import "spectest" "table" (table 0 funcref))
+ (import "spectest" "table" (table 0 funcref))
+ (table 10 funcref)
+ (table 10 funcref)
)
(module (import "test" "table-10-inf" (table 10 funcref)))
(module (import "test" "table-10-inf" (table 5 funcref)))
(module (import "test" "table-10-inf" (table 0 funcref)))
+(module (import "test" "table-10-20" (table 10 funcref)))
+(module (import "test" "table-10-20" (table 5 funcref)))
+(module (import "test" "table-10-20" (table 0 funcref)))
+(module (import "test" "table-10-20" (table 10 20 funcref)))
+(module (import "test" "table-10-20" (table 5 20 funcref)))
+(module (import "test" "table-10-20" (table 0 20 funcref)))
+(module (import "test" "table-10-20" (table 10 25 funcref)))
+(module (import "test" "table-10-20" (table 5 25 funcref)))
+(module (import "test" "table-10-20" (table 0 25 funcref)))
(module (import "spectest" "table" (table 10 funcref)))
(module (import "spectest" "table" (table 5 funcref)))
(module (import "spectest" "table" (table 0 funcref)))
@@ -349,6 +429,14 @@
"incompatible import type"
)
(assert_unlinkable
+ (module (import "test" "table-10-20" (table 12 20 funcref)))
+ "incompatible import type"
+)
+(assert_unlinkable
+ (module (import "test" "table-10-20" (table 10 18 funcref)))
+ "incompatible import type"
+)
+(assert_unlinkable
(module (import "spectest" "table" (table 12 funcref)))
"incompatible import type"
)
@@ -380,7 +468,7 @@
(module
(import "spectest" "memory" (memory 1 2))
- (data (i32.const 10) "\10")
+ (data (memory 0) (i32.const 10) "\10")
(func (export "load") (param i32) (result i32) (i32.load (local.get 0)))
)
@@ -392,7 +480,7 @@
(module
(memory (import "spectest" "memory") 1 2)
- (data (i32.const 10) "\10")
+ (data (memory 0) (i32.const 10) "\10")
(func (export "load") (param i32) (result i32) (i32.load (local.get 0)))
)
@@ -494,6 +582,27 @@
(assert_return (invoke "grow" (i32.const 1)) (i32.const -1))
(assert_return (invoke "grow" (i32.const 0)) (i32.const 2))
+(module $Mgm
+ (memory (export "memory") 1) ;; initial size is 1
+ (func (export "grow") (result i32) (memory.grow (i32.const 1)))
+)
+(register "grown-memory" $Mgm)
+(assert_return (invoke $Mgm "grow") (i32.const 1)) ;; now size is 2
+(module $Mgim1
+ ;; imported memory limits should match, because external memory size is 2 now
+ (memory (import "grown-memory" "memory") 2)
+ (export "memory" (memory 0))
+ (func (export "grow") (result i32) (memory.grow (i32.const 1)))
+)
+(register "grown-imported-memory" $Mgim1)
+(assert_return (invoke $Mgim1 "grow") (i32.const 2)) ;; now size is 3
+(module $Mgim2
+ ;; imported memory limits should match, because external memory size is 3 now
+ (import "grown-imported-memory" "memory" (memory 3))
+ (func (export "size") (result i32) (memory.size))
+)
+(assert_return (invoke $Mgim2 "size") (i32.const 3))
+
;; Syntax errors