Auto merge of #104456 - RalfJung:miri, r=RalfJung

update Miri

Not a huge sync, but there was a conflict and [josh](https://github.com/josh-project/josh/) seems to prefer those to be merged back ASAP.
This commit is contained in:
bors 2022-11-16 19:52:45 +00:00
commit e9493d63c2
22 changed files with 355 additions and 382 deletions

View file

@ -214,6 +214,18 @@ dependencies = [
"regex-automata",
]
[[package]]
name = "bstr"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fca0852af221f458706eb0725c03e4ed6c46af9ac98e6a689d5e634215d594dd"
dependencies = [
"memchr",
"once_cell",
"regex-automata",
"serde",
]
[[package]]
name = "build-manifest"
version = "0.1.0"
@ -919,25 +931,11 @@ dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "crossbeam"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-epoch",
"crossbeam-queue",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.4"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53"
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-utils",
@ -967,16 +965,6 @@ dependencies = [
"scopeguard",
]
[[package]]
name = "crossbeam-queue"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.8"
@ -1260,6 +1248,15 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]]
name = "fastrand"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
dependencies = [
"instant",
]
[[package]]
name = "filetime"
version = "0.2.14"
@ -1584,7 +1581,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a"
dependencies = [
"aho-corasick",
"bstr",
"bstr 0.2.17",
"fnv",
"log",
"regex",
@ -2341,9 +2338,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.12.0"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
[[package]]
name = "opener"
@ -2351,7 +2348,7 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ea3ebcd72a54701f56345f16785a6d3ac2df7e986d273eb4395c0b01db17952"
dependencies = [
"bstr",
"bstr 0.2.17",
"winapi",
]
@ -3008,9 +3005,9 @@ dependencies = [
[[package]]
name = "rustc-build-sysroot"
version = "0.3.3"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec5f3689b6c560d6a3a17fcbe54204cd870b4fcf46342d60de16715b660d2c92"
checksum = "20c4b4625eeb148cccf82d5e9b90ad7fab3b11a0204cf75cc7fa04981a0fdffd"
dependencies = [
"anyhow",
"rustc_version",
@ -3098,9 +3095,10 @@ dependencies = [
name = "rustc-workspace-hack"
version = "1.0.0"
dependencies = [
"bstr",
"bstr 0.2.17",
"clap 3.2.20",
"libz-sys",
"rand 0.8.5",
"regex",
"serde_json",
"syn",
@ -4767,13 +4765,13 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.2.0"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
dependencies = [
"cfg-if 1.0.0",
"fastrand",
"libc",
"rand 0.8.5",
"redox_syscall",
"remove_dir_all",
"winapi",
@ -5119,20 +5117,22 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
[[package]]
name = "ui_test"
version = "0.3.1"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d1f546a5883ae78da735bba529ec1116661e2f73582f23920d994dc97da3a22"
checksum = "bf4559da3fe6b481f8674a29379677cb9606cd6f75fc254a2c9834c55638503d"
dependencies = [
"bstr 1.0.1",
"cargo_metadata 0.15.0",
"color-eyre",
"colored",
"crossbeam",
"crossbeam-channel",
"diff",
"lazy_static",
"regex",
"rustc_version",
"serde",
"serde_json",
"tempfile",
]
[[package]]

View file

@ -67,10 +67,10 @@ jobs:
shell: bash
run: |
if [[ ${{ github.event_name }} == 'schedule' ]]; then
./miri toolchain HEAD --host ${{ matrix.host_target }}
else
./miri toolchain "" --host ${{ matrix.host_target }}
echo "Building against latest rustc git version"
git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1 > rust-version
fi
./miri toolchain --host ${{ matrix.host_target }}
- name: Show Rust version
run: |

View file

@ -150,7 +150,8 @@ is set the `MIRI_LIB_SRC` environment variable to the `library` folder of a
`rust-lang/rust` repository checkout. Note that changing files in that directory
does not automatically trigger a re-build of the standard library; you have to
clear the Miri build cache manually (on Linux, `rm -rf ~/.cache/miri`;
and on Windows, `rmdir /S "%LOCALAPPDATA%\rust-lang\miri\cache"`).
on Windows, `rmdir /S "%LOCALAPPDATA%\rust-lang\miri\cache"`;
and on macOS, `rm -rf ~/Library/Caches/org.rust-lang.miri`).
### Benchmarking
@ -208,23 +209,6 @@ We described above the simplest way to get a working build environment for Miri,
which is to use the version of rustc indicated by `rustc-version`. But
sometimes, that is not enough.
### Updating `rustc-version`
The `rustc-version` file is regularly updated to keep Miri close to the latest
version of rustc. Usually, new contributors do not have to worry about this. But
sometimes a newer rustc is needed for a patch, and sometimes Miri needs fixing
for changes in rustc. In both cases, `rustc-version` needs updating.
To update the `rustc-version` file and install the latest rustc, you can run:
```
./miri toolchain HEAD
```
Now edit Miri until `./miri test` passes, and submit a PR. Generally, it is
preferred to separate updating `rustc-version` and doing what it takes to get
Miri working again, from implementing new features that rely on the updated
rustc. This avoids blocking all Miri development on landing a big PR.
### Building Miri with a locally built rustc
[building Miri with a locally built rustc]: #building-miri-with-a-locally-built-rustc
@ -282,13 +266,13 @@ With this, you should now have a working development setup! See
## Advanced topic: Syncing with the rustc repo
We use the [`josh` proxy](https://github.com/josh-project/josh) to transmit
changes between the rustc and Miri repositories. For now, a fork of josh needs to be built
from source. This downloads and runs josh:
changes between the rustc and Miri repositories. For now, the latest git version
of josh needs to be built from source. This downloads and runs josh:
```sh
git clone https://github.com/RalfJung/josh
git clone https://github.com/josh-project/josh
cd josh
cargo run --release -p josh-proxy -- --local=$(pwd)/local --remote=https://github.com --no-background
cargo run --release -p josh-proxy -- --local=local --remote=https://github.com --no-background
```
### Importing changes from the rustc repo
@ -298,9 +282,10 @@ We assume we start on an up-to-date master branch in the Miri repo.
```sh
# Fetch and merge rustc side of the history. Takes ca 5 min the first time.
# This will also update the 'rustc-version' file.
./miri rustc-pull
# Update toolchain reference and apply formatting.
./miri toolchain HEAD && ./miri fmt
# Update local toolchain and apply formatting.
./miri toolchain && ./miri fmt
git commit -am "rustup"
```

View file

@ -64,6 +64,18 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bstr"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fca0852af221f458706eb0725c03e4ed6c46af9ac98e6a689d5e634215d594dd"
dependencies = [
"memchr",
"once_cell",
"regex-automata",
"serde",
]
[[package]]
name = "camino"
version = "1.1.1"
@ -145,20 +157,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "crossbeam"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c"
dependencies = [
"cfg-if",
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-epoch",
"crossbeam-queue",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.6"
@ -169,41 +167,6 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
"once_cell",
"scopeguard",
]
[[package]]
name = "crossbeam-queue"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.11"
@ -243,6 +206,15 @@ dependencies = [
"once_cell",
]
[[package]]
name = "fastrand"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
dependencies = [
"instant",
]
[[package]]
name = "getrandom"
version = "0.2.7"
@ -385,15 +357,6 @@ dependencies = [
"libc",
]
[[package]]
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]]
name = "miniz_oxide"
version = "0.5.4"
@ -560,12 +523,27 @@ dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "regex-syntax"
version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[package]]
name = "rustc-demangle"
version = "0.1.21"
@ -677,6 +655,20 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "tempfile"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
dependencies = [
"cfg-if",
"fastrand",
"libc",
"redox_syscall",
"remove_dir_all",
"winapi",
]
[[package]]
name = "termcolor"
version = "1.1.3"
@ -739,20 +731,22 @@ dependencies = [
[[package]]
name = "ui_test"
version = "0.3.1"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d1f546a5883ae78da735bba529ec1116661e2f73582f23920d994dc97da3a22"
checksum = "bf4559da3fe6b481f8674a29379677cb9606cd6f75fc254a2c9834c55638503d"
dependencies = [
"bstr",
"cargo_metadata",
"color-eyre",
"colored",
"crossbeam",
"crossbeam-channel",
"diff",
"lazy_static",
"regex",
"rustc_version",
"serde",
"serde_json",
"tempfile",
]
[[package]]

View file

@ -40,7 +40,7 @@ libloading = "0.7"
[dev-dependencies]
colored = "2"
ui_test = "0.3.1"
ui_test = "0.4"
rustc_version = "0.4"
# Features chosen to match those required by env_logger, to avoid rebuilds
regex = { version = "1.5.5", default-features = false, features = ["perf", "std"] }

View file

@ -432,7 +432,9 @@ Moreover, Miri recognizes some environment variables:
must point to the `library` subdirectory of a `rust-lang/rust` repository
checkout. Note that changing files in that directory does not automatically
trigger a re-build of the standard library; you have to clear the Miri build
cache manually (on Linux, `rm -rf ~/.cache/miri`).
cache manually (on Linux, `rm -rf ~/.cache/miri`;
on Windows, `rmdir /S "%LOCALAPPDATA%\rust-lang\miri\cache"`;
and on macOS, `rm -rf ~/Library/Caches/org.rust-lang.miri`).
* `MIRI_SYSROOT` (recognized by `cargo miri` and the Miri driver) indicates the sysroot to use. When
using `cargo miri`, this skips the automatic setup -- only set this if you do not want to use the
automatically created sysroot. For directly invoking the Miri driver, this variable (or a
@ -568,6 +570,15 @@ extern "Rust" {
/// program) the contents of a section of program memory, as bytes. Bytes
/// written using this function will emerge from the interpreter's stderr.
fn miri_write_to_stderr(bytes: &[u8]);
/// Miri-provided extern function to allocate memory from the interpreter.
///
/// This is useful when no fundamental way of allocating memory is
/// available, e.g. when using `no_std` + `alloc`.
fn miri_alloc(size: usize, align: usize) -> *mut u8;
/// Miri-provided extern function to deallocate memory.
fn miri_dealloc(ptr: *mut u8, size: usize, align: usize);
}
```

View file

@ -175,9 +175,9 @@ dependencies = [
[[package]]
name = "rustc-build-sysroot"
version = "0.3.3"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec5f3689b6c560d6a3a17fcbe54204cd870b4fcf46342d60de16715b660d2c92"
checksum = "20c4b4625eeb148cccf82d5e9b90ad7fab3b11a0204cf75cc7fa04981a0fdffd"
dependencies = [
"anyhow",
"rustc_version",

View file

@ -18,7 +18,7 @@ directories = "4"
rustc_version = "0.4"
serde_json = "1.0.40"
cargo_metadata = "0.15.0"
rustc-build-sysroot = "0.3.3"
rustc-build-sysroot = "0.4"
# A noop dependency that changes in the Rust repository, it's a bit of a hack.
# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`

View file

@ -5,7 +5,7 @@
use std::path::PathBuf;
use std::process::{self, Command};
use rustc_build_sysroot::{BuildMode, Sysroot, SysrootConfig};
use rustc_build_sysroot::{BuildMode, SysrootBuilder, SysrootConfig};
use rustc_version::VersionMeta;
use crate::util::*;
@ -70,9 +70,11 @@ pub fn setup(subcommand: &MiriCommand, target: &str, rustc_version: &VersionMeta
let sysroot_config = if std::env::var_os("MIRI_NO_STD").is_some() {
SysrootConfig::NoStd
} else {
SysrootConfig::WithStd { std_features: &["panic_unwind", "backtrace"] }
SysrootConfig::WithStd {
std_features: ["panic_unwind", "backtrace"].into_iter().map(Into::into).collect(),
}
};
let cargo_cmd = || {
let cargo_cmd = {
let mut command = cargo();
// Use Miri as rustc to build a libstd compatible with us (and use the right flags).
// However, when we are running in bootstrap, we cannot just overwrite `RUSTC`,
@ -106,13 +108,14 @@ pub fn setup(subcommand: &MiriCommand, target: &str, rustc_version: &VersionMeta
command.stdout(process::Stdio::null());
command.stderr(process::Stdio::null());
}
// Disable debug assertions in the standard library -- Miri is already slow enough.
// But keep the overflow checks, they are cheap. This completely overwrites flags
// the user might have set, which is consistent with normal `cargo build` that does
// not apply `RUSTFLAGS` to the sysroot either.
let rustflags = vec!["-Cdebug-assertions=off".into(), "-Coverflow-checks=on".into()];
(command, rustflags)
command
};
// Disable debug assertions in the standard library -- Miri is already slow enough.
// But keep the overflow checks, they are cheap. This completely overwrites flags
// the user might have set, which is consistent with normal `cargo build` that does
// not apply `RUSTFLAGS` to the sysroot either.
let rustflags = &["-Cdebug-assertions=off", "-Coverflow-checks=on"];
// Make sure all target-level Miri invocations know their sysroot.
std::env::set_var("MIRI_SYSROOT", &sysroot_dir);
@ -124,8 +127,13 @@ pub fn setup(subcommand: &MiriCommand, target: &str, rustc_version: &VersionMeta
// We want to be quiet, but still let the user know that something is happening.
eprint!("Preparing a sysroot for Miri (target: {target})... ");
}
Sysroot::new(&sysroot_dir, target)
.build_from_source(&rust_src, BuildMode::Check, sysroot_config, rustc_version, cargo_cmd)
SysrootBuilder::new(&sysroot_dir, target)
.build_mode(BuildMode::Check)
.rustc_version(rustc_version.clone())
.sysroot_config(sysroot_config)
.rustflags(rustflags)
.cargo(cargo_cmd)
.build_from_source(&rust_src)
.unwrap_or_else(|_| {
if only_setup {
show_error!("failed to build sysroot, see error details above")

View file

@ -42,22 +42,22 @@ many different seeds.
Runs the benchmarks from bench-cargo-miri in hyperfine. hyperfine needs to be installed.
<benches> can explicitly list the benchmarks to run; by default, all of them are run.
./miri rustc-pull:
Pull and merge Miri changes from the rustc repo.
./miri rustc-push <github user> <branch>:
Push Miri changes back to the rustc repo. This will update the 'master' branch
in the Rust fork of the given user to upstream. It will also pull a copy of the
rustc history into the Miri repo, unless you set the RUSTC_GIT env var to an
existing clone of the rustc repo.
./miri toolchain <commit> <flags>:
Update and activate the rustup toolchain 'miri'. If no commit is given, updates
to the commit given in the `rust-version` file. If the commit is `HEAD`, updates
to the latest upstream rustc commit.
./miri toolchain <flags>:
Update and activate the rustup toolchain 'miri' to the commit given in the
`rust-version` file.
`rustup-toolchain-install-master` must be installed for this to work. Any extra
flags are passed to `rustup-toolchain-install-master`.
./miri rustc-pull:
Pull and merge Miri changes from the rustc repo. The fetched commit is stored in
the `rust-version` file, so the next `./miri toolchain` will install the rustc
we just pulled.
./miri rustc-push <github user> <branch>:
Push Miri changes back to the rustc repo. This will pull a copy of the rustc
history into the Miri repo, unless you set the RUSTC_GIT env var to an existing
clone of the rustc repo.
ENVIRONMENT VARIABLES
MIRI_SYSROOT:
@ -78,7 +78,7 @@ shift
# macOS does not have a useful readlink/realpath so we have to use Python instead...
MIRIDIR=$(python3 -c 'import os, sys; print(os.path.dirname(os.path.realpath(sys.argv[1])))' "$0")
# Used for rustc syncs.
JOSH_FILTER=":at_commit=75dd959a3a40eb5b4574f8d2e23aa6efbeb33573[:prefix=src/tools/miri]:/src/tools/miri"
JOSH_FILTER=":rev(75dd959a3a40eb5b4574f8d2e23aa6efbeb33573:prefix=src/tools/miri):/src/tools/miri"
# Needed for `./miri bench`.
TOOLCHAIN=$(cd "$MIRIDIR"; rustup show active-toolchain | head -n 1 | cut -d ' ' -f 1)
@ -86,21 +86,12 @@ TOOLCHAIN=$(cd "$MIRIDIR"; rustup show active-toolchain | head -n 1 | cut -d ' '
case "$COMMAND" in
toolchain)
cd "$MIRIDIR"
NEW_COMMIT=$(cat rust-version)
# Make sure rustup-toolchain-install-master is installed.
if ! which rustup-toolchain-install-master >/dev/null; then
echo "Please install rustup-toolchain-install-master by running 'cargo install rustup-toolchain-install-master'"
exit 1
fi
# Determine new commit.
if [[ "$1" == "" ]]; then
NEW_COMMIT=$(cat rust-version)
elif [[ "$1" == "HEAD" ]]; then
NEW_COMMIT=$(git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1)
else
NEW_COMMIT="$1"
fi
echo "$NEW_COMMIT" > rust-version
shift || true # don't fail if shifting fails because no commit was given
# Check if we already are at that commit.
CUR_COMMIT=$(rustc +miri --version -v 2>/dev/null | grep "^commit-hash: " | cut -d " " -f 2)
if [[ "$CUR_COMMIT" == "$NEW_COMMIT" ]]; then
@ -122,8 +113,18 @@ toolchain)
;;
rustc-pull)
cd "$MIRIDIR"
FETCH_COMMIT=$(git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1)
# We can't pull from a commit with josh
# (https://github.com/josh-project/josh/issues/1034), so we just hope that
# nothing gets merged into rustc *during* this pull.
git fetch http://localhost:8000/rust-lang/rust.git$JOSH_FILTER.git master
# Just verify that `master` didn't move.
if [[ $FETCH_COMMIT != $(git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1) ]]; then
echo "Looks like something got merged into Rust *while we were pulling*. Aborting. Please try again."
fi
echo "$FETCH_COMMIT" > rust-version # do this *before* merging as merging will fail in case of conflicts
git merge FETCH_HEAD --no-ff -m "Merge from rustc"
git commit rust-version --amend -m "Merge from rustc"
exit 0
;;
rustc-push)
@ -145,19 +146,21 @@ rustc-push)
fi
cd "$MIRIDIR"
fi
# Prepare the branches. For reliable pushing we need to push to a non-existent branch
# and set `-o base` to a branch that holds current rustc master.
echo "Preparing $USER/rust..."
if git fetch https://github.com/$USER/rust $BRANCH &>/dev/null; then
echo "The '$BRANCH' seems to already exist in $USER/rust. Please delete it and try again."
# Prepare the branch. Pushing works much better if we use as base exactly
# the commit that we pulled from last time, so we use the `rust-version`
# file as a good approximation of that.
BASE=$(cat "$MIRIDIR/rust-version")
echo "Preparing $USER/rust (base: $BASE)..."
if git fetch "https://github.com/$USER/rust" "$BRANCH" &>/dev/null; then
echo "The branch '$BRANCH' seems to already exist in 'https://github.com/$USER/rust'. Please delete it and try again."
exit 1
fi
git fetch https://github.com/rust-lang/rust master
git push https://github.com/$USER/rust FETCH_HEAD:master
git fetch https://github.com/rust-lang/rust $BASE
git push https://github.com/$USER/rust $BASE:refs/heads/$BRANCH -f
# Do the actual push.
cd "$MIRIDIR"
echo "Pushing Miri changes..."
git push http://localhost:8000/$USER/rust.git$JOSH_FILTER.git HEAD:$BRANCH -o base=master
git push http://localhost:8000/$USER/rust.git$JOSH_FILTER.git HEAD:$BRANCH
exit 0
;;
many-seeds)

View file

@ -1 +1 @@
b03502b35d111bef0399a66ab3cc765f0802e8ba
101e1822c3e54e63996c8aaa014d55716f3937eb

View file

@ -49,7 +49,7 @@
use rustc_ast::Mutability;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::{mir, ty::layout::TyAndLayout};
use rustc_middle::mir;
use rustc_target::abi::{Align, Size};
use crate::*;
@ -440,33 +440,6 @@ fn write_race_detect(
/// Evaluation context extensions.
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for MiriInterpCx<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
/// Atomic variant of read_scalar_at_offset.
fn read_scalar_at_offset_atomic(
&self,
op: &OpTy<'tcx, Provenance>,
offset: u64,
layout: TyAndLayout<'tcx>,
atomic: AtomicReadOrd,
) -> InterpResult<'tcx, Scalar<Provenance>> {
let this = self.eval_context_ref();
let value_place = this.deref_operand_and_offset(op, offset, layout)?;
this.read_scalar_atomic(&value_place, atomic)
}
/// Atomic variant of write_scalar_at_offset.
fn write_scalar_at_offset_atomic(
&mut self,
op: &OpTy<'tcx, Provenance>,
offset: u64,
value: impl Into<Scalar<Provenance>>,
layout: TyAndLayout<'tcx>,
atomic: AtomicWriteOrd,
) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
let value_place = this.deref_operand_and_offset(op, offset, layout)?;
this.write_scalar_atomic(value.into(), &value_place, atomic)
}
/// Perform an atomic read operation at the memory location.
fn read_scalar_atomic(
&self,
@ -713,7 +686,10 @@ pub fn new_allocation(
let (alloc_timestamp, alloc_index) = match kind {
// User allocated and stack memory should track allocation.
MemoryKind::Machine(
MiriMemoryKind::Rust | MiriMemoryKind::C | MiriMemoryKind::WinHeap,
MiriMemoryKind::Rust
| MiriMemoryKind::Miri
| MiriMemoryKind::C
| MiriMemoryKind::WinHeap,
)
| MemoryKind::Stack => {
let (alloc_index, clocks) = global.current_thread_state(thread_mgr);

View file

@ -193,8 +193,9 @@ impl<'mir, 'tcx: 'mir> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'m
pub(super) trait EvalContextExtPriv<'mir, 'tcx: 'mir>:
crate::MiriInterpCxExt<'mir, 'tcx>
{
/// Lazily initialize the ID of this Miri sync structure.
/// ('0' indicates uninit.)
#[inline]
// Miri sync structures contain zero-initialized ids stored at some offset behind a pointer
fn get_or_create_id<Id: SyncId>(
&mut self,
next_id: Id,
@ -205,6 +206,7 @@ fn get_or_create_id<Id: SyncId>(
let value_place =
this.deref_operand_and_offset(lock_op, offset, this.machine.layouts.u32)?;
// Since we are lazy, this update has to be atomic.
let (old, success) = this
.atomic_compare_exchange_scalar(
&value_place,

View file

@ -668,7 +668,7 @@ fn deref_operand_and_offset(
layout: TyAndLayout<'tcx>,
) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> {
let this = self.eval_context_ref();
let op_place = this.deref_operand(op)?;
let op_place = this.deref_operand(op)?; // FIXME: we still deref with the original type!
let offset = Size::from_bytes(offset);
// Ensure that the access is within bounds.
@ -688,17 +688,6 @@ fn read_scalar_at_offset(
this.read_scalar(&value_place.into())
}
fn write_immediate_at_offset(
&mut self,
op: &OpTy<'tcx, Provenance>,
offset: u64,
value: &ImmTy<'tcx, Provenance>,
) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
let value_place = this.deref_operand_and_offset(op, offset, value.layout)?;
this.write_immediate(**value, &value_place.into())
}
fn write_scalar_at_offset(
&mut self,
op: &OpTy<'tcx, Provenance>,
@ -706,7 +695,9 @@ fn write_scalar_at_offset(
value: impl Into<Scalar<Provenance>>,
layout: TyAndLayout<'tcx>,
) -> InterpResult<'tcx, ()> {
self.write_immediate_at_offset(op, offset, &ImmTy::from_scalar(value.into(), layout))
let this = self.eval_context_mut();
let value_place = this.deref_operand_and_offset(op, offset, layout)?;
this.write_scalar(value, &value_place.into())
}
/// Parse a `timespec` struct and return it as a `std::time::Duration`. It returns `None`

View file

@ -77,6 +77,8 @@ fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
pub enum MiriMemoryKind {
/// `__rust_alloc` memory.
Rust,
/// `miri_alloc` memory.
Miri,
/// `malloc` memory.
C,
/// Windows `HeapAlloc` memory.
@ -110,7 +112,7 @@ impl MayLeak for MiriMemoryKind {
fn may_leak(self) -> bool {
use self::MiriMemoryKind::*;
match self {
Rust | C | WinHeap | Runtime => false,
Rust | Miri | C | WinHeap | Runtime => false,
Machine | Global | ExternStatic | Tls => true,
}
}
@ -121,6 +123,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use self::MiriMemoryKind::*;
match self {
Rust => write!(f, "Rust heap"),
Miri => write!(f, "Miri bare-metal heap"),
C => write!(f, "C heap"),
WinHeap => write!(f, "Windows heap"),
Machine => write!(f, "machine-managed memory"),

View file

@ -513,22 +513,37 @@ fn emulate_foreign_item_by_name(
}
// Rust allocation
"__rust_alloc" => {
"__rust_alloc" | "miri_alloc" => {
let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
let size = this.read_scalar(size)?.to_machine_usize(this)?;
let align = this.read_scalar(align)?.to_machine_usize(this)?;
return this.emulate_allocator(Symbol::intern("__rg_alloc"), |this| {
let default = |this: &mut MiriInterpCx<'mir, 'tcx>| {
Self::check_alloc_request(size, align)?;
let memory_kind = match link_name.as_str() {
"__rust_alloc" => MiriMemoryKind::Rust,
"miri_alloc" => MiriMemoryKind::Miri,
_ => unreachable!(),
};
let ptr = this.allocate_ptr(
Size::from_bytes(size),
Align::from_bytes(align).unwrap(),
MiriMemoryKind::Rust.into(),
memory_kind.into(),
)?;
this.write_pointer(ptr, dest)
});
};
match link_name.as_str() {
"__rust_alloc" => return this.emulate_allocator(Symbol::intern("__rg_alloc"), default),
"miri_alloc" => {
default(this)?;
return Ok(EmulateByNameResult::NeedsJumping);
},
_ => unreachable!(),
}
}
"__rust_alloc_zeroed" => {
let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
@ -549,20 +564,35 @@ fn emulate_foreign_item_by_name(
this.write_pointer(ptr, dest)
});
}
"__rust_dealloc" => {
"__rust_dealloc" | "miri_dealloc" => {
let [ptr, old_size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
let old_size = this.read_scalar(old_size)?.to_machine_usize(this)?;
let align = this.read_scalar(align)?.to_machine_usize(this)?;
return this.emulate_allocator(Symbol::intern("__rg_dealloc"), |this| {
let default = |this: &mut MiriInterpCx<'mir, 'tcx>| {
let memory_kind = match link_name.as_str() {
"__rust_dealloc" => MiriMemoryKind::Rust,
"miri_dealloc" => MiriMemoryKind::Miri,
_ => unreachable!(),
};
// No need to check old_size/align; we anyway check that they match the allocation.
this.deallocate_ptr(
ptr,
Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())),
MiriMemoryKind::Rust.into(),
memory_kind.into(),
)
});
};
match link_name.as_str() {
"__rust_dealloc" => return this.emulate_allocator(Symbol::intern("__rg_dealloc"), default),
"miri_dealloc" => {
default(this)?;
return Ok(EmulateByNameResult::NeedsJumping);
}
_ => unreachable!(),
}
}
"__rust_realloc" => {
let [ptr, old_size, align, new_size] = this.check_shim(abi, Abi::Rust, link_name, args)?;

View file

@ -1,8 +1,5 @@
use std::time::SystemTime;
use rustc_hir::LangItem;
use rustc_middle::ty::{layout::TyAndLayout, query::TyCtxtAt, Ty};
use crate::concurrency::sync::CondvarLock;
use crate::concurrency::thread::{MachineCallback, Time};
use crate::*;
@ -20,39 +17,34 @@
/// in `pthread_mutexattr_settype` function.
const PTHREAD_MUTEX_NORMAL_FLAG: i32 = 0x8000000;
const MUTEX_ID_OFFSET: u64 = 4;
const RWLOCK_ID_OFFSET: u64 = 4;
const CONDVAR_ID_OFFSET: u64 = 4;
fn is_mutex_kind_default<'mir, 'tcx: 'mir>(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
kind: Scalar<Provenance>,
kind: i32,
) -> InterpResult<'tcx, bool> {
Ok(kind == ecx.eval_libc("PTHREAD_MUTEX_DEFAULT")?)
Ok(kind == ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?)
}
fn is_mutex_kind_normal<'mir, 'tcx: 'mir>(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
kind: Scalar<Provenance>,
kind: i32,
) -> InterpResult<'tcx, bool> {
let kind = kind.to_i32()?;
let mutex_normal_kind = ecx.eval_libc("PTHREAD_MUTEX_NORMAL")?.to_i32()?;
let mutex_normal_kind = ecx.eval_libc_i32("PTHREAD_MUTEX_NORMAL")?;
Ok(kind == (mutex_normal_kind | PTHREAD_MUTEX_NORMAL_FLAG))
}
fn mutexattr_get_kind<'mir, 'tcx: 'mir>(
ecx: &MiriInterpCx<'mir, 'tcx>,
attr_op: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, Scalar<Provenance>> {
ecx.read_scalar_at_offset(attr_op, 0, ecx.machine.layouts.i32)
) -> InterpResult<'tcx, i32> {
ecx.read_scalar_at_offset(attr_op, 0, ecx.machine.layouts.i32)?.to_i32()
}
fn mutexattr_set_kind<'mir, 'tcx: 'mir>(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
attr_op: &OpTy<'tcx, Provenance>,
kind: impl Into<Scalar<Provenance>>,
kind: i32,
) -> InterpResult<'tcx, ()> {
ecx.write_scalar_at_offset(attr_op, 0, kind, layout_of_maybe_uninit(ecx.tcx, ecx.tcx.types.i32))
ecx.write_scalar_at_offset(attr_op, 0, Scalar::from_i32(kind), ecx.machine.layouts.i32)
}
// pthread_mutex_t is between 24 and 48 bytes, depending on the platform.
@ -64,53 +56,35 @@ fn mutexattr_set_kind<'mir, 'tcx: 'mir>(
// bytes 12-15 or 16-19 (depending on platform): mutex kind, as an i32
// (the kind has to be at its offset for compatibility with static initializer macros)
fn mutex_get_id<'mir, 'tcx: 'mir>(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
mutex_op: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, MutexId> {
ecx.mutex_get_or_create_id(mutex_op, 4)
}
fn mutex_reset_id<'mir, 'tcx: 'mir>(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
mutex_op: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, ()> {
ecx.write_scalar_at_offset(mutex_op, 4, Scalar::from_i32(0), ecx.machine.layouts.u32)
}
fn mutex_get_kind<'mir, 'tcx: 'mir>(
ecx: &MiriInterpCx<'mir, 'tcx>,
mutex_op: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, Scalar<Provenance>> {
) -> InterpResult<'tcx, i32> {
let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 };
ecx.read_scalar_at_offset_atomic(
mutex_op,
offset,
ecx.machine.layouts.i32,
AtomicReadOrd::Relaxed,
)
ecx.read_scalar_at_offset(mutex_op, offset, ecx.machine.layouts.i32)?.to_i32()
}
fn mutex_set_kind<'mir, 'tcx: 'mir>(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
mutex_op: &OpTy<'tcx, Provenance>,
kind: impl Into<Scalar<Provenance>>,
kind: i32,
) -> InterpResult<'tcx, ()> {
let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 };
ecx.write_scalar_at_offset_atomic(
mutex_op,
offset,
kind,
layout_of_maybe_uninit(ecx.tcx, ecx.tcx.types.i32),
AtomicWriteOrd::Relaxed,
)
}
fn mutex_get_id<'mir, 'tcx: 'mir>(
ecx: &MiriInterpCx<'mir, 'tcx>,
mutex_op: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, Scalar<Provenance>> {
ecx.read_scalar_at_offset_atomic(mutex_op, 4, ecx.machine.layouts.u32, AtomicReadOrd::Relaxed)
}
fn mutex_set_id<'mir, 'tcx: 'mir>(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
mutex_op: &OpTy<'tcx, Provenance>,
id: impl Into<Scalar<Provenance>>,
) -> InterpResult<'tcx, ()> {
ecx.write_scalar_at_offset_atomic(
mutex_op,
4,
id,
layout_of_maybe_uninit(ecx.tcx, ecx.tcx.types.u32),
AtomicWriteOrd::Relaxed,
)
ecx.write_scalar_at_offset(mutex_op, offset, Scalar::from_i32(kind), ecx.machine.layouts.i32)
}
// pthread_rwlock_t is between 32 and 56 bytes, depending on the platform.
@ -121,10 +95,10 @@ fn mutex_set_id<'mir, 'tcx: 'mir>(
// bytes 4-7: rwlock id as u32 or 0 if id is not assigned yet.
fn rwlock_get_id<'mir, 'tcx: 'mir>(
ecx: &MiriInterpCx<'mir, 'tcx>,
ecx: &mut MiriInterpCx<'mir, 'tcx>,
rwlock_op: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, Scalar<Provenance>> {
ecx.read_scalar_at_offset_atomic(rwlock_op, 4, ecx.machine.layouts.u32, AtomicReadOrd::Relaxed)
) -> InterpResult<'tcx, RwLockId> {
ecx.rwlock_get_or_create_id(rwlock_op, 4)
}
// pthread_condattr_t
@ -136,21 +110,16 @@ fn rwlock_get_id<'mir, 'tcx: 'mir>(
fn condattr_get_clock_id<'mir, 'tcx: 'mir>(
ecx: &MiriInterpCx<'mir, 'tcx>,
attr_op: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, Scalar<Provenance>> {
ecx.read_scalar_at_offset(attr_op, 0, ecx.machine.layouts.i32)
) -> InterpResult<'tcx, i32> {
ecx.read_scalar_at_offset(attr_op, 0, ecx.machine.layouts.i32)?.to_i32()
}
fn condattr_set_clock_id<'mir, 'tcx: 'mir>(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
attr_op: &OpTy<'tcx, Provenance>,
clock_id: impl Into<Scalar<Provenance>>,
clock_id: i32,
) -> InterpResult<'tcx, ()> {
ecx.write_scalar_at_offset(
attr_op,
0,
clock_id,
layout_of_maybe_uninit(ecx.tcx, ecx.machine.layouts.i32.ty),
)
ecx.write_scalar_at_offset(attr_op, 0, Scalar::from_i32(clock_id), ecx.machine.layouts.i32)
}
// pthread_cond_t
@ -163,44 +132,32 @@ fn condattr_set_clock_id<'mir, 'tcx: 'mir>(
// bytes 8-11: the clock id constant as i32
fn cond_get_id<'mir, 'tcx: 'mir>(
ecx: &MiriInterpCx<'mir, 'tcx>,
cond_op: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, Scalar<Provenance>> {
ecx.read_scalar_at_offset_atomic(cond_op, 4, ecx.machine.layouts.u32, AtomicReadOrd::Relaxed)
}
fn cond_set_id<'mir, 'tcx: 'mir>(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
cond_op: &OpTy<'tcx, Provenance>,
id: impl Into<Scalar<Provenance>>,
) -> InterpResult<'tcx, CondvarId> {
ecx.condvar_get_or_create_id(cond_op, 4)
}
fn cond_reset_id<'mir, 'tcx: 'mir>(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
cond_op: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, ()> {
ecx.write_scalar_at_offset_atomic(
cond_op,
4,
id,
layout_of_maybe_uninit(ecx.tcx, ecx.tcx.types.u32),
AtomicWriteOrd::Relaxed,
)
ecx.write_scalar_at_offset(cond_op, 4, Scalar::from_i32(0), ecx.machine.layouts.u32)
}
fn cond_get_clock_id<'mir, 'tcx: 'mir>(
ecx: &MiriInterpCx<'mir, 'tcx>,
cond_op: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, Scalar<Provenance>> {
ecx.read_scalar_at_offset(cond_op, 8, ecx.machine.layouts.i32)
) -> InterpResult<'tcx, i32> {
ecx.read_scalar_at_offset(cond_op, 8, ecx.machine.layouts.i32)?.to_i32()
}
fn cond_set_clock_id<'mir, 'tcx: 'mir>(
ecx: &mut MiriInterpCx<'mir, 'tcx>,
cond_op: &OpTy<'tcx, Provenance>,
clock_id: impl Into<Scalar<Provenance>>,
clock_id: i32,
) -> InterpResult<'tcx, ()> {
ecx.write_scalar_at_offset(
cond_op,
8,
clock_id,
layout_of_maybe_uninit(ecx.tcx, ecx.tcx.types.i32),
)
ecx.write_scalar_at_offset(cond_op, 8, Scalar::from_i32(clock_id), ecx.machine.layouts.i32)
}
/// Try to reacquire the mutex associated with the condition variable after we
@ -260,7 +217,7 @@ fn pthread_mutexattr_init(
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
let default_kind = this.eval_libc("PTHREAD_MUTEX_DEFAULT")?;
let default_kind = this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?;
mutexattr_set_kind(this, attr_op, default_kind)?;
Ok(0)
@ -273,8 +230,8 @@ fn pthread_mutexattr_settype(
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
let kind = this.read_scalar(kind_op)?;
if kind == this.eval_libc("PTHREAD_MUTEX_NORMAL")? {
let kind = this.read_scalar(kind_op)?.to_i32()?;
if kind == this.eval_libc_i32("PTHREAD_MUTEX_NORMAL")? {
// In `glibc` implementation, the numeric values of
// `PTHREAD_MUTEX_NORMAL` and `PTHREAD_MUTEX_DEFAULT` are equal.
// However, a mutex created by explicitly passing
@ -287,16 +244,16 @@ fn pthread_mutexattr_settype(
// use the same trick as glibc: for the case when
// `pthread_mutexattr_settype` is caled explicitly, we set the
// `PTHREAD_MUTEX_NORMAL_FLAG` flag.
let normal_kind = kind.to_i32()? | PTHREAD_MUTEX_NORMAL_FLAG;
let normal_kind = kind | PTHREAD_MUTEX_NORMAL_FLAG;
// Check that after setting the flag, the kind is distinguishable
// from all other kinds.
assert_ne!(normal_kind, this.eval_libc("PTHREAD_MUTEX_DEFAULT")?.to_i32()?);
assert_ne!(normal_kind, this.eval_libc("PTHREAD_MUTEX_ERRORCHECK")?.to_i32()?);
assert_ne!(normal_kind, this.eval_libc("PTHREAD_MUTEX_RECURSIVE")?.to_i32()?);
mutexattr_set_kind(this, attr_op, Scalar::from_i32(normal_kind))?;
} else if kind == this.eval_libc("PTHREAD_MUTEX_DEFAULT")?
|| kind == this.eval_libc("PTHREAD_MUTEX_ERRORCHECK")?
|| kind == this.eval_libc("PTHREAD_MUTEX_RECURSIVE")?
assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?);
assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")?);
assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")?);
mutexattr_set_kind(this, attr_op, normal_kind)?;
} else if kind == this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?
|| kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")?
|| kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")?
{
mutexattr_set_kind(this, attr_op, kind)?;
} else {
@ -342,13 +299,13 @@ fn pthread_mutex_init(
let attr = this.read_pointer(attr_op)?;
let kind = if this.ptr_is_null(attr)? {
this.eval_libc("PTHREAD_MUTEX_DEFAULT")?
this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?
} else {
mutexattr_get_kind(this, attr_op)?
};
// Write 0 to use the same code path as the static initializers.
mutex_set_id(this, mutex_op, Scalar::from_i32(0))?;
mutex_reset_id(this, mutex_op)?;
mutex_set_kind(this, mutex_op, kind)?;
@ -359,7 +316,7 @@ fn pthread_mutex_lock(&mut self, mutex_op: &OpTy<'tcx, Provenance>) -> InterpRes
let this = self.eval_context_mut();
let kind = mutex_get_kind(this, mutex_op)?;
let id = this.mutex_get_or_create_id(mutex_op, MUTEX_ID_OFFSET)?;
let id = mutex_get_id(this, mutex_op)?;
let active_thread = this.get_active_thread();
if this.mutex_is_locked(id) {
@ -374,9 +331,9 @@ fn pthread_mutex_lock(&mut self, mutex_op: &OpTy<'tcx, Provenance>) -> InterpRes
throw_ub_format!("trying to acquire already locked default mutex");
} else if is_mutex_kind_normal(this, kind)? {
throw_machine_stop!(TerminationInfo::Deadlock);
} else if kind == this.eval_libc("PTHREAD_MUTEX_ERRORCHECK")? {
} else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")? {
this.eval_libc_i32("EDEADLK")
} else if kind == this.eval_libc("PTHREAD_MUTEX_RECURSIVE")? {
} else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")? {
this.mutex_lock(id, active_thread);
Ok(0)
} else {
@ -399,7 +356,7 @@ fn pthread_mutex_trylock(
let this = self.eval_context_mut();
let kind = mutex_get_kind(this, mutex_op)?;
let id = this.mutex_get_or_create_id(mutex_op, MUTEX_ID_OFFSET)?;
let id = mutex_get_id(this, mutex_op)?;
let active_thread = this.get_active_thread();
if this.mutex_is_locked(id) {
@ -409,10 +366,10 @@ fn pthread_mutex_trylock(
} else {
if is_mutex_kind_default(this, kind)?
|| is_mutex_kind_normal(this, kind)?
|| kind == this.eval_libc("PTHREAD_MUTEX_ERRORCHECK")?
|| kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")?
{
this.eval_libc_i32("EBUSY")
} else if kind == this.eval_libc("PTHREAD_MUTEX_RECURSIVE")? {
} else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")? {
this.mutex_lock(id, active_thread);
Ok(0)
} else {
@ -435,7 +392,7 @@ fn pthread_mutex_unlock(
let this = self.eval_context_mut();
let kind = mutex_get_kind(this, mutex_op)?;
let id = this.mutex_get_or_create_id(mutex_op, MUTEX_ID_OFFSET)?;
let id = mutex_get_id(this, mutex_op)?;
let active_thread = this.get_active_thread();
if let Some(_old_locked_count) = this.mutex_unlock(id, active_thread) {
@ -453,8 +410,8 @@ fn pthread_mutex_unlock(
throw_ub_format!(
"unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread"
);
} else if kind == this.eval_libc("PTHREAD_MUTEX_ERRORCHECK")?
|| kind == this.eval_libc("PTHREAD_MUTEX_RECURSIVE")?
} else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")?
|| kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")?
{
this.eval_libc_i32("EPERM")
} else {
@ -469,7 +426,7 @@ fn pthread_mutex_destroy(
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
let id = this.mutex_get_or_create_id(mutex_op, MUTEX_ID_OFFSET)?;
let id = mutex_get_id(this, mutex_op)?;
if this.mutex_is_locked(id) {
throw_ub_format!("destroyed a locked mutex");
@ -492,7 +449,7 @@ fn pthread_rwlock_rdlock(
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
let id = this.rwlock_get_or_create_id(rwlock_op, RWLOCK_ID_OFFSET)?;
let id = rwlock_get_id(this, rwlock_op)?;
let active_thread = this.get_active_thread();
if this.rwlock_is_write_locked(id) {
@ -510,7 +467,7 @@ fn pthread_rwlock_tryrdlock(
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
let id = this.rwlock_get_or_create_id(rwlock_op, RWLOCK_ID_OFFSET)?;
let id = rwlock_get_id(this, rwlock_op)?;
let active_thread = this.get_active_thread();
if this.rwlock_is_write_locked(id) {
@ -527,7 +484,7 @@ fn pthread_rwlock_wrlock(
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
let id = this.rwlock_get_or_create_id(rwlock_op, RWLOCK_ID_OFFSET)?;
let id = rwlock_get_id(this, rwlock_op)?;
let active_thread = this.get_active_thread();
if this.rwlock_is_locked(id) {
@ -557,7 +514,7 @@ fn pthread_rwlock_trywrlock(
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
let id = this.rwlock_get_or_create_id(rwlock_op, RWLOCK_ID_OFFSET)?;
let id = rwlock_get_id(this, rwlock_op)?;
let active_thread = this.get_active_thread();
if this.rwlock_is_locked(id) {
@ -574,7 +531,7 @@ fn pthread_rwlock_unlock(
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
let id = this.rwlock_get_or_create_id(rwlock_op, RWLOCK_ID_OFFSET)?;
let id = rwlock_get_id(this, rwlock_op)?;
let active_thread = this.get_active_thread();
#[allow(clippy::if_same_then_else)]
@ -593,7 +550,7 @@ fn pthread_rwlock_destroy(
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
let id = this.rwlock_get_or_create_id(rwlock_op, RWLOCK_ID_OFFSET)?;
let id = rwlock_get_id(this, rwlock_op)?;
if this.rwlock_is_locked(id) {
throw_ub_format!("destroyed a locked rwlock");
@ -618,7 +575,7 @@ fn pthread_condattr_init(
// The default value of the clock attribute shall refer to the system
// clock.
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_condattr_setclock.html
let default_clock_id = this.eval_libc("CLOCK_REALTIME")?;
let default_clock_id = this.eval_libc_i32("CLOCK_REALTIME")?;
condattr_set_clock_id(this, attr_op, default_clock_id)?;
Ok(0)
@ -631,9 +588,9 @@ fn pthread_condattr_setclock(
) -> InterpResult<'tcx, Scalar<Provenance>> {
let this = self.eval_context_mut();
let clock_id = this.read_scalar(clock_id_op)?;
if clock_id == this.eval_libc("CLOCK_REALTIME")?
|| clock_id == this.eval_libc("CLOCK_MONOTONIC")?
let clock_id = this.read_scalar(clock_id_op)?.to_i32()?;
if clock_id == this.eval_libc_i32("CLOCK_REALTIME")?
|| clock_id == this.eval_libc_i32("CLOCK_MONOTONIC")?
{
condattr_set_clock_id(this, attr_op, clock_id)?;
} else {
@ -652,7 +609,7 @@ fn pthread_condattr_getclock(
let this = self.eval_context_mut();
let clock_id = condattr_get_clock_id(this, attr_op)?;
this.write_scalar(clock_id, &this.deref_operand(clk_id_op)?.into())?;
this.write_scalar(Scalar::from_i32(clock_id), &this.deref_operand(clk_id_op)?.into())?;
Ok(Scalar::from_i32(0))
}
@ -681,13 +638,13 @@ fn pthread_cond_init(
let attr = this.read_pointer(attr_op)?;
let clock_id = if this.ptr_is_null(attr)? {
this.eval_libc("CLOCK_REALTIME")?
this.eval_libc_i32("CLOCK_REALTIME")?
} else {
condattr_get_clock_id(this, attr_op)?
};
// Write 0 to use the same code path as the static initializers.
cond_set_id(this, cond_op, Scalar::from_i32(0))?;
cond_reset_id(this, cond_op)?;
cond_set_clock_id(this, cond_op, clock_id)?;
@ -696,7 +653,7 @@ fn pthread_cond_init(
fn pthread_cond_signal(&mut self, cond_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
let id = this.condvar_get_or_create_id(cond_op, CONDVAR_ID_OFFSET)?;
let id = cond_get_id(this, cond_op)?;
if let Some((thread, lock)) = this.condvar_signal(id) {
if let CondvarLock::Mutex(mutex) = lock {
post_cond_signal(this, thread, mutex)?;
@ -713,7 +670,7 @@ fn pthread_cond_broadcast(
cond_op: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
let id = this.condvar_get_or_create_id(cond_op, CONDVAR_ID_OFFSET)?;
let id = cond_get_id(this, cond_op)?;
while let Some((thread, lock)) = this.condvar_signal(id) {
if let CondvarLock::Mutex(mutex) = lock {
@ -733,8 +690,8 @@ fn pthread_cond_wait(
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
let id = this.condvar_get_or_create_id(cond_op, CONDVAR_ID_OFFSET)?;
let mutex_id = this.mutex_get_or_create_id(mutex_op, MUTEX_ID_OFFSET)?;
let id = cond_get_id(this, cond_op)?;
let mutex_id = mutex_get_id(this, mutex_op)?;
let active_thread = this.get_active_thread();
release_cond_mutex_and_block(this, active_thread, mutex_id)?;
@ -752,12 +709,12 @@ fn pthread_cond_timedwait(
) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
let id = this.condvar_get_or_create_id(cond_op, CONDVAR_ID_OFFSET)?;
let mutex_id = this.mutex_get_or_create_id(mutex_op, MUTEX_ID_OFFSET)?;
let id = cond_get_id(this, cond_op)?;
let mutex_id = mutex_get_id(this, mutex_op)?;
let active_thread = this.get_active_thread();
// Extract the timeout.
let clock_id = cond_get_clock_id(this, cond_op)?.to_i32()?;
let clock_id = cond_get_clock_id(this, cond_op)?;
let duration = match this.read_timespec(&this.deref_operand(abstime_op)?)? {
Some(duration) => duration,
None => {
@ -830,7 +787,7 @@ fn pthread_cond_destroy(
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
let id = this.condvar_get_or_create_id(cond_op, CONDVAR_ID_OFFSET)?;
let id = cond_get_id(this, cond_op)?;
if this.condvar_is_awaited(id) {
throw_ub_format!("destroying an awaited conditional variable");
}
@ -846,11 +803,3 @@ fn pthread_cond_destroy(
Ok(0)
}
}
fn layout_of_maybe_uninit<'tcx>(tcx: TyCtxtAt<'tcx>, param: Ty<'tcx>) -> TyAndLayout<'tcx> {
let def_id = tcx.require_lang_item(LangItem::MaybeUninit, None);
let ty = tcx.bound_type_of(def_id).subst(*tcx, &[param.into()]);
let param_env = tcx.param_env(def_id);
tcx.layout_of(param_env.and(ty)).unwrap()
}

View file

@ -1,5 +1,5 @@
use colored::*;
use regex::Regex;
use regex::bytes::Regex;
use std::path::{Path, PathBuf};
use std::{env, process::Command};
use ui_test::{color_eyre::Result, Config, Mode, OutputConflictHandling};
@ -129,8 +129,8 @@ fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> R
macro_rules! regexes {
($name:ident: $($regex:expr => $replacement:expr,)*) => {lazy_static::lazy_static! {
static ref $name: Vec<(Regex, &'static str)> = vec![
$((Regex::new($regex).unwrap(), $replacement),)*
static ref $name: Vec<(Regex, &'static [u8])> = vec![
$((Regex::new($regex).unwrap(), $replacement.as_bytes()),)*
];
}};
}

View file

@ -1,11 +0,0 @@
The following memory was leaked: ALLOC (Rust heap, size: 32, align: 8) {
0x00 │ 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 │ ................
0x10 │ 00 00 00 00 00 00 00 00 ╾$HEX[a1765]<TAG>─╼ │ ........╾──────╼
}
error: the evaluated program leaked memory
note: pass `-Zmiri-ignore-leaks` to disable this check
error: aborting due to previous error

View file

@ -0,0 +1,29 @@
#![feature(lang_items, start)]
#![no_std]
// windows tls dtors go through libstd right now, thus this test
// cannot pass. When windows tls dtors go through the special magic
// windows linker section, we can run this test on windows again.
//@ignore-target-windows: no-std not supported on Windows
extern "Rust" {
fn miri_alloc(size: usize, align: usize) -> *mut u8;
fn miri_dealloc(ptr: *mut u8, size: usize, align: usize);
}
#[start]
fn start(_: isize, _: *const *const u8) -> isize {
unsafe {
let ptr = miri_alloc(123, 1);
core::ptr::write_bytes(ptr, 0u8, 123);
miri_dealloc(ptr, 123, 1);
}
0
}
#[panic_handler]
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
loop {}
}
#[lang = "eh_personality"]
fn eh_personality() {}

View file

@ -82,6 +82,8 @@ regex = { version = "1.5.6" }
serde_json = { version = "1.0.31", features = ["raw_value", "unbounded_depth"] }
syn = { version = "1", features = ['full', 'visit'] }
url = { version = "2.0", features = ['serde'] }
# Ensure default features of rand, which are disabled in some scenarios.
rand = { version = "0.8.5" }
[target.'cfg(not(windows))'.dependencies]
openssl = { version = "0.10.35", optional = true }

View file

@ -117,6 +117,7 @@
"env_logger",
"expect-test",
"fallible-iterator", // dependency of `thorin`
"fastrand",
"filetime",
"fixedbitset",
"flate2",