Skip to content

Commit 53dc505

Browse files
authored
Merge pull request #488 from RalfJung/start-fn
Automatically use start-fn if we have all the MIR
2 parents 8d754e6 + 8134918 commit 53dc505

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+108
-153
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ script:
5050
# test `cargo miri`
5151
cd cargo-miri-test &&
5252
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
53-
cargo miri -q -- -Zmiri-start-fn
53+
cargo miri -q
5454
else
55-
cargo miri -q -- -Zmiri-start-fn >stdout.real 2>stderr.real &&
55+
cargo miri -q >stdout.real 2>stderr.real &&
5656
cat stdout.real stderr.real &&
5757
# Test `cargo miri` output. Not on mac because output redirecting doesn't
5858
# work. There is no error. It just stops CI.

src/bin/miri-rustc-tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
9595
if i.attrs.iter().any(|attr| attr.name() == "test") {
9696
let did = self.0.hir.body_owner_def_id(body_id);
9797
println!("running test: {}", self.0.def_path_debug_str(did));
98-
miri::eval_main(self.0, did, None, /*validate*/true);
98+
miri::eval_main(self.0, did, /*validate*/true);
9999
self.1.session.abort_if_errors();
100100
}
101101
}
@@ -106,7 +106,7 @@ fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
106106
state.hir_crate.unwrap().visit_all_item_likes(&mut Visitor(tcx, state));
107107
} else if let Some((entry_node_id, _, _)) = *state.session.entry_fn.borrow() {
108108
let entry_def_id = tcx.hir.local_def_id(entry_node_id);
109-
miri::eval_main(tcx, entry_def_id, None, /*validate*/true);
109+
miri::eval_main(tcx, entry_def_id, /*validate*/true);
110110

111111
state.session.abort_if_errors();
112112
} else {

src/bin/miri.rs

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,6 @@ use std::path::PathBuf;
2626
struct MiriCompilerCalls {
2727
default: Box<RustcDefaultCalls>,
2828

29-
/// Whether to begin interpretation at the start_fn lang item or not.
30-
///
31-
/// If false, the interpretation begins at the `main` function.
32-
start_fn: bool,
33-
3429
/// Whether to enforce the validity invariant.
3530
validate: bool,
3631
}
@@ -90,10 +85,9 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
9085
let this = *self;
9186
let mut control = this.default.build_controller(sess, matches);
9287
control.after_hir_lowering.callback = Box::new(after_hir_lowering);
93-
let start_fn = this.start_fn;
9488
let validate = this.validate;
9589
control.after_analysis.callback =
96-
Box::new(move |state| after_analysis(state, start_fn, validate));
90+
Box::new(move |state| after_analysis(state, validate));
9791
control.after_analysis.stop = Compilation::Stop;
9892
control
9993
}
@@ -109,7 +103,6 @@ fn after_hir_lowering(state: &mut CompileState) {
109103

110104
fn after_analysis<'a, 'tcx>(
111105
state: &mut CompileState<'a, 'tcx>,
112-
use_start_fn: bool,
113106
validate: bool,
114107
) {
115108
state.session.abort_if_errors();
@@ -134,7 +127,7 @@ fn after_analysis<'a, 'tcx>(
134127
"running test: {}",
135128
self.tcx.def_path_debug_str(did),
136129
);
137-
miri::eval_main(self.tcx, did, None, self.validate);
130+
miri::eval_main(self.tcx, did, self.validate);
138131
self.state.session.abort_if_errors();
139132
}
140133
}
@@ -147,13 +140,7 @@ fn after_analysis<'a, 'tcx>(
147140
);
148141
} else if let Some((entry_node_id, _, _)) = *state.session.entry_fn.borrow() {
149142
let entry_def_id = tcx.hir.local_def_id(entry_node_id);
150-
// Use start_fn lang item if we have -Zmiri-start-fn set
151-
let start_wrapper = if use_start_fn {
152-
Some(tcx.lang_items().start_fn().unwrap())
153-
} else {
154-
None
155-
};
156-
miri::eval_main(tcx, entry_def_id, start_wrapper, validate);
143+
miri::eval_main(tcx, entry_def_id, validate);
157144

158145
state.session.abort_if_errors();
159146
} else {
@@ -231,14 +218,9 @@ fn main() {
231218
args.push(find_sysroot());
232219
}
233220

234-
let mut start_fn = false;
235221
let mut validate = true;
236222
args.retain(|arg| {
237223
match arg.as_str() {
238-
"-Zmiri-start-fn" => {
239-
start_fn = true;
240-
false
241-
},
242224
"-Zmiri-disable-validation" => {
243225
validate = false;
244226
false
@@ -251,7 +233,6 @@ fn main() {
251233
let result = rustc_driver::run(move || {
252234
rustc_driver::run_compiler(&args, Box::new(MiriCompilerCalls {
253235
default: Box::new(RustcDefaultCalls),
254-
start_fn,
255236
validate,
256237
}), None, None)
257238
});

src/fn_call.rs

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
use rustc::ty;
22
use rustc::ty::layout::{Align, LayoutOf, Size};
3-
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
3+
use rustc::hir::def_id::DefId;
44
use rustc::mir;
55
use syntax::attr;
66

7-
use std::mem;
8-
97
use super::*;
108

119
pub trait EvalContextExt<'tcx, 'mir> {
@@ -19,8 +17,6 @@ pub trait EvalContextExt<'tcx, 'mir> {
1917
ret: mir::BasicBlock,
2018
) -> EvalResult<'tcx>;
2119

22-
fn resolve_path(&self, path: &[&str]) -> EvalResult<'tcx, ty::Instance<'tcx>>;
23-
2420
/// Emulate a function that should have MIR but does not.
2521
/// This is solely to support execution without full MIR.
2622
/// Fail if emulating this function is not supported.
@@ -638,40 +634,6 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for EvalContext<'a, '
638634
Ok(())
639635
}
640636

641-
/// Get an instance for a path.
642-
fn resolve_path(&self, path: &[&str]) -> EvalResult<'tcx, ty::Instance<'tcx>> {
643-
self.tcx
644-
.crates()
645-
.iter()
646-
.find(|&&krate| self.tcx.original_crate_name(krate) == path[0])
647-
.and_then(|krate| {
648-
let krate = DefId {
649-
krate: *krate,
650-
index: CRATE_DEF_INDEX,
651-
};
652-
let mut items = self.tcx.item_children(krate);
653-
let mut path_it = path.iter().skip(1).peekable();
654-
655-
while let Some(segment) = path_it.next() {
656-
for item in mem::replace(&mut items, Default::default()).iter() {
657-
if item.ident.name == *segment {
658-
if path_it.peek().is_none() {
659-
return Some(ty::Instance::mono(self.tcx.tcx, item.def.def_id()));
660-
}
661-
662-
items = self.tcx.item_children(item.def.def_id());
663-
break;
664-
}
665-
}
666-
}
667-
None
668-
})
669-
.ok_or_else(|| {
670-
let path = path.iter().map(|&s| s.to_owned()).collect();
671-
EvalErrorKind::PathNotFound(path).into()
672-
})
673-
}
674-
675637
fn emulate_missing_fn(
676638
&mut self,
677639
path: String,
@@ -699,7 +661,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for EvalContext<'a, '
699661
"std::io::_print" |
700662
"std::io::_eprint" => {
701663
warn!(
702-
"Ignoring output. To run programs that print, make sure you have a libstd with full MIR."
664+
"Ignoring output. To run programs that prints, make sure you have a libstd with full MIR."
703665
);
704666
}
705667
"std::thread::Builder::new" => {

src/helpers.rs

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1-
use super::{Scalar, ScalarMaybeUndef, EvalResult};
1+
use std::mem;
22

3-
pub trait FalibleScalarExt {
3+
use rustc::ty;
4+
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
5+
6+
use super::*;
7+
8+
pub trait ScalarExt {
49
/// HACK: this function just extracts all bits if `defined != 0`
510
/// Mainly used for args of C-functions and we should totally correctly fetch the size
611
/// of their arguments
712
fn to_bytes(self) -> EvalResult<'static, u128>;
813
}
914

10-
impl FalibleScalarExt for Scalar {
15+
impl ScalarExt for Scalar {
1116
fn to_bytes(self) -> EvalResult<'static, u128> {
1217
match self {
1318
Scalar::Bits { bits, size } => {
@@ -19,8 +24,49 @@ impl FalibleScalarExt for Scalar {
1924
}
2025
}
2126

22-
impl FalibleScalarExt for ScalarMaybeUndef {
27+
impl ScalarExt for ScalarMaybeUndef {
2328
fn to_bytes(self) -> EvalResult<'static, u128> {
2429
self.not_undef()?.to_bytes()
2530
}
2631
}
32+
33+
pub trait EvalContextExt<'tcx> {
34+
fn resolve_path(&self, path: &[&str]) -> EvalResult<'tcx, ty::Instance<'tcx>>;
35+
}
36+
37+
38+
impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super::Evaluator<'tcx>> {
39+
/// Get an instance for a path.
40+
fn resolve_path(&self, path: &[&str]) -> EvalResult<'tcx, ty::Instance<'tcx>> {
41+
self.tcx
42+
.crates()
43+
.iter()
44+
.find(|&&krate| self.tcx.original_crate_name(krate) == path[0])
45+
.and_then(|krate| {
46+
let krate = DefId {
47+
krate: *krate,
48+
index: CRATE_DEF_INDEX,
49+
};
50+
let mut items = self.tcx.item_children(krate);
51+
let mut path_it = path.iter().skip(1).peekable();
52+
53+
while let Some(segment) = path_it.next() {
54+
for item in mem::replace(&mut items, Default::default()).iter() {
55+
if item.ident.name == *segment {
56+
if path_it.peek().is_none() {
57+
return Some(ty::Instance::mono(self.tcx.tcx, item.def.def_id()));
58+
}
59+
60+
items = self.tcx.item_children(item.def.def_id());
61+
break;
62+
}
63+
}
64+
}
65+
None
66+
})
67+
.ok_or_else(|| {
68+
let path = path.iter().map(|&s| s.to_owned()).collect();
69+
EvalErrorKind::PathNotFound(path).into()
70+
})
71+
}
72+
}

src/intrinsic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_mir::interpret::{EvalContext, PlaceTy, OpTy};
77

88
use super::{
99
Value, Scalar, ScalarMaybeUndef,
10-
FalibleScalarExt, OperatorEvalContextExt
10+
ScalarExt, OperatorEvalContextExt
1111
};
1212

1313
pub trait EvalContextExt<'tcx> {

src/lib.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ use operator::EvalContextExt as OperatorEvalContextExt;
4343
use intrinsic::EvalContextExt as IntrinsicEvalContextExt;
4444
use tls::{EvalContextExt as TlsEvalContextExt, TlsData};
4545
use range_map::RangeMap;
46-
use helpers::FalibleScalarExt;
46+
#[allow(unused_imports)] // FIXME rustc bug https://github.com/rust-lang/rust/issues/53682
47+
use helpers::{ScalarExt, EvalContextExt as HelpersEvalContextExt};
4748
use mono_hash_map::MonoHashMap;
4849

4950
pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
5051
tcx: TyCtxt<'a, 'tcx, 'tcx>,
5152
main_id: DefId,
52-
start_wrapper: Option<DefId>,
5353
validate: bool,
5454
) -> EvalResult<'tcx, EvalContext<'a, 'mir, 'tcx, Evaluator<'tcx>>> {
5555
let mut ecx = EvalContext::new(
@@ -69,8 +69,14 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
6969
));
7070
}
7171

72-
if let Some(start_id) = start_wrapper {
73-
let main_ret_ty = ecx.tcx.fn_sig(main_id).output();
72+
let libstd_has_mir = {
73+
let rustc_panic = ecx.resolve_path(&["std", "panicking", "rust_panic"])?;
74+
ecx.load_mir(rustc_panic.def).is_ok()
75+
};
76+
77+
if libstd_has_mir {
78+
let start_id = tcx.lang_items().start_fn().unwrap();
79+
let main_ret_ty = tcx.fn_sig(main_id).output();
7480
let main_ret_ty = main_ret_ty.no_late_bound_regions().unwrap();
7581
let start_instance = ty::Instance::resolve(
7682
ecx.tcx.tcx,
@@ -145,10 +151,9 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
145151
pub fn eval_main<'a, 'tcx: 'a>(
146152
tcx: TyCtxt<'a, 'tcx, 'tcx>,
147153
main_id: DefId,
148-
start_wrapper: Option<DefId>,
149154
validate: bool,
150155
) {
151-
let mut ecx = create_ecx(tcx, main_id, start_wrapper, validate).expect("Couldn't create ecx");
156+
let mut ecx = create_ecx(tcx, main_id, validate).expect("Couldn't create ecx");
152157

153158
let res: EvalResult = (|| {
154159
ecx.run()?;

tests/compile-fail-fullmir/reallocate-change-alloc.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ fn main() {
99
unsafe {
1010
let x = Global.alloc(Layout::from_size_align_unchecked(1, 1)).unwrap();
1111
Global.realloc(x, Layout::from_size_align_unchecked(1, 1), 1).unwrap();
12-
let _z = *(x.as_ptr() as *mut u8); //~ ERROR constant evaluation error
13-
//~^ NOTE dangling pointer was dereferenced
12+
let _z = *(x.as_ptr() as *mut u8); //~ ERROR dangling pointer was dereferenced
1413
}
1514
}

tests/compile-fail/alignment.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ fn main() {
55
let x_ptr: *mut u8 = &mut x[0];
66
let y_ptr = x_ptr as *mut u64;
77
unsafe {
8-
*y_ptr = 42; //~ ERROR constant evaluation error
9-
//~^ NOTE tried to access memory with alignment 1, but alignment
8+
*y_ptr = 42; //~ ERROR tried to access memory with alignment 1, but alignment
109
}
1110
panic!("unreachable in miri");
1211
}

tests/compile-fail/assume.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ fn main() {
55
unsafe {
66
std::intrinsics::assume(x < 10);
77
std::intrinsics::assume(x > 1);
8-
std::intrinsics::assume(x > 42); //~ ERROR constant evaluation error
9-
//~^ NOTE `assume` argument was false
8+
std::intrinsics::assume(x > 42); //~ `assume` argument was false
109
}
1110
}

tests/compile-fail/bitop-beyond-alignment.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,10 @@ fn mk_rec() -> Rec {
2828
fn is_u64_aligned(u: &Tag<u64>) -> bool {
2929
let p: usize = unsafe { mem::transmute(u) };
3030
let u64_align = std::mem::align_of::<u64>();
31-
return (p & (u64_align + 1)) == 0; //~ ERROR constant evaluation error
32-
//~^ NOTE a raw memory access tried to access part of a pointer value as raw bytes
31+
return (p & (u64_align + 1)) == 0; //~ ERROR a raw memory access tried to access part of a pointer value as raw bytes
3332
}
3433

3534
pub fn main() {
3635
let x = mk_rec();
37-
assert!(is_u64_aligned(&x.t)); //~ NOTE inside call to `is_u64_aligned
36+
assert!(is_u64_aligned(&x.t));
3837
}

tests/compile-fail/cast_box_int_to_fn_ptr.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,5 @@ fn main() {
77
std::mem::transmute::<&usize, &fn(i32)>(&b)
88
};
99

10-
(*g)(42) //~ ERROR constant evaluation error
11-
//~^ NOTE a memory access tried to interpret some bytes as a pointer
10+
(*g)(42) //~ ERROR a memory access tried to interpret some bytes as a pointer
1211
}

tests/compile-fail/cast_int_to_fn_ptr.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,5 @@ fn main() {
66
std::mem::transmute::<usize, fn(i32)>(42)
77
};
88

9-
g(42) //~ ERROR constant evaluation error
10-
//~^ NOTE a memory access tried to interpret some bytes as a pointer
9+
g(42) //~ ERROR a memory access tried to interpret some bytes as a pointer
1110
}

tests/compile-fail/dangling_pointer_deref.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ fn main() {
33
let b = Box::new(42);
44
&*b as *const i32
55
};
6-
let x = unsafe { *p }; //~ ERROR constant evaluation error
7-
//~^ NOTE dangling pointer was dereferenced
6+
let x = unsafe { *p }; //~ ERROR dangling pointer was dereferenced
87
panic!("this should never print: {}", x);
98
}

tests/compile-fail/div-by-zero-2.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,5 @@
1111
#![allow(const_err)]
1212

1313
fn main() {
14-
let _n = 1 / 0; //~ ERROR constant evaluation error
15-
//~^ NOTE attempt to divide by zero
14+
let _n = 1 / 0; //~ ERROR attempt to divide by zero
1615
}

tests/compile-fail/execute_memory.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ fn main() {
77
let x = box 42;
88
unsafe {
99
let f = std::mem::transmute::<Box<i32>, fn()>(x);
10-
f() //~ ERROR constant evaluation error
11-
//~^ NOTE tried to treat a memory pointer as a function pointer
10+
f() //~ ERROR tried to treat a memory pointer as a function pointer
1211
}
1312
}

tests/compile-fail/fn_ptr_offset.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,5 @@ fn main() {
1010
let y : *mut u8 = unsafe { mem::transmute(x) };
1111
let y = y.wrapping_offset(1);
1212
let x : fn() = unsafe { mem::transmute(y) };
13-
x(); //~ ERROR constant evaluation error
14-
//~^ NOTE tried to use a function pointer after offsetting it
13+
x(); //~ ERROR tried to use a function pointer after offsetting it
1514
}

0 commit comments

Comments
 (0)