-
Notifications
You must be signed in to change notification settings - Fork 360
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
interpret StorageLive & StorageDead, and check dead stack slots are not used #176
Conversation
MIR-libstd fails in flush_buf: https://github.com/rust-lang/rust/blob/2277f4bdcc1195a5f6c9c96d8d1fb32482cbd673/src/libstd/io/buffered.rs#L385 It has a loop, so I assume it's the same issue. |
The bugs qere in old trans, where we weren't always consistent about scopes. FWIW you could experiment yourself by using |
Well, I doubt I will be able to find interesting things by randomly adding such calls. The questions: Do we have hard evidence that redundant StorageLive are harmful? When we talked about this in IRC (#rustc) earlier today, rkruppe quoted LLVM devs saying that they should be fine: https://botbot.me/mozilla/rustc/2017-06-01/?msg=86639833&page=1 |
LLVM optimizations are relatively easy to trigger: just read & write a variable and see how IR changes with lifetime intrinsics. As for the actual bugs, it's been a while, although @arielb1 might remember better. |
src/eval_context.rs
Outdated
@@ -452,10 +453,33 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { | |||
) -> EvalResult<'tcx> { | |||
::log_settings::settings().indentation += 1; | |||
|
|||
/// Return the set of locals that have a stroage annotation anywhere |
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.
Typo storage
src/eval_context.rs
Outdated
let num_locals = mir.local_decls.len() - 1; | ||
let locals = vec![Value::ByVal(PrimVal::Undef); num_locals]; | ||
let mut locals = Vec::with_capacity(num_locals); | ||
for i in 0..num_locals { |
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.
Init locals with vec![None; num_locals]
and use the loop from the function to change to Some
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.
Actually.. why are you marking these as alive here and not at the storagelive call?
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.
This marks those variables as live that do not have a StorageLive call.
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.
Oh. I didn't see the inversion.
I'm not sure whether multiple |
src/lvalue.rs
Outdated
@@ -130,7 +130,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { | |||
Ok(Value::ByRef(ptr)) | |||
} | |||
Lvalue::Local { frame, local, field } => { | |||
Ok(self.stack[frame].get_local(local, field.map(|(i, _)| i))) | |||
Ok(self.stack[frame].get_local(local, field.map(|(i, _)| i))?) |
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.
Ok(
and ?)
is redundant
src/step.rs
Outdated
StorageLive(ref lvalue) | StorageDead(ref lvalue)=> { | ||
let (frame, local) = match self.eval_lvalue(lvalue)? { | ||
Lvalue::Local{ frame, local, field: None } if self.stack.len() == frame+1 => (frame, local), | ||
_ => return Err(EvalError::Unimplemented("Stroage annotations must refer to locals of the topmost stack frame.".to_owned())) // FIXME maybe this should get its own error type |
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.
*storage
I fixed the nits you brought up. I also adapted the suggestion of @arielb1 to make Finally, I opened a bug in rustc proper about StorageLive in loops: rust-lang/rust#42371. |
Github says "Changes requested", but I think I made all the requested changes... how do I clear that flag? |
You didnt fix the spell error at step.rs line 133 yet. |
oops sorry, missed that one |
(This is work-in-progress, test suite currently fails.)
This changes the stack slots to be of type
Option<Value>
, whereNone
represents the case of a "dead" stack slot.StorageLive
/StorageDead
mark slots as live/dead. So this also effectively defines the semantics of these commands. Right now, the semantics are as follows:The third bullet point above is the most questionable. In particular, it makes the test suite fail in loops.rs. Have a look at _4 in factorial_loop in http://play.integer32.com/?gist=08a6b697560aabb9bd8165efcbd8b082&version=nightly. As the program goes around the loop, it runs StorageLive twice without running StorageDead in between, so miri bails out. LLVM is unfortunately unclear on whether this is legal or not. @eddyb mentioned there were some bugs with redundant StorageLive, or maybe I misunderstood?
(Test suite with MIR-libstd fails every test, I am still investigating that.)
Cc @nikomatsakis
Fixes #49.