Include emergency stack slots when laying out the stack.
Emergency stack slots are a new kind of stack slot added relatively recently. They need to be allocated a stack offset just like explicit and spill slots. Also, make StackSlotData's offset field an Option, to catch problems like this in the future. Previously the value 0 was used when offsets weren't assigned yet, however that made it non-obvious when the field meant "not assigned yet" and when it meant "assigned the value 0".
This commit is contained in:
@@ -111,7 +111,7 @@ pub struct StackSlotData {
|
||||
///
|
||||
/// For `OutgoingArg` stack slots, the offset is relative to the current function's stack
|
||||
/// pointer immediately before the call.
|
||||
pub offset: StackOffset,
|
||||
pub offset: Option<StackOffset>,
|
||||
}
|
||||
|
||||
impl StackSlotData {
|
||||
@@ -120,7 +120,7 @@ impl StackSlotData {
|
||||
StackSlotData {
|
||||
kind,
|
||||
size,
|
||||
offset: 0,
|
||||
offset: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,8 +138,8 @@ impl StackSlotData {
|
||||
impl fmt::Display for StackSlotData {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{} {}", self.kind, self.size)?;
|
||||
if self.offset != 0 {
|
||||
write!(f, ", offset {}", self.offset)?;
|
||||
if let Some(offset) = self.offset {
|
||||
write!(f, ", offset {}", offset)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -204,7 +204,7 @@ impl StackSlots {
|
||||
|
||||
/// Set the offset of a stack slot.
|
||||
pub fn set_offset(&mut self, ss: StackSlot, offset: StackOffset) {
|
||||
self.slots[ss].offset = offset;
|
||||
self.slots[ss].offset = Some(offset);
|
||||
}
|
||||
|
||||
/// Get an iterator over all the stack slot keys.
|
||||
@@ -245,7 +245,7 @@ impl StackSlots {
|
||||
pub fn make_incoming_arg(&mut self, ty: Type, offset: StackOffset) -> StackSlot {
|
||||
let mut data = StackSlotData::new(StackSlotKind::IncomingArg, ty.bytes());
|
||||
assert!(offset <= StackOffset::max_value() - data.size as StackOffset);
|
||||
data.offset = offset;
|
||||
data.offset = Some(offset);
|
||||
self.push(data)
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ impl StackSlots {
|
||||
|
||||
// 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, self[ss].size)
|
||||
(self[ss].offset.unwrap(), self[ss].size)
|
||||
}) {
|
||||
Ok(idx) => return self.outgoing[idx],
|
||||
Err(idx) => idx,
|
||||
@@ -270,7 +270,7 @@ impl StackSlots {
|
||||
// No existing slot found. Make one and insert it into `outgoing`.
|
||||
let mut data = StackSlotData::new(StackSlotKind::OutgoingArg, size);
|
||||
assert!(offset <= StackOffset::max_value() - size as StackOffset);
|
||||
data.offset = offset;
|
||||
data.offset = Some(offset);
|
||||
let ss = self.slots.push(data);
|
||||
self.outgoing.insert(inspos, ss);
|
||||
ss
|
||||
@@ -344,13 +344,13 @@ mod tests {
|
||||
let ss1 = sss.get_outgoing_arg(types::I32, 4);
|
||||
let ss2 = sss.get_outgoing_arg(types::I64, 8);
|
||||
|
||||
assert_eq!(sss[ss0].offset, 8);
|
||||
assert_eq!(sss[ss0].offset, Some(8));
|
||||
assert_eq!(sss[ss0].size, 4);
|
||||
|
||||
assert_eq!(sss[ss1].offset, 4);
|
||||
assert_eq!(sss[ss1].offset, Some(4));
|
||||
assert_eq!(sss[ss1].size, 4);
|
||||
|
||||
assert_eq!(sss[ss2].offset, 8);
|
||||
assert_eq!(sss[ss2].offset, Some(8));
|
||||
assert_eq!(sss[ss2].size, 8);
|
||||
|
||||
assert_eq!(sss.get_outgoing_arg(types::I32, 8), ss0);
|
||||
|
||||
Reference in New Issue
Block a user