]> git.lizzy.rs Git - rust.git/blobdiff - src/bin/miri.rs
rustup for more LocalDefId changes
[rust.git] / src / bin / miri.rs
index 6e67246d2ca1d4fec3a72655ebad568faf2e7ff2..06101fe24e2d8256d541790b71599ab1c2542099 100644 (file)
@@ -1,61 +1,54 @@
 #![feature(rustc_private)]
 
-extern crate env_logger;
-extern crate getopts;
-#[macro_use]
-extern crate log;
-extern crate log_settings;
-extern crate miri;
-extern crate rustc;
-extern crate rustc_metadata;
+extern crate rustc_middle;
 extern crate rustc_driver;
-extern crate rustc_errors;
-extern crate rustc_codegen_utils;
+extern crate rustc_hir;
 extern crate rustc_interface;
-extern crate syntax;
+extern crate rustc_session;
 
-use std::str::FromStr;
+use std::convert::TryFrom;
 use std::env;
+use std::str::FromStr;
 
 use hex::FromHexError;
+use log::debug;
 
-use rustc_interface::interface;
-use rustc::hir::def_id::LOCAL_CRATE;
+use rustc_session::CtfeBacktrace;
+use rustc_driver::Compilation;
+use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_interface::{interface, Queries};
+use rustc_middle::ty::TyCtxt;
 
 struct MiriCompilerCalls {
     miri_config: miri::MiriConfig,
 }
 
 impl rustc_driver::Callbacks for MiriCompilerCalls {
-    fn after_parsing(&mut self, compiler: &interface::Compiler) -> bool {
-        let attr = (
-            syntax::symbol::Symbol::intern("miri"),
-            syntax::feature_gate::AttributeType::Whitelisted,
-        );
-        compiler.session().plugin_attributes.borrow_mut().push(attr);
-
-        // Continue execution
-        true
-    }
-
-    fn after_analysis(&mut self, compiler: &interface::Compiler) -> bool {
-        init_late_loggers();
+    fn after_analysis<'tcx>(
+        &mut self,
+        compiler: &interface::Compiler,
+        queries: &'tcx Queries<'tcx>,
+    ) -> Compilation {
         compiler.session().abort_if_errors();
 
-        compiler.global_ctxt().unwrap().peek_mut().enter(|tcx| {
+        queries.global_ctxt().unwrap().peek_mut().enter(|tcx| {
+            init_late_loggers(tcx);
             let (entry_def_id, _) = tcx.entry_fn(LOCAL_CRATE).expect("no main function found!");
             let mut config = self.miri_config.clone();
 
             // Add filename to `miri` arguments.
             config.args.insert(0, compiler.input().filestem().to_string());
 
-            miri::eval_main(tcx, entry_def_id, config);
+            if let Some(return_code) = miri::eval_main(tcx, entry_def_id.to_def_id(), config) {
+                std::process::exit(
+                    i32::try_from(return_code).expect("Return value was too large!"),
+                );
+            }
         });
 
         compiler.session().abort_if_errors();
 
-        // Don't continue execution
-        false
+        Compilation::Stop
     }
 }
 
@@ -73,7 +66,7 @@ fn init_early_loggers() {
     }
 }
 
-fn init_late_loggers() {
+fn init_late_loggers(tcx: TyCtxt<'_>) {
     // We initialize loggers right before we start evaluation. We overwrite the `RUSTC_LOG`
     // env var if it is not set, control it based on `MIRI_LOG`.
     if let Ok(var) = env::var("MIRI_LOG") {
@@ -84,8 +77,10 @@ fn init_late_loggers() {
             // 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 log::Level::from_str(&var).is_ok() {
-                env::set_var("RUSTC_LOG",
-                    &format!("rustc::mir::interpret={0},rustc_mir::interpret={0}", var));
+                env::set_var(
+                    "RUSTC_LOG",
+                    &format!("rustc_middle::mir::interpret={0},rustc_mir::interpret={0}", var),
+                );
             } else {
                 env::set_var("RUSTC_LOG", &var);
             }
@@ -93,12 +88,15 @@ fn init_late_loggers() {
         }
     }
 
-    // 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);
-        }
+    // If `MIRI_BACKTRACE` is set and `RUSTC_CTFE_BACKTRACE` is not, set `RUSTC_CTFE_BACKTRACE`.
+    // Do this late, so we ideally only apply this to Miri's errors.
+    if let Ok(val) = env::var("MIRI_BACKTRACE") {
+        let ctfe_backtrace = match &*val {
+            "immediate" => CtfeBacktrace::Immediate,
+            "0" => CtfeBacktrace::Disabled,
+            _ => CtfeBacktrace::Capture,
+        };
+        *tcx.sess.ctfe_backtrace.borrow_mut() = ctfe_backtrace;
     }
 }
 
@@ -118,11 +116,9 @@ fn compile_time_sysroot() -> Option<String> {
     let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
     Some(match (home, toolchain) {
         (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
-        _ => {
-            option_env!("RUST_SYSROOT")
-                .expect("To build Miri without rustup, set the `RUST_SYSROOT` env var at build time")
-                .to_owned()
-        }
+        _ => option_env!("RUST_SYSROOT")
+            .expect("To build Miri without rustup, set the `RUST_SYSROOT` env var at build time")
+            .to_owned(),
     })
 }
 
@@ -131,23 +127,41 @@ fn main() {
 
     // Parse our arguments and split them across `rustc` and `miri`.
     let mut validate = true;
+    let mut stacked_borrows = true;
+    let mut check_alignment = true;
+    let mut communicate = false;
+    let mut ignore_leaks = false;
     let mut seed: Option<u64> = None;
+    let mut tracked_pointer_tag: Option<miri::PtrId> = None;
+    let mut tracked_alloc_id: Option<miri::AllocId> = None;
     let mut rustc_args = vec![];
     let mut miri_args = vec![];
     let mut after_dashdash = false;
+    let mut excluded_env_vars = vec![];
     for arg in std::env::args() {
         if rustc_args.is_empty() {
             // Very first arg: for `rustc`.
             rustc_args.push(arg);
-        }
-        else if after_dashdash {
+        } else if after_dashdash {
             // Everything that comes after are `miri` args.
             miri_args.push(arg);
         } else {
             match arg.as_str() {
                 "-Zmiri-disable-validation" => {
                     validate = false;
-                },
+                }
+                "-Zmiri-disable-stacked-borrows" => {
+                    stacked_borrows = false;
+                }
+                "-Zmiri-disable-alignment-check" => {
+                    check_alignment = false;
+                }
+                "-Zmiri-disable-isolation" => {
+                    communicate = true;
+                }
+                "-Zmiri-ignore-leaks" => {
+                    ignore_leaks = true;
+                }
                 "--" => {
                     after_dashdash = true;
                 }
@@ -160,18 +174,51 @@ fn main() {
                             FromHexError::InvalidHexCharacter { .. } => panic!(
                                 "-Zmiri-seed should only contain valid hex digits [0-9a-fA-F]"
                             ),
-                            FromHexError::OddLength => panic!("-Zmiri-seed should have an even number of digits"),
+                            FromHexError::OddLength =>
+                                panic!("-Zmiri-seed should have an even number of digits"),
                             err => panic!("Unknown error decoding -Zmiri-seed as hex: {:?}", err),
                         });
                     if seed_raw.len() > 8 {
-                        panic!(format!("-Zmiri-seed must be at most 8 bytes, was {}", seed_raw.len()));
+                        panic!(format!(
+                            "-Zmiri-seed must be at most 8 bytes, was {}",
+                            seed_raw.len()
+                        ));
                     }
 
                     let mut bytes = [0; 8];
                     bytes[..seed_raw.len()].copy_from_slice(&seed_raw);
                     seed = Some(u64::from_be_bytes(bytes));
-
-                },
+                }
+                arg if arg.starts_with("-Zmiri-env-exclude=") => {
+                    excluded_env_vars
+                        .push(arg.trim_start_matches("-Zmiri-env-exclude=").to_owned());
+                }
+                arg if arg.starts_with("-Zmiri-track-pointer-tag=") => {
+                    let id: u64 = match arg.trim_start_matches("-Zmiri-track-pointer-tag=").parse()
+                    {
+                        Ok(id) => id,
+                        Err(err) => panic!(
+                            "-Zmiri-track-pointer-tag requires a valid `u64` as the argument: {}",
+                            err
+                        ),
+                    };
+                    if let Some(id) = miri::PtrId::new(id) {
+                        tracked_pointer_tag = Some(id);
+                    } else {
+                        panic!("-Zmiri-track-pointer-tag must be a nonzero id");
+                    }
+                }
+                arg if arg.starts_with("-Zmiri-track-alloc-id=") => {
+                    let id: u64 = match arg.trim_start_matches("-Zmiri-track-alloc-id=").parse()
+                    {
+                        Ok(id) => id,
+                        Err(err) => panic!(
+                            "-Zmiri-track-alloc-id requires a valid `u64` as the argument: {}",
+                            err
+                        ),
+                    };
+                    tracked_alloc_id = Some(miri::AllocId(id));
+                }
                 _ => {
                     rustc_args.push(arg);
                 }
@@ -197,9 +244,26 @@ fn main() {
 
     debug!("rustc arguments: {:?}", rustc_args);
     debug!("miri arguments: {:?}", miri_args);
-    let miri_config = miri::MiriConfig { validate, args: miri_args, seed };
-    let result = rustc_driver::report_ices_to_stderr_if_any(move || {
+    let miri_config = miri::MiriConfig {
+        validate,
+        stacked_borrows,
+        check_alignment,
+        communicate,
+        ignore_leaks,
+        excluded_env_vars,
+        seed,
+        args: miri_args,
+        tracked_pointer_tag,
+        tracked_alloc_id,
+    };
+    rustc_driver::install_ice_hook();
+    let result = rustc_driver::catch_fatal_errors(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);
+    })
+    .and_then(|result| result);
+    let exit_code = match result {
+        Ok(()) => rustc_driver::EXIT_SUCCESS,
+        Err(_) => rustc_driver::EXIT_FAILURE,
+    };
+    std::process::exit(exit_code);
 }