Skip to content

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

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

Merged
merged 5 commits into from
Jun 15, 2016
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
4 changes: 0 additions & 4 deletions benches/fibonacci_helper.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
#![feature(custom_attribute)]
#![allow(unused_attributes)]

#[miri_run]
#[inline(never)]
pub fn main() {
assert_eq!(fib(10), 55);
Expand Down
4 changes: 0 additions & 4 deletions benches/fibonacci_helper_iterative.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
#![feature(custom_attribute)]
#![allow(unused_attributes)]

#[miri_run]
#[inline(never)]
pub fn main() {
assert_eq!(fib(10), 55);
Expand Down
4 changes: 0 additions & 4 deletions benches/smoke_helper.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
#![feature(custom_attribute)]
#![allow(unused_attributes)]

#[miri_run]
#[inline(never)]
pub fn main() {
}
82 changes: 35 additions & 47 deletions src/bin/miri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use miri::{
use rustc::session::Session;
use rustc_driver::{driver, CompilerCalls};
use rustc::ty::{TyCtxt, subst};
use rustc::mir::mir_map::MirMap;
use rustc::hir::def_id::DefId;

struct MiriCompilerCalls;
Expand All @@ -34,57 +33,46 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls {

control.after_analysis.callback = Box::new(|state| {
state.session.abort_if_errors();
interpret_start_points(state.tcx.unwrap(), state.mir_map.unwrap());
});

control
}
}


let tcx = state.tcx.unwrap();
let mir_map = state.mir_map.unwrap();

let (node_id, span) = state.session.entry_fn.borrow().expect("no main or start function found");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, so this returns either the #[main] or #[start] function? That's a bit weird - we need to call them differently. Currently we're calling a #[start] without its two arguments, which I believe means they are left as undefined bytes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

debug!("found `main` function at: {:?}", span);

let mir = mir_map.map.get(&node_id).expect("no mir for main function");
let def_id = tcx.map.local_def_id(node_id);
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));

if mir.arg_decls.len() == 2 {
// start function
let ptr_size = ecx.memory().pointer_size;
let nargs = ecx.memory_mut().allocate(ptr_size);
ecx.memory_mut().write_usize(nargs, 0).unwrap();
let args = ecx.memory_mut().allocate(ptr_size);
ecx.memory_mut().write_usize(args, 0).unwrap();
ecx.frame_mut().locals[0] = nargs;
ecx.frame_mut().locals[1] = args;
}

fn interpret_start_points<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir_map: &MirMap<'tcx>,
) {
let initial_indentation = ::log_settings::settings().indentation;
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;
}
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
}
}

Expand Down
6 changes: 5 additions & 1 deletion src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
&self.memory
}

pub fn memory_mut(&mut self) -> &mut Memory<'tcx> {
&mut self.memory
}

pub fn stack(&self) -> &[Frame] {
&self.stack
}
Expand Down Expand Up @@ -1373,7 +1377,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
self.stack.last().expect("no call frames exist")
}

fn frame_mut(&mut self) -> &mut Frame<'a, 'tcx> {
pub fn frame_mut(&mut self) -> &mut Frame<'a, 'tcx> {
self.stack.last_mut().expect("no call frames exist")
}

Expand Down
8 changes: 8 additions & 0 deletions tests/compile-fail/dangling_pointer_deref.rs
Original file line number Diff line number Diff line change
@@ -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);
}
13 changes: 4 additions & 9 deletions tests/compile-fail/deref_fn_ptr.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 0 additions & 62 deletions tests/compile-fail/errors.rs

This file was deleted.

8 changes: 2 additions & 6 deletions tests/compile-fail/execute_memory.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
#![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 {
let f = std::mem::transmute::<Box<i32>, fn()>(x);
f()
}
}

fn main() {}
4 changes: 4 additions & 0 deletions tests/compile-fail/invalid_bool.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 4 additions & 0 deletions tests/compile-fail/null_pointer_deref.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 5 additions & 0 deletions tests/compile-fail/out_of_bounds_read.rs
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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!()
}
}
6 changes: 6 additions & 0 deletions tests/compile-fail/undefined_byte_read.rs
Original file line number Diff line number Diff line change
@@ -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);
}
9 changes: 1 addition & 8 deletions tests/compile-fail/unimplemented.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 5 additions & 0 deletions tests/compile-fail/wild_pointer_deref.rs
Original file line number Diff line number Diff line change
@@ -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);
}
9 changes: 6 additions & 3 deletions tests/compiletest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,23 @@ 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 flags = 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"];

for &target in targets {
use std::io::Write;
let stderr = std::io::stderr();
write!(stderr.lock(), "running tests for target {}", target).unwrap();
let mut config = compiletest::default_config();
config.host_rustcflags = Some(sysroot_flag.clone());
config.host_rustcflags = Some(flags.clone());
config.mode = mode.parse().expect("Invalid mode");
config.run_lib_path = format!("{}/lib/rustlib/{}/lib", sysroot, target);
config.rustc_path = "target/debug/miri".into();
config.src_base = PathBuf::from(format!("tests/{}", mode));
config.target = target.to_owned();
config.target_rustcflags = Some(sysroot_flag.clone());
config.target_rustcflags = Some(flags.clone());
compiletest::run_tests(&config);
}
}
Expand Down
13 changes: 1 addition & 12 deletions tests/run-pass/arrays.rs
Original file line number Diff line number Diff line change
@@ -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);
Expand All @@ -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]);
}
Loading