@@ -51,25 +51,6 @@ impl Pointer {
51
51
offset : 0 ,
52
52
}
53
53
}
54
- pub fn is_aligned_to ( & self , align : usize ) -> bool {
55
- self . offset % align == 0
56
- }
57
- pub fn check_align ( & self , align : usize ) -> EvalResult < ' static , ( ) > {
58
- if self . is_aligned_to ( align) {
59
- Ok ( ( ) )
60
- } else {
61
- let mut best = self . offset ;
62
- let mut i = 1 ;
63
- while best > 0 && ( best & 1 == 0 ) {
64
- best >>= 1 ;
65
- i <<= 1 ;
66
- }
67
- Err ( EvalError :: AlignmentCheckFailed {
68
- required : align,
69
- has : i,
70
- } )
71
- }
72
- }
73
54
}
74
55
75
56
#[ derive( Debug , Copy , Clone , Hash , Eq , PartialEq ) ]
@@ -118,11 +99,11 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
118
99
bytes : Vec :: new ( ) ,
119
100
relocations : BTreeMap :: new ( ) ,
120
101
undef_mask : UndefMask :: new ( 0 ) ,
121
- align : 0 ,
102
+ align : 1 ,
122
103
} ;
123
104
mem. alloc_map . insert ( ZST_ALLOC_ID , alloc) ;
124
105
// check that additional zst allocs work
125
- debug_assert ! ( mem. allocate( 0 , 0 ) . unwrap( ) . points_to_zst( ) ) ;
106
+ debug_assert ! ( mem. allocate( 0 , 1 ) . unwrap( ) . points_to_zst( ) ) ;
126
107
debug_assert ! ( mem. get( ZST_ALLOC_ID ) . is_ok( ) ) ;
127
108
mem
128
109
}
@@ -155,40 +136,38 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
155
136
}
156
137
157
138
pub fn allocate ( & mut self , size : usize , align : usize ) -> EvalResult < ' tcx , Pointer > {
139
+ assert ! ( align != 0 ) ;
158
140
if size == 0 {
159
141
return Ok ( Pointer :: zst_ptr ( ) ) ;
160
142
}
161
- // make sure we can offset the result pointer by the worst possible alignment
162
- // this allows cheaply checking for alignment directly in the pointer
163
- let least_aligned_size = size + align;
164
143
if self . memory_size - self . memory_usage < size {
165
144
return Err ( EvalError :: OutOfMemory {
166
- allocation_size : least_aligned_size ,
145
+ allocation_size : size ,
167
146
memory_size : self . memory_size ,
168
147
memory_usage : self . memory_usage ,
169
148
} ) ;
170
149
}
171
150
self . memory_usage += size;
172
151
let alloc = Allocation {
173
- bytes : vec ! [ 0 ; least_aligned_size ] ,
152
+ bytes : vec ! [ 0 ; size ] ,
174
153
relocations : BTreeMap :: new ( ) ,
175
- undef_mask : UndefMask :: new ( least_aligned_size ) ,
154
+ undef_mask : UndefMask :: new ( size ) ,
176
155
align : align,
177
156
} ;
178
157
let id = self . next_id ;
179
158
self . next_id . 0 += 1 ;
180
159
self . alloc_map . insert ( id, alloc) ;
181
160
Ok ( Pointer {
182
161
alloc_id : id,
183
- // offset by the alignment, so larger accesses will fail
184
- offset : align,
162
+ offset : 0 ,
185
163
} )
186
164
}
187
165
188
166
// TODO(solson): Track which allocations were returned from __rust_allocate and report an error
189
167
// when reallocating/deallocating any others.
190
168
pub fn reallocate ( & mut self , ptr : Pointer , new_size : usize , align : usize ) -> EvalResult < ' tcx , Pointer > {
191
- if ptr. offset != self . get ( ptr. alloc_id ) ?. align {
169
+ // TODO(solson): Report error about non-__rust_allocate'd pointer.
170
+ if ptr. offset != 0 {
192
171
// TODO(solson): Report error about non-__rust_allocate'd pointer.
193
172
return Err ( EvalError :: Unimplemented ( format ! ( "bad pointer offset: {}" , ptr. offset) ) ) ;
194
173
}
@@ -197,27 +176,26 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
197
176
}
198
177
199
178
let size = self . get ( ptr. alloc_id ) ?. bytes . len ( ) ;
200
- let least_aligned_size = new_size + align;
201
179
202
- if least_aligned_size > size {
203
- let amount = least_aligned_size - size;
180
+ if new_size > size {
181
+ let amount = new_size - size;
204
182
self . memory_usage += amount;
205
183
let alloc = self . get_mut ( ptr. alloc_id ) ?;
206
184
alloc. bytes . extend ( iter:: repeat ( 0 ) . take ( amount) ) ;
207
185
alloc. undef_mask . grow ( amount, false ) ;
208
- } else if size > least_aligned_size {
186
+ } else if size > new_size {
209
187
// it's possible to cause miri to use arbitrary amounts of memory that aren't detectable
210
188
// through the memory_usage value, by allocating a lot and reallocating to zero
211
- self . memory_usage -= size - least_aligned_size ;
212
- self . clear_relocations ( ptr. offset ( least_aligned_size as isize ) , size - least_aligned_size ) ?;
189
+ self . memory_usage -= size - new_size ;
190
+ self . clear_relocations ( ptr. offset ( new_size as isize ) , size - new_size ) ?;
213
191
let alloc = self . get_mut ( ptr. alloc_id ) ?;
214
- alloc. bytes . truncate ( least_aligned_size ) ;
215
- alloc. undef_mask . truncate ( least_aligned_size ) ;
192
+ alloc. bytes . truncate ( new_size ) ;
193
+ alloc. undef_mask . truncate ( new_size ) ;
216
194
}
217
195
218
196
Ok ( Pointer {
219
197
alloc_id : ptr. alloc_id ,
220
- offset : align ,
198
+ offset : 0 ,
221
199
} )
222
200
}
223
201
@@ -226,7 +204,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
226
204
if ptr. points_to_zst ( ) {
227
205
return Ok ( ( ) ) ;
228
206
}
229
- if ptr. offset != self . get ( ptr . alloc_id ) ? . align {
207
+ if ptr. offset != 0 {
230
208
// TODO(solson): Report error about non-__rust_allocate'd pointer.
231
209
return Err ( EvalError :: Unimplemented ( format ! ( "bad pointer offset: {}" , ptr. offset) ) ) ;
232
210
}
@@ -251,6 +229,24 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
251
229
pub fn endianess ( & self ) -> layout:: Endian {
252
230
self . layout . endian
253
231
}
232
+
233
+ pub fn check_align ( & self , ptr : Pointer , align : usize ) -> EvalResult < ' tcx , ( ) > {
234
+ let alloc = self . get ( ptr. alloc_id ) ?;
235
+ if alloc. align < align {
236
+ return Err ( EvalError :: AlignmentCheckFailed {
237
+ has : alloc. align ,
238
+ required : align,
239
+ } ) ;
240
+ }
241
+ if ptr. offset % align == 0 {
242
+ Ok ( ( ) )
243
+ } else {
244
+ Err ( EvalError :: AlignmentCheckFailed {
245
+ has : ptr. offset % align,
246
+ required : align,
247
+ } )
248
+ }
249
+ }
254
250
}
255
251
256
252
/// Allocation accessors
@@ -368,15 +364,17 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
368
364
Ok ( & mut alloc. bytes [ ptr. offset ..ptr. offset + size] )
369
365
}
370
366
371
- fn get_bytes ( & self , ptr : Pointer , size : usize ) -> EvalResult < ' tcx , & [ u8 ] > {
367
+ fn get_bytes ( & self , ptr : Pointer , size : usize , align : usize ) -> EvalResult < ' tcx , & [ u8 ] > {
368
+ self . check_align ( ptr, align) ?;
372
369
if self . relocations ( ptr, size) ?. count ( ) != 0 {
373
370
return Err ( EvalError :: ReadPointerAsBytes ) ;
374
371
}
375
372
self . check_defined ( ptr, size) ?;
376
373
self . get_bytes_unchecked ( ptr, size)
377
374
}
378
375
379
- fn get_bytes_mut ( & mut self , ptr : Pointer , size : usize ) -> EvalResult < ' tcx , & mut [ u8 ] > {
376
+ fn get_bytes_mut ( & mut self , ptr : Pointer , size : usize , align : usize ) -> EvalResult < ' tcx , & mut [ u8 ] > {
377
+ self . check_align ( ptr, align) ?;
380
378
self . clear_relocations ( ptr, size) ?;
381
379
self . mark_definedness ( ptr, size, true ) ?;
382
380
self . get_bytes_unchecked_mut ( ptr, size)
@@ -385,11 +383,11 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
385
383
386
384
/// Reading and writing
387
385
impl < ' a , ' tcx > Memory < ' a , ' tcx > {
388
- pub fn copy ( & mut self , src : Pointer , dest : Pointer , size : usize ) -> EvalResult < ' tcx , ( ) > {
386
+ pub fn copy ( & mut self , src : Pointer , dest : Pointer , size : usize , align : usize ) -> EvalResult < ' tcx , ( ) > {
389
387
self . check_relocation_edges ( src, size) ?;
390
388
391
389
let src_bytes = self . get_bytes_unchecked_mut ( src, size) ?. as_mut_ptr ( ) ;
392
- let dest_bytes = self . get_bytes_mut ( dest, size) ?. as_mut_ptr ( ) ;
390
+ let dest_bytes = self . get_bytes_mut ( dest, size, align ) ?. as_mut_ptr ( ) ;
393
391
394
392
// SAFE: The above indexing would have panicked if there weren't at least `size` bytes
395
393
// behind `src` and `dest`. Also, we use the overlapping-safe `ptr::copy` if `src` and
@@ -409,17 +407,17 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
409
407
}
410
408
411
409
pub fn read_bytes ( & self , ptr : Pointer , size : usize ) -> EvalResult < ' tcx , & [ u8 ] > {
412
- self . get_bytes ( ptr, size)
410
+ self . get_bytes ( ptr, size, 1 )
413
411
}
414
412
415
413
pub fn write_bytes ( & mut self , ptr : Pointer , src : & [ u8 ] ) -> EvalResult < ' tcx , ( ) > {
416
- let bytes = self . get_bytes_mut ( ptr, src. len ( ) ) ?;
414
+ let bytes = self . get_bytes_mut ( ptr, src. len ( ) , 1 ) ?;
417
415
bytes. clone_from_slice ( src) ;
418
416
Ok ( ( ) )
419
417
}
420
418
421
419
pub fn write_repeat ( & mut self , ptr : Pointer , val : u8 , count : usize ) -> EvalResult < ' tcx , ( ) > {
422
- let bytes = self . get_bytes_mut ( ptr, count) ?;
420
+ let bytes = self . get_bytes_mut ( ptr, count, 1 ) ?;
423
421
for b in bytes { * b = val; }
424
422
Ok ( ( ) )
425
423
}
@@ -465,8 +463,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
465
463
}
466
464
467
465
pub fn read_bool ( & self , ptr : Pointer ) -> EvalResult < ' tcx , bool > {
468
- ptr. check_align ( self . layout . i1_align . abi ( ) as usize ) ?;
469
- let bytes = self . get_bytes ( ptr, 1 ) ?;
466
+ let bytes = self . get_bytes ( ptr, 1 , self . layout . i1_align . abi ( ) as usize ) ?;
470
467
match bytes[ 0 ] {
471
468
0 => Ok ( false ) ,
472
469
1 => Ok ( true ) ,
@@ -475,42 +472,43 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
475
472
}
476
473
477
474
pub fn write_bool ( & mut self , ptr : Pointer , b : bool ) -> EvalResult < ' tcx , ( ) > {
478
- ptr. check_align ( self . layout . i1_align . abi ( ) as usize ) ?;
479
- self . get_bytes_mut ( ptr, 1 ) . map ( |bytes| bytes[ 0 ] = b as u8 )
475
+ let align = self . layout . i1_align . abi ( ) as usize ;
476
+ self . get_bytes_mut ( ptr, 1 , align)
477
+ . map ( |bytes| bytes[ 0 ] = b as u8 )
480
478
}
481
479
482
- fn check_int_align ( & self , ptr : Pointer , size : usize ) -> EvalResult < ' tcx , ( ) > {
480
+ fn int_align ( & self , size : usize ) -> EvalResult < ' tcx , usize > {
483
481
match size {
484
- 1 => ptr . check_align ( self . layout . i8_align . abi ( ) as usize ) ,
485
- 2 => ptr . check_align ( self . layout . i16_align . abi ( ) as usize ) ,
486
- 4 => ptr . check_align ( self . layout . i32_align . abi ( ) as usize ) ,
487
- 8 => ptr . check_align ( self . layout . i64_align . abi ( ) as usize ) ,
482
+ 1 => Ok ( self . layout . i8_align . abi ( ) as usize ) ,
483
+ 2 => Ok ( self . layout . i16_align . abi ( ) as usize ) ,
484
+ 4 => Ok ( self . layout . i32_align . abi ( ) as usize ) ,
485
+ 8 => Ok ( self . layout . i64_align . abi ( ) as usize ) ,
488
486
_ => panic ! ( "bad integer size" ) ,
489
487
}
490
488
}
491
489
492
490
pub fn read_int ( & self , ptr : Pointer , size : usize ) -> EvalResult < ' tcx , i64 > {
493
- self . check_int_align ( ptr , size) ?;
494
- self . get_bytes ( ptr, size) . map ( |b| read_target_int ( self . endianess ( ) , b) . unwrap ( ) )
491
+ let align = self . int_align ( size) ?;
492
+ self . get_bytes ( ptr, size, align ) . map ( |b| read_target_int ( self . endianess ( ) , b) . unwrap ( ) )
495
493
}
496
494
497
495
pub fn write_int ( & mut self , ptr : Pointer , n : i64 , size : usize ) -> EvalResult < ' tcx , ( ) > {
498
- self . check_int_align ( ptr , size) ?;
496
+ let align = self . int_align ( size) ?;
499
497
let endianess = self . endianess ( ) ;
500
- let b = self . get_bytes_mut ( ptr, size) ?;
498
+ let b = self . get_bytes_mut ( ptr, size, align ) ?;
501
499
write_target_int ( endianess, b, n) . unwrap ( ) ;
502
500
Ok ( ( ) )
503
501
}
504
502
505
503
pub fn read_uint ( & self , ptr : Pointer , size : usize ) -> EvalResult < ' tcx , u64 > {
506
- self . check_int_align ( ptr , size) ?;
507
- self . get_bytes ( ptr, size) . map ( |b| read_target_uint ( self . endianess ( ) , b) . unwrap ( ) )
504
+ let align = self . int_align ( size) ?;
505
+ self . get_bytes ( ptr, size, align ) . map ( |b| read_target_uint ( self . endianess ( ) , b) . unwrap ( ) )
508
506
}
509
507
510
508
pub fn write_uint ( & mut self , ptr : Pointer , n : u64 , size : usize ) -> EvalResult < ' tcx , ( ) > {
511
- self . check_int_align ( ptr , size) ?;
509
+ let align = self . int_align ( size) ?;
512
510
let endianess = self . endianess ( ) ;
513
- let b = self . get_bytes_mut ( ptr, size) ?;
511
+ let b = self . get_bytes_mut ( ptr, size, align ) ?;
514
512
write_target_uint ( endianess, b, n) . unwrap ( ) ;
515
513
Ok ( ( ) )
516
514
}
@@ -534,29 +532,29 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
534
532
}
535
533
536
534
pub fn write_f32 ( & mut self , ptr : Pointer , f : f32 ) -> EvalResult < ' tcx , ( ) > {
537
- ptr. check_align ( self . layout . f32_align . abi ( ) as usize ) ?;
538
535
let endianess = self . endianess ( ) ;
539
- let b = self . get_bytes_mut ( ptr, 4 ) ?;
536
+ let align = self . layout . f32_align . abi ( ) as usize ;
537
+ let b = self . get_bytes_mut ( ptr, 4 , align) ?;
540
538
write_target_f32 ( endianess, b, f) . unwrap ( ) ;
541
539
Ok ( ( ) )
542
540
}
543
541
544
542
pub fn write_f64 ( & mut self , ptr : Pointer , f : f64 ) -> EvalResult < ' tcx , ( ) > {
545
- ptr. check_align ( self . layout . f64_align . abi ( ) as usize ) ?;
546
543
let endianess = self . endianess ( ) ;
547
- let b = self . get_bytes_mut ( ptr, 8 ) ?;
544
+ let align = self . layout . f64_align . abi ( ) as usize ;
545
+ let b = self . get_bytes_mut ( ptr, 8 , align) ?;
548
546
write_target_f64 ( endianess, b, f) . unwrap ( ) ;
549
547
Ok ( ( ) )
550
548
}
551
549
552
550
pub fn read_f32 ( & self , ptr : Pointer ) -> EvalResult < ' tcx , f32 > {
553
- ptr . check_align ( self . layout . f32_align . abi ( ) as usize ) ? ;
554
- self . get_bytes ( ptr , 4 ) . map ( |b| read_target_f32 ( self . endianess ( ) , b) . unwrap ( ) )
551
+ self . get_bytes ( ptr , 4 , self . layout . f32_align . abi ( ) as usize )
552
+ . map ( |b| read_target_f32 ( self . endianess ( ) , b) . unwrap ( ) )
555
553
}
556
554
557
555
pub fn read_f64 ( & self , ptr : Pointer ) -> EvalResult < ' tcx , f64 > {
558
- ptr . check_align ( self . layout . f64_align . abi ( ) as usize ) ? ;
559
- self . get_bytes ( ptr , 8 ) . map ( |b| read_target_f64 ( self . endianess ( ) , b) . unwrap ( ) )
556
+ self . get_bytes ( ptr , 8 , self . layout . f64_align . abi ( ) as usize )
557
+ . map ( |b| read_target_f64 ( self . endianess ( ) , b) . unwrap ( ) )
560
558
}
561
559
}
562
560
0 commit comments