diff --git a/lib/cretonne/src/ir/extfunc.rs b/lib/cretonne/src/ir/extfunc.rs index 5c4d1d1c71..9f81d11442 100644 --- a/lib/cretonne/src/ir/extfunc.rs +++ b/lib/cretonne/src/ir/extfunc.rs @@ -6,8 +6,9 @@ //! This module declares the data types used to represent external functions and call signatures. use ir::{Type, FunctionName, SigRef, ArgumentLoc}; +use isa::RegInfo; use std::cmp; -use std::fmt::{self, Display, Formatter}; +use std::fmt; /// Function signature. /// @@ -55,34 +56,51 @@ impl Signature { .fold(0, cmp::max); self.argument_bytes = Some(bytes); } + + /// Return an object that can display `self` with correct register names. + pub fn display<'a, R: Into>>(&'a self, regs: R) -> DisplaySignature<'a> { + DisplaySignature(self, regs.into()) + } } -fn write_list(f: &mut Formatter, args: &Vec) -> fmt::Result { +/// Wrapper type capable of displaying a `Signature` with correct register names. +pub struct DisplaySignature<'a>(&'a Signature, Option<&'a RegInfo>); + +fn write_list(f: &mut fmt::Formatter, + args: &Vec, + regs: Option<&RegInfo>) + -> fmt::Result { match args.split_first() { None => {} Some((first, rest)) => { - write!(f, "{}", first)?; + write!(f, "{}", first.display(regs))?; for arg in rest { - write!(f, ", {}", arg)?; + write!(f, ", {}", arg.display(regs))?; } } } Ok(()) } -impl Display for Signature { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { +impl<'a> fmt::Display for DisplaySignature<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "(")?; - write_list(f, &self.argument_types)?; + write_list(f, &self.0.argument_types, self.1)?; write!(f, ")")?; - if !self.return_types.is_empty() { + if !self.0.return_types.is_empty() { write!(f, " -> ")?; - write_list(f, &self.return_types)?; + write_list(f, &self.0.return_types, self.1)?; } Ok(()) } } +impl fmt::Display for Signature { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.display(None).fmt(f) + } +} + /// Function argument or return value type. /// /// This describes the value type being passed to or from a function along with flags that affect @@ -111,26 +129,39 @@ impl ArgumentType { location: Default::default(), } } + + /// Return an object that can display `self` with correct register names. + pub fn display<'a, R: Into>>(&'a self, regs: R) -> DisplayArgumentType<'a> { + DisplayArgumentType(self, regs.into()) + } } -impl Display for ArgumentType { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{}", self.value_type)?; - match self.extension { +/// Wrapper type capable of displaying an `ArgumentType` with correct register names. +pub struct DisplayArgumentType<'a>(&'a ArgumentType, Option<&'a RegInfo>); + +impl<'a> fmt::Display for DisplayArgumentType<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0.value_type)?; + match self.0.extension { ArgumentExtension::None => {} ArgumentExtension::Uext => write!(f, " uext")?, ArgumentExtension::Sext => write!(f, " sext")?, } - if self.inreg { + if self.0.inreg { write!(f, " inreg")?; } - // This really needs a `&TargetAbi` so we can print register units correctly. - match self.location { - ArgumentLoc::Reg(ru) => write!(f, " [%{}]", ru), - ArgumentLoc::Stack(offset) => write!(f, " [{}]", offset), - ArgumentLoc::Unassigned => Ok(()), + if self.0.location.is_assigned() { + write!(f, " [{}]", self.0.location.display(self.1))?; } + + Ok(()) + } +} + +impl fmt::Display for ArgumentType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.display(None).fmt(f) } } @@ -159,8 +190,8 @@ pub struct ExtFuncData { pub signature: SigRef, } -impl Display for ExtFuncData { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { +impl fmt::Display for ExtFuncData { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{} {}", self.signature, self.name) } } diff --git a/lib/cretonne/src/ir/function.rs b/lib/cretonne/src/ir/function.rs index 2828104daa..b1ae83dc28 100644 --- a/lib/cretonne/src/ir/function.rs +++ b/lib/cretonne/src/ir/function.rs @@ -20,7 +20,7 @@ pub struct Function { pub name: FunctionName, /// Signature of this function. - signature: Signature, + pub signature: Signature, /// Stack slots allocated in this function. pub stack_slots: EntityMap, diff --git a/lib/cretonne/src/ir/valueloc.rs b/lib/cretonne/src/ir/valueloc.rs index db1ee2baf2..253c5ceb33 100644 --- a/lib/cretonne/src/ir/valueloc.rs +++ b/lib/cretonne/src/ir/valueloc.rs @@ -88,6 +88,14 @@ impl Default for ArgumentLoc { } impl ArgumentLoc { + /// Is this an assigned location? (That is, not `Unassigned`). + pub fn is_assigned(&self) -> bool { + match self { + &ArgumentLoc::Unassigned => false, + _ => true, + } + } + /// Return an object that can display this argument location, using the register info from the /// target ISA. pub fn display<'a, R: Into>>(self, regs: R) -> DisplayArgumentLoc<'a> { diff --git a/lib/cretonne/src/write.rs b/lib/cretonne/src/write.rs index 957f8a036d..40b625d6e0 100644 --- a/lib/cretonne/src/write.rs +++ b/lib/cretonne/src/write.rs @@ -5,16 +5,19 @@ //! `cretonne-reader` crate. use ir::{Function, Ebb, Inst, Value, Type}; -use isa::TargetIsa; +use isa::{TargetIsa, RegInfo}; use std::fmt::{Result, Error, Write}; use std::result; /// Write `func` to `w` as equivalent text. /// Use `isa` to emit ISA-dependent annotations. pub fn write_function(w: &mut Write, func: &Function, isa: Option<&TargetIsa>) -> Result { - write_spec(w, func)?; + let regs = isa.map(TargetIsa::register_info); + let regs = regs.as_ref(); + + write_spec(w, func, regs)?; writeln!(w, " {{")?; - let mut any = write_preamble(w, func)?; + let mut any = write_preamble(w, func, regs)?; for ebb in &func.layout { if any { writeln!(w, "")?; @@ -31,11 +34,14 @@ pub fn write_function(w: &mut Write, func: &Function, isa: Option<&TargetIsa>) - // // ====--------------------------------------------------------------------------------------====// -fn write_spec(w: &mut Write, func: &Function) -> Result { - write!(w, "function {}{}", func.name, func.own_signature()) +fn write_spec(w: &mut Write, func: &Function, regs: Option<&RegInfo>) -> Result { + write!(w, "function {}{}", func.name, func.signature.display(regs)) } -fn write_preamble(w: &mut Write, func: &Function) -> result::Result { +fn write_preamble(w: &mut Write, + func: &Function, + regs: Option<&RegInfo>) + -> result::Result { let mut any = false; for ss in func.stack_slots.keys() { @@ -47,7 +53,10 @@ fn write_preamble(w: &mut Write, func: &Function) -> result::Result // signatures. for sig in func.dfg.signatures.keys() { any = true; - writeln!(w, " {} = signature{}", sig, func.dfg.signatures[sig])?; + writeln!(w, + " {} = signature{}", + sig, + func.dfg.signatures[sig].display(regs))?; } for fnref in func.dfg.ext_funcs.keys() {