Skip to content

Commit 55ce55d

Browse files
committed
switch intptrcast to helper trait pattern like everything else
1 parent f386329 commit 55ce55d

File tree

3 files changed

+87
-88
lines changed

3 files changed

+87
-88
lines changed

src/tools/miri/src/intptrcast.rs

Lines changed: 82 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,21 @@ impl GlobalStateInner {
6262
}
6363
}
6464

65-
impl<'mir, 'tcx> GlobalStateInner {
65+
/// Shifts `addr` to make it aligned with `align` by rounding `addr` to the smallest multiple
66+
/// of `align` that is larger or equal to `addr`
67+
fn align_addr(addr: u64, align: u64) -> u64 {
68+
match addr % align {
69+
0 => addr,
70+
rem => addr.checked_add(align).unwrap() - rem,
71+
}
72+
}
73+
74+
impl<'mir, 'tcx: 'mir> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
75+
trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
6676
// Returns the exposed `AllocId` that corresponds to the specified addr,
6777
// or `None` if the addr is out of bounds
68-
fn alloc_id_from_addr(ecx: &MiriInterpCx<'mir, 'tcx>, addr: u64) -> Option<AllocId> {
78+
fn alloc_id_from_addr(&self, addr: u64) -> Option<AllocId> {
79+
let ecx = self.eval_context_ref();
6980
let global_state = ecx.machine.intptrcast.borrow();
7081
assert!(global_state.provenance_mode != ProvenanceMode::Strict);
7182

@@ -105,65 +116,8 @@ impl<'mir, 'tcx> GlobalStateInner {
105116
None
106117
}
107118

108-
pub fn expose_ptr(
109-
ecx: &mut MiriInterpCx<'mir, 'tcx>,
110-
alloc_id: AllocId,
111-
tag: BorTag,
112-
) -> InterpResult<'tcx> {
113-
let global_state = ecx.machine.intptrcast.get_mut();
114-
// In strict mode, we don't need this, so we can save some cycles by not tracking it.
115-
if global_state.provenance_mode != ProvenanceMode::Strict {
116-
trace!("Exposing allocation id {alloc_id:?}");
117-
global_state.exposed.insert(alloc_id);
118-
if ecx.machine.borrow_tracker.is_some() {
119-
ecx.expose_tag(alloc_id, tag)?;
120-
}
121-
}
122-
Ok(())
123-
}
124-
125-
pub fn ptr_from_addr_cast(
126-
ecx: &MiriInterpCx<'mir, 'tcx>,
127-
addr: u64,
128-
) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
129-
trace!("Casting {:#x} to a pointer", addr);
130-
131-
// Potentially emit a warning.
132-
let global_state = ecx.machine.intptrcast.borrow();
133-
match global_state.provenance_mode {
134-
ProvenanceMode::Default => {
135-
// The first time this happens at a particular location, print a warning.
136-
thread_local! {
137-
// `Span` is non-`Send`, so we use a thread-local instead.
138-
static PAST_WARNINGS: RefCell<FxHashSet<Span>> = RefCell::default();
139-
}
140-
PAST_WARNINGS.with_borrow_mut(|past_warnings| {
141-
let first = past_warnings.is_empty();
142-
if past_warnings.insert(ecx.cur_span()) {
143-
// Newly inserted, so first time we see this span.
144-
ecx.emit_diagnostic(NonHaltingDiagnostic::Int2Ptr { details: first });
145-
}
146-
});
147-
}
148-
ProvenanceMode::Strict => {
149-
throw_machine_stop!(TerminationInfo::Int2PtrWithStrictProvenance);
150-
}
151-
ProvenanceMode::Permissive => {}
152-
}
153-
154-
// We do *not* look up the `AllocId` here! This is a `ptr as usize` cast, and it is
155-
// completely legal to do a cast and then `wrapping_offset` to another allocation and only
156-
// *then* do a memory access. So the allocation that the pointer happens to point to on a
157-
// cast is fairly irrelevant. Instead we generate this as a "wildcard" pointer, such that
158-
// *every time the pointer is used*, we do an `AllocId` lookup to find the (exposed)
159-
// allocation it might be referencing.
160-
Ok(Pointer::new(Some(Provenance::Wildcard), Size::from_bytes(addr)))
161-
}
162-
163-
fn alloc_base_addr(
164-
ecx: &MiriInterpCx<'mir, 'tcx>,
165-
alloc_id: AllocId,
166-
) -> InterpResult<'tcx, u64> {
119+
fn addr_from_alloc_id(&self, alloc_id: AllocId) -> InterpResult<'tcx, u64> {
120+
let ecx = self.eval_context_ref();
167121
let mut global_state = ecx.machine.intptrcast.borrow_mut();
168122
let global_state = &mut *global_state;
169123

@@ -186,7 +140,7 @@ impl<'mir, 'tcx> GlobalStateInner {
186140
.next_base_addr
187141
.checked_add(slack)
188142
.ok_or_else(|| err_exhaust!(AddressSpaceFull))?;
189-
let base_addr = Self::align_addr(base_addr, align.bytes());
143+
let base_addr = align_addr(base_addr, align.bytes());
190144
entry.insert(base_addr);
191145
trace!(
192146
"Assigning base address {:#x} to allocation {:?} (size: {}, align: {}, slack: {})",
@@ -216,15 +170,71 @@ impl<'mir, 'tcx> GlobalStateInner {
216170
}
217171
})
218172
}
173+
}
174+
175+
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
176+
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
177+
fn expose_ptr(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> {
178+
let ecx = self.eval_context_mut();
179+
let global_state = ecx.machine.intptrcast.get_mut();
180+
// In strict mode, we don't need this, so we can save some cycles by not tracking it.
181+
if global_state.provenance_mode != ProvenanceMode::Strict {
182+
trace!("Exposing allocation id {alloc_id:?}");
183+
global_state.exposed.insert(alloc_id);
184+
if ecx.machine.borrow_tracker.is_some() {
185+
ecx.expose_tag(alloc_id, tag)?;
186+
}
187+
}
188+
Ok(())
189+
}
190+
191+
fn ptr_from_addr_cast(&self, addr: u64) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
192+
trace!("Casting {:#x} to a pointer", addr);
193+
194+
let ecx = self.eval_context_ref();
195+
let global_state = ecx.machine.intptrcast.borrow();
196+
197+
// Potentially emit a warning.
198+
match global_state.provenance_mode {
199+
ProvenanceMode::Default => {
200+
// The first time this happens at a particular location, print a warning.
201+
thread_local! {
202+
// `Span` is non-`Send`, so we use a thread-local instead.
203+
static PAST_WARNINGS: RefCell<FxHashSet<Span>> = RefCell::default();
204+
}
205+
PAST_WARNINGS.with_borrow_mut(|past_warnings| {
206+
let first = past_warnings.is_empty();
207+
if past_warnings.insert(ecx.cur_span()) {
208+
// Newly inserted, so first time we see this span.
209+
ecx.emit_diagnostic(NonHaltingDiagnostic::Int2Ptr { details: first });
210+
}
211+
});
212+
}
213+
ProvenanceMode::Strict => {
214+
throw_machine_stop!(TerminationInfo::Int2PtrWithStrictProvenance);
215+
}
216+
ProvenanceMode::Permissive => {}
217+
}
218+
219+
// We do *not* look up the `AllocId` here! This is a `ptr as usize` cast, and it is
220+
// completely legal to do a cast and then `wrapping_offset` to another allocation and only
221+
// *then* do a memory access. So the allocation that the pointer happens to point to on a
222+
// cast is fairly irrelevant. Instead we generate this as a "wildcard" pointer, such that
223+
// *every time the pointer is used*, we do an `AllocId` lookup to find the (exposed)
224+
// allocation it might be referencing.
225+
Ok(Pointer::new(Some(Provenance::Wildcard), Size::from_bytes(addr)))
226+
}
219227

220228
/// Convert a relative (tcx) pointer to a Miri pointer.
221-
pub fn ptr_from_rel_ptr(
222-
ecx: &MiriInterpCx<'mir, 'tcx>,
229+
fn ptr_from_rel_ptr(
230+
&self,
223231
ptr: Pointer<AllocId>,
224232
tag: BorTag,
225233
) -> InterpResult<'tcx, Pointer<Provenance>> {
234+
let ecx = self.eval_context_ref();
235+
226236
let (alloc_id, offset) = ptr.into_parts(); // offset is relative (AllocId provenance)
227-
let base_addr = GlobalStateInner::alloc_base_addr(ecx, alloc_id)?;
237+
let base_addr = ecx.addr_from_alloc_id(alloc_id)?;
228238

229239
// Add offset with the right kind of pointer-overflowing arithmetic.
230240
let dl = ecx.data_layout();
@@ -234,22 +244,21 @@ impl<'mir, 'tcx> GlobalStateInner {
234244

235245
/// When a pointer is used for a memory access, this computes where in which allocation the
236246
/// access is going.
237-
pub fn ptr_get_alloc(
238-
ecx: &MiriInterpCx<'mir, 'tcx>,
239-
ptr: Pointer<Provenance>,
240-
) -> Option<(AllocId, Size)> {
247+
fn ptr_get_alloc(&self, ptr: Pointer<Provenance>) -> Option<(AllocId, Size)> {
248+
let ecx = self.eval_context_ref();
249+
241250
let (tag, addr) = ptr.into_parts(); // addr is absolute (Tag provenance)
242251

243252
let alloc_id = if let Provenance::Concrete { alloc_id, .. } = tag {
244253
alloc_id
245254
} else {
246255
// A wildcard pointer.
247-
GlobalStateInner::alloc_id_from_addr(ecx, addr.bytes())?
256+
ecx.alloc_id_from_addr(addr.bytes())?
248257
};
249258

250259
// This cannot fail: since we already have a pointer with that provenance, rel_ptr_to_addr
251260
// must have been called in the past.
252-
let base_addr = GlobalStateInner::alloc_base_addr(ecx, alloc_id).unwrap();
261+
let base_addr = ecx.addr_from_alloc_id(alloc_id).unwrap();
253262

254263
// Wrapping "addr - base_addr"
255264
#[allow(clippy::cast_possible_wrap)] // we want to wrap here
@@ -259,15 +268,6 @@ impl<'mir, 'tcx> GlobalStateInner {
259268
Size::from_bytes(ecx.overflowing_signed_offset(addr.bytes(), neg_base_addr).0),
260269
))
261270
}
262-
263-
/// Shifts `addr` to make it aligned with `align` by rounding `addr` to the smallest multiple
264-
/// of `align` that is larger or equal to `addr`
265-
fn align_addr(addr: u64, align: u64) -> u64 {
266-
match addr % align {
267-
0 => addr,
268-
rem => addr.checked_add(align).unwrap() - rem,
269-
}
270-
}
271271
}
272272

273273
#[cfg(test)]
@@ -276,7 +276,7 @@ mod tests {
276276

277277
#[test]
278278
fn test_align_addr() {
279-
assert_eq!(GlobalStateInner::align_addr(37, 4), 40);
280-
assert_eq!(GlobalStateInner::align_addr(44, 4), 44);
279+
assert_eq!(align_addr(37, 4), 40);
280+
assert_eq!(align_addr(44, 4), 44);
281281
}
282282
}

src/tools/miri/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ pub use crate::eval::{
117117
create_ecx, eval_entry, AlignmentCheck, BacktraceStyle, IsolatedOp, MiriConfig, RejectOpWith,
118118
};
119119
pub use crate::helpers::EvalContextExt as _;
120-
pub use crate::intptrcast::ProvenanceMode;
120+
pub use crate::intptrcast::{EvalContextExt as _, ProvenanceMode};
121121
pub use crate::machine::{
122122
AllocExtra, FrameExtra, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind,
123123
PrimitiveLayouts, Provenance, ProvenanceExtra,

src/tools/miri/src/machine.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,7 +1149,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
11491149
// Value does not matter, SB is disabled
11501150
BorTag::default()
11511151
};
1152-
intptrcast::GlobalStateInner::ptr_from_rel_ptr(ecx, ptr, tag)
1152+
ecx.ptr_from_rel_ptr(ptr, tag)
11531153
}
11541154

11551155
/// Called on `usize as ptr` casts.
@@ -1158,7 +1158,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
11581158
ecx: &MiriInterpCx<'mir, 'tcx>,
11591159
addr: u64,
11601160
) -> InterpResult<'tcx, Pointer<Option<Self::Provenance>>> {
1161-
intptrcast::GlobalStateInner::ptr_from_addr_cast(ecx, addr)
1161+
ecx.ptr_from_addr_cast(addr)
11621162
}
11631163

11641164
/// Called on `ptr as usize` casts.
@@ -1169,8 +1169,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
11691169
ptr: Pointer<Self::Provenance>,
11701170
) -> InterpResult<'tcx> {
11711171
match ptr.provenance {
1172-
Provenance::Concrete { alloc_id, tag } =>
1173-
intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag),
1172+
Provenance::Concrete { alloc_id, tag } => ecx.expose_ptr(alloc_id, tag),
11741173
Provenance::Wildcard => {
11751174
// No need to do anything for wildcard pointers as
11761175
// their provenances have already been previously exposed.
@@ -1191,7 +1190,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
11911190
ecx: &MiriInterpCx<'mir, 'tcx>,
11921191
ptr: Pointer<Self::Provenance>,
11931192
) -> Option<(AllocId, Size, Self::ProvenanceExtra)> {
1194-
let rel = intptrcast::GlobalStateInner::ptr_get_alloc(ecx, ptr);
1193+
let rel = ecx.ptr_get_alloc(ptr);
11951194

11961195
rel.map(|(alloc_id, size)| {
11971196
let tag = match ptr.provenance {

0 commit comments

Comments
 (0)