Use the new rustc interface

This commit is contained in:
John Kåre Alsaker 2019-02-01 23:26:42 +01:00 committed by Oliver Scherer
parent e66d6ec58b
commit 7d142ecf75
3 changed files with 105 additions and 219 deletions

View file

@ -2,18 +2,39 @@ extern crate getopts;
extern crate miri;
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_interface;
extern crate test;
use rustc_driver::{driver, Compilation};
use self::miri::eval_main;
use rustc::hir::def_id::LOCAL_CRATE;
use std::cell::RefCell;
use std::rc::Rc;
use miri::{MiriConfig, eval_main};
use rustc_interface::interface;
use crate::test::Bencher;
pub struct MiriCompilerCalls<'a>(Rc<RefCell<&'a mut Bencher>>);
struct MiriCompilerCalls<'a> {
bencher: &'a mut Bencher,
}
impl rustc_driver::Callbacks for MiriCompilerCalls<'_> {
fn after_analysis(&mut self, compiler: &interface::Compiler<'_>) -> bool {
compiler.session().abort_if_errors();
compiler.global_ctxt().unwrap().peek_mut().enter(|tcx| {
let (entry_def_id, _) = tcx.entry_fn(LOCAL_CRATE).expect(
"no main or start function found",
);
self.bencher.iter(|| {
let config = MiriConfig { validate: true, args: vec![] };
eval_main(tcx, entry_def_id, config);
});
});
compiler.session().abort_if_errors();
// Don't continue execution
false
}
}
fn find_sysroot() -> String {
// Taken from https://github.com/Manishearth/rust-clippy/pull/911.
@ -38,26 +59,5 @@ pub fn run(filename: &str, bencher: &mut Bencher) {
"--sysroot".to_string(),
find_sysroot(),
];
let bencher = RefCell::new(bencher);
let mut control = driver::CompileController::basic();
control.after_analysis.stop = Compilation::Stop;
control.after_analysis.callback = Box::new(move |state| {
state.session.abort_if_errors();
let tcx = state.tcx.unwrap();
let (entry_def_id, _) = tcx.entry_fn(LOCAL_CRATE).expect(
"no main or start function found",
);
bencher.borrow_mut().iter(|| {
let config = MiriConfig { validate: true, args: vec![] };
eval_main(tcx, entry_def_id, config);
});
state.session.abort_if_errors();
});
rustc_driver::run_compiler(args, Box::new(control), None, None);
rustc_driver::run_compiler(args, &mut MiriCompilerCalls { bencher }, None, None);
}

View file

@ -6,6 +6,7 @@ extern crate rustc_metadata;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_codegen_utils;
extern crate rustc_interface;
extern crate syntax;
use std::path::{PathBuf, Path};
@ -15,12 +16,10 @@ use std::io;
use rustc::session::Session;
use rustc_interface::interface;
use rustc_metadata::cstore::CStore;
use rustc_driver::{Compilation, CompilerCalls, RustcDefaultCalls};
use rustc_driver::driver::{CompileState, CompileController};
use rustc::session::config::{self, Input, ErrorOutputType};
use rustc::hir::{self, itemlikevisit};
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc::ty::TyCtxt;
use syntax::ast;
use rustc::hir::def_id::LOCAL_CRATE;
@ -28,93 +27,55 @@ use rustc::hir::def_id::LOCAL_CRATE;
use miri::MiriConfig;
struct MiriCompilerCalls {
default: Box<RustcDefaultCalls>,
/// whether we are building for the host
host_target: bool,
}
impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
fn early_callback(
&mut self,
matches: &getopts::Matches,
sopts: &config::Options,
cfg: &ast::CrateConfig,
descriptions: &rustc_errors::registry::Registry,
output: ErrorOutputType
) -> Compilation {
self.default.early_callback(matches, sopts, cfg, descriptions, output)
}
fn no_input(
&mut self,
matches: &getopts::Matches,
sopts: &config::Options,
cfg: &ast::CrateConfig,
odir: &Option<PathBuf>,
ofile: &Option<PathBuf>,
descriptions: &rustc_errors::registry::Registry
) -> Option<(Input, Option<PathBuf>)> {
self.default.no_input(matches, sopts, cfg, odir, ofile, descriptions)
}
fn late_callback(
&mut self,
trans: &CodegenBackend,
matches: &getopts::Matches,
sess: &Session,
cstore: &CStore,
input: &Input,
odir: &Option<PathBuf>,
ofile: &Option<PathBuf>,
) -> Compilation {
self.default.late_callback(trans, matches, sess, cstore, input, odir, ofile)
}
fn build_controller(self: Box<Self>, sess: &Session, matches: &getopts::Matches) -> CompileController<'a> {
let this = *self;
let mut control = this.default.build_controller(sess, matches);
control.after_hir_lowering.callback = Box::new(after_hir_lowering);
control.after_analysis.callback = Box::new(after_analysis);
if !this.host_target {
// only fully compile targets on the host
control.after_analysis.stop = Compilation::Stop;
}
control
}
}
impl rustc_driver::Callbacks for MiriCompilerCalls {
fn after_parsing(&mut self, compiler: &interface::Compiler<'_>) -> bool {
let attr = (
String::from("miri"),
syntax::feature_gate::AttributeType::Whitelisted,
);
compiler.session().plugin_attributes.borrow_mut().push(attr);
fn after_hir_lowering(state: &mut CompileState) {
let attr = (String::from("miri"), syntax::feature_gate::AttributeType::Whitelisted);
state.session.plugin_attributes.borrow_mut().push(attr);
}
// Continue execution
true
}
fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
state.session.abort_if_errors();
let tcx = state.tcx.unwrap();
if std::env::args().any(|arg| arg == "--test") {
struct Visitor<'a, 'tcx: 'a>(TyCtxt<'a, 'tcx, 'tcx>, &'a CompileState<'a, 'tcx>);
impl<'a, 'tcx: 'a, 'hir> itemlikevisit::ItemLikeVisitor<'hir> for Visitor<'a, 'tcx> {
fn visit_item(&mut self, i: &'hir hir::Item) {
if let hir::ItemKind::Fn(.., body_id) = i.node {
if i.attrs.iter().any(|attr| attr.name() == "test") {
let config = MiriConfig { validate: true, args: vec![] };
let did = self.0.hir().body_owner_def_id(body_id);
println!("running test: {}", self.0.def_path_debug_str(did));
miri::eval_main(self.0, did, config);
self.1.session.abort_if_errors();
fn after_analysis(&mut self, compiler: &interface::Compiler<'_>) -> bool {
compiler.session().abort_if_errors();
compiler.global_ctxt().unwrap().peek_mut().enter(|tcx| {
if std::env::args().any(|arg| arg == "--test") {
struct Visitor<'a, 'tcx: 'a>(TyCtxt<'a, 'tcx, 'tcx>);
impl<'a, 'tcx: 'a, 'hir> itemlikevisit::ItemLikeVisitor<'hir> for Visitor<'a, 'tcx> {
fn visit_item(&mut self, i: &'hir hir::Item) {
if let hir::ItemKind::Fn(.., body_id) = i.node {
if i.attrs.iter().any(|attr| attr.name() == "test") {
let config = MiriConfig { validate: true, args: vec![] };
let did = self.0.hir().body_owner_def_id(body_id);
println!("running test: {}", self.0.def_path_debug_str(did));
miri::eval_main(self.0, did, config);
self.0.sess.abort_if_errors();
}
}
}
fn visit_trait_item(&mut self, _trait_item: &'hir hir::TraitItem) {}
fn visit_impl_item(&mut self, _impl_item: &'hir hir::ImplItem) {}
}
}
fn visit_trait_item(&mut self, _trait_item: &'hir hir::TraitItem) {}
fn visit_impl_item(&mut self, _impl_item: &'hir hir::ImplItem) {}
}
state.hir_crate.unwrap().visit_all_item_likes(&mut Visitor(tcx, state));
} else if let Some((entry_def_id, _)) = tcx.entry_fn(LOCAL_CRATE) {
let config = MiriConfig { validate: true, args: vec![] };
miri::eval_main(tcx, entry_def_id, config);
tcx.hir().krate().visit_all_item_likes(&mut Visitor(tcx));
} else if let Some((entry_def_id, _)) = tcx.entry_fn(LOCAL_CRATE) {
let config = MiriConfig { validate: true, args: vec![] };
miri::eval_main(tcx, entry_def_id, config);
state.session.abort_if_errors();
} else {
println!("no main function found, assuming auxiliary build");
compiler.session().abort_if_errors();
} else {
println!("no main function found, assuming auxiliary build");
}
});
// Continue execution on host target
self.host_target
}
}
@ -185,10 +146,7 @@ fn main() {
let buf = BufWriter::default();
let output = buf.clone();
let result = std::panic::catch_unwind(|| {
rustc_driver::run_compiler(&args, Box::new(MiriCompilerCalls {
default: Box::new(RustcDefaultCalls),
host_target,
}), None, Some(Box::new(buf)));
rustc_driver::run_compiler(&args, &mut MiriCompilerCalls { host_target }, None, Some(Box::new(buf)));
});
match result {

View file

@ -11,115 +11,46 @@ extern crate rustc_metadata;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_codegen_utils;
extern crate rustc_interface;
extern crate syntax;
use std::path::PathBuf;
use std::str::FromStr;
use std::env;
use miri::MiriConfig;
use rustc::session::Session;
use rustc_metadata::cstore::CStore;
use rustc_driver::{Compilation, CompilerCalls, RustcDefaultCalls};
use rustc_driver::driver::{CompileState, CompileController};
use rustc::session::config::{self, Input, ErrorOutputType};
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc_interface::interface;
use rustc::hir::def_id::LOCAL_CRATE;
use syntax::ast;
struct MiriCompilerCalls {
default: Box<RustcDefaultCalls>,
miri_config: MiriConfig,
miri_config: miri::MiriConfig,
}
impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
fn early_callback(
&mut self,
matches: &getopts::Matches,
sopts: &config::Options,
cfg: &ast::CrateConfig,
descriptions: &rustc_errors::registry::Registry,
output: ErrorOutputType,
) -> Compilation {
self.default.early_callback(
matches,
sopts,
cfg,
descriptions,
output,
)
impl rustc_driver::Callbacks for MiriCompilerCalls {
fn after_parsing(&mut self, compiler: &interface::Compiler) -> bool {
let attr = (
String::from("miri"),
syntax::feature_gate::AttributeType::Whitelisted,
);
compiler.session().plugin_attributes.borrow_mut().push(attr);
// Continue execution
true
}
fn no_input(
&mut self,
matches: &getopts::Matches,
sopts: &config::Options,
cfg: &ast::CrateConfig,
odir: &Option<PathBuf>,
ofile: &Option<PathBuf>,
descriptions: &rustc_errors::registry::Registry,
) -> Option<(Input, Option<PathBuf>)> {
self.default.no_input(
matches,
sopts,
cfg,
odir,
ofile,
descriptions,
)
fn after_analysis(&mut self, compiler: &interface::Compiler) -> bool {
init_late_loggers();
compiler.session().abort_if_errors();
compiler.global_ctxt().unwrap().peek_mut().enter(|tcx| {
let (entry_def_id, _) = tcx.entry_fn(LOCAL_CRATE).expect("no main function found!");
miri::eval_main(tcx, entry_def_id, self.miri_config.clone());
});
compiler.session().abort_if_errors();
// Don't continue execution
false
}
fn late_callback(
&mut self,
codegen_backend: &CodegenBackend,
matches: &getopts::Matches,
sess: &Session,
cstore: &CStore,
input: &Input,
odir: &Option<PathBuf>,
ofile: &Option<PathBuf>,
) -> Compilation {
// Called *before* `build_controller`. Add filename to `miri` arguments.
self.miri_config.args.insert(0, input.filestem().to_string());
self.default.late_callback(codegen_backend, matches, sess, cstore, input, odir, ofile)
}
fn build_controller(
self: Box<Self>,
sess: &Session,
matches: &getopts::Matches,
) -> CompileController<'a> {
let this = *self;
let mut control = this.default.build_controller(sess, matches);
control.after_hir_lowering.callback = Box::new(after_hir_lowering);
let miri_config = this.miri_config;
control.after_analysis.callback =
Box::new(move |state| after_analysis(state, miri_config.clone()));
control.after_analysis.stop = Compilation::Stop;
control
}
}
fn after_hir_lowering(state: &mut CompileState) {
let attr = (
String::from("miri"),
syntax::feature_gate::AttributeType::Whitelisted,
);
state.session.plugin_attributes.borrow_mut().push(attr);
}
fn after_analysis<'a, 'tcx>(
state: &mut CompileState<'a, 'tcx>,
miri_config: MiriConfig,
) {
init_late_loggers();
state.session.abort_if_errors();
let tcx = state.tcx.unwrap();
let (entry_def_id, _) = tcx.entry_fn(LOCAL_CRATE).expect("no main function found!");
miri::eval_main(tcx, entry_def_id, miri_config);
state.session.abort_if_errors();
}
fn init_early_loggers() {
@ -228,12 +159,9 @@ fn main() {
debug!("rustc arguments: {:?}", rustc_args);
debug!("miri arguments: {:?}", miri_args);
let miri_config = MiriConfig { validate, args: miri_args };
let result = rustc_driver::run(move || {
rustc_driver::run_compiler(&rustc_args, Box::new(MiriCompilerCalls {
default: Box::new(RustcDefaultCalls),
miri_config,
}), None, None)
});
std::process::exit(result as i32);
let miri_config = miri::MiriConfig { validate, args: miri_args };
let result = rustc_driver::report_ices_to_stderr_if_any(move || {
rustc_driver::run_compiler(&rustc_args, &mut MiriCompilerCalls { miri_config }, None, None)
}).and_then(|result| result);
std::process::exit(result.is_err() as i32);
}