@@ -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}
0 commit comments