library/compiler-builtins/compiler-builtins/build.rs RUST 650 lines View on github.com → Search inside
1#[path = "../libm/configure.rs"]2mod configure;34use std::env;56use configure::{Config, Library, set_cfg};78fn main() {9    let cfg = Config::from_env(Library::CompilerBuiltins);10    let llvm_target = &cfg.target_triple_split;1112    // Work around building as part of `builtins-shim`: if only `build.rs` is used, Cargo always13    // considers the build dirty because `builtins-shim/build.rs` does not exist. If only14    // `../c-b/build.rs` is used, the same may happen if not built in the workspace.15    // Note: this may be `None` if CARGO_MANIFEST_DIR doesn't end in a directory name (e.g. ".")16    if let Some(dir) = cfg.manifest_dir.file_name()17        && dir == "builtins-shim"18    {19        println!("cargo::rerun-if-changed=../compiler-builtins/build.rs");20    } else {21        println!("cargo::rerun-if-changed=build.rs");22    }2324    println!("cargo::rerun-if-changed=../libm/configure.rs");2526    configure::emit(&cfg);27    configure_check_cfg();2829    let cwd = env::current_dir().unwrap();30    println!("cargo:compiler-rt={}", cwd.join("compiler-rt").display());3132    // Forcibly enable memory intrinsics on wasm & SGX as we don't have a libc to33    // provide them.34    if (cfg.target_triple.contains("wasm") && !cfg.target_triple.contains("wasi"))35        || (cfg.target_triple.contains("sgx") && cfg.target_triple.contains("fortanix"))36        || cfg.target_triple.contains("-none")37        || cfg.target_triple.contains("nvptx")38        || cfg.target_triple.contains("uefi")39        || cfg.target_triple.contains("xous")40    {41        println!("cargo:rustc-cfg=feature=\"mem\"");42    }4344    // These targets have hardware unaligned access support.45    let mem_unaligned = cfg.target_arch.contains("x86_64")46        || cfg.target_arch.contains("x86")47        || cfg.target_arch.contains("aarch64")48        || cfg.target_arch.contains("bpf");49    set_cfg("mem_unaligned", mem_unaligned);5051    // Only emit the ARM Linux atomic emulation on pre-ARMv6 architectures. This52    // includes the old androideabi. It is deprecated but it is available as a53    // rustc target (arm-linux-androideabi).54    let kernel_user_helpers = llvm_target[0] == "armv4t"55        || llvm_target[0] == "armv5te"56        || cfg.target_triple == "arm-linux-androideabi";57    set_cfg("kernel_user_helpers", kernel_user_helpers);5859    let mut maybe_build_c = true;6061    // Emscripten's runtime includes all the builtins62    if cfg.target_os == "emscripten" {63        maybe_build_c = false;64    }6566    // OpenBSD provides compiler_rt by default, use it instead of rebuilding it from source67    if cfg.target_os == "openbsd" {68        println!("cargo:rustc-link-search=native=/usr/lib");69        println!("cargo:rustc-link-lib=compiler_rt");70        maybe_build_c = false;71    }7273    // Everything is LLVM bitcode, not compatible with mixed C/Rust74    if cfg.target_arch.contains("nvptx") {75        maybe_build_c = false;76    }7778    // Build missing intrinsics from compiler-rt C source code. If we're79    // mangling names though we assume that we're also in test mode so we don't80    // build anything and we rely on the upstream implementation of compiler-rt81    // functions82    if cfg!(feature = "unmangled-names") && cfg!(feature = "c") && maybe_build_c {83        #[cfg(feature = "c")]84        c::compile(&cfg);85    }86}8788/// Emit directives for features we expect to support that aren't in `Cargo.toml`.89///90/// These are mostly cfg elements emitted by this `build.rs`.91fn configure_check_cfg() {92    // Functions where we can set the "optimized-c" flag93    const HAS_OPTIMIZED_C: &[&str] = &[94        "__ashldi3",95        "__ashlsi3",96        "__ashrdi3",97        "__ashrsi3",98        "__bswapsi2",99        "__bswapdi2",100        "__bswapti2",101        "__divdi3",102        "__divsi3",103        "__divmoddi4",104        "__divmodsi4",105        "__divmodsi4",106        "__divmodti4",107        "__lshrdi3",108        "__lshrsi3",109        "__moddi3",110        "__modsi3",111        "__muldi3",112        "__udivdi3",113        "__udivmoddi4",114        "__udivmodsi4",115        "__udivsi3",116        "__umoddi3",117        "__umodsi3",118    ];119120    // Build a list of all aarch64 atomic operation functions121    let mut aarch_atomic = Vec::new();122    for aarch_op in ["cas", "ldadd", "ldclr", "ldeor", "ldset", "swp"] {123        let op_sizes = if aarch_op == "cas" {124            [1, 2, 4, 8, 16].as_slice()125        } else {126            [1, 2, 4, 8].as_slice()127        };128129        for op_size in op_sizes {130            for ordering in ["relax", "acq", "rel", "acq_rel"] {131                aarch_atomic.push(format!("__aarch64_{aarch_op}{op_size}_{ordering}"));132            }133        }134    }135136    for fn_name in HAS_OPTIMIZED_C137        .iter()138        .copied()139        .chain(aarch_atomic.iter().map(|s| s.as_str()))140    {141        println!("cargo::rustc-check-cfg=cfg({fn_name}, values(\"optimized-c\"))",);142    }143144    // Rustc is unaware of sparc target features, but this does show up from145    // `rustc --print target-features --target sparc64-unknown-linux-gnu`.146    println!("cargo::rustc-check-cfg=cfg(target_feature, values(\"vis3\"))");147}148149#[cfg(feature = "c")]150mod c {151    use std::collections::{BTreeMap, HashSet};152    use std::env;153    use std::fs::{self, File};154    use std::io::Write;155    use std::path::{Path, PathBuf};156157    use super::Config;158159    struct Sources {160        // SYMBOL -> PATH TO SOURCE161        map: BTreeMap<&'static str, &'static str>,162    }163164    impl Sources {165        fn new() -> Sources {166            Sources {167                map: BTreeMap::new(),168            }169        }170171        fn extend(&mut self, sources: &[(&'static str, &'static str)]) {172            // NOTE Some intrinsics have both a generic implementation (e.g.173            // `floatdidf.c`) and an arch optimized implementation174            // (`x86_64/floatdidf.c`). In those cases, we keep the arch optimized175            // implementation and discard the generic implementation. If we don't176            // and keep both implementations, the linker will yell at us about177            // duplicate symbols!178            for (symbol, src) in sources {179                if src.contains("/") {180                    // Arch-optimized implementation (preferred)181                    self.map.insert(symbol, src);182                } else {183                    // Generic implementation184                    if !self.map.contains_key(symbol) {185                        self.map.insert(symbol, src);186                    }187                }188            }189        }190191        fn remove(&mut self, symbols: &[&str]) {192            for symbol in symbols {193                self.map.remove(*symbol).unwrap();194            }195        }196    }197198    /// Compile intrinsics from the compiler-rt C source code199    pub fn compile(cfg: &Config) {200        let llvm_target = &cfg.target_triple_split;201        let mut consider_float_intrinsics = true;202        let build = &mut cc::Build::new();203204        // AArch64 GCCs exit with an error condition when they encounter any kind of floating point205        // code if the `nofp` and/or `nosimd` compiler flags have been set.206        //207        // Therefore, evaluate if those flags are present and set a boolean that causes any208        // compiler-rt intrinsics that contain floating point source to be excluded for this target.209        if cfg.target_arch == "aarch64" {210            let cflags_key = String::from("CFLAGS_") + &(cfg.target_triple.replace("-", "_"));211            if let Ok(cflags_value) = env::var(cflags_key) {212                if cflags_value.contains("+nofp") || cflags_value.contains("+nosimd") {213                    consider_float_intrinsics = false;214                }215            }216        }217218        // `compiler-rt` requires `COMPILER_RT_HAS_FLOAT16` to be defined to make it use the219        // `_Float16` type for `f16` intrinsics. This shouldn't matter as all existing `f16`220        // intrinsics have been ported to Rust in `compiler-builtins` as C compilers don't221        // support `_Float16` on all targets (whereas Rust does). However, define the macro222        // anyway to prevent issues like rust#118813 and rust#123885 silently reoccuring if more223        // `f16` intrinsics get accidentally added here in the future.224        build.define("COMPILER_RT_HAS_FLOAT16", None);225226        build.warnings(false);227228        if cfg.target_env == "msvc" {229            // Don't pull in extra libraries on MSVC230            build.flag("/Zl");231232            // Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP233            build.define("__func__", Some("__FUNCTION__"));234        } else {235            // Turn off various features of gcc and such, mostly copying236            // compiler-rt's build system already237            build.flag("-fno-builtin");238            build.flag("-fvisibility=hidden");239            build.flag("-ffreestanding");240            // Avoid the following warning appearing once **per file**:241            // clang: warning: optimization flag '-fomit-frame-pointer' is not supported for target 'armv7' [-Wignored-optimization-argument]242            //243            // Note that compiler-rt's build system also checks244            //245            // `check_cxx_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG)`246            //247            // in https://github.com/rust-lang/compiler-rt/blob/c8fbcb3/cmake/config-ix.cmake#L19.248            build.flag_if_supported("-fomit-frame-pointer");249            build.define("VISIBILITY_HIDDEN", None);250251            if let "aarch64" | "arm64ec" = cfg.target_arch.as_str() {252                // FIXME(llvm20): Older GCCs on A64 fail to build with253                // -Werror=implicit-function-declaration due to a compiler-rt bug.254                // With a newer LLVM we should be able to enable the flag everywhere.255                // https://github.com/llvm/llvm-project/commit/8aa9d6206ce55bdaaf422839c351fbd63f033b89256            } else {257                // Avoid implicitly creating references to undefined functions258                build.flag("-Werror=implicit-function-declaration");259            }260        }261262        // int_util.c tries to include stdlib.h if `_WIN32` is defined,263        // which it is when compiling UEFI targets with clang. This is264        // at odds with compiling with `-ffreestanding`, as the header265        // may be incompatible or not present. Create a minimal stub266        // header to use instead.267        if cfg.target_os == "uefi" {268            let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());269            let include_dir = out_dir.join("include");270            if !include_dir.exists() {271                fs::create_dir(&include_dir).unwrap();272            }273            fs::write(include_dir.join("stdlib.h"), "#include <stddef.h>").unwrap();274            build.flag(&format!("-I{}", include_dir.to_str().unwrap()));275        }276277        let mut sources = Sources::new();278        sources.extend(&[279            ("__absvdi2", "absvdi2.c"),280            ("__absvsi2", "absvsi2.c"),281            ("__addvdi3", "addvdi3.c"),282            ("__addvsi3", "addvsi3.c"),283            ("__cmpdi2", "cmpdi2.c"),284            ("__int_util", "int_util.c"),285            ("__mulvdi3", "mulvdi3.c"),286            ("__mulvsi3", "mulvsi3.c"),287            ("__negdi2", "negdi2.c"),288            ("__negvdi2", "negvdi2.c"),289            ("__negvsi2", "negvsi2.c"),290            ("__paritydi2", "paritydi2.c"),291            ("__paritysi2", "paritysi2.c"),292            ("__popcountdi2", "popcountdi2.c"),293            ("__popcountsi2", "popcountsi2.c"),294            ("__subvdi3", "subvdi3.c"),295            ("__subvsi3", "subvsi3.c"),296            ("__ucmpdi2", "ucmpdi2.c"),297        ]);298299        if consider_float_intrinsics {300            sources.extend(&[301                ("__divdc3", "divdc3.c"),302                ("__divsc3", "divsc3.c"),303                ("__muldc3", "muldc3.c"),304                ("__mulsc3", "mulsc3.c"),305                ("__negdf2", "negdf2.c"),306                ("__negsf2", "negsf2.c"),307            ]);308        }309310        // On iOS and 32-bit OSX these are all just empty intrinsics, no need to311        // include them.312        if cfg.target_vendor != "apple" || cfg.target_arch != "x86" {313            sources.extend(&[314                ("__absvti2", "absvti2.c"),315                ("__addvti3", "addvti3.c"),316                ("__cmpti2", "cmpti2.c"),317                ("__ffsti2", "ffsti2.c"),318                ("__mulvti3", "mulvti3.c"),319                ("__negti2", "negti2.c"),320                ("__parityti2", "parityti2.c"),321                ("__popcountti2", "popcountti2.c"),322                ("__subvti3", "subvti3.c"),323                ("__ucmpti2", "ucmpti2.c"),324            ]);325326            if consider_float_intrinsics {327                sources.extend(&[("__negvti2", "negvti2.c")]);328            }329        }330331        if cfg.target_vendor == "apple" {332            sources.extend(&[333                ("atomic_flag_clear", "atomic_flag_clear.c"),334                ("atomic_flag_clear_explicit", "atomic_flag_clear_explicit.c"),335                ("atomic_flag_test_and_set", "atomic_flag_test_and_set.c"),336                (337                    "atomic_flag_test_and_set_explicit",338                    "atomic_flag_test_and_set_explicit.c",339                ),340                ("atomic_signal_fence", "atomic_signal_fence.c"),341                ("atomic_thread_fence", "atomic_thread_fence.c"),342            ]);343        }344345        if cfg.target_env != "msvc" {346            if cfg.target_arch == "x86" {347                sources.extend(&[348                    ("__ashldi3", "i386/ashldi3.S"),349                    ("__ashrdi3", "i386/ashrdi3.S"),350                    ("__divdi3", "i386/divdi3.S"),351                    ("__lshrdi3", "i386/lshrdi3.S"),352                    ("__moddi3", "i386/moddi3.S"),353                    ("__muldi3", "i386/muldi3.S"),354                    ("__udivdi3", "i386/udivdi3.S"),355                    ("__umoddi3", "i386/umoddi3.S"),356                ]);357            }358        }359360        if cfg.target_arch == "arm" && cfg.target_vendor != "apple" && cfg.target_env != "msvc" {361            sources.extend(&[362                ("__aeabi_div0", "arm/aeabi_div0.c"),363                ("__aeabi_drsub", "arm/aeabi_drsub.c"),364                ("__aeabi_frsub", "arm/aeabi_frsub.c"),365                ("__bswapdi2", "arm/bswapdi2.S"),366                ("__bswapsi2", "arm/bswapsi2.S"),367                ("__divmodsi4", "arm/divmodsi4.S"),368                ("__divsi3", "arm/divsi3.S"),369                ("__modsi3", "arm/modsi3.S"),370                ("__switch16", "arm/switch16.S"),371                ("__switch32", "arm/switch32.S"),372                ("__switch8", "arm/switch8.S"),373                ("__switchu8", "arm/switchu8.S"),374                ("__sync_synchronize", "arm/sync_synchronize.S"),375                ("__udivmodsi4", "arm/udivmodsi4.S"),376                ("__udivsi3", "arm/udivsi3.S"),377                ("__umodsi3", "arm/umodsi3.S"),378            ]);379380            if cfg.target_os == "freebsd" {381                sources.extend(&[("__clear_cache", "clear_cache.c")]);382            }383384            // First of all aeabi_cdcmp and aeabi_cfcmp are never called by LLVM.385            // Second are little-endian only, so build fail on big-endian targets.386            // Temporally workaround: exclude these files for big-endian targets.387            if !llvm_target[0].starts_with("thumbeb") && !llvm_target[0].starts_with("armeb") {388                sources.extend(&[389                    ("__aeabi_cdcmp", "arm/aeabi_cdcmp.S"),390                    ("__aeabi_cdcmpeq_check_nan", "arm/aeabi_cdcmpeq_check_nan.c"),391                    ("__aeabi_cfcmp", "arm/aeabi_cfcmp.S"),392                    ("__aeabi_cfcmpeq_check_nan", "arm/aeabi_cfcmpeq_check_nan.c"),393                ]);394            }395        }396397        if llvm_target[0] == "armv7" {398            sources.extend(&[399                ("__sync_fetch_and_add_4", "arm/sync_fetch_and_add_4.S"),400                ("__sync_fetch_and_add_8", "arm/sync_fetch_and_add_8.S"),401                ("__sync_fetch_and_and_4", "arm/sync_fetch_and_and_4.S"),402                ("__sync_fetch_and_and_8", "arm/sync_fetch_and_and_8.S"),403                ("__sync_fetch_and_max_4", "arm/sync_fetch_and_max_4.S"),404                ("__sync_fetch_and_max_8", "arm/sync_fetch_and_max_8.S"),405                ("__sync_fetch_and_min_4", "arm/sync_fetch_and_min_4.S"),406                ("__sync_fetch_and_min_8", "arm/sync_fetch_and_min_8.S"),407                ("__sync_fetch_and_nand_4", "arm/sync_fetch_and_nand_4.S"),408                ("__sync_fetch_and_nand_8", "arm/sync_fetch_and_nand_8.S"),409                ("__sync_fetch_and_or_4", "arm/sync_fetch_and_or_4.S"),410                ("__sync_fetch_and_or_8", "arm/sync_fetch_and_or_8.S"),411                ("__sync_fetch_and_sub_4", "arm/sync_fetch_and_sub_4.S"),412                ("__sync_fetch_and_sub_8", "arm/sync_fetch_and_sub_8.S"),413                ("__sync_fetch_and_umax_4", "arm/sync_fetch_and_umax_4.S"),414                ("__sync_fetch_and_umax_8", "arm/sync_fetch_and_umax_8.S"),415                ("__sync_fetch_and_umin_4", "arm/sync_fetch_and_umin_4.S"),416                ("__sync_fetch_and_umin_8", "arm/sync_fetch_and_umin_8.S"),417                ("__sync_fetch_and_xor_4", "arm/sync_fetch_and_xor_4.S"),418                ("__sync_fetch_and_xor_8", "arm/sync_fetch_and_xor_8.S"),419            ]);420        }421422        if llvm_target.last().unwrap().ends_with("eabihf") {423            if !llvm_target[0].starts_with("thumbv7em")424                && !llvm_target[0].starts_with("thumbv8m.main")425            {426                // The FPU option chosen for these architectures in cc-rs, ie:427                //     -mfpu=fpv4-sp-d16 for thumbv7em428                //     -mfpu=fpv5-sp-d16 for thumbv8m.main429                // do not support double precision floating points conversions so the files430                // that include such instructions are not included for these targets.431                sources.extend(&[432                    ("__fixdfsivfp", "arm/fixdfsivfp.S"),433                    ("__fixunsdfsivfp", "arm/fixunsdfsivfp.S"),434                    ("__floatsidfvfp", "arm/floatsidfvfp.S"),435                    ("__floatunssidfvfp", "arm/floatunssidfvfp.S"),436                ]);437            }438439            sources.extend(&[440                ("__fixsfsivfp", "arm/fixsfsivfp.S"),441                ("__fixunssfsivfp", "arm/fixunssfsivfp.S"),442                ("__floatsisfvfp", "arm/floatsisfvfp.S"),443                ("__floatunssisfvfp", "arm/floatunssisfvfp.S"),444                ("__floatunssisfvfp", "arm/floatunssisfvfp.S"),445                ("__restore_vfp_d8_d15_regs", "arm/restore_vfp_d8_d15_regs.S"),446                ("__save_vfp_d8_d15_regs", "arm/save_vfp_d8_d15_regs.S"),447                ("__negdf2vfp", "arm/negdf2vfp.S"),448                ("__negsf2vfp", "arm/negsf2vfp.S"),449            ]);450        }451452        if (cfg.target_arch == "aarch64" || cfg.target_arch == "arm64ec")453            && consider_float_intrinsics454        {455            sources.extend(&[456                ("__fe_getround", "fp_mode.c"),457                ("__fe_raise_inexact", "fp_mode.c"),458            ]);459460            if cfg.target_os != "windows" && cfg.target_os != "cygwin" {461                sources.extend(&[("__multc3", "multc3.c")]);462            }463        }464465        if cfg.target_arch == "mips" || cfg.target_arch == "riscv32" || cfg.target_arch == "riscv64"466        {467            sources.extend(&[("__bswapsi2", "bswapsi2.c")]);468        }469470        if cfg.target_arch == "mips64" {471            sources.extend(&[("__fe_getround", "fp_mode.c")]);472        }473474        if cfg.target_arch == "loongarch64" {475            sources.extend(&[("__fe_getround", "fp_mode.c")]);476        }477478        // Remove the assembly implementations that won't compile for the target479        if llvm_target[0] == "thumbv6m"480            || llvm_target[0] == "thumbv8m.base"481            || cfg.target_os == "uefi"482        {483            let mut to_remove = Vec::new();484            for (k, v) in sources.map.iter() {485                if v.ends_with(".S") {486                    to_remove.push(*k);487                }488            }489            sources.remove(&to_remove);490        }491492        if llvm_target[0] == "thumbv7m" || llvm_target[0] == "thumbv7em" {493            sources.remove(&["__aeabi_cdcmp", "__aeabi_cfcmp"]);494        }495496        // Android and Cygwin uses emulated TLS so we need a runtime support function.497        if cfg.target_os == "android" || cfg.target_os == "cygwin" {498            sources.extend(&[("__emutls_get_address", "emutls.c")]);499        }500501        // Work around a bug in the NDK headers (fixed in502        // https://r.android.com/2038949 which will be released in a future503        // NDK version) by providing a definition of LONG_BIT.504        if cfg.target_os == "android" {505            build.define("LONG_BIT", "(8 * sizeof(long))");506        }507508        // OpenHarmony also uses emulated TLS.509        if cfg.target_env == "ohos" {510            sources.extend(&[("__emutls_get_address", "emutls.c")]);511        }512513        // Optionally, link against a prebuilt llvm compiler-rt containing the builtins514        // library. Only the builtins library is required. On many platforms, this is515        // available as a library named libclang_rt.builtins.a.516        let link_against_prebuilt_rt = env::var_os("LLVM_COMPILER_RT_LIB").is_some();517518        // When compiling the C code we require the user to tell us where the519        // source code is, and this is largely done so when we're compiling as520        // part of rust-lang/rust we can use the same llvm-project repository as521        // rust-lang/rust.522        let root = match env::var_os("RUST_COMPILER_RT_ROOT") {523            Some(s) => PathBuf::from(s),524            // If a prebuild libcompiler-rt is provided, set a valid525            // path to simplify later logic. Nothing should be compiled.526            None if link_against_prebuilt_rt => PathBuf::new(),527            None => {528                panic!(529                    "RUST_COMPILER_RT_ROOT is not set. You may need to run \530                    `ci/download-compiler-rt.sh`."531                );532            }533        };534        if !link_against_prebuilt_rt && !root.exists() {535            panic!("RUST_COMPILER_RT_ROOT={} does not exist", root.display());536        }537538        // Support deterministic builds by remapping the __FILE__ prefix if the539        // compiler supports it.  This fixes the nondeterminism caused by the540        // use of that macro in lib/builtins/int_util.h in compiler-rt.541        build.flag_if_supported(&format!("-ffile-prefix-map={}=.", root.display()));542543        // Include out-of-line atomics for aarch64, which are all generated by supplying different544        // sets of flags to the same source file.545        // Note: Out-of-line aarch64 atomics are not supported by the msvc toolchain (#430) and546        // on uefi.547        let src_dir = root.join("lib/builtins");548        if cfg.target_arch == "aarch64" && cfg.target_env != "msvc" && cfg.target_os != "uefi" {549            // See below for why we're building these as separate libraries.550            build_aarch64_out_of_line_atomics_libraries(&src_dir, build, link_against_prebuilt_rt);551552            // Some run-time CPU feature detection is necessary, as well.553            let cpu_model_src = if src_dir.join("cpu_model.c").exists() {554                "cpu_model.c"555            } else {556                "cpu_model/aarch64.c"557            };558            sources.extend(&[("__aarch64_have_lse_atomics", cpu_model_src)]);559        }560561        let mut added_sources = HashSet::new();562        for (sym, src) in sources.map.iter() {563            let src = src_dir.join(src);564            if !link_against_prebuilt_rt && added_sources.insert(src.clone()) {565                build.file(&src);566                println!("cargo:rerun-if-changed={}", src.display());567            }568            println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);569        }570571        if link_against_prebuilt_rt {572            let rt_builtins_ext = PathBuf::from(env::var_os("LLVM_COMPILER_RT_LIB").unwrap());573            if !rt_builtins_ext.exists() {574                panic!(575                    "LLVM_COMPILER_RT_LIB={} does not exist",576                    rt_builtins_ext.display()577                );578            }579            if let Some(dir) = rt_builtins_ext.parent() {580                println!("cargo::rustc-link-search=native={}", dir.display());581            }582            if let Some(lib) = rt_builtins_ext.file_name() {583                println!(584                    "cargo::rustc-link-lib=static:+verbatim={}",585                    lib.to_str().unwrap()586                );587            }588        } else {589            build.compile("libcompiler-rt.a");590        }591    }592593    fn build_aarch64_out_of_line_atomics_libraries(594        builtins_dir: &Path,595        cfg: &mut cc::Build,596        link_against_prebuilt_rt: bool,597    ) {598        let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());599        let outlined_atomics_file = builtins_dir.join("aarch64").join("lse.S");600        if !link_against_prebuilt_rt {601            println!("cargo:rerun-if-changed={}", outlined_atomics_file.display());602        }603604        cfg.include(&builtins_dir);605606        for instruction_type in &["cas", "swp", "ldadd", "ldclr", "ldeor", "ldset"] {607            for size in &[1, 2, 4, 8, 16] {608                if *size == 16 && *instruction_type != "cas" {609                    continue;610                }611612                for (model_number, model_name) in613                    &[(1, "relax"), (2, "acq"), (3, "rel"), (4, "acq_rel")]614                {615                    let sym = format!("__aarch64_{}{}_{}", instruction_type, size, model_name);616                    println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);617618                    if link_against_prebuilt_rt {619                        continue;620                    }621622                    // The original compiler-rt build system compiles the same623                    // source file multiple times with different compiler624                    // options. Here we do something slightly different: we625                    // create multiple .S files with the proper #defines and626                    // then include the original file.627                    //628                    // This is needed because the cc crate doesn't allow us to629                    // override the name of object files and libtool requires630                    // all objects in an archive to have unique names.631                    let path =632                        out_dir.join(format!("lse_{}{}_{}.S", instruction_type, size, model_name));633                    let mut file = File::create(&path).unwrap();634                    writeln!(file, "#define L_{}", instruction_type).unwrap();635                    writeln!(file, "#define SIZE {}", size).unwrap();636                    writeln!(file, "#define MODEL {}", model_number).unwrap();637                    writeln!(638                        file,639                        "#include \"{}\"",640                        outlined_atomics_file.canonicalize().unwrap().display()641                    )642                    .unwrap();643                    drop(file);644                    cfg.file(path);645                }646            }647        }648    }649}

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.