Remove the need for #[cfg] in #[use_c_shim_if]

This commit tweaks the implementation of the synthetic
`#[use_c_shim_if]` attribute, renaming it to
`#[maybe_use_optimized_c_shim]` in the process. This no longer requires
specifying a `#[cfg]` clause indicating when the optimized intrinsic
should be used, but rather this is inferred and printed from the build
script.

The build script will now print out appropriate `#[cfg]` directives for
rustc to indicate what intrinsics it's compiling. This should remove the
need for us to keep the build script and the source in sync, but rather
the build script can simply take care of everything.
master
Alex Crichton 2019-05-15 12:57:36 -07:00
parent 6178e2c611
commit cf98161da7
9 changed files with 198 additions and 222 deletions

336
build.rs
View File

@ -49,7 +49,6 @@ fn main() {
if !target.contains("wasm32") && !target.contains("nvptx") && !target.starts_with("riscv") { if !target.contains("wasm32") && !target.contains("nvptx") && !target.starts_with("riscv") {
#[cfg(feature = "c")] #[cfg(feature = "c")]
c::compile(&llvm_target); c::compile(&llvm_target);
println!("cargo:rustc-cfg=use_c");
} }
} }
@ -91,15 +90,14 @@ mod c {
} }
} }
fn extend(&mut self, sources: &[&'static str]) { fn extend(&mut self, sources: &[(&'static str, &'static str)]) {
// NOTE Some intrinsics have both a generic implementation (e.g. // NOTE Some intrinsics have both a generic implementation (e.g.
// `floatdidf.c`) and an arch optimized implementation // `floatdidf.c`) and an arch optimized implementation
// (`x86_64/floatdidf.c`). In those cases, we keep the arch optimized // (`x86_64/floatdidf.c`). In those cases, we keep the arch optimized
// implementation and discard the generic implementation. If we don't // implementation and discard the generic implementation. If we don't
// and keep both implementations, the linker will yell at us about // and keep both implementations, the linker will yell at us about
// duplicate symbols! // duplicate symbols!
for &src in sources { for (symbol, src) in sources {
let symbol = Path::new(src).file_stem().unwrap().to_str().unwrap();
if src.contains("/") { if src.contains("/") {
// Arch-optimized implementation (preferred) // Arch-optimized implementation (preferred)
self.map.insert(symbol, src); self.map.insert(symbol, src);
@ -155,42 +153,42 @@ mod c {
let mut sources = Sources::new(); let mut sources = Sources::new();
sources.extend(&[ sources.extend(&[
"absvdi2.c", ("__absvdi2", "absvdi2.c"),
"absvsi2.c", ("__absvsi2", "absvsi2.c"),
"addvdi3.c", ("__addvdi3", "addvdi3.c"),
"addvsi3.c", ("__addvsi3", "addvsi3.c"),
"apple_versioning.c", ("apple_versioning", "apple_versioning.c"),
"clzdi2.c", ("__clzdi2", "clzdi2.c"),
"clzsi2.c", ("__clzsi2", "clzsi2.c"),
"cmpdi2.c", ("__cmpdi2", "cmpdi2.c"),
"ctzdi2.c", ("__ctzdi2", "ctzdi2.c"),
"ctzsi2.c", ("__ctzsi2", "ctzsi2.c"),
"divdc3.c", ("__divdc3", "divdc3.c"),
"divsc3.c", ("__divsc3", "divsc3.c"),
"divxc3.c", ("__divxc3", "divxc3.c"),
"extendhfsf2.c", ("__extendhfsf2", "extendhfsf2.c"),
"int_util.c", ("__int_util", "int_util.c"),
"muldc3.c", ("__muldc3", "muldc3.c"),
"mulsc3.c", ("__mulsc3", "mulsc3.c"),
"mulvdi3.c", ("__mulvdi3", "mulvdi3.c"),
"mulvsi3.c", ("__mulvsi3", "mulvsi3.c"),
"mulxc3.c", ("__mulxc3", "mulxc3.c"),
"negdf2.c", ("__negdf2", "negdf2.c"),
"negdi2.c", ("__negdi2", "negdi2.c"),
"negsf2.c", ("__negsf2", "negsf2.c"),
"negvdi2.c", ("__negvdi2", "negvdi2.c"),
"negvsi2.c", ("__negvsi2", "negvsi2.c"),
"paritydi2.c", ("__paritydi2", "paritydi2.c"),
"paritysi2.c", ("__paritysi2", "paritysi2.c"),
"popcountdi2.c", ("__popcountdi2", "popcountdi2.c"),
"popcountsi2.c", ("__popcountsi2", "popcountsi2.c"),
"powixf2.c", ("__powixf2", "powixf2.c"),
"subvdi3.c", ("__subvdi3", "subvdi3.c"),
"subvsi3.c", ("__subvsi3", "subvsi3.c"),
"truncdfhf2.c", ("__truncdfhf2", "truncdfhf2.c"),
"truncdfsf2.c", ("__truncdfsf2", "truncdfsf2.c"),
"truncsfhf2.c", ("__truncsfhf2", "truncsfhf2.c"),
"ucmpdi2.c", ("__ucmpdi2", "ucmpdi2.c"),
]); ]);
// When compiling in rustbuild (the rust-lang/rust repo) this library // When compiling in rustbuild (the rust-lang/rust repo) this library
@ -198,43 +196,49 @@ mod c {
// need, so include a few more that aren't typically needed by // need, so include a few more that aren't typically needed by
// LLVM/Rust. // LLVM/Rust.
if cfg!(feature = "rustbuild") { if cfg!(feature = "rustbuild") {
sources.extend(&["ffsdi2.c"]); sources.extend(&[("__ffsdi2", "ffsdi2.c")]);
} }
// On iOS and 32-bit OSX these are all just empty intrinsics, no need to // On iOS and 32-bit OSX these are all just empty intrinsics, no need to
// include them. // include them.
if target_os != "ios" && (target_vendor != "apple" || target_arch != "x86") { if target_os != "ios" && (target_vendor != "apple" || target_arch != "x86") {
sources.extend(&[ sources.extend(&[
"absvti2.c", ("__absvti2", "absvti2.c"),
"addvti3.c", ("__addvti3", "addvti3.c"),
"clzti2.c", ("__clzti2", "clzti2.c"),
"cmpti2.c", ("__cmpti2", "cmpti2.c"),
"ctzti2.c", ("__ctzti2", "ctzti2.c"),
"ffsti2.c", ("__ffsti2", "ffsti2.c"),
"mulvti3.c", ("__mulvti3", "mulvti3.c"),
"negti2.c", ("__negti2", "negti2.c"),
"negvti2.c", ("__negvti2", "negvti2.c"),
"parityti2.c", ("__parityti2", "parityti2.c"),
"popcountti2.c", ("__popcountti2", "popcountti2.c"),
"subvti3.c", ("__subvti3", "subvti3.c"),
"ucmpti2.c", ("__ucmpti2", "ucmpti2.c"),
]); ]);
} }
if target_vendor == "apple" { if target_vendor == "apple" {
sources.extend(&[ sources.extend(&[
"atomic_flag_clear.c", ("atomic_flag_clear", "atomic_flag_clear.c"),
"atomic_flag_clear_explicit.c", ("atomic_flag_clear_explicit", "atomic_flag_clear_explicit.c"),
"atomic_flag_test_and_set.c", ("atomic_flag_test_and_set", "atomic_flag_test_and_set.c"),
"atomic_flag_test_and_set_explicit.c", (
"atomic_signal_fence.c", "atomic_flag_test_and_set_explicit",
"atomic_thread_fence.c", "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_env == "msvc" {
if target_arch == "x86_64" { if target_arch == "x86_64" {
sources.extend(&["x86_64/floatdisf.c", "x86_64/floatdixf.c"]); sources.extend(&[
("__floatdisf", "x86_64/floatdisf.c"),
("__floatdixf", "x86_64/floatdixf.c"),
]);
} }
} else { } else {
// None of these seem to be used on x86_64 windows, and they've all // None of these seem to be used on x86_64 windows, and they've all
@ -242,59 +246,59 @@ mod c {
if target_os != "windows" { if target_os != "windows" {
if target_arch == "x86_64" { if target_arch == "x86_64" {
sources.extend(&[ sources.extend(&[
"x86_64/floatdisf.c", ("__floatdisf", "x86_64/floatdisf.c"),
"x86_64/floatdixf.c", ("__floatdixf", "x86_64/floatdixf.c"),
"x86_64/floatundidf.S", ("__floatundidf", "x86_64/floatundidf.S"),
"x86_64/floatundisf.S", ("__floatundisf", "x86_64/floatundisf.S"),
"x86_64/floatundixf.S", ("__floatundixf", "x86_64/floatundixf.S"),
]); ]);
} }
} }
if target_arch == "x86" { if target_arch == "x86" {
sources.extend(&[ sources.extend(&[
"i386/ashldi3.S", ("__ashldi3", "i386/ashldi3.S"),
"i386/ashrdi3.S", ("__ashrdi3", "i386/ashrdi3.S"),
"i386/divdi3.S", ("__divdi3", "i386/divdi3.S"),
"i386/floatdidf.S", ("__floatdidf", "i386/floatdidf.S"),
"i386/floatdisf.S", ("__floatdisf", "i386/floatdisf.S"),
"i386/floatdixf.S", ("__floatdixf", "i386/floatdixf.S"),
"i386/floatundidf.S", ("__floatundidf", "i386/floatundidf.S"),
"i386/floatundisf.S", ("__floatundisf", "i386/floatundisf.S"),
"i386/floatundixf.S", ("__floatundixf", "i386/floatundixf.S"),
"i386/lshrdi3.S", ("__lshrdi3", "i386/lshrdi3.S"),
"i386/moddi3.S", ("__moddi3", "i386/moddi3.S"),
"i386/muldi3.S", ("__muldi3", "i386/muldi3.S"),
"i386/udivdi3.S", ("__udivdi3", "i386/udivdi3.S"),
"i386/umoddi3.S", ("__umoddi3", "i386/umoddi3.S"),
]); ]);
} }
} }
if target_arch == "arm" && target_os != "ios" && target_env != "msvc" { if target_arch == "arm" && target_os != "ios" && target_env != "msvc" {
sources.extend(&[ sources.extend(&[
"arm/aeabi_div0.c", ("__aeabi_div0", "arm/aeabi_div0.c"),
"arm/aeabi_drsub.c", ("__aeabi_drsub", "arm/aeabi_drsub.c"),
"arm/aeabi_frsub.c", ("__aeabi_frsub", "arm/aeabi_frsub.c"),
"arm/bswapdi2.S", ("__bswapdi2", "arm/bswapdi2.S"),
"arm/bswapsi2.S", ("__bswapsi2", "arm/bswapsi2.S"),
"arm/clzdi2.S", ("__clzdi2", "arm/clzdi2.S"),
"arm/clzsi2.S", ("__clzsi2", "arm/clzsi2.S"),
"arm/divmodsi4.S", ("__divmodsi4", "arm/divmodsi4.S"),
"arm/divsi3.S", ("__divsi3", "arm/divsi3.S"),
"arm/modsi3.S", ("__modsi3", "arm/modsi3.S"),
"arm/switch16.S", ("__switch16", "arm/switch16.S"),
"arm/switch32.S", ("__switch32", "arm/switch32.S"),
"arm/switch8.S", ("__switch8", "arm/switch8.S"),
"arm/switchu8.S", ("__switchu8", "arm/switchu8.S"),
"arm/sync_synchronize.S", ("__sync_synchronize", "arm/sync_synchronize.S"),
"arm/udivmodsi4.S", ("__udivmodsi4", "arm/udivmodsi4.S"),
"arm/udivsi3.S", ("__udivsi3", "arm/udivsi3.S"),
"arm/umodsi3.S", ("__umodsi3", "arm/umodsi3.S"),
]); ]);
if target_os == "freebsd" { if target_os == "freebsd" {
sources.extend(&["clear_cache.c"]); sources.extend(&[("__clear_cache", "clear_cache.c")]);
} }
// First of all aeabi_cdcmp and aeabi_cfcmp are never called by LLVM. // First of all aeabi_cdcmp and aeabi_cfcmp are never called by LLVM.
@ -302,36 +306,36 @@ mod c {
// Temporally workaround: exclude these files for big-endian targets. // Temporally workaround: exclude these files for big-endian targets.
if !llvm_target[0].starts_with("thumbeb") && !llvm_target[0].starts_with("armeb") { if !llvm_target[0].starts_with("thumbeb") && !llvm_target[0].starts_with("armeb") {
sources.extend(&[ sources.extend(&[
"arm/aeabi_cdcmp.S", ("__aeabi_cdcmp", "arm/aeabi_cdcmp.S"),
"arm/aeabi_cdcmpeq_check_nan.c", ("__aeabi_cdcmpeq_check_nan", "arm/aeabi_cdcmpeq_check_nan.c"),
"arm/aeabi_cfcmp.S", ("__aeabi_cfcmp", "arm/aeabi_cfcmp.S"),
"arm/aeabi_cfcmpeq_check_nan.c", ("__aeabi_cfcmpeq_check_nan", "arm/aeabi_cfcmpeq_check_nan.c"),
]); ]);
} }
} }
if llvm_target[0] == "armv7" { if llvm_target[0] == "armv7" {
sources.extend(&[ sources.extend(&[
"arm/sync_fetch_and_add_4.S", ("__sync_fetch_and_add_4", "arm/sync_fetch_and_add_4.S"),
"arm/sync_fetch_and_add_8.S", ("__sync_fetch_and_add_8", "arm/sync_fetch_and_add_8.S"),
"arm/sync_fetch_and_and_4.S", ("__sync_fetch_and_and_4", "arm/sync_fetch_and_and_4.S"),
"arm/sync_fetch_and_and_8.S", ("__sync_fetch_and_and_8", "arm/sync_fetch_and_and_8.S"),
"arm/sync_fetch_and_max_4.S", ("__sync_fetch_and_max_4", "arm/sync_fetch_and_max_4.S"),
"arm/sync_fetch_and_max_8.S", ("__sync_fetch_and_max_8", "arm/sync_fetch_and_max_8.S"),
"arm/sync_fetch_and_min_4.S", ("__sync_fetch_and_min_4", "arm/sync_fetch_and_min_4.S"),
"arm/sync_fetch_and_min_8.S", ("__sync_fetch_and_min_8", "arm/sync_fetch_and_min_8.S"),
"arm/sync_fetch_and_nand_4.S", ("__sync_fetch_and_nand_4", "arm/sync_fetch_and_nand_4.S"),
"arm/sync_fetch_and_nand_8.S", ("__sync_fetch_and_nand_8", "arm/sync_fetch_and_nand_8.S"),
"arm/sync_fetch_and_or_4.S", ("__sync_fetch_and_or_4", "arm/sync_fetch_and_or_4.S"),
"arm/sync_fetch_and_or_8.S", ("__sync_fetch_and_or_8", "arm/sync_fetch_and_or_8.S"),
"arm/sync_fetch_and_sub_4.S", ("__sync_fetch_and_sub_4", "arm/sync_fetch_and_sub_4.S"),
"arm/sync_fetch_and_sub_8.S", ("__sync_fetch_and_sub_8", "arm/sync_fetch_and_sub_8.S"),
"arm/sync_fetch_and_umax_4.S", ("__sync_fetch_and_umax_4", "arm/sync_fetch_and_umax_4.S"),
"arm/sync_fetch_and_umax_8.S", ("__sync_fetch_and_umax_8", "arm/sync_fetch_and_umax_8.S"),
"arm/sync_fetch_and_umin_4.S", ("__sync_fetch_and_umin_4", "arm/sync_fetch_and_umin_4.S"),
"arm/sync_fetch_and_umin_8.S", ("__sync_fetch_and_umin_8", "arm/sync_fetch_and_umin_8.S"),
"arm/sync_fetch_and_xor_4.S", ("__sync_fetch_and_xor_4", "arm/sync_fetch_and_xor_4.S"),
"arm/sync_fetch_and_xor_8.S", ("__sync_fetch_and_xor_8", "arm/sync_fetch_and_xor_8.S"),
]); ]);
} }
@ -345,73 +349,66 @@ mod c {
// do not support double precision floating points conversions so the files // do not support double precision floating points conversions so the files
// that include such instructions are not included for these targets. // that include such instructions are not included for these targets.
sources.extend(&[ sources.extend(&[
"arm/fixdfsivfp.S", ("__fixdfsivfp", "arm/fixdfsivfp.S"),
"arm/fixunsdfsivfp.S", ("__fixunsdfsivfp", "arm/fixunsdfsivfp.S"),
"arm/floatsidfvfp.S", ("__floatsidfvfp", "arm/floatsidfvfp.S"),
"arm/floatunssidfvfp.S", ("__floatunssidfvfp", "arm/floatunssidfvfp.S"),
]); ]);
} }
sources.extend(&[ sources.extend(&[
"arm/fixsfsivfp.S", ("__fixsfsivfp", "arm/fixsfsivfp.S"),
"arm/fixunssfsivfp.S", ("__fixunssfsivfp", "arm/fixunssfsivfp.S"),
"arm/floatsisfvfp.S", ("__floatsisfvfp", "arm/floatsisfvfp.S"),
"arm/floatunssisfvfp.S", ("__floatunssisfvfp", "arm/floatunssisfvfp.S"),
"arm/floatunssisfvfp.S", ("__floatunssisfvfp", "arm/floatunssisfvfp.S"),
"arm/restore_vfp_d8_d15_regs.S", ("__restore_vfp_d8_d15_regs", "arm/restore_vfp_d8_d15_regs.S"),
"arm/save_vfp_d8_d15_regs.S", ("__save_vfp_d8_d15_regs", "arm/save_vfp_d8_d15_regs.S"),
"arm/negdf2vfp.S", ("__negdf2vfp", "arm/negdf2vfp.S"),
"arm/negsf2vfp.S", ("__negsf2vfp", "arm/negsf2vfp.S"),
]); ]);
} }
if target_arch == "aarch64" { if target_arch == "aarch64" {
sources.extend(&[ sources.extend(&[
"comparetf2.c", ("__comparetf2", "comparetf2.c"),
"extenddftf2.c", ("__extenddftf2", "extenddftf2.c"),
"extendsftf2.c", ("__extendsftf2", "extendsftf2.c"),
"fixtfdi.c", ("__fixtfdi", "fixtfdi.c"),
"fixtfsi.c", ("__fixtfsi", "fixtfsi.c"),
"fixtfti.c", ("__fixtfti", "fixtfti.c"),
"fixunstfdi.c", ("__fixunstfdi", "fixunstfdi.c"),
"fixunstfsi.c", ("__fixunstfsi", "fixunstfsi.c"),
"fixunstfti.c", ("__fixunstfti", "fixunstfti.c"),
"floatditf.c", ("__floatditf", "floatditf.c"),
"floatsitf.c", ("__floatsitf", "floatsitf.c"),
"floatunditf.c", ("__floatunditf", "floatunditf.c"),
"floatunsitf.c", ("__floatunsitf", "floatunsitf.c"),
"trunctfdf2.c", ("__trunctfdf2", "trunctfdf2.c"),
"trunctfsf2.c", ("__trunctfsf2", "trunctfsf2.c"),
]); ]);
if target_os != "windows" { if target_os != "windows" {
sources.extend(&["multc3.c"]); sources.extend(&[("__multc3", "multc3.c")]);
} }
} }
// Remove the assembly implementations that won't compile for the target // Remove the assembly implementations that won't compile for the target
if llvm_target[0] == "thumbv6m" || llvm_target[0] == "thumbv8m.base" { if llvm_target[0] == "thumbv6m" || llvm_target[0] == "thumbv8m.base" {
sources.remove(&[ let mut to_remove = Vec::new();
"clzdi2", for (k, v) in sources.map.iter() {
"clzsi2", if v.ends_with(".S") {
"divmodsi4", to_remove.push(*k);
"divsi3", }
"modsi3", }
"switch16", sources.remove(&to_remove);
"switch32",
"switch8",
"switchu8",
"udivmodsi4",
"udivsi3",
"umodsi3",
]);
// But use some generic implementations where possible // But use some generic implementations where possible
sources.extend(&["clzdi2.c", "clzsi2.c"]) sources.extend(&[("__clzdi2", "clzdi2.c"), ("__clzsi2", "clzsi2.c")])
} }
if llvm_target[0] == "thumbv7m" || llvm_target[0] == "thumbv7em" { if llvm_target[0] == "thumbv7m" || llvm_target[0] == "thumbv7em" {
sources.remove(&["aeabi_cdcmp", "aeabi_cfcmp"]); sources.remove(&["__aeabi_cdcmp", "__aeabi_cfcmp"]);
} }
// When compiling in rustbuild (the rust-lang/rust repo) this build // When compiling in rustbuild (the rust-lang/rust repo) this build
@ -423,10 +420,11 @@ mod c {
}; };
let src_dir = root.join("compiler-rt/lib/builtins"); let src_dir = root.join("compiler-rt/lib/builtins");
for src in sources.map.values() { for (sym, src) in sources.map.iter() {
let src = src_dir.join(src); let src = src_dir.join(src);
cfg.file(&src); cfg.file(&src);
println!("cargo:rerun-if-changed={}", src.display()); println!("cargo:rerun-if-changed={}", src.display());
println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
} }
cfg.compile("libcompiler-rt.a"); cfg.compile("libcompiler-rt.a");

View File

@ -1,5 +1,6 @@
set -ex set -ex
export CARGO_INCREMENTAL=0
cargo=cargo cargo=cargo
# Test our implementation # Test our implementation

View File

@ -87,11 +87,7 @@ intrinsics! {
int_to_float!(i, i32, f64) int_to_float!(i, i32, f64)
} }
#[use_c_shim_if(any( #[maybe_use_optimized_c_shim]
all(target_arch = "x86", not(target_env = "msvc")),
all(target_arch = "x86_64", not(windows)),
all(target_arch = "x86_64", target_env = "msvc"),
))]
#[arm_aeabi_alias = __aeabi_l2f] #[arm_aeabi_alias = __aeabi_l2f]
pub extern "C" fn __floatdisf(i: i64) -> f32 { pub extern "C" fn __floatdisf(i: i64) -> f32 {
// On x86_64 LLVM will use native instructions for this conversion, we // On x86_64 LLVM will use native instructions for this conversion, we
@ -103,7 +99,7 @@ intrinsics! {
} }
} }
#[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] #[maybe_use_optimized_c_shim]
#[arm_aeabi_alias = __aeabi_l2d] #[arm_aeabi_alias = __aeabi_l2d]
pub extern "C" fn __floatdidf(i: i64) -> f64 { pub extern "C" fn __floatdidf(i: i64) -> f64 {
// On x86_64 LLVM will use native instructions for this conversion, we // On x86_64 LLVM will use native instructions for this conversion, we
@ -135,19 +131,13 @@ intrinsics! {
int_to_float!(i, u32, f64) int_to_float!(i, u32, f64)
} }
#[use_c_shim_if(any( #[maybe_use_optimized_c_shim]
all(target_arch = "x86", not(target_env = "msvc")),
all(target_arch = "x86_64", not(windows)),
))]
#[arm_aeabi_alias = __aeabi_ul2f] #[arm_aeabi_alias = __aeabi_ul2f]
pub extern "C" fn __floatundisf(i: u64) -> f32 { pub extern "C" fn __floatundisf(i: u64) -> f32 {
int_to_float!(i, u64, f32) int_to_float!(i, u64, f32)
} }
#[use_c_shim_if(any( #[maybe_use_optimized_c_shim]
all(target_arch = "x86", not(target_env = "msvc")),
all(target_arch = "x86_64", not(windows)),
))]
#[arm_aeabi_alias = __aeabi_ul2d] #[arm_aeabi_alias = __aeabi_ul2d]
pub extern "C" fn __floatundidf(i: u64) -> f64 { pub extern "C" fn __floatundidf(i: u64) -> f64 {
int_to_float!(i, u64, f64) int_to_float!(i, u64, f64)

View File

@ -302,7 +302,7 @@ impl_wide_int!(u32, u64, 32);
impl_wide_int!(u64, u128, 64); impl_wide_int!(u64, u128, 64);
intrinsics! { intrinsics! {
#[use_c_shim_if(/* always if C compilation is enabled */)] #[maybe_use_optimized_c_shim]
#[cfg(any( #[cfg(any(
target_pointer_width = "16", target_pointer_width = "16",
target_pointer_width = "32", target_pointer_width = "32",

View File

@ -84,7 +84,7 @@ trait UMulo: Int {
impl UMulo for u128 {} impl UMulo for u128 {}
intrinsics! { intrinsics! {
#[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] #[maybe_use_optimized_c_shim]
#[arm_aeabi_alias = __aeabi_lmul] #[arm_aeabi_alias = __aeabi_lmul]
pub extern "C" fn __muldi3(a: u64, b: u64) -> u64 { pub extern "C" fn __muldi3(a: u64, b: u64) -> u64 {
a.mul(b) a.mul(b)

View File

@ -58,13 +58,13 @@ impl Divmod for i32 {}
impl Divmod for i64 {} impl Divmod for i64 {}
intrinsics! { intrinsics! {
#[use_c_shim_if(all(target_arch = "arm", not(target_os = "ios"), not(thumb_1)))] #[maybe_use_optimized_c_shim]
#[arm_aeabi_alias = __aeabi_idiv] #[arm_aeabi_alias = __aeabi_idiv]
pub extern "C" fn __divsi3(a: i32, b: i32) -> i32 { pub extern "C" fn __divsi3(a: i32, b: i32) -> i32 {
a.div(b) a.div(b)
} }
#[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] #[maybe_use_optimized_c_shim]
pub extern "C" fn __divdi3(a: i64, b: i64) -> i64 { pub extern "C" fn __divdi3(a: i64, b: i64) -> i64 {
a.div(b) a.div(b)
} }
@ -74,15 +74,12 @@ intrinsics! {
a.div(b) a.div(b)
} }
#[use_c_shim_if(all(target_arch = "arm", #[maybe_use_optimized_c_shim]
not(target_os = "ios"),
not(target_env = "msvc"),
not(thumb_1)))]
pub extern "C" fn __modsi3(a: i32, b: i32) -> i32 { pub extern "C" fn __modsi3(a: i32, b: i32) -> i32 {
a.mod_(b) a.mod_(b)
} }
#[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] #[maybe_use_optimized_c_shim]
pub extern "C" fn __moddi3(a: i64, b: i64) -> i64 { pub extern "C" fn __moddi3(a: i64, b: i64) -> i64 {
a.mod_(b) a.mod_(b)
} }
@ -92,8 +89,7 @@ intrinsics! {
a.mod_(b) a.mod_(b)
} }
#[use_c_shim_if(all(target_arch = "arm", not(target_env = "msvc"), #[maybe_use_optimized_c_shim]
not(target_os = "ios"), not(thumb_1)))]
pub extern "C" fn __divmodsi4(a: i32, b: i32, rem: &mut i32) -> i32 { pub extern "C" fn __divmodsi4(a: i32, b: i32, rem: &mut i32) -> i32 {
a.divmod(b, rem, |a, b| __divsi3(a, b)) a.divmod(b, rem, |a, b| __divsi3(a, b))
} }

View File

@ -74,7 +74,7 @@ impl Lshr for u64 {}
impl Lshr for u128 {} impl Lshr for u128 {}
intrinsics! { intrinsics! {
#[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] #[maybe_use_optimized_c_shim]
#[arm_aeabi_alias = __aeabi_llsl] #[arm_aeabi_alias = __aeabi_llsl]
pub extern "C" fn __ashldi3(a: u64, b: u32) -> u64 { pub extern "C" fn __ashldi3(a: u64, b: u32) -> u64 {
a.ashl(b) a.ashl(b)
@ -84,7 +84,7 @@ intrinsics! {
a.ashl(b) a.ashl(b)
} }
#[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] #[maybe_use_optimized_c_shim]
#[arm_aeabi_alias = __aeabi_lasr] #[arm_aeabi_alias = __aeabi_lasr]
pub extern "C" fn __ashrdi3(a: i64, b: u32) -> i64 { pub extern "C" fn __ashrdi3(a: i64, b: u32) -> i64 {
a.ashr(b) a.ashr(b)
@ -94,7 +94,7 @@ intrinsics! {
a.ashr(b) a.ashr(b)
} }
#[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] #[maybe_use_optimized_c_shim]
#[arm_aeabi_alias = __aeabi_llsr] #[arm_aeabi_alias = __aeabi_llsr]
pub extern "C" fn __lshrdi3(a: u64, b: u32) -> u64 { pub extern "C" fn __lshrdi3(a: u64, b: u32) -> u64 {
a.lshr(b) a.lshr(b)

View File

@ -152,9 +152,7 @@ macro_rules! udivmod_inner {
} }
intrinsics! { intrinsics! {
#[use_c_shim_if(all(target_arch = "arm", #[maybe_use_optimized_c_shim]
not(target_os = "ios"),
not(thumb_1)))]
#[arm_aeabi_alias = __aeabi_uidiv] #[arm_aeabi_alias = __aeabi_uidiv]
/// Returns `n / d` /// Returns `n / d`
pub extern "C" fn __udivsi3(n: u32, d: u32) -> u32 { pub extern "C" fn __udivsi3(n: u32, d: u32) -> u32 {
@ -212,20 +210,14 @@ intrinsics! {
(q << 1) | carry (q << 1) | carry
} }
#[use_c_shim_if(all(target_arch = "arm", #[maybe_use_optimized_c_shim]
not(target_os = "ios"),
not(target_env = "msvc"),
not(thumb_1)))]
/// Returns `n % d` /// Returns `n % d`
pub extern "C" fn __umodsi3(n: u32, d: u32) -> u32 { pub extern "C" fn __umodsi3(n: u32, d: u32) -> u32 {
let q = __udivsi3(n, d); let q = __udivsi3(n, d);
n - q * d n - q * d
} }
#[use_c_shim_if(all(target_arch = "arm", #[maybe_use_optimized_c_shim]
not(target_os = "ios"),
not(target_env = "msvc"),
not(thumb_1)))]
/// Returns `n / d` and sets `*rem = n % d` /// Returns `n / d` and sets `*rem = n % d`
pub extern "C" fn __udivmodsi4(n: u32, d: u32, rem: Option<&mut u32>) -> u32 { pub extern "C" fn __udivmodsi4(n: u32, d: u32, rem: Option<&mut u32>) -> u32 {
let q = __udivsi3(n, d); let q = __udivsi3(n, d);
@ -235,13 +227,13 @@ intrinsics! {
q q
} }
#[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] #[maybe_use_optimized_c_shim]
/// Returns `n / d` /// Returns `n / d`
pub extern "C" fn __udivdi3(n: u64, d: u64) -> u64 { pub extern "C" fn __udivdi3(n: u64, d: u64) -> u64 {
__udivmoddi4(n, d, None) __udivmoddi4(n, d, None)
} }
#[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] #[maybe_use_optimized_c_shim]
/// Returns `n % d` /// Returns `n % d`
pub extern "C" fn __umoddi3(n: u64, d: u64) -> u64 { pub extern "C" fn __umoddi3(n: u64, d: u64) -> u64 {
let mut rem = 0; let mut rem = 0;

View File

@ -30,8 +30,8 @@
/// ///
/// A quick overview of attributes supported right now are: /// A quick overview of attributes supported right now are:
/// ///
/// * `use_c_shim_if` - takes a #[cfg] directive and falls back to the /// * `maybe_use_optimized_c_shim` - indicates that the Rust implementation is
/// C-compiled version if `use_c` is specified. /// ignored if an optimized C version was compiled.
/// * `aapcs_on_arm` - forces the ABI of the function to be `"aapcs"` on ARM and /// * `aapcs_on_arm` - forces the ABI of the function to be `"aapcs"` on ARM and
/// the specified ABI everywhere else. /// the specified ABI everywhere else.
/// * `unadjusted_on_win64` - like `aapcs_on_arm` this switches to the /// * `unadjusted_on_win64` - like `aapcs_on_arm` this switches to the
@ -51,15 +51,14 @@ macro_rules! intrinsics {
// to the architecture-specific versions which should be more optimized. The // to the architecture-specific versions which should be more optimized. The
// purpose of this macro is to easily allow specifying this. // purpose of this macro is to easily allow specifying this.
// //
// The argument to `use_c_shim_if` is a `#[cfg]` directive which, when true, // The `#[maybe_use_optimized_c_shim]` attribute indicates that this
// will cause this crate's exported version of `$name` to just redirect to // intrinsic may have an optimized C version. In these situations the build
// the C implementation. No symbol named `$name` will be in the object file // script, if the C code is enabled and compiled, will emit a cfg directive
// for this crate itself. // to get passed to rustc for our compilation. If that cfg is set we skip
// // the Rust implementation, but if the attribute is not enabled then we
// When the `#[cfg]` directive is false, or when the `c` feature is // compile in the Rust implementation.
// disabled, the provided implementation is used instead.
( (
#[use_c_shim_if($($cfg_clause:tt)*)] #[maybe_use_optimized_c_shim]
$(#[$($attr:tt)*])* $(#[$($attr:tt)*])*
pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty {
$($body:tt)* $($body:tt)*
@ -68,7 +67,7 @@ macro_rules! intrinsics {
$($rest:tt)* $($rest:tt)*
) => ( ) => (
#[cfg(all(use_c, $($cfg_clause)*))] #[cfg($name = "optimized-c")]
pub extern $abi fn $name( $($argname: $ty),* ) -> $ret { pub extern $abi fn $name( $($argname: $ty),* ) -> $ret {
extern $abi { extern $abi {
fn $name($($argname: $ty),*) -> $ret; fn $name($($argname: $ty),*) -> $ret;
@ -78,7 +77,7 @@ macro_rules! intrinsics {
} }
} }
#[cfg(not(all(use_c, $($cfg_clause)*)))] #[cfg(not($name = "optimized-c"))]
intrinsics! { intrinsics! {
$(#[$($attr)*])* $(#[$($attr)*])*
pub extern $abi fn $name( $($argname: $ty),* ) -> $ret { pub extern $abi fn $name( $($argname: $ty),* ) -> $ret {