From 36ec29b048145d7e27c9f8cdd56161117a498226 Mon Sep 17 00:00:00 2001 From: Jef Date: Mon, 18 Mar 2019 21:17:18 +0100 Subject: [PATCH] Fix imported memories --- README.md | 34 ++++---- src/backend.rs | 210 +++++++++++++++++++++++++++++++++++-------------- src/module.rs | 16 ++++ 3 files changed, 182 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 63d23adf95..8900d4864b 100644 --- a/README.md +++ b/README.md @@ -178,24 +178,24 @@ test spec_testsuite::br_if ... ok test spec_testsuite::address ... ok test spec_testsuite::comments ... ok test spec_testsuite::const_ ... ok -test spec_testsuite::call ... ok +test spec_testsuite::conversions ... FAILED test spec_testsuite::custom ... ok test spec_testsuite::custom_section ... ok -test spec_testsuite::conversions ... FAILED -test spec_testsuite::data ... ok +test spec_testsuite::call ... ok test spec_testsuite::br_table ... FAILED +test spec_testsuite::data ... ok test spec_testsuite::exports ... ok test spec_testsuite::elem ... ok test spec_testsuite::endianness ... ok -test spec_testsuite::call_indirect ... ok test spec_testsuite::f32_bitwise ... ok +test spec_testsuite::call_indirect ... ok test spec_testsuite::f64_bitwise ... ok test spec_testsuite::f32_cmp ... ok test spec_testsuite::fac ... ok -test spec_testsuite::f32 ... ok test spec_testsuite::f64 ... ok -test spec_testsuite::f64_cmp ... ok +test spec_testsuite::f32 ... ok test spec_testsuite::float_memory ... ok +test spec_testsuite::f64_cmp ... ok test spec_testsuite::forward ... ok test spec_testsuite::float_literals ... ok test spec_testsuite::func_ptrs ... FAILED @@ -208,12 +208,12 @@ test spec_testsuite::imports ... FAILED test spec_testsuite::inline_module ... ok test spec_testsuite::i32 ... ok test spec_testsuite::i64 ... ok -test spec_testsuite::labels ... ok test spec_testsuite::if_ ... ok test spec_testsuite::int_literals ... ok -test spec_testsuite::linking ... FAILED -test spec_testsuite::loop_ ... ok +test spec_testsuite::labels ... ok +test spec_testsuite::linking ... ok test spec_testsuite::int_exprs ... ok +test spec_testsuite::loop_ ... ok test spec_testsuite::memory_redundancy ... ok test spec_testsuite::memory_trap ... FAILED test spec_testsuite::memory_grow ... FAILED @@ -221,30 +221,30 @@ test spec_testsuite::left_to_right ... ok test spec_testsuite::memory ... ok test spec_testsuite::resizing ... ok test spec_testsuite::return_minimal ... ok -test spec_testsuite::nop ... ok test spec_testsuite::select ... ok test spec_testsuite::return_ ... ok +test spec_testsuite::skip_stack_guard_page ... FAILED +test spec_testsuite::nop ... ok +test spec_testsuite::set_local ... FAILED +test spec_testsuite::store_retval ... ok test spec_testsuite::stack ... ok test spec_testsuite::start ... ok -test spec_testsuite::store_retval ... ok -test spec_testsuite::skip_stack_guard_page ... FAILED -test spec_testsuite::switch ... ok -test spec_testsuite::set_local ... FAILED test spec_testsuite::token ... ok +test spec_testsuite::switch ... ok test spec_testsuite::type_ ... ok -test spec_testsuite::typecheck ... ok test spec_testsuite::traps ... FAILED +test spec_testsuite::typecheck ... ok test spec_testsuite::unreached_invalid ... ok test spec_testsuite::unwind ... FAILED test spec_testsuite::utf8_custom_section_id ... ok test spec_testsuite::utf8_import_field ... ok test spec_testsuite::utf8_import_module ... ok test spec_testsuite::utf8_invalid_encoding ... ok -test spec_testsuite::tee_local ... FAILED test spec_testsuite::unreachable ... ok +test spec_testsuite::tee_local ... FAILED test spec_testsuite::names ... ok -test result: FAILED. 62 passed; 12 failed; 0 ignored; 0 measured; 0 filtered out +test result: FAILED. 61 passed; 14 failed; 0 ignored; 0 measured; 0 filtered out ``` ## Getting involved diff --git a/src/backend.rs b/src/backend.rs index 24fb7e72e0..e81fa2d08a 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -1643,35 +1643,65 @@ macro_rules! load { dst: GPR, (offset, runtime_offset): (i32, Result) ) { - let memory_def_index = ctx.module_context - .defined_memory_index(0).unwrap(); + let mem_index = 0; + let reg_offset = ctx.module_context + .defined_memory_index(mem_index) + .map(|index| ( + None, + ctx.module_context.vmctx_vmmemory_definition(index) as i32 + )); + let (reg, mem_offset) = reg_offset.unwrap_or_else(|| { + let reg = ctx.block_state.regs.take(I64); - let vmctx_mem_ptr_offset = ctx.module_context - .vmctx_vmmemory_definition_base(memory_def_index) as i32; + dynasm!(ctx.asm + ; mov Rq(reg.rq().unwrap()), [ + Rq(VMCTX) + ctx.module_context.vmctx_vmmemory_import_from(mem_index) as i32 + ] + ); + + (Some(reg), 0) + }); + + let vmctx = GPR::Rq(VMCTX); if ctx.module_context.emit_memory_bounds_check() { - let vmctx_mem_len_offset = ctx.module_context - .vmctx_vmmemory_definition_current_length(memory_def_index) as i32; let trap_label = ctx.trap_label(); - let addr_reg = ctx.block_state.regs.take(I64); - match runtime_offset { + let addr_reg = match runtime_offset { Ok(imm) => { + let addr_reg = ctx.block_state.regs.take(I64); dynasm!(ctx.asm ; mov Rq(addr_reg.rq().unwrap()), QWORD imm as i64 + offset as i64 ); + addr_reg } Err(gpr) => { - let offset_reg = ctx.block_state.regs.take(I64); - dynasm!(ctx.asm - ; mov Rd(offset_reg.rq().unwrap()), offset - ; mov Rq(addr_reg.rq().unwrap()), Rq(gpr.rq().unwrap()) - ; add Rq(addr_reg.rq().unwrap()), Rq(offset_reg.rq().unwrap()) - ); - ctx.block_state.regs.release(offset_reg); + if offset == 0 { + ctx.to_reg(I32, ValueLocation::Reg(gpr)) + } else if offset > 0 { + let addr_reg = ctx.block_state.regs.take(I64); + dynasm!(ctx.asm + ; lea Rq(addr_reg.rq().unwrap()), [Rq(gpr.rq().unwrap()) + offset] + ); + addr_reg + } else { + let addr_reg = ctx.block_state.regs.take(I64); + let offset_reg = ctx.block_state.regs.take(I64); + dynasm!(ctx.asm + ; mov Rd(offset_reg.rq().unwrap()), offset + ; mov Rq(addr_reg.rq().unwrap()), Rq(gpr.rq().unwrap()) + ; add Rq(addr_reg.rq().unwrap()), Rq(offset_reg.rq().unwrap()) + ); + ctx.block_state.regs.release(offset_reg); + addr_reg + } } - } + }; dynasm!(ctx.asm - ; cmp [Rq(VMCTX) + vmctx_mem_len_offset], Rq(addr_reg.rq().unwrap()) + ; cmp [ + Rq(reg.unwrap_or(vmctx).rq().unwrap()) + + mem_offset + + ctx.module_context.vmmemory_definition_current_length() as i32 + ], Rq(addr_reg.rq().unwrap()) ; jna =>trap_label.0 ); ctx.block_state.regs.release(addr_reg); @@ -1679,8 +1709,15 @@ macro_rules! load { let mem_ptr_reg = ctx.block_state.regs.take(I64); dynasm!(ctx.asm - ; mov Rq(mem_ptr_reg.rq().unwrap()), [Rq(VMCTX) + vmctx_mem_ptr_offset] + ; mov Rq(mem_ptr_reg.rq().unwrap()), [ + Rq(reg.unwrap_or(vmctx).rq().unwrap()) + + mem_offset + + ctx.module_context.vmmemory_definition_base() as i32 + ] ); + if let Some(reg) = reg { + ctx.block_state.regs.release(reg); + } $emit_fn(ctx, dst, mem_ptr_reg, runtime_offset, offset); ctx.block_state.regs.release(mem_ptr_reg); } @@ -1765,44 +1802,81 @@ macro_rules! store { src: GPR, (offset, runtime_offset): (i32, Result) ) { - let memory_def_index = ctx.module_context - .defined_memory_index(0).unwrap(); + let mem_index = 0; + let reg_offset = ctx.module_context + .defined_memory_index(mem_index) + .map(|index| ( + None, + ctx.module_context.vmctx_vmmemory_definition(index) as i32 + )); + let (reg, mem_offset) = reg_offset.unwrap_or_else(|| { + let reg = ctx.block_state.regs.take(I64); - let vmctx_mem_ptr_offset = ctx.module_context - .vmctx_vmmemory_definition_base(memory_def_index) as i32; + dynasm!(ctx.asm + ; mov Rq(reg.rq().unwrap()), [ + Rq(VMCTX) + ctx.module_context.vmctx_vmmemory_import_from(mem_index) as i32 + ] + ); + + (Some(reg), 0) + }); + + let vmctx = GPR::Rq(VMCTX); if ctx.module_context.emit_memory_bounds_check() { - let vmctx_mem_len_offset = ctx.module_context - .vmctx_vmmemory_definition_current_length(memory_def_index) as i32; let trap_label = ctx.trap_label(); - let addr_reg = ctx.block_state.regs.take(I64); - match runtime_offset { + let addr_reg = match runtime_offset { Ok(imm) => { + let addr_reg = ctx.block_state.regs.take(I64); dynasm!(ctx.asm ; mov Rq(addr_reg.rq().unwrap()), QWORD imm as i64 + offset as i64 ); + addr_reg } Err(gpr) => { - let offset_reg = ctx.block_state.regs.take(I64); - dynasm!(ctx.asm - ; mov Rd(offset_reg.rq().unwrap()), offset - ; mov Rq(addr_reg.rq().unwrap()), Rq(gpr.rq().unwrap()) - ; add Rq(addr_reg.rq().unwrap()), Rq(offset_reg.rq().unwrap()) - ); - ctx.block_state.regs.release(offset_reg); + if offset == 0 { + ctx.to_reg(I32, ValueLocation::Reg(gpr)) + } else if offset > 0 { + let addr_reg = ctx.block_state.regs.take(I64); + dynasm!(ctx.asm + ; lea Rq(addr_reg.rq().unwrap()), [Rq(gpr.rq().unwrap()) + offset] + ); + addr_reg + } else { + let addr_reg = ctx.block_state.regs.take(I64); + let offset_reg = ctx.block_state.regs.take(I64); + dynasm!(ctx.asm + ; mov Rd(offset_reg.rq().unwrap()), offset + ; mov Rq(addr_reg.rq().unwrap()), Rq(gpr.rq().unwrap()) + ; add Rq(addr_reg.rq().unwrap()), Rq(offset_reg.rq().unwrap()) + ); + ctx.block_state.regs.release(offset_reg); + addr_reg + } } - } + }; dynasm!(ctx.asm - ; cmp [Rq(VMCTX) + vmctx_mem_len_offset], Rq(addr_reg.rq().unwrap()) + ; cmp [ + Rq(reg.unwrap_or(vmctx).rq().unwrap()) + + mem_offset + + ctx.module_context.vmmemory_definition_current_length() as i32 + ], Rq(addr_reg.rq().unwrap()) ; jna =>trap_label.0 ); ctx.block_state.regs.release(addr_reg); } - let mem_ptr_reg = ctx.block_state.regs.take(GPRType::Rq); + let mem_ptr_reg = ctx.block_state.regs.take(I64); dynasm!(ctx.asm - ; mov Rq(mem_ptr_reg.rq().unwrap()), [Rq(VMCTX) + vmctx_mem_ptr_offset] + ; mov Rq(mem_ptr_reg.rq().unwrap()), [ + Rq(reg.unwrap_or(vmctx).rq().unwrap()) + + mem_offset + + ctx.module_context.vmmemory_definition_base() as i32 + ] ); + if let Some(reg) = reg { + ctx.block_state.regs.release(reg); + } let src = $match_offset(ctx, mem_ptr_reg, runtime_offset, offset, src); ctx.block_state.regs.release(mem_ptr_reg); @@ -3960,33 +4034,42 @@ impl<'module, M: ModuleContext> Context<'module, M> { // TODO: Other memory indices pub fn memory_size(&mut self) { - self.push(ValueLocation::Immediate(0u32.into())); - self.relocated_function_call( - &magic::get_memory32_size_name(), - iter::once(I32), - iter::once(I32), - ); - // let tmp = self.block_state.regs.take(I32); - // - // // 16 is log2(64KiB as bytes) - // dynasm!(self.asm - // ; mov Rd(tmp.rq().unwrap()), [ - // rdi + self.module_context.vmctx_vmmemory_definition_current_length(0) as i32 - // ] - // ; shr Rd(tmp.rq().unwrap()), 16 - // ); - // - // self.push(ValueLocation::Reg(tmp)); + let memory_index = 0; + if let Some(defined_memory_index) = self.module_context.defined_memory_index(memory_index) { + self.push(ValueLocation::Immediate(defined_memory_index.into())); + self.relocated_function_call( + &magic::get_memory32_size_name(), + iter::once(I32), + iter::once(I32), + ); + } else { + self.push(ValueLocation::Immediate(memory_index.into())); + self.relocated_function_call( + &magic::get_imported_memory32_size_name(), + iter::once(I32), + iter::once(I32), + ); + } } // TODO: Other memory indices pub fn memory_grow(&mut self) { - self.push(ValueLocation::Immediate(0u32.into())); - self.relocated_function_call( - &magic::get_memory32_grow_name(), - iter::once(I32).chain(iter::once(I32)), - iter::once(I32), - ); + let memory_index = 0; + if let Some(defined_memory_index) = self.module_context.defined_memory_index(memory_index) { + self.push(ValueLocation::Immediate(defined_memory_index.into())); + self.relocated_function_call( + &magic::get_memory32_grow_name(), + iter::once(I32).chain(iter::once(I32)), + iter::once(I32), + ); + } else { + self.push(ValueLocation::Immediate(memory_index.into())); + self.relocated_function_call( + &magic::get_imported_memory32_grow_name(), + iter::once(I32).chain(iter::once(I32)), + iter::once(I32), + ); + } } // TODO: Use `ArrayVec`? @@ -4156,7 +4239,12 @@ impl<'module, M: ModuleContext> Context<'module, M> { let reg_offset = self .module_context .defined_table_index(table_index) - .map(|index| (None, self.module_context.vmctx_vmtable_definition(index) as i32)); + .map(|index| { + ( + None, + self.module_context.vmctx_vmtable_definition(index) as i32, + ) + }); let vmctx = GPR::Rq(VMCTX); let (reg, offset) = reg_offset.unwrap_or_else(|| { let reg = self.block_state.regs.take(I64); diff --git a/src/module.rs b/src/module.rs index 5517e9fef9..290b97ef68 100644 --- a/src/module.rs +++ b/src/module.rs @@ -420,8 +420,12 @@ pub trait ModuleContext { type GlobalType: SigType; fn vmctx_vmglobal_definition(&self, index: u32) -> u32; + fn vmctx_vmmemory_import_from(&self, memory_index: u32) -> u32; + fn vmctx_vmmemory_definition(&self, defined_memory_index: u32) -> u32; fn vmctx_vmmemory_definition_base(&self, defined_memory_index: u32) -> u32; fn vmctx_vmmemory_definition_current_length(&self, defined_memory_index: u32) -> u32; + fn vmmemory_definition_base(&self) -> u8; + fn vmmemory_definition_current_length(&self) -> u8; fn vmctx_vmtable_import_from(&self, table_index: u32) -> u32; fn vmctx_vmtable_definition(&self, defined_table_index: u32) -> u32; fn vmctx_vmtable_definition_base(&self, defined_table_index: u32) -> u32; @@ -514,6 +518,18 @@ impl ModuleContext for SimpleContext { unimplemented!() } + fn vmctx_vmmemory_definition(&self, defined_memory_index: u32) -> u32 { + unimplemented!() + } + fn vmctx_vmmemory_import_from(&self, memory_index: u32) -> u32 { + unimplemented!() + } + fn vmmemory_definition_base(&self) -> u8 { + unimplemented!() + } + fn vmmemory_definition_current_length(&self) -> u8 { + unimplemented!() + } fn vmctx_vmmemory_definition_base(&self, defined_memory_index: u32) -> u32 { VmCtx::offset_of_memory_ptr() }