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>,
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.
let jmp_location = self.buf.len();
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.
self.join_map.insert(*id, self.buf.len() as u64);
self.build_stmt(body, ret_layout);
// 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);
}
/// Setups a join piont.
/// To do this, each of the join pionts params are loaded into a single location (either stack or reg).
/// Setups a join point.
/// To do this, each of the join pionts params are given a storage location.
/// Then those locations are stored.
/// 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];
param_storage.reserve(params.len());
for Param {
symbol,
borrow,
layout: _,
layout,
} in params
{
if *borrow {
@ -782,25 +787,21 @@ impl<
// Otherwise, we probably need to copy back to the param at the end of the joinpoint.
todo!("joinpoints with borrowed parameters");
}
// move to single location.
// TODO: this may be wrong, params may be a list of new symbols.
// In that case, this should be claiming storage for each symbol.
match self.remove_storage_for_sym(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));
// Claim a location for every join point parameter to be loaded at.
match layout {
single_register_integers!() => {
self.claim_general_reg(buf, symbol);
}
storage => {
self.symbol_storage_map.insert(*symbol, storage);
param_storage.push(storage);
single_register_floats!() => {
self.claim_float_reg(buf, symbol);
}
_ => {
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");
}
}
Layout::Struct(&[]) => {}
x if x.stack_size(TARGET_INFO) == 0 => {}
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");
}
}
Layout::Struct(&[]) => {}
x if x.stack_size(TARGET_INFO) == 0 => {}
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!() => {
internal_error!("single register layouts are not complex symbols");
}
Layout::Struct([]) => {}
Layout::Builtin(Builtin::Str | Builtin::List(_)) => {
let (base_offset, _size) = storage_manager.stack_offset_and_size(sym);
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,
);
}
x if x.stack_size(TARGET_INFO) == 0 => {}
x => todo!("returning complex type, {:?}", x),
}
}
@ -397,12 +397,12 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
single_register_layouts!() => {
internal_error!("single register layouts are not complex symbols");
}
Layout::Struct([]) => {}
Layout::Builtin(Builtin::Str | Builtin::List(_)) => {
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 + 8, Self::GENERAL_RETURN_REGS[1]);
}
x if x.stack_size(TARGET_INFO) == 0 => {}
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.
todo!("Passing str args with Windows fast call");
}
Layout::Struct(&[]) => {}
x if x.stack_size(TARGET_INFO) == 0 => {}
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.
todo!("Passing str args with Windows fast call");
}
Layout::Struct(&[]) => {}
x if x.stack_size(TARGET_INFO) == 0 => {}
x => {
todo!("calling with arg type, {:?}", x);
}