diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs index 4339092b63e85..29ec3572016d7 100644 --- a/compiler/rustc_graphviz/src/lib.rs +++ b/compiler/rustc_graphviz/src/lib.rs @@ -599,6 +599,7 @@ pub enum RenderOption { NoNodeStyles, Monospace, + DarkTheme, } /// Returns vec holding all the default render options. @@ -630,10 +631,23 @@ where writeln!(w, "digraph {} {{", g.graph_id().as_slice())?; // Global graph properties + let mut graph_attrs = Vec::new(); + let mut content_attrs = Vec::new(); if options.contains(&RenderOption::Monospace) { - writeln!(w, r#" graph[fontname="monospace"];"#)?; - writeln!(w, r#" node[fontname="monospace"];"#)?; - writeln!(w, r#" edge[fontname="monospace"];"#)?; + let font = r#"fontname="Courier, monospace""#; + graph_attrs.push(font); + content_attrs.push(font); + }; + if options.contains(&RenderOption::DarkTheme) { + graph_attrs.push(r#"bgcolor="black""#); + content_attrs.push(r#"color="white""#); + content_attrs.push(r#"fontcolor="white""#); + } + if !(graph_attrs.is_empty() && content_attrs.is_empty()) { + writeln!(w, r#" graph[{}];"#, graph_attrs.join(" "))?; + let content_attrs_str = content_attrs.join(" "); + writeln!(w, r#" node[{}];"#, content_attrs_str)?; + writeln!(w, r#" edge[{}];"#, content_attrs_str)?; } for n in g.nodes().iter() { diff --git a/compiler/rustc_mir/src/dataflow/framework/engine.rs b/compiler/rustc_mir/src/dataflow/framework/engine.rs index d3ad42f6bbcce..0b5b437d186aa 100644 --- a/compiler/rustc_mir/src/dataflow/framework/engine.rs +++ b/compiler/rustc_mir/src/dataflow/framework/engine.rs @@ -306,7 +306,11 @@ where let mut buf = Vec::new(); let graphviz = graphviz::Formatter::new(body, def_id, results, style); - dot::render_opts(&graphviz, &mut buf, &[dot::RenderOption::Monospace])?; + let mut render_opts = vec![dot::RenderOption::Monospace]; + if tcx.sess.opts.debugging_opts.graphviz_dark_mode { + render_opts.push(dot::RenderOption::DarkTheme); + } + dot::render_opts(&graphviz, &mut buf, &render_opts)?; if let Some(parent) = path.parent() { fs::create_dir_all(parent)?; diff --git a/compiler/rustc_mir/src/util/graphviz.rs b/compiler/rustc_mir/src/util/graphviz.rs index 50193c4a0db7d..e89c943770638 100644 --- a/compiler/rustc_mir/src/util/graphviz.rs +++ b/compiler/rustc_mir/src/util/graphviz.rs @@ -55,16 +55,28 @@ where writeln!(w, "{} {}Mir_{} {{", kind, cluster, def_name)?; // Global graph properties - writeln!(w, r#" graph [fontname="monospace"];"#)?; - writeln!(w, r#" node [fontname="monospace"];"#)?; - writeln!(w, r#" edge [fontname="monospace"];"#)?; + let font = r#"fontname="Courier, monospace""#; + let mut graph_attrs = vec![font]; + let mut content_attrs = vec![font]; + + let dark_mode = tcx.sess.opts.debugging_opts.graphviz_dark_mode; + if dark_mode { + graph_attrs.push(r#"bgcolor="black""#); + content_attrs.push(r#"color="white""#); + content_attrs.push(r#"fontcolor="white""#); + } + + writeln!(w, r#" graph [{}];"#, graph_attrs.join(" "))?; + let content_attrs_str = content_attrs.join(" "); + writeln!(w, r#" node [{}];"#, content_attrs_str)?; + writeln!(w, r#" edge [{}];"#, content_attrs_str)?; // Graph label write_graph_label(tcx, def_id, body, w)?; // Nodes for (block, _) in body.basic_blocks().iter_enumerated() { - write_node(def_id, block, body, w)?; + write_node(def_id, block, body, dark_mode, w)?; } // Edges @@ -84,6 +96,7 @@ where pub fn write_node_label( block: BasicBlock, body: &Body<'_>, + dark_mode: bool, w: &mut W, num_cols: u32, init: INIT, @@ -100,8 +113,9 @@ where // Basic block number at the top. write!( w, - r#"{blk}"#, - attrs = r#"bgcolor="gray" align="center""#, + r#"{blk}"#, + bgcolor = if dark_mode { "dimgray" } else { "gray" }, + attrs = r#"align="center""#, colspan = num_cols, blk = block.index() )?; @@ -134,11 +148,12 @@ fn write_node( def_id: DefId, block: BasicBlock, body: &Body<'_>, + dark_mode: bool, w: &mut W, ) -> io::Result<()> { // Start a new node with the label to follow, in one of DOT's pseudo-HTML tables. write!(w, r#" {} [shape="none", label=<"#, node(def_id, block))?; - write_node_label(block, body, w, 1, |_| Ok(()), |_| Ok(()))?; + write_node_label(block, body, dark_mode, w, 1, |_| Ok(()), |_| Ok(()))?; // Close the node label and the node itself. writeln!(w, ">];") } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 848c7cb7d7552..c5050dbea7339 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -909,6 +909,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "force all crates to be `rustc_private` unstable (default: no)"), fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED], "set the optimization fuel quota for a crate"), + graphviz_dark_mode: bool = (false, parse_bool, [UNTRACKED], + "use dark-themed colors in graphviz output (default: no)"), hir_stats: bool = (false, parse_bool, [UNTRACKED], "print some statistics about AST and HIR (default: no)"), human_readable_cgu_names: bool = (false, parse_bool, [TRACKED], diff --git a/src/test/mir-opt/graphviz.main.mir_map.0.dot b/src/test/mir-opt/graphviz.main.mir_map.0.dot index f5d8b84812a3e..df4f11f0f2169 100644 --- a/src/test/mir-opt/graphviz.main.mir_map.0.dot +++ b/src/test/mir-opt/graphviz.main.mir_map.0.dot @@ -1,7 +1,7 @@ digraph Mir_0_3 { - graph [fontname="monospace"]; - node [fontname="monospace"]; - edge [fontname="monospace"]; + graph [fontname="Courier, monospace"]; + node [fontname="Courier, monospace"]; + edge [fontname="Courier, monospace"]; label=>; bb0__0_3 [shape="none", label=<
0
_0 = const ()
goto
>]; bb1__0_3 [shape="none", label=<
1
resume
>];