@@ -6,6 +6,7 @@ use std::{fmt, iter, mem, ptr};
6
6
use rustc:: hir:: def_id:: DefId ;
7
7
use rustc:: ty:: BareFnTy ;
8
8
use rustc:: ty:: subst:: Substs ;
9
+ use rustc:: ty:: layout:: TargetDataLayout ;
9
10
10
11
use error:: { EvalError , EvalResult } ;
11
12
use primval:: PrimVal ;
@@ -53,7 +54,7 @@ pub struct FunctionDefinition<'tcx> {
53
54
// Top-level interpreter memory
54
55
////////////////////////////////////////////////////////////////////////////////
55
56
56
- pub struct Memory < ' tcx > {
57
+ pub struct Memory < ' a , ' tcx > {
57
58
/// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations)
58
59
alloc_map : HashMap < AllocId , Allocation > ,
59
60
/// Function "allocations". They exist solely so pointers have something to point to, and
@@ -62,18 +63,17 @@ pub struct Memory<'tcx> {
62
63
/// Inverse map of `functions` so we don't allocate a new pointer every time we need one
63
64
function_alloc_cache : HashMap < FunctionDefinition < ' tcx > , AllocId > ,
64
65
next_id : AllocId ,
65
- pub pointer_size : usize ,
66
+ pub layout : & ' a TargetDataLayout ,
66
67
}
67
68
68
- impl < ' tcx > Memory < ' tcx > {
69
- // FIXME: pass tcx.data_layout (This would also allow it to use primitive type alignments to diagnose unaligned memory accesses.)
70
- pub fn new ( pointer_size : usize ) -> Self {
69
+ impl < ' a , ' tcx > Memory < ' a , ' tcx > {
70
+ pub fn new ( layout : & ' a TargetDataLayout ) -> Self {
71
71
Memory {
72
72
alloc_map : HashMap :: new ( ) ,
73
73
functions : HashMap :: new ( ) ,
74
74
function_alloc_cache : HashMap :: new ( ) ,
75
75
next_id : AllocId ( 0 ) ,
76
- pointer_size : pointer_size ,
76
+ layout : layout ,
77
77
}
78
78
}
79
79
@@ -156,10 +156,13 @@ impl<'tcx> Memory<'tcx> {
156
156
Ok ( ( ) )
157
157
}
158
158
159
- ////////////////////////////////////////////////////////////////////////////////
160
- // Allocation accessors
161
- ////////////////////////////////////////////////////////////////////////////////
159
+ pub fn pointer_size ( & self ) -> usize {
160
+ self . layout . pointer_size . bytes ( ) as usize
161
+ }
162
+ }
162
163
164
+ /// Allocation accessors
165
+ impl < ' a , ' tcx > Memory < ' a , ' tcx > {
163
166
pub fn get ( & self , id : AllocId ) -> EvalResult < ' tcx , & Allocation > {
164
167
match self . alloc_map . get ( & id) {
165
168
Some ( alloc) => Ok ( alloc) ,
@@ -235,21 +238,20 @@ impl<'tcx> Memory<'tcx> {
235
238
if !relocations. is_empty ( ) {
236
239
print ! ( "{:1$}" , "" , prefix. len( ) ) ; // Print spaces.
237
240
let mut pos = 0 ;
238
- let relocation_width = ( self . pointer_size - 1 ) * 3 ;
241
+ let relocation_width = ( self . pointer_size ( ) - 1 ) * 3 ;
239
242
for ( i, target_id) in relocations {
240
243
print ! ( "{:1$}" , "" , ( i - pos) * 3 ) ;
241
244
print ! ( "└{0:─^1$}┘ " , format!( "({})" , target_id) , relocation_width) ;
242
- pos = i + self . pointer_size ;
245
+ pos = i + self . pointer_size ( ) ;
243
246
}
244
247
println ! ( "" ) ;
245
248
}
246
249
}
247
250
}
251
+ }
248
252
249
- ////////////////////////////////////////////////////////////////////////////////
250
- // Byte accessors
251
- ////////////////////////////////////////////////////////////////////////////////
252
-
253
+ /// Byte accessors
254
+ impl < ' a , ' tcx > Memory < ' a , ' tcx > {
253
255
fn get_bytes_unchecked ( & self , ptr : Pointer , size : usize ) -> EvalResult < ' tcx , & [ u8 ] > {
254
256
let alloc = self . get ( ptr. alloc_id ) ?;
255
257
if ptr. offset + size > alloc. bytes . len ( ) {
@@ -287,11 +289,10 @@ impl<'tcx> Memory<'tcx> {
287
289
self . mark_definedness ( ptr, size, true ) ?;
288
290
self . get_bytes_unchecked_mut ( ptr, size)
289
291
}
292
+ }
290
293
291
- ////////////////////////////////////////////////////////////////////////////////
292
- // Reading and writing
293
- ////////////////////////////////////////////////////////////////////////////////
294
-
294
+ /// Reading and writing
295
+ impl < ' a , ' tcx > Memory < ' a , ' tcx > {
295
296
pub fn copy ( & mut self , src : Pointer , dest : Pointer , size : usize ) -> EvalResult < ' tcx , ( ) > {
296
297
self . check_relocation_edges ( src, size) ?;
297
298
@@ -336,7 +337,7 @@ impl<'tcx> Memory<'tcx> {
336
337
}
337
338
338
339
pub fn read_ptr ( & self , ptr : Pointer ) -> EvalResult < ' tcx , Pointer > {
339
- let size = self . pointer_size ;
340
+ let size = self . pointer_size ( ) ;
340
341
self . check_defined ( ptr, size) ?;
341
342
let offset = self . get_bytes_unchecked ( ptr, size) ?
342
343
. read_uint :: < NativeEndian > ( size) . unwrap ( ) as usize ;
@@ -349,7 +350,7 @@ impl<'tcx> Memory<'tcx> {
349
350
350
351
pub fn write_ptr ( & mut self , dest : Pointer , ptr : Pointer ) -> EvalResult < ' tcx , ( ) > {
351
352
{
352
- let size = self . pointer_size ;
353
+ let size = self . pointer_size ( ) ;
353
354
let mut bytes = self . get_bytes_mut ( dest, size) ?;
354
355
bytes. write_uint :: < NativeEndian > ( ptr. offset as u64 , size) . unwrap ( ) ;
355
356
}
@@ -358,7 +359,7 @@ impl<'tcx> Memory<'tcx> {
358
359
}
359
360
360
361
pub fn write_primval ( & mut self , ptr : Pointer , val : PrimVal ) -> EvalResult < ' tcx , ( ) > {
361
- let pointer_size = self . pointer_size ;
362
+ let pointer_size = self . pointer_size ( ) ;
362
363
match val {
363
364
PrimVal :: Bool ( b) => self . write_bool ( ptr, b) ,
364
365
PrimVal :: I8 ( n) => self . write_int ( ptr, n as i64 , 1 ) ,
@@ -406,31 +407,30 @@ impl<'tcx> Memory<'tcx> {
406
407
}
407
408
408
409
pub fn read_isize ( & self , ptr : Pointer ) -> EvalResult < ' tcx , i64 > {
409
- self . read_int ( ptr, self . pointer_size )
410
+ self . read_int ( ptr, self . pointer_size ( ) )
410
411
}
411
412
412
413
pub fn write_isize ( & mut self , ptr : Pointer , n : i64 ) -> EvalResult < ' tcx , ( ) > {
413
- let size = self . pointer_size ;
414
+ let size = self . pointer_size ( ) ;
414
415
self . write_int ( ptr, n, size)
415
416
}
416
417
417
418
pub fn read_usize ( & self , ptr : Pointer ) -> EvalResult < ' tcx , u64 > {
418
- self . read_uint ( ptr, self . pointer_size )
419
+ self . read_uint ( ptr, self . pointer_size ( ) )
419
420
}
420
421
421
422
pub fn write_usize ( & mut self , ptr : Pointer , n : u64 ) -> EvalResult < ' tcx , ( ) > {
422
- let size = self . pointer_size ;
423
+ let size = self . pointer_size ( ) ;
423
424
self . write_uint ( ptr, n, size)
424
425
}
426
+ }
425
427
426
- ////////////////////////////////////////////////////////////////////////////////
427
- // Relocations
428
- ////////////////////////////////////////////////////////////////////////////////
429
-
428
+ /// Relocations
429
+ impl < ' a , ' tcx > Memory < ' a , ' tcx > {
430
430
fn relocations ( & self , ptr : Pointer , size : usize )
431
431
-> EvalResult < ' tcx , btree_map:: Range < usize , AllocId > >
432
432
{
433
- let start = ptr. offset . saturating_sub ( self . pointer_size - 1 ) ;
433
+ let start = ptr. offset . saturating_sub ( self . pointer_size ( ) - 1 ) ;
434
434
let end = ptr. offset + size;
435
435
Ok ( self . get ( ptr. alloc_id ) ?. relocations . range ( Included ( & start) , Excluded ( & end) ) )
436
436
}
@@ -444,7 +444,7 @@ impl<'tcx> Memory<'tcx> {
444
444
let start = ptr. offset ;
445
445
let end = start + size;
446
446
let first = * keys. first ( ) . unwrap ( ) ;
447
- let last = * keys. last ( ) . unwrap ( ) + self . pointer_size ;
447
+ let last = * keys. last ( ) . unwrap ( ) + self . pointer_size ( ) ;
448
448
449
449
let alloc = self . get_mut ( ptr. alloc_id ) ?;
450
450
@@ -478,11 +478,10 @@ impl<'tcx> Memory<'tcx> {
478
478
self . get_mut ( dest. alloc_id ) ?. relocations . extend ( relocations) ;
479
479
Ok ( ( ) )
480
480
}
481
+ }
481
482
482
- ////////////////////////////////////////////////////////////////////////////////
483
- // Undefined bytes
484
- ////////////////////////////////////////////////////////////////////////////////
485
-
483
+ /// Undefined bytes
484
+ impl < ' a , ' tcx > Memory < ' a , ' tcx > {
486
485
// FIXME(solson): This is a very naive, slow version.
487
486
fn copy_undef_mask ( & mut self , src : Pointer , dest : Pointer , size : usize ) -> EvalResult < ' tcx , ( ) > {
488
487
// The bits have to be saved locally before writing to dest in case src and dest overlap.
0 commit comments