@@ -8,7 +8,7 @@ use rustc::hir::{Mutability, MutMutable, MutImmutable};
88use crate :: {
99 EvalResult , EvalErrorKind , MiriEvalContext , HelpersEvalContextExt , Evaluator , MutValueVisitor ,
1010 MemoryKind , MiriMemoryKind , RangeMap , AllocId , Allocation , AllocationExtra ,
11- Pointer , MemPlace , Scalar , Immediate , ImmTy , PlaceTy , MPlaceTy ,
11+ Pointer , Immediate , ImmTy , PlaceTy , MPlaceTy ,
1212} ;
1313
1414pub type Timestamp = u64 ;
@@ -534,19 +534,21 @@ pub trait EvalContextExt<'tcx> {
534534 size : Size ,
535535 fn_barrier : bool ,
536536 new_bor : Borrow
537- ) -> EvalResult < ' tcx , Pointer < Borrow > > ;
537+ ) -> EvalResult < ' tcx > ;
538538
539539 /// Retag an indidual pointer, returning the retagged version.
540540 fn retag_reference (
541541 & mut self ,
542542 ptr : ImmTy < ' tcx , Borrow > ,
543543 mutbl : Mutability ,
544544 fn_barrier : bool ,
545+ two_phase : bool ,
545546 ) -> EvalResult < ' tcx , Immediate < Borrow > > ;
546547
547548 fn retag (
548549 & mut self ,
549550 fn_entry : bool ,
551+ two_phase : bool ,
550552 place : PlaceTy < ' tcx , Borrow >
551553 ) -> EvalResult < ' tcx > ;
552554
@@ -644,9 +646,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
644646 size : Size ,
645647 fn_barrier : bool ,
646648 new_bor : Borrow
647- ) -> EvalResult < ' tcx , Pointer < Borrow > > {
649+ ) -> EvalResult < ' tcx > {
648650 let ptr = place. ptr . to_ptr ( ) ?;
649- let new_ptr = Pointer :: new_with_tag ( ptr. alloc_id , ptr. offset , new_bor) ;
650651 let barrier = if fn_barrier { Some ( self . frame ( ) . extra ) } else { None } ;
651652 trace ! ( "reborrow: Creating new reference for {:?} (pointee {}): {:?}" ,
652653 ptr, place. layout. ty, new_bor) ;
@@ -666,14 +667,15 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
666667 let kind = if new_bor. is_unique ( ) { RefKind :: Unique } else { RefKind :: Raw } ;
667668 alloc. extra . reborrow ( ptr, size, barrier, new_bor, kind) ?;
668669 }
669- Ok ( new_ptr )
670+ Ok ( ( ) )
670671 }
671672
672673 fn retag_reference (
673674 & mut self ,
674675 val : ImmTy < ' tcx , Borrow > ,
675676 mutbl : Mutability ,
676677 fn_barrier : bool ,
678+ two_phase : bool ,
677679 ) -> EvalResult < ' tcx , Immediate < Borrow > > {
678680 // We want a place for where the ptr *points to*, so we get one.
679681 let place = self . ref_to_mplace ( val) ?;
@@ -693,16 +695,24 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
693695 } ;
694696
695697 // Reborrow.
696- let new_ptr = self . reborrow ( place, size, fn_barrier, new_bor) ?;
698+ self . reborrow ( place, size, fn_barrier, new_bor) ?;
699+ let new_place = place. with_tag ( new_bor) ;
700+ // Handle two-phase borrows.
701+ if two_phase {
702+ // We immediately share it, to allow read accesses
703+ let two_phase_time = self . machine . stacked_borrows . increment_clock ( ) ;
704+ let two_phase_bor = Borrow :: Shr ( Some ( two_phase_time) ) ;
705+ self . reborrow ( new_place, size, /*fn_barrier*/ false , two_phase_bor) ?;
706+ }
697707
698- // Return new ptr
699- let new_place = MemPlace { ptr : Scalar :: Ptr ( new_ptr) , ..* place } ;
708+ // Return new ptr.
700709 Ok ( new_place. to_ref ( ) )
701710 }
702711
703712 fn retag (
704713 & mut self ,
705714 fn_entry : bool ,
715+ two_phase : bool ,
706716 place : PlaceTy < ' tcx , Borrow >
707717 ) -> EvalResult < ' tcx > {
708718 // Determine mutability and whether to add a barrier.
@@ -725,19 +735,20 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
725735 if let Some ( ( mutbl, barrier) ) = qualify ( place. layout . ty , fn_entry) {
726736 // fast path
727737 let val = self . read_immediate ( self . place_to_op ( place) ?) ?;
728- let val = self . retag_reference ( val, mutbl, barrier) ?;
738+ let val = self . retag_reference ( val, mutbl, barrier, two_phase ) ?;
729739 self . write_immediate ( val, place) ?;
730740 return Ok ( ( ) ) ;
731741 }
732742 let place = self . force_allocation ( place) ?;
733743
734- let mut visitor = RetagVisitor { ecx : self , fn_entry } ;
744+ let mut visitor = RetagVisitor { ecx : self , fn_entry, two_phase } ;
735745 visitor. visit_value ( place) ?;
736746
737747 // The actual visitor
738748 struct RetagVisitor < ' ecx , ' a , ' mir , ' tcx > {
739749 ecx : & ' ecx mut MiriEvalContext < ' a , ' mir , ' tcx > ,
740750 fn_entry : bool ,
751+ two_phase : bool ,
741752 }
742753 impl < ' ecx , ' a , ' mir , ' tcx >
743754 MutValueVisitor < ' a , ' mir , ' tcx , Evaluator < ' tcx > >
@@ -758,7 +769,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
758769 // making it useless.
759770 if let Some ( ( mutbl, barrier) ) = qualify ( place. layout . ty , self . fn_entry ) {
760771 let val = self . ecx . read_immediate ( place. into ( ) ) ?;
761- let val = self . ecx . retag_reference ( val, mutbl, barrier) ?;
772+ let val = self . ecx . retag_reference ( val, mutbl, barrier, self . two_phase ) ?;
762773 self . ecx . write_immediate ( val, place. into ( ) ) ?;
763774 }
764775 Ok ( ( ) )
0 commit comments