Track stack slot kinds.
Add a StackSlotKind enumeration to help keep track of the different kinds of stack slots supported: - Incoming and outgoing function arguments on the stack. - Spill slots and locals. Change the text format syntax for declaring a stack slot to use a kind keyword rather than just 'stack_slot'.
This commit is contained in:
@@ -22,7 +22,7 @@ pub use ir::extfunc::{Signature, ArgumentType, ArgumentExtension, ArgumentPurpos
|
||||
pub use ir::types::Type;
|
||||
pub use ir::entities::{Ebb, Inst, Value, StackSlot, JumpTable, FuncRef, SigRef};
|
||||
pub use ir::instructions::{Opcode, InstructionData, VariableArgs, ValueList, ValueListPool};
|
||||
pub use ir::stackslot::StackSlotData;
|
||||
pub use ir::stackslot::{StackSlotKind, StackSlotData};
|
||||
pub use ir::jumptable::JumpTableData;
|
||||
pub use ir::valueloc::{ValueLoc, ArgumentLoc};
|
||||
pub use ir::dfg::{DataFlowGraph, ValueDef};
|
||||
|
||||
@@ -3,43 +3,104 @@
|
||||
//! The `StackSlotData` struct keeps track of a single stack slot in a function.
|
||||
//!
|
||||
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
/// The kind of a stack slot.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum StackSlotKind {
|
||||
/// A spill slot. This is a stack slot created by the register allocator.
|
||||
SpillSlot,
|
||||
|
||||
/// A local variable. This is a chunk of local stack memory for use by the `stack_load` and
|
||||
/// `stack_store` instructions.
|
||||
Local,
|
||||
|
||||
/// An incoming function argument.
|
||||
///
|
||||
/// If the current function has more arguments than fits in registers, the remaining arguments
|
||||
/// are passed on the stack by the caller. These incoming arguments are represented as SSA
|
||||
/// values assigned to incoming stack slots.
|
||||
IncomingArg,
|
||||
|
||||
/// An outgoing function argument.
|
||||
///
|
||||
/// When preparing to call a function whose arguments don't fit in registers, outgoing argument
|
||||
/// stack slots are used to represent individual arguments in the outgoing call frame. These
|
||||
/// stack slots are only valid while setting up a call.
|
||||
OutgoingArg,
|
||||
}
|
||||
|
||||
impl FromStr for StackSlotKind {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<StackSlotKind, ()> {
|
||||
use self::StackSlotKind::*;
|
||||
match s {
|
||||
"local" => Ok(Local),
|
||||
"spill_slot" => Ok(SpillSlot),
|
||||
"incoming_arg" => Ok(IncomingArg),
|
||||
"outgoing_arg" => Ok(OutgoingArg),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for StackSlotKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use self::StackSlotKind::*;
|
||||
f.write_str(match *self {
|
||||
Local => "local",
|
||||
SpillSlot => "spill_slot",
|
||||
IncomingArg => "incoming_arg",
|
||||
OutgoingArg => "outgoing_arg",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Contents of a stack slot.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct StackSlotData {
|
||||
/// The kind of stack slot.
|
||||
pub kind: StackSlotKind,
|
||||
|
||||
/// Size of stack slot in bytes.
|
||||
pub size: u32,
|
||||
}
|
||||
|
||||
impl StackSlotData {
|
||||
/// Create a stack slot with the specified byte size.
|
||||
pub fn new(size: u32) -> StackSlotData {
|
||||
StackSlotData { size: size }
|
||||
pub fn new(kind: StackSlotKind, size: u32) -> StackSlotData {
|
||||
StackSlotData { kind, size }
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for StackSlotData {
|
||||
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
||||
write!(fmt, "stack_slot {}", self.size)
|
||||
impl fmt::Display for StackSlotData {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{} {}", self.kind, self.size)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ir::Function;
|
||||
use super::StackSlotData;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn stack_slot() {
|
||||
let mut func = Function::new();
|
||||
|
||||
let ss0 = func.stack_slots.push(StackSlotData::new(4));
|
||||
let ss1 = func.stack_slots.push(StackSlotData::new(8));
|
||||
let ss0 = func.stack_slots
|
||||
.push(StackSlotData::new(StackSlotKind::IncomingArg, 4));
|
||||
let ss1 = func.stack_slots
|
||||
.push(StackSlotData::new(StackSlotKind::SpillSlot, 8));
|
||||
assert_eq!(ss0.to_string(), "ss0");
|
||||
assert_eq!(ss1.to_string(), "ss1");
|
||||
|
||||
assert_eq!(func.stack_slots[ss0].size, 4);
|
||||
assert_eq!(func.stack_slots[ss1].size, 8);
|
||||
|
||||
assert_eq!(func.stack_slots[ss0].to_string(), "incoming_arg 4");
|
||||
assert_eq!(func.stack_slots[ss1].to_string(), "spill_slot 8");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,7 +359,7 @@ impl<'a> fmt::Display for DisplayValues<'a> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ir::{Function, FunctionName, StackSlotData};
|
||||
use ir::{Function, FunctionName, StackSlotData, StackSlotKind};
|
||||
use ir::types;
|
||||
|
||||
#[test]
|
||||
@@ -370,21 +370,21 @@ mod tests {
|
||||
f.name = FunctionName::new("foo");
|
||||
assert_eq!(f.to_string(), "function %foo() {\n}\n");
|
||||
|
||||
f.stack_slots.push(StackSlotData::new(4));
|
||||
assert_eq!(f.to_string(),
|
||||
"function %foo() {\n ss0 = stack_slot 4\n}\n");
|
||||
f.stack_slots
|
||||
.push(StackSlotData::new(StackSlotKind::Local, 4));
|
||||
assert_eq!(f.to_string(), "function %foo() {\n ss0 = local 4\n}\n");
|
||||
|
||||
let ebb = f.dfg.make_ebb();
|
||||
f.layout.append_ebb(ebb);
|
||||
assert_eq!(f.to_string(),
|
||||
"function %foo() {\n ss0 = stack_slot 4\n\nebb0:\n}\n");
|
||||
"function %foo() {\n ss0 = local 4\n\nebb0:\n}\n");
|
||||
|
||||
f.dfg.append_ebb_arg(ebb, types::I8);
|
||||
assert_eq!(f.to_string(),
|
||||
"function %foo() {\n ss0 = stack_slot 4\n\nebb0(v0: i8):\n}\n");
|
||||
"function %foo() {\n ss0 = local 4\n\nebb0(v0: i8):\n}\n");
|
||||
|
||||
f.dfg.append_ebb_arg(ebb, types::F32.by(4).unwrap());
|
||||
assert_eq!(f.to_string(),
|
||||
"function %foo() {\n ss0 = stack_slot 4\n\nebb0(v0: i8, v1: f32x4):\n}\n");
|
||||
"function %foo() {\n ss0 = local 4\n\nebb0(v0: i8, v1: f32x4):\n}\n");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user