Merge branch 'master' into appveyor
This commit is contained in:
commit
bab9abefa1
@ -39,6 +39,7 @@ directories = { version = "1.0", optional = true }
|
|||||||
rustc_version = { version = "0.2.3", optional = true }
|
rustc_version = { version = "0.2.3", optional = true }
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
shell-escape = "0.1.4"
|
||||||
# A noop dependency that changes in the Rust repository, it's a bit of a hack.
|
# 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`
|
# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
|
||||||
# for more information.
|
# for more information.
|
||||||
|
@ -48,6 +48,13 @@ Now you can run your project in Miri:
|
|||||||
3. If you have a binary project, you can run it through Miri using `cargo
|
3. If you have a binary project, you can run it through Miri using `cargo
|
||||||
+nightly miri run`.
|
+nightly miri run`.
|
||||||
|
|
||||||
|
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
|
||||||
|
+nightly miri run -- -Zmiri-disable-validation` runs the program without
|
||||||
|
validation of basic type invariants and references. `cargo +nightly miri test
|
||||||
|
-- -- filter` passes `filter` to the test suite the same way `cargo test filter`
|
||||||
|
would.
|
||||||
|
|
||||||
When running code via `cargo miri`, the `miri` config flag is set. You can
|
When running code via `cargo miri`, the `miri` config flag is set. You can
|
||||||
use this to exclude test cases that will fail under Miri because they do things
|
use this to exclude test cases that will fail under Miri because they do things
|
||||||
Miri does not support:
|
Miri does not support:
|
||||||
|
@ -4,11 +4,13 @@
|
|||||||
extern crate rustc_driver;
|
extern crate rustc_driver;
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
|
||||||
use self::miri::eval_main;
|
use rustc_driver::{driver, Compilation};
|
||||||
use self::rustc_driver::{driver, Compilation};
|
|
||||||
use rustc::hir::def_id::LOCAL_CRATE;
|
use rustc::hir::def_id::LOCAL_CRATE;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use miri::{MiriConfig, eval_main};
|
||||||
|
|
||||||
use crate::test::Bencher;
|
use crate::test::Bencher;
|
||||||
|
|
||||||
pub struct MiriCompilerCalls<'a>(Rc<RefCell<&'a mut Bencher>>);
|
pub struct MiriCompilerCalls<'a>(Rc<RefCell<&'a mut Bencher>>);
|
||||||
@ -50,7 +52,8 @@ pub fn run(filename: &str, bencher: &mut Bencher) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
bencher.borrow_mut().iter(|| {
|
bencher.borrow_mut().iter(|| {
|
||||||
eval_main(tcx, entry_def_id, false);
|
let config = MiriConfig { validate: true, args: vec![] };
|
||||||
|
eval_main(tcx, entry_def_id, config);
|
||||||
});
|
});
|
||||||
|
|
||||||
state.session.abort_if_errors();
|
state.session.abort_if_errors();
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
const CARGO_MIRI_HELP: &str = r#"Interprets bin crates and tests in Miri
|
const CARGO_MIRI_HELP: &str = r#"Interprets bin crates and tests in Miri
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
cargo miri [subcommand] [options] [--] [<miri opts>...]
|
cargo miri [subcommand] [options] [--] [<miri opts>...] [--] [<program opts>...]
|
||||||
|
|
||||||
Subcommands:
|
Subcommands:
|
||||||
run Run binaries (default)
|
run Run binaries (default)
|
||||||
@ -22,8 +22,9 @@
|
|||||||
--features Features to compile for the package
|
--features Features to compile for the package
|
||||||
-V, --version Print version info and exit
|
-V, --version Print version info and exit
|
||||||
|
|
||||||
Other [options] are the same as `cargo rustc`. Everything after the "--" is
|
Other [options] are the same as `cargo rustc`. Everything after the first "--" is
|
||||||
passed verbatim to Miri.
|
passed verbatim to Miri, which will pass everything after the second "--" verbatim
|
||||||
|
to the interpreted program.
|
||||||
|
|
||||||
The config flag `miri` is automatically defined for convenience. You can use
|
The config flag `miri` is automatically defined for convenience. You can use
|
||||||
it to configure the resource limits
|
it to configure the resource limits
|
||||||
@ -355,11 +356,13 @@ fn in_cargo_miri() {
|
|||||||
}
|
}
|
||||||
cmd.arg(arg);
|
cmd.arg(arg);
|
||||||
}
|
}
|
||||||
// add "--" "-Zcargo-miri-marker" and the remaining user flags
|
// Add "--" (to end the cargo flags), and then the user flags. We add markers around the user flags
|
||||||
|
// to be able to identify them later.
|
||||||
cmd
|
cmd
|
||||||
.arg("--")
|
.arg("--")
|
||||||
.arg("cargo-miri-marker")
|
.arg("cargo-miri-marker-begin")
|
||||||
.args(args);
|
.args(args)
|
||||||
|
.arg("cargo-miri-marker-end");
|
||||||
let path = std::env::current_exe().expect("current executable path invalid");
|
let path = std::env::current_exe().expect("current executable path invalid");
|
||||||
cmd.env("RUSTC_WRAPPER", path);
|
cmd.env("RUSTC_WRAPPER", path);
|
||||||
if verbose {
|
if verbose {
|
||||||
@ -413,10 +416,19 @@ fn inside_cargo_rustc() {
|
|||||||
};
|
};
|
||||||
args.splice(0..0, miri::miri_default_args().iter().map(ToString::to_string));
|
args.splice(0..0, miri::miri_default_args().iter().map(ToString::to_string));
|
||||||
|
|
||||||
// see if we have cargo-miri-marker, which means we want to interpret this crate in Miri
|
// See if we can find the cargo-miri markers. Those only get added to the binary we want to
|
||||||
// (and remove the marker).
|
// run. They also serve to mark the user-defined arguments, which we have to move all the way to the
|
||||||
let needs_miri = if let Some(pos) = args.iter().position(|arg| arg == "cargo-miri-marker") {
|
// end (they get added somewhere in the middle).
|
||||||
args.remove(pos);
|
let needs_miri = if let Some(begin) = args.iter().position(|arg| arg == "cargo-miri-marker-begin") {
|
||||||
|
let end = args.iter().position(|arg| arg == "cargo-miri-marker-end").expect("Cannot find end marker");
|
||||||
|
// These mark the user arguments. We remove the first and last as they are the markers.
|
||||||
|
let mut user_args = args.drain(begin..=end);
|
||||||
|
assert_eq!(user_args.next().unwrap(), "cargo-miri-marker-begin");
|
||||||
|
assert_eq!(user_args.next_back().unwrap(), "cargo-miri-marker-end");
|
||||||
|
// Collect the rest and add it back at the end
|
||||||
|
let mut user_args = user_args.collect::<Vec<String>>();
|
||||||
|
args.append(&mut user_args);
|
||||||
|
// Run this in Miri
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use rustc::hir::def_id::LOCAL_CRATE;
|
use rustc::hir::def_id::LOCAL_CRATE;
|
||||||
|
|
||||||
|
use miri::MiriConfig;
|
||||||
|
|
||||||
struct MiriCompilerCalls {
|
struct MiriCompilerCalls {
|
||||||
default: Box<RustcDefaultCalls>,
|
default: Box<RustcDefaultCalls>,
|
||||||
/// whether we are building for the host
|
/// whether we are building for the host
|
||||||
@ -94,9 +96,10 @@ impl<'a, 'tcx: 'a, 'hir> itemlikevisit::ItemLikeVisitor<'hir> for Visitor<'a, 't
|
|||||||
fn visit_item(&mut self, i: &'hir hir::Item) {
|
fn visit_item(&mut self, i: &'hir hir::Item) {
|
||||||
if let hir::ItemKind::Fn(.., body_id) = i.node {
|
if let hir::ItemKind::Fn(.., body_id) = i.node {
|
||||||
if i.attrs.iter().any(|attr| attr.name() == "test") {
|
if i.attrs.iter().any(|attr| attr.name() == "test") {
|
||||||
|
let config = MiriConfig { validate: true, args: vec![] };
|
||||||
let did = self.0.hir().body_owner_def_id(body_id);
|
let did = self.0.hir().body_owner_def_id(body_id);
|
||||||
println!("running test: {}", self.0.def_path_debug_str(did));
|
println!("running test: {}", self.0.def_path_debug_str(did));
|
||||||
miri::eval_main(self.0, did, /*validate*/true);
|
miri::eval_main(self.0, did, config);
|
||||||
self.1.session.abort_if_errors();
|
self.1.session.abort_if_errors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,7 +109,8 @@ fn visit_impl_item(&mut self, _impl_item: &'hir hir::ImplItem) {}
|
|||||||
}
|
}
|
||||||
state.hir_crate.unwrap().visit_all_item_likes(&mut Visitor(tcx, state));
|
state.hir_crate.unwrap().visit_all_item_likes(&mut Visitor(tcx, state));
|
||||||
} else if let Some((entry_def_id, _)) = tcx.entry_fn(LOCAL_CRATE) {
|
} else if let Some((entry_def_id, _)) = tcx.entry_fn(LOCAL_CRATE) {
|
||||||
miri::eval_main(tcx, entry_def_id, /*validate*/true);
|
let config = MiriConfig { validate: true, args: vec![] };
|
||||||
|
miri::eval_main(tcx, entry_def_id, config);
|
||||||
|
|
||||||
state.session.abort_if_errors();
|
state.session.abort_if_errors();
|
||||||
} else {
|
} else {
|
||||||
|
@ -27,11 +27,11 @@
|
|||||||
use rustc::hir::def_id::LOCAL_CRATE;
|
use rustc::hir::def_id::LOCAL_CRATE;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
|
||||||
|
use miri::MiriConfig;
|
||||||
|
|
||||||
struct MiriCompilerCalls {
|
struct MiriCompilerCalls {
|
||||||
default: Box<RustcDefaultCalls>,
|
default: Box<RustcDefaultCalls>,
|
||||||
|
miri_config: MiriConfig,
|
||||||
/// Whether to enforce the validity invariant.
|
|
||||||
validate: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
|
impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
|
||||||
@ -79,6 +79,8 @@ fn late_callback(
|
|||||||
odir: &Option<PathBuf>,
|
odir: &Option<PathBuf>,
|
||||||
ofile: &Option<PathBuf>,
|
ofile: &Option<PathBuf>,
|
||||||
) -> Compilation {
|
) -> Compilation {
|
||||||
|
// Called *before* build_controller. Add filename to miri arguments.
|
||||||
|
self.miri_config.args.insert(0, input.filestem().to_string());
|
||||||
self.default.late_callback(codegen_backend, matches, sess, cstore, input, odir, ofile)
|
self.default.late_callback(codegen_backend, matches, sess, cstore, input, odir, ofile)
|
||||||
}
|
}
|
||||||
fn build_controller(
|
fn build_controller(
|
||||||
@ -89,9 +91,9 @@ fn build_controller(
|
|||||||
let this = *self;
|
let this = *self;
|
||||||
let mut control = this.default.build_controller(sess, matches);
|
let mut control = this.default.build_controller(sess, matches);
|
||||||
control.after_hir_lowering.callback = Box::new(after_hir_lowering);
|
control.after_hir_lowering.callback = Box::new(after_hir_lowering);
|
||||||
let validate = this.validate;
|
let miri_config = this.miri_config;
|
||||||
control.after_analysis.callback =
|
control.after_analysis.callback =
|
||||||
Box::new(move |state| after_analysis(state, validate));
|
Box::new(move |state| after_analysis(state, miri_config.clone()));
|
||||||
control.after_analysis.stop = Compilation::Stop;
|
control.after_analysis.stop = Compilation::Stop;
|
||||||
control
|
control
|
||||||
}
|
}
|
||||||
@ -107,7 +109,7 @@ fn after_hir_lowering(state: &mut CompileState) {
|
|||||||
|
|
||||||
fn after_analysis<'a, 'tcx>(
|
fn after_analysis<'a, 'tcx>(
|
||||||
state: &mut CompileState<'a, 'tcx>,
|
state: &mut CompileState<'a, 'tcx>,
|
||||||
validate: bool,
|
miri_config: MiriConfig,
|
||||||
) {
|
) {
|
||||||
init_late_loggers();
|
init_late_loggers();
|
||||||
state.session.abort_if_errors();
|
state.session.abort_if_errors();
|
||||||
@ -117,7 +119,7 @@ fn after_analysis<'a, 'tcx>(
|
|||||||
|
|
||||||
let (entry_def_id, _) = tcx.entry_fn(LOCAL_CRATE).expect("no main function found!");
|
let (entry_def_id, _) = tcx.entry_fn(LOCAL_CRATE).expect("no main function found!");
|
||||||
|
|
||||||
miri::eval_main(tcx, entry_def_id, validate);
|
miri::eval_main(tcx, entry_def_id, miri_config);
|
||||||
|
|
||||||
state.session.abort_if_errors();
|
state.session.abort_if_errors();
|
||||||
}
|
}
|
||||||
@ -188,34 +190,51 @@ fn find_sysroot() -> String {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
init_early_loggers();
|
init_early_loggers();
|
||||||
let mut args: Vec<String> = std::env::args().collect();
|
|
||||||
|
|
||||||
// Parse our own -Z flags and remove them before rustc gets their hand on them.
|
// Parse our arguments and split them across rustc and miri
|
||||||
let mut validate = true;
|
let mut validate = true;
|
||||||
args.retain(|arg| {
|
let mut rustc_args = vec![];
|
||||||
match arg.as_str() {
|
let mut miri_args = vec![];
|
||||||
"-Zmiri-disable-validation" => {
|
let mut after_dashdash = false;
|
||||||
validate = false;
|
for arg in std::env::args() {
|
||||||
false
|
if rustc_args.is_empty() {
|
||||||
},
|
// Very first arg: for rustc
|
||||||
_ => true
|
rustc_args.push(arg);
|
||||||
}
|
}
|
||||||
});
|
else if after_dashdash {
|
||||||
|
// Everything that comes is Miri args
|
||||||
|
miri_args.push(arg);
|
||||||
|
} else {
|
||||||
|
match arg.as_str() {
|
||||||
|
"-Zmiri-disable-validation" => {
|
||||||
|
validate = false;
|
||||||
|
},
|
||||||
|
"--" => {
|
||||||
|
after_dashdash = true;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
rustc_args.push(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Determine sysroot and let rustc know about it
|
// Determine sysroot and let rustc know about it
|
||||||
let sysroot_flag = String::from("--sysroot");
|
let sysroot_flag = String::from("--sysroot");
|
||||||
if !args.contains(&sysroot_flag) {
|
if !rustc_args.contains(&sysroot_flag) {
|
||||||
args.push(sysroot_flag);
|
rustc_args.push(sysroot_flag);
|
||||||
args.push(find_sysroot());
|
rustc_args.push(find_sysroot());
|
||||||
}
|
}
|
||||||
// Finally, add the default flags all the way in the beginning, but after the binary name.
|
// Finally, add the default flags all the way in the beginning, but after the binary name.
|
||||||
args.splice(1..1, miri::miri_default_args().iter().map(ToString::to_string));
|
rustc_args.splice(1..1, miri::miri_default_args().iter().map(ToString::to_string));
|
||||||
|
|
||||||
trace!("rustc arguments: {:?}", args);
|
debug!("rustc arguments: {:?}", rustc_args);
|
||||||
|
debug!("miri arguments: {:?}", miri_args);
|
||||||
|
let miri_config = MiriConfig { validate, args: miri_args };
|
||||||
let result = rustc_driver::run(move || {
|
let result = rustc_driver::run(move || {
|
||||||
rustc_driver::run_compiler(&args, Box::new(MiriCompilerCalls {
|
rustc_driver::run_compiler(&rustc_args, Box::new(MiriCompilerCalls {
|
||||||
default: Box::new(RustcDefaultCalls),
|
default: Box::new(RustcDefaultCalls),
|
||||||
validate,
|
miri_config,
|
||||||
}), None, None)
|
}), None, None)
|
||||||
});
|
});
|
||||||
std::process::exit(result as i32);
|
std::process::exit(result as i32);
|
||||||
|
57
src/lib.rs
57
src/lib.rs
@ -57,16 +57,23 @@ pub fn miri_default_args() -> &'static [&'static str] {
|
|||||||
&["-Zalways-encode-mir", "-Zmir-emit-retag", "-Zmir-opt-level=0", "--cfg=miri"]
|
&["-Zalways-encode-mir", "-Zmir-emit-retag", "-Zmir-opt-level=0", "--cfg=miri"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Configuration needed to spawn a Miri instance
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct MiriConfig {
|
||||||
|
pub validate: bool,
|
||||||
|
pub args: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
// Used by priroda
|
// Used by priroda
|
||||||
pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
|
pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
main_id: DefId,
|
main_id: DefId,
|
||||||
validate: bool,
|
config: MiriConfig,
|
||||||
) -> EvalResult<'tcx, EvalContext<'a, 'mir, 'tcx, Evaluator<'tcx>>> {
|
) -> EvalResult<'tcx, EvalContext<'a, 'mir, 'tcx, Evaluator<'tcx>>> {
|
||||||
let mut ecx = EvalContext::new(
|
let mut ecx = EvalContext::new(
|
||||||
tcx.at(syntax::source_map::DUMMY_SP),
|
tcx.at(syntax::source_map::DUMMY_SP),
|
||||||
ty::ParamEnv::reveal_all(),
|
ty::ParamEnv::reveal_all(),
|
||||||
Evaluator::new(validate),
|
Evaluator::new(config.validate),
|
||||||
);
|
);
|
||||||
|
|
||||||
let main_instance = ty::Instance::mono(ecx.tcx.tcx, main_id);
|
let main_instance = ty::Instance::mono(ecx.tcx.tcx, main_id);
|
||||||
@ -120,7 +127,7 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
|
|||||||
|
|
||||||
// Second argument (argc): 1
|
// Second argument (argc): 1
|
||||||
let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?;
|
let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?;
|
||||||
let argc = Scalar::from_int(1, dest.layout.size);
|
let argc = Scalar::from_uint(config.args.len() as u128, dest.layout.size);
|
||||||
ecx.write_scalar(argc, dest)?;
|
ecx.write_scalar(argc, dest)?;
|
||||||
// Store argc for macOS _NSGetArgc
|
// Store argc for macOS _NSGetArgc
|
||||||
{
|
{
|
||||||
@ -130,18 +137,38 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: extract main source file path
|
// FIXME: extract main source file path
|
||||||
// Third argument (argv): &[b"foo"]
|
// Third argument (argv): Created from config.args
|
||||||
const CMD: &str = "running-in-miri\0";
|
|
||||||
let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?;
|
let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?;
|
||||||
let cmd = ecx.memory_mut().allocate_static_bytes(CMD.as_bytes()).with_default_tag();
|
// For Windows, construct a command string with all the aguments
|
||||||
let raw_str_layout = ecx.layout_of(ecx.tcx.mk_imm_ptr(ecx.tcx.types.u8))?;
|
let mut cmd = String::new();
|
||||||
let cmd_place = ecx.allocate(raw_str_layout, MiriMemoryKind::Env.into());
|
for arg in config.args.iter() {
|
||||||
ecx.write_scalar(Scalar::Ptr(cmd), cmd_place.into())?;
|
if !cmd.is_empty() {
|
||||||
ecx.memory_mut().mark_immutable(cmd_place.to_ptr()?.alloc_id)?;
|
cmd.push(' ');
|
||||||
|
}
|
||||||
|
cmd.push_str(&*shell_escape::windows::escape(arg.as_str().into()));
|
||||||
|
}
|
||||||
|
cmd.push(std::char::from_u32(0).unwrap()); // don't forget 0 terminator
|
||||||
|
// Collect the pointers to the individual strings.
|
||||||
|
let mut argvs = Vec::<Pointer<Borrow>>::new();
|
||||||
|
for arg in config.args {
|
||||||
|
// Add 0 terminator
|
||||||
|
let mut arg = arg.into_bytes();
|
||||||
|
arg.push(0);
|
||||||
|
argvs.push(ecx.memory_mut().allocate_static_bytes(arg.as_slice()).with_default_tag());
|
||||||
|
}
|
||||||
|
// Make an array with all these pointers, in the Miri memory.
|
||||||
|
let argvs_layout = ecx.layout_of(ecx.tcx.mk_array(ecx.tcx.mk_imm_ptr(ecx.tcx.types.u8), argvs.len() as u64))?;
|
||||||
|
let argvs_place = ecx.allocate(argvs_layout, MiriMemoryKind::Env.into());
|
||||||
|
for (idx, arg) in argvs.into_iter().enumerate() {
|
||||||
|
let place = ecx.mplace_field(argvs_place, idx as u64)?;
|
||||||
|
ecx.write_scalar(Scalar::Ptr(arg), place.into())?;
|
||||||
|
}
|
||||||
|
ecx.memory_mut().mark_immutable(argvs_place.to_ptr()?.alloc_id)?;
|
||||||
|
// Write a pointe to that place as the argument.
|
||||||
|
let argv = argvs_place.ptr;
|
||||||
|
ecx.write_scalar(argv, dest)?;
|
||||||
// Store argv for macOS _NSGetArgv
|
// Store argv for macOS _NSGetArgv
|
||||||
{
|
{
|
||||||
let argv = cmd_place.ptr;
|
|
||||||
ecx.write_scalar(argv, dest)?;
|
|
||||||
let argv_place = ecx.allocate(dest.layout, MiriMemoryKind::Env.into());
|
let argv_place = ecx.allocate(dest.layout, MiriMemoryKind::Env.into());
|
||||||
ecx.write_scalar(argv, argv_place.into())?;
|
ecx.write_scalar(argv, argv_place.into())?;
|
||||||
ecx.machine.argv = Some(argv_place.ptr.to_ptr()?);
|
ecx.machine.argv = Some(argv_place.ptr.to_ptr()?);
|
||||||
@ -149,7 +176,7 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
|
|||||||
// Store cmdline as UTF-16 for Windows GetCommandLineW
|
// Store cmdline as UTF-16 for Windows GetCommandLineW
|
||||||
{
|
{
|
||||||
let tcx = &{ecx.tcx.tcx};
|
let tcx = &{ecx.tcx.tcx};
|
||||||
let cmd_utf16: Vec<u16> = CMD.encode_utf16().collect();
|
let cmd_utf16: Vec<u16> = cmd.encode_utf16().collect();
|
||||||
let cmd_ptr = ecx.memory_mut().allocate(
|
let cmd_ptr = ecx.memory_mut().allocate(
|
||||||
Size::from_bytes(cmd_utf16.len() as u64 * 2),
|
Size::from_bytes(cmd_utf16.len() as u64 * 2),
|
||||||
Align::from_bytes(2).unwrap(),
|
Align::from_bytes(2).unwrap(),
|
||||||
@ -179,9 +206,9 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
|
|||||||
pub fn eval_main<'a, 'tcx: 'a>(
|
pub fn eval_main<'a, 'tcx: 'a>(
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
main_id: DefId,
|
main_id: DefId,
|
||||||
validate: bool,
|
config: MiriConfig,
|
||||||
) {
|
) {
|
||||||
let mut ecx = create_ecx(tcx, main_id, validate).expect("Couldn't create ecx");
|
let mut ecx = create_ecx(tcx, main_id, config).expect("Couldn't create ecx");
|
||||||
|
|
||||||
// Run! The main execution.
|
// Run! The main execution.
|
||||||
let res: EvalResult = (|| {
|
let res: EvalResult = (|| {
|
||||||
|
@ -37,10 +37,19 @@ def test(name, cmd, stdout_ref, stderr_ref):
|
|||||||
|
|
||||||
def test_cargo_miri_run():
|
def test_cargo_miri_run():
|
||||||
test("cargo miri run", ["cargo", "miri", "run", "-q"], "stdout.ref", "stderr.ref")
|
test("cargo miri run", ["cargo", "miri", "run", "-q"], "stdout.ref", "stderr.ref")
|
||||||
|
test("cargo miri run (with arguments)",
|
||||||
|
["cargo", "miri", "run", "-q", "--", "--", "hello world", '"hello world"'],
|
||||||
|
"stdout.ref", "stderr.ref2"
|
||||||
|
)
|
||||||
|
|
||||||
def test_cargo_miri_test():
|
def test_cargo_miri_test():
|
||||||
test("cargo miri test", ["cargo", "miri", "test", "-q"], "test.stdout.ref", "test.stderr.ref")
|
test("cargo miri test", ["cargo", "miri", "test", "-q"], "test.stdout.ref", "test.stderr.ref")
|
||||||
|
test("cargo miri test (with filter)",
|
||||||
|
["cargo", "miri", "test", "-q", "--", "--", "impl"],
|
||||||
|
"test.stdout.ref2", "test.stderr.ref"
|
||||||
|
)
|
||||||
|
|
||||||
test_cargo_miri_run()
|
test_cargo_miri_run()
|
||||||
test_cargo_miri_test()
|
test_cargo_miri_test()
|
||||||
|
print("TEST SUCCESSFUL!")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
@ -9,7 +9,9 @@ fn main() {
|
|||||||
let n = <BigEndian as ByteOrder>::read_u32(buf);
|
let n = <BigEndian as ByteOrder>::read_u32(buf);
|
||||||
assert_eq!(n, 0x01020304);
|
assert_eq!(n, 0x01020304);
|
||||||
println!("{:#010x}", n);
|
println!("{:#010x}", n);
|
||||||
eprintln!("standard error");
|
for arg in std::env::args() {
|
||||||
|
eprintln!("{}", arg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -1 +1 @@
|
|||||||
standard error
|
main
|
||||||
|
3
test-cargo-miri/stderr.ref2
Normal file
3
test-cargo-miri/stderr.ref2
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
main
|
||||||
|
hello world
|
||||||
|
"hello world"
|
11
test-cargo-miri/test.stdout.ref2
Normal file
11
test-cargo-miri/test.stdout.ref2
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
running 0 tests
|
||||||
|
|
||||||
|
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out
|
||||||
|
|
||||||
|
|
||||||
|
running 1 test
|
||||||
|
test simple ... ok
|
||||||
|
|
||||||
|
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out
|
||||||
|
|
5
tests/run-pass/args.rs
Normal file
5
tests/run-pass/args.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
fn main() {
|
||||||
|
for arg in std::env::args() {
|
||||||
|
println!("{}", arg);
|
||||||
|
}
|
||||||
|
}
|
1
tests/run-pass/args.stdout
Normal file
1
tests/run-pass/args.stdout
Normal file
@ -0,0 +1 @@
|
|||||||
|
args
|
Loading…
Reference in New Issue
Block a user