diff --git a/.travis.yml b/.travis.yml index d2315c7e9538..095af11627fa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,9 +18,8 @@ before_script: if [ "$TRAVIS_EVENT_TYPE" = cron ]; then RUST_TOOLCHAIN=nightly else - RUST_TOOLCHAIN=$(cat rust-toolchain) + RUST_TOOLCHAIN=$(cat rust-version) fi -- rm rust-toolchain # install Rust - curl https://build.travis-ci.org/files/rustup-init.sh -sSf | sh -s -- -y --default-toolchain "$RUST_TOOLCHAIN" - export PATH=$HOME/.cargo/bin:$PATH diff --git a/README.md b/README.md index e59accaea1b9..0e88c8138a51 100644 --- a/README.md +++ b/README.md @@ -7,18 +7,28 @@ undergraduate research course at the [University of Saskatchewan][usask]. ## Building Miri -I recommend that you install [rustup][rustup] to obtain Rust. Miri comes with a -`rust-toolchain` file so rustup will automatically pick a suitable nightly -version. Then all you have to do is: +I recommend that you install [rustup][rustup] to obtain Rust. Then all you have +to do is: ```sh -cargo build +cargo +nightly build ``` +This uses the very latest Rust version. If you experience any problem, refer to +the `rust-version` file which contains a particular Rust nightly version that +has been tested against the version of miri you are using. Make sure to use +that particular `nightly-YYYY-MM-DD` whenever the instructions just say +`nightly`. + +To avoid repeating the nightly version all the time, you can use +`rustup override set nightly` (or `rustup override set nightly-YYYY-MM-DD`), +which means `nightly` Rust will automatically be used whenever you are working +in this directory. + ## Running Miri ```sh -cargo run tests/run-pass/vecs.rs # Or whatever test you like. +cargo +nightly run tests/run-pass/vecs.rs # Or whatever test you like. ``` ## Running Miri with full libstd @@ -28,40 +38,77 @@ Miri hits a call to such a function, execution terminates. To fix this, it is possible to compile libstd with full MIR: ```sh -rustup component add rust-src -cargo install xargo -xargo/build.sh +rustup component add --toolchain nightly rust-src +cargo +nightly install xargo +rustup run nightly xargo/build.sh ``` Now you can run Miri against the libstd compiled by xargo: ```sh -MIRI_SYSROOT=~/.xargo/HOST cargo run tests/run-pass-fullmir/hashmap.rs +MIRI_SYSROOT=~/.xargo/HOST cargo +nightly run tests/run-pass-fullmir/hashmap.rs ``` -Notice that you will have to re-run the last step of the preparations above when -your toolchain changes (e.g., when you update the nightly). - -You can also set `-Zmiri-start-fn` to make Miri start evaluation with the -`start_fn` lang item, instead of starting at the `main` function. +Notice that you will have to re-run the last step of the preparations above +(`xargo/build.sh`) when your toolchain changes (e.g., when you update the +nightly). ## Running Miri on your own project('s test suite) -Install Miri as a cargo subcommand with `cargo install --all-features`, and install -a full libstd as described above. +Install Miri as a cargo subcommand with `cargo install +nightly --all-features +--path .`. Be aware that if you used `rustup override set` to fix a particular +Rust version for the miri directory, that will *not* apply to your own project +directory! You have to use a consistent Rust version for building miri and your +project for this to work, so remember to either always specify the nightly +version manually, overriding it in your project directory as well, or use +`rustup default nightly` (or `rustup default nightly-YYYY-MM-DD`) to globally +make `nightly` the default toolchain. -Then, inside your own project, use `MIRI_SYSROOT=~/.xargo/HOST cargo +nightly -miri` to run your project, if it is a bin project, or run -`MIRI_SYSROOT=~/.xargo/HOST cargo +nightly miri test` to run all tests in your -project through Miri. +We assume that you have prepared a MIR-enabled libstd as described above. Now +compile your project and its dependencies against that libstd: + +1. Run `cargo clean` to eliminate any cached dependencies that were built against +the non-MIR `libstd`. +2. To run all tests in your project through, Miri, use +`MIRI_SYSROOT=~/.xargo/HOST cargo +nightly miri test`. +3. If you have a binary project, you can run it through Miri using +`MIRI_SYSROOT=~/.xargo/HOST cargo +nightly miri`. + +### Common Problems + +When using the above instructions, you may encounter a number of confusing compiler +errors. + +#### "constant evaluation error: no mir for ``" + +You may have forgotten to set `MIRI_SYSROOT` when calling `cargo miri`, and +your program called into `std` or `core`. Be sure to set `MIRI_SYSROOT=~/.xargo/HOST`. + +#### "found possibly newer version of crate `std` which `` depends on" + +Your build directory may contain artifacts from an earlier build that did/did not +have `MIRI_SYSROOT` set. Run `cargo clean` before switching from non-Miri to Miri +builds and vice-versa. + +#### "found crate `std` compiled by an incompatible version of rustc" + +You may be running `cargo miri` with a different compiler version than the one +used to build the MIR-enabled `std`. Be sure to consistently use the same toolchain, +which should be the toolchain specified in the `rust-version` file. ## Miri `-Z` flags -Miri adds some extra `-Z` flags to control its behavior: +Several `-Z` flags are relevant for miri: -* `-Zmiri-start-fn`: This makes interpretation start with `lang_start` (defined - in libstd) instead of starting with `main`. Requires full MIR! -* `-Zmiri-disable-validation` disables enforcing the validity invariant. +* `-Zmir-opt-level` controls how many MIR optimizations are performed. miri + overrides the default to be `0`; be advised that using any higher level can + make miri miss bugs in your program because they got optimized away. +* `-Zalways-encode-mir` makes rustc dump MIR even for completely monomorphic + functions. This is needed so that miri can execute such functions, so miri + sets this flag per default. +* `-Zmiri-disable-validation` is a custom `-Z` flag added by miri. It disables + enforcing the validity invariant, which is enforced by default. This is + mostly useful for debugging; it means miri will miss bugs in your program. ## Development and Debugging diff --git a/appveyor.yml b/appveyor.yml index 4614891a3129..cf578120c9dd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,7 +16,7 @@ branches: install: # install Rust - set PATH=C:\Program Files\Git\mingw64\bin;C:\msys64\mingw%MSYS2_BITS%\bin;%PATH% - - set /p RUST_TOOLCHAIN= EvalContextExt<'tcx, 'mir> for super::MiriEvalCo "free" => { let ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation, no tag - if !ptr.is_null() { + if !ptr.is_null_ptr(&self) { self.memory_mut().deallocate( ptr.to_ptr()?.with_default_tag(), None, @@ -355,7 +355,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo let mut success = None; { let name_ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation - if !name_ptr.is_null() { + if !name_ptr.is_null_ptr(&self) { let name = self.memory().read_c_str(name_ptr.to_ptr()? .with_default_tag())?.to_owned(); if !name.is_empty() && !name.contains(&b'=') { @@ -379,7 +379,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo let name_ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation let value_ptr = self.read_scalar(args[1])?.to_ptr()?.erase_tag(); // raw ptr operation let value = self.memory().read_c_str(value_ptr.with_default_tag())?; - if !name_ptr.is_null() { + if !name_ptr.is_null_ptr(&self) { let name = self.memory().read_c_str(name_ptr.to_ptr()?.with_default_tag())?; if !name.is_empty() && !name.contains(&b'=') { new = Some((name.to_owned(), value.to_owned())); diff --git a/src/intrinsic.rs b/src/intrinsic.rs index 98c57894a9d6..ee8df3e25ec1 100644 --- a/src/intrinsic.rs +++ b/src/intrinsic.rs @@ -231,7 +231,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, ' let a = self.read_value(args[0])?; let b = self.read_value(args[1])?; // check x % y != 0 - if !self.binary_op_val(mir::BinOp::Rem, a, b)?.0.is_null() { + if self.binary_op_val(mir::BinOp::Rem, a, b)?.0.to_bytes()? != 0 { return err!(ValidationFailure(format!("exact_div: {:?} cannot be divided by {:?}", a, b))); } self.binop_ignore_overflow(mir::BinOp::Div, a, b, dest)?; diff --git a/src/tls.rs b/src/tls.rs index 2bddc43df8c4..b315e27c45d0 100644 --- a/src/tls.rs +++ b/src/tls.rs @@ -121,7 +121,7 @@ impl<'tcx> TlsData<'tcx> { for (&key, &mut TlsEntry { ref mut data, dtor }) in thread_local.range_mut((start, Unbounded)) { - if !data.is_null() { + if !data.is_null_ptr(cx) { if let Some(dtor) = dtor { let ret = Some((dtor, *data, key)); *data = Scalar::ptr_null(cx);