don't use #[miri_run] anymore, but execute the main function

This commit is contained in:
Oliver Schneider
2016-06-13 14:27:05 +02:00
parent fe9b455006
commit 55fd060cd8
30 changed files with 107 additions and 241 deletions
-4
View File
@@ -1,7 +1,3 @@
#![feature(custom_attribute)]
#![allow(unused_attributes)]
#[miri_run]
#[inline(never)]
pub fn main() {
assert_eq!(fib(10), 55);
-4
View File
@@ -1,7 +1,3 @@
#![feature(custom_attribute)]
#![allow(unused_attributes)]
#[miri_run]
#[inline(never)]
pub fn main() {
assert_eq!(fib(10), 55);
-4
View File
@@ -1,7 +1,3 @@
#![feature(custom_attribute)]
#![allow(unused_attributes)]
#[miri_run]
#[inline(never)]
pub fn main() {
}
+32 -41
View File
@@ -20,7 +20,10 @@
use rustc_driver::{driver, CompilerCalls};
use rustc::ty::{TyCtxt, subst};
use rustc::mir::mir_map::MirMap;
use rustc::mir::repr::Mir;
use rustc::hir::def_id::DefId;
use rustc::hir::{map, ItemFn, Item};
use syntax::codemap::Span;
struct MiriCompilerCalls;
@@ -34,58 +37,46 @@ fn build_controller(
control.after_analysis.callback = Box::new(|state| {
state.session.abort_if_errors();
interpret_start_points(state.tcx.unwrap(), state.mir_map.unwrap());
let tcx = state.tcx.unwrap();
let mir_map = state.mir_map.unwrap();
let (span, mir, def_id) = get_main(tcx, mir_map);
println!("found `main` function at: {:?}", span);
let mut ecx = EvalContext::new(tcx, mir_map);
let substs = tcx.mk_substs(subst::Substs::empty());
let return_ptr = ecx.alloc_ret_ptr(mir.return_ty, substs).expect("main function should not be diverging");
ecx.push_stack_frame(def_id, mir.span, CachedMir::Ref(mir), substs, Some(return_ptr));
loop {
match step(&mut ecx) {
Ok(true) => {}
Ok(false) => break,
// FIXME: diverging functions can end up here in some future miri
Err(e) => {
report(tcx, &ecx, e);
break;
}
}
}
});
control
}
}
fn interpret_start_points<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir_map: &MirMap<'tcx>,
) {
let initial_indentation = ::log_settings::settings().indentation;
fn get_main<'a, 'b, 'tcx: 'b>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir_map: &'b MirMap<'tcx>) -> (Span, &'b Mir<'tcx>, DefId) {
for (&id, mir) in &mir_map.map {
for attr in tcx.map.attrs(id) {
use syntax::attr::AttrMetaMethods;
if attr.check_name("miri_run") {
let item = tcx.map.expect_item(id);
::log_settings::settings().indentation = initial_indentation;
debug!("Interpreting: {}", item.name);
let mut ecx = EvalContext::new(tcx, mir_map);
let substs = tcx.mk_substs(subst::Substs::empty());
let return_ptr = ecx.alloc_ret_ptr(mir.return_ty, substs);
ecx.push_stack_frame(tcx.map.local_def_id(id), mir.span, CachedMir::Ref(mir), substs, return_ptr);
loop {
match step(&mut ecx) {
Ok(true) => {}
Ok(false) => {
match return_ptr {
Some(ptr) => if log_enabled!(::log::LogLevel::Debug) {
ecx.memory().dump(ptr.alloc_id);
},
None => warn!("diverging function returned"),
}
break;
}
// FIXME: diverging functions can end up here in some future miri
Err(e) => {
report(tcx, &ecx, e);
break;
}
}
if let map::Node::NodeItem(&Item { name, span, ref node, .. }) = tcx.map.get(id) {
if let ItemFn(..) = *node {
if name.as_str() == "main" {
return (span, mir, tcx.map.local_def_id(id));
}
}
}
}
panic!("no main function found");
}
fn report(tcx: TyCtxt, ecx: &EvalContext, e: EvalError) {
@@ -0,0 +1,8 @@
fn main() {
let p = {
let b = Box::new(42);
&*b as *const i32
};
let x = unsafe { *p }; //~ ERROR: dangling pointer was dereferenced
panic!("this should never print: {}", x);
}
+4 -9
View File
@@ -1,13 +1,8 @@
#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]
fn f() {}
#[miri_run]
fn deref_fn_ptr() -> i32 {
unsafe {
fn main() {
let x: i32 = unsafe {
*std::mem::transmute::<fn(), *const i32>(f) //~ ERROR: tried to dereference a function pointer
}
};
panic!("this should never print: {}", x);
}
fn main() {}
-62
View File
@@ -1,62 +0,0 @@
#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]
#[miri_run]
fn overwriting_part_of_relocation_makes_the_rest_undefined() -> i32 {
let mut p = &42;
unsafe {
let ptr: *mut _ = &mut p;
*(ptr as *mut u8) = 123; // if we ever support 8 bit pointers, this is gonna cause
// "attempted to interpret some raw bytes as a pointer address" instead of
// "attempted to read undefined bytes"
}
*p //~ ERROR: attempted to read undefined bytes
}
#[miri_run]
fn pointers_to_different_allocations_are_unorderable() -> bool {
let x: *const u8 = &1;
let y: *const u8 = &2;
x < y //~ ERROR: attempted to do math or a comparison on pointers into different allocations
}
#[miri_run]
fn invalid_bool() -> u8 {
let b = unsafe { std::mem::transmute::<u8, bool>(2) };
if b { 1 } else { 2 } //~ ERROR: invalid boolean value read
}
#[miri_run]
fn undefined_byte_read() -> u8 {
let v: Vec<u8> = Vec::with_capacity(10);
let undef = unsafe { *v.get_unchecked(5) };
undef + 1 //~ ERROR: attempted to read undefined bytes
}
#[miri_run]
fn out_of_bounds_read() -> u8 {
let v: Vec<u8> = vec![1, 2];
unsafe { *v.get_unchecked(5) } //~ ERROR: memory access of 5..6 outside bounds of allocation 11 which has size 2
}
#[miri_run]
fn dangling_pointer_deref() -> i32 {
let p = {
let b = Box::new(42);
&*b as *const i32
};
unsafe { *p } //~ ERROR: dangling pointer was dereferenced
}
#[miri_run]
fn wild_pointer_deref() -> i32 {
let p = 42 as *const i32;
unsafe { *p } //~ ERROR: attempted to interpret some raw bytes as a pointer address
}
#[miri_run]
fn null_pointer_deref() -> i32 {
unsafe { *std::ptr::null() } //~ ERROR: attempted to interpret some raw bytes as a pointer address
}
fn main() {}
+2 -6
View File
@@ -1,8 +1,6 @@
#![feature(custom_attribute, box_syntax)]
#![allow(dead_code, unused_attributes)]
#![feature(box_syntax)]
#[miri_run]
fn deref_fn_ptr() {
fn main() {
//FIXME: this span is wrong
let x = box 42; //~ ERROR: tried to treat a memory pointer as a function pointer
unsafe {
@@ -10,5 +8,3 @@ fn deref_fn_ptr() {
f()
}
}
fn main() {}
+4
View File
@@ -0,0 +1,4 @@
fn main() {
let b = unsafe { std::mem::transmute::<u8, bool>(2) };
if b { unreachable!() } else { unreachable!() } //~ ERROR: invalid boolean value read
}
+4
View File
@@ -0,0 +1,4 @@
fn main() {
let x: i32 = unsafe { *std::ptr::null() }; //~ ERROR: attempted to interpret some raw bytes as a pointer address
panic!("this should never print: {}", x);
}
+5
View File
@@ -0,0 +1,5 @@
fn main() {
let v: Vec<u8> = vec![1, 2];
let x = unsafe { *v.get_unchecked(5) }; //~ ERROR: memory access of 5..6 outside bounds of allocation 29 which has size 2
panic!("this should never print: {}", x);
}
@@ -0,0 +1,11 @@
fn main() {
let mut p = &42;
unsafe {
let ptr: *mut _ = &mut p;
*(ptr as *mut u8) = 123; // if we ever support 8 bit pointers, this is gonna cause
// "attempted to interpret some raw bytes as a pointer address" instead of
// "attempted to read undefined bytes"
}
let x = *p; //~ ERROR: attempted to read undefined bytes
panic!("this should never print: {}", x);
}
@@ -0,0 +1,7 @@
fn main() {
let x: *const u8 = &1;
let y: *const u8 = &2;
if x < y { //~ ERROR: attempted to do math or a comparison on pointers into different allocations
unreachable!()
}
}
@@ -0,0 +1,6 @@
fn main() {
let v: Vec<u8> = Vec::with_capacity(10);
let undef = unsafe { *v.get_unchecked(5) };
let x = undef + 1; //~ ERROR: attempted to read undefined bytes
panic!("this should never print: {}", x);
}
+1 -8
View File
@@ -1,12 +1,5 @@
#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]
//error-pattern:begin_panic_fmt
#[miri_run]
fn failed_assertions() {
fn main() {
assert_eq!(5, 6);
}
fn main() {}
+5
View File
@@ -0,0 +1,5 @@
fn main() {
let p = 42 as *const i32;
let x = unsafe { *p }; //~ ERROR: attempted to interpret some raw bytes as a pointer address
panic!("this should never print: {}", x);
}
+1 -1
View File
@@ -15,7 +15,7 @@ fn run_mode(mode: &'static str) {
.expect("need to specify RUST_SYSROOT env var or use rustup or multirust")
.to_owned(),
};
let sysroot_flag = format!("--sysroot {}", sysroot);
let sysroot_flag = format!("--sysroot {} -Dwarnings", sysroot);
// FIXME: read directories in sysroot/lib/rustlib and generate the test targets from that
let targets = &["x86_64-unknown-linux-gnu", "i686-unknown-linux-gnu"];
+1 -12
View File
@@ -1,50 +1,38 @@
#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]
#[miri_run]
fn empty_array() -> [u16; 0] {
[]
}
#[miri_run]
fn mini_array() -> [u16; 1] {
[42]
}
#[miri_run]
fn big_array() -> [u16; 5] {
[5, 4, 3, 2, 1]
}
#[miri_run]
fn array_array() -> [[u8; 2]; 3] {
[[5, 4], [3, 2], [1, 0]]
}
#[miri_run]
fn index_unsafe() -> i32 {
let a = [0, 10, 20, 30];
unsafe { *a.get_unchecked(2) }
}
#[miri_run]
fn index() -> i32 {
let a = [0, 10, 20, 30];
a[2]
}
#[miri_run]
fn array_repeat() -> [u8; 8] {
[42; 8]
}
#[miri_run]
fn slice_index() -> u8 {
let arr: &[_] = &[101, 102, 103, 104, 105, 106];
arr[5]
}
#[miri_run]
fn main() {
assert_eq!(empty_array(), []);
assert_eq!(index_unsafe(), 20);
@@ -53,4 +41,5 @@ fn main() {
assert_eq!(big_array(), [5, 4, 3, 2, 1]);
assert_eq!(array_array(), [[5, 4], [3, 2], [1, 0]]);
assert_eq!(array_repeat(), [42; 8]);
assert_eq!(mini_array(), [42]);
}
-8
View File
@@ -1,24 +1,17 @@
#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]
#[miri_run]
fn boolean() -> bool {
true
}
#[miri_run]
fn if_false() -> i64 {
let c = false;
if c { 1 } else { 0 }
}
#[miri_run]
fn if_true() -> i64 {
let c = true;
if c { 1 } else { 0 }
}
#[miri_run]
fn match_bool() -> i16 {
let b = true;
match b {
@@ -27,7 +20,6 @@ fn match_bool() -> i16 {
}
}
#[miri_run]
fn main() {
assert!(boolean());
assert_eq!(if_false(), 0);
+1 -7
View File
@@ -1,14 +1,8 @@
#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]
static mut X: usize = 5;
#[miri_run]
fn static_mut() {
fn main() {
unsafe {
X = 6;
assert_eq!(X, 6);
}
}
fn main() {}
-7
View File
@@ -1,6 +1,3 @@
#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]
enum Foo {
Bar = 42,
Baz,
@@ -13,17 +10,14 @@ enum Signed {
Quux = 100,
}
#[miri_run]
fn foo() -> [u8; 3] {
[Foo::Bar as u8, Foo::Baz as u8, Foo::Quux as u8]
}
#[miri_run]
fn signed() -> [i8; 3] {
[Signed::Bar as i8, Signed::Baz as i8, Signed::Quux as i8]
}
#[miri_run]
fn unsafe_match() -> bool {
match unsafe { std::mem::transmute::<u8, Foo>(43) } {
Foo::Baz => true,
@@ -31,7 +25,6 @@ fn unsafe_match() -> bool {
}
}
#[miri_run]
fn main() {
assert_eq!(foo(), [42, 43, 100]);
assert_eq!(signed(), [-42, -41, 100]);
+2 -8
View File
@@ -1,7 +1,5 @@
#![feature(custom_attribute, const_fn)]
#![allow(dead_code, unused_attributes)]
#![feature(const_fn)]
#[miri_run]
fn call() -> i32 {
fn increment(x: i32) -> i32 {
x + 1
@@ -9,7 +7,6 @@ fn increment(x: i32) -> i32 {
increment(1)
}
#[miri_run]
fn factorial_recursive() -> i64 {
fn fact(n: i64) -> i64 {
if n == 0 {
@@ -21,31 +18,28 @@ fn fact(n: i64) -> i64 {
fact(10)
}
#[miri_run]
fn call_generic() -> (i16, bool) {
fn id<T>(t: T) -> T { t }
(id(42), id(true))
}
// Test calling a very simple function from the standard library.
#[miri_run]
fn cross_crate_fn_call() -> i64 {
if 1i32.is_positive() { 1 } else { 0 }
}
const fn foo(i: i64) -> i64 { *&i + 1 }
#[miri_run]
fn const_fn_call() -> i64 {
let x = 5 + foo(5);
assert_eq!(x, 11);
x
}
#[miri_run]
fn main() {
assert_eq!(call(), 2);
assert_eq!(factorial_recursive(), 3628800);
assert_eq!(call_generic(), (42, true));
assert_eq!(cross_crate_fn_call(), 1);
assert_eq!(const_fn_call(), 11);
}
+3 -5
View File
@@ -1,6 +1,3 @@
#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]
fn f() -> i32 {
42
}
@@ -9,9 +6,10 @@ fn return_fn_ptr() -> fn() -> i32 {
f
}
#[miri_run]
fn call_fn_ptr() -> i32 {
return_fn_ptr()()
}
fn main() {}
fn main() {
assert_eq!(call_fn_ptr(), 42);
}
+2 -6
View File
@@ -1,17 +1,13 @@
#![feature(custom_attribute, box_syntax)]
#![allow(dead_code, unused_attributes)]
#![feature(box_syntax)]
#[miri_run]
fn make_box() -> Box<(i16, i16)> {
Box::new((1, 2))
}
#[miri_run]
fn make_box_syntax() -> Box<(i16, i16)> {
box (1, 2)
}
#[miri_run]
fn allocate_reallocate() {
let mut s = String::new();
@@ -31,8 +27,8 @@ fn allocate_reallocate() {
assert_eq!(s.capacity(), 9);
}
#[miri_run]
fn main() {
assert_eq!(*make_box(), (1, 2));
assert_eq!(*make_box_syntax(), (1, 2));
allocate_reallocate();
}
-4
View File
@@ -1,9 +1,5 @@
#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]
use std::mem::{size_of, size_of_val};
#[miri_run]
fn main() {
assert_eq!(size_of::<Option<i32>>(), 8);
assert_eq!(size_of_val(&()), 0);
-7
View File
@@ -1,7 +1,3 @@
#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]
#[miri_run]
fn factorial_loop() -> i64 {
let mut product = 1;
let mut i = 1;
@@ -14,7 +10,6 @@ fn factorial_loop() -> i64 {
product
}
#[miri_run]
fn index_for_loop() -> usize {
let mut sum = 0;
let a = [0, 10, 20, 30];
@@ -24,7 +19,6 @@ fn index_for_loop() -> usize {
sum
}
#[miri_run]
fn for_loop() -> usize {
let mut sum = 0;
let a = [0, 10, 20, 30];
@@ -34,7 +28,6 @@ fn for_loop() -> usize {
sum
}
#[miri_run]
fn main() {
assert_eq!(factorial_loop(), 3628800);
assert_eq!(index_for_loop(), 60);
-11
View File
@@ -1,25 +1,18 @@
#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]
#[miri_run]
fn one_line_ref() -> i16 {
*&1
}
#[miri_run]
fn basic_ref() -> i16 {
let x = &1;
*x
}
#[miri_run]
fn basic_ref_mut() -> i16 {
let x = &mut 1;
*x += 2;
*x
}
#[miri_run]
fn basic_ref_mut_var() -> i16 {
let mut a = 1;
{
@@ -29,7 +22,6 @@ fn basic_ref_mut_var() -> i16 {
a
}
#[miri_run]
fn tuple_ref_mut() -> (i8, i8) {
let mut t = (10, 20);
{
@@ -39,7 +31,6 @@ fn tuple_ref_mut() -> (i8, i8) {
t
}
#[miri_run]
fn match_ref_mut() -> i8 {
let mut t = (20, 22);
{
@@ -52,13 +43,11 @@ fn match_ref_mut() -> i8 {
t.0
}
#[miri_run]
fn dangling_pointer() -> *const i32 {
let b = Box::new(42);
&*b as *const i32
}
#[miri_run]
fn main() {
assert_eq!(one_line_ref(), 1);
assert_eq!(basic_ref(), 1);
+2 -9
View File
@@ -1,11 +1,7 @@
#![feature(custom_attribute, box_syntax)]
#![allow(dead_code, unused_attributes)]
use std::cell::{Cell, RefCell};
use std::cell::Cell;
use std::rc::Rc;
use std::sync::Arc;
#[miri_run]
fn rc_cell() -> Rc<Cell<i32>> {
let r = Rc::new(Cell::new(42));
let x = r.get();
@@ -15,7 +11,6 @@ fn rc_cell() -> Rc<Cell<i32>> {
// TODO(solson): also requires destructors to run for the second borrow to work
// TODO(solson): needs StructWrappedNullablePointer support
// #[miri_run]
// fn rc_refcell() -> i32 {
// let r = Rc::new(RefCell::new(42));
// *r.borrow_mut() += 10;
@@ -23,19 +18,17 @@ fn rc_cell() -> Rc<Cell<i32>> {
// x
// }
#[miri_run]
fn arc() -> Arc<i32> {
let a = Arc::new(42);
a
}
#[miri_run]
fn true_assert() {
assert_eq!(1, 1);
}
#[miri_run]
fn main() {
assert_eq!(*arc(), 42);
assert_eq!(rc_cell().get(), 84);
true_assert();
}
+4 -9
View File
@@ -4,7 +4,6 @@
#[derive(Debug, PartialEq)]
enum Unit { Unit(()) } // Force non-C-enum representation.
#[miri_run]
fn return_unit() -> Unit {
Unit::Unit(())
}
@@ -12,27 +11,22 @@ fn return_unit() -> Unit {
#[derive(Debug, PartialEq)]
enum MyBool { False(()), True(()) } // Force non-C-enum representation.
#[miri_run]
fn return_true() -> MyBool {
MyBool::True(())
}
#[miri_run]
fn return_false() -> MyBool {
MyBool::False(())
}
#[miri_run]
fn return_none() -> Option<i64> {
None
}
#[miri_run]
fn return_some() -> Option<i64> {
Some(42)
}
#[miri_run]
fn match_opt_none() -> i8 {
let x = None;
match x {
@@ -41,7 +35,6 @@ fn match_opt_none() -> i8 {
}
}
#[miri_run]
fn match_opt_some() -> i8 {
let x = Some(13);
match x {
@@ -50,13 +43,12 @@ fn match_opt_some() -> i8 {
}
}
#[miri_run]
fn two_nones() -> (Option<i16>, Option<i16>) {
(None, None)
}
// FIXME(solson): Casts inside PartialEq fails on 32-bit.
#[cfg_attr(target_pointer_width = "64", miri_run)]
#[cfg(target_pointer_width = "64")]
fn main() {
assert_eq!(two_nones(), (None, None));
assert_eq!(match_opt_some(), 13);
@@ -67,3 +59,6 @@ fn main() {
assert_eq!(return_true(), MyBool::True(()));
assert_eq!(return_unit(), Unit::Unit(()));
}
#[cfg(not(target_pointer_width = "64"))]
fn main() {}
+2 -9
View File
@@ -1,7 +1,3 @@
#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]
#[miri_run]
fn make_vec() -> Vec<u8> {
let mut v = Vec::with_capacity(4);
v.push(1);
@@ -9,17 +5,14 @@ fn make_vec() -> Vec<u8> {
v
}
#[miri_run]
fn make_vec_macro() -> Vec<u8> {
vec![1, 2]
}
#[miri_run]
fn make_vec_macro_repeat() -> Vec<u8> {
vec![42; 5]
}
#[miri_run]
fn vec_into_iter() -> u8 {
vec![1, 2, 3, 4]
.into_iter()
@@ -27,7 +20,6 @@ fn vec_into_iter() -> u8 {
.fold(0, |x, y| x + y)
}
#[miri_run]
fn vec_reallocate() -> Vec<u8> {
let mut v = vec![1, 2];
v.push(3);
@@ -36,9 +28,10 @@ fn vec_reallocate() -> Vec<u8> {
v
}
#[miri_run]
fn main() {
assert_eq!(vec_reallocate().len(), 5);
assert_eq!(vec_into_iter(), 30);
assert_eq!(make_vec().capacity(), 4);
assert_eq!(make_vec_macro(), [1, 2]);
assert_eq!(make_vec_macro_repeat(), [42; 5]);
}