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);