library/compiler-builtins/compiler-builtins/build.rs RUST 647 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    if cfg.manifest_dir.file_name().unwrap() == "builtins-shim" {16        println!("cargo::rerun-if-changed=../compiler-builtins/build.rs");17    } else {18        println!("cargo::rerun-if-changed=build.rs");19    }2021    println!("cargo::rerun-if-changed=../libm/configure.rs");2223    configure::emit(&cfg);24    configure_check_cfg();2526    let cwd = env::current_dir().unwrap();27    println!("cargo:compiler-rt={}", cwd.join("compiler-rt").display());2829    // Forcibly enable memory intrinsics on wasm & SGX as we don't have a libc to30    // provide them.31    if (cfg.target_triple.contains("wasm") && !cfg.target_triple.contains("wasi"))32        || (cfg.target_triple.contains("sgx") && cfg.target_triple.contains("fortanix"))33        || cfg.target_triple.contains("-none")34        || cfg.target_triple.contains("nvptx")35        || cfg.target_triple.contains("uefi")36        || cfg.target_triple.contains("xous")37    {38        println!("cargo:rustc-cfg=feature=\"mem\"");39    }4041    // These targets have hardware unaligned access support.42    let mem_unaligned = cfg.target_arch.contains("x86_64")43        || cfg.target_arch.contains("x86")44        || cfg.target_arch.contains("aarch64")45        || cfg.target_arch.contains("bpf");46    set_cfg("mem_unaligned", mem_unaligned);4748    // Only emit the ARM Linux atomic emulation on pre-ARMv6 architectures. This49    // includes the old androideabi. It is deprecated but it is available as a50    // rustc target (arm-linux-androideabi).51    let kernel_user_helpers = llvm_target[0] == "armv4t"52        || llvm_target[0] == "armv5te"53        || cfg.target_triple == "arm-linux-androideabi";54    set_cfg("kernel_user_helpers", kernel_user_helpers);5556    let mut maybe_build_c = true;5758    // Emscripten's runtime includes all the builtins59    if cfg.target_os == "emscripten" {60        maybe_build_c = false;61    }6263    // OpenBSD provides compiler_rt by default, use it instead of rebuilding it from source64    if cfg.target_os == "openbsd" {65        println!("cargo:rustc-link-search=native=/usr/lib");66        println!("cargo:rustc-link-lib=compiler_rt");67        maybe_build_c = false;68    }6970    // Everything is LLVM bitcode, not compatible with mixed C/Rust71    if cfg.target_arch.contains("nvptx") {72        maybe_build_c = false;73    }7475    // Build missing intrinsics from compiler-rt C source code. If we're76    // mangling names though we assume that we're also in test mode so we don't77    // build anything and we rely on the upstream implementation of compiler-rt78    // functions79    if cfg!(feature = "unmangled-names") && cfg!(feature = "c") && maybe_build_c {80        #[cfg(feature = "c")]81        c::compile(&cfg);82    }83}8485/// Emit directives for features we expect to support that aren't in `Cargo.toml`.86///87/// These are mostly cfg elements emitted by this `build.rs`.88fn configure_check_cfg() {89    // Functions where we can set the "optimized-c" flag90    const HAS_OPTIMIZED_C: &[&str] = &[91        "__ashldi3",92        "__ashlsi3",93        "__ashrdi3",94        "__ashrsi3",95        "__bswapsi2",96        "__bswapdi2",97        "__bswapti2",98        "__divdi3",99        "__divsi3",100        "__divmoddi4",101        "__divmodsi4",102        "__divmodsi4",103        "__divmodti4",104        "__lshrdi3",105        "__lshrsi3",106        "__moddi3",107        "__modsi3",108        "__muldi3",109        "__udivdi3",110        "__udivmoddi4",111        "__udivmodsi4",112        "__udivsi3",113        "__umoddi3",114        "__umodsi3",115    ];116117    // Build a list of all aarch64 atomic operation functions118    let mut aarch_atomic = Vec::new();119    for aarch_op in ["cas", "ldadd", "ldclr", "ldeor", "ldset", "swp"] {120        let op_sizes = if aarch_op == "cas" {121            [1, 2, 4, 8, 16].as_slice()122        } else {123            [1, 2, 4, 8].as_slice()124        };125126        for op_size in op_sizes {127            for ordering in ["relax", "acq", "rel", "acq_rel"] {128                aarch_atomic.push(format!("__aarch64_{aarch_op}{op_size}_{ordering}"));129            }130        }131    }132133    for fn_name in HAS_OPTIMIZED_C134        .iter()135        .copied()136        .chain(aarch_atomic.iter().map(|s| s.as_str()))137    {138        println!("cargo::rustc-check-cfg=cfg({fn_name}, values(\"optimized-c\"))",);139    }140141    // Rustc is unaware of sparc target features, but this does show up from142    // `rustc --print target-features --target sparc64-unknown-linux-gnu`.143    println!("cargo::rustc-check-cfg=cfg(target_feature, values(\"vis3\"))");144}145146#[cfg(feature = "c")]147mod c {148    use std::collections::{BTreeMap, HashSet};149    use std::env;150    use std::fs::{self, File};151    use std::io::Write;152    use std::path::{Path, PathBuf};153154    use super::Config;155156    struct Sources {157        // SYMBOL -> PATH TO SOURCE158        map: BTreeMap<&'static str, &'static str>,159    }160161    impl Sources {162        fn new() -> Sources {163            Sources {164                map: BTreeMap::new(),165            }166        }167168        fn extend(&mut self, sources: &[(&'static str, &'static str)]) {169            // NOTE Some intrinsics have both a generic implementation (e.g.170            // `floatdidf.c`) and an arch optimized implementation171            // (`x86_64/floatdidf.c`). In those cases, we keep the arch optimized172            // implementation and discard the generic implementation. If we don't173            // and keep both implementations, the linker will yell at us about174            // duplicate symbols!175            for (symbol, src) in sources {176                if src.contains("/") {177                    // Arch-optimized implementation (preferred)178                    self.map.insert(symbol, src);179                } else {180                    // Generic implementation181                    if !self.map.contains_key(symbol) {182                        self.map.insert(symbol, src);183                    }184                }185            }186        }187188        fn remove(&mut self, symbols: &[&str]) {189            for symbol in symbols {190                self.map.remove(*symbol).unwrap();191            }192        }193    }194195    /// Compile intrinsics from the compiler-rt C source code196    pub fn compile(cfg: &Config) {197        let llvm_target = &cfg.target_triple_split;198        let mut consider_float_intrinsics = true;199        let build = &mut cc::Build::new();200201        // AArch64 GCCs exit with an error condition when they encounter any kind of floating point202        // code if the `nofp` and/or `nosimd` compiler flags have been set.203        //204        // Therefore, evaluate if those flags are present and set a boolean that causes any205        // compiler-rt intrinsics that contain floating point source to be excluded for this target.206        if cfg.target_arch == "aarch64" {207            let cflags_key = String::from("CFLAGS_") + &(cfg.target_triple.replace("-", "_"));208            if let Ok(cflags_value) = env::var(cflags_key) {209                if cflags_value.contains("+nofp") || cflags_value.contains("+nosimd") {210                    consider_float_intrinsics = false;211                }212            }213        }214215        // `compiler-rt` requires `COMPILER_RT_HAS_FLOAT16` to be defined to make it use the216        // `_Float16` type for `f16` intrinsics. This shouldn't matter as all existing `f16`217        // intrinsics have been ported to Rust in `compiler-builtins` as C compilers don't218        // support `_Float16` on all targets (whereas Rust does). However, define the macro219        // anyway to prevent issues like rust#118813 and rust#123885 silently reoccuring if more220        // `f16` intrinsics get accidentally added here in the future.221        build.define("COMPILER_RT_HAS_FLOAT16", None);222223        build.warnings(false);224225        if cfg.target_env == "msvc" {226            // Don't pull in extra libraries on MSVC227            build.flag("/Zl");228229            // Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP230            build.define("__func__", Some("__FUNCTION__"));231        } else {232            // Turn off various features of gcc and such, mostly copying233            // compiler-rt's build system already234            build.flag("-fno-builtin");235            build.flag("-fvisibility=hidden");236            build.flag("-ffreestanding");237            // Avoid the following warning appearing once **per file**:238            // clang: warning: optimization flag '-fomit-frame-pointer' is not supported for target 'armv7' [-Wignored-optimization-argument]239            //240            // Note that compiler-rt's build system also checks241            //242            // `check_cxx_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG)`243            //244            // in https://github.com/rust-lang/compiler-rt/blob/c8fbcb3/cmake/config-ix.cmake#L19.245            build.flag_if_supported("-fomit-frame-pointer");246            build.define("VISIBILITY_HIDDEN", None);247248            if let "aarch64" | "arm64ec" = cfg.target_arch.as_str() {249                // FIXME(llvm20): Older GCCs on A64 fail to build with250                // -Werror=implicit-function-declaration due to a compiler-rt bug.251                // With a newer LLVM we should be able to enable the flag everywhere.252                // https://github.com/llvm/llvm-project/commit/8aa9d6206ce55bdaaf422839c351fbd63f033b89253            } else {254                // Avoid implicitly creating references to undefined functions255                build.flag("-Werror=implicit-function-declaration");256            }257        }258259        // int_util.c tries to include stdlib.h if `_WIN32` is defined,260        // which it is when compiling UEFI targets with clang. This is261        // at odds with compiling with `-ffreestanding`, as the header262        // may be incompatible or not present. Create a minimal stub263        // header to use instead.264        if cfg.target_os == "uefi" {265            let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());266            let include_dir = out_dir.join("include");267            if !include_dir.exists() {268                fs::create_dir(&include_dir).unwrap();269            }270            fs::write(include_dir.join("stdlib.h"), "#include <stddef.h>").unwrap();271            build.flag(&format!("-I{}", include_dir.to_str().unwrap()));272        }273274        let mut sources = Sources::new();275        sources.extend(&[276            ("__absvdi2", "absvdi2.c"),277            ("__absvsi2", "absvsi2.c"),278            ("__addvdi3", "addvdi3.c"),279            ("__addvsi3", "addvsi3.c"),280            ("__cmpdi2", "cmpdi2.c"),281            ("__int_util", "int_util.c"),282            ("__mulvdi3", "mulvdi3.c"),283            ("__mulvsi3", "mulvsi3.c"),284            ("__negdi2", "negdi2.c"),285            ("__negvdi2", "negvdi2.c"),286            ("__negvsi2", "negvsi2.c"),287            ("__paritydi2", "paritydi2.c"),288            ("__paritysi2", "paritysi2.c"),289            ("__popcountdi2", "popcountdi2.c"),290            ("__popcountsi2", "popcountsi2.c"),291            ("__subvdi3", "subvdi3.c"),292            ("__subvsi3", "subvsi3.c"),293            ("__ucmpdi2", "ucmpdi2.c"),294        ]);295296        if consider_float_intrinsics {297            sources.extend(&[298                ("__divdc3", "divdc3.c"),299                ("__divsc3", "divsc3.c"),300                ("__muldc3", "muldc3.c"),301                ("__mulsc3", "mulsc3.c"),302                ("__negdf2", "negdf2.c"),303                ("__negsf2", "negsf2.c"),304            ]);305        }306307        // On iOS and 32-bit OSX these are all just empty intrinsics, no need to308        // include them.309        if cfg.target_vendor != "apple" || cfg.target_arch != "x86" {310            sources.extend(&[311                ("__absvti2", "absvti2.c"),312                ("__addvti3", "addvti3.c"),313                ("__cmpti2", "cmpti2.c"),314                ("__ffsti2", "ffsti2.c"),315                ("__mulvti3", "mulvti3.c"),316                ("__negti2", "negti2.c"),317                ("__parityti2", "parityti2.c"),318                ("__popcountti2", "popcountti2.c"),319                ("__subvti3", "subvti3.c"),320                ("__ucmpti2", "ucmpti2.c"),321            ]);322323            if consider_float_intrinsics {324                sources.extend(&[("__negvti2", "negvti2.c")]);325            }326        }327328        if cfg.target_vendor == "apple" {329            sources.extend(&[330                ("atomic_flag_clear", "atomic_flag_clear.c"),331                ("atomic_flag_clear_explicit", "atomic_flag_clear_explicit.c"),332                ("atomic_flag_test_and_set", "atomic_flag_test_and_set.c"),333                (334                    "atomic_flag_test_and_set_explicit",335                    "atomic_flag_test_and_set_explicit.c",336                ),337                ("atomic_signal_fence", "atomic_signal_fence.c"),338                ("atomic_thread_fence", "atomic_thread_fence.c"),339            ]);340        }341342        if cfg.target_env != "msvc" {343            if cfg.target_arch == "x86" {344                sources.extend(&[345                    ("__ashldi3", "i386/ashldi3.S"),346                    ("__ashrdi3", "i386/ashrdi3.S"),347                    ("__divdi3", "i386/divdi3.S"),348                    ("__lshrdi3", "i386/lshrdi3.S"),349                    ("__moddi3", "i386/moddi3.S"),350                    ("__muldi3", "i386/muldi3.S"),351                    ("__udivdi3", "i386/udivdi3.S"),352                    ("__umoddi3", "i386/umoddi3.S"),353                ]);354            }355        }356357        if cfg.target_arch == "arm" && cfg.target_vendor != "apple" && cfg.target_env != "msvc" {358            sources.extend(&[359                ("__aeabi_div0", "arm/aeabi_div0.c"),360                ("__aeabi_drsub", "arm/aeabi_drsub.c"),361                ("__aeabi_frsub", "arm/aeabi_frsub.c"),362                ("__bswapdi2", "arm/bswapdi2.S"),363                ("__bswapsi2", "arm/bswapsi2.S"),364                ("__divmodsi4", "arm/divmodsi4.S"),365                ("__divsi3", "arm/divsi3.S"),366                ("__modsi3", "arm/modsi3.S"),367                ("__switch16", "arm/switch16.S"),368                ("__switch32", "arm/switch32.S"),369                ("__switch8", "arm/switch8.S"),370                ("__switchu8", "arm/switchu8.S"),371                ("__sync_synchronize", "arm/sync_synchronize.S"),372                ("__udivmodsi4", "arm/udivmodsi4.S"),373                ("__udivsi3", "arm/udivsi3.S"),374                ("__umodsi3", "arm/umodsi3.S"),375            ]);376377            if cfg.target_os == "freebsd" {378                sources.extend(&[("__clear_cache", "clear_cache.c")]);379            }380381            // First of all aeabi_cdcmp and aeabi_cfcmp are never called by LLVM.382            // Second are little-endian only, so build fail on big-endian targets.383            // Temporally workaround: exclude these files for big-endian targets.384            if !llvm_target[0].starts_with("thumbeb") && !llvm_target[0].starts_with("armeb") {385                sources.extend(&[386                    ("__aeabi_cdcmp", "arm/aeabi_cdcmp.S"),387                    ("__aeabi_cdcmpeq_check_nan", "arm/aeabi_cdcmpeq_check_nan.c"),388                    ("__aeabi_cfcmp", "arm/aeabi_cfcmp.S"),389                    ("__aeabi_cfcmpeq_check_nan", "arm/aeabi_cfcmpeq_check_nan.c"),390                ]);391            }392        }393394        if llvm_target[0] == "armv7" {395            sources.extend(&[396                ("__sync_fetch_and_add_4", "arm/sync_fetch_and_add_4.S"),397                ("__sync_fetch_and_add_8", "arm/sync_fetch_and_add_8.S"),398                ("__sync_fetch_and_and_4", "arm/sync_fetch_and_and_4.S"),399                ("__sync_fetch_and_and_8", "arm/sync_fetch_and_and_8.S"),400                ("__sync_fetch_and_max_4", "arm/sync_fetch_and_max_4.S"),401                ("__sync_fetch_and_max_8", "arm/sync_fetch_and_max_8.S"),402                ("__sync_fetch_and_min_4", "arm/sync_fetch_and_min_4.S"),403                ("__sync_fetch_and_min_8", "arm/sync_fetch_and_min_8.S"),404                ("__sync_fetch_and_nand_4", "arm/sync_fetch_and_nand_4.S"),405                ("__sync_fetch_and_nand_8", "arm/sync_fetch_and_nand_8.S"),406                ("__sync_fetch_and_or_4", "arm/sync_fetch_and_or_4.S"),407                ("__sync_fetch_and_or_8", "arm/sync_fetch_and_or_8.S"),408                ("__sync_fetch_and_sub_4", "arm/sync_fetch_and_sub_4.S"),409                ("__sync_fetch_and_sub_8", "arm/sync_fetch_and_sub_8.S"),410                ("__sync_fetch_and_umax_4", "arm/sync_fetch_and_umax_4.S"),411                ("__sync_fetch_and_umax_8", "arm/sync_fetch_and_umax_8.S"),412                ("__sync_fetch_and_umin_4", "arm/sync_fetch_and_umin_4.S"),413                ("__sync_fetch_and_umin_8", "arm/sync_fetch_and_umin_8.S"),414                ("__sync_fetch_and_xor_4", "arm/sync_fetch_and_xor_4.S"),415                ("__sync_fetch_and_xor_8", "arm/sync_fetch_and_xor_8.S"),416            ]);417        }418419        if llvm_target.last().unwrap().ends_with("eabihf") {420            if !llvm_target[0].starts_with("thumbv7em")421                && !llvm_target[0].starts_with("thumbv8m.main")422            {423                // The FPU option chosen for these architectures in cc-rs, ie:424                //     -mfpu=fpv4-sp-d16 for thumbv7em425                //     -mfpu=fpv5-sp-d16 for thumbv8m.main426                // do not support double precision floating points conversions so the files427                // that include such instructions are not included for these targets.428                sources.extend(&[429                    ("__fixdfsivfp", "arm/fixdfsivfp.S"),430                    ("__fixunsdfsivfp", "arm/fixunsdfsivfp.S"),431                    ("__floatsidfvfp", "arm/floatsidfvfp.S"),432                    ("__floatunssidfvfp", "arm/floatunssidfvfp.S"),433                ]);434            }435436            sources.extend(&[437                ("__fixsfsivfp", "arm/fixsfsivfp.S"),438                ("__fixunssfsivfp", "arm/fixunssfsivfp.S"),439                ("__floatsisfvfp", "arm/floatsisfvfp.S"),440                ("__floatunssisfvfp", "arm/floatunssisfvfp.S"),441                ("__floatunssisfvfp", "arm/floatunssisfvfp.S"),442                ("__restore_vfp_d8_d15_regs", "arm/restore_vfp_d8_d15_regs.S"),443                ("__save_vfp_d8_d15_regs", "arm/save_vfp_d8_d15_regs.S"),444                ("__negdf2vfp", "arm/negdf2vfp.S"),445                ("__negsf2vfp", "arm/negsf2vfp.S"),446            ]);447        }448449        if (cfg.target_arch == "aarch64" || cfg.target_arch == "arm64ec")450            && consider_float_intrinsics451        {452            sources.extend(&[453                ("__fe_getround", "fp_mode.c"),454                ("__fe_raise_inexact", "fp_mode.c"),455            ]);456457            if cfg.target_os != "windows" && cfg.target_os != "cygwin" {458                sources.extend(&[("__multc3", "multc3.c")]);459            }460        }461462        if cfg.target_arch == "mips" || cfg.target_arch == "riscv32" || cfg.target_arch == "riscv64"463        {464            sources.extend(&[("__bswapsi2", "bswapsi2.c")]);465        }466467        if cfg.target_arch == "mips64" {468            sources.extend(&[("__fe_getround", "fp_mode.c")]);469        }470471        if cfg.target_arch == "loongarch64" {472            sources.extend(&[("__fe_getround", "fp_mode.c")]);473        }474475        // Remove the assembly implementations that won't compile for the target476        if llvm_target[0] == "thumbv6m"477            || llvm_target[0] == "thumbv8m.base"478            || cfg.target_os == "uefi"479        {480            let mut to_remove = Vec::new();481            for (k, v) in sources.map.iter() {482                if v.ends_with(".S") {483                    to_remove.push(*k);484                }485            }486            sources.remove(&to_remove);487        }488489        if llvm_target[0] == "thumbv7m" || llvm_target[0] == "thumbv7em" {490            sources.remove(&["__aeabi_cdcmp", "__aeabi_cfcmp"]);491        }492493        // Android and Cygwin uses emulated TLS so we need a runtime support function.494        if cfg.target_os == "android" || cfg.target_os == "cygwin" {495            sources.extend(&[("__emutls_get_address", "emutls.c")]);496        }497498        // Work around a bug in the NDK headers (fixed in499        // https://r.android.com/2038949 which will be released in a future500        // NDK version) by providing a definition of LONG_BIT.501        if cfg.target_os == "android" {502            build.define("LONG_BIT", "(8 * sizeof(long))");503        }504505        // OpenHarmony also uses emulated TLS.506        if cfg.target_env == "ohos" {507            sources.extend(&[("__emutls_get_address", "emutls.c")]);508        }509510        // Optionally, link against a prebuilt llvm compiler-rt containing the builtins511        // library. Only the builtins library is required. On many platforms, this is512        // available as a library named libclang_rt.builtins.a.513        let link_against_prebuilt_rt = env::var_os("LLVM_COMPILER_RT_LIB").is_some();514515        // When compiling the C code we require the user to tell us where the516        // source code is, and this is largely done so when we're compiling as517        // part of rust-lang/rust we can use the same llvm-project repository as518        // rust-lang/rust.519        let root = match env::var_os("RUST_COMPILER_RT_ROOT") {520            Some(s) => PathBuf::from(s),521            // If a prebuild libcompiler-rt is provided, set a valid522            // path to simplify later logic. Nothing should be compiled.523            None if link_against_prebuilt_rt => PathBuf::new(),524            None => {525                panic!(526                    "RUST_COMPILER_RT_ROOT is not set. You may need to run \527                    `ci/download-compiler-rt.sh`."528                );529            }530        };531        if !link_against_prebuilt_rt && !root.exists() {532            panic!("RUST_COMPILER_RT_ROOT={} does not exist", root.display());533        }534535        // Support deterministic builds by remapping the __FILE__ prefix if the536        // compiler supports it.  This fixes the nondeterminism caused by the537        // use of that macro in lib/builtins/int_util.h in compiler-rt.538        build.flag_if_supported(&format!("-ffile-prefix-map={}=.", root.display()));539540        // Include out-of-line atomics for aarch64, which are all generated by supplying different541        // sets of flags to the same source file.542        // Note: Out-of-line aarch64 atomics are not supported by the msvc toolchain (#430) and543        // on uefi.544        let src_dir = root.join("lib/builtins");545        if cfg.target_arch == "aarch64" && cfg.target_env != "msvc" && cfg.target_os != "uefi" {546            // See below for why we're building these as separate libraries.547            build_aarch64_out_of_line_atomics_libraries(&src_dir, build, link_against_prebuilt_rt);548549            // Some run-time CPU feature detection is necessary, as well.550            let cpu_model_src = if src_dir.join("cpu_model.c").exists() {551                "cpu_model.c"552            } else {553                "cpu_model/aarch64.c"554            };555            sources.extend(&[("__aarch64_have_lse_atomics", cpu_model_src)]);556        }557558        let mut added_sources = HashSet::new();559        for (sym, src) in sources.map.iter() {560            let src = src_dir.join(src);561            if !link_against_prebuilt_rt && added_sources.insert(src.clone()) {562                build.file(&src);563                println!("cargo:rerun-if-changed={}", src.display());564            }565            println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);566        }567568        if link_against_prebuilt_rt {569            let rt_builtins_ext = PathBuf::from(env::var_os("LLVM_COMPILER_RT_LIB").unwrap());570            if !rt_builtins_ext.exists() {571                panic!(572                    "LLVM_COMPILER_RT_LIB={} does not exist",573                    rt_builtins_ext.display()574                );575            }576            if let Some(dir) = rt_builtins_ext.parent() {577                println!("cargo::rustc-link-search=native={}", dir.display());578            }579            if let Some(lib) = rt_builtins_ext.file_name() {580                println!(581                    "cargo::rustc-link-lib=static:+verbatim={}",582                    lib.to_str().unwrap()583                );584            }585        } else {586            build.compile("libcompiler-rt.a");587        }588    }589590    fn build_aarch64_out_of_line_atomics_libraries(591        builtins_dir: &Path,592        cfg: &mut cc::Build,593        link_against_prebuilt_rt: bool,594    ) {595        let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());596        let outlined_atomics_file = builtins_dir.join("aarch64").join("lse.S");597        if !link_against_prebuilt_rt {598            println!("cargo:rerun-if-changed={}", outlined_atomics_file.display());599        }600601        cfg.include(&builtins_dir);602603        for instruction_type in &["cas", "swp", "ldadd", "ldclr", "ldeor", "ldset"] {604            for size in &[1, 2, 4, 8, 16] {605                if *size == 16 && *instruction_type != "cas" {606                    continue;607                }608609                for (model_number, model_name) in610                    &[(1, "relax"), (2, "acq"), (3, "rel"), (4, "acq_rel")]611                {612                    let sym = format!("__aarch64_{}{}_{}", instruction_type, size, model_name);613                    println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);614615                    if link_against_prebuilt_rt {616                        continue;617                    }618619                    // The original compiler-rt build system compiles the same620                    // source file multiple times with different compiler621                    // options. Here we do something slightly different: we622                    // create multiple .S files with the proper #defines and623                    // then include the original file.624                    //625                    // This is needed because the cc crate doesn't allow us to626                    // override the name of object files and libtool requires627                    // all objects in an archive to have unique names.628                    let path =629                        out_dir.join(format!("lse_{}{}_{}.S", instruction_type, size, model_name));630                    let mut file = File::create(&path).unwrap();631                    writeln!(file, "#define L_{}", instruction_type).unwrap();632                    writeln!(file, "#define SIZE {}", size).unwrap();633                    writeln!(file, "#define MODEL {}", model_number).unwrap();634                    writeln!(635                        file,636                        "#include \"{}\"",637                        outlined_atomics_file.canonicalize().unwrap().display()638                    )639                    .unwrap();640                    drop(file);641                    cfg.file(path);642                }643            }644        }645    }646}

Code quality findings 46

Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
if cfg.manifest_dir.file_name().unwrap() == "builtins-shim" {
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
let cwd = env::current_dir().unwrap();
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
let kernel_user_helpers = llvm_target[0] == "armv4t"
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
|| llvm_target[0] == "armv5te"
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
for aarch_op in ["cas", "ldadd", "ldclr", "ldeor", "ldset", "swp"] {
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
for ordering in ["relax", "acq", "rel", "acq_rel"] {
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
self.map.remove(*symbol).unwrap();
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
fs::create_dir(&include_dir).unwrap();
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
fs::write(include_dir.join("stdlib.h"), "#include <stddef.h>").unwrap();
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
build.flag(&format!("-I{}", include_dir.to_str().unwrap()));
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
if !llvm_target[0].starts_with("thumbeb") && !llvm_target[0].starts_with("armeb") {
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
if llvm_target[0] == "armv7" {
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
if llvm_target.last().unwrap().ends_with("eabihf") {
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
if !llvm_target[0].starts_with("thumbv7em")
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
&& !llvm_target[0].starts_with("thumbv8m.main")
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
if llvm_target[0] == "thumbv6m"
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
|| llvm_target[0] == "thumbv8m.base"
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
if llvm_target[0] == "thumbv7m" || llvm_target[0] == "thumbv7em" {
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
let rt_builtins_ext = PathBuf::from(env::var_os("LLVM_COMPILER_RT_LIB").unwrap());
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
lib.to_str().unwrap()
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
let mut file = File::create(&path).unwrap();
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
writeln!(file, "#define L_{}", instruction_type).unwrap();
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
writeln!(file, "#define SIZE {}", size).unwrap();
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
writeln!(file, "#define MODEL {}", model_number).unwrap();
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
outlined_atomics_file.canonicalize().unwrap().display()
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
.unwrap();
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("cargo::rerun-if-changed=../compiler-builtins/build.rs");
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("cargo::rerun-if-changed=build.rs");
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("cargo::rerun-if-changed=../libm/configure.rs");
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("cargo:compiler-rt={}", cwd.join("compiler-rt").display());
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("cargo:rustc-cfg=feature=\"mem\"");
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("cargo:rustc-link-search=native=/usr/lib");
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("cargo:rustc-link-lib=compiler_rt");
Performance Info: Calling .push() repeatedly inside a loop without prior capacity reservation can lead to multiple reallocations. Consider using `Vec::with_capacity(n)` or `vec.reserve(n)` if the approximate number of elements is known.
info performance push-without-reserve
aarch_atomic.push(format!("__aarch64_{aarch_op}{op_size}_{ordering}"));
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("cargo::rustc-check-cfg=cfg({fn_name}, values(\"optimized-c\"))",);
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("cargo::rustc-check-cfg=cfg(target_feature, values(\"vis3\"))");
Performance Info: Calling .push() repeatedly inside a loop without prior capacity reservation can lead to multiple reallocations. Consider using `Vec::with_capacity(n)` or `vec.reserve(n)` if the approximate number of elements is known.
info performance push-without-reserve
to_remove.push(*k);
Performance Info: Frequent cloning, especially of Strings, Vecs, or other heap-allocated types inside loops, can be expensive. Consider using references/borrowing where possible.
info performance clone-in-loop
if !link_against_prebuilt_rt && added_sources.insert(src.clone()) {
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("cargo:rerun-if-changed={}", src.display());
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("cargo::rustc-link-search=native={}", dir.display());
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!(
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("cargo:rerun-if-changed={}", outlined_atomics_file.display());
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);

Get this view in your editor

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