def _compute_table_offsets( store: Store, elements: Tuple[ElementSegment, ...], module_instance: ModuleInstance) -> Iterator[UInt32]: for element_segment in elements: frame = Frame( module=module_instance, locals=[], instructions=InstructionSequence(element_segment.offset), arity=1, ) config = Configuration(store=store) config.push_frame(frame) result = config.execute() if len(result) != 1: raise Exception( "Invariant: element segment offset returned empty result") offset = UInt32(cast(int, result[0])) table_address = module_instance.table_addrs[element_segment.table_idx] table_instance = store.tables[table_address] if offset + len(element_segment.init) > len(table_instance.elem): raise Unlinkable( f"Computed element segment offset exceeds table size: {offset} " f"+ {len(element_segment.init)} > {len(table_instance.elem)}") yield offset
def _initialize_globals( store: Store, module: Module, globals_addresses: Tuple[GlobalAddress, ...], ) -> Iterator[UInt32]: module_instances = ModuleInstance( types=(), func_addrs=(), memory_addrs=(), table_addrs=(), global_addrs=globals_addresses, exports=(), ) for global_ in module.globals: config = Configuration(store=store) frame = Frame( module=module_instances, locals=[], instructions=InstructionSequence(global_.init), arity=1, ) config.push_frame(frame) result = config.execute() if len(result) != 1: raise Exception( "Invariant: globals initialization returned empty result") yield UInt32(cast(int, result[0]))
def _compute_data_offsets(store: Store, datas: Tuple[DataSegment, ...], module_instance: ModuleInstance) -> Iterator[UInt32]: for data_segment in datas: frame = Frame( module=module_instance, locals=[], instructions=InstructionSequence(data_segment.offset), arity=1, ) config = Configuration(store=store) config.push_frame(frame) result = config.execute() if len(result) != 1: raise Exception( "Invariant: data segment offset returned empty result") offset = UInt32(cast(int, result[0])) memory_address = module_instance.memory_addrs[data_segment.memory_idx] memory_instance = store.mems[memory_address] if offset + len(data_segment.init) > len(memory_instance.data): raise Unlinkable( f"Computed data segment offset exceeds memory size: {offset} " f"+ {len(data_segment.init)} > {len(memory_instance.data)}") yield offset
def get_type_for_address(self, address: TAddress) -> TExtern: if isinstance(address, FunctionAddress): funcinst = self.funcs[address] return funcinst.type elif isinstance(address, TableAddress): tableinst = self.tables[address] return TableType( limits=Limits(UInt32(len(tableinst.elem)), tableinst.max), elem_type=FunctionAddress, ) elif isinstance(address, MemoryAddress): meminst = self.mems[address] return MemoryType( UInt32(len(meminst.data) // constants.PAGE_SIZE_64K), meminst.max, ) elif isinstance(address, GlobalAddress): globalinst = self.globals[address] return GlobalType( globalinst.mut, globalinst.valtype, ) else: raise Exception(f"Invariant: unknown address type: {type(address)}")
def parse_u32(stream: io.BytesIO) -> UInt32: start_pos = stream.tell() value = parse_unsigned_leb128(stream) end_pos = stream.tell() byte_width = end_pos - start_pos if byte_width > 5: # ceil(32 / 7) raise MalformedModule( f"encoded u32 exceeds maximum byte width: {byte_width} > 10" ) elif 0 <= value < constants.UINT32_CEIL: return UInt32(value) elif value < 0: raise MalformedModule( f"decoded uin32 was not positive: {value}" ) elif value > constants.UINT32_MAX: raise MalformedModule( f"decoded uin32 is greater than UINT32_MAX: {value} > 2**32 - 1" ) else: raise Exception("Invariant")
def instantiate_spectest_module(store: Store) -> ModuleInstance: logger = logging.getLogger("wasm.tools.fixtures.modules.spectest") def spectest__print_i32(store, arg): logger.debug('print_i32: %s', arg) return store, [] def spectest__print_i64(store, arg): logger.debug('print_i64: %s', arg) return store, [] def spectest__print_f32(store, arg): logger.debug('print_f32: %s', arg) return store, [] def spectest__print_f64(store, arg): logger.debug('print_f64: %s', arg) return store, [] def spectest__print_i32_f32(store, arg): logger.debug('print_i32_f32: %s', arg) return store, [] def spectest__print_f64_f64(store, arg): logger.debug('print_f64_f64: %s', arg) return store, [] def spectest__print(store, arg): logger.debug('print: %s', arg) return store, [] store.allocate_host_function(FunctionType((ValType.i32, ), ()), spectest__print_i32) store.allocate_host_function(FunctionType((ValType.i64, ), ()), spectest__print_i64) store.allocate_host_function(FunctionType((ValType.f32, ), ()), spectest__print_f32) store.allocate_host_function(FunctionType((ValType.f64, ), ()), spectest__print_f64) store.allocate_host_function(FunctionType((ValType.i32, ValType.f32), ()), spectest__print_i32_f32) store.allocate_host_function(FunctionType((ValType.f64, ValType.f64), ()), spectest__print_f64_f64) store.allocate_host_function(FunctionType((), ()), spectest__print) # min:1,max:2 required by import.wast: store.allocate_memory(MemoryType(UInt32(1), UInt32(2))) # 666 required by import.wast store.allocate_global(GlobalType(Mutability.const, ValType.i32), UInt32(666)) store.allocate_global(GlobalType(Mutability.const, ValType.f32), Float32(0.0)) store.allocate_global(GlobalType(Mutability.const, ValType.f64), Float64(0.0)) store.allocate_table( TableType( Limits(UInt32(10), UInt32(20)), FunctionAddress)) # max was 30, changed to 20 for import.wast moduleinst = ModuleInstance( types=( FunctionType((ValType.i32, ), ()), FunctionType((ValType.i64, ), ()), FunctionType((ValType.f32, ), ()), FunctionType((ValType.f64, ), ()), FunctionType((ValType.i32, ValType.f32), ()), FunctionType((ValType.f64, ValType.f64), ()), FunctionType((), ()), ), func_addrs=tuple(FunctionAddress(idx) for idx in range(7)), table_addrs=(TableAddress(0), ), memory_addrs=(MemoryAddress(0), ), global_addrs=(GlobalAddress(0), GlobalAddress(1)), exports=( ExportInstance("print_i32", FunctionAddress(0)), ExportInstance("print_i64", FunctionAddress(1)), ExportInstance("print_f32", FunctionAddress(2)), ExportInstance("print_f64", FunctionAddress(3)), ExportInstance("print_i32_f32", FunctionAddress(4)), ExportInstance("print_f64_f64", FunctionAddress(5)), ExportInstance("print", FunctionAddress(6)), ExportInstance("memory", MemoryAddress(0)), ExportInstance("global_i32", GlobalAddress(0)), ExportInstance("global_f32", GlobalAddress(1)), ExportInstance("global_f64", GlobalAddress(2)), ExportInstance("table", TableAddress(0)), ), ) return moduleinst
def instantiate_test_module(store): def test__func(store, arg): pass def test__func_i32(store, arg): pass def test__func_f32(store, arg): pass def test__func__i32(store, arg): pass def test__func__f32(store, arg): pass def test__func_i32_i32(store, arg): pass def test__func_i64_i64(store, arg): pass store.allocate_host_function(FunctionType((), ()), test__func) store.allocate_host_function(FunctionType((ValType.i32, ), ()), test__func_i32) store.allocate_host_function(FunctionType((ValType.f32, ), ()), test__func_f32) store.allocate_host_function(FunctionType((), (ValType.i32, )), test__func__i32) store.allocate_host_function(FunctionType((), (ValType.f32, )), test__func__f32) store.allocate_host_function( FunctionType((ValType.i32, ), (ValType.i32, )), test__func_i32_i32) store.allocate_host_function( FunctionType((ValType.i64, ), (ValType.i64, )), test__func_i64_i64) store.allocate_memory(MemoryType(1, None)) store.allocate_global(GlobalType(Mutability.const, ValType.i32), UInt32(666)) store.allocate_global(GlobalType(Mutability.const, ValType.f32), Float32(0.0)) store.allocate_table(TableType(Limits(10, None), FunctionAddress)) moduleinst = ModuleInstance( types=( FunctionType((), ()), FunctionType((ValType.i32, ), ()), FunctionType((ValType.f32, ), ()), FunctionType((), (ValType.i32, )), FunctionType((), (ValType.f32, )), FunctionType((ValType.i32, ), (ValType.i32, )), FunctionType((ValType.i64, ), (ValType.i64, )), ), func_addrs=tuple(FunctionAddress(idx) for idx in range(7)), table_addrs=(TableAddress(0), ), memory_addrs=(MemoryAddress(0), ), global_addrs=(GlobalAddress(0), GlobalAddress(1)), exports=( ExportInstance("func", FunctionAddress(0)), ExportInstance("func_i32", FunctionAddress(1)), ExportInstance("func_f32", FunctionAddress(2)), ExportInstance("func__i32", FunctionAddress(3)), ExportInstance("func__f32", FunctionAddress(4)), ExportInstance("func__i32_i32", FunctionAddress(5)), ExportInstance("func__i64_i64", FunctionAddress(6)), ExportInstance("memory-2-inf", MemoryAddress(0)), ExportInstance("global-i32", GlobalAddress(0)), ExportInstance("global-f32", GlobalAddress(1)), ExportInstance("table-10-inf", TableAddress(0)), ), ) return moduleinst
def s32_to_u32(value: SInt32) -> UInt32: if value < 0: return UInt32(value + constants.UINT32_CEIL) else: return UInt32(value)