@@ -62,10 +62,21 @@ impl GlobalStateInner {
62
62
}
63
63
}
64
64
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 > {
66
76
// Returns the exposed `AllocId` that corresponds to the specified addr,
67
77
// 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 ( ) ;
69
80
let global_state = ecx. machine . intptrcast . borrow ( ) ;
70
81
assert ! ( global_state. provenance_mode != ProvenanceMode :: Strict ) ;
71
82
@@ -105,65 +116,8 @@ impl<'mir, 'tcx> GlobalStateInner {
105
116
None
106
117
}
107
118
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 ( ) ;
167
121
let mut global_state = ecx. machine . intptrcast . borrow_mut ( ) ;
168
122
let global_state = & mut * global_state;
169
123
@@ -186,7 +140,7 @@ impl<'mir, 'tcx> GlobalStateInner {
186
140
. next_base_addr
187
141
. checked_add ( slack)
188
142
. 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 ( ) ) ;
190
144
entry. insert ( base_addr) ;
191
145
trace ! (
192
146
"Assigning base address {:#x} to allocation {:?} (size: {}, align: {}, slack: {})" ,
@@ -216,15 +170,71 @@ impl<'mir, 'tcx> GlobalStateInner {
216
170
}
217
171
} )
218
172
}
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
+ }
219
227
220
228
/// 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 ,
223
231
ptr : Pointer < AllocId > ,
224
232
tag : BorTag ,
225
233
) -> InterpResult < ' tcx , Pointer < Provenance > > {
234
+ let ecx = self . eval_context_ref ( ) ;
235
+
226
236
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) ?;
228
238
229
239
// Add offset with the right kind of pointer-overflowing arithmetic.
230
240
let dl = ecx. data_layout ( ) ;
@@ -234,22 +244,21 @@ impl<'mir, 'tcx> GlobalStateInner {
234
244
235
245
/// When a pointer is used for a memory access, this computes where in which allocation the
236
246
/// 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
+
241
250
let ( tag, addr) = ptr. into_parts ( ) ; // addr is absolute (Tag provenance)
242
251
243
252
let alloc_id = if let Provenance :: Concrete { alloc_id, .. } = tag {
244
253
alloc_id
245
254
} else {
246
255
// A wildcard pointer.
247
- GlobalStateInner :: alloc_id_from_addr ( ecx , addr. bytes ( ) ) ?
256
+ ecx . alloc_id_from_addr ( addr. bytes ( ) ) ?
248
257
} ;
249
258
250
259
// This cannot fail: since we already have a pointer with that provenance, rel_ptr_to_addr
251
260
// 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 ( ) ;
253
262
254
263
// Wrapping "addr - base_addr"
255
264
#[ allow( clippy:: cast_possible_wrap) ] // we want to wrap here
@@ -259,15 +268,6 @@ impl<'mir, 'tcx> GlobalStateInner {
259
268
Size :: from_bytes ( ecx. overflowing_signed_offset ( addr. bytes ( ) , neg_base_addr) . 0 ) ,
260
269
) )
261
270
}
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
- }
271
271
}
272
272
273
273
#[ cfg( test) ]
@@ -276,7 +276,7 @@ mod tests {
276
276
277
277
#[ test]
278
278
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 ) ;
281
281
}
282
282
}
0 commit comments