Skip to content
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

Rollup of 9 pull requests #73838

Merged
merged 32 commits into from
Jun 28, 2020
Merged
Changes from 2 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
4c8ce48
Add partition_point
VillSnow Jun 21, 2020
c9b4915
fix: doc test
VillSnow Jun 21, 2020
27b06f1
update: doc comment
VillSnow Jun 22, 2020
8cc6998
add: tests
VillSnow Jun 22, 2020
558c8a8
Handle stores to projections correctly in liveness analysis
ecstatic-morse Jun 26, 2020
2340197
Add peek test for projections
ecstatic-morse Jun 26, 2020
88fe556
Add test for issue-71381
JohnTitor Jun 27, 2020
4c14f9d
Forward Hash::write_iN to Hash::write_uN
nikic Jun 27, 2020
99884bd
Add test for issue-71382
JohnTitor Jun 27, 2020
7125ce7
Add test for issue-71611
JohnTitor Jun 27, 2020
1d16aed
Add test for issue-72352
JohnTitor Jun 27, 2020
ffcfaa1
Fix comment.
ecstatic-morse Jun 27, 2020
6d0e5bf
Rename two `Resolver` traits
petrochenkov Jun 27, 2020
c72a5dd
Rename the lint to clashing_extern_declarations.
jumbatm Jun 28, 2020
8291a22
Fix docstring typo
cjrh Jun 28, 2020
52f9762
Add comment on use of unsafe
VillSnow Jun 28, 2020
9335787
Update src/libcore/slice/mod.rs
VillSnow Jun 28, 2020
83d5998
Merge branch 'master' of https://github.com/VillSnow/rust
VillSnow Jun 28, 2020
d720a19
Update doc comment
VillSnow Jun 28, 2020
60f2ba2
Update tracking issue number
VillSnow Jun 28, 2020
4d978af
Remove GlobalCtxt::enter_local
bjorn3 Jun 28, 2020
b9f4e0d
Erase all block-only locals at the end of every block, even if they h…
oli-obk Jun 26, 2020
6f8ad3b
Update src/libcore/slice/mod.rs
VillSnow Jun 28, 2020
ec48989
Rollup merge of #73577 - VillSnow:master, r=Amanieu
Manishearth Jun 28, 2020
ccc1bf7
Rollup merge of #73757 - oli-obk:const_prop_hardening, r=wesleywiser
Manishearth Jun 28, 2020
3f826a8
Rollup merge of #73774 - ecstatic-morse:liveness-of-projections, r=ol…
Manishearth Jun 28, 2020
2c1b732
Rollup merge of #73795 - JohnTitor:tests-for-const-fn-ptrs, r=oli-obk
Manishearth Jun 28, 2020
95da53f
Rollup merge of #73800 - nikic:hash_i, r=kennytm
Manishearth Jun 28, 2020
dd81139
Rollup merge of #73813 - petrochenkov:restrait, r=davidtwco
Manishearth Jun 28, 2020
8b92eec
Rollup merge of #73817 - jumbatm:rename-to-clashing-extern-declaratio…
Manishearth Jun 28, 2020
5304511
Rollup merge of #73826 - cjrh:cjrh-patch-1, r=jonas-schievink
Manishearth Jun 28, 2020
117b734
Rollup merge of #73833 - bjorn3:remove_gcx_enter_local, r=matthewjasper
Manishearth Jun 28, 2020
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
7 changes: 7 additions & 0 deletions src/librustc_mir/interpret/eval_context.rs
Original file line number Diff line number Diff line change
@@ -132,6 +132,10 @@ pub enum LocalValue<Tag = ()> {
}

impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
/// Read the local's value or error if the local is not yet live or not live anymore.
///
/// Note: This may only be invoked from the `Machine::access_local` hook and not from
/// anywhere else. You may be invalidating machine invariants if you do!
pub fn access(&self) -> InterpResult<'tcx, Operand<Tag>> {
match self.value {
LocalValue::Dead => throw_ub!(DeadLocal),
@@ -144,6 +148,9 @@ impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {

/// Overwrite the local. If the local can be overwritten in place, return a reference
/// to do so; otherwise return the `MemPlace` to consult instead.
///
/// Note: This may only be invoked from the `Machine::access_local_mut` hook and not from
/// anywhere else. You may be invalidating machine invariants if you do!
pub fn access_mut(
&mut self,
) -> InterpResult<'tcx, Result<&mut LocalValue<Tag>, MemPlace<Tag>>> {
19 changes: 18 additions & 1 deletion src/librustc_mir/interpret/machine.rs
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ use rustc_span::def_id::DefId;

use super::{
AllocId, Allocation, AllocationExtra, CheckInAllocMsg, Frame, ImmTy, InterpCx, InterpResult,
Memory, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Scalar,
LocalValue, MemPlace, Memory, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Scalar,
};

/// Data returned by Machine::stack_pop,
@@ -192,6 +192,8 @@ pub trait Machine<'mir, 'tcx>: Sized {
) -> InterpResult<'tcx>;

/// Called to read the specified `local` from the `frame`.
/// Since reading a ZST is not actually accessing memory or locals, this is never invoked
/// for ZST reads.
#[inline]
fn access_local(
_ecx: &InterpCx<'mir, 'tcx, Self>,
@@ -201,6 +203,21 @@ pub trait Machine<'mir, 'tcx>: Sized {
frame.locals[local].access()
}

/// Called to write the specified `local` from the `frame`.
/// Since writing a ZST is not actually accessing memory or locals, this is never invoked
/// for ZST reads.
#[inline]
fn access_local_mut<'a>(
ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
frame: usize,
local: mir::Local,
) -> InterpResult<'tcx, Result<&'a mut LocalValue<Self::PointerTag>, MemPlace<Self::PointerTag>>>
where
'tcx: 'mir,
{
ecx.stack_mut()[frame].locals[local].access_mut()
}

/// Called before a basic block terminator is executed.
/// You can use this to detect endlessly running programs.
#[inline]
6 changes: 5 additions & 1 deletion src/librustc_mir/interpret/operand.rs
Original file line number Diff line number Diff line change
@@ -432,7 +432,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
})
}

/// This is used by [priroda](https://github.com/oli-obk/priroda) to get an OpTy from a local
/// Read from a local. Will not actually access the local if reading from a ZST.
/// Will not access memory, instead an indirect `Operand` is returned.
///
/// This is public because it is used by [priroda](https://github.com/oli-obk/priroda) to get an
/// OpTy from a local
pub fn access_local(
&self,
frame: &super::Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
6 changes: 3 additions & 3 deletions src/librustc_mir/interpret/place.rs
Original file line number Diff line number Diff line change
@@ -741,7 +741,7 @@ where
// but not factored as a separate function.
let mplace = match dest.place {
Place::Local { frame, local } => {
match self.stack_mut()[frame].locals[local].access_mut()? {
match M::access_local_mut(self, frame, local)? {
Ok(local) => {
// Local can be updated in-place.
*local = LocalValue::Live(Operand::Immediate(src));
@@ -974,7 +974,7 @@ where
) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::PointerTag>, Option<Size>)> {
let (mplace, size) = match place.place {
Place::Local { frame, local } => {
match self.stack_mut()[frame].locals[local].access_mut()? {
match M::access_local_mut(self, frame, local)? {
Ok(&mut local_val) => {
// We need to make an allocation.

@@ -998,7 +998,7 @@ where
}
// Now we can call `access_mut` again, asserting it goes well,
// and actually overwrite things.
*self.stack_mut()[frame].locals[local].access_mut().unwrap().unwrap() =
*M::access_local_mut(self, frame, local).unwrap().unwrap() =
LocalValue::Live(Operand::Indirect(mplace));
(mplace, Some(size))
}
68 changes: 57 additions & 11 deletions src/librustc_mir/transform/const_prop.rs
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
use std::cell::Cell;

use rustc_ast::ast::Mutability;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::DefKind;
use rustc_hir::HirId;
use rustc_index::bit_set::BitSet;
@@ -28,7 +29,7 @@ use rustc_trait_selection::traits;
use crate::const_eval::error_to_const_error;
use crate::interpret::{
self, compile_time_machine, AllocId, Allocation, Frame, ImmTy, Immediate, InterpCx, LocalState,
LocalValue, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer,
LocalValue, MemPlace, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer,
ScalarMaybeUninit, StackPopCleanup,
};
use crate::transform::{MirPass, MirSource};
@@ -151,11 +152,19 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
struct ConstPropMachine<'mir, 'tcx> {
/// The virtual call stack.
stack: Vec<Frame<'mir, 'tcx, (), ()>>,
/// `OnlyInsideOwnBlock` locals that were written in the current block get erased at the end.
written_only_inside_own_block_locals: FxHashSet<Local>,
/// Locals that need to be cleared after every block terminates.
only_propagate_inside_block_locals: BitSet<Local>,
}

impl<'mir, 'tcx> ConstPropMachine<'mir, 'tcx> {
fn new() -> Self {
Self { stack: Vec::new() }
fn new(only_propagate_inside_block_locals: BitSet<Local>) -> Self {
Self {
stack: Vec::new(),
written_only_inside_own_block_locals: Default::default(),
only_propagate_inside_block_locals,
}
}
}

@@ -227,6 +236,18 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
l.access()
}

fn access_local_mut<'a>(
ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
frame: usize,
local: Local,
) -> InterpResult<'tcx, Result<&'a mut LocalValue<Self::PointerTag>, MemPlace<Self::PointerTag>>>
{
if frame == 0 && ecx.machine.only_propagate_inside_block_locals.contains(local) {
ecx.machine.written_only_inside_own_block_locals.insert(local);
}
ecx.machine.stack[frame].locals[local].access_mut()
}

fn before_access_global(
_memory_extra: &(),
_alloc_id: AllocId,
@@ -274,8 +295,6 @@ struct ConstPropagator<'mir, 'tcx> {
// Because we have `MutVisitor` we can't obtain the `SourceInfo` from a `Location`. So we store
// the last known `SourceInfo` here and just keep revisiting it.
source_info: Option<SourceInfo>,
// Locals we need to forget at the end of the current block
locals_of_current_block: BitSet<Local>,
}

impl<'mir, 'tcx> LayoutOf for ConstPropagator<'mir, 'tcx> {
@@ -313,8 +332,20 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
let param_env = tcx.param_env(def_id).with_reveal_all();

let span = tcx.def_span(def_id);
let mut ecx = InterpCx::new(tcx, span, param_env, ConstPropMachine::new(), ());
let can_const_prop = CanConstProp::check(body);
let mut only_propagate_inside_block_locals = BitSet::new_empty(can_const_prop.len());
for (l, mode) in can_const_prop.iter_enumerated() {
if *mode == ConstPropMode::OnlyInsideOwnBlock {
only_propagate_inside_block_locals.insert(l);
}
}
let mut ecx = InterpCx::new(
tcx,
span,
param_env,
ConstPropMachine::new(only_propagate_inside_block_locals),
(),
);

let ret = ecx
.layout_of(body.return_ty().subst(tcx, substs))
@@ -345,7 +376,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
//FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it
local_decls: body.local_decls.clone(),
source_info: None,
locals_of_current_block: BitSet::new_empty(body.local_decls.len()),
}
}

@@ -900,7 +930,6 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
Will remove it from const-prop after block is finished. Local: {:?}",
place.local
);
self.locals_of_current_block.insert(place.local);
}
ConstPropMode::OnlyPropagateInto | ConstPropMode::NoPropagation => {
trace!("can't propagate into {:?}", place);
@@ -1089,10 +1118,27 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
}
}
}
// We remove all Locals which are restricted in propagation to their containing blocks.
for local in self.locals_of_current_block.iter() {

// We remove all Locals which are restricted in propagation to their containing blocks and
// which were modified in the current block.
// Take it out of the ecx so we can get a mutable reference to the ecx for `remove_const`
let mut locals = std::mem::take(&mut self.ecx.machine.written_only_inside_own_block_locals);
for &local in locals.iter() {
Self::remove_const(&mut self.ecx, local);
}
self.locals_of_current_block.clear();
locals.clear();
// Put it back so we reuse the heap of the storage
self.ecx.machine.written_only_inside_own_block_locals = locals;
if cfg!(debug_assertions) {
// Ensure we are correctly erasing locals with the non-debug-assert logic.
for local in self.ecx.machine.only_propagate_inside_block_locals.iter() {
assert!(
self.get_const(local.into()).is_none()
|| self
.layout_of(self.local_decls[local].ty)
.map_or(true, |layout| layout.is_zst())
)
}
}
}
}