Add DataFlowGraph::display_inst().

This method returns an object that can display an instruction in the
standard textual format, but without any encoding annotations.
This commit is contained in:
Jakob Stoklund Olesen
2017-03-15 13:40:58 -07:00
parent 210530da9c
commit aa400d46ec
2 changed files with 80 additions and 43 deletions

View File

@@ -8,7 +8,9 @@ use entity_map::{EntityMap, PrimaryEntityData};
use ir::builder::{InsertBuilder, ReplaceBuilder}; use ir::builder::{InsertBuilder, ReplaceBuilder};
use ir::layout::Cursor; use ir::layout::Cursor;
use packed_option::PackedOption; use packed_option::PackedOption;
use write::write_operands;
use std::fmt;
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
use std::u16; use std::u16;
@@ -337,6 +339,11 @@ impl DataFlowGraph {
self.insts.next_key() self.insts.next_key()
} }
/// Returns an object that displays `inst`.
pub fn display_inst(&self, inst: Inst) -> DisplayInst {
DisplayInst(self, inst)
}
/// Create result values for an instruction that produces multiple results. /// Create result values for an instruction that produces multiple results.
/// ///
/// Instructions that produce 0 or 1 result values only need to be created with `make_inst`. If /// Instructions that produce 0 or 1 result values only need to be created with `make_inst`. If
@@ -649,6 +656,34 @@ impl EbbData {
} }
} }
/// Object that can display an instruction.
pub struct DisplayInst<'a>(&'a DataFlowGraph, Inst);
impl<'a> fmt::Display for DisplayInst<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let dfg = self.0;
let inst = &dfg[self.1];
let mut results = dfg.inst_results(self.1);
if let Some(first) = results.next() {
write!(f, "{}", first)?;
for v in results {
write!(f, ", {}", v)?;
}
write!(f, " = ")?;
}
let typevar = inst.ctrl_typevar(dfg);
if typevar.is_void() {
write!(f, "{}", inst.opcode())?;
} else {
write!(f, "{}.{}", inst.opcode(), typevar)?;
}
write_operands(f, dfg, self.1)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@@ -665,6 +700,7 @@ mod tests {
}; };
let inst = dfg.make_inst(idata); let inst = dfg.make_inst(idata);
assert_eq!(inst.to_string(), "inst0"); assert_eq!(inst.to_string(), "inst0");
assert_eq!(dfg.display_inst(inst).to_string(), "v0 = iconst.i32");
// Immutable reference resolution. // Immutable reference resolution.
{ {
@@ -692,6 +728,7 @@ mod tests {
ty: types::VOID, ty: types::VOID,
}; };
let inst = dfg.make_inst(idata); let inst = dfg.make_inst(idata);
assert_eq!(dfg.display_inst(inst).to_string(), "trap");
// Result iterator should be empty. // Result iterator should be empty.
let mut res = dfg.inst_results(inst); let mut res = dfg.inst_results(inst);

View File

@@ -4,7 +4,7 @@
//! equivalent textual representation. This textual representation can be read back by the //! equivalent textual representation. This textual representation can be read back by the
//! `cretonne-reader` crate. //! `cretonne-reader` crate.
use ir::{Function, Ebb, Inst, Value, Type}; use ir::{Function, DataFlowGraph, Ebb, Inst, Value, Type};
use isa::{TargetIsa, RegInfo}; use isa::{TargetIsa, RegInfo};
use std::fmt::{self, Result, Error, Write}; use std::fmt::{self, Result, Error, Write};
use std::result; use std::result;
@@ -228,69 +228,69 @@ fn write_instruction(w: &mut Write,
None => write!(w, "{}", opcode)?, None => write!(w, "{}", opcode)?,
} }
// Then the operands, depending on format. write_operands(w, &func.dfg, inst)?;
let pool = &func.dfg.value_lists; writeln!(w, "")
}
/// Write the operands of `inst` to `w` with a prepended space.
pub fn write_operands(w: &mut Write, dfg: &DataFlowGraph, inst: Inst) -> Result {
let pool = &dfg.value_lists;
use ir::instructions::InstructionData::*; use ir::instructions::InstructionData::*;
match func.dfg[inst] { match dfg[inst] {
Nullary { .. } => writeln!(w, ""), Nullary { .. } => write!(w, ""),
Unary { arg, .. } => writeln!(w, " {}", arg), Unary { arg, .. } => write!(w, " {}", arg),
UnaryImm { imm, .. } => writeln!(w, " {}", imm), UnaryImm { imm, .. } => write!(w, " {}", imm),
UnaryIeee32 { imm, .. } => writeln!(w, " {}", imm), UnaryIeee32 { imm, .. } => write!(w, " {}", imm),
UnaryIeee64 { imm, .. } => writeln!(w, " {}", imm), UnaryIeee64 { imm, .. } => write!(w, " {}", imm),
UnarySplit { arg, .. } => writeln!(w, " {}", arg), UnarySplit { arg, .. } => write!(w, " {}", arg),
Binary { args, .. } => writeln!(w, " {}, {}", args[0], args[1]), Binary { args, .. } => write!(w, " {}, {}", args[0], args[1]),
BinaryImm { arg, imm, .. } => writeln!(w, " {}, {}", arg, imm), BinaryImm { arg, imm, .. } => write!(w, " {}, {}", arg, imm),
BinaryOverflow { args, .. } => writeln!(w, " {}, {}", args[0], args[1]), BinaryOverflow { args, .. } => write!(w, " {}, {}", args[0], args[1]),
Ternary { args, .. } => writeln!(w, " {}, {}, {}", args[0], args[1], args[2]), Ternary { args, .. } => write!(w, " {}, {}, {}", args[0], args[1], args[2]),
MultiAry { ref args, .. } => { MultiAry { ref args, .. } => {
if args.is_empty() { if args.is_empty() {
writeln!(w, "") write!(w, "")
} else { } else {
writeln!(w, write!(w, " {}", DisplayValues(args.as_slice(pool)))
" {}",
DisplayValues(args.as_slice(&func.dfg.value_lists)))
} }
} }
InsertLane { lane, args, .. } => writeln!(w, " {}, {}, {}", args[0], lane, args[1]), InsertLane { lane, args, .. } => write!(w, " {}, {}, {}", args[0], lane, args[1]),
ExtractLane { lane, arg, .. } => writeln!(w, " {}, {}", arg, lane), ExtractLane { lane, arg, .. } => write!(w, " {}, {}", arg, lane),
IntCompare { cond, args, .. } => writeln!(w, " {}, {}, {}", cond, args[0], args[1]), IntCompare { cond, args, .. } => write!(w, " {}, {}, {}", cond, args[0], args[1]),
FloatCompare { cond, args, .. } => writeln!(w, " {}, {}, {}", cond, args[0], args[1]), FloatCompare { cond, args, .. } => write!(w, " {}, {}, {}", cond, args[0], args[1]),
Jump { destination, ref args, .. } => { Jump { destination, ref args, .. } => {
if args.is_empty() { if args.is_empty() {
writeln!(w, " {}", destination) write!(w, " {}", destination)
} else { } else {
writeln!(w, write!(w,
" {}({})", " {}({})",
destination, destination,
DisplayValues(args.as_slice(pool))) DisplayValues(args.as_slice(pool)))
} }
} }
Branch { destination, ref args, .. } => { Branch { destination, ref args, .. } => {
let args = args.as_slice(pool); let args = args.as_slice(pool);
if args.len() == 1 { if args.len() == 1 {
writeln!(w, " {}, {}", args[0], destination) write!(w, " {}, {}", args[0], destination)
} else { } else {
writeln!(w, write!(w,
" {}, {}({})", " {}, {}({})",
args[0], args[0],
destination, destination,
DisplayValues(&args[1..])) DisplayValues(&args[1..]))
} }
} }
BranchTable { arg, table, .. } => writeln!(w, " {}, {}", arg, table), BranchTable { arg, table, .. } => write!(w, " {}, {}", arg, table),
Call { func_ref, ref args, .. } => { Call { func_ref, ref args, .. } => {
writeln!(w, write!(w, " {}({})", func_ref, DisplayValues(args.as_slice(pool)))
" {}({})",
func_ref,
DisplayValues(args.as_slice(&func.dfg.value_lists)))
} }
IndirectCall { sig_ref, ref args, .. } => { IndirectCall { sig_ref, ref args, .. } => {
let args = args.as_slice(pool); let args = args.as_slice(pool);
writeln!(w, write!(w,
" {}, {}({})", " {}, {}({})",
sig_ref, sig_ref,
args[0], args[0],
DisplayValues(&args[1..])) DisplayValues(&args[1..]))
} }
} }
} }