Use ISA information to display function signatures.

The argument locations contains register unit references that we want to
display with their correct names.
This commit is contained in:
Jakob Stoklund Olesen
2017-03-03 10:34:29 -08:00
parent 00772fb6c4
commit cb3e503f07
4 changed files with 77 additions and 29 deletions

View File

@@ -6,8 +6,9 @@
//! This module declares the data types used to represent external functions and call signatures. //! This module declares the data types used to represent external functions and call signatures.
use ir::{Type, FunctionName, SigRef, ArgumentLoc}; use ir::{Type, FunctionName, SigRef, ArgumentLoc};
use isa::RegInfo;
use std::cmp; use std::cmp;
use std::fmt::{self, Display, Formatter}; use std::fmt;
/// Function signature. /// Function signature.
/// ///
@@ -55,34 +56,51 @@ impl Signature {
.fold(0, cmp::max); .fold(0, cmp::max);
self.argument_bytes = Some(bytes); self.argument_bytes = Some(bytes);
} }
/// Return an object that can display `self` with correct register names.
pub fn display<'a, R: Into<Option<&'a RegInfo>>>(&'a self, regs: R) -> DisplaySignature<'a> {
DisplaySignature(self, regs.into())
}
} }
fn write_list(f: &mut Formatter, args: &Vec<ArgumentType>) -> 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<ArgumentType>,
regs: Option<&RegInfo>)
-> fmt::Result {
match args.split_first() { match args.split_first() {
None => {} None => {}
Some((first, rest)) => { Some((first, rest)) => {
write!(f, "{}", first)?; write!(f, "{}", first.display(regs))?;
for arg in rest { for arg in rest {
write!(f, ", {}", arg)?; write!(f, ", {}", arg.display(regs))?;
} }
} }
} }
Ok(()) Ok(())
} }
impl Display for Signature { impl<'a> fmt::Display for DisplaySignature<'a> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(")?; write!(f, "(")?;
write_list(f, &self.argument_types)?; write_list(f, &self.0.argument_types, self.1)?;
write!(f, ")")?; write!(f, ")")?;
if !self.return_types.is_empty() { if !self.0.return_types.is_empty() {
write!(f, " -> ")?; write!(f, " -> ")?;
write_list(f, &self.return_types)?; write_list(f, &self.0.return_types, self.1)?;
} }
Ok(()) 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. /// Function argument or return value type.
/// ///
/// This describes the value type being passed to or from a function along with flags that affect /// 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(), location: Default::default(),
} }
} }
/// Return an object that can display `self` with correct register names.
pub fn display<'a, R: Into<Option<&'a RegInfo>>>(&'a self, regs: R) -> DisplayArgumentType<'a> {
DisplayArgumentType(self, regs.into())
}
} }
impl Display for ArgumentType { /// Wrapper type capable of displaying an `ArgumentType` with correct register names.
fn fmt(&self, f: &mut Formatter) -> fmt::Result { pub struct DisplayArgumentType<'a>(&'a ArgumentType, Option<&'a RegInfo>);
write!(f, "{}", self.value_type)?;
match self.extension { 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::None => {}
ArgumentExtension::Uext => write!(f, " uext")?, ArgumentExtension::Uext => write!(f, " uext")?,
ArgumentExtension::Sext => write!(f, " sext")?, ArgumentExtension::Sext => write!(f, " sext")?,
} }
if self.inreg { if self.0.inreg {
write!(f, " inreg")?; write!(f, " inreg")?;
} }
// This really needs a `&TargetAbi` so we can print register units correctly. if self.0.location.is_assigned() {
match self.location { write!(f, " [{}]", self.0.location.display(self.1))?;
ArgumentLoc::Reg(ru) => write!(f, " [%{}]", ru),
ArgumentLoc::Stack(offset) => write!(f, " [{}]", offset),
ArgumentLoc::Unassigned => Ok(()),
} }
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, pub signature: SigRef,
} }
impl Display for ExtFuncData { impl fmt::Display for ExtFuncData {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {}", self.signature, self.name) write!(f, "{} {}", self.signature, self.name)
} }
} }

View File

@@ -20,7 +20,7 @@ pub struct Function {
pub name: FunctionName, pub name: FunctionName,
/// Signature of this function. /// Signature of this function.
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: EntityMap<StackSlot, StackSlotData>,

View File

@@ -88,6 +88,14 @@ impl Default for ArgumentLoc {
} }
impl 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 /// Return an object that can display this argument location, using the register info from the
/// target ISA. /// target ISA.
pub fn display<'a, R: Into<Option<&'a RegInfo>>>(self, regs: R) -> DisplayArgumentLoc<'a> { pub fn display<'a, R: Into<Option<&'a RegInfo>>>(self, regs: R) -> DisplayArgumentLoc<'a> {

View File

@@ -5,16 +5,19 @@
//! `cretonne-reader` crate. //! `cretonne-reader` crate.
use ir::{Function, Ebb, Inst, Value, Type}; use ir::{Function, Ebb, Inst, Value, Type};
use isa::TargetIsa; use isa::{TargetIsa, RegInfo};
use std::fmt::{Result, Error, Write}; use std::fmt::{Result, Error, Write};
use std::result; use std::result;
/// Write `func` to `w` as equivalent text. /// Write `func` to `w` as equivalent text.
/// Use `isa` to emit ISA-dependent annotations. /// Use `isa` to emit ISA-dependent annotations.
pub fn write_function(w: &mut Write, func: &Function, isa: Option<&TargetIsa>) -> Result { 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, " {{")?; writeln!(w, " {{")?;
let mut any = write_preamble(w, func)?; let mut any = write_preamble(w, func, regs)?;
for ebb in &func.layout { for ebb in &func.layout {
if any { if any {
writeln!(w, "")?; 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 { fn write_spec(w: &mut Write, func: &Function, regs: Option<&RegInfo>) -> Result {
write!(w, "function {}{}", func.name, func.own_signature()) write!(w, "function {}{}", func.name, func.signature.display(regs))
} }
fn write_preamble(w: &mut Write, func: &Function) -> result::Result<bool, Error> { fn write_preamble(w: &mut Write,
func: &Function,
regs: Option<&RegInfo>)
-> result::Result<bool, Error> {
let mut any = false; let mut any = false;
for ss in func.stack_slots.keys() { for ss in func.stack_slots.keys() {
@@ -47,7 +53,10 @@ fn write_preamble(w: &mut Write, func: &Function) -> result::Result<bool, Error>
// signatures. // signatures.
for sig in func.dfg.signatures.keys() { for sig in func.dfg.signatures.keys() {
any = true; 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() { for fnref in func.dfg.ext_funcs.keys() {