10
10
11
11
//! The virtual memory representation of the MIR interpreter
12
12
13
- use super :: { Pointer , EvalResult , AllocId } ;
13
+ use super :: {
14
+ Pointer , EvalResult , AllocId , ScalarMaybeUndef , write_target_uint, read_target_uint, Scalar ,
15
+ truncate,
16
+ } ;
14
17
15
- use ty:: layout:: { Size , Align } ;
18
+ use ty:: layout:: { self , Size , Align } ;
16
19
use syntax:: ast:: Mutability ;
17
20
use std:: iter;
18
21
use mir;
@@ -88,24 +91,28 @@ impl<'tcx, Tag, Extra> Allocation<Tag, Extra> {
88
91
89
92
/// Reading and writing
90
93
impl < ' tcx , Tag : Copy , Extra : AllocationExtra < Tag > > Allocation < Tag , Extra > {
91
- pub fn read_c_str ( & self , ptr : Pointer < M :: PointerTag > ) -> EvalResult < ' tcx , & [ u8 ] > {
92
- let alloc = self . get ( ptr. alloc_id ) ?;
94
+ pub fn read_c_str (
95
+ & self ,
96
+ cx : & impl HasDataLayout ,
97
+ ptr : Pointer < Tag > ,
98
+ ) -> EvalResult < ' tcx , & [ u8 ] > {
93
99
assert_eq ! ( ptr. offset. bytes( ) as usize as u64 , ptr. offset. bytes( ) ) ;
94
100
let offset = ptr. offset . bytes ( ) as usize ;
95
- match alloc . bytes [ offset..] . iter ( ) . position ( |& c| c == 0 ) {
101
+ match self . bytes [ offset..] . iter ( ) . position ( |& c| c == 0 ) {
96
102
Some ( size) => {
97
103
let p1 = Size :: from_bytes ( ( size + 1 ) as u64 ) ;
98
- self . check_relocations ( ptr, p1) ?;
104
+ self . check_relocations ( cx , ptr, p1) ?;
99
105
self . check_defined ( ptr, p1) ?;
100
- Ok ( & alloc . bytes [ offset..offset + size] )
106
+ Ok ( & self . bytes [ offset..offset + size] )
101
107
}
102
108
None => err ! ( UnterminatedCString ( ptr. erase_tag( ) ) ) ,
103
109
}
104
110
}
105
111
106
112
pub fn check_bytes (
107
113
& self ,
108
- ptr : Scalar < M :: PointerTag > ,
114
+ cx : & impl HasDataLayout ,
115
+ ptr : Pointer < Tag > ,
109
116
size : Size ,
110
117
allow_ptr_and_undef : bool ,
111
118
) -> EvalResult < ' tcx > {
@@ -115,42 +122,54 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
115
122
self . check_align ( ptr, align) ?;
116
123
return Ok ( ( ) ) ;
117
124
}
118
- let ptr = ptr. to_ptr ( ) ?;
119
125
// Check bounds, align and relocations on the edges
120
- self . get_bytes_with_undef_and_ptr ( ptr, size, align) ?;
126
+ self . get_bytes_with_undef_and_ptr ( cx , ptr, size, align) ?;
121
127
// Check undef and ptr
122
128
if !allow_ptr_and_undef {
123
129
self . check_defined ( ptr, size) ?;
124
- self . check_relocations ( ptr, size) ?;
130
+ self . check_relocations ( cx , ptr, size) ?;
125
131
}
126
132
Ok ( ( ) )
127
133
}
128
134
129
- pub fn read_bytes ( & self , ptr : Scalar < M :: PointerTag > , size : Size ) -> EvalResult < ' tcx , & [ u8 ] > {
135
+ pub fn read_bytes (
136
+ & self ,
137
+ cx : & impl HasDataLayout ,
138
+ ptr : Pointer < Tag > ,
139
+ size : Size ,
140
+ ) -> EvalResult < ' tcx , & [ u8 ] > {
130
141
// Empty accesses don't need to be valid pointers, but they should still be non-NULL
131
142
let align = Align :: from_bytes ( 1 ) . unwrap ( ) ;
132
143
if size. bytes ( ) == 0 {
133
144
self . check_align ( ptr, align) ?;
134
145
return Ok ( & [ ] ) ;
135
146
}
136
- self . get_bytes ( ptr. to_ptr ( ) ? , size, align)
147
+ self . get_bytes ( cx , ptr, size, align)
137
148
}
138
149
139
- pub fn write_bytes ( & mut self , ptr : Scalar < M :: PointerTag > , src : & [ u8 ] ) -> EvalResult < ' tcx > {
150
+ pub fn write_bytes (
151
+ & mut self ,
152
+ cx : & impl HasDataLayout ,
153
+ ptr : Pointer < Tag > ,
154
+ src : & [ u8 ] ,
155
+ ) -> EvalResult < ' tcx > {
140
156
// Empty accesses don't need to be valid pointers, but they should still be non-NULL
141
157
let align = Align :: from_bytes ( 1 ) . unwrap ( ) ;
142
158
if src. is_empty ( ) {
143
159
self . check_align ( ptr, align) ?;
144
160
return Ok ( ( ) ) ;
145
161
}
146
- let bytes = self . get_bytes_mut ( ptr. to_ptr ( ) ?, Size :: from_bytes ( src. len ( ) as u64 ) , align) ?;
162
+ let bytes = self . get_bytes_mut (
163
+ cx, ptr, Size :: from_bytes ( src. len ( ) as u64 ) , align,
164
+ ) ?;
147
165
bytes. clone_from_slice ( src) ;
148
166
Ok ( ( ) )
149
167
}
150
168
151
169
pub fn write_repeat (
152
170
& mut self ,
153
- ptr : Scalar < M :: PointerTag > ,
171
+ cx : & impl HasDataLayout ,
172
+ ptr : Pointer < Tag > ,
154
173
val : u8 ,
155
174
count : Size
156
175
) -> EvalResult < ' tcx > {
@@ -160,7 +179,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
160
179
self . check_align ( ptr, align) ?;
161
180
return Ok ( ( ) ) ;
162
181
}
163
- let bytes = self . get_bytes_mut ( ptr. to_ptr ( ) ? , count, align) ?;
182
+ let bytes = self . get_bytes_mut ( cx , ptr, count, align) ?;
164
183
for b in bytes {
165
184
* b = val;
166
185
}
@@ -170,13 +189,14 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
170
189
/// Read a *non-ZST* scalar
171
190
pub fn read_scalar (
172
191
& self ,
173
- ptr : Pointer < M :: PointerTag > ,
192
+ cx : & impl HasDataLayout ,
193
+ ptr : Pointer < Tag > ,
174
194
ptr_align : Align ,
175
195
size : Size
176
- ) -> EvalResult < ' tcx , ScalarMaybeUndef < M :: PointerTag > > {
196
+ ) -> EvalResult < ' tcx , ScalarMaybeUndef < Tag > > {
177
197
// get_bytes_unchecked tests alignment and relocation edges
178
198
let bytes = self . get_bytes_with_undef_and_ptr (
179
- ptr, size, ptr_align. min ( self . int_align ( size) )
199
+ cx , ptr, size, ptr_align. min ( self . int_align ( cx , size) )
180
200
) ?;
181
201
// Undef check happens *after* we established that the alignment is correct.
182
202
// We must not return Ok() for unaligned pointers!
@@ -186,14 +206,13 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
186
206
return Ok ( ScalarMaybeUndef :: Undef ) ;
187
207
}
188
208
// Now we do the actual reading
189
- let bits = read_target_uint ( self . tcx . data_layout . endian , bytes) . unwrap ( ) ;
209
+ let bits = read_target_uint ( cx . data_layout ( ) . endian , bytes) . unwrap ( ) ;
190
210
// See if we got a pointer
191
- if size != self . pointer_size ( ) {
211
+ if size != cx . data_layout ( ) . pointer_size {
192
212
// *Now* better make sure that the inside also is free of relocations.
193
- self . check_relocations ( ptr, size) ?;
213
+ self . check_relocations ( cx , ptr, size) ?;
194
214
} else {
195
- let alloc = self . get ( ptr. alloc_id ) ?;
196
- match alloc. relocations . get ( & ptr. offset ) {
215
+ match self . relocations . get ( & ptr. offset ) {
197
216
Some ( & ( tag, alloc_id) ) => {
198
217
let ptr = Pointer :: new_with_tag ( alloc_id, Size :: from_bytes ( bits as u64 ) , tag) ;
199
218
return Ok ( ScalarMaybeUndef :: Scalar ( ptr. into ( ) ) )
@@ -207,18 +226,20 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
207
226
208
227
pub fn read_ptr_sized (
209
228
& self ,
210
- ptr : Pointer < M :: PointerTag > ,
229
+ cx : & impl HasDataLayout ,
230
+ ptr : Pointer < Tag > ,
211
231
ptr_align : Align
212
- ) -> EvalResult < ' tcx , ScalarMaybeUndef < M :: PointerTag > > {
213
- self . read_scalar ( ptr, ptr_align, self . pointer_size ( ) )
232
+ ) -> EvalResult < ' tcx , ScalarMaybeUndef < Tag > > {
233
+ self . read_scalar ( cx , ptr, ptr_align, cx . data_layout ( ) . pointer_size )
214
234
}
215
235
216
236
/// Write a *non-ZST* scalar
217
237
pub fn write_scalar (
218
238
& mut self ,
219
- ptr : Pointer < M :: PointerTag > ,
239
+ cx : & impl HasDataLayout ,
240
+ ptr : Pointer < Tag > ,
220
241
ptr_align : Align ,
221
- val : ScalarMaybeUndef < M :: PointerTag > ,
242
+ val : ScalarMaybeUndef < Tag > ,
222
243
type_size : Size ,
223
244
) -> EvalResult < ' tcx > {
224
245
let val = match val {
@@ -228,7 +249,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
228
249
229
250
let bytes = match val {
230
251
Scalar :: Ptr ( val) => {
231
- assert_eq ! ( type_size, self . pointer_size ( ) ) ;
252
+ assert_eq ! ( type_size, cx . data_layout ( ) . pointer_size ) ;
232
253
val. offset . bytes ( ) as u128
233
254
}
234
255
@@ -242,15 +263,15 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
242
263
243
264
{
244
265
// get_bytes_mut checks alignment
245
- let endian = self . tcx . data_layout . endian ;
246
- let dst = self . get_bytes_mut ( ptr, type_size, ptr_align) ?;
266
+ let endian = cx . data_layout ( ) . endian ;
267
+ let dst = self . get_bytes_mut ( cx , ptr, type_size, ptr_align) ?;
247
268
write_target_uint ( endian, dst, bytes) . unwrap ( ) ;
248
269
}
249
270
250
271
// See if we have to also write a relocation
251
272
match val {
252
273
Scalar :: Ptr ( val) => {
253
- self . get_mut ( ptr . alloc_id ) ? . relocations . insert (
274
+ self . relocations . insert (
254
275
ptr. offset ,
255
276
( val. tag , val. alloc_id ) ,
256
277
) ;
@@ -263,15 +284,20 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
263
284
264
285
pub fn write_ptr_sized (
265
286
& mut self ,
266
- ptr : Pointer < M :: PointerTag > ,
287
+ cx : & impl HasDataLayout ,
288
+ ptr : Pointer < Tag > ,
267
289
ptr_align : Align ,
268
- val : ScalarMaybeUndef < M :: PointerTag >
290
+ val : ScalarMaybeUndef < Tag >
269
291
) -> EvalResult < ' tcx > {
270
- let ptr_size = self . pointer_size ( ) ;
271
- self . write_scalar ( ptr. into ( ) , ptr_align, val, ptr_size)
292
+ let ptr_size = cx . data_layout ( ) . pointer_size ;
293
+ self . write_scalar ( cx , ptr. into ( ) , ptr_align, val, ptr_size)
272
294
}
273
295
274
- fn int_align ( & self , size : Size ) -> Align {
296
+ fn int_align (
297
+ & self ,
298
+ cx : & impl HasDataLayout ,
299
+ size : Size ,
300
+ ) -> Align {
275
301
// We assume pointer-sized integers have the same alignment as pointers.
276
302
// We also assume signed and unsigned integers of the same size have the same alignment.
277
303
let ity = match size. bytes ( ) {
@@ -282,7 +308,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
282
308
16 => layout:: I128 ,
283
309
_ => bug ! ( "bad integer size: {}" , size. bytes( ) ) ,
284
310
} ;
285
- ity. align ( self ) . abi
311
+ ity. align ( cx ) . abi
286
312
}
287
313
}
288
314
@@ -337,7 +363,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
337
363
/// It is the caller's responsibility to handle undefined and pointer bytes.
338
364
/// However, this still checks that there are no relocations on the *edges*.
339
365
#[ inline]
340
- fn get_bytes_with_undef_and_ptr (
366
+ pub fn get_bytes_with_undef_and_ptr (
341
367
& self ,
342
368
cx : & impl HasDataLayout ,
343
369
ptr : Pointer < Tag > ,
@@ -349,7 +375,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
349
375
350
376
/// Just calling this already marks everything as defined and removes relocations,
351
377
/// so be sure to actually put data there!
352
- fn get_bytes_mut (
378
+ pub fn get_bytes_mut (
353
379
& mut self ,
354
380
cx : & impl HasDataLayout ,
355
381
ptr : Pointer < Tag > ,
@@ -375,7 +401,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
375
401
/// Relocations
376
402
impl < ' tcx , Tag : Copy , Extra > Allocation < Tag , Extra > {
377
403
/// Return all relocations overlapping with the given ptr-offset pair.
378
- fn relocations (
404
+ pub fn relocations (
379
405
& self ,
380
406
cx : & impl HasDataLayout ,
381
407
ptr : Pointer < Tag > ,
0 commit comments