From eb153810e35748d2b4556d39dd6778d35ceb1a9e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 31 Oct 2018 10:09:55 +0100 Subject: [PATCH] Use MIRI_ env vars to set RUST_ ones This means we can do `MIRI_LOG=debug cargo run` and get something reasonable, even if cargo has to build some dependencies first. --- src/bin/miri.rs | 64 +++++++++++++++++++++---------------------------- src/lib.rs | 15 +++++++++++- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/src/bin/miri.rs b/src/bin/miri.rs index d4494a838852..c8103c2a1176 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -12,6 +12,9 @@ extern crate log_settings; extern crate syntax; extern crate log; +use std::path::PathBuf; +use std::env; + use rustc::session::Session; use rustc_metadata::cstore::CStore; use rustc_driver::{Compilation, CompilerCalls, RustcDefaultCalls}; @@ -21,7 +24,6 @@ use rustc::hir::{self, itemlikevisit}; use rustc::ty::TyCtxt; use rustc_codegen_utils::codegen_backend::CodegenBackend; use syntax::ast; -use std::path::PathBuf; struct MiriCompilerCalls { default: Box, @@ -148,42 +150,31 @@ fn after_analysis<'a, 'tcx>( } } -fn init_logger() { - let format = |formatter: &mut env_logger::fmt::Formatter, record: &log::Record| { - use std::io::Write; - if record.level() == log::Level::Trace { - // prepend frame number - let indentation = log_settings::settings().indentation; - writeln!( - formatter, - "{indentation}:{lvl}:{module}: {text}", - lvl = record.level(), - module = record.module_path().unwrap_or(""), - indentation = indentation, - text = record.args(), - ) - } else { - writeln!( - formatter, - "{lvl}:{module}: {text}", - lvl = record.level(), - module = record.module_path().unwrap_or(""), - text = record.args(), - ) +fn init_loggers() { + // Notice that our `extern crate log` is NOT the same as rustc's! So we have to initialize + // them both. + // First, miri. + let env = env_logger::Env::new().filter("MIRI_LOG").write_style("MIRI_LOG_STYLE"); + env_logger::init_from_env(env); + // Now, change the RUST_LOG env var to control rustc's logger. + // If MIRI_LOG is set and RUST_LOG is not, set RUST_LOG. + if let Ok(var) = env::var("MIRI_LOG") { + if env::var("RUST_LOG") == Err(env::VarError::NotPresent) { + // We try to be a bit clever here: If MIRI_LOG is just a single level + // used for everything, we only apply it to the parts of rustc that are + // CTFE-related. Only if MIRI_LOG contains `module=level`, we just + // use the same value for RUST_LOG. + // This way, if you set `MIRI_LOG=trace`, you get only the right parts of + // rustc traced, but you can also do `MIRI_LOG=miri=trace,rustc_mir::interpret=debug`. + if var.contains('=') { + env::set_var("RUST_LOG", &var); + } else { + env::set_var("RUST_LOG", + &format!("rustc::mir::interpret={0},rustc_mir::interpret={0}", var)); + } } - }; - - let mut builder = env_logger::Builder::new(); - builder.format(format).filter( - None, - log::LevelFilter::Info, - ); - - if std::env::var("MIRI_LOG").is_ok() { - builder.parse(&std::env::var("MIRI_LOG").unwrap()); } - - builder.init(); + rustc_driver::init_rustc_env_logger(); } fn find_sysroot() -> String { @@ -208,8 +199,7 @@ fn find_sysroot() -> String { } fn main() { - rustc_driver::init_rustc_env_logger(); - init_logger(); + init_loggers(); let mut args: Vec = std::env::args().collect(); let sysroot_flag = String::from("--sysroot"); diff --git a/src/lib.rs b/src/lib.rs index 9f4eb00877e4..fa60a0da00d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,10 +11,12 @@ extern crate rustc; extern crate rustc_data_structures; extern crate rustc_mir; extern crate rustc_target; +extern crate rustc_driver; extern crate syntax; use std::collections::HashMap; use std::borrow::Cow; +use std::env; use rustc::ty::{self, Ty, TyCtxt, query::TyCtxtAt}; use rustc::ty::layout::{TyLayout, LayoutOf, Size}; @@ -157,11 +159,21 @@ pub fn eval_main<'a, 'tcx: 'a>( ) { let mut ecx = create_ecx(tcx, main_id, validate).expect("Couldn't create ecx"); + // If MIRI_BACKTRACE is set and RUST_CTFE_BACKTRACE is not, set RUST_CTFE_BACKTRACE. + // Do this late, so we really only apply this to miri's errors. + if let Ok(var) = env::var("MIRI_BACKTRACE") { + if env::var("RUST_CTFE_BACKTRACE") == Err(env::VarError::NotPresent) { + env::set_var("RUST_CTFE_BACKTRACE", &var); + } + } + + // Run! The main execution. let res: EvalResult = (|| { ecx.run()?; ecx.run_tls_dtors() })(); + // Process the result. match res { Ok(()) => { let leaks = ecx.memory().leak_report(); @@ -173,7 +185,8 @@ pub fn eval_main<'a, 'tcx: 'a>( tcx.sess.err("the evaluated program leaked memory"); } } - Err(e) => { + Err(mut e) => { + e.print_backtrace(); if let Some(frame) = ecx.stack().last() { let block = &frame.mir.basic_blocks()[frame.block]; let span = if frame.stmt < block.statements.len() {