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:
commit
e9493d63c2
78
Cargo.lock
78
Cargo.lock
@ -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]]
|
||||
|
6
src/tools/miri/.github/workflows/ci.yml
vendored
6
src/tools/miri/.github/workflows/ci.yml
vendored
@ -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: |
|
||||
|
@ -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"
|
||||
```
|
||||
|
||||
|
@ -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]]
|
||||
|
@ -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"] }
|
||||
|
@ -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);
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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`
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
@ -1 +1 @@
|
||||
b03502b35d111bef0399a66ab3cc765f0802e8ba
|
||||
101e1822c3e54e63996c8aaa014d55716f3937eb
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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`
|
||||
|
@ -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"),
|
||||
|
@ -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)?;
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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()),)*
|
||||
];
|
||||
}};
|
||||
}
|
||||
|
@ -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
|
||||
|
29
src/tools/miri/tests/pass/miri-alloc.rs
Normal file
29
src/tools/miri/tests/pass/miri-alloc.rs
Normal 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() {}
|
@ -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 }
|
||||
|
@ -117,6 +117,7 @@
|
||||
"env_logger",
|
||||
"expect-test",
|
||||
"fallible-iterator", // dependency of `thorin`
|
||||
"fastrand",
|
||||
"filetime",
|
||||
"fixedbitset",
|
||||
"flate2",
|
||||
|
Loading…
Reference in New Issue
Block a user