@@ -298,6 +298,33 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
298
298
Ok ( None )
299
299
}
300
300
301
+ /// Emulates calling the internal __rust_* allocator functions
302
+ fn emulate_allocator (
303
+ & mut self ,
304
+ symbol : Symbol ,
305
+ default : impl FnOnce ( & mut MiriEvalContext < ' mir , ' tcx > ) -> InterpResult < ' tcx > ,
306
+ ) -> InterpResult < ' tcx , EmulateByNameResult < ' mir , ' tcx > > {
307
+ let this = self . eval_context_mut ( ) ;
308
+
309
+ let allocator_kind = if let Some ( allocator_kind) = this. tcx . allocator_kind ( ( ) ) {
310
+ allocator_kind
311
+ } else {
312
+ // in real code, this symbol does not exist without an allocator
313
+ return Ok ( EmulateByNameResult :: NotSupported ) ;
314
+ } ;
315
+
316
+ match allocator_kind {
317
+ AllocatorKind :: Global => {
318
+ let body = this
319
+ . lookup_exported_symbol ( symbol) ?
320
+ . expect ( "symbol should be present if there is a global allocator" ) ;
321
+
322
+ Ok ( EmulateByNameResult :: MirBody ( body) )
323
+ }
324
+ AllocatorKind :: Default => default ( this) . map ( |( ) | EmulateByNameResult :: NeedsJumping ) ,
325
+ }
326
+ }
327
+
301
328
/// Emulates calling a foreign item using its name.
302
329
fn emulate_foreign_item_by_name (
303
330
& mut self ,
@@ -372,77 +399,48 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
372
399
let align = this. read_scalar ( align) ?. to_machine_usize ( this) ?;
373
400
Self :: check_alloc_request ( size, align) ?;
374
401
375
- let allocator_kind = this. tcx . allocator_kind ( ( ) ) ;
376
-
377
- match allocator_kind. expect ( "allocator should be present if used" ) {
378
- AllocatorKind :: Global => {
379
- let body = this. lookup_exported_symbol ( Symbol :: intern ( "__rg_alloc" ) ) ?
380
- . expect ( "symbol should be present if there is a global allocator" ) ;
381
-
382
- return Ok ( EmulateByNameResult :: MirBody ( body) )
383
- } ,
384
- AllocatorKind :: Default => {
385
- let ptr = this. memory . allocate (
386
- Size :: from_bytes ( size) ,
387
- Align :: from_bytes ( align) . unwrap ( ) ,
388
- MiriMemoryKind :: Rust . into ( ) ,
389
- ) ?;
390
- this. write_pointer ( ptr, dest) ?;
391
- }
392
- } ;
402
+ return this. emulate_allocator ( Symbol :: intern ( "__rg_alloc" ) , |this| {
403
+ let ptr = this. memory . allocate (
404
+ Size :: from_bytes ( size) ,
405
+ Align :: from_bytes ( align) . unwrap ( ) ,
406
+ MiriMemoryKind :: Rust . into ( ) ,
407
+ ) ?;
408
+
409
+ this. write_pointer ( ptr, dest)
410
+ } ) ;
393
411
}
394
412
"__rust_alloc_zeroed" => {
395
413
let & [ ref size, ref align] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
396
414
let size = this. read_scalar ( size) ?. to_machine_usize ( this) ?;
397
415
let align = this. read_scalar ( align) ?. to_machine_usize ( this) ?;
398
416
Self :: check_alloc_request ( size, align) ?;
399
417
400
- let allocator_kind = this. tcx . allocator_kind ( ( ) ) ;
401
-
402
- match allocator_kind. expect ( "allocator should be present if used" ) {
403
- AllocatorKind :: Global => {
404
- let body = this. lookup_exported_symbol ( Symbol :: intern ( "__rg_alloc_zeroed" ) ) ?
405
- . expect ( "symbol should be present if there is a global allocator" ) ;
406
-
407
- return Ok ( EmulateByNameResult :: MirBody ( body) )
408
- } ,
409
- AllocatorKind :: Default => {
410
- let ptr = this. memory . allocate (
411
- Size :: from_bytes ( size) ,
412
- Align :: from_bytes ( align) . unwrap ( ) ,
413
- MiriMemoryKind :: Rust . into ( ) ,
414
- ) ?;
415
-
416
- // We just allocated this, the access is definitely in-bounds.
417
- this. memory . write_bytes ( ptr. into ( ) , iter:: repeat ( 0u8 ) . take ( usize:: try_from ( size) . unwrap ( ) ) ) . unwrap ( ) ;
418
- this. write_pointer ( ptr, dest) ?;
419
- }
420
- }
418
+ return this. emulate_allocator ( Symbol :: intern ( "__rg_alloc_zeroed" ) , |this| {
419
+ let ptr = this. memory . allocate (
420
+ Size :: from_bytes ( size) ,
421
+ Align :: from_bytes ( align) . unwrap ( ) ,
422
+ MiriMemoryKind :: Rust . into ( ) ,
423
+ ) ?;
424
+
425
+ // We just allocated this, the access is definitely in-bounds.
426
+ this. memory . write_bytes ( ptr. into ( ) , iter:: repeat ( 0u8 ) . take ( usize:: try_from ( size) . unwrap ( ) ) ) . unwrap ( ) ;
427
+ this. write_pointer ( ptr, dest)
428
+ } ) ;
421
429
}
422
430
"__rust_dealloc" => {
423
431
let & [ ref ptr, ref old_size, ref align] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
424
432
let ptr = this. read_pointer ( ptr) ?;
425
433
let old_size = this. read_scalar ( old_size) ?. to_machine_usize ( this) ?;
426
434
let align = this. read_scalar ( align) ?. to_machine_usize ( this) ?;
427
435
428
- let allocator_kind = this. tcx . allocator_kind ( ( ) ) ;
429
-
430
- match allocator_kind. expect ( "allocator should be present if used" ) {
431
- AllocatorKind :: Global => {
432
- let body = this. lookup_exported_symbol ( Symbol :: intern ( "__rg_dealloc" ) ) ?
433
- . expect ( "symbol should be present if there is a global allocator" ) ;
434
-
435
- return Ok ( EmulateByNameResult :: MirBody ( body) )
436
- } ,
437
- AllocatorKind :: Default => {
438
- // No need to check old_size/align; we anyway check that they match the allocation.
439
- this. memory . deallocate (
440
- ptr,
441
- Some ( ( Size :: from_bytes ( old_size) , Align :: from_bytes ( align) . unwrap ( ) ) ) ,
442
- MiriMemoryKind :: Rust . into ( ) ,
443
- ) ?;
444
- }
445
- }
436
+ return this. emulate_allocator ( Symbol :: intern ( "__rg_dealloc" ) , |this| {
437
+ // No need to check old_size/align; we anyway check that they match the allocation.
438
+ this. memory . deallocate (
439
+ ptr,
440
+ Some ( ( Size :: from_bytes ( old_size) , Align :: from_bytes ( align) . unwrap ( ) ) ) ,
441
+ MiriMemoryKind :: Rust . into ( ) ,
442
+ )
443
+ } ) ;
446
444
}
447
445
"__rust_realloc" => {
448
446
let & [ ref ptr, ref old_size, ref align, ref new_size] = this. check_shim ( abi, Abi :: Rust , link_name, args) ?;
@@ -453,27 +451,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
453
451
Self :: check_alloc_request ( new_size, align) ?;
454
452
// No need to check old_size; we anyway check that they match the allocation.
455
453
456
- let allocator_kind = this. tcx . allocator_kind ( ( ) ) ;
457
-
458
- match allocator_kind. expect ( "allocator should be present if used" ) {
459
- AllocatorKind :: Global => {
460
- let body = this. lookup_exported_symbol ( Symbol :: intern ( "__rg_realloc" ) ) ?
461
- . expect ( "symbol should be present if there is a global allocator" ) ;
462
-
463
- return Ok ( EmulateByNameResult :: MirBody ( body) )
464
- } ,
465
- AllocatorKind :: Default => {
466
- let align = Align :: from_bytes ( align) . unwrap ( ) ;
467
- let new_ptr = this. memory . reallocate (
468
- ptr,
469
- Some ( ( Size :: from_bytes ( old_size) , align) ) ,
470
- Size :: from_bytes ( new_size) ,
471
- align,
472
- MiriMemoryKind :: Rust . into ( ) ,
473
- ) ?;
474
- this. write_pointer ( new_ptr, dest) ?;
475
- }
476
- }
454
+ return this. emulate_allocator ( Symbol :: intern ( "__rg_realloc" ) , |this| {
455
+ let align = Align :: from_bytes ( align) . unwrap ( ) ;
456
+ let new_ptr = this. memory . reallocate (
457
+ ptr,
458
+ Some ( ( Size :: from_bytes ( old_size) , align) ) ,
459
+ Size :: from_bytes ( new_size) ,
460
+ align,
461
+ MiriMemoryKind :: Rust . into ( ) ,
462
+ ) ?;
463
+ this. write_pointer ( new_ptr, dest)
464
+ } ) ;
477
465
}
478
466
479
467
// C memory handling functions
0 commit comments