Merge {make_incoming,get_outgoing}_{,struct_}arg
This commit is contained in:
@@ -286,12 +286,7 @@ impl StackSlots {
|
||||
}
|
||||
|
||||
/// Create a stack slot representing an incoming function argument.
|
||||
pub fn make_incoming_arg(&mut self, ty: Type, offset: StackOffset) -> StackSlot {
|
||||
self.make_incoming_struct_arg(ty.bytes(), offset)
|
||||
}
|
||||
|
||||
/// Create a stack slot representing an incoming struct function argument.
|
||||
pub fn make_incoming_struct_arg(&mut self, size: u32, offset: StackOffset) -> StackSlot {
|
||||
pub fn make_incoming_arg(&mut self, size: u32, offset: StackOffset) -> StackSlot {
|
||||
let mut data = StackSlotData::new(StackSlotKind::IncomingArg, size);
|
||||
debug_assert!(offset <= StackOffset::max_value() - data.size as StackOffset);
|
||||
data.offset = Some(offset);
|
||||
@@ -305,12 +300,7 @@ impl StackSlots {
|
||||
///
|
||||
/// The requested offset is relative to this function's stack pointer immediately before making
|
||||
/// the call.
|
||||
pub fn get_outgoing_arg(&mut self, ty: Type, offset: StackOffset) -> StackSlot {
|
||||
self.get_outgoing_struct_arg(ty.bytes(), offset)
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
pub fn get_outgoing_struct_arg(&mut self, size: u32, offset: StackOffset) -> StackSlot {
|
||||
pub fn get_outgoing_arg(&mut self, size: u32, offset: StackOffset) -> StackSlot {
|
||||
// Look for an existing outgoing stack slot with the same offset and size.
|
||||
let inspos = match self.outgoing.binary_search_by_key(&(offset, size), |&ss| {
|
||||
(self[ss].offset.unwrap(), self[ss].size)
|
||||
@@ -395,9 +385,9 @@ mod tests {
|
||||
fn outgoing() {
|
||||
let mut sss = StackSlots::new();
|
||||
|
||||
let ss0 = sss.get_outgoing_arg(types::I32, 8);
|
||||
let ss1 = sss.get_outgoing_arg(types::I32, 4);
|
||||
let ss2 = sss.get_outgoing_arg(types::I64, 8);
|
||||
let ss0 = sss.get_outgoing_arg(4, 8);
|
||||
let ss1 = sss.get_outgoing_arg(4, 4);
|
||||
let ss2 = sss.get_outgoing_arg(8, 8);
|
||||
|
||||
assert_eq!(sss[ss0].offset, Some(8));
|
||||
assert_eq!(sss[ss0].size, 4);
|
||||
@@ -408,9 +398,9 @@ mod tests {
|
||||
assert_eq!(sss[ss2].offset, Some(8));
|
||||
assert_eq!(sss[ss2].size, 8);
|
||||
|
||||
assert_eq!(sss.get_outgoing_arg(types::I32, 8), ss0);
|
||||
assert_eq!(sss.get_outgoing_arg(types::I32, 4), ss1);
|
||||
assert_eq!(sss.get_outgoing_arg(types::I64, 8), ss2);
|
||||
assert_eq!(sss.get_outgoing_arg(4, 8), ss0);
|
||||
assert_eq!(sss.get_outgoing_arg(4, 4), ss1);
|
||||
assert_eq!(sss.get_outgoing_arg(8, 8), ss2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -121,7 +121,7 @@ fn legalize_entry_params(func: &mut Function, entry: Block) {
|
||||
} else {
|
||||
unreachable!("StructArgument must already have a Stack ArgumentLoc assigned");
|
||||
};
|
||||
let ss = pos.func.stack_slots.make_incoming_struct_arg(size, offset);
|
||||
let ss = pos.func.stack_slots.make_incoming_arg(size, offset);
|
||||
let struct_arg = pos.ins().stack_addr(arg_type, ss, 0);
|
||||
pos.func.dfg.change_to_alias(arg, struct_arg);
|
||||
let dummy = pos
|
||||
@@ -1024,7 +1024,9 @@ fn spill_entry_params(func: &mut Function, entry: Block) {
|
||||
{
|
||||
if let ArgumentPurpose::StructArgument(_) = abi.purpose {
|
||||
} else if let ArgumentLoc::Stack(offset) = abi.location {
|
||||
let ss = func.stack_slots.make_incoming_arg(abi.value_type, offset);
|
||||
let ss = func
|
||||
.stack_slots
|
||||
.make_incoming_arg(abi.value_type.bytes(), offset);
|
||||
func.locations[arg] = ValueLoc::Stack(ss);
|
||||
}
|
||||
}
|
||||
@@ -1066,11 +1068,13 @@ fn spill_call_arguments(pos: &mut FuncCursor, isa: &dyn TargetIsa) -> bool {
|
||||
// slot. The legalization needs to be idempotent, so we should see a
|
||||
// correct outgoing slot on the second pass.
|
||||
let (ss, size) = match abi.purpose {
|
||||
ArgumentPurpose::StructArgument(size) => (
|
||||
stack_slots.get_outgoing_struct_arg(size, offset),
|
||||
Some(size),
|
||||
ArgumentPurpose::StructArgument(size) => {
|
||||
(stack_slots.get_outgoing_arg(size, offset), Some(size))
|
||||
}
|
||||
_ => (
|
||||
stack_slots.get_outgoing_arg(abi.value_type.bytes(), offset),
|
||||
None,
|
||||
),
|
||||
_ => (stack_slots.get_outgoing_arg(abi.value_type, offset), None),
|
||||
};
|
||||
if locations[arg] != ValueLoc::Stack(ss) {
|
||||
Some((idx, arg, ss, size))
|
||||
|
||||
@@ -152,8 +152,8 @@ mod tests {
|
||||
assert_eq!(layout_stack(sss, is_leaf, 16), Ok(0));
|
||||
|
||||
// Same for incoming arguments with non-negative offsets.
|
||||
let in0 = sss.make_incoming_arg(types::I64, 0);
|
||||
let in1 = sss.make_incoming_arg(types::I64, 8);
|
||||
let in0 = sss.make_incoming_arg(8, 0);
|
||||
let in1 = sss.make_incoming_arg(8, 8);
|
||||
|
||||
assert_eq!(layout_stack(sss, is_leaf, 1), Ok(0));
|
||||
assert_eq!(layout_stack(sss, is_leaf, 16), Ok(0));
|
||||
@@ -178,7 +178,7 @@ mod tests {
|
||||
|
||||
// An incoming argument with negative offset counts towards the total frame size, but it
|
||||
// should still pack nicely with the spill slots.
|
||||
let in2 = sss.make_incoming_arg(types::I32, -4);
|
||||
let in2 = sss.make_incoming_arg(4, -4);
|
||||
|
||||
assert_eq!(layout_stack(sss, is_leaf, 1), Ok(16));
|
||||
assert_eq!(sss[in0].offset, Some(0));
|
||||
@@ -195,7 +195,7 @@ mod tests {
|
||||
assert_eq!(sss[ss1].offset, Some(-8));
|
||||
|
||||
// Finally, make sure there is room for the outgoing args.
|
||||
let out0 = sss.get_outgoing_arg(types::I32, 0);
|
||||
let out0 = sss.get_outgoing_arg(4, 0);
|
||||
|
||||
assert_eq!(layout_stack(sss, is_leaf, 1), Ok(20));
|
||||
assert_eq!(sss[in0].offset, Some(0));
|
||||
@@ -214,7 +214,7 @@ mod tests {
|
||||
assert_eq!(sss[out0].offset, Some(0));
|
||||
|
||||
// Also test that an unsupported offset is rejected.
|
||||
sss.get_outgoing_arg(types::I8, StackOffset::max_value() - 1);
|
||||
sss.get_outgoing_arg(1, StackOffset::max_value() - 1);
|
||||
assert_eq!(
|
||||
layout_stack(sss, is_leaf, 1),
|
||||
Err(CodegenError::ImplLimitExceeded)
|
||||
|
||||
Reference in New Issue
Block a user