Skip to content

Commit

Permalink
rustc_driver: add env var RUSTC_PRETTY_DUMP=mode:dir which acts like …
Browse files Browse the repository at this point in the history
…--xpretty=mode -Z pretty-keep-going -Z pretty-dump-dir=dir.
  • Loading branch information
eddyb committed Mar 4, 2015
1 parent c082ee2 commit 496c8ba
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 67 deletions.
56 changes: 9 additions & 47 deletions src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ use std::cmp::Ordering::Equal;
use std::old_io::{self, stdio};
use std::iter::repeat;
use std::env;
use std::os;
use std::sync::mpsc::channel;
use std::thread;

Expand Down Expand Up @@ -236,8 +235,7 @@ pub trait CompilerCalls<'a> {
// CompilerCalls instance for a regular rustc build.
pub struct RustcDefaultCalls {
save_analysis: bool,
pretty_print: Option<(PpMode, Option<UserIdentifiedItem>)>,
pretty_dump_dir: Option<Path>
pretty_print: Option<(PpMode, Option<UserIdentifiedItem>)>
}

impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
Expand Down Expand Up @@ -305,19 +303,13 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
if sess.unstable_options() {
self.pretty_print = matches.opt_default("pretty", "normal").map(|a| {
// stable pretty-print variants only
pretty::parse_pretty(sess, &a, false)
pretty::parse_pretty(&a, false).unwrap_or_else(|e| sess.fatal(&e))
}).or_else(|| matches.opt_str("xpretty").map(|a| {
// extended with unstable pretty-print variants
pretty::parse_pretty(sess, &a, true)
pretty::parse_pretty(&a, true).unwrap_or_else(|e| sess.fatal(&e))
}));
}

if let Some(ref dir) = sess.opts.debugging_opts.pretty_dump_dir {
let pretty_dump_dir = os::getcwd().unwrap().join(dir);
assert!(pretty_dump_dir.is_absolute());
self.pretty_dump_dir = Some(pretty_dump_dir);
}

RustcDefaultCalls::print_crate_info(sess, Some(input), odir, ofile).and_then(
|| RustcDefaultCalls::list_metadata(sess, matches, input))
}
Expand All @@ -343,40 +335,11 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
control.after_llvm.stop = Compilation::Stop;
}

if let Some((ppm, opt_uii)) = self.pretty_print.take() {
let phase = pretty::printing_phase(&mut control, ppm, opt_uii.as_ref());

let dump_dir = self.pretty_dump_dir.take();
phase.callback = box move |state| {
let pretty_output_path;
let output = if let Some(ref dir) = dump_dir {
let file_path = if let Some(outputs) = state.output_filenames {
outputs.with_extension("rs")
} else {
state.session.fatal(
"-Z pretty-dump-dir cannot be used with --pretty \
options that print before expansion");
};
let file_path = os::getcwd().unwrap().join(&file_path);
assert!(file_path.is_absolute());

// Cheap isomorphism: /foo/bar--bar/baz <-> foo--bar----bar--baz.
let components: Vec<_> = file_path.components().map(|bytes| {
String::from_utf8_lossy(bytes).replace("--", "----")
}).collect();

pretty_output_path = dir.join(components.connect("--"));
Some(&pretty_output_path)
} else {
state.output
};
pretty::print_from_phase(state, ppm, opt_uii.as_ref(), output).unwrap();
};

if !sess.opts.debugging_opts.pretty_keep_going {
phase.stop = Compilation::Stop;
}
}
pretty::setup_controller(&mut control,
self.pretty_print.take(),
sess.opts.debugging_opts.pretty_dump_dir
.as_ref().map(|s| &s[..]),
sess.opts.debugging_opts.pretty_keep_going);

if self.save_analysis {
control.after_analysis.callback = box |state| {
Expand All @@ -398,8 +361,7 @@ impl RustcDefaultCalls {
pub fn new() -> RustcDefaultCalls {
RustcDefaultCalls {
save_analysis: false,
pretty_print: None,
pretty_dump_dir: None
pretty_print: None
}
}

Expand Down
102 changes: 82 additions & 20 deletions src/librustc_driver/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ use syntax::ptr::P;
use graphviz as dot;

use std::borrow::{Cow, IntoCow};
use std::env;
use std::old_io::{self, BufReader};
use std::option;
use std::os;
use std::str::FromStr;

#[derive(Copy, PartialEq, Debug)]
Expand Down Expand Up @@ -67,9 +69,8 @@ pub enum PpMode {
PpmFlowGraph(PpFlowGraphMode),
}

pub fn parse_pretty(sess: &Session,
name: &str,
extended: bool) -> (PpMode, Option<UserIdentifiedItem>) {
pub fn parse_pretty(name: &str, extended: bool)
-> Result<(PpMode, Option<UserIdentifiedItem>), String> {
let mut split = name.splitn(1, '=');
let first = split.next().unwrap();
let opt_second = split.next();
Expand All @@ -84,23 +85,23 @@ pub fn parse_pretty(sess: &Session,
("identified", _) => PpmSource(PpmIdentified),
("flowgraph", true) => PpmFlowGraph(PpFlowGraphMode::Default),
("flowgraph,unlabelled", true) => PpmFlowGraph(PpFlowGraphMode::UnlabelledEdges),
_ => {
_ => return Err({
if extended {
sess.fatal(&format!(
format!(
"argument to `xpretty` must be one of `normal`, \
`expanded`, `flowgraph[,unlabelled]=<nodeid>`, `typed`, \
`typed,unsuffixed_literals`, `identified`, \
`expanded,identified`, or `everybody_loops`; got {}", name));
`expanded,identified`, or `everybody_loops`; got {}", name)
} else {
sess.fatal(&format!(
format!(
"argument to `pretty` must be one of `normal`, \
`expanded`, `typed`, `identified`, \
or `expanded,identified`; got {}", name));
or `expanded,identified`; got {}", name)
}
}
})
};
let opt_second = opt_second.and_then(|s| s.parse::<UserIdentifiedItem>().ok());
(first, opt_second)
Ok((first, opt_second))
}

struct NoAnn;
Expand Down Expand Up @@ -391,15 +392,46 @@ impl fold::Folder for ReplaceBodyWithLoop {
}
}

pub fn printing_phase<'a, 'b>(control: &'a mut driver::CompileController<'b>,
ppm: PpMode,
opt_uii: Option<&UserIdentifiedItem>)
-> &'a mut driver::PhaseController<'b> {
pub fn setup_controller(control: &mut driver::CompileController,
ppm_and_uui: Option<(PpMode, Option<UserIdentifiedItem>)>,
dump_dir: Option<&str>,
keep_going: bool) {

fn mk_absolute(path: &str) -> Path {
let path = os::getcwd().unwrap().join(path);
assert!(path.is_absolute());
path
}

let (ppm, opt_uii, dump_dir, keep_going) = match ppm_and_uui {
Some((ppm, opt_uii)) => {
(ppm, opt_uii, dump_dir.map(mk_absolute), keep_going)
}
None => {
let decoded = env::var("RUSTC_PRETTY_DUMP").ok().and_then(|s| {
let mut s = s.split(":");

s.next().and_then(|mode| {
parse_pretty(mode, true).ok()
}).and_then(|(ppm, opt_uii)| {
s.next().map(|dump_dir| {
(ppm, opt_uii, Some(mk_absolute(dump_dir)), true)
})
})
});
if let Some(parts) = decoded {
parts
} else {
return;
}
}
};

if ppm == PpmSource(PpmEveryBodyLoops) {
control.every_body_loops = true;
}

match ppm {
let phase = match ppm {
PpmSource(PpmNormal) |
PpmSource(PpmEveryBodyLoops) |
PpmSource(PpmIdentified) => {
Expand All @@ -421,14 +453,44 @@ pub fn printing_phase<'a, 'b>(control: &'a mut driver::CompileController<'b>,
PpmFlowGraph(_) => {
&mut control.after_analysis
}
};

phase.callback = box move |state| {
let pretty_output_path;
let output = if let Some(ref dir) = dump_dir {
let file_path = if let Some(outputs) = state.output_filenames {
outputs.with_extension("rs")
} else {
state.session.fatal(
"-Z pretty-dump-dir cannot be used with --pretty \
options that print before expansion");
};
let file_path = os::getcwd().unwrap().join(&file_path);
assert!(file_path.is_absolute());

// Cheap isomorphism: /foo/bar--bar/baz <-> foo--bar----bar--baz.
let components: Vec<_> = file_path.components().map(|bytes| {
String::from_utf8_lossy(bytes).replace("--", "----")
}).collect();

pretty_output_path = dir.join(components.connect("--"));
Some(&pretty_output_path)
} else {
state.output
};
print_from_phase(state, ppm, opt_uii.as_ref(), output).unwrap();
};

if !keep_going {
phase.stop = ::Compilation::Stop;
}
}

pub fn print_from_phase(state: driver::CompileState,
ppm: PpMode,
opt_uii: Option<&UserIdentifiedItem>,
output: Option<&Path>)
-> old_io::IoResult<()> {
fn print_from_phase(state: driver::CompileState,
ppm: PpMode,
opt_uii: Option<&UserIdentifiedItem>,
output: Option<&Path>)
-> old_io::IoResult<()> {
let sess = state.session;
let krate = state.krate.or(state.expanded_crate)
.expect("--pretty=typed missing crate");
Expand Down

0 comments on commit 496c8ba

Please sign in to comment.