configure_builtins.rs - source
Description: Source of the Rust file `library/std/src/sys/configure_builtins.rs`.

#
std/sys/
configure_builtins.rs

    1//! The configure builtins provides runtime support compiler-builtin features
    2//! which require dynamic initialization to work as expected, e.g. aarch64
    3//! outline-atomics.
    4
    5/// Enable LSE atomic operations at startup, if supported.
    6///
    7/// Linker sections are based on what [`ctor`] does, with priorities to run slightly before user
    8/// code:
    9///
    10/// - Apple uses the section `__mod_init_func`, `mod_init_funcs` is needed to set
    11///   `S_MOD_INIT_FUNC_POINTERS`. There doesn't seem to be a way to indicate priorities.
    12/// - Windows uses `.CRT$XCT`, which is run before user constructors (these should use `.CRT$XCU`).
    13/// - ELF uses `.init_array` with a priority of 90, which runs before our `ARGV_INIT_ARRAY`
    14///   initializer (priority 99). Both are within the 0-100 implementation-reserved range, per docs
    15///   for the [`prio-ctor-dtor`] warning, and this matches compiler-rt's `CONSTRUCTOR_PRIORITY`.
    16///
    17/// To save startup time, the initializer is only run if outline atomic routines from
    18/// compiler-builtins may be used. If LSE is known to be available then the calls are never
    19/// emitted, and if we build the C intrinsics then it has its own initializer using the symbol
    20/// `__aarch64_have_lse_atomics`.
    21///
    22/// Initialization is done in a global constructor to so we get the same behavior regardless of
    23/// whether Rust's `init` is used, or if we are in a `dylib` or `no_main` situation (as opposed
    24/// to doing it as part of pre-main startup). This also matches C implementations.
    25///
    26/// Ideally `core` would have something similar, but detecting the CPU features requires the
    27/// auxiliary vector from the OS. We do the initialization in `std` rather than as part of
    28/// `compiler-builtins` because a builtins->std dependency isn't possible, and inlining parts of
    29/// `std-detect` would be much messier.
    30///
    31/// [`ctor`]: https://github.com/mmastrac/rust-ctor/blob/63382b833ddcbfb8b064f4e86bfa1ed4026ff356/shared/src/macros/mod.rs#L522-L534
    32/// [`prio-ctor-dtor`]: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
    33#[cfg(all(
    34    target_arch = "aarch64",
    35    target_feature = "outline-atomics",
    36    not(target_feature = "lse"),
    37    not(feature = "compiler-builtins-c"),
    38))]
    39#[used]
    40#[cfg_attr(target_vendor = "apple", unsafe(link_section = "__DATA,__mod_init_func,mod_init_funcs"))]
    41#[cfg_attr(target_os = "windows", unsafe(link_section = ".CRT$XCT"))]
    42#[cfg_attr(
    43    not(any(target_vendor = "apple", target_os = "windows")),
    44    unsafe(link_section = ".init_array.90")
    45)]
    46static RUST_LSE_INIT: extern "C" fn() = {
    47    extern "C" fn init_lse() {
    48        use crate::arch;
    49
    50        // This is provided by compiler-builtins::aarch64_outline_atomics.
    51        unsafe extern "C" {
    52            fn __rust_enable_lse();
    53        }
    54
    55        if arch::is_aarch64_feature_detected!("lse") {
    56            unsafe {
    57                __rust_enable_lse();
    58            }
    59        }
    60    }
    61    init_lse
    62};