diff --git a/lib/cretonne/src/ir/dfg.rs b/lib/cretonne/src/ir/dfg.rs index 35bb9c8f7e..b913f505e6 100644 --- a/lib/cretonne/src/ir/dfg.rs +++ b/lib/cretonne/src/ir/dfg.rs @@ -1,8 +1,9 @@ //! Data flow graph tracking Instructions, Values, and EBBs. -use ir::{Ebb, Inst, Value, Type}; +use ir::{Ebb, Inst, Value, Type, SigRef, Signature, FuncRef}; use ir::entities::{NO_VALUE, ExpandedValue}; use ir::instructions::InstructionData; +use ir::extfunc::ExtFuncData; use entity_map::{EntityMap, PrimaryEntityData}; use std::ops::{Index, IndexMut}; @@ -33,10 +34,19 @@ pub struct DataFlowGraph { /// This is implemented directly with a `Vec` rather than an `EntityMap` because /// the Value entity references can refer to two things -- an instruction or an extended value. extended_values: Vec, + + /// Function signature table. These signatures are referenced by indirect call instructions as + /// well as the external function references. + pub signatures: EntityMap, + + /// External function references. These are functions that can be called directly. + pub ext_funcs: EntityMap, } impl PrimaryEntityData for InstructionData {} impl PrimaryEntityData for EbbData {} +impl PrimaryEntityData for Signature {} +impl PrimaryEntityData for ExtFuncData {} impl DataFlowGraph { /// Create a new empty `DataFlowGraph`. @@ -45,6 +55,8 @@ impl DataFlowGraph { insts: EntityMap::new(), ebbs: EntityMap::new(), extended_values: Vec::new(), + signatures: EntityMap::new(), + ext_funcs: EntityMap::new(), } } diff --git a/lib/cretonne/src/ir/extfunc.rs b/lib/cretonne/src/ir/extfunc.rs index 78b723398e..6f89d5d307 100644 --- a/lib/cretonne/src/ir/extfunc.rs +++ b/lib/cretonne/src/ir/extfunc.rs @@ -6,7 +6,7 @@ //! This module declares the data types used to represent external functions and call signatures. use std::fmt::{self, Display, Formatter}; -use ir::Type; +use ir::{Type, FunctionName, SigRef}; /// Function signature. /// @@ -104,6 +104,21 @@ pub enum ArgumentExtension { Sext, } +/// An external function. +/// +/// Information about a function that can be called directly with a direct `call` instruction. +#[derive(Clone, Debug)] +pub struct ExtFuncData { + pub name: FunctionName, + pub signature: SigRef, +} + +impl Display for ExtFuncData { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{} {}", self.signature, self.name) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/lib/cretonne/src/ir/mod.rs b/lib/cretonne/src/ir/mod.rs index bbbc6d26ab..5056d9b29e 100644 --- a/lib/cretonne/src/ir/mod.rs +++ b/lib/cretonne/src/ir/mod.rs @@ -15,7 +15,7 @@ mod extfunc; mod builder; pub use ir::funcname::FunctionName; -pub use ir::extfunc::{Signature, ArgumentType, ArgumentExtension}; +pub use ir::extfunc::{Signature, ArgumentType, ArgumentExtension, ExtFuncData}; pub use ir::types::Type; pub use ir::entities::{Ebb, Inst, Value, StackSlot, JumpTable, FuncRef, SigRef}; pub use ir::instructions::{Opcode, InstructionData, VariableArgs}; diff --git a/lib/cretonne/src/write.rs b/lib/cretonne/src/write.rs index dfae305933..ac487c6f37 100644 --- a/lib/cretonne/src/write.rs +++ b/lib/cretonne/src/write.rs @@ -43,6 +43,17 @@ fn write_preamble(w: &mut Write, func: &Function) -> result::Result try!(writeln!(w, " {} = {}", ss, func.stack_slots[ss])); } + // Write out all signatures before functions since function decls can refer to signatures. + for sig in func.dfg.signatures.keys() { + any = true; + try!(writeln!(w, " {} = signature{}", sig, func.dfg.signatures[sig])); + } + + for fnref in func.dfg.ext_funcs.keys() { + any = true; + try!(writeln!(w, " {} = {}", fnref, func.dfg.ext_funcs[fnref])); + } + for jt in func.jump_tables.keys() { any = true; try!(writeln!(w, " {} = {}", jt, func.jump_tables[jt]));