Skip to content

Commit 85d089b

Browse files
committed
Auto merge of #103392 - RalfJung:miri, r=oli-obk
update Miri I had to use a hacked version of josh to create this, so let's be careful with merging this and maybe wait a bit to see if the josh issue becomes more clear. But the history looks good to me, we are not adding duplicates of rustc commits that were previously mirrored to Miri. Also I want to add some cross-testing of Miri in x.py.
2 parents c6bd7e2 + a157e0e commit 85d089b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+1522
-470
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -2262,6 +2262,7 @@ dependencies = [
22622262
"rand 0.8.5",
22632263
"regex",
22642264
"rustc-workspace-hack",
2265+
"rustc_version",
22652266
"shell-escape",
22662267
"smallvec",
22672268
"ui_test",

src/bootstrap/test.rs

+49-5
Original file line numberDiff line numberDiff line change
@@ -461,24 +461,30 @@ impl Step for RustDemangler {
461461
pub struct Miri {
462462
stage: u32,
463463
host: TargetSelection,
464+
target: TargetSelection,
464465
}
465466

466467
impl Step for Miri {
467468
type Output = ();
468-
const ONLY_HOSTS: bool = true;
469+
const ONLY_HOSTS: bool = false;
469470

470471
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
471472
run.path("src/tools/miri")
472473
}
473474

474475
fn make_run(run: RunConfig<'_>) {
475-
run.builder.ensure(Miri { stage: run.builder.top_stage, host: run.target });
476+
run.builder.ensure(Miri {
477+
stage: run.builder.top_stage,
478+
host: run.build_triple(),
479+
target: run.target,
480+
});
476481
}
477482

478483
/// Runs `cargo test` for miri.
479484
fn run(self, builder: &Builder<'_>) {
480485
let stage = self.stage;
481486
let host = self.host;
487+
let target = self.target;
482488
let compiler = builder.compiler(stage, host);
483489
// We need the stdlib for the *next* stage, as it was built with this compiler that also built Miri.
484490
// Except if we are at stage 2, the bootstrap loop is complete and we can stick with our current stage.
@@ -495,7 +501,7 @@ impl Step for Miri {
495501
builder.ensure(compile::Std::new(compiler_std, host));
496502
let sysroot = builder.sysroot(compiler_std);
497503

498-
// # Run `cargo miri setup`.
504+
// # Run `cargo miri setup` for the given target.
499505
let mut cargo = tool::prepare_tool_cargo(
500506
builder,
501507
compiler,
@@ -508,6 +514,7 @@ impl Step for Miri {
508514
);
509515
cargo.add_rustc_lib_path(builder, compiler);
510516
cargo.arg("--").arg("miri").arg("setup");
517+
cargo.arg("--target").arg(target.rustc_target_arg());
511518

512519
// Tell `cargo miri setup` where to find the sources.
513520
cargo.env("MIRI_LIB_SRC", builder.src.join("library"));
@@ -556,17 +563,54 @@ impl Step for Miri {
556563
cargo.add_rustc_lib_path(builder, compiler);
557564

558565
// miri tests need to know about the stage sysroot
559-
cargo.env("MIRI_SYSROOT", miri_sysroot);
566+
cargo.env("MIRI_SYSROOT", &miri_sysroot);
560567
cargo.env("MIRI_HOST_SYSROOT", sysroot);
561568
cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
562-
cargo.env("MIRI", miri);
569+
cargo.env("MIRI", &miri);
563570
// propagate --bless
564571
if builder.config.cmd.bless() {
565572
cargo.env("MIRI_BLESS", "Gesundheit");
566573
}
567574

575+
// Set the target.
576+
cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
577+
// Forward test filters.
578+
cargo.arg("--").args(builder.config.cmd.test_args());
579+
580+
let mut cargo = Command::from(cargo);
581+
builder.run(&mut cargo);
582+
583+
// # Run `cargo miri test`.
584+
// This is just a smoke test (Miri's own CI invokes this in a bunch of different ways and ensures
585+
// that we get the desired output), but that is sufficient to make sure that the libtest harness
586+
// itself executes properly under Miri.
587+
let mut cargo = tool::prepare_tool_cargo(
588+
builder,
589+
compiler,
590+
Mode::ToolRustc,
591+
host,
592+
"run",
593+
"src/tools/miri/cargo-miri",
594+
SourceType::Submodule,
595+
&[],
596+
);
597+
cargo.add_rustc_lib_path(builder, compiler);
598+
cargo.arg("--").arg("miri").arg("test");
599+
cargo
600+
.arg("--manifest-path")
601+
.arg(builder.src.join("src/tools/miri/test-cargo-miri/Cargo.toml"));
602+
cargo.arg("--target").arg(target.rustc_target_arg());
603+
cargo.arg("--tests"); // don't run doctests, they are too confused by the staging
568604
cargo.arg("--").args(builder.config.cmd.test_args());
569605

606+
// Tell `cargo miri` where to find things.
607+
cargo.env("MIRI_SYSROOT", &miri_sysroot);
608+
cargo.env("MIRI_HOST_SYSROOT", sysroot);
609+
cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
610+
cargo.env("MIRI", &miri);
611+
// Debug things.
612+
cargo.env("RUST_BACKTRACE", "1");
613+
570614
let mut cargo = Command::from(cargo);
571615
builder.run(&mut cargo);
572616
}

src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh

+5
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,8 @@ python3 "$X_PY" test --stage 2 check-tools
2525
python3 "$X_PY" test --stage 2 src/tools/clippy
2626
python3 "$X_PY" test --stage 2 src/tools/rustfmt
2727
python3 "$X_PY" test --stage 2 src/tools/miri
28+
# We natively run this script on x86_64-unknown-linux-gnu and x86_64-pc-windows-msvc.
29+
# Also cover some other targets (on both of these hosts) via cross-testing.
30+
python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-msvc
31+
#FIXME(https://github.com/rust-lang/rust/issues/103519): macOS testing is currently disabled
32+
# python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin

src/tools/miri/.github/workflows/ci.yml

+40-4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ jobs:
2222
RUST_BACKTRACE: 1
2323
HOST_TARGET: ${{ matrix.host_target }}
2424
strategy:
25+
fail-fast: false
2526
matrix:
2627
build: [linux64, macos, win32]
2728
include:
@@ -61,7 +62,7 @@ jobs:
6162
restore-keys: ${{ runner.os }}-cargo
6263

6364
- name: Install rustup-toolchain-install-master
64-
if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
65+
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
6566
shell: bash
6667
run: |
6768
cargo install -f rustup-toolchain-install-master
@@ -89,11 +90,46 @@ jobs:
8990
runs-on: ubuntu-latest
9091
steps:
9192
- uses: actions/checkout@v3
92-
- name: Install required toolchain
93-
# We need a toolchain that can actually build Miri, just a nightly won't do.
93+
94+
# This is exactly duplicated from above. GHA is pretty terrible when it comes
95+
# to avoiding code duplication.
96+
97+
# Cache the global cargo directory, but NOT the local `target` directory which
98+
# we cannot reuse anyway when the nightly changes (and it grows quite large
99+
# over time).
100+
- name: Add cache for cargo
101+
id: cache
102+
uses: actions/cache@v3
103+
with:
104+
path: |
105+
# Taken from <https://doc.rust-lang.org/nightly/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci>.
106+
~/.cargo/bin
107+
~/.cargo/registry/index
108+
~/.cargo/registry/cache
109+
~/.cargo/git/db
110+
# contains package information of crates installed via `cargo install`.
111+
~/.cargo/.crates.toml
112+
~/.cargo/.crates2.json
113+
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
114+
restore-keys: ${{ runner.os }}-cargo
115+
116+
- name: Install rustup-toolchain-install-master
117+
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
118+
shell: bash
119+
run: |
120+
cargo install -f rustup-toolchain-install-master
121+
122+
- name: Install "master" toolchain
123+
shell: bash
94124
run: |
95-
cargo install rustup-toolchain-install-master # TODO: cache this?
96125
./rustup-toolchain "" -c clippy
126+
127+
- name: Show Rust version
128+
run: |
129+
rustup show
130+
rustc -Vv
131+
cargo -V
132+
97133
- name: rustfmt
98134
run: ./miri fmt --check
99135
- name: clippy

src/tools/miri/CONTRIBUTING.md

+50-2
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ MIRI_LOG=rustc_mir::interpret=info,miri::stacked_borrows ./miri run tests/pass/v
104104
In addition, you can set `MIRI_BACKTRACE=1` to get a backtrace of where an
105105
evaluation error was originally raised.
106106

107-
#### UI testing
107+
### UI testing
108108

109109
We use ui-testing in Miri, meaning we generate `.stderr` and `.stdout` files for the output
110110
produced by Miri. You can use `./miri bless` to automatically (re)generate these files when
@@ -257,7 +257,7 @@ Note: When you are working with a locally built rustc or any other toolchain tha
257257
is not the same as the one in `rust-version`, you should not have `.auto-everything` or
258258
`.auto-toolchain` as that will keep resetting your toolchain.
259259

260-
```
260+
```sh
261261
rm -f .auto-everything .auto-toolchain
262262
```
263263

@@ -275,3 +275,51 @@ see <https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html>.
275275

276276
With this, you should now have a working development setup! See
277277
[above](#building-and-testing-miri) for how to proceed working on Miri.
278+
279+
## Advanced topic: Syncing with the rustc repo
280+
281+
We use the [`josh` proxy](https://github.com/josh-project/josh) to transmit
282+
changes between the rustc and Miri repositories. For now, a fork of josh needs to be built
283+
from source. This downloads and runs josh:
284+
285+
```sh
286+
git clone https://github.com/RalfJung/josh
287+
cd josh
288+
cargo run --release -p josh-proxy -- --local=$(pwd)/local --remote=https://github.com --no-background
289+
```
290+
291+
### Importing changes from the rustc repo
292+
293+
We assume we start on an up-to-date master branch in the Miri repo.
294+
295+
```sh
296+
# Fetch rustc side of the history. Takes ca 5 min the first time.
297+
# Do NOT change that commit ID, it needs to be exactly this!
298+
git fetch http://localhost:8000/rust-lang/rust.git:at_commit=75dd959a3a40eb5b4574f8d2e23aa6efbeb33573[:prefix=src/tools/miri]:/src/tools/miri.git master
299+
# Include that history into ours.
300+
git merge FETCH_HEAD -m "merge rustc history"
301+
# Update toolchain reference and apply formatting.
302+
./rustup-toolchain HEAD && ./miri fmt
303+
git commit -am "rustup"
304+
```
305+
306+
Now push this to a new branch in your Miri fork, and create a PR. It is worth
307+
running `./miri test` locally in parallel, since the test suite in the Miri repo
308+
is stricter than the one on the rustc side, so some small tweaks might be
309+
needed.
310+
311+
### Exporting changes to the rustc repo
312+
313+
We will use the josh proxy to push to your fork of rustc. You need to make sure
314+
that the master branch of your fork is up-to-date. Also make sure that there
315+
exists no branch called `miri` in your fork. Then run the following in the Miri
316+
repo, assuming we are on an up-to-date master branch:
317+
318+
```sh
319+
# Push the Miri changes to your rustc fork (substitute your github handle for YOUR_NAME).
320+
# Do NOT change that commit ID, it needs to be exactly this!
321+
git push http://localhost:8000/YOUR_NAME/rust.git:at_commit=75dd959a3a40eb5b4574f8d2e23aa6efbeb33573[:prefix=src/tools/miri]:/src/tools/miri.git -o base=master HEAD:miri
322+
```
323+
324+
This will create a new branch in your fork, and the output should include a link
325+
to create a rustc PR that will integrate those changes into the main repository.

src/tools/miri/Cargo.lock

+3-2
Original file line numberDiff line numberDiff line change
@@ -320,9 +320,9 @@ dependencies = [
320320

321321
[[package]]
322322
name = "libffi-sys"
323-
version = "2.0.0"
323+
version = "2.0.1"
324324
source = "registry+https://github.com/rust-lang/crates.io-index"
325-
checksum = "ab4106b7f09d7b87d021334d5618fac1dfcfb824d4c5fe111ff0074dfd242e15"
325+
checksum = "84e78d02e5a8eae9c24c38ce6e6026f80e16dff76adcdae4bc5c6c52c2de4a60"
326326
dependencies = [
327327
"cc",
328328
]
@@ -419,6 +419,7 @@ dependencies = [
419419
"rand",
420420
"regex",
421421
"rustc-workspace-hack",
422+
"rustc_version",
422423
"shell-escape",
423424
"smallvec",
424425
"ui_test",

src/tools/miri/Cargo.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,17 @@ smallvec = "1.7"
3131
rustc-workspace-hack = "1.0.0"
3232
measureme = "10.0.0"
3333

34-
[target."cfg(unix)".dependencies]
34+
[target.'cfg(unix)'.dependencies]
3535
libc = "0.2"
36+
37+
[target.'cfg(target_os = "linux")'.dependencies]
3638
libffi = "3.0.0"
3739
libloading = "0.7"
3840

3941
[dev-dependencies]
4042
colored = "2"
4143
ui_test = "0.3.1"
44+
rustc_version = "0.4"
4245
# Features chosen to match those required by env_logger, to avoid rebuilds
4346
regex = { version = "1.5.5", default-features = false, features = ["perf", "std"] }
4447
lazy_static = "1.4.0"

src/tools/miri/README.md

+30-5
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,11 @@ to Miri failing to detect cases of undefined behavior in a program.
377377
* `-Zmiri-retag-fields` changes Stacked Borrows retagging to recurse into fields.
378378
This means that references in fields of structs/enums/tuples/arrays/... are retagged,
379379
and in particular, they are protected when passed as function arguments.
380+
* `-Zmiri-retag-fields=<all|none|scalar>` controls when Stacked Borrows retagging recurses into
381+
fields. `all` means it always recurses (like `-Zmiri-retag-fields`), `none` means it never
382+
recurses (the default), `scalar` means it only recurses for types where we would also emit
383+
`noalias` annotations in the generated LLVM IR (types passed as indivudal scalars or pairs of
384+
scalars).
380385
* `-Zmiri-tag-gc=<blocks>` configures how often the pointer tag garbage collector runs. The default
381386
is to search for and remove unreachable tags once every `10000` basic blocks. Setting this to
382387
`0` disables the garbage collector, which causes some programs to have explosive memory usage
@@ -435,11 +440,10 @@ Moreover, Miri recognizes some environment variables:
435440
purpose.
436441
* `MIRI_NO_STD` (recognized by `cargo miri` and the test suite) makes sure that the target's
437442
sysroot is built without libstd. This allows testing and running no_std programs.
438-
* `MIRI_BLESS` (recognized by the test suite) overwrite all `stderr` and `stdout` files
439-
instead of checking whether the output matches.
440-
* `MIRI_SKIP_UI_CHECKS` (recognized by the test suite) don't check whether the
441-
`stderr` or `stdout` files match the actual output. Useful for the rustc test suite
442-
which has subtle differences that we don't care about.
443+
* `MIRI_BLESS` (recognized by the test suite and `cargo-miri-test/run-test.py`): overwrite all
444+
`stderr` and `stdout` files instead of checking whether the output matches.
445+
* `MIRI_SKIP_UI_CHECKS` (recognized by the test suite): don't check whether the
446+
`stderr` or `stdout` files match the actual output.
443447

444448
The following environment variables are *internal* and must not be used by
445449
anyone but Miri itself. They are used to communicate between different Miri
@@ -532,6 +536,27 @@ extern "Rust" {
532536
/// This is internal and unstable and should not be used; we give it here
533537
/// just to be complete.
534538
fn miri_start_panic(payload: *mut u8) -> !;
539+
540+
/// Miri-provided extern function to get the internal unique identifier for the allocation that a pointer
541+
/// points to. This is only useful as an input to `miri_print_stacks`, and it is a separate call because
542+
/// getting a pointer to an allocation at runtime can change the borrow stacks in the allocation.
543+
fn miri_get_alloc_id(ptr: *const ()) -> u64;
544+
545+
/// Miri-provided extern function to print (from the interpreter, not the program) the contents of all
546+
/// borrow stacks in an allocation. The format of what this emits is unstable and may change at any time.
547+
/// In particular, users should be aware that Miri will periodically attempt to garbage collect the
548+
/// contents of all stacks. Callers of this function may wish to pass `-Zmiri-tag-gc=0` to disable the GC.
549+
fn miri_print_stacks(alloc_id: u64);
550+
551+
/// Miri-provided extern function to print (from the interpreter, not the
552+
/// program) the contents of a section of program memory, as bytes. Bytes
553+
/// written using this function will emerge from the interpreter's stdout.
554+
fn miri_write_to_stdout(bytes: &[u8]);
555+
556+
/// Miri-provided extern function to print (from the interpreter, not the
557+
/// program) the contents of a section of program memory, as bytes. Bytes
558+
/// written using this function will emerge from the interpreter's stderr.
559+
fn miri_write_to_stderr(bytes: &[u8]);
535560
}
536561
```
537562

src/tools/miri/bench-cargo-miri/serde2/src/main.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use serde::Deserialize;
55
use std::thread;
66

77
#[derive(Deserialize)]
8+
#[allow(unused)]
89
struct DeriveStruct {
910
buffer: Vec<i16>,
1011
}

src/tools/miri/rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
acb8934fd57b3c2740c4abac0a5728c2c9b1423b
1+
b1ab3b738ac718da74cd4aa0bb7f362d0adbdf84

src/tools/miri/src/bin/miri.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use rustc_middle::{
3232
};
3333
use rustc_session::{config::CrateType, search_paths::PathKind, CtfeBacktrace};
3434

35-
use miri::{BacktraceStyle, ProvenanceMode};
35+
use miri::{BacktraceStyle, ProvenanceMode, RetagFields};
3636

3737
struct MiriCompilerCalls {
3838
miri_config: miri::MiriConfig,
@@ -426,7 +426,14 @@ fn main() {
426426
} else if arg == "-Zmiri-mute-stdout-stderr" {
427427
miri_config.mute_stdout_stderr = true;
428428
} else if arg == "-Zmiri-retag-fields" {
429-
miri_config.retag_fields = true;
429+
miri_config.retag_fields = RetagFields::Yes;
430+
} else if let Some(retag_fields) = arg.strip_prefix("-Zmiri-retag-fields=") {
431+
miri_config.retag_fields = match retag_fields {
432+
"all" => RetagFields::Yes,
433+
"none" => RetagFields::No,
434+
"scalar" => RetagFields::OnlyScalar,
435+
_ => show_error!("`-Zmiri-retag-fields` can only be `all`, `none`, or `scalar`"),
436+
};
430437
} else if arg == "-Zmiri-track-raw-pointers" {
431438
eprintln!(
432439
"WARNING: `-Zmiri-track-raw-pointers` has no effect; it is enabled by default"

0 commit comments

Comments
 (0)