diff --git a/hercules_cg/src/lib.rs b/hercules_cg/src/lib.rs index a70effb5fdaf96c066683735226779cb23d9c020..8aaab214e478ddd1d0e68878894b1d4bbaf2a965 100644 --- a/hercules_cg/src/lib.rs +++ b/hercules_cg/src/lib.rs @@ -10,18 +10,6 @@ pub use crate::rt::*; use hercules_ir::*; -/* - * Basic block info consists of two things: - * - * 1. A map from node to block (named by control nodes). - * 2. For each node, which nodes are in its own block. - * - * Note that for #2, the structure is Vec<NodeID>, meaning the nodes are ordered - * inside the block. This order corresponds to the traversal order of the nodes - * in the block needed by the backend code generators. - */ -pub type BasicBlocks = (Vec<NodeID>, Vec<Vec<NodeID>>); - /* * The alignment of a type does not depend on dynamic constants. */ diff --git a/hercules_ir/src/dot.rs b/hercules_ir/src/dot.rs index 4d526366808e8b2aea39fecd81f6c00269ffb154..9dd2cb1e4c0ae76ac2d60bb9e638d95cca646016 100644 --- a/hercules_ir/src/dot.rs +++ b/hercules_ir/src/dot.rs @@ -18,6 +18,7 @@ pub fn xdot_module( reverse_postorders: &Vec<Vec<NodeID>>, doms: Option<&Vec<DomTree>>, fork_join_maps: Option<&Vec<HashMap<NodeID, NodeID>>>, + bbs: Option<&Vec<BasicBlocks>>, ) { let mut tmp_path = temp_dir(); let mut rng = rand::thread_rng(); @@ -30,6 +31,7 @@ pub fn xdot_module( &reverse_postorders, doms, fork_join_maps, + bbs, &mut contents, ) .expect("PANIC: Unable to generate output file contents."); @@ -51,6 +53,7 @@ pub fn write_dot<W: Write>( reverse_postorders: &Vec<Vec<NodeID>>, doms: Option<&Vec<DomTree>>, fork_join_maps: Option<&Vec<HashMap<NodeID, NodeID>>>, + bbs: Option<&Vec<BasicBlocks>>, w: &mut W, ) -> std::fmt::Result { write_digraph_header(w)?; @@ -165,6 +168,26 @@ pub fn write_dot<W: Write>( } } + // Step 4: draw basic block edges in indigo. + if let Some(bbs) = bbs { + let bbs = &bbs[function_id.idx()].0; + for (idx, bb) in bbs.into_iter().enumerate() { + if idx != bb.idx() { + write_edge( + NodeID::new(idx), + function_id, + *bb, + function_id, + true, + "indigo", + "dotted", + &module, + w, + )?; + } + } + } + write_graph_footer(w)?; } diff --git a/hercules_ir/src/ir.rs b/hercules_ir/src/ir.rs index d1fdd225a7b5da380c6956aec9c6f8d7f272531d..46d35f25205d50494829777106035ee1c4b683cb 100644 --- a/hercules_ir/src/ir.rs +++ b/hercules_ir/src/ir.rs @@ -351,6 +351,18 @@ pub type FunctionSchedules = Vec<Vec<Schedule>>; */ pub type FunctionLabels = Vec<HashSet<LabelID>>; +/* + * Basic block info consists of two things: + * + * 1. A map from node to block (named by control nodes). + * 2. For each node, which nodes are in its own block. + * + * Note that for #2, the structure is Vec<NodeID>, meaning the nodes are ordered + * inside the block. This order corresponds to the traversal order of the nodes + * in the block needed by the backend code generators. + */ +pub type BasicBlocks = (Vec<NodeID>, Vec<Vec<NodeID>>); + impl Module { /* * Printing out types, constants, and dynamic constants fully requires a diff --git a/juno_scheduler/src/pm.rs b/juno_scheduler/src/pm.rs index e93e7ecbb304f4f5eb8e96f72f02f13ca4f78d77..43fba4fde2f540db625cf5012b9ec776864f1cf8 100644 --- a/juno_scheduler/src/pm.rs +++ b/juno_scheduler/src/pm.rs @@ -1529,15 +1529,15 @@ fn run_pass( pm.fork_join_maps = Some(fork_join_maps); } Pass::Xdot => { - assert!(args.len() == 1); - let force_analyses = match args[0] { - Value::Boolean { val } => val, - _ => { + let force_analyses = match args.get(0) { + Some(Value::Boolean { val }) => *val, + Some(_) => { return Err(SchedulerError::PassError { pass: "xdot".to_string(), error: "expected boolean argument".to_string(), }); } + None => true, }; pm.make_reverse_postorders(); @@ -1549,14 +1549,19 @@ fn run_pass( let reverse_postorders = pm.reverse_postorders.take().unwrap(); let doms = pm.doms.take(); let fork_join_maps = pm.fork_join_maps.take(); + let bbs = pm.bbs.take(); pm.with_mod(|module| { xdot_module( module, &reverse_postorders, doms.as_ref(), fork_join_maps.as_ref(), + bbs.as_ref(), ) }); + + // Put BasicBlocks back, since it's needed for Codegen. + pm.bbs = bbs; } }