Add heaps to the Cretonne IL.

Add preamble syntax for declaring static and dynamic heaps, and update
the langref section on heaps. Add IR support for heap references.

Remove the heap_load and heap_store as discussed in #144. We will use
heap_addr along with native load and store instructions in their place.

Add the heap_addr instruction and document its bounds checking
semantics.
This commit is contained in:
Jakob Stoklund Olesen
2017-08-18 12:51:54 -07:00
parent a9238eda7a
commit 3b71a27632
17 changed files with 405 additions and 83 deletions

View File

@@ -98,6 +98,11 @@ entity_impl!(FuncRef, "fn");
pub struct SigRef(u32);
entity_impl!(SigRef, "sig");
/// A reference to a heap.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct Heap(u32);
entity_impl!(Heap, "heap");
/// A reference to any of the entities defined in this module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum AnyEntity {
@@ -119,6 +124,8 @@ pub enum AnyEntity {
FuncRef(FuncRef),
/// A function call signature.
SigRef(SigRef),
/// A heap.
Heap(Heap),
}
impl fmt::Display for AnyEntity {
@@ -133,6 +140,7 @@ impl fmt::Display for AnyEntity {
AnyEntity::JumpTable(r) => r.fmt(f),
AnyEntity::FuncRef(r) => r.fmt(f),
AnyEntity::SigRef(r) => r.fmt(f),
AnyEntity::Heap(r) => r.fmt(f),
}
}
}
@@ -185,6 +193,12 @@ impl From<SigRef> for AnyEntity {
}
}
impl From<Heap> for AnyEntity {
fn from(r: Heap) -> AnyEntity {
AnyEntity::Heap(r)
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -29,6 +29,9 @@ pub struct Function {
/// Global variables referenced.
pub global_vars: PrimaryMap<ir::GlobalVar, ir::GlobalVarData>,
/// Heaps referenced.
pub heaps: PrimaryMap<ir::Heap, ir::HeapData>,
/// Jump tables used in this function.
pub jump_tables: JumpTables,
@@ -61,6 +64,7 @@ impl Function {
signature: sig,
stack_slots: StackSlots::new(),
global_vars: PrimaryMap::new(),
heaps: PrimaryMap::new(),
jump_tables: PrimaryMap::new(),
dfg: DataFlowGraph::new(),
layout: Layout::new(),

View File

@@ -0,0 +1,70 @@
//! Heaps.
use ir::immediates::Imm64;
use ir::GlobalVar;
use std::fmt;
/// Information about a heap declaration.
#[derive(Clone)]
pub struct HeapData {
/// Method for determining the heap base address.
pub base: HeapBase,
/// Guaranteed minimum heap size in bytes. Heap accesses before `min_size` don't need bounds
/// checking.
pub min_size: Imm64,
/// Size in bytes of the guard pages following the heap.
pub guard_size: Imm64,
/// Heap style, with additional style-specific info.
pub style: HeapStyle,
}
/// Method for determining the base address of a heap.
#[derive(Clone)]
pub enum HeapBase {
/// The heap base lives in a reserved register.
ReservedReg,
/// The heap base is in a global variable.
GlobalVar(GlobalVar),
}
/// Style of heap including style-specific information.
#[derive(Clone)]
pub enum HeapStyle {
/// A dynamic heap can be relocated to a different base address when it is grown.
Dynamic {
/// Global variable holding the current bound of the heap in bytes.
bound_gv: GlobalVar,
},
/// A static heap has a fixed base address and a number of not-yet-allocated pages before the
/// guard pages.
Static {
/// Heap bound in bytes. The guard pages are allocated after the bound.
bound: Imm64,
},
}
impl fmt::Display for HeapData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match self.style {
HeapStyle::Dynamic { .. } => "dynamic",
HeapStyle::Static { .. } => "static",
})?;
match self.base {
HeapBase::ReservedReg => write!(f, " reserved_reg")?,
HeapBase::GlobalVar(gv) => write!(f, " {}", gv)?,
}
write!(f, ", min {}", self.min_size)?;
match self.style {
HeapStyle::Dynamic { bound_gv } => write!(f, ", bound {}", bound_gv)?,
HeapStyle::Static { bound } => write!(f, ", bound {}", bound)?,
}
write!(f, ", guard {}", self.guard_size)
}
}

View File

@@ -12,7 +12,7 @@ use std::ops::{Deref, DerefMut};
use ir;
use ir::{Value, Type, Ebb, JumpTable, SigRef, FuncRef, StackSlot, MemFlags};
use ir::immediates::{Imm64, Uimm8, Ieee32, Ieee64, Offset32, Uoffset32};
use ir::immediates::{Imm64, Uimm8, Uimm32, Ieee32, Ieee64, Offset32, Uoffset32};
use ir::condcodes::*;
use ir::types;
use isa::RegUnit;
@@ -199,6 +199,12 @@ pub enum InstructionData {
args: [Value; 2],
offset: Uoffset32,
},
HeapAddr {
opcode: Opcode,
heap: ir::Heap,
arg: Value,
imm: Uimm32,
},
Load {
opcode: Opcode,
flags: MemFlags,

View File

@@ -14,18 +14,20 @@ mod builder;
mod extfunc;
mod funcname;
mod globalvar;
mod heap;
mod memflags;
mod progpoint;
mod valueloc;
pub use ir::builder::{InstBuilder, InstBuilderBase, InstInserterBase, InsertBuilder};
pub use ir::dfg::{DataFlowGraph, ValueDef};
pub use ir::entities::{Ebb, Inst, Value, StackSlot, GlobalVar, JumpTable, FuncRef, SigRef};
pub use ir::entities::{Ebb, Inst, Value, StackSlot, GlobalVar, JumpTable, FuncRef, SigRef, Heap};
pub use ir::extfunc::{Signature, CallConv, ArgumentType, ArgumentExtension, ArgumentPurpose,
ExtFuncData};
pub use ir::funcname::FunctionName;
pub use ir::function::Function;
pub use ir::globalvar::GlobalVarData;
pub use ir::heap::{HeapData, HeapStyle, HeapBase};
pub use ir::instructions::{Opcode, InstructionData, VariableArgs, ValueList, ValueListPool};
pub use ir::jumptable::JumpTableData;
pub use ir::layout::{Layout, CursorBase, Cursor};