@@ -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 ;
@@ -539,19 +539,21 @@ pub trait EvalContextExt<'tcx> {
539539 size : Size ,
540540 fn_barrier : bool ,
541541 new_bor : Borrow
542- ) -> EvalResult < ' tcx , Pointer < Borrow > > ;
542+ ) -> EvalResult < ' tcx > ;
543543
544544 /// Retag an indidual pointer, returning the retagged version.
545545 fn retag_reference (
546546 & mut self ,
547547 ptr : ImmTy < ' tcx , Borrow > ,
548548 mutbl : Mutability ,
549549 fn_barrier : bool ,
550+ two_phase : bool ,
550551 ) -> EvalResult < ' tcx , Immediate < Borrow > > ;
551552
552553 fn retag (
553554 & mut self ,
554555 fn_entry : bool ,
556+ two_phase : bool ,
555557 place : PlaceTy < ' tcx , Borrow >
556558 ) -> EvalResult < ' tcx > ;
557559
@@ -649,9 +651,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
649651 size : Size ,
650652 fn_barrier : bool ,
651653 new_bor : Borrow
652- ) -> EvalResult < ' tcx , Pointer < Borrow > > {
654+ ) -> EvalResult < ' tcx > {
653655 let ptr = place. ptr . to_ptr ( ) ?;
654- let new_ptr = Pointer :: new_with_tag ( ptr. alloc_id , ptr. offset , new_bor) ;
655656 let barrier = if fn_barrier { Some ( self . frame ( ) . extra ) } else { None } ;
656657 trace ! ( "reborrow: Creating new reference for {:?} (pointee {}): {:?}" ,
657658 ptr, place. layout. ty, new_bor) ;
@@ -671,14 +672,15 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
671672 let kind = if new_bor. is_unique ( ) { RefKind :: Unique } else { RefKind :: Raw } ;
672673 alloc. extra . reborrow ( ptr, size, barrier, new_bor, kind) ?;
673674 }
674- Ok ( new_ptr )
675+ Ok ( ( ) )
675676 }
676677
677678 fn retag_reference (
678679 & mut self ,
679680 val : ImmTy < ' tcx , Borrow > ,
680681 mutbl : Mutability ,
681682 fn_barrier : bool ,
683+ two_phase : bool ,
682684 ) -> EvalResult < ' tcx , Immediate < Borrow > > {
683685 // We want a place for where the ptr *points to*, so we get one.
684686 let place = self . ref_to_mplace ( val) ?;
@@ -698,16 +700,25 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
698700 } ;
699701
700702 // Reborrow.
701- let new_ptr = self . reborrow ( place, size, fn_barrier, new_bor) ?;
703+ self . reborrow ( place, size, fn_barrier, new_bor) ?;
704+ let new_place = place. with_tag ( new_bor) ;
705+ // Handle two-phase borrows.
706+ if two_phase {
707+ assert ! ( mutbl == MutMutable , "two-phase shared borrows make no sense" ) ;
708+ // We immediately share it, to allow read accesses
709+ let two_phase_time = self . machine . stacked_borrows . increment_clock ( ) ;
710+ let two_phase_bor = Borrow :: Shr ( Some ( two_phase_time) ) ;
711+ self . reborrow ( new_place, size, /*fn_barrier*/ false , two_phase_bor) ?;
712+ }
702713
703- // Return new ptr
704- let new_place = MemPlace { ptr : Scalar :: Ptr ( new_ptr) , ..* place } ;
714+ // Return new ptr.
705715 Ok ( new_place. to_ref ( ) )
706716 }
707717
708718 fn retag (
709719 & mut self ,
710720 fn_entry : bool ,
721+ two_phase : bool ,
711722 place : PlaceTy < ' tcx , Borrow >
712723 ) -> EvalResult < ' tcx > {
713724 // Determine mutability and whether to add a barrier.
@@ -730,19 +741,20 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
730741 if let Some ( ( mutbl, barrier) ) = qualify ( place. layout . ty , fn_entry) {
731742 // fast path
732743 let val = self . read_immediate ( self . place_to_op ( place) ?) ?;
733- let val = self . retag_reference ( val, mutbl, barrier) ?;
744+ let val = self . retag_reference ( val, mutbl, barrier, two_phase ) ?;
734745 self . write_immediate ( val, place) ?;
735746 return Ok ( ( ) ) ;
736747 }
737748 let place = self . force_allocation ( place) ?;
738749
739- let mut visitor = RetagVisitor { ecx : self , fn_entry } ;
750+ let mut visitor = RetagVisitor { ecx : self , fn_entry, two_phase } ;
740751 visitor. visit_value ( place) ?;
741752
742753 // The actual visitor
743754 struct RetagVisitor < ' ecx , ' a , ' mir , ' tcx > {
744755 ecx : & ' ecx mut MiriEvalContext < ' a , ' mir , ' tcx > ,
745756 fn_entry : bool ,
757+ two_phase : bool ,
746758 }
747759 impl < ' ecx , ' a , ' mir , ' tcx >
748760 MutValueVisitor < ' a , ' mir , ' tcx , Evaluator < ' tcx > >
@@ -763,7 +775,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
763775 // making it useless.
764776 if let Some ( ( mutbl, barrier) ) = qualify ( place. layout . ty , self . fn_entry ) {
765777 let val = self . ecx . read_immediate ( place. into ( ) ) ?;
766- let val = self . ecx . retag_reference ( val, mutbl, barrier) ?;
778+ let val = self . ecx . retag_reference ( val, mutbl, barrier, self . two_phase ) ?;
767779 self . ecx . write_immediate ( val, place. into ( ) ) ?;
768780 }
769781 Ok ( ( ) )
0 commit comments