fix join point param loading

This commit is contained in:
Brendan Hansknecht 2022-02-18 14:59:51 -08:00
parent 1f8ac3e150
commit 37afe28c98
3 changed files with 35 additions and 32 deletions

View file

@ -657,15 +657,17 @@ impl<
remainder: &'a Stmt<'a>, remainder: &'a Stmt<'a>,
ret_layout: &Layout<'a>, ret_layout: &Layout<'a>,
) { ) {
// Ensure all the joinpoint parameters have storage locations.
// On jumps to the joinpoint, we will overwrite those locations as a way to "pass parameters" to the joinpoint.
self.storage_manager
.setup_joinpoint(&mut self.buf, id, parameters);
// Create jump to remaining. // Create jump to remaining.
let jmp_location = self.buf.len(); let jmp_location = self.buf.len();
let start_offset = ASM::jmp_imm32(&mut self.buf, 0x1234_5678); let start_offset = ASM::jmp_imm32(&mut self.buf, 0x1234_5678);
// Ensure all the joinpoint parameters are loaded in only one location.
// On jumps to the joinpoint, we will overwrite those locations as a way to "pass parameters" to the joinpoint.
self.storage_manager.setup_joinpoint(id, parameters);
// Build all statements in body. // Build all statements in body.
self.join_map.insert(*id, self.buf.len() as u64);
self.build_stmt(body, ret_layout); self.build_stmt(body, ret_layout);
// Overwrite the original jump with the correct offset. // Overwrite the original jump with the correct offset.

View file

@ -764,17 +764,22 @@ impl<
self.fn_call_stack_size = max(self.fn_call_stack_size, tmp_size); self.fn_call_stack_size = max(self.fn_call_stack_size, tmp_size);
} }
/// Setups a join piont. /// Setups a join point.
/// To do this, each of the join pionts params are loaded into a single location (either stack or reg). /// To do this, each of the join pionts params are given a storage location.
/// Then those locations are stored. /// Then those locations are stored.
/// Later jumps to the join point can overwrite the stored locations to pass parameters. /// Later jumps to the join point can overwrite the stored locations to pass parameters.
pub fn setup_joinpoint(&mut self, id: &JoinPointId, params: &'a [Param<'a>]) { pub fn setup_joinpoint(
&mut self,
buf: &mut Vec<'a, u8>,
id: &JoinPointId,
params: &'a [Param<'a>],
) {
let mut param_storage = bumpalo::vec![in self.env.arena]; let mut param_storage = bumpalo::vec![in self.env.arena];
param_storage.reserve(params.len()); param_storage.reserve(params.len());
for Param { for Param {
symbol, symbol,
borrow, borrow,
layout: _, layout,
} in params } in params
{ {
if *borrow { if *borrow {
@ -782,25 +787,21 @@ impl<
// Otherwise, we probably need to copy back to the param at the end of the joinpoint. // Otherwise, we probably need to copy back to the param at the end of the joinpoint.
todo!("joinpoints with borrowed parameters"); todo!("joinpoints with borrowed parameters");
} }
// move to single location. // Claim a location for every join point parameter to be loaded at.
// TODO: this may be wrong, params may be a list of new symbols. match layout {
// In that case, this should be claiming storage for each symbol. single_register_integers!() => {
match self.remove_storage_for_sym(symbol) { self.claim_general_reg(buf, symbol);
// Only values that might be in 2 locations are primitives.
// They can be in a reg and on the stack.
Stack(Primitive {
reg: Some(reg),
base_offset,
}) => {
// Only care about the value in the register and reload to that.
// free the associated stack space.
self.free_stack_chunk(base_offset, 8);
self.symbol_storage_map.insert(*symbol, Reg(reg));
param_storage.push(Reg(reg));
} }
storage => { single_register_floats!() => {
self.symbol_storage_map.insert(*symbol, storage); self.claim_float_reg(buf, symbol);
param_storage.push(storage); }
_ => {
let stack_size = layout.stack_size(self.target_info);
if stack_size == 0 {
self.symbol_storage_map.insert(*symbol, NoData);
} else {
self.claim_stack_area(symbol, stack_size);
}
} }
} }
} }

View file

@ -243,7 +243,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
todo!("loading lists and strings args on the stack"); todo!("loading lists and strings args on the stack");
} }
} }
Layout::Struct(&[]) => {} x if x.stack_size(TARGET_INFO) == 0 => {}
x => { x => {
todo!("Loading args with layout {:?}", x); todo!("Loading args with layout {:?}", x);
} }
@ -341,7 +341,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
todo!("calling functions with strings on the stack"); todo!("calling functions with strings on the stack");
} }
} }
Layout::Struct(&[]) => {} x if x.stack_size(TARGET_INFO) == 0 => {}
x => { x => {
todo!("calling with arg type, {:?}", x); todo!("calling with arg type, {:?}", x);
} }
@ -366,7 +366,6 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
single_register_layouts!() => { single_register_layouts!() => {
internal_error!("single register layouts are not complex symbols"); internal_error!("single register layouts are not complex symbols");
} }
Layout::Struct([]) => {}
Layout::Builtin(Builtin::Str | Builtin::List(_)) => { Layout::Builtin(Builtin::Str | Builtin::List(_)) => {
let (base_offset, _size) = storage_manager.stack_offset_and_size(sym); let (base_offset, _size) = storage_manager.stack_offset_and_size(sym);
debug_assert_eq!(base_offset % 8, 0); debug_assert_eq!(base_offset % 8, 0);
@ -377,6 +376,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
base_offset + 8, base_offset + 8,
); );
} }
x if x.stack_size(TARGET_INFO) == 0 => {}
x => todo!("returning complex type, {:?}", x), x => todo!("returning complex type, {:?}", x),
} }
} }
@ -397,12 +397,12 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
single_register_layouts!() => { single_register_layouts!() => {
internal_error!("single register layouts are not complex symbols"); internal_error!("single register layouts are not complex symbols");
} }
Layout::Struct([]) => {}
Layout::Builtin(Builtin::Str | Builtin::List(_)) => { Layout::Builtin(Builtin::Str | Builtin::List(_)) => {
let offset = storage_manager.claim_stack_area(sym, 16); let offset = storage_manager.claim_stack_area(sym, 16);
X86_64Assembler::mov_base32_reg64(buf, offset, Self::GENERAL_RETURN_REGS[0]); X86_64Assembler::mov_base32_reg64(buf, offset, Self::GENERAL_RETURN_REGS[0]);
X86_64Assembler::mov_base32_reg64(buf, offset + 8, Self::GENERAL_RETURN_REGS[1]); X86_64Assembler::mov_base32_reg64(buf, offset + 8, Self::GENERAL_RETURN_REGS[1]);
} }
x if x.stack_size(TARGET_INFO) == 0 => {}
x => todo!("receiving complex return type, {:?}", x), x => todo!("receiving complex return type, {:?}", x),
} }
} }
@ -565,7 +565,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
// I think this just needs to be passed on the stack, so not a huge deal. // I think this just needs to be passed on the stack, so not a huge deal.
todo!("Passing str args with Windows fast call"); todo!("Passing str args with Windows fast call");
} }
Layout::Struct(&[]) => {} x if x.stack_size(TARGET_INFO) == 0 => {}
x => { x => {
todo!("Loading args with layout {:?}", x); todo!("Loading args with layout {:?}", x);
} }
@ -655,7 +655,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
// I think this just needs to be passed on the stack, so not a huge deal. // I think this just needs to be passed on the stack, so not a huge deal.
todo!("Passing str args with Windows fast call"); todo!("Passing str args with Windows fast call");
} }
Layout::Struct(&[]) => {} x if x.stack_size(TARGET_INFO) == 0 => {}
x => { x => {
todo!("calling with arg type, {:?}", x); todo!("calling with arg type, {:?}", x);
} }