commit
b8b18aac12
@ -176,15 +176,28 @@ impl Session {
|
|||||||
pub fn abort_if_errors(&self) {
|
pub fn abort_if_errors(&self) {
|
||||||
self.diagnostic().abort_if_errors();
|
self.diagnostic().abort_if_errors();
|
||||||
}
|
}
|
||||||
|
pub fn track_errors<F, T>(&self, f: F) -> Result<T, usize>
|
||||||
|
where F: FnOnce() -> T
|
||||||
|
{
|
||||||
|
let mut count = self.err_count();
|
||||||
|
let result = f();
|
||||||
|
count -= self.err_count();
|
||||||
|
if count == 0 {
|
||||||
|
Ok(result)
|
||||||
|
} else {
|
||||||
|
Err(count)
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn abort_if_new_errors<F, T>(&self, f: F) -> T
|
pub fn abort_if_new_errors<F, T>(&self, f: F) -> T
|
||||||
where F: FnOnce() -> T
|
where F: FnOnce() -> T
|
||||||
{
|
{
|
||||||
let count = self.err_count();
|
match self.track_errors(f) {
|
||||||
let result = f();
|
Ok(result) => result,
|
||||||
if self.err_count() > count {
|
Err(_) => {
|
||||||
self.abort_if_errors();
|
self.abort_if_errors();
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
result
|
|
||||||
}
|
}
|
||||||
pub fn span_warn(&self, sp: Span, msg: &str) {
|
pub fn span_warn(&self, sp: Span, msg: &str) {
|
||||||
self.diagnostic().span_warn(sp, msg)
|
self.diagnostic().span_warn(sp, msg)
|
||||||
|
@ -35,7 +35,7 @@ use rustc_plugin as plugin;
|
|||||||
use rustc_front::hir;
|
use rustc_front::hir;
|
||||||
use rustc_front::lowering::{lower_crate, LoweringContext};
|
use rustc_front::lowering::{lower_crate, LoweringContext};
|
||||||
use rustc_passes::{no_asm, loops, consts, const_fn, rvalues, static_recursion};
|
use rustc_passes::{no_asm, loops, consts, const_fn, rvalues, static_recursion};
|
||||||
use super::Compilation;
|
use super::{Compilation, CompileResult, compile_result_from_err_count};
|
||||||
|
|
||||||
use serialize::json;
|
use serialize::json;
|
||||||
|
|
||||||
@ -57,45 +57,50 @@ use syntax::visit;
|
|||||||
use syntax;
|
use syntax;
|
||||||
use syntax_ext;
|
use syntax_ext;
|
||||||
|
|
||||||
pub fn compile_input(sess: Session,
|
macro_rules! throw_if_errors {
|
||||||
|
($tsess: expr) => {{
|
||||||
|
let err_count = $tsess.err_count();
|
||||||
|
if err_count > 0 {
|
||||||
|
return Err(err_count);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compile_input(sess: &Session,
|
||||||
cstore: &CStore,
|
cstore: &CStore,
|
||||||
cfg: ast::CrateConfig,
|
cfg: ast::CrateConfig,
|
||||||
input: &Input,
|
input: &Input,
|
||||||
outdir: &Option<PathBuf>,
|
outdir: &Option<PathBuf>,
|
||||||
output: &Option<PathBuf>,
|
output: &Option<PathBuf>,
|
||||||
addl_plugins: Option<Vec<String>>,
|
addl_plugins: Option<Vec<String>>,
|
||||||
control: CompileController) {
|
control: CompileController) -> CompileResult {
|
||||||
macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: expr) => ({
|
macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: expr) => ({
|
||||||
let state = $make_state;
|
let state = $make_state;
|
||||||
(control.$point.callback)(state);
|
(control.$point.callback)(state);
|
||||||
|
|
||||||
if control.$point.stop == Compilation::Stop {
|
if control.$point.stop == Compilation::Stop {
|
||||||
$tsess.abort_if_errors();
|
return compile_result_from_err_count($tsess.err_count());
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
|
|
||||||
// We need nested scopes here, because the intermediate results can keep
|
// We need nested scopes here, because the intermediate results can keep
|
||||||
// large chunks of memory alive and we want to free them as soon as
|
// large chunks of memory alive and we want to free them as soon as
|
||||||
// possible to keep the peak memory usage low
|
// possible to keep the peak memory usage low
|
||||||
let result = {
|
let (outputs, trans) = {
|
||||||
let (outputs, expanded_crate, id) = {
|
let (outputs, expanded_crate, id) = {
|
||||||
let krate = phase_1_parse_input(&sess, cfg, input);
|
let krate = phase_1_parse_input(sess, cfg, input);
|
||||||
|
|
||||||
controller_entry_point!(after_parse,
|
controller_entry_point!(after_parse,
|
||||||
sess,
|
sess,
|
||||||
CompileState::state_after_parse(input, &sess, outdir, &krate));
|
CompileState::state_after_parse(input, sess, outdir, &krate));
|
||||||
|
|
||||||
let outputs = build_output_filenames(input, outdir, output, &krate.attrs, &sess);
|
let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess);
|
||||||
let id = link::find_crate_name(Some(&sess), &krate.attrs, input);
|
let id = link::find_crate_name(Some(sess), &krate.attrs, input);
|
||||||
let expanded_crate = match phase_2_configure_and_expand(&sess,
|
let expanded_crate = try!(phase_2_configure_and_expand(sess,
|
||||||
&cstore,
|
&cstore,
|
||||||
krate,
|
krate,
|
||||||
&id[..],
|
&id[..],
|
||||||
addl_plugins) {
|
addl_plugins));
|
||||||
None => return,
|
|
||||||
Some(k) => k,
|
|
||||||
};
|
|
||||||
|
|
||||||
(outputs, expanded_crate, id)
|
(outputs, expanded_crate, id)
|
||||||
};
|
};
|
||||||
@ -103,14 +108,14 @@ pub fn compile_input(sess: Session,
|
|||||||
controller_entry_point!(after_expand,
|
controller_entry_point!(after_expand,
|
||||||
sess,
|
sess,
|
||||||
CompileState::state_after_expand(input,
|
CompileState::state_after_expand(input,
|
||||||
&sess,
|
sess,
|
||||||
outdir,
|
outdir,
|
||||||
&expanded_crate,
|
&expanded_crate,
|
||||||
&id[..]));
|
&id[..]));
|
||||||
|
|
||||||
let expanded_crate = assign_node_ids(&sess, expanded_crate);
|
let expanded_crate = assign_node_ids(sess, expanded_crate);
|
||||||
// Lower ast -> hir.
|
// Lower ast -> hir.
|
||||||
let lcx = LoweringContext::new(&sess, Some(&expanded_crate));
|
let lcx = LoweringContext::new(sess, Some(&expanded_crate));
|
||||||
let mut hir_forest = time(sess.time_passes(),
|
let mut hir_forest = time(sess.time_passes(),
|
||||||
"lowering ast -> hir",
|
"lowering ast -> hir",
|
||||||
|| hir_map::Forest::new(lower_crate(&lcx, &expanded_crate)));
|
|| hir_map::Forest::new(lower_crate(&lcx, &expanded_crate)));
|
||||||
@ -122,14 +127,14 @@ pub fn compile_input(sess: Session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
let arenas = ty::CtxtArenas::new();
|
let arenas = ty::CtxtArenas::new();
|
||||||
let hir_map = make_map(&sess, &mut hir_forest);
|
let hir_map = make_map(sess, &mut hir_forest);
|
||||||
|
|
||||||
write_out_deps(&sess, &outputs, &id);
|
write_out_deps(sess, &outputs, &id);
|
||||||
|
|
||||||
controller_entry_point!(after_write_deps,
|
controller_entry_point!(after_write_deps,
|
||||||
sess,
|
sess,
|
||||||
CompileState::state_after_write_deps(input,
|
CompileState::state_after_write_deps(input,
|
||||||
&sess,
|
sess,
|
||||||
outdir,
|
outdir,
|
||||||
&hir_map,
|
&hir_map,
|
||||||
&expanded_crate,
|
&expanded_crate,
|
||||||
@ -138,12 +143,12 @@ pub fn compile_input(sess: Session,
|
|||||||
&lcx));
|
&lcx));
|
||||||
|
|
||||||
time(sess.time_passes(), "attribute checking", || {
|
time(sess.time_passes(), "attribute checking", || {
|
||||||
front::check_attr::check_crate(&sess, &expanded_crate);
|
front::check_attr::check_crate(sess, &expanded_crate);
|
||||||
});
|
});
|
||||||
|
|
||||||
time(sess.time_passes(),
|
time(sess.time_passes(),
|
||||||
"early lint checks",
|
"early lint checks",
|
||||||
|| lint::check_ast_crate(&sess, &expanded_crate));
|
|| lint::check_ast_crate(sess, &expanded_crate));
|
||||||
|
|
||||||
let opt_crate = if sess.opts.debugging_opts.keep_ast ||
|
let opt_crate = if sess.opts.debugging_opts.keep_ast ||
|
||||||
sess.opts.debugging_opts.save_analysis {
|
sess.opts.debugging_opts.save_analysis {
|
||||||
@ -153,14 +158,13 @@ pub fn compile_input(sess: Session,
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
phase_3_run_analysis_passes(&sess,
|
try!(try!(phase_3_run_analysis_passes(sess,
|
||||||
&cstore,
|
&cstore,
|
||||||
hir_map,
|
hir_map,
|
||||||
&arenas,
|
&arenas,
|
||||||
&id,
|
&id,
|
||||||
control.make_glob_map,
|
control.make_glob_map,
|
||||||
|tcx, mir_map, analysis| {
|
|tcx, mir_map, analysis| {
|
||||||
|
|
||||||
{
|
{
|
||||||
let state =
|
let state =
|
||||||
CompileState::state_after_analysis(input,
|
CompileState::state_after_analysis(input,
|
||||||
@ -175,9 +179,9 @@ pub fn compile_input(sess: Session,
|
|||||||
&id);
|
&id);
|
||||||
(control.after_analysis.callback)(state);
|
(control.after_analysis.callback)(state);
|
||||||
|
|
||||||
tcx.sess.abort_if_errors();
|
throw_if_errors!(tcx.sess);
|
||||||
if control.after_analysis.stop == Compilation::Stop {
|
if control.after_analysis.stop == Compilation::Stop {
|
||||||
return Err(());
|
return Err(0usize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,22 +202,18 @@ pub fn compile_input(sess: Session,
|
|||||||
token::get_ident_interner().clear();
|
token::get_ident_interner().clear();
|
||||||
|
|
||||||
Ok((outputs, trans))
|
Ok((outputs, trans))
|
||||||
})
|
})))
|
||||||
};
|
};
|
||||||
|
|
||||||
let (outputs, trans) = if let Ok(out) = result {
|
try!(phase_5_run_llvm_passes(sess, &trans, &outputs));
|
||||||
out
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
phase_5_run_llvm_passes(&sess, &trans, &outputs);
|
|
||||||
|
|
||||||
controller_entry_point!(after_llvm,
|
controller_entry_point!(after_llvm,
|
||||||
sess,
|
sess,
|
||||||
CompileState::state_after_llvm(input, &sess, outdir, &trans));
|
CompileState::state_after_llvm(input, sess, outdir, &trans));
|
||||||
|
|
||||||
phase_6_link_output(&sess, &trans, &outputs);
|
phase_6_link_output(sess, &trans, &outputs);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The name used for source code that doesn't originate in a file
|
/// The name used for source code that doesn't originate in a file
|
||||||
@ -457,7 +457,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
|||||||
mut krate: ast::Crate,
|
mut krate: ast::Crate,
|
||||||
crate_name: &str,
|
crate_name: &str,
|
||||||
addl_plugins: Option<Vec<String>>)
|
addl_plugins: Option<Vec<String>>)
|
||||||
-> Option<ast::Crate> {
|
-> Result<ast::Crate, usize> {
|
||||||
let time_passes = sess.time_passes();
|
let time_passes = sess.time_passes();
|
||||||
|
|
||||||
// strip before anything else because crate metadata may use #[cfg_attr]
|
// strip before anything else because crate metadata may use #[cfg_attr]
|
||||||
@ -469,13 +469,13 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
|||||||
// baz! should not use this definition unless foo is enabled.
|
// baz! should not use this definition unless foo is enabled.
|
||||||
|
|
||||||
let mut feature_gated_cfgs = vec![];
|
let mut feature_gated_cfgs = vec![];
|
||||||
krate = time(time_passes, "configuration 1", || {
|
krate = try!(time(time_passes, "configuration 1", || {
|
||||||
sess.abort_if_new_errors(|| {
|
sess.track_errors(|| {
|
||||||
syntax::config::strip_unconfigured_items(sess.diagnostic(),
|
syntax::config::strip_unconfigured_items(sess.diagnostic(),
|
||||||
krate,
|
krate,
|
||||||
&mut feature_gated_cfgs)
|
&mut feature_gated_cfgs)
|
||||||
})
|
})
|
||||||
});
|
}));
|
||||||
|
|
||||||
*sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs);
|
*sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs);
|
||||||
*sess.crate_metadata.borrow_mut() = collect_crate_metadata(sess, &krate.attrs);
|
*sess.crate_metadata.borrow_mut() = collect_crate_metadata(sess, &krate.attrs);
|
||||||
@ -484,8 +484,8 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
|||||||
middle::recursion_limit::update_recursion_limit(sess, &krate);
|
middle::recursion_limit::update_recursion_limit(sess, &krate);
|
||||||
});
|
});
|
||||||
|
|
||||||
time(time_passes, "gated macro checking", || {
|
try!(time(time_passes, "gated macro checking", || {
|
||||||
sess.abort_if_new_errors(|| {
|
sess.track_errors(|| {
|
||||||
let features =
|
let features =
|
||||||
syntax::feature_gate::check_crate_macros(sess.codemap(),
|
syntax::feature_gate::check_crate_macros(sess.codemap(),
|
||||||
&sess.parse_sess.span_diagnostic,
|
&sess.parse_sess.span_diagnostic,
|
||||||
@ -493,8 +493,8 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
|||||||
|
|
||||||
// these need to be set "early" so that expansion sees `quote` if enabled.
|
// these need to be set "early" so that expansion sees `quote` if enabled.
|
||||||
*sess.features.borrow_mut() = features;
|
*sess.features.borrow_mut() = features;
|
||||||
});
|
})
|
||||||
});
|
}));
|
||||||
|
|
||||||
|
|
||||||
krate = time(time_passes, "crate injection", || {
|
krate = time(time_passes, "crate injection", || {
|
||||||
@ -531,7 +531,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
|||||||
let Registry { syntax_exts, early_lint_passes, late_lint_passes, lint_groups,
|
let Registry { syntax_exts, early_lint_passes, late_lint_passes, lint_groups,
|
||||||
llvm_passes, attributes, .. } = registry;
|
llvm_passes, attributes, .. } = registry;
|
||||||
|
|
||||||
sess.abort_if_new_errors(|| {
|
try!(sess.track_errors(|| {
|
||||||
let mut ls = sess.lint_store.borrow_mut();
|
let mut ls = sess.lint_store.borrow_mut();
|
||||||
for pass in early_lint_passes {
|
for pass in early_lint_passes {
|
||||||
ls.register_early_pass(Some(sess), true, pass);
|
ls.register_early_pass(Some(sess), true, pass);
|
||||||
@ -546,14 +546,14 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
|||||||
|
|
||||||
*sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
|
*sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
|
||||||
*sess.plugin_attributes.borrow_mut() = attributes.clone();
|
*sess.plugin_attributes.borrow_mut() = attributes.clone();
|
||||||
});
|
}));
|
||||||
|
|
||||||
// Lint plugins are registered; now we can process command line flags.
|
// Lint plugins are registered; now we can process command line flags.
|
||||||
if sess.opts.describe_lints {
|
if sess.opts.describe_lints {
|
||||||
super::describe_lints(&*sess.lint_store.borrow(), true);
|
super::describe_lints(&*sess.lint_store.borrow(), true);
|
||||||
return None;
|
return Err(0);
|
||||||
}
|
}
|
||||||
sess.abort_if_new_errors(|| sess.lint_store.borrow_mut().process_command_line(sess));
|
try!(sess.track_errors(|| sess.lint_store.borrow_mut().process_command_line(sess)));
|
||||||
|
|
||||||
krate = time(time_passes, "expansion", || {
|
krate = time(time_passes, "expansion", || {
|
||||||
// Windows dlls do not have rpaths, so they don't know how to find their
|
// Windows dlls do not have rpaths, so they don't know how to find their
|
||||||
@ -596,21 +596,21 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
|||||||
// of macro expansion. This runs before #[cfg] to try to catch as
|
// of macro expansion. This runs before #[cfg] to try to catch as
|
||||||
// much as possible (e.g. help the programmer avoid platform
|
// much as possible (e.g. help the programmer avoid platform
|
||||||
// specific differences)
|
// specific differences)
|
||||||
time(time_passes, "complete gated feature checking 1", || {
|
try!(time(time_passes, "complete gated feature checking 1", || {
|
||||||
sess.abort_if_new_errors(|| {
|
sess.track_errors(|| {
|
||||||
let features = syntax::feature_gate::check_crate(sess.codemap(),
|
let features = syntax::feature_gate::check_crate(sess.codemap(),
|
||||||
&sess.parse_sess.span_diagnostic,
|
&sess.parse_sess.span_diagnostic,
|
||||||
&krate,
|
&krate,
|
||||||
&attributes,
|
&attributes,
|
||||||
sess.opts.unstable_features);
|
sess.opts.unstable_features);
|
||||||
*sess.features.borrow_mut() = features;
|
*sess.features.borrow_mut() = features;
|
||||||
});
|
})
|
||||||
});
|
}));
|
||||||
|
|
||||||
// JBC: make CFG processing part of expansion to avoid this problem:
|
// JBC: make CFG processing part of expansion to avoid this problem:
|
||||||
|
|
||||||
// strip again, in case expansion added anything with a #[cfg].
|
// strip again, in case expansion added anything with a #[cfg].
|
||||||
krate = sess.abort_if_new_errors(|| {
|
krate = try!(sess.track_errors(|| {
|
||||||
let krate = time(time_passes, "configuration 2", || {
|
let krate = time(time_passes, "configuration 2", || {
|
||||||
syntax::config::strip_unconfigured_items(sess.diagnostic(),
|
syntax::config::strip_unconfigured_items(sess.diagnostic(),
|
||||||
krate,
|
krate,
|
||||||
@ -627,7 +627,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
|||||||
});
|
});
|
||||||
|
|
||||||
krate
|
krate
|
||||||
});
|
}));
|
||||||
|
|
||||||
krate = time(time_passes, "maybe building test harness", || {
|
krate = time(time_passes, "maybe building test harness", || {
|
||||||
syntax::test::modify_for_testing(&sess.parse_sess, &sess.opts.cfg, krate, sess.diagnostic())
|
syntax::test::modify_for_testing(&sess.parse_sess, &sess.opts.cfg, krate, sess.diagnostic())
|
||||||
@ -648,16 +648,16 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
|||||||
// One final feature gating of the true AST that gets compiled
|
// One final feature gating of the true AST that gets compiled
|
||||||
// later, to make sure we've got everything (e.g. configuration
|
// later, to make sure we've got everything (e.g. configuration
|
||||||
// can insert new attributes via `cfg_attr`)
|
// can insert new attributes via `cfg_attr`)
|
||||||
time(time_passes, "complete gated feature checking 2", || {
|
try!(time(time_passes, "complete gated feature checking 2", || {
|
||||||
sess.abort_if_new_errors(|| {
|
sess.track_errors(|| {
|
||||||
let features = syntax::feature_gate::check_crate(sess.codemap(),
|
let features = syntax::feature_gate::check_crate(sess.codemap(),
|
||||||
&sess.parse_sess.span_diagnostic,
|
&sess.parse_sess.span_diagnostic,
|
||||||
&krate,
|
&krate,
|
||||||
&attributes,
|
&attributes,
|
||||||
sess.opts.unstable_features);
|
sess.opts.unstable_features);
|
||||||
*sess.features.borrow_mut() = features;
|
*sess.features.borrow_mut() = features;
|
||||||
});
|
})
|
||||||
});
|
}));
|
||||||
|
|
||||||
time(time_passes,
|
time(time_passes,
|
||||||
"const fn bodies and arguments",
|
"const fn bodies and arguments",
|
||||||
@ -667,7 +667,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
|||||||
println!("Post-expansion node count: {}", count_nodes(&krate));
|
println!("Post-expansion node count: {}", count_nodes(&krate));
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(krate)
|
Ok(krate)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assign_node_ids(sess: &Session, krate: ast::Crate) -> ast::Crate {
|
pub fn assign_node_ids(sess: &Session, krate: ast::Crate) -> ast::Crate {
|
||||||
@ -712,7 +712,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
|||||||
name: &str,
|
name: &str,
|
||||||
make_glob_map: resolve::MakeGlobMap,
|
make_glob_map: resolve::MakeGlobMap,
|
||||||
f: F)
|
f: F)
|
||||||
-> R
|
-> Result<R, usize>
|
||||||
where F: for<'a> FnOnce(&'a ty::ctxt<'tcx>, MirMap<'tcx>, ty::CrateAnalysis) -> R
|
where F: for<'a> FnOnce(&'a ty::ctxt<'tcx>, MirMap<'tcx>, ty::CrateAnalysis) -> R
|
||||||
{
|
{
|
||||||
let time_passes = sess.time_passes();
|
let time_passes = sess.time_passes();
|
||||||
@ -722,11 +722,11 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
|||||||
"external crate/lib resolution",
|
"external crate/lib resolution",
|
||||||
|| LocalCrateReader::new(sess, cstore, &hir_map).read_crates(krate));
|
|| LocalCrateReader::new(sess, cstore, &hir_map).read_crates(krate));
|
||||||
|
|
||||||
let lang_items = time(time_passes, "language item collection", || {
|
let lang_items = try!(time(time_passes, "language item collection", || {
|
||||||
sess.abort_if_new_errors(|| {
|
sess.track_errors(|| {
|
||||||
middle::lang_items::collect_language_items(&sess, &hir_map)
|
middle::lang_items::collect_language_items(&sess, &hir_map)
|
||||||
})
|
})
|
||||||
});
|
}));
|
||||||
|
|
||||||
let resolve::CrateMap {
|
let resolve::CrateMap {
|
||||||
def_map,
|
def_map,
|
||||||
@ -827,7 +827,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
|||||||
// lot of annoying errors in the compile-fail tests (basically,
|
// lot of annoying errors in the compile-fail tests (basically,
|
||||||
// lint warnings and so on -- kindck used to do this abort, but
|
// lint warnings and so on -- kindck used to do this abort, but
|
||||||
// kindck is gone now). -nmatsakis
|
// kindck is gone now). -nmatsakis
|
||||||
tcx.sess.abort_if_errors();
|
throw_if_errors!(tcx.sess);
|
||||||
|
|
||||||
let reachable_map =
|
let reachable_map =
|
||||||
time(time_passes,
|
time(time_passes,
|
||||||
@ -853,9 +853,9 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
|||||||
|| lint::check_crate(tcx, &access_levels));
|
|| lint::check_crate(tcx, &access_levels));
|
||||||
|
|
||||||
// The above three passes generate errors w/o aborting
|
// The above three passes generate errors w/o aborting
|
||||||
tcx.sess.abort_if_errors();
|
throw_if_errors!(tcx.sess);
|
||||||
|
|
||||||
f(tcx,
|
Ok(f(tcx,
|
||||||
mir_map,
|
mir_map,
|
||||||
ty::CrateAnalysis {
|
ty::CrateAnalysis {
|
||||||
export_map: export_map,
|
export_map: export_map,
|
||||||
@ -863,7 +863,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
|||||||
reachable: reachable_map,
|
reachable: reachable_map,
|
||||||
name: name,
|
name: name,
|
||||||
glob_map: glob_map,
|
glob_map: glob_map,
|
||||||
})
|
}))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -893,7 +893,7 @@ pub fn phase_4_translate_to_llvm<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|||||||
/// as a side effect.
|
/// as a side effect.
|
||||||
pub fn phase_5_run_llvm_passes(sess: &Session,
|
pub fn phase_5_run_llvm_passes(sess: &Session,
|
||||||
trans: &trans::CrateTranslation,
|
trans: &trans::CrateTranslation,
|
||||||
outputs: &OutputFilenames) {
|
outputs: &OutputFilenames) -> CompileResult {
|
||||||
if sess.opts.cg.no_integrated_as {
|
if sess.opts.cg.no_integrated_as {
|
||||||
let mut map = HashMap::new();
|
let mut map = HashMap::new();
|
||||||
map.insert(OutputType::Assembly, None);
|
map.insert(OutputType::Assembly, None);
|
||||||
@ -913,7 +913,8 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
|
|||||||
|| write::run_passes(sess, trans, &sess.opts.output_types, outputs));
|
|| write::run_passes(sess, trans, &sess.opts.output_types, outputs));
|
||||||
}
|
}
|
||||||
|
|
||||||
sess.abort_if_errors();
|
throw_if_errors!(sess);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run the linker on any artifacts that resulted from the LLVM run.
|
/// Run the linker on any artifacts that resulted from the LLVM run.
|
||||||
|
@ -105,49 +105,95 @@ pub mod target_features;
|
|||||||
const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\
|
const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\
|
||||||
md#bug-reports";
|
md#bug-reports";
|
||||||
|
|
||||||
|
// Err(0) means compilation was stopped, but no errors were found.
|
||||||
|
// This would be better as a dedicated enum, but using try! is so convenient.
|
||||||
|
pub type CompileResult = Result<(), usize>;
|
||||||
|
|
||||||
|
pub fn compile_result_from_err_count(err_count: usize) -> CompileResult {
|
||||||
|
if err_count == 0 {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(err_count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn abort_msg(err_count: usize) -> String {
|
||||||
|
match err_count {
|
||||||
|
0 => "aborting with no errors (maybe a bug?)".to_owned(),
|
||||||
|
1 => "aborting due to previous error".to_owned(),
|
||||||
|
e => format!("aborting due to {} previous errors", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn abort_on_err<T>(result: Result<T, usize>, sess: &Session) -> T {
|
||||||
|
match result {
|
||||||
|
Err(err_count) => {
|
||||||
|
sess.fatal(&abort_msg(err_count));
|
||||||
|
}
|
||||||
|
Ok(x) => x,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run(args: Vec<String>) -> isize {
|
pub fn run(args: Vec<String>) -> isize {
|
||||||
monitor(move || run_compiler(&args, &mut RustcDefaultCalls));
|
monitor(move || {
|
||||||
|
let (result, session) = run_compiler(&args, &mut RustcDefaultCalls);
|
||||||
|
if let Err(err_count) = result {
|
||||||
|
if err_count > 0 {
|
||||||
|
match session {
|
||||||
|
Some(sess) => sess.fatal(&abort_msg(err_count)),
|
||||||
|
None => {
|
||||||
|
let mut emitter =
|
||||||
|
errors::emitter::BasicEmitter::stderr(errors::ColorConfig::Auto);
|
||||||
|
emitter.emit(None, &abort_msg(err_count), None, errors::Level::Fatal);
|
||||||
|
panic!(errors::FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse args and run the compiler. This is the primary entry point for rustc.
|
// Parse args and run the compiler. This is the primary entry point for rustc.
|
||||||
// See comments on CompilerCalls below for details about the callbacks argument.
|
// See comments on CompilerCalls below for details about the callbacks argument.
|
||||||
pub fn run_compiler<'a>(args: &[String], callbacks: &mut CompilerCalls<'a>) {
|
pub fn run_compiler<'a>(args: &[String],
|
||||||
macro_rules! do_or_return {($expr: expr) => {
|
callbacks: &mut CompilerCalls<'a>)
|
||||||
|
-> (CompileResult, Option<Session>) {
|
||||||
|
macro_rules! do_or_return {($expr: expr, $sess: expr) => {
|
||||||
match $expr {
|
match $expr {
|
||||||
Compilation::Stop => return,
|
Compilation::Stop => return (Ok(()), $sess),
|
||||||
Compilation::Continue => {}
|
Compilation::Continue => {}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
let matches = match handle_options(args.to_vec()) {
|
let matches = match handle_options(args.to_vec()) {
|
||||||
Some(matches) => matches,
|
Some(matches) => matches,
|
||||||
None => return,
|
None => return (Ok(()), None),
|
||||||
};
|
};
|
||||||
|
|
||||||
let sopts = config::build_session_options(&matches);
|
let sopts = config::build_session_options(&matches);
|
||||||
|
|
||||||
let descriptions = diagnostics_registry();
|
let descriptions = diagnostics_registry();
|
||||||
|
|
||||||
do_or_return!(callbacks.early_callback(&matches, &descriptions, sopts.error_format));
|
do_or_return!(callbacks.early_callback(&matches, &descriptions, sopts.error_format), None);
|
||||||
|
|
||||||
let (odir, ofile) = make_output(&matches);
|
let (odir, ofile) = make_output(&matches);
|
||||||
let (input, input_file_path) = match make_input(&matches.free) {
|
let (input, input_file_path) = match make_input(&matches.free) {
|
||||||
Some((input, input_file_path)) => callbacks.some_input(input, input_file_path),
|
Some((input, input_file_path)) => callbacks.some_input(input, input_file_path),
|
||||||
None => match callbacks.no_input(&matches, &sopts, &odir, &ofile, &descriptions) {
|
None => match callbacks.no_input(&matches, &sopts, &odir, &ofile, &descriptions) {
|
||||||
Some((input, input_file_path)) => (input, input_file_path),
|
Some((input, input_file_path)) => (input, input_file_path),
|
||||||
None => return,
|
None => return (Ok(()), None),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let cstore = Rc::new(CStore::new(token::get_ident_interner()));
|
let cstore = Rc::new(CStore::new(token::get_ident_interner()));
|
||||||
let sess = build_session(sopts, input_file_path, descriptions,
|
let sess = build_session(sopts, input_file_path, descriptions, cstore.clone());
|
||||||
cstore.clone());
|
|
||||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||||
let mut cfg = config::build_configuration(&sess);
|
let mut cfg = config::build_configuration(&sess);
|
||||||
target_features::add_configuration(&mut cfg, &sess);
|
target_features::add_configuration(&mut cfg, &sess);
|
||||||
|
|
||||||
do_or_return!(callbacks.late_callback(&matches, &sess, &input, &odir, &ofile));
|
do_or_return!(callbacks.late_callback(&matches, &sess, &input, &odir, &ofile), Some(sess));
|
||||||
|
|
||||||
// It is somewhat unfortunate that this is hardwired in - this is forced by
|
// It is somewhat unfortunate that this is hardwired in - this is forced by
|
||||||
// the fact that pretty_print_input requires the session by value.
|
// the fact that pretty_print_input requires the session by value.
|
||||||
@ -155,7 +201,7 @@ pub fn run_compiler<'a>(args: &[String], callbacks: &mut CompilerCalls<'a>) {
|
|||||||
match pretty {
|
match pretty {
|
||||||
Some((ppm, opt_uii)) => {
|
Some((ppm, opt_uii)) => {
|
||||||
pretty::pretty_print_input(sess, &cstore, cfg, &input, ppm, opt_uii, ofile);
|
pretty::pretty_print_input(sess, &cstore, cfg, &input, ppm, opt_uii, ofile);
|
||||||
return;
|
return (Ok(()), None);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// continue
|
// continue
|
||||||
@ -164,8 +210,9 @@ pub fn run_compiler<'a>(args: &[String], callbacks: &mut CompilerCalls<'a>) {
|
|||||||
|
|
||||||
let plugins = sess.opts.debugging_opts.extra_plugins.clone();
|
let plugins = sess.opts.debugging_opts.extra_plugins.clone();
|
||||||
let control = callbacks.build_controller(&sess);
|
let control = callbacks.build_controller(&sess);
|
||||||
driver::compile_input(sess, &cstore, cfg, &input, &odir, &ofile,
|
(driver::compile_input(&sess, &cstore, cfg, &input, &odir, &ofile,
|
||||||
Some(plugins), control);
|
Some(plugins), control),
|
||||||
|
Some(sess))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract output directory and file from matches.
|
// Extract output directory and file from matches.
|
||||||
|
@ -17,7 +17,7 @@ use self::NodesMatchingUII::*;
|
|||||||
|
|
||||||
use rustc_trans::back::link;
|
use rustc_trans::back::link;
|
||||||
|
|
||||||
use driver;
|
use {driver, abort_on_err};
|
||||||
|
|
||||||
use rustc::middle::ty;
|
use rustc::middle::ty;
|
||||||
use rustc::middle::cfg;
|
use rustc::middle::cfg;
|
||||||
@ -194,7 +194,7 @@ impl PpSourceMode {
|
|||||||
f(&annotation, payload, &ast_map.forest.krate)
|
f(&annotation, payload, &ast_map.forest.krate)
|
||||||
}
|
}
|
||||||
PpmTyped => {
|
PpmTyped => {
|
||||||
driver::phase_3_run_analysis_passes(sess,
|
abort_on_err(driver::phase_3_run_analysis_passes(sess,
|
||||||
cstore,
|
cstore,
|
||||||
ast_map.clone(),
|
ast_map.clone(),
|
||||||
arenas,
|
arenas,
|
||||||
@ -208,7 +208,7 @@ impl PpSourceMode {
|
|||||||
f(&annotation,
|
f(&annotation,
|
||||||
payload,
|
payload,
|
||||||
&ast_map.forest.krate)
|
&ast_map.forest.krate)
|
||||||
})
|
}), sess)
|
||||||
}
|
}
|
||||||
_ => panic!("Should use call_with_pp_support"),
|
_ => panic!("Should use call_with_pp_support"),
|
||||||
}
|
}
|
||||||
@ -694,8 +694,8 @@ pub fn pretty_print_input(sess: Session,
|
|||||||
let compute_ast_map = needs_ast_map(&ppm, &opt_uii);
|
let compute_ast_map = needs_ast_map(&ppm, &opt_uii);
|
||||||
let krate = if compute_ast_map {
|
let krate = if compute_ast_map {
|
||||||
match driver::phase_2_configure_and_expand(&sess, &cstore, krate, &id[..], None) {
|
match driver::phase_2_configure_and_expand(&sess, &cstore, krate, &id[..], None) {
|
||||||
None => return,
|
Err(_) => return,
|
||||||
Some(k) => driver::assign_node_ids(&sess, k),
|
Ok(k) => driver::assign_node_ids(&sess, k),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
krate
|
krate
|
||||||
@ -818,7 +818,7 @@ pub fn pretty_print_input(sess: Session,
|
|||||||
match code {
|
match code {
|
||||||
Some(code) => {
|
Some(code) => {
|
||||||
let variants = gather_flowgraph_variants(&sess);
|
let variants = gather_flowgraph_variants(&sess);
|
||||||
driver::phase_3_run_analysis_passes(&sess,
|
abort_on_err(driver::phase_3_run_analysis_passes(&sess,
|
||||||
&cstore,
|
&cstore,
|
||||||
ast_map,
|
ast_map,
|
||||||
&arenas,
|
&arenas,
|
||||||
@ -830,7 +830,7 @@ pub fn pretty_print_input(sess: Session,
|
|||||||
code,
|
code,
|
||||||
mode,
|
mode,
|
||||||
out)
|
out)
|
||||||
})
|
}), &sess)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let message = format!("--pretty=flowgraph needs block, fn, or method; got \
|
let message = format!("--pretty=flowgraph needs block, fn, or method; got \
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
pub use self::MaybeTyped::*;
|
pub use self::MaybeTyped::*;
|
||||||
|
|
||||||
use rustc_lint;
|
use rustc_lint;
|
||||||
use rustc_driver::{driver, target_features};
|
use rustc_driver::{driver, target_features, abort_on_err};
|
||||||
use rustc::session::{self, config};
|
use rustc::session::{self, config};
|
||||||
use rustc::middle::def_id::DefId;
|
use rustc::middle::def_id::DefId;
|
||||||
use rustc::middle::privacy::AccessLevels;
|
use rustc::middle::privacy::AccessLevels;
|
||||||
@ -147,7 +147,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
|
|||||||
let arenas = ty::CtxtArenas::new();
|
let arenas = ty::CtxtArenas::new();
|
||||||
let hir_map = driver::make_map(&sess, &mut hir_forest);
|
let hir_map = driver::make_map(&sess, &mut hir_forest);
|
||||||
|
|
||||||
driver::phase_3_run_analysis_passes(&sess,
|
abort_on_err(driver::phase_3_run_analysis_passes(&sess,
|
||||||
&cstore,
|
&cstore,
|
||||||
hir_map,
|
hir_map,
|
||||||
&arenas,
|
&arenas,
|
||||||
@ -200,5 +200,5 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
|
|||||||
*analysis.inlined.borrow_mut() = map;
|
*analysis.inlined.borrow_mut() = map;
|
||||||
analysis.deref_trait_did = ctxt.deref_trait_did.get();
|
analysis.deref_trait_did = ctxt.deref_trait_did.get();
|
||||||
(krate, analysis)
|
(krate, analysis)
|
||||||
})
|
}), &sess)
|
||||||
}
|
}
|
||||||
|
@ -250,7 +250,12 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec<String>, libs: SearchPaths,
|
|||||||
if no_run {
|
if no_run {
|
||||||
control.after_analysis.stop = Compilation::Stop;
|
control.after_analysis.stop = Compilation::Stop;
|
||||||
}
|
}
|
||||||
driver::compile_input(sess, &cstore, cfg, &input, &out, &None, None, control);
|
let result = driver::compile_input(&sess, &cstore, cfg, &input,
|
||||||
|
&out, &None, None, control);
|
||||||
|
match result {
|
||||||
|
Err(count) if count > 0 => sess.fatal("aborting due to previous error(s)"),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
if no_run { return }
|
if no_run { return }
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ use rustc::middle::cstore::{CrateStore, LinkagePreference};
|
|||||||
use rustc::middle::ty;
|
use rustc::middle::ty;
|
||||||
use rustc::session::config::{self, basic_options, build_configuration, Input, Options};
|
use rustc::session::config::{self, basic_options, build_configuration, Input, Options};
|
||||||
use rustc::session::build_session;
|
use rustc::session::build_session;
|
||||||
use rustc_driver::driver;
|
use rustc_driver::{driver, abort_on_err};
|
||||||
use rustc_front::lowering::{lower_crate, LoweringContext};
|
use rustc_front::lowering::{lower_crate, LoweringContext};
|
||||||
use rustc_resolve::MakeGlobMap;
|
use rustc_resolve::MakeGlobMap;
|
||||||
use rustc_metadata::cstore::CStore;
|
use rustc_metadata::cstore::CStore;
|
||||||
@ -234,7 +234,7 @@ fn compile_program(input: &str, sysroot: PathBuf)
|
|||||||
let arenas = ty::CtxtArenas::new();
|
let arenas = ty::CtxtArenas::new();
|
||||||
let ast_map = driver::make_map(&sess, &mut hir_forest);
|
let ast_map = driver::make_map(&sess, &mut hir_forest);
|
||||||
|
|
||||||
driver::phase_3_run_analysis_passes(
|
abort_on_err(driver::phase_3_run_analysis_passes(
|
||||||
&sess, &cstore, ast_map, &arenas, &id,
|
&sess, &cstore, ast_map, &arenas, &id,
|
||||||
MakeGlobMap::No, |tcx, mir_map, analysis| {
|
MakeGlobMap::No, |tcx, mir_map, analysis| {
|
||||||
|
|
||||||
@ -254,7 +254,7 @@ fn compile_program(input: &str, sysroot: PathBuf)
|
|||||||
let modp = llmod as usize;
|
let modp = llmod as usize;
|
||||||
|
|
||||||
(modp, deps)
|
(modp, deps)
|
||||||
})
|
}), &sess)
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
|
|
||||||
match handle.join() {
|
match handle.join() {
|
||||||
|
@ -65,7 +65,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
|
|||||||
let cfg = build_configuration(&sess);
|
let cfg = build_configuration(&sess);
|
||||||
let control = CompileController::basic();
|
let control = CompileController::basic();
|
||||||
|
|
||||||
compile_input(sess, &cstore,
|
compile_input(&sess, &cstore,
|
||||||
cfg,
|
cfg,
|
||||||
&Input::Str(code),
|
&Input::Str(code),
|
||||||
&None,
|
&None,
|
||||||
|
Loading…
Reference in New Issue
Block a user