-
Notifications
You must be signed in to change notification settings - Fork 343
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
Hold the state #18
Hold the state #18
Changes from 7 commits
e73fa77
8398781
5a8b0ab
2405c81
77e1ec2
0c269a5
5211178
6ac64f1
97bc1d4
38ae352
05f829c
cc1ca73
f995db9
346560b
02eed64
4743842
dc85b11
4c833a5
4d44a97
f42be6d
c881cf1
1f27d3f
6b939bb
8b25bc8
3de30e3
3868a62
240f0c0
2178961
cbbf58b
59d858a
225a6a2
040a501
05eaa52
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
use super::{ | ||
FnEvalContext, | ||
CachedMir, | ||
TerminatorTarget, | ||
}; | ||
use error::EvalResult; | ||
use rustc::mir::repr as mir; | ||
|
||
pub enum Event<'a, 'tcx: 'a> { | ||
Assignment(&'a mir::Statement<'tcx>), | ||
Terminator(&'a mir::Terminator<'tcx>), | ||
Done, | ||
} | ||
|
||
pub struct Stepper<'fncx, 'a: 'fncx, 'b: 'a + 'mir, 'mir: 'fncx, 'tcx: 'b>{ | ||
fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>, | ||
block: mir::BasicBlock, | ||
stmt: usize, | ||
mir: CachedMir<'mir, 'tcx>, | ||
process: fn (&mut Stepper<'fncx, 'a, 'b, 'mir, 'tcx>) -> EvalResult<()>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we replace the function pointers with an I'm not sure why we'd use a function pointer in the first place. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
because ... reasons ... no idea. I did a refactoring to get rid of the |
||
} | ||
|
||
impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx> { | ||
pub(super) fn new(fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>) -> Self { | ||
Stepper { | ||
block: fncx.frame().next_block, | ||
mir: fncx.mir(), | ||
fncx: fncx, | ||
stmt: 0, | ||
process: Self::dummy, | ||
} | ||
} | ||
|
||
fn dummy(&mut self) -> EvalResult<()> { Ok(()) } | ||
|
||
fn statement(&mut self) -> EvalResult<()> { | ||
let block_data = self.mir.basic_block_data(self.block); | ||
let stmt = &block_data.statements[self.stmt]; | ||
let mir::StatementKind::Assign(ref lvalue, ref rvalue) = stmt.kind; | ||
let result = self.fncx.eval_assignment(lvalue, rvalue); | ||
self.fncx.maybe_report(stmt.span, result)?; | ||
self.stmt += 1; | ||
Ok(()) | ||
} | ||
|
||
fn terminator(&mut self) -> EvalResult<()> { | ||
self.stmt = 0; | ||
let term = { | ||
let block_data = self.mir.basic_block_data(self.block); | ||
let terminator = block_data.terminator(); | ||
let result = self.fncx.eval_terminator(terminator); | ||
self.fncx.maybe_report(terminator.span, result)? | ||
}; | ||
match term { | ||
TerminatorTarget::Block(block) => { | ||
self.block = block; | ||
}, | ||
TerminatorTarget::Return => { | ||
self.fncx.pop_stack_frame(); | ||
self.fncx.name_stack.pop(); | ||
if !self.fncx.stack.is_empty() { | ||
self.block = self.fncx.frame().next_block; | ||
self.mir = self.fncx.mir(); | ||
} | ||
}, | ||
TerminatorTarget::Call => { | ||
self.block = self.fncx.frame().next_block; | ||
self.mir = self.fncx.mir(); | ||
}, | ||
} | ||
Ok(()) | ||
} | ||
|
||
pub fn step<'step>(&'step mut self) -> EvalResult<Event<'step, 'tcx>> { | ||
(self.process)(self)?; | ||
|
||
if self.fncx.stack.is_empty() { | ||
// fuse the iterator | ||
self.process = Self::dummy; | ||
return Ok(Event::Done); | ||
} | ||
|
||
let basic_block = self.mir.basic_block_data(self.block); | ||
|
||
if let Some(stmt) = basic_block.statements.get(self.stmt) { | ||
self.process = Self::statement; | ||
return Ok(Event::Assignment(&stmt)); | ||
} | ||
|
||
self.process = Self::terminator; | ||
Ok(Event::Terminator(basic_block.terminator())) | ||
} | ||
|
||
pub fn block(&self) -> mir::BasicBlock { | ||
self.block | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ | |
filling_drop, | ||
question_mark, | ||
rustc_private, | ||
pub_restricted, | ||
)] | ||
|
||
// From rustc. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#![feature(custom_attribute)] | ||
#![allow(dead_code, unused_attributes)] | ||
|
||
//error-pattern:literal items (e.g. mentions of function items) are unimplemented | ||
|
||
static mut X: usize = 5; | ||
|
||
#[miri_run] | ||
fn static_mut() { | ||
unsafe { | ||
X = 6; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So yeah, this might fail for a different reason in the future (mutation of a static), but I'm fine with having it here so we notice when that happens. Although it would be allowed in versions of Miri not intended for rustc const eval. |
||
assert_eq!(X, 6); | ||
} | ||
} | ||
|
||
fn main() {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we remove this field and just use
fncx.mir()
all the time?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done