diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index 84bd275df347c..0554fd821ba2e 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -15,6 +15,8 @@ use core::intrinsics::{min_align_of_val, size_of_val}; use core::ptr::{NonNull, Unique}; use core::usize; +#[cfg(target_has_atomic = "ptr")] use core::{mem, ptr}; +#[cfg(target_has_atomic = "ptr")] use core::sync::atomic::{AtomicPtr, Ordering}; #[stable(feature = "alloc_module", since = "1.28.0")] #[doc(inline)] @@ -191,12 +193,89 @@ pub(crate) unsafe fn box_free(ptr: Unique) { #[stable(feature = "global_alloc", since = "1.28.0")] #[rustc_allocator_nounwind] pub fn handle_alloc_error(layout: Layout) -> ! { - #[allow(improper_ctypes)] - extern "Rust" { - #[lang = "oom"] - fn oom_impl(layout: Layout) -> !; + #[cfg(target_has_atomic = "ptr")] + { + let hook = HOOK.load(Ordering::SeqCst); + let hook: fn(Layout) = if hook.is_null() { + default_alloc_error_hook + } else { + unsafe { mem::transmute(hook) } + }; + hook(layout); + } + #[cfg(not(target_has_atomic = "ptr"))] + { + default_alloc_error_hook(layout) + } + + unsafe { + #[cfg(not(stage0))] + { + #[allow(improper_ctypes)] + extern "Rust" { + // This function is generated by the compiler + // and calls __rust_abort_internal in src/libstd/alloc.rs + // if the `std` crate is linked. + fn __rust_maybe_abort_internal(); + } + __rust_maybe_abort_internal(); + } + // The above does nothing and returns when `std` is not linked. + // In that case we abort "naively" here: + ::core::intrinsics::abort() + } +} + +fn default_alloc_error_hook(layout: Layout) { + #[cfg(stage0)] + let _ = layout; + #[cfg(not(stage0))] + unsafe { + #[allow(improper_ctypes)] + extern "Rust" { + // This function is generated by the compiler + // and calls __rust_default_alloc_error_hook in src/libstd/alloc.rs + // if the `std` crate is linked. + fn __rust_maybe_default_alloc_error_hook(size: usize, align: usize); + } + __rust_maybe_default_alloc_error_hook(layout.size(), layout.align()) + } +} + +#[cfg(target_has_atomic = "ptr")] +static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); + +/// Registers a custom allocation error hook, replacing any that was previously registered. +/// +/// The allocation error hook is invoked when an infallible memory allocation fails, before +/// the runtime aborts. The default hook prints a message to standard error, +/// but this behavior can be customized with the [`set_alloc_error_hook`] and +/// [`take_alloc_error_hook`] functions. +/// +/// The hook is provided with a `Layout` struct which contains information +/// about the allocation that failed. +/// +/// The allocation error hook is a global resource. +#[unstable(feature = "alloc_error_hook", issue = "51245")] +#[cfg(target_has_atomic = "ptr")] +pub fn set_alloc_error_hook(hook: fn(Layout)) { + HOOK.store(hook as *mut (), Ordering::SeqCst); +} + +/// Unregisters the current allocation error hook, returning it. +/// +/// *See also the function [`set_alloc_error_hook`].* +/// +/// If no custom hook is registered, the default hook will be returned. +#[unstable(feature = "alloc_error_hook", issue = "51245")] +#[cfg(target_has_atomic = "ptr")] +pub fn take_alloc_error_hook() -> fn(Layout) { + let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst); + if hook.is_null() { + default_alloc_error_hook + } else { + unsafe { mem::transmute(hook) } } - unsafe { oom_impl(layout) } } #[cfg(test)] diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index fe676919a7d14..3195b507b1c20 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -307,7 +307,6 @@ language_item_table! { ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn; BoxFreeFnLangItem, "box_free", box_free_fn; DropInPlaceFnLangItem, "drop_in_place", drop_in_place_fn; - OomLangItem, "oom", oom; StartFnLangItem, "start", start_fn; diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index 3c2ea047218a7..6a1a9e9bc4f8b 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -151,5 +151,4 @@ weak_lang_items! { panic_impl, PanicImplLangItem, rust_begin_unwind; eh_personality, EhPersonalityLangItem, rust_eh_personality; eh_unwind_resume, EhUnwindResumeLangItem, rust_eh_unwind_resume; - oom, OomLangItem, rust_oom; } diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index f28e91e19b73c..3c66bd3032ea9 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -74,10 +74,6 @@ #![stable(feature = "alloc_module", since = "1.28.0")] -use core::sync::atomic::{AtomicPtr, Ordering}; -use core::{mem, ptr}; -use sys_common::util::dumb_print; - #[stable(feature = "alloc_module", since = "1.28.0")] #[doc(inline)] pub use alloc_crate::alloc::*; @@ -86,64 +82,14 @@ pub use alloc_crate::alloc::*; #[doc(inline)] pub use alloc_system::System; -static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); - -/// Registers a custom allocation error hook, replacing any that was previously registered. -/// -/// The allocation error hook is invoked when an infallible memory allocation fails, before -/// the runtime aborts. The default hook prints a message to standard error, -/// but this behavior can be customized with the [`set_alloc_error_hook`] and -/// [`take_alloc_error_hook`] functions. -/// -/// The hook is provided with a `Layout` struct which contains information -/// about the allocation that failed. -/// -/// The allocation error hook is a global resource. -#[unstable(feature = "alloc_error_hook", issue = "51245")] -pub fn set_alloc_error_hook(hook: fn(Layout)) { - HOOK.store(hook as *mut (), Ordering::SeqCst); -} - -/// Unregisters the current allocation error hook, returning it. -/// -/// *See also the function [`set_alloc_error_hook`].* -/// -/// If no custom hook is registered, the default hook will be returned. -#[unstable(feature = "alloc_error_hook", issue = "51245")] -pub fn take_alloc_error_hook() -> fn(Layout) { - let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst); - if hook.is_null() { - default_alloc_error_hook - } else { - unsafe { mem::transmute(hook) } - } -} - -fn default_alloc_error_hook(layout: Layout) { - dumb_print(format_args!("memory allocation of {} bytes failed", layout.size())); -} - -#[cfg(not(test))] -#[doc(hidden)] -#[lang = "oom"] -#[unstable(feature = "alloc_internals", issue = "0")] -pub extern fn rust_oom(layout: Layout) -> ! { - let hook = HOOK.load(Ordering::SeqCst); - let hook: fn(Layout) = if hook.is_null() { - default_alloc_error_hook - } else { - unsafe { mem::transmute(hook) } - }; - hook(layout); - unsafe { ::sys::abort_internal(); } -} - #[cfg(not(test))] #[doc(hidden)] #[allow(unused_attributes)] #[unstable(feature = "alloc_internals", issue = "0")] pub mod __default_lib_allocator { use super::{System, Layout, GlobalAlloc}; + use sys_common::util::dumb_print; + // for symbol names src/librustc/middle/allocator.rs // for signatures src/librustc_allocator/lib.rs @@ -181,4 +127,16 @@ pub mod __default_lib_allocator { let layout = Layout::from_size_align_unchecked(size, align); System.alloc_zeroed(layout) } + + #[no_mangle] + #[rustc_std_internal_symbol] + pub extern fn __rust_default_alloc_error_hook(size: usize, _align: usize) { + dumb_print(format_args!("memory allocation of {} bytes failed", size)); + } + + #[no_mangle] + #[rustc_std_internal_symbol] + pub unsafe extern fn __rust_abort_internal() { + ::sys::abort_internal() + } } diff --git a/src/test/ui/missing-allocator.rs b/src/test/ui/missing-allocator.rs index 24282631b7eea..7cc56ce264731 100644 --- a/src/test/ui/missing-allocator.rs +++ b/src/test/ui/missing-allocator.rs @@ -20,7 +20,4 @@ fn panic(_: &core::panic::PanicInfo) -> ! { loop {} } -#[lang = "oom"] -fn oom() {} - extern crate alloc;