Add a stack frame manager.
Use a new StackSlots struct to keep track of a function's stack slots instead of just an entity map. This let's us build more internal data structures for tracking the stack slots if necessary. Start by adding a make_spill_slot() function that will be used by the register allocator.
This commit is contained in:
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
use binemit::CodeOffset;
|
use binemit::CodeOffset;
|
||||||
use entity_map::{EntityMap, PrimaryEntityData};
|
use entity_map::{EntityMap, PrimaryEntityData};
|
||||||
use ir::{FunctionName, Signature, Value, Inst, Ebb, StackSlot, StackSlotData, JumpTable,
|
use ir::{FunctionName, Signature, Value, Inst, Ebb, StackSlots, JumpTable, JumpTableData,
|
||||||
JumpTableData, ValueLoc, DataFlowGraph, Layout};
|
ValueLoc, DataFlowGraph, Layout};
|
||||||
use isa::{TargetIsa, Encoding};
|
use isa::{TargetIsa, Encoding};
|
||||||
use std::fmt::{self, Display, Debug, Formatter};
|
use std::fmt::{self, Display, Debug, Formatter};
|
||||||
use write::write_function;
|
use write::write_function;
|
||||||
@@ -24,7 +24,7 @@ pub struct Function {
|
|||||||
pub signature: Signature,
|
pub signature: Signature,
|
||||||
|
|
||||||
/// Stack slots allocated in this function.
|
/// Stack slots allocated in this function.
|
||||||
pub stack_slots: EntityMap<StackSlot, StackSlotData>,
|
pub stack_slots: StackSlots,
|
||||||
|
|
||||||
/// Jump tables used in this function.
|
/// Jump tables used in this function.
|
||||||
pub jump_tables: EntityMap<JumpTable, JumpTableData>,
|
pub jump_tables: EntityMap<JumpTable, JumpTableData>,
|
||||||
@@ -50,7 +50,6 @@ pub struct Function {
|
|||||||
pub offsets: EntityMap<Ebb, CodeOffset>,
|
pub offsets: EntityMap<Ebb, CodeOffset>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrimaryEntityData for StackSlotData {}
|
|
||||||
impl PrimaryEntityData for JumpTableData {}
|
impl PrimaryEntityData for JumpTableData {}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
@@ -59,7 +58,7 @@ impl Function {
|
|||||||
Function {
|
Function {
|
||||||
name,
|
name,
|
||||||
signature: sig,
|
signature: sig,
|
||||||
stack_slots: EntityMap::new(),
|
stack_slots: StackSlots::new(),
|
||||||
jump_tables: EntityMap::new(),
|
jump_tables: EntityMap::new(),
|
||||||
dfg: DataFlowGraph::new(),
|
dfg: DataFlowGraph::new(),
|
||||||
layout: Layout::new(),
|
layout: Layout::new(),
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ pub use ir::extfunc::{Signature, ArgumentType, ArgumentExtension, ArgumentPurpos
|
|||||||
pub use ir::types::Type;
|
pub use ir::types::Type;
|
||||||
pub use ir::entities::{Ebb, Inst, Value, StackSlot, JumpTable, FuncRef, SigRef};
|
pub use ir::entities::{Ebb, Inst, Value, StackSlot, JumpTable, FuncRef, SigRef};
|
||||||
pub use ir::instructions::{Opcode, InstructionData, VariableArgs, ValueList, ValueListPool};
|
pub use ir::instructions::{Opcode, InstructionData, VariableArgs, ValueList, ValueListPool};
|
||||||
pub use ir::stackslot::{StackSlotKind, StackSlotData};
|
pub use ir::stackslot::{StackSlots, StackSlotKind, StackSlotData};
|
||||||
pub use ir::jumptable::JumpTableData;
|
pub use ir::jumptable::JumpTableData;
|
||||||
pub use ir::valueloc::{ValueLoc, ArgumentLoc};
|
pub use ir::valueloc::{ValueLoc, ArgumentLoc};
|
||||||
pub use ir::dfg::{DataFlowGraph, ValueDef};
|
pub use ir::dfg::{DataFlowGraph, ValueDef};
|
||||||
|
|||||||
@@ -3,7 +3,10 @@
|
|||||||
//! The `StackSlotData` struct keeps track of a single stack slot in a function.
|
//! The `StackSlotData` struct keeps track of a single stack slot in a function.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
|
use entity_map::{EntityMap, PrimaryEntityData, Keys};
|
||||||
|
use ir::{Type, StackSlot};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::ops::Index;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
/// The kind of a stack slot.
|
/// The kind of a stack slot.
|
||||||
@@ -81,6 +84,71 @@ impl fmt::Display for StackSlotData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PrimaryEntityData for StackSlotData {}
|
||||||
|
|
||||||
|
/// Stack frame manager.
|
||||||
|
///
|
||||||
|
/// Keep track of all the stack slots used by a function.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct StackSlots {
|
||||||
|
slots: EntityMap<StackSlot, StackSlotData>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stack slot manager functions that behave mostly like an entity map.
|
||||||
|
impl StackSlots {
|
||||||
|
/// Create an empty stack slot manager.
|
||||||
|
pub fn new() -> StackSlots {
|
||||||
|
StackSlots { slots: EntityMap::new() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clear out everything.
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
self.slots.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Allocate a new stack slot.
|
||||||
|
///
|
||||||
|
/// This function should be primarily used by the text format parser. There are more convenient
|
||||||
|
/// functions for creating specific kinds of stack slots below.
|
||||||
|
pub fn push(&mut self, data: StackSlotData) -> StackSlot {
|
||||||
|
self.slots.push(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if `ss` is a valid stack slot reference.
|
||||||
|
pub fn is_valid(&self, ss: StackSlot) -> bool {
|
||||||
|
self.slots.is_valid(ss)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get an iterator over all the stack slot keys.
|
||||||
|
pub fn keys(&self) -> Keys<StackSlot> {
|
||||||
|
self.slots.keys()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the next stack slot that would be created by `push()`.
|
||||||
|
///
|
||||||
|
/// This should just be used by the parser.
|
||||||
|
pub fn next_key(&self) -> StackSlot {
|
||||||
|
self.slots.next_key()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Higher-level stack frame manipulation functions.
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Index<StackSlot> for StackSlots {
|
||||||
|
type Output = StackSlotData;
|
||||||
|
|
||||||
|
fn index(&self, ss: StackSlot) -> &StackSlotData {
|
||||||
|
&self.slots[ss]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use ir::Function;
|
use ir::Function;
|
||||||
|
|||||||
Reference in New Issue
Block a user