diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index d90bf1b61a7..a50a9c819f6 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -376,7 +376,7 @@ macro_rules! make_mir_visitor { ref $($mutability)* inputs, asm: _ } => { for output in & $($mutability)* outputs[..] { - self.visit_place(output, PlaceContext::Store, location); + self.visit_place(output, PlaceContext::AsmOutput, location); } for input in & $($mutability)* inputs[..] { self.visit_operand(input, location); @@ -835,6 +835,11 @@ pub enum PlaceContext<'tcx> { // Appears as LHS of an assignment Store, + // Can often be treated as a Store, but needs to be separate because + // ASM is allowed to read outputs as well, so a Store-AsmOutput sequence + // cannot be simplified the way a Store-Store can be. + AsmOutput, + // Dest of a call Call, @@ -910,7 +915,7 @@ impl<'tcx> PlaceContext<'tcx> { /// Returns true if this place context represents a use that potentially changes the value. pub fn is_mutating_use(&self) -> bool { match *self { - PlaceContext::Store | PlaceContext::Call | + PlaceContext::Store | PlaceContext::AsmOutput | PlaceContext::Call | PlaceContext::Borrow { kind: BorrowKind::Mut, .. } | PlaceContext::Projection(Mutability::Mut) | PlaceContext::Drop => true, @@ -932,6 +937,7 @@ impl<'tcx> PlaceContext<'tcx> { PlaceContext::Projection(Mutability::Not) | PlaceContext::Copy | PlaceContext::Move => true, PlaceContext::Borrow { kind: BorrowKind::Mut, .. } | PlaceContext::Store | + PlaceContext::AsmOutput | PlaceContext::Call | PlaceContext::Projection(Mutability::Mut) | PlaceContext::Drop | PlaceContext::StorageLive | PlaceContext::StorageDead | PlaceContext::Validate => false, diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index c61a57cdda0..2504aa5ff37 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -540,6 +540,10 @@ impl<'a, 'b, 'tcx> FindPlaceUses<'a, 'b, 'tcx> { // "deep" does validation go? PlaceContext::Validate => false, + // FIXME: This is here to not change behaviour from before + // AsmOutput existed, but it's not necessarily a pure overwrite. + // so it's possible this should activate the place. + PlaceContext::AsmOutput | // pure overwrites of an place do not activate it. (note // PlaceContext::Call is solely about dest place) PlaceContext::Store | PlaceContext::Call => false, diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 7833f4bbac7..d9ef5235d19 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -173,6 +173,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { ty::TyAdt(adt, _) => { if adt.is_union() { if context == PlaceContext::Store || + context == PlaceContext::AsmOutput || context == PlaceContext::Drop { let elem_ty = match elem { diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 1e5b0bc1392..1545040f2da 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -103,6 +103,7 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> { if *temp == TempState::Undefined { match context { PlaceContext::Store | + PlaceContext::AsmOutput | PlaceContext::Call => { *temp = TempState::Defined { location, diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 45c3fcd8a61..0af08e1bc8a 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -240,6 +240,9 @@ impl<'tcx> Visitor<'tcx> for DefsUsesVisitor { PlaceContext::Store | + // This is potentially both a def and a use... + PlaceContext::AsmOutput | + // We let Call define the result in both the success and // unwind cases. This is not really correct, however it // does not seem to be observable due to the way that we diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs index b5e5dd3b9ce..cfe55aba0d3 100644 --- a/src/librustc_trans/mir/analyze.rs +++ b/src/librustc_trans/mir/analyze.rs @@ -193,6 +193,7 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> { PlaceContext::Inspect | PlaceContext::Store | + PlaceContext::AsmOutput | PlaceContext::Borrow { .. } | PlaceContext::Projection(..) => { self.mark_as_memory(index);