def test_benchmark_headless_time_nbody_cranelift_native(benchmark): store = Store(engine.Native(Cranelift)) module = Module(store, TEST_BYTES) serialized = module.serialize() @benchmark def bench(): deserialized = Module.deserialize(store, serialized) _ = Instance(deserialized)
def test_benchmark_memory_view_int8_get(benchmark): store = Store(engine.JIT(Compiler)) module = Module(store, TEST_BYTES) instance = Instance(module) memory = instance.exports.memory.uint8_view() def bench(): _ = memory[0] benchmark(bench)
def test_benchmark_memory_view_bytearray_get(benchmark): store = Store(engine.JIT(Compiler)) module = Module(store, TEST_BYTES) instance = Instance(module) memory = bytearray(instance.exports.memory.buffer) def bench(): _ = memory[0] benchmark(bench)
def test_wasi(): store = Store() wasi_env = \ wasi.StateBuilder("test-program"). \ argument("--foo"). \ environments({"ABC": "DEF", "X": "YZ"}). \ map_directory("the_host_current_dir", "."). \ finalize() import_object = wasi_env.generate_import_object(store, wasi.Version.LATEST) instance = Instance(Module(store, TEST_BYTES), import_object) instance.exports._start()
def test_wat2wasm2instance(): wat = """ (module (type (func (param i32 i32) (result i32))) (func (type 0) local.get 0 local.get 1 i32.add) (export "sum" (func 0))) """ wasm_bytes = wat2wasm(wat) instance = Instance(Module(Store(), wasm_bytes)) assert instance.exports.sum(1, 2) == 3
def test_constructor_mutable(): store = Store() global_ = Global(store, Value.i32(42), mutable=True) assert global_.value == 42 type = global_.type assert type.type == Type.I32 assert type.mutable == True global_.value = 153 assert global_.value == 153
def test_return_multiple_values(): store = Store() module = Module( store, """ (module (type $swap_t (func (param i32 i64) (result i64 i32))) (func $swap_f (type $swap_t) (param $x i32) (param $y i64) (result i64 i32) local.get $y local.get $x) (export "swap" (func $swap_f))) """ ) instance = Instance(module) assert instance.exports.swap(41, 42) == (42, 41)
def test_exports_all_kind(): module = Module( Store(), """ (module (func (export "func") (param i32 i64)) (global (export "glob") i32 (i32.const 7)) (table (export "tab") 0 funcref) (memory (export "mem") 1)) """) instance = Instance(module) exports = instance.exports assert isinstance(exports, Exports) assert isinstance(exports.func, Function) assert isinstance(exports.glob, Global) assert isinstance(exports.tab, Table) assert isinstance(exports.mem, Memory)
def test_memory_views_length(): store = Store() memory_type = MemoryType(minimum=1, maximum=1) memory = Memory(store, memory_type) PAGE_SIZE = 65536 assert memory.size == 1 assert len(memory.uint8_view()) == PAGE_SIZE assert len(memory.int8_view()) == PAGE_SIZE assert len(memory.uint16_view()) == PAGE_SIZE / 2 assert len(memory.int16_view()) == PAGE_SIZE / 2 assert len(memory.uint32_view()) == PAGE_SIZE / 4 assert len(memory.int32_view()) == PAGE_SIZE / 4 assert len(memory.uint64_view()) == PAGE_SIZE / 8 assert len(memory.int64_view()) == PAGE_SIZE / 8 assert len(memory.float32_view()) == PAGE_SIZE / 4 assert len(memory.float64_view()) == PAGE_SIZE / 8
def test_deserialize(): store = Store() serialized_module = Module( store, """ (module (func (export "function") (param i32 i64))) """).serialize() module = Module.deserialize(store, serialized_module) del serialized_module exports = module.exports assert len(module.exports) == 1 assert exports[0].name == "function" assert isinstance(exports[0].type, FunctionType) assert exports[0].type.params == [Type.I32, Type.I64] assert exports[0].type.results == []
def build_instance(): import_object = ImportObject() store = Store(engine.JIT(Compiler)) import_object.register( "env", { "__sys_getpid": Function(store, lambda: 42, FunctionType([], [Type.I32])), }) import_object.register( "wasi_snapshot_preview1", { "proc_exit": Function(store, lambda *args: None, FunctionType([Type.I32], [])), "clock_time_get": Function(store, lambda *args: int(time.time()), FunctionType([Type.I32, Type.I64, Type.I32], [Type.I32])), "fd_close": Function(store, lambda *args: 1, FunctionType([Type.I32], [Type.I32])), "fd_write": Function( store, lambda *args: 1, FunctionType([Type.I32, Type.I32, Type.I32, Type.I32], [Type.I32])), "fd_seek": Function( store, lambda *args: 1, FunctionType([Type.I32, Type.I64, Type.I32, Type.I32], [Type.I32])), "fd_read": Function( store, lambda *args: 1, FunctionType([Type.I32, Type.I32, Type.I32, Type.I32], [Type.I32])), }) # Let's compile the module to be able to execute it! module = Module(store, open(quiet_path, 'rb').read()) # Now the module is compiled, we can instantiate it. return Instance(module, import_object)
def test_constructor(): store = Store() global_ = Global(store, Value.i32(42)) assert global_.value == 42 type = global_.type assert type.type == Type.I32 assert type.mutable == False global_ = Global(store, Value.i64(153), mutable=False) assert global_.value == 153 type = global_.type assert type.type == Type.I64 assert type.mutable == False
def test_wasi_imports(): env = wasi.StateBuilder("foo").finalize() import_object = env.generate_imports(Store(), wasi.Version.LATEST) assert isinstance(import_object, dict) assert sorted(import_object['wasi_snapshot_preview1'].keys()) == [ 'args_get', 'args_sizes_get', 'clock_res_get', 'clock_time_get', 'environ_get', 'environ_sizes_get', 'fd_advise', 'fd_allocate', 'fd_close', 'fd_datasync', 'fd_fdstat_get', 'fd_fdstat_set_flags', 'fd_fdstat_set_rights', 'fd_filestat_get', 'fd_filestat_set_size', 'fd_filestat_set_times', 'fd_pread', 'fd_prestat_dir_name', 'fd_prestat_get', 'fd_pwrite', 'fd_read', 'fd_readdir', 'fd_renumber', 'fd_seek', 'fd_sync', 'fd_tell', 'fd_write', 'path_create_directory', 'path_filestat_get', 'path_filestat_set_times', 'path_link', 'path_open', 'path_readlink', 'path_remove_directory', 'path_rename', 'path_symlink', 'path_unlink_file', 'poll_oneoff', 'proc_exit', 'proc_raise', 'random_get', 'sched_yield', 'sock_recv', 'sock_send', 'sock_shutdown' ]
def test_exports_iterable(): module = Module( Store(), """ (module (func (export "func") (param i32 i64)) (global (export "glob") i32 (i32.const 7)) (table (export "tab") 0 funcref) (memory (export "mem") 1)) """) instance = Instance(module) exports_iterator = iter(instance.exports) assert isinstance(exports_iterator, ExportsIterator) (export_name, export) = next(exports_iterator) assert export_name == "func" assert isinstance(export, Function) (export_name, export) = next(exports_iterator) assert export_name == "glob" assert isinstance(export, Global) (export_name, export) = next(exports_iterator) assert export_name == "tab" assert isinstance(export, Table) (export_name, export) = next(exports_iterator) assert export_name == "mem" assert isinstance(export, Memory) with pytest.raises(StopIteration): next(exports_iterator) # Works in a loop. for (name, export) in instance.exports: assert True # Works in a loop with `iter` called while it's not necessary. for (name, export) in iter(instance.exports): assert True assert [name for (name, _) in instance.exports ] == ["func", "glob", "tab", "mem"]
def test_import_function_defaultdict(): def sum(x: int, y: int) -> int: return x + y store = Store() module = Module( store, """ (module (import "math" "sum" (func $sum (param i32 i32) (result i32))) (func (export "add_one") (param i32) (result i32) local.get 0 i32.const 1 call $sum)) """) import_object = defaultdict(dict) import_object["math"]["sum"] = Function(store, sum) instance = Instance(module, import_object) assert instance.exports.add_one(1) == 2
def test_import_function(): def sum(x: int, y: int) -> int: return x + y store = Store() module = Module( store, """ (module (import "math" "sum" (func $sum (param i32 i32) (result i32))) (func (export "add_one") (param i32) (result i32) local.get 0 i32.const 1 call $sum)) """) import_object = ImportObject() import_object.register("math", {"sum": Function(store, sum)}) instance = Instance(module, import_object) assert instance.exports.add_one(1) == 2
def test_early_exit(): store = Store() module = Module( store, """ (module (type $run_t (func (param i32 i32) (result i32))) (type $early_exit_t (func (param) (result))) (import "env" "early_exit" (func $early_exit (type $early_exit_t))) (func $run (type $run_t) (param $x i32) (param $y i32) (result i32) (call $early_exit) (i32.add local.get $x local.get $y)) (export "run" (func $run))) """ ) def early_exit(): raise Exception('oops') import_object = ImportObject() import_object.register( "env", { "early_exit": Function(store, early_exit), } ) instance = Instance(module, import_object) try: instance.exports.run(1, 2) except Exception as err: assert 'oops' in str(err) else: assert False
def main(): # Create a store store = Store(engine.JIT(Compiler)) # Convert Wat file contents into Wasm binary code wat_file_name = str(sys.argv[1]) with open(wat_file_name) as wat_file: wat_source_code = wat_file.read() wasm_bytes = wat2wasm(wat_source_code) # Compile the Wasm module module = Module(store, wasm_bytes) # Obtain functions to be imported from the Wasm module import_object = make_import_object(store) # Instantiate the module instance = Instance(module, import_object) # Run start function and return to OS its exit code sys.exit(instance.exports.main())
def test_cross_compilation_roundtrip(): triple = target.Triple('x86_64-linux-musl') cpu_features = target.CpuFeatures() cpu_features.add('sse2') target_ = target.Target(triple, cpu_features) engine_ = engine.Native(Compiler, target_) store = Store(engine_) module = Module( store, """ (module (type $sum_t (func (param i32 i32) (result i32))) (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) local.get $x local.get $y i32.add) (export "sum" (func $sum_f))) """) assert isinstance(module, Module)
def test_constructor_with_annotated_function(): store = Store() def sum(a: int, b: 'i32', c: 'I32', d: 'i64', e: 'I64', f: float, g: 'f32', h: 'F32', i: 'f64', j: 'F64') -> int: return a + b function = Function(store, sum) function_type = function.type assert function_type.params == [Type.I32, Type.I32, Type.I32, Type.I64, Type.I64, Type.F32, Type.F32, Type.F32, Type.F64, Type.F64] assert function_type.results == [Type.I32] def return_none(a: int) -> None: pass function = Function(store, return_none) function_type = function.type assert function_type.params == [Type.I32] assert function_type.results == [] def take_none(a: None): pass with pytest.raises(RuntimeError) as context_manager: Function(store, take_none) exception = context_manager.value assert str(exception) == 'Variable `a` cannot have type `None`' def tuple(a: int) -> (int, int): return (a, a) function = Function(store, tuple) function_type = function.type assert function_type.params == [Type.I32] assert function_type.results == [Type.I32, Type.I32]
def test_imports(): imports = Module( Store(), """ (module (import "ns" "function" (func)) (import "ns" "global" (global f32)) (import "ns" "table" (table 1 2 anyfunc)) (import "ns" "memory" (memory 3 4))) """).imports assert isinstance(imports[0], ImportType) assert imports[0].module == "ns" assert imports[0].name == "function" assert isinstance(imports[0].type, FunctionType) assert imports[0].type.params == [] assert imports[0].type.results == [] assert imports[1].module == "ns" assert imports[1].name == "global" assert isinstance(imports[1].type, GlobalType) assert imports[1].type.type == Type.F32 assert imports[1].type.mutable == False assert imports[2].module == "ns" assert imports[2].name == "table" assert isinstance(imports[2].type, TableType) assert imports[2].type.type == Type.FUNC_REF assert imports[2].type.minimum == 1 assert imports[2].type.maximum == 2 assert imports[3].module == "ns" assert imports[3].name == "memory" assert isinstance(imports[3].type, MemoryType) assert imports[3].type.minimum == 3 assert imports[3].type.maximum == 4 assert imports[3].type.shared == False
def test_import_global(): store = Store() module = Module( store, """ (module (import "env" "global" (global $global (mut i32))) (func (export "read_g") (result i32) global.get $global) (func (export "write_g") (param i32) local.get 0 global.set $global)) """) global_ = Global(store, Value.i32(7), mutable=True) import_object = defaultdict(dict) import_object["env"]["global"] = global_ instance = Instance(module, import_object) assert instance.exports.read_g() == 7 global_.value = 153 assert instance.exports.read_g() == 153 instance.exports.write_g(11) assert global_.value == 11
(func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) local.get $x local.get $y i32.add) (export "sum" (func $sum_f))) """ ) # Define the engine that will drive everything. # # In this case, the engine is `wasmer.engine.JIT` which roughly # means that the executable code will live in memory. engine = engine.JIT(Compiler) # Create a store, that holds the engine. store = Store(engine) # Here we go. # # Let's compile the Wasm module. It is at this step that the Wasm text # is transformed into Wasm bytes (if necessary), and then compiled to # executable code by the compiler, which is then stored in memory by # the engine. module = Module(store, wasm_bytes) # Congrats, the Wasm module is compiled! Now let's execute it for the # sake of having a complete example. # # Let's instantiate the Wasm module. instance = Instance(module)
def get_string_ptr(string, instance): prepared_string = bytes(string, 'utf-8') length_of_string = len(prepared_string) + 1 string_ptr = instance.exports.allocate(length_of_string) memory = instance.exports.memory.uint8_view(string_ptr) memory[0:length_of_string] = prepared_string memory[length_of_string] = 0 return (string_ptr, length_of_string) relative_dir = 'lib/python' wasm_bytes = open(f'{relative_dir}/smartcore_wasi_lib.wasm', 'rb').read() store = Store(engine.JIT(Compiler)) module = Module(store, wasm_bytes) wasi_version = wasi.get_version(module, strict=True) wasi_env = wasi.StateBuilder('smartcore-wasi-lib').preopen_directory( ".").finalize() import_object = wasi_env.generate_import_object(store, wasi_version) instance = Instance(module, import_object) (file_ptr, file_len) = get_string_ptr(f'{relative_dir}/iris_knn.model', instance) instance.exports.init(file_ptr) perfomances = [] num_executions = 1000 if os.environ.get("noe") is not None: num_executions = int(os.environ.get("noe"))
def instance(): return Instance(Module(Store(), TEST_BYTES))
# #[no_mangle] # pub extern "C" fn add_one(x: i32) -> i32 { # unsafe { sum(x, 1) } # } # ``` wasm_bytes = wat2wasm(""" (module (import "env" "sum" (func $sum (param i32 i32) (result i32))) (func (export "add_one") (param $x i32) (result i32) local.get $x i32.const 1 call $sum)) """) # Create a store. store = Store(engine.Universal(Compiler)) # Let's compile the Wasm module. module = Module(store, wasm_bytes) # Here we go. # # When creating an `Instance`, we can pass an `ImportObject`. All # entities that must be imported are registered inside the # `ImportObject`. import_object = ImportObject() # Let's write the Python function that is going to be imported, # i.e. called by the WebAssembly module. def sum(x: int, y: int) -> int:
def test_wasi_import_object(): env = wasi.StateBuilder("foo").finalize() assert isinstance(env.generate_import_object(Store(), wasi.Version.LATEST), ImportObject)
def initiate_instance(): wasm_bytes = open(wasm_file_location, 'rb').read() store = Store() module = Module(store, wasm_bytes) instance = Instance(module) return instance
def test_store_defaults(): store = Store() assert store.engine_name == 'jit' assert store.compiler_name == 'cranelift'
def test_wasi_env_memory(): store = Store() wasi_env = wasi.StateBuilder("foo").finalize() import_object = wasi_env.generate_import_object(store, wasi.Version.LATEST) instance = Instance(Module(store, TEST_BYTES), import_object)