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:
@@ -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);
|
||||||
|
|||||||
@@ -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..]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user