Merge {make_incoming,get_outgoing}_{,struct_}arg

This commit is contained in:
bjorn3
2020-07-15 19:20:50 +02:00
committed by Benjamin Bouvier
parent 0d4fa6d32a
commit 4971d9ee80
3 changed files with 23 additions and 29 deletions

View File

@@ -286,12 +286,7 @@ impl StackSlots {
} }
/// Create a stack slot representing an incoming function argument. /// Create a stack slot representing an incoming function argument.
pub fn make_incoming_arg(&mut self, ty: Type, offset: StackOffset) -> StackSlot { pub fn make_incoming_arg(&mut self, size: u32, 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 {
let mut data = StackSlotData::new(StackSlotKind::IncomingArg, size); let mut data = StackSlotData::new(StackSlotKind::IncomingArg, size);
debug_assert!(offset <= StackOffset::max_value() - data.size as StackOffset); debug_assert!(offset <= StackOffset::max_value() - data.size as StackOffset);
data.offset = Some(offset); 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 requested offset is relative to this function's stack pointer immediately before making
/// the call. /// the call.
pub fn get_outgoing_arg(&mut self, ty: Type, offset: StackOffset) -> StackSlot { pub fn get_outgoing_arg(&mut self, size: u32, 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 {
// Look for an existing outgoing stack slot with the same offset and size. // 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| { let inspos = match self.outgoing.binary_search_by_key(&(offset, size), |&ss| {
(self[ss].offset.unwrap(), self[ss].size) (self[ss].offset.unwrap(), self[ss].size)
@@ -395,9 +385,9 @@ mod tests {
fn outgoing() { fn outgoing() {
let mut sss = StackSlots::new(); let mut sss = StackSlots::new();
let ss0 = sss.get_outgoing_arg(types::I32, 8); let ss0 = sss.get_outgoing_arg(4, 8);
let ss1 = sss.get_outgoing_arg(types::I32, 4); let ss1 = sss.get_outgoing_arg(4, 4);
let ss2 = sss.get_outgoing_arg(types::I64, 8); let ss2 = sss.get_outgoing_arg(8, 8);
assert_eq!(sss[ss0].offset, Some(8)); assert_eq!(sss[ss0].offset, Some(8));
assert_eq!(sss[ss0].size, 4); assert_eq!(sss[ss0].size, 4);
@@ -408,9 +398,9 @@ mod tests {
assert_eq!(sss[ss2].offset, Some(8)); assert_eq!(sss[ss2].offset, Some(8));
assert_eq!(sss[ss2].size, 8); assert_eq!(sss[ss2].size, 8);
assert_eq!(sss.get_outgoing_arg(types::I32, 8), ss0); assert_eq!(sss.get_outgoing_arg(4, 8), ss0);
assert_eq!(sss.get_outgoing_arg(types::I32, 4), ss1); assert_eq!(sss.get_outgoing_arg(4, 4), ss1);
assert_eq!(sss.get_outgoing_arg(types::I64, 8), ss2); assert_eq!(sss.get_outgoing_arg(8, 8), ss2);
} }
#[test] #[test]

View File

@@ -121,7 +121,7 @@ fn legalize_entry_params(func: &mut Function, entry: Block) {
} else { } else {
unreachable!("StructArgument must already have a Stack ArgumentLoc assigned"); 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); let struct_arg = pos.ins().stack_addr(arg_type, ss, 0);
pos.func.dfg.change_to_alias(arg, struct_arg); pos.func.dfg.change_to_alias(arg, struct_arg);
let dummy = pos let dummy = pos
@@ -1024,7 +1024,9 @@ fn spill_entry_params(func: &mut Function, entry: Block) {
{ {
if let ArgumentPurpose::StructArgument(_) = abi.purpose { if let ArgumentPurpose::StructArgument(_) = abi.purpose {
} else if let ArgumentLoc::Stack(offset) = abi.location { } 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); 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 // slot. The legalization needs to be idempotent, so we should see a
// correct outgoing slot on the second pass. // correct outgoing slot on the second pass.
let (ss, size) = match abi.purpose { let (ss, size) = match abi.purpose {
ArgumentPurpose::StructArgument(size) => ( ArgumentPurpose::StructArgument(size) => {
stack_slots.get_outgoing_struct_arg(size, offset), (stack_slots.get_outgoing_arg(size, offset), Some(size))
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) { if locations[arg] != ValueLoc::Stack(ss) {
Some((idx, arg, ss, size)) Some((idx, arg, ss, size))

View File

@@ -152,8 +152,8 @@ mod tests {
assert_eq!(layout_stack(sss, is_leaf, 16), Ok(0)); assert_eq!(layout_stack(sss, is_leaf, 16), Ok(0));
// Same for incoming arguments with non-negative offsets. // Same for incoming arguments with non-negative offsets.
let in0 = sss.make_incoming_arg(types::I64, 0); let in0 = sss.make_incoming_arg(8, 0);
let in1 = sss.make_incoming_arg(types::I64, 8); 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, 1), Ok(0));
assert_eq!(layout_stack(sss, is_leaf, 16), 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 // An incoming argument with negative offset counts towards the total frame size, but it
// should still pack nicely with the spill slots. // 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!(layout_stack(sss, is_leaf, 1), Ok(16));
assert_eq!(sss[in0].offset, Some(0)); assert_eq!(sss[in0].offset, Some(0));
@@ -195,7 +195,7 @@ mod tests {
assert_eq!(sss[ss1].offset, Some(-8)); assert_eq!(sss[ss1].offset, Some(-8));
// Finally, make sure there is room for the outgoing args. // 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!(layout_stack(sss, is_leaf, 1), Ok(20));
assert_eq!(sss[in0].offset, Some(0)); assert_eq!(sss[in0].offset, Some(0));
@@ -214,7 +214,7 @@ mod tests {
assert_eq!(sss[out0].offset, Some(0)); assert_eq!(sss[out0].offset, Some(0));
// Also test that an unsupported offset is rejected. // 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!( assert_eq!(
layout_stack(sss, is_leaf, 1), layout_stack(sss, is_leaf, 1),
Err(CodegenError::ImplLimitExceeded) Err(CodegenError::ImplLimitExceeded)