Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement graphviz #23

Merged
merged 11 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/codegen/src/critical_edge.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::cfg::ControlFlowGraph;
use sonatina_ir::ControlFlowGraph;

use sonatina_ir::{
func_cursor::{CursorLocation, FuncCursor, InsnInserter},
Expand Down
4 changes: 1 addition & 3 deletions crates/codegen/src/domtree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ use std::collections::BTreeSet;

use cranelift_entity::{packed_option::PackedOption, SecondaryMap};

use sonatina_ir::Block;

use super::cfg::ControlFlowGraph;
use sonatina_ir::{Block, ControlFlowGraph};

#[derive(Default, Debug)]
pub struct DomTree {
Expand Down
1 change: 0 additions & 1 deletion crates/codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// See <https://github.com/rust-lang/rust-clippy/issues/7512> and <https://github.com/rust-lang/rust-clippy/issues/7336>
#![allow(clippy::needless_collect)]

pub mod cfg;
pub mod critical_edge;
pub mod domtree;
pub mod loop_analysis;
Expand Down
4 changes: 2 additions & 2 deletions crates/codegen/src/loop_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use cranelift_entity::{entity_impl, packed_option::PackedOption, PrimaryMap, Sec
use fxhash::FxHashMap;
use smallvec::SmallVec;

use crate::{cfg::ControlFlowGraph, domtree::DomTree};
use crate::domtree::DomTree;

use sonatina_ir::Block;
use sonatina_ir::{Block, ControlFlowGraph};

#[derive(Debug, Default)]
pub struct LoopTree {
Expand Down
7 changes: 2 additions & 5 deletions crates/codegen/src/optim/gvn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,12 @@ use std::collections::BTreeSet;
use cranelift_entity::{entity_impl, packed_option::PackedOption, PrimaryMap, SecondaryMap};
use fxhash::{FxHashMap, FxHashSet};

use crate::{
cfg::ControlFlowGraph,
domtree::{DomTree, DominatorTreeTraversable},
};
use crate::domtree::{DomTree, DominatorTreeTraversable};

use sonatina_ir::{
func_cursor::{CursorLocation, FuncCursor, InsnInserter},
insn::{BinaryOp, CastOp, InsnData, UnaryOp},
Block, DataFlowGraph, Function, Immediate, Insn, Type, Value,
Block, ControlFlowGraph, DataFlowGraph, Function, Immediate, Insn, Type, Value,
};

use super::{constant_folding, simplify_impl};
Expand Down
7 changes: 2 additions & 5 deletions crates/codegen/src/optim/licm.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
// TODO: Add control flow hoisting.
use fxhash::{FxHashMap, FxHashSet};

use crate::{
cfg::ControlFlowGraph,
loop_analysis::{Loop, LoopTree},
};
use crate::loop_analysis::{Loop, LoopTree};

use sonatina_ir::{
func_cursor::{CursorLocation, FuncCursor, InsnInserter},
Block, Function, Insn, InsnData, Value,
Block, ControlFlowGraph, Function, Insn, InsnData, Value,
};

#[derive(Debug)]
Expand Down
4 changes: 1 addition & 3 deletions crates/codegen/src/optim/sccp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,10 @@ use std::{collections::BTreeSet, ops};

use cranelift_entity::SecondaryMap;

use crate::cfg::ControlFlowGraph;

use sonatina_ir::{
func_cursor::{CursorLocation, FuncCursor, InsnInserter},
insn::{BinaryOp, CastOp, InsnData, UnaryOp},
Block, Function, Immediate, Insn, Type, Value,
Block, ControlFlowGraph, Function, Immediate, Insn, Type, Value,
};

#[derive(Debug)]
Expand Down
7 changes: 2 additions & 5 deletions crates/codegen/src/post_domtree.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
//! This module contains implementation of `Post Dominator Tree`.

use super::{
cfg::ControlFlowGraph,
domtree::{DFSet, DomTree},
};
use super::domtree::{DFSet, DomTree};

use sonatina_ir::{Block, Function};
use sonatina_ir::{Block, ControlFlowGraph, Function};

#[derive(Debug)]
pub struct PostDomTree {
Expand Down
4 changes: 2 additions & 2 deletions crates/filecheck/src/gvn.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::path::{Path, PathBuf};

use sonatina_codegen::{cfg::ControlFlowGraph, domtree::DomTree, optim::gvn::GvnSolver};
use sonatina_codegen::{domtree::DomTree, optim::gvn::GvnSolver};

use sonatina_ir::Function;
use sonatina_ir::{ControlFlowGraph, Function};

use super::{FuncTransform, FIXTURE_ROOT};

Expand Down
6 changes: 2 additions & 4 deletions crates/filecheck/src/licm.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use std::path::{Path, PathBuf};

use sonatina_codegen::{
cfg::ControlFlowGraph, domtree::DomTree, loop_analysis::LoopTree, optim::licm::LicmSolver,
};
use sonatina_codegen::{domtree::DomTree, loop_analysis::LoopTree, optim::licm::LicmSolver};

use sonatina_ir::Function;
use sonatina_ir::{ControlFlowGraph, Function};

use super::{FuncTransform, FIXTURE_ROOT};

Expand Down
4 changes: 2 additions & 2 deletions crates/filecheck/src/sccp.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::path::{Path, PathBuf};

use sonatina_codegen::{cfg::ControlFlowGraph, optim::sccp::SccpSolver};
use sonatina_codegen::optim::sccp::SccpSolver;

use sonatina_ir::Function;
use sonatina_ir::{ControlFlowGraph, Function};

use super::{FuncTransform, FIXTURE_ROOT};

Expand Down
1 change: 1 addition & 0 deletions crates/ir/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ fxhash = "0.2.1"
dyn-clone = "1.0.4"
sonatina-triple = { path = "../triple", version = "0.0.3-alpha" }
indexmap = "2.0.0"
dot2 = { git = "https://github.com/sanpii/dot2.rs.git" }
6 changes: 3 additions & 3 deletions crates/codegen/src/cfg.rs → crates/ir/src/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ use std::collections::BTreeSet;

use cranelift_entity::{packed_option::PackedOption, SecondaryMap};

use sonatina_ir::{Block, Function, Insn};
use crate::{Block, Function, Insn};

#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct ControlFlowGraph {
entry: PackedOption<Block>,
blocks: SecondaryMap<Block, BlockNode>,
pub(super) exits: smallvec::SmallVec<[Block; 8]>,
pub exits: smallvec::SmallVec<[Block; 8]>,
}

impl ControlFlowGraph {
Expand Down Expand Up @@ -62,7 +62,7 @@ impl ControlFlowGraph {
self.blocks[from].remove_succ(to);
}

pub(super) fn reverse_edges(&mut self, new_entry: Block, new_exits: &[Block]) {
pub fn reverse_edges(&mut self, new_entry: Block, new_exits: &[Block]) {
for node in self.blocks.values_mut() {
node.reverse_edge();
}
Expand Down
8 changes: 7 additions & 1 deletion crates/ir/src/dfg.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! This module contains Sonatine IR data flow graph.
use std::{collections::BTreeSet, fmt};

use cranelift_entity::{packed_option::PackedOption, PrimaryMap, SecondaryMap};
use fxhash::FxHashMap;
use std::collections::BTreeSet;

use crate::{global_variable::ConstantValue, module::ModuleCtx, GlobalVariable};

Expand Down Expand Up @@ -308,6 +308,12 @@ pub enum ValueDef {
pub struct Block(pub u32);
cranelift_entity::entity_impl!(Block);

impl fmt::Display for Block {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "block{}", self.0)
}
}

/// A block data definition.
/// A Block data doesn't hold any information for layout of a program. It is managed by
/// [`super::layout::Layout`].
Expand Down
38 changes: 37 additions & 1 deletion crates/ir/src/function.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::fmt::{self, Write};

use fxhash::FxHashMap;
use smallvec::SmallVec;

use crate::{module::ModuleCtx, Linkage};
use crate::{module::ModuleCtx, types::DisplayType, Linkage};

use super::{module::FuncRef, DataFlowGraph, Layout, Type, Value};

Expand Down Expand Up @@ -87,3 +89,37 @@ impl Signature {
self.ret_ty = ty;
}
}

pub struct DisplaySignature<'a> {
sig: &'a Signature,
dfg: &'a DataFlowGraph,
}

impl<'a> DisplaySignature<'a> {
pub fn new(sig: &'a Signature, dfg: &'a DataFlowGraph) -> Self {
Self { sig, dfg }
}
}

impl<'a> fmt::Display for DisplaySignature<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let Self { sig, dfg } = *self;
let Signature {
name,
linkage,
args,
ret_ty,
} = sig;

let mut args_ty = String::new();
for arg_ty in args {
let ty = DisplayType::new(*arg_ty, dfg);
write!(&mut args_ty, "{ty} ")?;
}
let args_ty = args_ty.trim();

let ret_ty = DisplayType::new(*ret_ty, dfg);

write!(f, "func {linkage} %{name}({args_ty}) -> {ret_ty}")
}
}
67 changes: 67 additions & 0 deletions crates/ir/src/graphviz/block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use std::fmt::Write;

use dot2::label;

use crate::{function::DisplaySignature, insn::DisplayInsn, Block, ControlFlowGraph, Function};

use super::function::DUMMY_BLOCK;

#[derive(Debug, Clone, Copy)]
pub(super) struct BlockNode<'a> {
pub(super) func: &'a Function,
pub(super) cfg: &'a ControlFlowGraph,
pub(super) block: Block,
}

impl<'a> BlockNode<'a> {
pub(super) fn new(func: &'a Function, cfg: &'a ControlFlowGraph, block: Block) -> Self {
Self { func, cfg, block }
}

pub(super) fn succs(self) -> Vec<Self> {
let mut cfg = ControlFlowGraph::new();
cfg.compute(self.func);
k0aki marked this conversation as resolved.
Show resolved Hide resolved
cfg.succs_of(self.block)
.map(|block| BlockNode::new(self.func, self.cfg, *block))
.collect()
k0aki marked this conversation as resolved.
Show resolved Hide resolved
}
}

impl<'a> BlockNode<'a> {
pub(super) fn label(self) -> label::Text<'static> {
let Self { block, func, .. } = self;
let Function {
sig, dfg, layout, ..
} = func;
if block == DUMMY_BLOCK {
let sig = DisplaySignature::new(sig, dfg);
return label::Text::LabelStr(format!("{sig}").into());
}

let mut label = r#"<table border="0" cellborder="1" cellspacing="0">"#.to_string();

// Write block header.
write!(
&mut label,
r#"<tr><td bgcolor="gray" align="center" colspan="1">{}</td></tr>"#,
block
)
.unwrap();

// Write block body.
write!(label, r#"<tr><td align="left" balign="left">"#).unwrap();
for insn in layout.iter_insn(self.block) {
let display_insn = DisplayInsn::new(insn, func);
let mut insn_string = String::new();
write!(&mut insn_string, "{}", display_insn).unwrap();

write!(label, "{}", dot2::escape_html(&insn_string)).unwrap();
write!(label, "<br/>").unwrap();
}
write!(label, r#"</td></tr>"#).unwrap();

write!(label, "</table>").unwrap();

label::Text::HtmlStr(label.into())
}
}
Loading
Loading