From 15de8fdeef99e34182a99e06b7c155b52ccd8f39 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Wed, 25 Sep 2024 16:10:36 +0200 Subject: [PATCH] Fix graphviz module --- crates/ir/src/func_cursor.rs | 3 +- crates/ir/src/function.rs | 2 +- crates/ir/src/graphviz/block.rs | 20 ++++-- crates/ir/src/graphviz/mod.rs | 114 +++++++++++++++----------------- crates/ir/src/ir_writer.rs | 4 +- 5 files changed, 75 insertions(+), 68 deletions(-) diff --git a/crates/ir/src/func_cursor.rs b/crates/ir/src/func_cursor.rs index 12fa02e..65760d4 100644 --- a/crates/ir/src/func_cursor.rs +++ b/crates/ir/src/func_cursor.rs @@ -70,10 +70,11 @@ pub trait FuncCursor { fn remove_inst(&mut self, func: &mut Function) { let inst_id = self.expect_inst(); + let next_loc = self.next_loc(func); + func.dfg.untrack_inst(inst_id); func.layout.remove_inst(inst_id); - let next_loc = self.next_loc(func); self.set_location(next_loc); } diff --git a/crates/ir/src/function.rs b/crates/ir/src/function.rs index 3f049fd..ce339da 100644 --- a/crates/ir/src/function.rs +++ b/crates/ir/src/function.rs @@ -111,6 +111,6 @@ impl DisplayWithFunc for Signature { let args_ty = args_ty.trim(); let ret_ty = DisplayableWithModule(ret_ty, func.ctx()); - write!(formatter, "func {linkage} %{name}({args_ty} -> {ret_ty})") + write!(formatter, "func {linkage} %{name}({args_ty}) -> {ret_ty}") } } diff --git a/crates/ir/src/graphviz/block.rs b/crates/ir/src/graphviz/block.rs index f28dc32..220ba47 100644 --- a/crates/ir/src/graphviz/block.rs +++ b/crates/ir/src/graphviz/block.rs @@ -2,7 +2,10 @@ use std::fmt::Write; use dot2::label; -use crate::{ir_writer::DisplayableWithFunc, BlockId, ControlFlowGraph, Function}; +use crate::{ + ir_writer::{DisplayableWithFunc, ValueWithTy}, + BlockId, ControlFlowGraph, Function, +}; use super::function::DUMMY_BLOCK; @@ -48,11 +51,20 @@ impl<'a> BlockNode<'a> { // Write block body. write!(label, r#""#).unwrap(); for inst in layout.iter_inst(self.block) { + let mut inst_string = String::new(); + if let Some(result) = self.func.dfg.inst_result(inst) { + let result_with_ty = ValueWithTy(result); + write!( + &mut inst_string, + "{} = ", + DisplayableWithFunc(result_with_ty, self.func) + ) + .unwrap(); + } let inst = DisplayableWithFunc(inst, self.func); - let mut insn_string = String::new(); - write!(&mut insn_string, "{}", inst).unwrap(); + write!(&mut inst_string, "{inst};").unwrap(); - write!(label, "{}", dot2::escape_html(&insn_string)).unwrap(); + write!(label, "{}", dot2::escape_html(&inst_string)).unwrap(); write!(label, "
").unwrap(); } write!(label, r#""#).unwrap(); diff --git a/crates/ir/src/graphviz/mod.rs b/crates/ir/src/graphviz/mod.rs index dc80983..3ee04e0 100644 --- a/crates/ir/src/graphviz/mod.rs +++ b/crates/ir/src/graphviz/mod.rs @@ -19,78 +19,72 @@ pub fn render_to(func: &Function, output: &mut W) -> io::Result<() #[cfg(test)] mod test { - - use macros::inst_set; - use crate::{ builder::test_util::test_func_builder, inst::{ arith::Add, control_flow::{Br, Jump, Phi, Return}, }, + isa::Isa, Type, }; use super::*; - #[inst_set(InstKind = "TestInstKind")] - struct TestInstSet(Add, Return, Jump, Phi, Br); - #[test] fn test_dump_ir() { - // let mut builder = test_func_builder(&[Type::I64], Type::Void); - // let is = TestInstSet::new(); - // - // let entry_block = builder.append_block(); - // let then_block = builder.append_block(); - // let else_block = builder.append_block(); - // let merge_block = builder.append_block(); - // - // let arg0 = builder.args()[0]; - // - // builder.switch_to_block(entry_block); - // let br = Br::new(&is, arg0, then_block, else_block); - // builder.insert_inst_no_result(br); - // - // builder.switch_to_block(then_block); - // let v1 = builder.make_imm_value(1i64); - // let jump = Jump::new(&is, merge_block); - // builder.insert_inst_no_result(jump); - // - // builder.switch_to_block(else_block); - // let v2 = builder.make_imm_value(2i64); - // let jump = Jump::new(&is, merge_block); - // builder.insert_inst_no_result(jump); - // - // builder.switch_to_block(merge_block); - // let phi = Phi::new(&is, vec![(v1, then_block), (v2, else_block)], Type::I64); - // let v3 = builder.insert_inst(phi, Type::I64); - // let add = Add::new(&is, v3, arg0); - // builder.insert_inst(add, Type::I64); - // let ret = Return::new(&is, None); - // builder.insert_inst_no_result(ret); - // - // builder.seal_all(); - // let module = builder.finish().build(); - // let func_ref = module.iter_functions().next().unwrap(); - // - // let mut text = vec![]; - // render_to(&module.funcs[func_ref], &mut text).unwrap(); - // let text = String::from_utf8(text).unwrap(); - // - // let expected = "digraph test_func { - // block3[label=<
block3
v3.i64 = phi (1.i64 block1) (2.i64 block2);
v4.i64 = add v3 v0;
ret;
>][shape=\"none\"]; - // block2[label=<
block2
jump block3;
>][shape=\"none\"]; - // block1[label=<
block1
jump block3;
>][shape=\"none\"]; - // block0[label=<
block0
branch v0 block1 block2;
>][shape=\"none\"]; - // dummy_block[label=\"func public %test_func(i64) -> ()\"][shape=\"none\"]; - // dummy_block -> block0[label=\"\"][style=\"invis\"]; - // block2 -> block3[label=\"2.i64\"]; - // block1 -> block3[label=\"1.i64\"]; - // block0 -> block1[label=\"\"]; - // block0 -> block2[label=\"\"]; - //} - //"; - // assert_eq!(text, expected); + let (evm, mut builder) = test_func_builder(&[Type::I64], Type::Void); + let is = evm.inst_set(); + + let entry_block = builder.append_block(); + let then_block = builder.append_block(); + let else_block = builder.append_block(); + let merge_block = builder.append_block(); + + let arg0 = builder.args()[0]; + + builder.switch_to_block(entry_block); + let br = Br::new(is, arg0, then_block, else_block); + builder.insert_inst_no_result(br); + + builder.switch_to_block(then_block); + let v1 = builder.make_imm_value(1i64); + let jump = Jump::new(is, merge_block); + builder.insert_inst_no_result(jump); + + builder.switch_to_block(else_block); + let v2 = builder.make_imm_value(2i64); + let jump = Jump::new(is, merge_block); + builder.insert_inst_no_result(jump); + + builder.switch_to_block(merge_block); + let phi = Phi::new(is, vec![(v1, then_block), (v2, else_block)], Type::I64); + let v3 = builder.insert_inst(phi, Type::I64); + let add = Add::new(is, v3, arg0); + builder.insert_inst(add, Type::I64); + let ret = Return::new(is, None); + builder.insert_inst_no_result(ret); + + builder.seal_all(); + let module = builder.finish().build(); + let func_ref = module.iter_functions().next().unwrap(); + + let mut text = vec![]; + render_to(&module.funcs[func_ref], &mut text).unwrap(); + let text = String::from_utf8(text).unwrap(); + let expected = "digraph test_func { + block3[label=<
block3
v3.i64 = phi (1.i64 block1) (2.i64 block2);
v4.i64 = add v3 v0;
return;
>][shape=\"none\"]; + block2[label=<
block2
jump block3;
>][shape=\"none\"]; + block1[label=<
block1
jump block3;
>][shape=\"none\"]; + block0[label=<
block0
br v0 block1 block2;
>][shape=\"none\"]; + dummy_block[label=\"func public %test_func(i64) -> void\"][shape=\"none\"]; + dummy_block -> block0[label=\"\"][style=\"invis\"]; + block2 -> block3[label=\"2.i64\"]; + block1 -> block3[label=\"1.i64\"]; + block0 -> block1[label=\"\"]; + block0 -> block2[label=\"\"]; +} +"; + assert_eq!(text, expected); } } diff --git a/crates/ir/src/ir_writer.rs b/crates/ir/src/ir_writer.rs index 3b42b7b..e523bcc 100644 --- a/crates/ir/src/ir_writer.rs +++ b/crates/ir/src/ir_writer.rs @@ -70,7 +70,7 @@ impl<'a> FuncDisplayHelper<'a> { Self { func, level: 0 } } - fn display(&mut self, mut f: &mut fmt::Formatter) -> fmt::Result { + fn display(&mut self, f: &mut fmt::Formatter) -> fmt::Result { f.write_fmt(format_args!( "func {} %{}(", self.func.sig.linkage(), @@ -185,7 +185,7 @@ where } #[derive(Clone)] -struct ValueWithTy(ValueId); +pub(super) struct ValueWithTy(pub(super) ValueId); impl DisplayWithFunc for ValueWithTy { fn fmt(&self, func: &Function, formatter: &mut fmt::Formatter) -> fmt::Result {