Add an ISA argument to dfg.display_inst().

Include ISA-specific annotations in tracing and error messages.
This commit is contained in:
Jakob Stoklund Olesen
2017-07-12 10:12:20 -07:00
parent e4da2e1f22
commit 69f974ba5d
10 changed files with 42 additions and 33 deletions

View File

@@ -127,7 +127,7 @@ impl SubTest for TestBinEmit {
AnyEntity::Inst(inst) => {
if let Some(prev) = bins.insert(inst, want) {
return Err(format!("multiple 'bin:' directives on {}: '{}' and '{}'",
func.dfg.display_inst(inst),
func.dfg.display_inst(inst, isa),
prev,
want));
}
@@ -166,7 +166,7 @@ impl SubTest for TestBinEmit {
encinfo.bytes(enc),
"Inconsistent size for [{}] {}",
encinfo.display(enc),
func.dfg.display_inst(inst));
func.dfg.display_inst(inst, isa));
}
// Check against bin: directives.
@@ -174,13 +174,13 @@ impl SubTest for TestBinEmit {
if !enc.is_legal() {
return Err(format!("{} can't be encoded: {}",
inst,
func.dfg.display_inst(inst)));
func.dfg.display_inst(inst, isa)));
}
let have = sink.text.trim();
if have != want {
return Err(format!("Bad machine code for {}: {}\nWant: {}\nGot: {}",
inst,
func.dfg.display_inst(inst),
func.dfg.display_inst(inst, isa),
want,
have));
}

View File

@@ -42,7 +42,7 @@ pub fn pretty_verifier_error(func: &ir::Function,
let mut msg = err.to_string();
match err.location {
AnyEntity::Inst(inst) => {
write!(msg, "\n{}: {}\n\n", inst, func.dfg.display_inst(inst)).unwrap()
write!(msg, "\n{}: {}\n\n", inst, func.dfg.display_inst(inst, isa)).unwrap()
}
_ => msg.push('\n'),
}

View File

@@ -53,5 +53,5 @@ pub trait CodeSink {
pub fn bad_encoding(func: &Function, inst: Inst) -> ! {
panic!("Bad encoding {} for {}",
func.encodings[inst],
func.dfg.display_inst(inst));
func.dfg.display_inst(inst, None));
}

View File

@@ -135,7 +135,7 @@ fn relax_branch(dfg: &mut DataFlowGraph,
let inst = pos.current_inst().unwrap();
dbg!("Relaxing [{}] {} for {:#x}-{:#x} range",
encinfo.display(encodings[inst]),
dfg.display_inst(inst),
dfg.display_inst(inst, None),
offset,
dest_offset);
unimplemented!();

View File

@@ -1,6 +1,7 @@
//! Data flow graph tracking Instructions, Values, and EBBs.
use entity_map::{EntityMap, PrimaryEntityData};
use isa::TargetIsa;
use ir::builder::{InsertBuilder, ReplaceBuilder};
use ir::extfunc::ExtFuncData;
use ir::instructions::{Opcode, InstructionData, CallInfo};
@@ -162,7 +163,7 @@ impl DataFlowGraph {
self.results[inst].get(num as usize, &self.value_lists),
"Dangling result value {}: {}",
v,
self.display_inst(inst));
self.display_inst(inst, None));
ValueDef::Res(inst, num as usize)
}
ValueData::Arg { ebb, num, .. } => {
@@ -376,8 +377,11 @@ impl DataFlowGraph {
}
/// Returns an object that displays `inst`.
pub fn display_inst(&self, inst: Inst) -> DisplayInst {
DisplayInst(self, inst)
pub fn display_inst<'a, I: Into<Option<&'a TargetIsa>>>(&'a self,
inst: Inst,
isa: I)
-> DisplayInst<'a> {
DisplayInst(self, isa.into(), inst)
}
/// Get all value arguments on `inst` as a slice.
@@ -552,7 +556,7 @@ impl DataFlowGraph {
old_value,
"{} wasn't detached from {}",
old_value,
self.display_inst(inst));
self.display_inst(inst, None));
new_value
}
@@ -830,14 +834,15 @@ impl EbbData {
}
/// Object that can display an instruction.
pub struct DisplayInst<'a>(&'a DataFlowGraph, Inst);
pub struct DisplayInst<'a>(&'a DataFlowGraph, Option<&'a TargetIsa>, 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 isa = self.1;
let inst = self.2;
if let Some((first, rest)) = dfg.inst_results(self.1).split_first() {
if let Some((first, rest)) = dfg.inst_results(inst).split_first() {
write!(f, "{}", first)?;
for v in rest {
write!(f, ", {}", v)?;
@@ -846,13 +851,13 @@ impl<'a> fmt::Display for DisplayInst<'a> {
}
let typevar = dfg.ctrl_typevar(self.1);
let typevar = dfg.ctrl_typevar(inst);
if typevar.is_void() {
write!(f, "{}", inst.opcode())?;
write!(f, "{}", dfg[inst].opcode())?;
} else {
write!(f, "{}.{}", inst.opcode(), typevar)?;
write!(f, "{}.{}", dfg[inst].opcode(), typevar)?;
}
write_operands(f, dfg, None, self.1)
write_operands(f, dfg, isa, inst)
}
}
@@ -870,7 +875,7 @@ mod tests {
let inst = dfg.make_inst(idata);
dfg.make_inst_results(inst, types::I32);
assert_eq!(inst.to_string(), "inst0");
assert_eq!(dfg.display_inst(inst).to_string(), "v0 = iconst.i32");
assert_eq!(dfg.display_inst(inst, None).to_string(), "v0 = iconst.i32");
// Immutable reference resolution.
{
@@ -902,7 +907,7 @@ mod tests {
let idata = InstructionData::Nullary { opcode: Opcode::Trap };
let inst = dfg.make_inst(idata);
assert_eq!(dfg.display_inst(inst).to_string(), "trap");
assert_eq!(dfg.display_inst(inst, None).to_string(), "trap");
// Result slice should be empty.
assert_eq!(dfg.inst_results(inst), &[]);

View File

@@ -474,7 +474,7 @@ pub fn handle_call_abi(dfg: &mut DataFlowGraph, cfg: &ControlFlowGraph, pos: &mu
debug_assert!(check_call_signature(dfg, inst).is_ok(),
"Signature still wrong: {}, {}{}",
dfg.display_inst(inst),
dfg.display_inst(inst, None),
sig_ref,
dfg.signatures[sig_ref]);
@@ -523,7 +523,7 @@ pub fn handle_return_abi(dfg: &mut DataFlowGraph,
if special_args > 0 {
dbg!("Adding {} special-purpose arguments to {}",
special_args,
dfg.display_inst(inst));
dfg.display_inst(inst, None));
let mut vlist = dfg[inst].take_value_list().unwrap();
for arg in &sig.return_types[abi_args..] {
match arg.purpose {
@@ -550,7 +550,7 @@ pub fn handle_return_abi(dfg: &mut DataFlowGraph,
debug_assert!(check_return_signature(dfg, inst, sig),
"Signature still wrong: {} / signature {}",
dfg.display_inst(inst),
dfg.display_inst(inst, None),
sig);
// Yes, we changed stuff.

View File

@@ -123,7 +123,7 @@ fn split_any(dfg: &mut DataFlowGraph,
let branch_opc = dfg[inst].opcode();
assert!(branch_opc.is_branch(),
"Predecessor not a branch: {}",
dfg.display_inst(inst));
dfg.display_inst(inst, None));
let fixed_args = branch_opc.constraints().fixed_value_arguments();
let mut args = dfg[inst]
.take_value_list()

View File

@@ -399,7 +399,7 @@ impl<'a> Context<'a> {
dbg!("Checking {}: {}: {}",
pred_val,
pred_ebb,
self.func.dfg.display_inst(pred_inst));
self.func.dfg.display_inst(pred_inst, self.isa));
// Never coalesce incoming function arguments on the stack. These arguments are
// pre-spilled, and the rest of the virtual register would be forced to spill to the
@@ -474,9 +474,9 @@ impl<'a> Context<'a> {
let ty = self.func.dfg.value_type(copy);
dbg!("Inserted {}, before {}: {}",
self.func.dfg.display_inst(inst),
self.func.dfg.display_inst(inst, self.isa),
pred_ebb,
self.func.dfg.display_inst(pred_inst));
self.func.dfg.display_inst(pred_inst, self.isa));
// Give it an encoding.
let encoding = self.isa
@@ -519,7 +519,7 @@ impl<'a> Context<'a> {
self.liveness.move_def_locally(succ_val, inst);
dbg!("Inserted {}, following {}({}: {})",
self.func.dfg.display_inst(inst),
self.func.dfg.display_inst(inst, self.isa),
ebb,
new_val,
ty);

View File

@@ -73,6 +73,7 @@ pub struct Coloring {
/// Immutable context information and mutable references that don't need to be borrowed across
/// method calls should go in this struct.
struct Context<'a> {
isa: &'a TargetIsa,
// Cached ISA information.
// We save it here to avoid frequent virtual function calls on the `TargetIsa` trait object.
reginfo: RegInfo,
@@ -111,6 +112,7 @@ impl Coloring {
tracker: &mut LiveValueTracker) {
dbg!("Coloring for:\n{}", func.display(isa));
let mut ctx = Context {
isa,
reginfo: isa.register_info(),
encinfo: isa.encoding_info(),
domtree,
@@ -279,7 +281,7 @@ impl<'a> Context<'a> {
locations: &mut ValueLocations,
func_signature: &Signature) {
dbg!("Coloring {}\n {}",
dfg.display_inst(inst),
dfg.display_inst(inst, self.isa),
regs.display(&self.reginfo));
// EBB whose arguments should be colored to match the current branch instruction's
@@ -308,7 +310,7 @@ impl<'a> Context<'a> {
assert_eq!(dfg.inst_variable_args(inst).len(),
0,
"Can't handle EBB arguments: {}",
dfg.display_inst(inst));
dfg.display_inst(inst, self.isa));
self.undivert_regs(|lr| !lr.is_local());
}
}

View File

@@ -246,7 +246,9 @@ impl<'a> Context<'a> {
pos: &mut Cursor,
dfg: &mut DataFlowGraph,
tracker: &mut LiveValueTracker) {
dbg!("Inst {}, {}", dfg.display_inst(inst), self.pressure);
dbg!("Inst {}, {}",
dfg.display_inst(inst, self.isa),
self.pressure);
// We may need to resolve register constraints if there are any noteworthy uses.
assert!(self.reg_uses.is_empty());
@@ -292,7 +294,7 @@ impl<'a> Context<'a> {
None => {
panic!("Ran out of {} registers for {}",
op.regclass,
dfg.display_inst(inst))
dfg.display_inst(inst, self.isa))
}
}
}
@@ -429,7 +431,7 @@ impl<'a> Context<'a> {
None => {
panic!("Ran out of {} registers when inserting copy before {}",
rc,
dfg.display_inst(inst))
dfg.display_inst(inst, self.isa))
}
}
}