Skip to content

Commit

Permalink
Auto merge of #55716 - RalfJung:escape-to-raw, r=oli-obk
Browse files Browse the repository at this point in the history
Add escape-to-raw MIR statement

Add a new MIR "ghost state statement": Escaping a ptr to permit raw accesses.

~~This includes #55549, [click here](RalfJung/rust@miri-visitor...RalfJung:escape-to-raw) for just the new commits.~~
  • Loading branch information
bors committed Nov 15, 2018
2 parents 7d3b9b1 + b891a81 commit 4ec0ba9
Show file tree
Hide file tree
Showing 31 changed files with 267 additions and 163 deletions.
3 changes: 3 additions & 0 deletions src/librustc/ich/impls_mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,9 @@ for mir::StatementKind<'gcx> {
mir::StatementKind::EndRegion(ref region_scope) => {
region_scope.hash_stable(hcx, hasher);
}
mir::StatementKind::EscapeToRaw(ref place) => {
place.hash_stable(hcx, hasher);
}
mir::StatementKind::Retag { fn_entry, ref place } => {
fn_entry.hash_stable(hcx, hasher);
place.hash_stable(hcx, hasher);
Expand Down
9 changes: 9 additions & 0 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1782,6 +1782,13 @@ pub enum StatementKind<'tcx> {
place: Place<'tcx>,
},

/// Escape the given reference to a raw pointer, so that it can be accessed
/// without precise provenance tracking. These statements are currently only interpreted
/// by miri and only generated when "-Z mir-emit-retag" is passed.
/// See <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/>
/// for more details.
EscapeToRaw(Operand<'tcx>),

/// Mark one terminating point of a region scope (i.e. static region).
/// (The starting point(s) arise implicitly from borrows.)
EndRegion(region::Scope),
Expand Down Expand Up @@ -1843,6 +1850,7 @@ impl<'tcx> Debug for Statement<'tcx> {
EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)),
Retag { fn_entry, ref place } =>
write!(fmt, "Retag({}{:?})", if fn_entry { "[fn entry] " } else { "" }, place),
EscapeToRaw(ref place) => write!(fmt, "EscapeToRaw({:?})", place),
StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place),
StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place),
SetDiscriminant {
Expand Down Expand Up @@ -3019,6 +3027,7 @@ EnumTypeFoldableImpl! {
(StatementKind::StorageDead)(a),
(StatementKind::InlineAsm) { asm, outputs, inputs },
(StatementKind::Retag) { fn_entry, place },
(StatementKind::EscapeToRaw)(place),
(StatementKind::EndRegion)(a),
(StatementKind::AscribeUserType)(a, v, b),
(StatementKind::Nop),
Expand Down
5 changes: 4 additions & 1 deletion src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,9 @@ macro_rules! make_mir_visitor {
location
);
}
StatementKind::EscapeToRaw(ref $($mutability)* op) => {
self.visit_operand(op, location);
}
StatementKind::StorageLive(ref $($mutability)* local) => {
self.visit_local(
local,
Expand Down Expand Up @@ -1022,7 +1025,7 @@ pub enum MutatingUseContext<'tcx> {
/// f(&mut x.y);
///
Projection,
/// Retagging (updating the "Stacked Borrows" tag)
/// Retagging, a "Stacked Borrows" shadow state operation
Retag,
}

Expand Down
3 changes: 2 additions & 1 deletion src/librustc_codegen_llvm/mir/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,9 @@ impl FunctionCx<'a, 'll, 'tcx> {
bx
}
mir::StatementKind::FakeRead(..) |
mir::StatementKind::EndRegion(_) |
mir::StatementKind::EndRegion(..) |
mir::StatementKind::Retag { .. } |
mir::StatementKind::EscapeToRaw { .. } |
mir::StatementKind::AscribeUserType(..) |
mir::StatementKind::Nop => bx,
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/borrow_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
StatementKind::Nop
| StatementKind::AscribeUserType(..)
| StatementKind::Retag { .. }
| StatementKind::EscapeToRaw { .. }
| StatementKind::StorageLive(..) => {
// `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant
// to borrow check.
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/borrow_check/nll/invalidation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
StatementKind::Nop |
StatementKind::AscribeUserType(..) |
StatementKind::Retag { .. } |
StatementKind::EscapeToRaw { .. } |
StatementKind::StorageLive(..) => {
// `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant
// to borrow check.
Expand Down
5 changes: 3 additions & 2 deletions src/librustc_mir/borrow_check/nll/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1311,11 +1311,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
}
}
StatementKind::FakeRead(..)
| StatementKind::StorageLive(_)
| StatementKind::StorageDead(_)
| StatementKind::StorageLive(..)
| StatementKind::StorageDead(..)
| StatementKind::InlineAsm { .. }
| StatementKind::EndRegion(_)
| StatementKind::Retag { .. }
| StatementKind::EscapeToRaw { .. }
| StatementKind::Nop => {}
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/librustc_mir/build/expr/as_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
// region_scope=None so place indexes live forever. They are scalars so they
// do not need storage annotations, and they are often copied between
// places.
// Making this a *fresh* temporary also means we do not have to worry about
// the index changing later: Nothing will ever change this temporary.
// The "retagging" transformation (for Stacked Borrows) relies on this.
let idx = unpack!(block = this.as_temp(block, None, index, Mutability::Mut));

// bounds check:
Expand Down
1 change: 0 additions & 1 deletion src/librustc_mir/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,6 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>;

const STATIC_KIND: Option<!> = None; // no copying of statics allowed
const ENABLE_PTR_TRACKING_HOOKS: bool = false; // we don't have no provenance

#[inline(always)]
fn enforce_validity(_ecx: &EvalContext<'a, 'mir, 'tcx, Self>) -> bool {
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/dataflow/impls/borrows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
mir::StatementKind::SetDiscriminant { .. } |
mir::StatementKind::StorageLive(..) |
mir::StatementKind::Retag { .. } |
mir::StatementKind::EscapeToRaw { .. } |
mir::StatementKind::AscribeUserType(..) |
mir::StatementKind::Nop => {}

Expand Down
3 changes: 2 additions & 1 deletion src/librustc_mir/dataflow/move_paths/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,9 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
span_bug!(stmt.source_info.span,
"SetDiscriminant should not exist during borrowck");
}
StatementKind::EndRegion(_) |
StatementKind::EndRegion(..) |
StatementKind::Retag { .. } |
StatementKind::EscapeToRaw { .. } |
StatementKind::AscribeUserType(..) |
StatementKind::Nop => {}
}
Expand Down
27 changes: 7 additions & 20 deletions src/librustc_mir/interpret/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,40 +44,28 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
}

Misc => {
let src_layout = src.layout;
let src = self.read_immediate(src)?;

let src = if M::ENABLE_PTR_TRACKING_HOOKS && src_layout.ty.is_region_ptr() {
// The only `Misc` casts on references are those creating raw pointers.
assert!(dest.layout.ty.is_unsafe_ptr());
// For the purpose of the "ptr tag hooks", treat this as creating
// a new, raw reference.
let place = self.ref_to_mplace(src)?;
self.create_ref(place, None)?
} else {
*src
};

if self.type_is_fat_ptr(src_layout.ty) {
match (src, self.type_is_fat_ptr(dest.layout.ty)) {
if self.type_is_fat_ptr(src.layout.ty) {
match (*src, self.type_is_fat_ptr(dest.layout.ty)) {
// pointers to extern types
(Immediate::Scalar(_),_) |
// slices and trait objects to other slices/trait objects
(Immediate::ScalarPair(..), true) => {
// No change to immediate
self.write_immediate(src, dest)?;
self.write_immediate(*src, dest)?;
}
// slices and trait objects to thin pointers (dropping the metadata)
(Immediate::ScalarPair(data, _), false) => {
self.write_scalar(data, dest)?;
}
}
} else {
match src_layout.variants {
match src.layout.variants {
layout::Variants::Single { index } => {
if let Some(def) = src_layout.ty.ty_adt_def() {
if let Some(def) = src.layout.ty.ty_adt_def() {
// Cast from a univariant enum
assert!(src_layout.is_zst());
assert!(src.layout.is_zst());
let discr_val = def
.discriminant_for_variant(*self.tcx, index)
.val;
Expand All @@ -90,8 +78,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
layout::Variants::NicheFilling { .. } => {},
}

let src = src.to_scalar()?;
let dest_val = self.cast_scalar(src, src_layout, dest.layout)?;
let dest_val = self.cast_scalar(src.to_scalar()?, src.layout, dest.layout)?;
self.write_scalar(dest_val, dest)?;
}
}
Expand Down
14 changes: 6 additions & 8 deletions src/librustc_mir/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,18 +201,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
} else if Some(def_id) == self.tcx.lang_items().panic_fn() {
assert!(args.len() == 1);
// &(&'static str, &'static str, u32, u32)
let ptr = self.read_immediate(args[0])?;
let place = self.ref_to_mplace(ptr)?;
let place = self.deref_operand(args[0])?;
let (msg, file, line, col) = (
self.mplace_field(place, 0)?,
self.mplace_field(place, 1)?,
self.mplace_field(place, 2)?,
self.mplace_field(place, 3)?,
);

let msg_place = self.ref_to_mplace(self.read_immediate(msg.into())?)?;
let msg_place = self.deref_operand(msg.into())?;
let msg = Symbol::intern(self.read_str(msg_place)?);
let file_place = self.ref_to_mplace(self.read_immediate(file.into())?)?;
let file_place = self.deref_operand(file.into())?;
let file = Symbol::intern(self.read_str(file_place)?);
let line = self.read_scalar(line.into())?.to_u32()?;
let col = self.read_scalar(col.into())?.to_u32()?;
Expand All @@ -221,17 +220,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
assert!(args.len() == 2);
// &'static str, &(&'static str, u32, u32)
let msg = args[0];
let ptr = self.read_immediate(args[1])?;
let place = self.ref_to_mplace(ptr)?;
let place = self.deref_operand(args[1])?;
let (file, line, col) = (
self.mplace_field(place, 0)?,
self.mplace_field(place, 1)?,
self.mplace_field(place, 2)?,
);

let msg_place = self.ref_to_mplace(self.read_immediate(msg.into())?)?;
let msg_place = self.deref_operand(msg.into())?;
let msg = Symbol::intern(self.read_str(msg_place)?);
let file_place = self.ref_to_mplace(self.read_immediate(file.into())?)?;
let file_place = self.deref_operand(file.into())?;
let file = Symbol::intern(self.read_str(file_place)?);
let line = self.read_scalar(line.into())?.to_u32()?;
let col = self.read_scalar(col.into())?.to_u32()?;
Expand Down
28 changes: 10 additions & 18 deletions src/librustc_mir/interpret/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,6 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
/// that is added to the memory so that the work is not done twice.
const STATIC_KIND: Option<Self::MemoryKinds>;

/// As an optimization, you can prevent the pointer tracking hooks from ever being
/// called. You should only do this if you do not care about provenance tracking.
/// This controls the `tag_reference` and `tag_dereference` hooks.
const ENABLE_PTR_TRACKING_HOOKS: bool;

/// Whether to enforce the validity invariant
fn enforce_validity(ecx: &EvalContext<'a, 'mir, 'tcx, Self>) -> bool;

Expand Down Expand Up @@ -181,18 +176,6 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
kind: MemoryKind<Self::MemoryKinds>,
) -> EvalResult<'tcx, Pointer<Self::PointerTag>>;

/// Executed when evaluating the `&` operator: Creating a new reference.
/// This has the chance to adjust the tag. It should not change anything else!
/// `mutability` can be `None` in case a raw ptr is being created.
#[inline]
fn tag_reference(
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
place: MPlaceTy<'tcx, Self::PointerTag>,
_mutability: Option<hir::Mutability>,
) -> EvalResult<'tcx, Scalar<Self::PointerTag>> {
Ok(place.ptr)
}

/// Executed when evaluating the `*` operator: Following a reference.
/// This has the chance to adjust the tag. It should not change anything else!
/// `mutability` can be `None` in case a raw ptr is being dereferenced.
Expand All @@ -205,7 +188,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
Ok(place.ptr)
}

/// Execute a validation operation
/// Execute a retagging operation
#[inline]
fn retag(
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
Expand All @@ -214,4 +197,13 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
) -> EvalResult<'tcx> {
Ok(())
}

/// Execute an escape-to-raw operation
#[inline]
fn escape_to_raw(
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
_ptr: OpTy<'tcx, Self::PointerTag>,
) -> EvalResult<'tcx> {
Ok(())
}
}
11 changes: 0 additions & 11 deletions src/librustc_mir/interpret/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,17 +431,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
})
}

// Take an operand, representing a pointer, and dereference it to a place -- that
// will always be a MemPlace.
pub(super) fn deref_operand(
&self,
src: OpTy<'tcx, M::PointerTag>,
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
let val = self.read_immediate(src)?;
trace!("deref to {} on {:?}", val.layout.ty, *val);
Ok(self.ref_to_mplace(val)?)
}

pub fn operand_projection(
&self,
base: OpTy<'tcx, M::PointerTag>,
Expand Down
Loading

0 comments on commit 4ec0ba9

Please sign in to comment.