TwoHalves & trying to get cowsay to compile again

This commit is contained in:
losfair 2019-07-25 02:44:28 +08:00
parent 0133b92bec
commit cc4f0e31a6
4 changed files with 170 additions and 39 deletions

View File

@ -1,4 +1,4 @@
use super::stackmap::{self, StackmapRegistry}; use super::stackmap::{self, StackmapRegistry, StkMapRecord};
use crate::intrinsics::Intrinsics; use crate::intrinsics::Intrinsics;
use inkwell::{ use inkwell::{
memory_buffer::MemoryBuffer, memory_buffer::MemoryBuffer,
@ -18,6 +18,7 @@ use std::{
ptr::{self, NonNull}, ptr::{self, NonNull},
slice, str, slice, str,
sync::{Arc, Once}, sync::{Arc, Once},
collections::BTreeMap,
}; };
use wasmer_runtime_core::{ use wasmer_runtime_core::{
backend::{ backend::{
@ -304,7 +305,7 @@ impl LLVMBackend {
}; };
if raw_stackmap.len() > 0 { if raw_stackmap.len() > 0 {
let map = stackmap::StackMap::parse(raw_stackmap).unwrap(); let map = stackmap::StackMap::parse(raw_stackmap).unwrap();
eprintln!("{:?}", map); println!("{:?}", map);
let (code_ptr, code_size) = unsafe { let (code_ptr, code_size) = unsafe {
( (
@ -316,10 +317,16 @@ impl LLVMBackend {
local_functions: Default::default(), local_functions: Default::default(),
total_size: code_size, total_size: code_size,
}; };
let mut map_records: BTreeMap<usize, &StkMapRecord> = 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; let mut map_record_idx: usize = 0;
for size_record in &map.stk_size_records { for size_record in &map.stk_size_records {
for _ in 0..size_record.record_count { for _ in 0..size_record.record_count as usize {
let map_record = &map.stk_map_records[map_record_idx]; let map_record = map_records.get(&map_record_idx).expect("map record not found");
let map_entry = &stackmaps.entries[map_record_idx]; let map_entry = &stackmaps.entries[map_record_idx];
assert_eq!(map_record.patchpoint_id, map_record_idx as u64); assert_eq!(map_record.patchpoint_id, map_record_idx as u64);
map_record_idx += 1; map_record_idx += 1;

View File

@ -447,6 +447,26 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
let ctx = CtxType::new(module_info, function, cache_builder); let ctx = CtxType::new(module_info, function, cache_builder);
self.ctx = Some(ctx); 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(()) Ok(())
} }
@ -2582,20 +2602,6 @@ impl ModuleCodeGenerator<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
let local_func_index = self.functions.len(); 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 { let code = LLVMFunctionCodeGenerator {
state, state,
context: Some(context), context: Some(context),

View File

@ -74,7 +74,7 @@ impl StackmapEntry {
map_record: &StkMapRecord, map_record: &StkMapRecord,
msm: &mut ModuleStateMap, msm: &mut ModuleStateMap,
) { ) {
#[derive(Copy, Clone, Debug)] #[derive(Clone, Debug)]
enum RuntimeOrConstant { enum RuntimeOrConstant {
Runtime(MachineValue), Runtime(MachineValue),
Constant(u64), Constant(u64),
@ -88,10 +88,9 @@ impl StackmapEntry {
}); });
assert_eq!(self.value_semantics.len(), map_record.locations.len()); 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<MachineValue> = let mut machine_stack_half_layout: Vec<MachineValue> = Vec::new();
vec![MachineValue::Undefined; (size_record.stack_size as usize) / 8];
let mut regs: Vec<(RegisterIndex, MachineValue)> = vec![]; let mut regs: Vec<(RegisterIndex, MachineValue)> = vec![];
let mut stack_constants: HashMap<usize, u64> = HashMap::new(); let mut stack_constants: HashMap<usize, u64> = HashMap::new();
@ -145,30 +144,38 @@ impl StackmapEntry {
} }
LocationType::Direct => match mv { LocationType::Direct => match mv {
MachineValue::WasmLocal(_) => { MachineValue::WasmLocal(_) => {
assert_eq!(loc.location_size, 8); assert_eq!(loc.location_size, 8); // the pointer itself
assert!(loc.offset_or_small_constant < 0);
assert!( assert!(
X64Register::from_dwarf_regnum(loc.dwarf_regnum).unwrap() X64Register::from_dwarf_regnum(loc.dwarf_regnum).unwrap()
== X64Register::GPR(GPR::RBP) == X64Register::GPR(GPR::RBP)
); );
let stack_offset = ((-loc.offset_or_small_constant) % 8) as usize; if loc.offset_or_small_constant >= 0 {
assert!(stack_offset > 0 && stack_offset <= machine_stack_layout.len()); eprintln!("XXX: {}", loc.offset_or_small_constant);
machine_stack_layout[stack_offset - 1] = mv; }
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!( _ => unreachable!(
"Direct location type is not expected for values other than local" "Direct location type is not expected for values other than local"
), ),
}, },
LocationType::Indirect => { LocationType::Indirect => {
assert_eq!(loc.location_size, 8);
assert!(loc.offset_or_small_constant < 0); assert!(loc.offset_or_small_constant < 0);
assert!( assert!(
X64Register::from_dwarf_regnum(loc.dwarf_regnum).unwrap() X64Register::from_dwarf_regnum(loc.dwarf_regnum).unwrap()
== X64Register::GPR(GPR::RBP) == X64Register::GPR(GPR::RBP)
); );
let stack_offset = ((-loc.offset_or_small_constant) % 8) as usize; let stack_offset = ((-loc.offset_or_small_constant) / 4) as usize;
assert!(stack_offset > 0 && stack_offset <= machine_stack_layout.len()); while stack_offset > machine_stack_half_layout.len() {
machine_stack_layout[stack_offset - 1] = mv; 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_stack.len(), self.stack_count);
assert_eq!(wasm_locals.len(), self.local_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<MachineValue> = 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 { let diff = MachineStateDiff {
last: None, last: None,
stack_push: machine_stack_layout, stack_push: machine_stack_layout,

View File

@ -35,7 +35,7 @@ pub struct MachineStateDiff {
pub wasm_inst_offset: usize, // absolute value; not a diff. 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 { pub enum MachineValue {
Undefined, Undefined,
Vmctx, Vmctx,
@ -44,6 +44,7 @@ pub enum MachineValue {
ExplicitShadow, // indicates that all values above this are above the shadow region ExplicitShadow, // indicates that all values above this are above the shadow region
WasmStack(usize), WasmStack(usize),
WasmLocal(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)] #[derive(Clone, Debug)]
@ -203,7 +204,7 @@ impl MachineState {
.iter() .iter()
.zip(old.stack_values.iter()) .zip(old.stack_values.iter())
.enumerate() .enumerate()
.find(|&(_, (&a, &b))| a != b) .find(|&(_, (a, b))| a != b)
.map(|x| x.0) .map(|x| x.0)
.unwrap_or(old.stack_values.len().min(self.stack_values.len())); .unwrap_or(old.stack_values.len().min(self.stack_values.len()));
assert_eq!(self.register_values.len(), old.register_values.len()); assert_eq!(self.register_values.len(), old.register_values.len());
@ -212,15 +213,15 @@ impl MachineState {
.iter() .iter()
.zip(old.register_values.iter()) .zip(old.register_values.iter())
.enumerate() .enumerate()
.filter(|&(_, (&a, &b))| a != b) .filter(|&(_, (a, b))| a != b)
.map(|(i, (&a, _))| (RegisterIndex(i), a)) .map(|(i, (a, _))| (RegisterIndex(i), a.clone()))
.collect(); .collect();
let first_diff_wasm_stack_depth: usize = self let first_diff_wasm_stack_depth: usize = self
.wasm_stack .wasm_stack
.iter() .iter()
.zip(old.wasm_stack.iter()) .zip(old.wasm_stack.iter())
.enumerate() .enumerate()
.find(|&(_, (&a, &b))| a != b) .find(|&(_, (a, b))| a != b)
.map(|x| x.0) .map(|x| x.0)
.unwrap_or(old.wasm_stack.len().min(self.wasm_stack.len())); .unwrap_or(old.wasm_stack.len().min(self.wasm_stack.len()));
MachineStateDiff { MachineStateDiff {
@ -255,10 +256,10 @@ impl MachineStateDiff {
state.stack_values.pop().unwrap(); state.stack_values.pop().unwrap();
} }
for v in &x.stack_push { for v in &x.stack_push {
state.stack_values.push(*v); state.stack_values.push(v.clone());
} }
for &(index, v) in &x.reg_diff { for &(index, ref v) in &x.reg_diff {
state.register_values[index.0] = v; state.register_values[index.0] = v.clone();
} }
for _ in 0..x.wasm_stack_pop { for _ in 0..x.wasm_stack_pop {
state.wasm_stack.pop().unwrap(); 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 { if !got_explicit_shadow {
@ -785,6 +852,30 @@ pub mod x64 {
wasm_locals[idx] = Some(*stack); wasm_locals[idx] = Some(*stack);
stack = stack.offset(1); 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 stack = stack.offset(1); // RBP