11use std:: { collections:: hash_map:: Entry , io:: Write , iter, path:: Path } ;
22
33use rustc_apfloat:: Float ;
4- use rustc_ast:: expand:: allocator:: { alloc_error_handler_name, AllocatorKind } ;
4+ use rustc_ast:: expand:: allocator:: alloc_error_handler_name;
55use rustc_hir:: { def:: DefKind , def_id:: CrateNum } ;
66use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
77use rustc_middle:: mir;
@@ -12,6 +12,7 @@ use rustc_target::{
1212 spec:: abi:: Abi ,
1313} ;
1414
15+ use super :: alloc:: { check_alloc_request, EvalContextExt as _} ;
1516use super :: backtrace:: EvalContextExt as _;
1617use crate :: * ;
1718use helpers:: { ToHost , ToSoft } ;
@@ -232,138 +233,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
232233 Some ( instance) => Ok ( Some ( ( this. load_mir ( instance. def , None ) ?, instance) ) ) ,
233234 }
234235 }
235-
236- fn malloc (
237- & mut self ,
238- size : u64 ,
239- zero_init : bool ,
240- kind : MiriMemoryKind ,
241- ) -> InterpResult < ' tcx , Pointer < Option < Provenance > > > {
242- let this = self . eval_context_mut ( ) ;
243- if size == 0 {
244- Ok ( Pointer :: null ( ) )
245- } else {
246- let align = this. min_align ( size, kind) ;
247- let ptr = this. allocate_ptr ( Size :: from_bytes ( size) , align, kind. into ( ) ) ?;
248- if zero_init {
249- // We just allocated this, the access is definitely in-bounds and fits into our address space.
250- this. write_bytes_ptr (
251- ptr. into ( ) ,
252- iter:: repeat ( 0u8 ) . take ( usize:: try_from ( size) . unwrap ( ) ) ,
253- )
254- . unwrap ( ) ;
255- }
256- Ok ( ptr. into ( ) )
257- }
258- }
259-
260- fn free (
261- & mut self ,
262- ptr : Pointer < Option < Provenance > > ,
263- kind : MiriMemoryKind ,
264- ) -> InterpResult < ' tcx > {
265- let this = self . eval_context_mut ( ) ;
266- if !this. ptr_is_null ( ptr) ? {
267- this. deallocate_ptr ( ptr, None , kind. into ( ) ) ?;
268- }
269- Ok ( ( ) )
270- }
271-
272- fn realloc (
273- & mut self ,
274- old_ptr : Pointer < Option < Provenance > > ,
275- new_size : u64 ,
276- kind : MiriMemoryKind ,
277- ) -> InterpResult < ' tcx , Pointer < Option < Provenance > > > {
278- let this = self . eval_context_mut ( ) ;
279- let new_align = this. min_align ( new_size, kind) ;
280- if this. ptr_is_null ( old_ptr) ? {
281- if new_size == 0 {
282- Ok ( Pointer :: null ( ) )
283- } else {
284- let new_ptr =
285- this. allocate_ptr ( Size :: from_bytes ( new_size) , new_align, kind. into ( ) ) ?;
286- Ok ( new_ptr. into ( ) )
287- }
288- } else {
289- if new_size == 0 {
290- this. deallocate_ptr ( old_ptr, None , kind. into ( ) ) ?;
291- Ok ( Pointer :: null ( ) )
292- } else {
293- let new_ptr = this. reallocate_ptr (
294- old_ptr,
295- None ,
296- Size :: from_bytes ( new_size) ,
297- new_align,
298- kind. into ( ) ,
299- ) ?;
300- Ok ( new_ptr. into ( ) )
301- }
302- }
303- }
304236}
305237
306238impl < ' mir , ' tcx : ' mir > EvalContextExtPriv < ' mir , ' tcx > for crate :: MiriInterpCx < ' mir , ' tcx > { }
307239trait EvalContextExtPriv < ' mir , ' tcx : ' mir > : crate :: MiriInterpCxExt < ' mir , ' tcx > {
308- /// Returns the minimum alignment for the target architecture for allocations of the given size.
309- fn min_align ( & self , size : u64 , kind : MiriMemoryKind ) -> Align {
310- let this = self . eval_context_ref ( ) ;
311- // List taken from `library/std/src/sys/pal/common/alloc.rs`.
312- // This list should be kept in sync with the one from libstd.
313- let min_align = match this. tcx . sess . target . arch . as_ref ( ) {
314- "x86" | "arm" | "mips" | "mips32r6" | "powerpc" | "powerpc64" | "wasm32" => 8 ,
315- "x86_64" | "aarch64" | "mips64" | "mips64r6" | "s390x" | "sparc64" | "loongarch64" =>
316- 16 ,
317- arch => bug ! ( "unsupported target architecture for malloc: `{}`" , arch) ,
318- } ;
319- // Windows always aligns, even small allocations.
320- // Source: <https://support.microsoft.com/en-us/help/286470/how-to-use-pageheap-exe-in-windows-xp-windows-2000-and-windows-server>
321- // But jemalloc does not, so for the C heap we only align if the allocation is sufficiently big.
322- if kind == MiriMemoryKind :: WinHeap || size >= min_align {
323- return Align :: from_bytes ( min_align) . unwrap ( ) ;
324- }
325- // We have `size < min_align`. Round `size` *down* to the next power of two and use that.
326- fn prev_power_of_two ( x : u64 ) -> u64 {
327- let next_pow2 = x. next_power_of_two ( ) ;
328- if next_pow2 == x {
329- // x *is* a power of two, just use that.
330- x
331- } else {
332- // x is between two powers, so next = 2*prev.
333- next_pow2 / 2
334- }
335- }
336- Align :: from_bytes ( prev_power_of_two ( size) ) . unwrap ( )
337- }
338-
339- /// Emulates calling the internal __rust_* allocator functions
340- fn emulate_allocator (
341- & mut self ,
342- default : impl FnOnce ( & mut MiriInterpCx < ' mir , ' tcx > ) -> InterpResult < ' tcx > ,
343- ) -> InterpResult < ' tcx , EmulateForeignItemResult > {
344- let this = self . eval_context_mut ( ) ;
345-
346- let Some ( allocator_kind) = this. tcx . allocator_kind ( ( ) ) else {
347- // in real code, this symbol does not exist without an allocator
348- return Ok ( EmulateForeignItemResult :: NotSupported ) ;
349- } ;
350-
351- match allocator_kind {
352- AllocatorKind :: Global => {
353- // When `#[global_allocator]` is used, `__rust_*` is defined by the macro expansion
354- // of this attribute. As such we have to call an exported Rust function,
355- // and not execute any Miri shim. Somewhat unintuitively doing so is done
356- // by returning `NotSupported`, which triggers the `lookup_exported_symbol`
357- // fallback case in `emulate_foreign_item`.
358- return Ok ( EmulateForeignItemResult :: NotSupported ) ;
359- }
360- AllocatorKind :: Default => {
361- default ( this) ?;
362- Ok ( EmulateForeignItemResult :: NeedsJumping )
363- }
364- }
365- }
366-
367240 fn emulate_foreign_item_inner (
368241 & mut self ,
369242 link_name : Symbol ,
@@ -610,7 +483,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
610483 let size = this. read_target_usize ( size) ?;
611484 let align = this. read_target_usize ( align) ?;
612485
613- Self :: check_alloc_request ( size, align) ?;
486+ check_alloc_request ( size, align) ?;
614487
615488 let memory_kind = match link_name. as_str ( ) {
616489 "__rust_alloc" => MiriMemoryKind :: Rust ,
@@ -644,7 +517,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
644517 let size = this. read_target_usize ( size) ?;
645518 let align = this. read_target_usize ( align) ?;
646519
647- Self :: check_alloc_request ( size, align) ?;
520+ check_alloc_request ( size, align) ?;
648521
649522 let ptr = this. allocate_ptr (
650523 Size :: from_bytes ( size) ,
@@ -708,7 +581,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
708581 let new_size = this. read_target_usize ( new_size) ?;
709582 // No need to check old_size; we anyway check that they match the allocation.
710583
711- Self :: check_alloc_request ( new_size, align) ?;
584+ check_alloc_request ( new_size, align) ?;
712585
713586 let align = Align :: from_bytes ( align) . unwrap ( ) ;
714587 let new_ptr = this. reallocate_ptr (
@@ -1100,16 +973,4 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
1100973 // i.e., if we actually emulated the function with one of the shims.
1101974 Ok ( EmulateForeignItemResult :: NeedsJumping )
1102975 }
1103-
1104- /// Check some basic requirements for this allocation request:
1105- /// non-zero size, power-of-two alignment.
1106- fn check_alloc_request ( size : u64 , align : u64 ) -> InterpResult < ' tcx > {
1107- if size == 0 {
1108- throw_ub_format ! ( "creating allocation with size 0" ) ;
1109- }
1110- if !align. is_power_of_two ( ) {
1111- throw_ub_format ! ( "creating allocation with non-power-of-two alignment {}" , align) ;
1112- }
1113- Ok ( ( ) )
1114- }
1115976}
0 commit comments