Skip to content

Commit 111ead3

Browse files
committed
retag return places
1 parent 9046749 commit 111ead3

File tree

2 files changed

+43
-5
lines changed

2 files changed

+43
-5
lines changed

src/machine.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -468,11 +468,10 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
468468
kind: mir::RetagKind,
469469
place: PlaceTy<'tcx, Tag>,
470470
) -> InterpResult<'tcx> {
471-
if ecx.memory.extra.stacked_borrows.is_none() {
472-
// No tracking.
473-
Ok(())
474-
} else {
471+
if ecx.memory.extra.stacked_borrows.is_some() {
475472
ecx.retag(kind, place)
473+
} else {
474+
Ok(())
476475
}
477476
}
478477

@@ -489,6 +488,15 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
489488
Ok(frame.with_extra(extra))
490489
}
491490

491+
#[inline(always)]
492+
fn after_stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
493+
if ecx.memory.extra.stacked_borrows.is_some() {
494+
ecx.retag_return_place()
495+
} else {
496+
Ok(())
497+
}
498+
}
499+
492500
#[inline(always)]
493501
fn after_stack_pop(
494502
ecx: &mut InterpCx<'mir, 'tcx, Self>,

src/stacked_borrows.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use log::trace;
1111
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1212
use rustc_middle::mir::RetagKind;
1313
use rustc_middle::ty;
14-
use rustc_target::abi::Size;
14+
use rustc_target::abi::{LayoutOf, Size};
1515
use rustc_hir::Mutability;
1616

1717
use crate::*;
@@ -645,4 +645,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
645645

646646
Ok(())
647647
}
648+
649+
/// After a stack frame got pushed, retag the return place so that we are sure
650+
/// it does not alias with anything.
651+
fn retag_return_place(&mut self) -> InterpResult<'tcx> {
652+
let this = self.eval_context_mut();
653+
let return_place = if let Some(return_place) = this.frame_mut().return_place {
654+
return_place
655+
} else {
656+
// No return place, nothing to do.
657+
return Ok(());
658+
};
659+
if return_place.layout.is_zst() {
660+
// There may not be any memory here, nothing to do.
661+
return Ok(());
662+
}
663+
// We need this to be in-memory to use tagged pointers.
664+
let return_place = this.force_allocation(return_place)?;
665+
666+
// We have to turn the place into a reference to use the existing code.
667+
let ptr_layout = this.layout_of(this.tcx.mk_mut_ptr(return_place.layout.ty))?;
668+
let val = ImmTy::from_immediate(return_place.to_ref(), ptr_layout);
669+
// Reborrow it, then make it back into an `ImmTy`.
670+
let val = this.retag_reference(val, RefKind::Unique { two_phase: false }, /*protector*/ true)?;
671+
let val = ImmTy::from_immediate(val, ptr_layout);
672+
// And use reborrowed pointer for return place.
673+
let return_place = this.ref_to_mplace(val)?;
674+
this.frame_mut().return_place = Some(return_place.into());
675+
676+
Ok(())
677+
}
648678
}

0 commit comments

Comments
 (0)