Skip to content

Commit

Permalink
Auto merge of #1249 - RalfJung:rustup, r=RalfJung
Browse files Browse the repository at this point in the history
Cross-test targets

We should now be able to run Linux targets on macOS hosts and vice versa.
Cc #1198
  • Loading branch information
bors committed Mar 22, 2020
2 parents 7f47626 + b843de6 commit d7d2266
Show file tree
Hide file tree
Showing 19 changed files with 78 additions and 53 deletions.
2 changes: 0 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ env:
- RUST_BACKTRACE=1

before_script:
# Linux: install extra stuff for cross-compilation
- if [[ "$TRAVIS_OS_NAME" == linux ]]; then sudo apt update && sudo apt install gcc-multilib; fi
# Compute the rust version we use. We do not use "language: rust" to have more control here.
- |
if [[ "$TRAVIS_EVENT_TYPE" == cron ]]; then
Expand Down
10 changes: 6 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,19 @@ all the same flags as `rustc` (though the ones only affecting code generation
and linking obviously will have no effect) [and more][miri-flags].

Running the Miri driver requires some fiddling with environment variables, so
the `miri` script helps you do that. For example, you can run the driver on a
particular file by doing
the `miri` script helps you do that. For example, you can (cross-)run the
driver on a particular file by doing

```sh
./miri run tests/run-pass/format.rs
./miri run tests/run-pass/hello.rs --target i686-unknown-linux-gnu
```

and you can run the test suite using:
and you can (cross-)run the test suite using:

```
./miri test
MIRI_TEST_TARGET=i686-unknown-linux-gnu ./miri test
```

`./miri test FILTER` only runs those tests that contain `FILTER` in their
Expand Down Expand Up @@ -104,7 +105,8 @@ and then you can use it as if it was installed by `rustup`. Make sure you use
the same toolchain when calling `cargo miri` that you used when installing Miri!

There's a test for the cargo wrapper in the `test-cargo-miri` directory; run
`./run-test.py` in there to execute it.
`./run-test.py` in there to execute it. Like `./miri test`, this respects the
`MIRI_TEST_TARGET` environment variable to execute the test for another target.

## Building Miri with a locally built rustc

Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ Now you can run your project in Miri:
The first time you run Miri, it will perform some extra setup and install some
dependencies. It will ask you for confirmation before installing anything.

Miri supports cross-execution: if you want to run the program as if it was a
Linux program, you can do `cargo miri run --target x86_64-unknown-linux-gnu`.
This is particularly useful if you are using Windows, as the Linux target is
much better supported than Windows targets.

You can pass arguments to Miri after the first `--`, and pass arguments to the
interpreted program or test suite after the second `--`. For example, `cargo
miri run -- -Zmiri-disable-validation` runs the program without validation of
Expand Down
2 changes: 1 addition & 1 deletion rust-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
98803c182b2ba6ef5dccb6bf501958249295eac0
38114ff16e7856f98b2b4be7ab4cd29b38bed59a
2 changes: 1 addition & 1 deletion src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
/// Returns `Some(return_code)` if program executed completed.
/// Returns `None` if an evaluation error occured.
pub fn eval_main<'tcx>(tcx: TyCtxt<'tcx>, main_id: DefId, config: MiriConfig) -> Option<i64> {
// FIXME: We always ignore leaks on some platforms where we do not
// FIXME: We always ignore leaks on some OSs where we do not
// correctly implement TLS destructors.
let target_os = tcx.sess.target.target.target_os.as_str();
let ignore_leaks = config.ignore_leaks || target_os == "windows" || target_os == "macos";
Expand Down
12 changes: 6 additions & 6 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,16 +374,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
}
Ok(())
}
/// Helper function used inside the shims of foreign functions to assert that the target
/// platform is `platform`. It panics showing a message with the `name` of the foreign function
/// Helper function used inside the shims of foreign functions to assert that the target OS
/// is `target_os`. It panics showing a message with the `name` of the foreign function
/// if this is not the case.
fn assert_platform(&self, platform: &str, name: &str) {
fn assert_target_os(&self, target_os: &str, name: &str) {
assert_eq!(
self.eval_context_ref().tcx.sess.target.target.target_os,
platform,
"`{}` is only available on the `{}` platform",
target_os,
"`{}` is only available on the `{}` target OS",
name,
platform,
target_os,
)
}

Expand Down
2 changes: 1 addition & 1 deletion src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ impl MemoryExtra {
.insert(Symbol::intern("environ"), this.machine.env_vars.environ.unwrap().ptr.assert_ptr().alloc_id)
.unwrap_none();
}
_ => {} // No "extern statics" supported on this platform
_ => {} // No "extern statics" supported on this target
}
Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion src/shims/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
_ => match this.tcx.sess.target.target.target_os.as_str() {
"linux" | "macos" => return posix::EvalContextExt::emulate_foreign_item_by_name(this, link_name, args, dest, ret),
"windows" => return windows::EvalContextExt::emulate_foreign_item_by_name(this, link_name, args, dest, ret),
target => throw_unsup_format!("the {} target platform is not supported", target),
target => throw_unsup_format!("the target `{}` is not supported", target),
}
};

Expand Down
26 changes: 13 additions & 13 deletions src/shims/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ impl FileHandler {

impl<'mir, 'tcx> EvalContextExtPrivate<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
trait EvalContextExtPrivate<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
/// Emulate `stat` or `lstat` on the `macos` platform. This function is not intended to be
/// Emulate `stat` or `lstat` on `macos`. This function is not intended to be
/// called directly from `emulate_foreign_item_by_name`, so it does not check if isolation is
/// disabled or if the target platform is the correct one. Please use `macos_stat` or
/// disabled or if the target OS is the correct one. Please use `macos_stat` or
/// `macos_lstat` instead.
fn macos_stat_or_lstat(
&mut self,
Expand Down Expand Up @@ -114,7 +114,7 @@ trait EvalContextExtPrivate<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, '
let blksize_t_layout = this.libc_ty_layout("blksize_t")?;
let uint32_t_layout = this.libc_ty_layout("uint32_t")?;

// We need to add 32 bits of padding after `st_rdev` if we are on a 64-bit platform.
// We need to add 32 bits of padding after `st_rdev` if we are on a 64-bit target.
let pad_layout = if this.tcx.sess.target.ptr_width == 64 {
uint32_t_layout
} else {
Expand Down Expand Up @@ -258,10 +258,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let o_wronly = this.eval_libc_i32("O_WRONLY")?;
let o_rdwr = this.eval_libc_i32("O_RDWR")?;
// The first two bits of the flag correspond to the access mode in linux, macOS and
// windows. We need to check that in fact the access mode flags for the current platform
// only use these two bits, otherwise we are in an unsupported platform and should error.
// windows. We need to check that in fact the access mode flags for the current target
// only use these two bits, otherwise we are in an unsupported target and should error.
if (o_rdonly | o_wronly | o_rdwr) & !0b11 != 0 {
throw_unsup_format!("access mode flags on this platform are unsupported");
throw_unsup_format!("access mode flags on this target are unsupported");
}
let mut writable = true;

Expand Down Expand Up @@ -574,7 +574,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
buf_op: OpTy<'tcx, Tag>,
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
this.assert_platform("macos", "stat");
this.assert_target_os("macos", "stat");
this.check_no_isolation("stat")?;
// `stat` always follows symlinks.
this.macos_stat_or_lstat(true, path_op, buf_op)
Expand All @@ -587,7 +587,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
buf_op: OpTy<'tcx, Tag>,
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
this.assert_platform("macos", "lstat");
this.assert_target_os("macos", "lstat");
this.check_no_isolation("lstat")?;
this.macos_stat_or_lstat(false, path_op, buf_op)
}
Expand All @@ -599,7 +599,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();

this.assert_platform("macos", "fstat");
this.assert_target_os("macos", "fstat");
this.check_no_isolation("fstat")?;

let fd = this.read_scalar(fd_op)?.to_i32()?;
Expand All @@ -621,7 +621,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();

this.assert_platform("linux", "statx");
this.assert_target_os("linux", "statx");
this.check_no_isolation("statx")?;

let statxbuf_scalar = this.read_scalar(statxbuf_op)?.not_undef()?;
Expand Down Expand Up @@ -685,7 +685,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// the `_mask_op` paramter specifies the file information that the caller requested.
// However `statx` is allowed to return information that was not requested or to not
// return information that was requested. This `mask` represents the information we can
// actually provide in any host platform.
// actually provide for any target.
let mut mask =
this.eval_libc("STATX_TYPE")?.to_u32()? | this.eval_libc("STATX_SIZE")?.to_u32()?;

Expand Down Expand Up @@ -880,7 +880,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();

this.assert_platform("linux", "readdir64_r");
this.assert_target_os("linux", "readdir64_r");
this.check_no_isolation("readdir64_r")?;

let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
Expand Down Expand Up @@ -967,7 +967,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();

this.assert_platform("macos", "readdir_r");
this.assert_target_os("macos", "readdir_r");
this.check_no_isolation("readdir_r")?;

let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
Expand Down
4 changes: 2 additions & 2 deletions src/shims/panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ pub struct CatchUnwindData<'tcx> {

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
/// Check if panicking is supported on this platform, and give a good error otherwise.
/// Check if panicking is supported on this target, and give a good error otherwise.
fn check_panic_supported(&self) -> InterpResult<'tcx> {
match self.eval_context_ref().tcx.sess.target.target.target_os.as_str() {
"linux" | "macos" => Ok(()),
_ => throw_unsup_format!("panicking is not supported on this platform"),
_ => throw_unsup_format!("panicking is not supported on this target"),
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/shims/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();

this.assert_platform("linux", "clock_gettime");
this.assert_target_os("linux", "clock_gettime");
this.check_no_isolation("clock_gettime")?;

let clk_id = this.read_scalar(clk_id_op)?.to_i32()?;
Expand Down Expand Up @@ -58,7 +58,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();

this.assert_platform("macos", "gettimeofday");
this.assert_target_os("macos", "gettimeofday");
this.check_no_isolation("gettimeofday")?;

// Using tz is obsolete and should always be null
Expand Down Expand Up @@ -88,7 +88,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
fn mach_absolute_time(&self) -> InterpResult<'tcx, u64> {
let this = self.eval_context_ref();

this.assert_platform("macos", "mach_absolute_time");
this.assert_target_os("macos", "mach_absolute_time");
this.check_no_isolation("mach_absolute_time")?;

// This returns a u64, with time units determined dynamically by `mach_timebase_info`.
Expand Down
7 changes: 7 additions & 0 deletions test-cargo-miri/run-test.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

import sys, subprocess, os

CGREEN = '\33[32m'
CBOLD = '\33[1m'
CEND = '\33[0m'

def fail(msg):
print("\nTEST FAIL: {}".format(msg))
sys.exit(1)
Expand Down Expand Up @@ -67,6 +71,9 @@ def test_cargo_miri_test():

os.chdir(os.path.dirname(os.path.realpath(__file__)))

target_str = " for target {}".format(os.environ['MIRI_TEST_TARGET']) if 'MIRI_TEST_TARGET' in os.environ else ""
print(CGREEN + CBOLD + "## Running `cargo miri` tests{}".format(target_str) + CEND)

if not 'MIRI_SYSROOT' in os.environ:
# Make sure we got a working sysroot.
# (If the sysroot gets built later when output is compared, that leads to test failures.)
Expand Down
2 changes: 1 addition & 1 deletion test-cargo-miri/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ fn num_cpus() {

// FIXME: Remove this `cfg` once we fix https://github.com/rust-lang/miri/issues/1059.
// We cfg-gate the `should_panic` attribute and the `panic!` itself, so that the test
// stdout does not depend on the platform.
// stdout does not depend on the target.
#[test]
#[cfg_attr(not(windows), should_panic(expected="Explicit panic"))]
fn do_panic() { // In large, friendly letters :)
Expand Down
2 changes: 1 addition & 1 deletion tests/compile-fail/panic/windows1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

// Test that panics on Windows give a reasonable error message.

// error-pattern: panicking is not supported on this platform
// error-pattern: panicking is not supported on this target
fn main() {
core::panic!("this is {}", "Windows");
}
2 changes: 1 addition & 1 deletion tests/compile-fail/panic/windows2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

// Test that panics on Windows give a reasonable error message.

// error-pattern: panicking is not supported on this platform
// error-pattern: panicking is not supported on this target
fn main() {
std::panic!("this is Windows");
}
2 changes: 1 addition & 1 deletion tests/compile-fail/panic/windows3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

// Test that panics on Windows give a reasonable error message.

// error-pattern: panicking is not supported on this platform
// error-pattern: panicking is not supported on this target
#[allow(unconditional_panic)]
fn main() {
let _val = 1/0;
Expand Down
2 changes: 1 addition & 1 deletion tests/run-pass/bitop-beyond-alignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@ fn is_u64_aligned(u: &Tag<u64>) -> bool {

pub fn main() {
let x = mk_rec();
is_u64_aligned(&x.t); // the result of this is non-deterministic (even with a fixed seed, results vary between platforms)
is_u64_aligned(&x.t); // the result of this is non-deterministic (even with a fixed seed, results vary between targets)
}
2 changes: 1 addition & 1 deletion tests/run-pass/memchr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use core::slice::memchr::{memchr, memrchr};

// test fallback implementations on all platforms
// test fallback implementations on all targets
fn matches_one() {
assert_eq!(Some(0), memchr(b'a', b"a"));
}
Expand Down
39 changes: 26 additions & 13 deletions travis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
set -euo pipefail

# Determine configuration
if [ "$TRAVIS_OS_NAME" == linux ]; then
FOREIGN_TARGET=i686-unknown-linux-gnu
fi
export CARGO_EXTRA_FLAGS="--all-features"
export RUSTC_EXTRA_FLAGS="-D warnings"

Expand All @@ -16,19 +13,35 @@ echo

# Test
function run_tests {
./miri test --locked
if [ -n "${MIRI_TEST_TARGET+exists}" ]; then
echo "Testing foreign architecture $MIRI_TEST_TARGET"
else
echo "Testing host architecture"
fi

./miri test --locked
if ! [ -n "${MIRI_TEST_TARGET+exists}" ]; then
# Only for host architecture: tests with MIR optimizations
MIRI_TEST_FLAGS="-Z mir-opt-level=3" ./miri test
# "miri test" has built the sysroot for us, now this should pass without
# any interactive questions.
test-cargo-miri/run-test.py
fi
# "miri test" has built the sysroot for us, now this should pass without
# any interactive questions.
test-cargo-miri/run-test.py

echo
}

echo "Test host architecture"
# host
run_tests
echo
# cross-test 32bit Linux from everywhere
MIRI_TEST_TARGET=i686-unknown-linux-gnu run_tests

if [ -n "${FOREIGN_TARGET+exists}" ]; then
echo "Test foreign architecture ($FOREIGN_TARGET)"
MIRI_TEST_TARGET="$FOREIGN_TARGET" run_tests
echo
if [ "$TRAVIS_OS_NAME" == linux ]; then
# cross-test 64bit macOS from Linux
MIRI_TEST_TARGET=x86_64-apple-darwin run_tests
# cross-test 32bit Windows from Linux
MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests
elif [ "$TRAVIS_OS_NAME" == osx ]; then
# cross-test 64bit Windows from macOS
MIRI_TEST_TARGET=x86_64-pc-windows-msvc run_tests
fi

0 comments on commit d7d2266

Please sign in to comment.