Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cross-test targets #1249

Merged
merged 7 commits into from
Mar 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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