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.
|
/// 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]
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user