Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into rustup
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Oct 26, 2018
2 parents a34b9c7 + 09a3f72 commit 4a98f64
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 33 deletions.
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
97 changes: 72 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:

## Miri `-Z` flags
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 `<function>`"

Miri adds some extra `-Z` flags to control its behavior:
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 `<dependency>` 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

* `-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.
Several `-Z` flags are relevant for miri:

* `-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

Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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=<rust-toolchain
- set /p RUST_TOOLCHAIN=<rust-version
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
- rustup-init.exe -y --default-host %TARGET% --default-toolchain %RUST_TOOLCHAIN%
- set PATH=%USERPROFILE%\.cargo\bin;%PATH%
Expand Down
File renamed without changes.
6 changes: 3 additions & 3 deletions src/fn_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> 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,
Expand Down Expand Up @@ -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'=') {
Expand All @@ -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()));
Expand Down
2 changes: 1 addition & 1 deletion src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand Down
2 changes: 1 addition & 1 deletion src/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 4a98f64

Please sign in to comment.