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>,
|
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.
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue