@@ -6,7 +6,7 @@ use rustc::hir;
6
6
use crate :: {
7
7
EvalResult , MiriEvalContext , HelpersEvalContextExt ,
8
8
MemoryKind , MiriMemoryKind , RangeMap , AllocId , Allocation , AllocationExtra ,
9
- Pointer , PlaceTy , MPlaceTy ,
9
+ Pointer , MemPlace , Scalar , Immediate , ImmTy , PlaceTy , MPlaceTy ,
10
10
} ;
11
11
12
12
pub type Timestamp = u64 ;
@@ -395,13 +395,6 @@ impl<'tcx> Stacks {
395
395
396
396
397
397
pub trait EvalContextExt < ' tcx > {
398
- fn tag_reference (
399
- & mut self ,
400
- place : MPlaceTy < ' tcx , Borrow > ,
401
- size : Size ,
402
- usage : UsageKind ,
403
- ) -> EvalResult < ' tcx , Borrow > ;
404
-
405
398
fn tag_dereference (
406
399
& self ,
407
400
place : MPlaceTy < ' tcx , Borrow > ,
@@ -415,47 +408,27 @@ pub trait EvalContextExt<'tcx> {
415
408
kind : MemoryKind < MiriMemoryKind > ,
416
409
) -> Borrow ;
417
410
411
+ /// Retag an indidual pointer, returning the retagged version.
412
+ fn retag_ptr (
413
+ & mut self ,
414
+ ptr : ImmTy < ' tcx , Borrow > ,
415
+ mutbl : hir:: Mutability ,
416
+ ) -> EvalResult < ' tcx , Immediate < Borrow > > ;
417
+
418
418
fn retag (
419
419
& mut self ,
420
420
fn_entry : bool ,
421
421
place : PlaceTy < ' tcx , Borrow >
422
422
) -> EvalResult < ' tcx > ;
423
- }
424
423
425
- impl < ' a , ' mir , ' tcx > EvalContextExt < ' tcx > for MiriEvalContext < ' a , ' mir , ' tcx > {
426
- /// Called for place-to-value conversion.
427
- fn tag_reference (
424
+ fn escape_to_raw (
428
425
& mut self ,
429
426
place : MPlaceTy < ' tcx , Borrow > ,
430
427
size : Size ,
431
- usage : UsageKind ,
432
- ) -> EvalResult < ' tcx , Borrow > {
433
- let ptr = place. ptr . to_ptr ( ) ?;
434
- let time = self . machine . stacked_borrows . increment_clock ( ) ;
435
- let new_bor = match usage {
436
- UsageKind :: Write => Borrow :: Uniq ( time) ,
437
- UsageKind :: Read => Borrow :: Shr ( Some ( time) ) ,
438
- UsageKind :: Raw => Borrow :: Shr ( None ) ,
439
- } ;
440
- trace ! ( "tag_reference: Creating new reference ({:?}) for {:?} (pointee {}): {:?}" ,
441
- usage, ptr, place. layout. ty, new_bor) ;
442
-
443
- // Update the stacks. First create the new ref as usual, then maybe freeze stuff.
444
- self . memory ( ) . check_bounds ( ptr, size, false ) ?;
445
- let alloc = self . memory ( ) . get ( ptr. alloc_id ) . expect ( "We checked that the ptr is fine!" ) ;
446
- alloc. extra . use_and_maybe_re_borrow ( ptr, size, usage, Some ( new_bor) ) ?;
447
- // Maybe freeze stuff
448
- if let Borrow :: Shr ( Some ( bor_t) ) = new_bor {
449
- self . visit_frozen ( place, size, |frz_ptr, size| {
450
- debug_assert_eq ! ( frz_ptr. alloc_id, ptr. alloc_id) ;
451
- // Be frozen!
452
- alloc. extra . freeze ( frz_ptr, size, bor_t)
453
- } ) ?;
454
- }
455
-
456
- Ok ( new_bor)
457
- }
428
+ ) -> EvalResult < ' tcx > ;
429
+ }
458
430
431
+ impl < ' a , ' mir , ' tcx > EvalContextExt < ' tcx > for MiriEvalContext < ' a , ' mir , ' tcx > {
459
432
/// Called for value-to-place conversion.
460
433
///
461
434
/// Note that this does NOT mean that all this memory will actually get accessed/referenced!
@@ -466,9 +439,9 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
466
439
size : Size ,
467
440
usage : UsageKind ,
468
441
) -> EvalResult < ' tcx , Borrow > {
469
- let ptr = place. ptr . to_ptr ( ) ?;
470
442
trace ! ( "tag_dereference: Accessing reference ({:?}) for {:?} (pointee {})" ,
471
- usage, ptr, place. layout. ty) ;
443
+ usage, place. ptr, place. layout. ty) ;
444
+ let ptr = place. ptr . to_ptr ( ) ?;
472
445
// In principle we should not have to do anything here. However, with transmutes involved,
473
446
// it can happen that the tag of `ptr` does not actually match `usage`, and we
474
447
// should adjust for that.
@@ -551,27 +524,81 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
551
524
Borrow :: Uniq ( time)
552
525
}
553
526
527
+ fn retag_ptr (
528
+ & mut self ,
529
+ val : ImmTy < ' tcx , Borrow > ,
530
+ mutbl : hir:: Mutability ,
531
+ ) -> EvalResult < ' tcx , Immediate < Borrow > > {
532
+ // We want a place for where the ptr *points to*, so we get one.
533
+ let place = self . ref_to_mplace ( val) ?;
534
+ let size = self . size_and_align_of_mplace ( place) ?
535
+ . map ( |( size, _) | size)
536
+ . unwrap_or_else ( || place. layout . size ) ;
537
+ if size == Size :: ZERO {
538
+ // Nothing to do for ZSTs.
539
+ return Ok ( * val) ;
540
+ }
541
+
542
+ // Prepare to re-borrow this place.
543
+ let ptr = place. ptr . to_ptr ( ) ?;
544
+ let time = self . machine . stacked_borrows . increment_clock ( ) ;
545
+ let new_bor = match mutbl {
546
+ hir:: MutMutable => Borrow :: Uniq ( time) ,
547
+ hir:: MutImmutable => Borrow :: Shr ( Some ( time) ) ,
548
+ } ;
549
+ trace ! ( "retag: Creating new reference ({:?}) for {:?} (pointee {}): {:?}" ,
550
+ mutbl, ptr, place. layout. ty, new_bor) ;
551
+
552
+ // Update the stacks. First create a new borrow, then maybe freeze stuff.
553
+ self . memory ( ) . check_bounds ( ptr, size, false ) ?; // `ptr_dereference` wouldn't do any checks if this is a raw ptr
554
+ let alloc = self . memory ( ) . get ( ptr. alloc_id ) . expect ( "We checked that the ptr is fine!" ) ;
555
+ alloc. extra . use_and_maybe_re_borrow ( ptr, size, Some ( mutbl) . into ( ) , Some ( new_bor) ) ?;
556
+ // Maybe freeze stuff
557
+ if let Borrow :: Shr ( Some ( bor_t) ) = new_bor {
558
+ self . visit_frozen ( place, size, |frz_ptr, size| {
559
+ debug_assert_eq ! ( frz_ptr. alloc_id, ptr. alloc_id) ;
560
+ // Be frozen!
561
+ alloc. extra . freeze ( frz_ptr, size, bor_t)
562
+ } ) ?;
563
+ }
564
+
565
+ // Compute the new value and return that
566
+ let new_ptr = Scalar :: Ptr ( Pointer :: new_with_tag ( ptr. alloc_id , ptr. offset , new_bor) ) ;
567
+ let new_place = MemPlace { ptr : new_ptr, ..* place } ;
568
+ Ok ( new_place. to_ref ( ) )
569
+ }
570
+
554
571
fn retag (
555
572
& mut self ,
556
573
_fn_entry : bool ,
557
574
place : PlaceTy < ' tcx , Borrow >
558
575
) -> EvalResult < ' tcx > {
559
576
// For now, we only retag if the toplevel type is a reference.
560
577
// TODO: Recurse into structs and enums, sharing code with validation.
578
+ // TODO: Honor `fn_entry`.
561
579
let mutbl = match place. layout . ty . sty {
562
580
ty:: Ref ( _, _, mutbl) => mutbl, // go ahead
563
- _ => return Ok ( ( ) ) , // don't do a thing
581
+ _ => return Ok ( ( ) ) , // do nothing, for now
564
582
} ;
565
- // We want to reborrow the reference stored there. This will call the hooks
566
- // above. First deref, which will call `tag_dereference`.
567
- // (This is somewhat redundant because validation already did the same thing,
568
- // but what can you do.)
583
+ // Retag the pointer and write it back.
569
584
let val = self . read_immediate ( self . place_to_op ( place) ?) ?;
570
- let dest = self . ref_to_mplace ( val) ?;
571
- // Now put a new ref into the old place, which will call `tag_reference`.
572
- // FIXME: Honor `fn_entry`!
573
- let val = self . create_ref ( dest, Some ( mutbl) ) ?;
585
+ let val = self . retag_ptr ( val, mutbl) ?;
574
586
self . write_immediate ( val, place) ?;
575
587
Ok ( ( ) )
576
588
}
589
+
590
+ fn escape_to_raw (
591
+ & mut self ,
592
+ place : MPlaceTy < ' tcx , Borrow > ,
593
+ size : Size ,
594
+ ) -> EvalResult < ' tcx > {
595
+ trace ! ( "self: {:?} is now accessible by raw pointers" , * place) ;
596
+ // Re-borrow to raw. This is a NOP for shared borrows, but we do not know the borrow
597
+ // type here and that's also okay.
598
+ let ptr = place. ptr . to_ptr ( ) ?;
599
+ self . memory ( ) . check_bounds ( ptr, size, false ) ?; // `ptr_dereference` wouldn't do any checks if this is a raw ptr
600
+ let alloc = self . memory ( ) . get ( ptr. alloc_id ) . expect ( "We checked that the ptr is fine!" ) ;
601
+ alloc. extra . use_and_maybe_re_borrow ( ptr, size, UsageKind :: Raw , Some ( Borrow :: default ( ) ) ) ?;
602
+ Ok ( ( ) )
603
+ }
577
604
}
0 commit comments