use std::env;
fn main() {
println!("cargo:rerun-if-changed=build.rs");
let target = env::var("TARGET").unwrap();
let cwd = env::current_dir().unwrap();
println!("cargo:compiler-rt={}", cwd.join("compiler-rt").display());
println!("cargo:rustc-cfg=feature=\"unstable\"");
if target.contains("emscripten") {
return;
}
if target.contains("openbsd") {
println!("cargo:rustc-link-search=native=/usr/lib");
println!("cargo:rustc-link-lib=compiler_rt");
return;
}
if (target.contains("wasm") && !target.contains("wasi"))
|| (target.contains("sgx") && target.contains("fortanix"))
|| target.contains("-none")
|| target.contains("nvptx")
{
println!("cargo:rustc-cfg=feature=\"mem\"");
}
if target.contains("x86_64")
|| target.contains("i686")
|| target.contains("aarch64")
|| target.contains("bpf")
{
println!("cargo:rustc-cfg=feature=\"mem-unaligned\"");
}
let llvm_target = target.split('-').collect::<Vec<_>>();
if !cfg!(feature = "mangled-names") && cfg!(feature = "c") {
if !target.contains("wasm") && !target.contains("nvptx") && !target.starts_with("riscv") {
#[cfg(feature = "c")]
c::compile(&llvm_target, &target);
}
}
if llvm_target[0].starts_with("thumb") {
println!("cargo:rustc-cfg=thumb")
}
if llvm_target[0] == "thumbv6m" || llvm_target[0] == "thumbv8m.base" {
println!("cargo:rustc-cfg=thumb_1")
}
if llvm_target[0] == "armv4t"
|| llvm_target[0] == "armv5te"
|| target == "arm-linux-androideabi"
{
println!("cargo:rustc-cfg=kernel_user_helpers")
}
}
#[cfg(feature = "c")]
mod c {
extern crate cc;
use std::collections::{BTreeMap, HashSet};
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
struct Sources {
map: BTreeMap<&'static str, &'static str>,
}
impl Sources {
fn new() -> Sources {
Sources {
map: BTreeMap::new(),
}
}
fn extend(&mut self, sources: &[(&'static str, &'static str)]) {
for (symbol, src) in sources {
if src.contains("/") {
self.map.insert(symbol, src);
} else {
if !self.map.contains_key(symbol) {
self.map.insert(symbol, src);
}
}
}
}
fn remove(&mut self, symbols: &[&str]) {
for symbol in symbols {
self.map.remove(*symbol).unwrap();
}
}
}
pub fn compile(llvm_target: &[&str], target: &String) {
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap();
let mut consider_float_intrinsics = true;
let cfg = &mut cc::Build::new();
if target_arch == "aarch64" {
let cflags_key = String::from("CFLAGS_") + &(target.to_owned().replace("-", "_"));
if let Ok(cflags_value) = env::var(cflags_key) {
if cflags_value.contains("+nofp") || cflags_value.contains("+nosimd") {
consider_float_intrinsics = false;
}
}
}
cfg.warnings(false);
if target_env == "msvc" {
cfg.flag("/Zl");
cfg.define("__func__", Some("__FUNCTION__"));
} else {
cfg.flag("-fno-builtin");
cfg.flag("-fvisibility=hidden");
cfg.flag("-ffreestanding");
cfg.flag_if_supported("-fomit-frame-pointer");
cfg.define("VISIBILITY_HIDDEN", None);
}
let mut sources = Sources::new();
sources.extend(&[
("__absvdi2", "absvdi2.c"),
("__absvsi2", "absvsi2.c"),
("__addvdi3", "addvdi3.c"),
("__addvsi3", "addvsi3.c"),
("apple_versioning", "apple_versioning.c"),
("__clzdi2", "clzdi2.c"),
("__clzsi2", "clzsi2.c"),
("__cmpdi2", "cmpdi2.c"),
("__ctzdi2", "ctzdi2.c"),
("__ctzsi2", "ctzsi2.c"),
("__int_util", "int_util.c"),
("__mulvdi3", "mulvdi3.c"),
("__mulvsi3", "mulvsi3.c"),
("__negdi2", "negdi2.c"),
("__negvdi2", "negvdi2.c"),
("__negvsi2", "negvsi2.c"),
("__paritydi2", "paritydi2.c"),
("__paritysi2", "paritysi2.c"),
("__popcountdi2", "popcountdi2.c"),
("__popcountsi2", "popcountsi2.c"),
("__subvdi3", "subvdi3.c"),
("__subvsi3", "subvsi3.c"),
("__ucmpdi2", "ucmpdi2.c"),
]);
if consider_float_intrinsics {
sources.extend(&[
("__divdc3", "divdc3.c"),
("__divsc3", "divsc3.c"),
("__divxc3", "divxc3.c"),
("__extendhfsf2", "extendhfsf2.c"),
("__muldc3", "muldc3.c"),
("__mulsc3", "mulsc3.c"),
("__mulxc3", "mulxc3.c"),
("__negdf2", "negdf2.c"),
("__negsf2", "negsf2.c"),
("__powixf2", "powixf2.c"),
("__truncdfhf2", "truncdfhf2.c"),
("__truncsfhf2", "truncsfhf2.c"),
]);
}
if cfg!(feature = "rustbuild") {
sources.extend(&[("__ffsdi2", "ffsdi2.c")]);
}
if target_os != "ios" && (target_vendor != "apple" || target_arch != "x86") {
sources.extend(&[
("__absvti2", "absvti2.c"),
("__addvti3", "addvti3.c"),
("__clzti2", "clzti2.c"),
("__cmpti2", "cmpti2.c"),
("__ctzti2", "ctzti2.c"),
("__ffsti2", "ffsti2.c"),
("__mulvti3", "mulvti3.c"),
("__negti2", "negti2.c"),
("__parityti2", "parityti2.c"),
("__popcountti2", "popcountti2.c"),
("__subvti3", "subvti3.c"),
("__ucmpti2", "ucmpti2.c"),
]);
if consider_float_intrinsics {
sources.extend(&[("__negvti2", "negvti2.c")]);
}
}
if target_vendor == "apple" {
sources.extend(&[
("atomic_flag_clear", "atomic_flag_clear.c"),
("atomic_flag_clear_explicit", "atomic_flag_clear_explicit.c"),
("atomic_flag_test_and_set", "atomic_flag_test_and_set.c"),
(
"atomic_flag_test_and_set_explicit",
"atomic_flag_test_and_set_explicit.c",
),
("atomic_signal_fence", "atomic_signal_fence.c"),
("atomic_thread_fence", "atomic_thread_fence.c"),
]);
}
if target_env == "msvc" {
if target_arch == "x86_64" {
sources.extend(&[
("__floatdisf", "x86_64/floatdisf.c"),
("__floatdixf", "x86_64/floatdixf.c"),
]);
}
} else {
if target_os != "windows" {
if target_arch == "x86_64" {
sources.extend(&[
("__floatdisf", "x86_64/floatdisf.c"),
("__floatdixf", "x86_64/floatdixf.c"),
("__floatundidf", "x86_64/floatundidf.S"),
("__floatundisf", "x86_64/floatundisf.S"),
("__floatundixf", "x86_64/floatundixf.S"),
]);
}
}
if target_arch == "x86" {
sources.extend(&[
("__ashldi3", "i386/ashldi3.S"),
("__ashrdi3", "i386/ashrdi3.S"),
("__divdi3", "i386/divdi3.S"),
("__floatdidf", "i386/floatdidf.S"),
("__floatdisf", "i386/floatdisf.S"),
("__floatdixf", "i386/floatdixf.S"),
("__floatundidf", "i386/floatundidf.S"),
("__floatundisf", "i386/floatundisf.S"),
("__floatundixf", "i386/floatundixf.S"),
("__lshrdi3", "i386/lshrdi3.S"),
("__moddi3", "i386/moddi3.S"),
("__muldi3", "i386/muldi3.S"),
("__udivdi3", "i386/udivdi3.S"),
("__umoddi3", "i386/umoddi3.S"),
]);
}
}
if target_arch == "arm" && target_os != "ios" && target_env != "msvc" {
sources.extend(&[
("__aeabi_div0", "arm/aeabi_div0.c"),
("__aeabi_drsub", "arm/aeabi_drsub.c"),
("__aeabi_frsub", "arm/aeabi_frsub.c"),
("__bswapdi2", "arm/bswapdi2.S"),
("__bswapsi2", "arm/bswapsi2.S"),
("__clzdi2", "arm/clzdi2.S"),
("__clzsi2", "arm/clzsi2.S"),
("__divmodsi4", "arm/divmodsi4.S"),
("__divsi3", "arm/divsi3.S"),
("__modsi3", "arm/modsi3.S"),
("__switch16", "arm/switch16.S"),
("__switch32", "arm/switch32.S"),
("__switch8", "arm/switch8.S"),
("__switchu8", "arm/switchu8.S"),
("__sync_synchronize", "arm/sync_synchronize.S"),
("__udivmodsi4", "arm/udivmodsi4.S"),
("__udivsi3", "arm/udivsi3.S"),
("__umodsi3", "arm/umodsi3.S"),
]);
if target_os == "freebsd" {
sources.extend(&[("__clear_cache", "clear_cache.c")]);
}
if !llvm_target[0].starts_with("thumbeb") && !llvm_target[0].starts_with("armeb") {
sources.extend(&[
("__aeabi_cdcmp", "arm/aeabi_cdcmp.S"),
("__aeabi_cdcmpeq_check_nan", "arm/aeabi_cdcmpeq_check_nan.c"),
("__aeabi_cfcmp", "arm/aeabi_cfcmp.S"),
("__aeabi_cfcmpeq_check_nan", "arm/aeabi_cfcmpeq_check_nan.c"),
]);
}
}
if llvm_target[0] == "armv7" {
sources.extend(&[
("__sync_fetch_and_add_4", "arm/sync_fetch_and_add_4.S"),
("__sync_fetch_and_add_8", "arm/sync_fetch_and_add_8.S"),
("__sync_fetch_and_and_4", "arm/sync_fetch_and_and_4.S"),
("__sync_fetch_and_and_8", "arm/sync_fetch_and_and_8.S"),
("__sync_fetch_and_max_4", "arm/sync_fetch_and_max_4.S"),
("__sync_fetch_and_max_8", "arm/sync_fetch_and_max_8.S"),
("__sync_fetch_and_min_4", "arm/sync_fetch_and_min_4.S"),
("__sync_fetch_and_min_8", "arm/sync_fetch_and_min_8.S"),
("__sync_fetch_and_nand_4", "arm/sync_fetch_and_nand_4.S"),
("__sync_fetch_and_nand_8", "arm/sync_fetch_and_nand_8.S"),
("__sync_fetch_and_or_4", "arm/sync_fetch_and_or_4.S"),
("__sync_fetch_and_or_8", "arm/sync_fetch_and_or_8.S"),
("__sync_fetch_and_sub_4", "arm/sync_fetch_and_sub_4.S"),
("__sync_fetch_and_sub_8", "arm/sync_fetch_and_sub_8.S"),
("__sync_fetch_and_umax_4", "arm/sync_fetch_and_umax_4.S"),
("__sync_fetch_and_umax_8", "arm/sync_fetch_and_umax_8.S"),
("__sync_fetch_and_umin_4", "arm/sync_fetch_and_umin_4.S"),
("__sync_fetch_and_umin_8", "arm/sync_fetch_and_umin_8.S"),
("__sync_fetch_and_xor_4", "arm/sync_fetch_and_xor_4.S"),
("__sync_fetch_and_xor_8", "arm/sync_fetch_and_xor_8.S"),
]);
}
if llvm_target.last().unwrap().ends_with("eabihf") {
if !llvm_target[0].starts_with("thumbv7em")
&& !llvm_target[0].starts_with("thumbv8m.main")
{
sources.extend(&[
("__fixdfsivfp", "arm/fixdfsivfp.S"),
("__fixunsdfsivfp", "arm/fixunsdfsivfp.S"),
("__floatsidfvfp", "arm/floatsidfvfp.S"),
("__floatunssidfvfp", "arm/floatunssidfvfp.S"),
]);
}
sources.extend(&[
("__fixsfsivfp", "arm/fixsfsivfp.S"),
("__fixunssfsivfp", "arm/fixunssfsivfp.S"),
("__floatsisfvfp", "arm/floatsisfvfp.S"),
("__floatunssisfvfp", "arm/floatunssisfvfp.S"),
("__floatunssisfvfp", "arm/floatunssisfvfp.S"),
("__restore_vfp_d8_d15_regs", "arm/restore_vfp_d8_d15_regs.S"),
("__save_vfp_d8_d15_regs", "arm/save_vfp_d8_d15_regs.S"),
("__negdf2vfp", "arm/negdf2vfp.S"),
("__negsf2vfp", "arm/negsf2vfp.S"),
]);
}
if target_arch == "aarch64" && consider_float_intrinsics {
sources.extend(&[
("__comparetf2", "comparetf2.c"),
("__extenddftf2", "extenddftf2.c"),
("__extendsftf2", "extendsftf2.c"),
("__fixtfdi", "fixtfdi.c"),
("__fixtfsi", "fixtfsi.c"),
("__fixtfti", "fixtfti.c"),
("__fixunstfdi", "fixunstfdi.c"),
("__fixunstfsi", "fixunstfsi.c"),
("__fixunstfti", "fixunstfti.c"),
("__floatditf", "floatditf.c"),
("__floatsitf", "floatsitf.c"),
("__floatunditf", "floatunditf.c"),
("__floatunsitf", "floatunsitf.c"),
("__trunctfdf2", "trunctfdf2.c"),
("__trunctfsf2", "trunctfsf2.c"),
("__addtf3", "addtf3.c"),
("__multf3", "multf3.c"),
("__subtf3", "subtf3.c"),
("__divtf3", "divtf3.c"),
("__powitf2", "powitf2.c"),
("__fe_getround", "fp_mode.c"),
("__fe_raise_inexact", "fp_mode.c"),
]);
if target_os != "windows" {
sources.extend(&[("__multc3", "multc3.c")]);
}
}
if target_arch == "mips" {
sources.extend(&[("__bswapsi2", "bswapsi2.c")]);
}
if target_arch == "mips64" {
sources.extend(&[
("__extenddftf2", "extenddftf2.c"),
("__netf2", "comparetf2.c"),
("__addtf3", "addtf3.c"),
("__multf3", "multf3.c"),
("__subtf3", "subtf3.c"),
("__fixtfsi", "fixtfsi.c"),
("__floatsitf", "floatsitf.c"),
("__fixunstfsi", "fixunstfsi.c"),
("__floatunsitf", "floatunsitf.c"),
("__fe_getround", "fp_mode.c"),
("__divtf3", "divtf3.c"),
("__trunctfdf2", "trunctfdf2.c"),
]);
}
if llvm_target[0] == "thumbv6m" || llvm_target[0] == "thumbv8m.base" {
let mut to_remove = Vec::new();
for (k, v) in sources.map.iter() {
if v.ends_with(".S") {
to_remove.push(*k);
}
}
sources.remove(&to_remove);
sources.extend(&[("__clzdi2", "clzdi2.c"), ("__clzsi2", "clzsi2.c")])
}
if llvm_target[0] == "thumbv7m" || llvm_target[0] == "thumbv7em" {
sources.remove(&["__aeabi_cdcmp", "__aeabi_cfcmp"]);
}
let root = match env::var_os("RUST_COMPILER_RT_ROOT") {
Some(s) => PathBuf::from(s),
None => panic!("RUST_COMPILER_RT_ROOT is not set"),
};
if !root.exists() {
panic!("RUST_COMPILER_RT_ROOT={} does not exist", root.display());
}
cfg.flag_if_supported(&format!("-ffile-prefix-map={}=.", root.display()));
let src_dir = root.join("lib/builtins");
if target_arch == "aarch64" && target_env != "msvc" {
build_aarch64_out_of_line_atomics_libraries(&src_dir, cfg);
sources.extend(&[("__aarch64_have_lse_atomics", "cpu_model.c")]);
}
let mut added_sources = HashSet::new();
for (sym, src) in sources.map.iter() {
let src = src_dir.join(src);
if added_sources.insert(src.clone()) {
cfg.file(&src);
println!("cargo:rerun-if-changed={}", src.display());
}
println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
}
cfg.compile("libcompiler-rt.a");
}
fn build_aarch64_out_of_line_atomics_libraries(builtins_dir: &Path, cfg: &mut cc::Build) {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let outlined_atomics_file = builtins_dir.join("aarch64/lse.S");
println!("cargo:rerun-if-changed={}", outlined_atomics_file.display());
cfg.include(&builtins_dir);
for instruction_type in &["cas", "swp", "ldadd", "ldclr", "ldeor", "ldset"] {
for size in &[1, 2, 4, 8, 16] {
if *size == 16 && *instruction_type != "cas" {
continue;
}
for (model_number, model_name) in
&[(1, "relax"), (2, "acq"), (3, "rel"), (4, "acq_rel")]
{
let path =
out_dir.join(format!("lse_{}{}_{}.S", instruction_type, size, model_name));
let mut file = File::create(&path).unwrap();
writeln!(file, "#define L_{}", instruction_type).unwrap();
writeln!(file, "#define SIZE {}", size).unwrap();
writeln!(file, "#define MODEL {}", model_number).unwrap();
writeln!(
file,
"#include \"{}\"",
outlined_atomics_file.canonicalize().unwrap().display()
)
.unwrap();
drop(file);
cfg.file(path);
let sym = format!("__aarch64_{}{}_{}", instruction_type, size, model_name);
println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
}
}
}
}
}