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:
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>,
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
Reference in New Issue
Block a user