mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
fix join point param loading
This commit is contained in:
parent
1f8ac3e150
commit
37afe28c98
3 changed files with 35 additions and 32 deletions
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue