Add an offset to StackSlotData.
The offset is relative to the stack pointer in the calling function, so it excludes the return address pushed by the call instruction itself on Intel ISAs. Change the ArgumentLoc::Stack offset to an i32, so it matches the stack slot offsets.
This commit is contained in:
@@ -51,8 +51,8 @@ impl Signature {
|
||||
let bytes = self.argument_types
|
||||
.iter()
|
||||
.filter_map(|arg| match arg.location {
|
||||
ArgumentLoc::Stack(offset) => {
|
||||
Some(offset + arg.value_type.bits() as u32 / 8)
|
||||
ArgumentLoc::Stack(offset) if offset > 0 => {
|
||||
Some(offset as u32 + arg.value_type.bytes())
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
|
||||
@@ -69,18 +69,33 @@ pub struct StackSlotData {
|
||||
|
||||
/// Size of stack slot in bytes.
|
||||
pub size: u32,
|
||||
|
||||
/// Offset of stack slot relative to the stack pointer in the caller.
|
||||
///
|
||||
/// On Intel ISAs, the base address is the stack pointer *before* the return address was
|
||||
/// pushed. On RISC ISAs, the base address is the value of the stack pointer on entry to the
|
||||
/// function.
|
||||
pub offset: i32,
|
||||
}
|
||||
|
||||
impl StackSlotData {
|
||||
/// Create a stack slot with the specified byte size.
|
||||
pub fn new(kind: StackSlotKind, size: u32) -> StackSlotData {
|
||||
StackSlotData { kind, size }
|
||||
StackSlotData {
|
||||
kind,
|
||||
size,
|
||||
offset: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for StackSlotData {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{} {}", self.kind, self.size)
|
||||
write!(f, "{} {}", self.kind, self.size)?;
|
||||
if self.offset != 0 {
|
||||
write!(f, ", offset {}", self.offset)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,8 +151,15 @@ impl StackSlots {
|
||||
impl StackSlots {
|
||||
/// Create a new spill slot for spilling values of type `ty`.
|
||||
pub fn make_spill_slot(&mut self, ty: Type) -> StackSlot {
|
||||
let bytes = (ty.bits() as u32 + 7) / 8;
|
||||
self.push(StackSlotData::new(StackSlotKind::SpillSlot, bytes))
|
||||
self.push(StackSlotData::new(StackSlotKind::SpillSlot, ty.bytes()))
|
||||
}
|
||||
|
||||
/// Create a stack slot representing an incoming function argument.
|
||||
pub fn make_incoming_arg(&mut self, ty: Type, offset: u32) -> StackSlot {
|
||||
let mut data = StackSlotData::new(StackSlotKind::IncomingArg, ty.bytes());
|
||||
assert!(offset <= i32::max_value() as u32 - data.size);
|
||||
data.offset = offset as i32;
|
||||
self.push(data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -197,6 +197,11 @@ impl Type {
|
||||
self.lane_bits() as u16 * self.lane_count()
|
||||
}
|
||||
|
||||
/// Get the number of bytes used to store this type in memory.
|
||||
pub fn bytes(self) -> u32 {
|
||||
(self.bits() as u32 + 7) / 8
|
||||
}
|
||||
|
||||
/// Get a SIMD vector type with `n` times more lanes than this one.
|
||||
///
|
||||
/// If this is a scalar type, this produces a SIMD type with this as a lane type and `n` lanes.
|
||||
|
||||
@@ -86,7 +86,7 @@ pub enum ArgumentLoc {
|
||||
/// Argument is passed in a register.
|
||||
Reg(RegUnit),
|
||||
/// Argument is passed on the stack, at the given byte offset into the argument array.
|
||||
Stack(u32),
|
||||
Stack(i32),
|
||||
}
|
||||
|
||||
impl Default for ArgumentLoc {
|
||||
|
||||
@@ -77,8 +77,9 @@ impl ArgAssigner for Args {
|
||||
ArgumentLoc::Reg(reg).into()
|
||||
} else {
|
||||
// Assign a stack location.
|
||||
let loc = ArgumentLoc::Stack(self.offset);
|
||||
let loc = ArgumentLoc::Stack(self.offset as i32);
|
||||
self.offset += self.pointer_bytes;
|
||||
assert!(self.offset <= i32::max_value() as u32);
|
||||
loc.into()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user