From cc4f0e31a69a7087cff05bd2ae29ed2ed91f177c Mon Sep 17 00:00:00 2001 From: losfair Date: Thu, 25 Jul 2019 02:44:28 +0800 Subject: [PATCH] TwoHalves & trying to get cowsay to compile again --- lib/llvm-backend/src/backend.rs | 15 +++-- lib/llvm-backend/src/code.rs | 34 ++++++---- lib/llvm-backend/src/stackmap.rs | 53 +++++++++++---- lib/runtime-core/src/state.rs | 107 ++++++++++++++++++++++++++++--- 4 files changed, 170 insertions(+), 39 deletions(-) diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 778f7ddba..d148c074c 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -1,4 +1,4 @@ -use super::stackmap::{self, StackmapRegistry}; +use super::stackmap::{self, StackmapRegistry, StkMapRecord}; use crate::intrinsics::Intrinsics; use inkwell::{ memory_buffer::MemoryBuffer, @@ -18,6 +18,7 @@ use std::{ ptr::{self, NonNull}, slice, str, sync::{Arc, Once}, + collections::BTreeMap, }; use wasmer_runtime_core::{ backend::{ @@ -304,7 +305,7 @@ impl LLVMBackend { }; if raw_stackmap.len() > 0 { let map = stackmap::StackMap::parse(raw_stackmap).unwrap(); - eprintln!("{:?}", map); + println!("{:?}", map); let (code_ptr, code_size) = unsafe { ( @@ -316,10 +317,16 @@ impl LLVMBackend { local_functions: Default::default(), total_size: code_size, }; + + let mut map_records: BTreeMap = BTreeMap::new(); + for r in &map.stk_map_records { + map_records.insert(r.patchpoint_id as usize, r); + } + let mut map_record_idx: usize = 0; for size_record in &map.stk_size_records { - for _ in 0..size_record.record_count { - let map_record = &map.stk_map_records[map_record_idx]; + for _ in 0..size_record.record_count as usize { + let map_record = map_records.get(&map_record_idx).expect("map record not found"); let map_entry = &stackmaps.entries[map_record_idx]; assert_eq!(map_record.patchpoint_id, map_record_idx as u64); map_record_idx += 1; diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 32131873f..be623a91f 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -447,6 +447,26 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { let ctx = CtxType::new(module_info, function, cache_builder); self.ctx = Some(ctx); + + + { + let mut state = &mut self.state; + let builder = self.builder.as_ref().unwrap(); + let intrinsics = self.intrinsics.as_ref().unwrap(); + + let mut stackmaps = self.stackmaps.borrow_mut(); + emit_stack_map( + &intrinsics, + &builder, + self.index, + &mut *stackmaps, + StackmapEntryKind::FunctionHeader, + &self.locals, + &state, + ::std::usize::MAX, + ); + } + Ok(()) } @@ -2582,20 +2602,6 @@ impl ModuleCodeGenerator let local_func_index = self.functions.len(); - { - let mut stackmaps = self.stackmaps.borrow_mut(); - emit_stack_map( - &intrinsics, - &builder, - local_func_index, - &mut *stackmaps, - StackmapEntryKind::FunctionHeader, - &locals, - &state, - ::std::usize::MAX, - ); - } - let code = LLVMFunctionCodeGenerator { state, context: Some(context), diff --git a/lib/llvm-backend/src/stackmap.rs b/lib/llvm-backend/src/stackmap.rs index e75148f24..fa14985bd 100644 --- a/lib/llvm-backend/src/stackmap.rs +++ b/lib/llvm-backend/src/stackmap.rs @@ -74,7 +74,7 @@ impl StackmapEntry { map_record: &StkMapRecord, msm: &mut ModuleStateMap, ) { - #[derive(Copy, Clone, Debug)] + #[derive(Clone, Debug)] enum RuntimeOrConstant { Runtime(MachineValue), Constant(u64), @@ -88,10 +88,9 @@ impl StackmapEntry { }); assert_eq!(self.value_semantics.len(), map_record.locations.len()); - assert!(size_record.stack_size % 8 == 0); + //assert!(size_record.stack_size % 8 == 0); // is this also aligned to 16 bytes? - let mut machine_stack_layout: Vec = - vec![MachineValue::Undefined; (size_record.stack_size as usize) / 8]; + let mut machine_stack_half_layout: Vec = Vec::new(); let mut regs: Vec<(RegisterIndex, MachineValue)> = vec![]; let mut stack_constants: HashMap = HashMap::new(); @@ -145,30 +144,38 @@ impl StackmapEntry { } LocationType::Direct => match mv { MachineValue::WasmLocal(_) => { - assert_eq!(loc.location_size, 8); - assert!(loc.offset_or_small_constant < 0); + assert_eq!(loc.location_size, 8); // the pointer itself assert!( X64Register::from_dwarf_regnum(loc.dwarf_regnum).unwrap() == X64Register::GPR(GPR::RBP) ); - let stack_offset = ((-loc.offset_or_small_constant) % 8) as usize; - assert!(stack_offset > 0 && stack_offset <= machine_stack_layout.len()); - machine_stack_layout[stack_offset - 1] = mv; + if loc.offset_or_small_constant >= 0 { + eprintln!("XXX: {}", loc.offset_or_small_constant); + } + assert!(loc.offset_or_small_constant < 0); + let stack_offset = ((-loc.offset_or_small_constant) / 4) as usize; + while stack_offset > machine_stack_half_layout.len() { + machine_stack_half_layout.push(MachineValue::Undefined); + } + assert!(stack_offset > 0 && stack_offset <= machine_stack_half_layout.len()); + machine_stack_half_layout[stack_offset - 1] = mv; } _ => unreachable!( "Direct location type is not expected for values other than local" ), }, LocationType::Indirect => { - assert_eq!(loc.location_size, 8); assert!(loc.offset_or_small_constant < 0); assert!( X64Register::from_dwarf_regnum(loc.dwarf_regnum).unwrap() == X64Register::GPR(GPR::RBP) ); - let stack_offset = ((-loc.offset_or_small_constant) % 8) as usize; - assert!(stack_offset > 0 && stack_offset <= machine_stack_layout.len()); - machine_stack_layout[stack_offset - 1] = mv; + let stack_offset = ((-loc.offset_or_small_constant) / 4) as usize; + while stack_offset > machine_stack_half_layout.len() { + machine_stack_half_layout.push(MachineValue::Undefined); + } + assert!(stack_offset > 0 && stack_offset <= machine_stack_half_layout.len()); + machine_stack_half_layout[stack_offset - 1] = mv; } } } @@ -176,6 +183,26 @@ impl StackmapEntry { assert_eq!(wasm_stack.len(), self.stack_count); assert_eq!(wasm_locals.len(), self.local_count); + if machine_stack_half_layout.len() % 2 != 0 { + machine_stack_half_layout.push(MachineValue::Undefined); + } + + let mut machine_stack_layout: Vec = Vec::with_capacity(machine_stack_half_layout.len() / 2); + + for i in 0..machine_stack_half_layout.len() / 2 { + let left = &machine_stack_half_layout[i * 2]; + let right = &machine_stack_half_layout[i * 2 + 1]; + let only_left = match *right { + MachineValue::Undefined => true, + _ => false, + }; + if only_left { + machine_stack_layout.push(left.clone()); + } else { + machine_stack_layout.push(MachineValue::TwoHalves(Box::new((right.clone(), left.clone())))); + } + } + let diff = MachineStateDiff { last: None, stack_push: machine_stack_layout, diff --git a/lib/runtime-core/src/state.rs b/lib/runtime-core/src/state.rs index 9b1c289df..2e5559c86 100644 --- a/lib/runtime-core/src/state.rs +++ b/lib/runtime-core/src/state.rs @@ -35,7 +35,7 @@ pub struct MachineStateDiff { pub wasm_inst_offset: usize, // absolute value; not a diff. } -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +#[derive(Clone, Debug, Eq, PartialEq, Hash)] pub enum MachineValue { Undefined, Vmctx, @@ -44,6 +44,7 @@ pub enum MachineValue { ExplicitShadow, // indicates that all values above this are above the shadow region WasmStack(usize), WasmLocal(usize), + TwoHalves(Box<(MachineValue, MachineValue)>), // 32-bit values. TODO: optimize: add another type for inner "half" value to avoid boxing? } #[derive(Clone, Debug)] @@ -203,7 +204,7 @@ impl MachineState { .iter() .zip(old.stack_values.iter()) .enumerate() - .find(|&(_, (&a, &b))| a != b) + .find(|&(_, (a, b))| a != b) .map(|x| x.0) .unwrap_or(old.stack_values.len().min(self.stack_values.len())); assert_eq!(self.register_values.len(), old.register_values.len()); @@ -212,15 +213,15 @@ impl MachineState { .iter() .zip(old.register_values.iter()) .enumerate() - .filter(|&(_, (&a, &b))| a != b) - .map(|(i, (&a, _))| (RegisterIndex(i), a)) + .filter(|&(_, (a, b))| a != b) + .map(|(i, (a, _))| (RegisterIndex(i), a.clone())) .collect(); let first_diff_wasm_stack_depth: usize = self .wasm_stack .iter() .zip(old.wasm_stack.iter()) .enumerate() - .find(|&(_, (&a, &b))| a != b) + .find(|&(_, (a, b))| a != b) .map(|x| x.0) .unwrap_or(old.wasm_stack.len().min(self.wasm_stack.len())); MachineStateDiff { @@ -255,10 +256,10 @@ impl MachineStateDiff { state.stack_values.pop().unwrap(); } for v in &x.stack_push { - state.stack_values.push(*v); + state.stack_values.push(v.clone()); } - for &(index, v) in &x.reg_diff { - state.register_values[index.0] = v; + for &(index, ref v) in &x.reg_diff { + state.register_values[index.0] = v.clone(); } for _ in 0..x.wasm_stack_pop { state.wasm_stack.pop().unwrap(); @@ -488,6 +489,72 @@ pub mod x64 { } } } + MachineValue::TwoHalves(ref inner) => { + stack_offset -= 1; + // TODO: Cleanup + match inner.0 { + MachineValue::WasmStack(x) => { + match state.wasm_stack[x] { + WasmAbstractValue::Const(x) => { + assert!(x <= ::std::u32::MAX as u64); + stack[stack_offset] |= x; + } + WasmAbstractValue::Runtime => { + let v = f.stack[x].unwrap(); + assert!(v <= ::std::u32::MAX as u64); + stack[stack_offset] |= v; + } + } + } + MachineValue::WasmLocal(x) => { + stack_offset -= 1; + match fsm.locals[x] { + WasmAbstractValue::Const(x) => { + assert!(x <= ::std::u32::MAX as u64); + stack[stack_offset] |= x; + } + WasmAbstractValue::Runtime => { + let v = f.locals[x].unwrap(); + assert!(v <= ::std::u32::MAX as u64); + stack[stack_offset] |= v; + } + } + } + MachineValue::Undefined => {} + _ => unimplemented!("TwoHalves.0"), + } + match inner.1 { + MachineValue::WasmStack(x) => { + match state.wasm_stack[x] { + WasmAbstractValue::Const(x) => { + assert!(x <= ::std::u32::MAX as u64); + stack[stack_offset] |= x << 32; + } + WasmAbstractValue::Runtime => { + let v = f.stack[x].unwrap(); + assert!(v <= ::std::u32::MAX as u64); + stack[stack_offset] |= v << 32; + } + } + } + MachineValue::WasmLocal(x) => { + stack_offset -= 1; + match fsm.locals[x] { + WasmAbstractValue::Const(x) => { + assert!(x <= ::std::u32::MAX as u64); + stack[stack_offset] |= x << 32; + } + WasmAbstractValue::Runtime => { + let v = f.locals[x].unwrap(); + assert!(v <= ::std::u32::MAX as u64); + stack[stack_offset] |= v << 32; + } + } + } + MachineValue::Undefined => {} + _ => unimplemented!("TwoHalves.1"), + } + } } } if !got_explicit_shadow { @@ -785,6 +852,30 @@ pub mod x64 { wasm_locals[idx] = Some(*stack); stack = stack.offset(1); } + MachineValue::TwoHalves(ref inner) => { + let v = *stack; + stack = stack.offset(1); + match inner.0 { + MachineValue::WasmStack(idx) => { + wasm_stack[idx] = Some(v & 0xffffffffu64); + } + MachineValue::WasmLocal(idx) => { + wasm_locals[idx] = Some(v & 0xffffffffu64); + } + MachineValue::Undefined => {}, + _ => unimplemented!("TwoHalves.0 (read)") + } + match inner.1 { + MachineValue::WasmStack(idx) => { + wasm_stack[idx] = Some(v >> 32); + } + MachineValue::WasmLocal(idx) => { + wasm_locals[idx] = Some(v >> 32); + } + MachineValue::Undefined => {}, + _ => unimplemented!("TwoHalves.1 (read)") + } + } } } stack = stack.offset(1); // RBP