Skip to content

Commit 1211d02

Browse files
authored
Merge pull request #652 from tgross35/control-f16-f128-feature
2 parents 9dcc46a + c6f95d7 commit 1211d02

File tree

17 files changed

+263
-237
lines changed

17 files changed

+263
-237
lines changed

build.rs

+122-42
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,97 @@
11
use std::{collections::BTreeMap, env, path::PathBuf, sync::atomic::Ordering};
22

3+
#[allow(dead_code)]
4+
struct Target {
5+
triple: String,
6+
os: String,
7+
arch: String,
8+
vendor: String,
9+
env: String,
10+
pointer_width: u8,
11+
little_endian: bool,
12+
features: Vec<String>,
13+
}
14+
15+
impl Target {
16+
fn from_env() -> Self {
17+
let little_endian = match env::var("CARGO_CFG_TARGET_ENDIAN").unwrap().as_str() {
18+
"little" => true,
19+
"big" => false,
20+
x => panic!("unknown endian {x}"),
21+
};
22+
23+
Self {
24+
triple: env::var("TARGET").unwrap(),
25+
os: env::var("CARGO_CFG_TARGET_OS").unwrap(),
26+
arch: env::var("CARGO_CFG_TARGET_ARCH").unwrap(),
27+
vendor: env::var("CARGO_CFG_TARGET_VENDOR").unwrap(),
28+
env: env::var("CARGO_CFG_TARGET_ENV").unwrap(),
29+
pointer_width: env::var("CARGO_CFG_TARGET_POINTER_WIDTH")
30+
.unwrap()
31+
.parse()
32+
.unwrap(),
33+
little_endian,
34+
features: env::var("CARGO_CFG_TARGET_FEATURE")
35+
.unwrap_or_default()
36+
.split(",")
37+
.map(ToOwned::to_owned)
38+
.collect(),
39+
}
40+
}
41+
}
42+
343
fn main() {
444
println!("cargo:rerun-if-changed=build.rs");
5-
configure_check_cfg();
6-
7-
let target = env::var("TARGET").unwrap();
45+
let target = Target::from_env();
846
let cwd = env::current_dir().unwrap();
947

48+
configure_check_cfg();
49+
configure_f16_f128(&target);
50+
1051
println!("cargo:compiler-rt={}", cwd.join("compiler-rt").display());
1152

1253
// Activate libm's unstable features to make full use of Nightly.
1354
println!("cargo::rustc-check-cfg=cfg(feature, values(\"unstable\"))");
1455
println!("cargo:rustc-cfg=feature=\"unstable\"");
1556

1657
// Emscripten's runtime includes all the builtins
17-
if target.contains("emscripten") {
58+
if target.env == "emscripten" {
1859
return;
1960
}
2061

2162
// OpenBSD provides compiler_rt by default, use it instead of rebuilding it from source
22-
if target.contains("openbsd") {
63+
if target.os == "openbsd" {
2364
println!("cargo:rustc-link-search=native=/usr/lib");
2465
println!("cargo:rustc-link-lib=compiler_rt");
2566
return;
2667
}
2768

2869
// Forcibly enable memory intrinsics on wasm & SGX as we don't have a libc to
2970
// provide them.
30-
if (target.contains("wasm") && !target.contains("wasi"))
31-
|| (target.contains("sgx") && target.contains("fortanix"))
32-
|| target.contains("-none")
33-
|| target.contains("nvptx")
34-
|| target.contains("uefi")
35-
|| target.contains("xous")
71+
if (target.triple.contains("wasm") && !target.triple.contains("wasi"))
72+
|| (target.triple.contains("sgx") && target.triple.contains("fortanix"))
73+
|| target.triple.contains("-none")
74+
|| target.triple.contains("nvptx")
75+
|| target.triple.contains("uefi")
76+
|| target.triple.contains("xous")
3677
{
3778
println!("cargo:rustc-cfg=feature=\"mem\"");
3879
}
3980

4081
// These targets have hardware unaligned access support.
4182
println!("cargo::rustc-check-cfg=cfg(feature, values(\"mem-unaligned\"))");
42-
if target.contains("x86_64")
43-
|| target.contains("i686")
44-
|| target.contains("aarch64")
45-
|| target.contains("bpf")
83+
if target.arch.contains("x86_64")
84+
|| target.arch.contains("i686")
85+
|| target.arch.contains("aarch64")
86+
|| target.arch.contains("bpf")
4687
{
4788
println!("cargo:rustc-cfg=feature=\"mem-unaligned\"");
4889
}
4990

5091
// NOTE we are going to assume that llvm-target, what determines our codegen option, matches the
5192
// target triple. This is usually correct for our built-in targets but can break in presence of
5293
// custom targets, which can have arbitrary names.
53-
let llvm_target = target.split('-').collect::<Vec<_>>();
94+
let llvm_target = target.triple.split('-').collect::<Vec<_>>();
5495

5596
// Build missing intrinsics from compiler-rt C source code. If we're
5697
// mangling names though we assume that we're also in test mode so we don't
@@ -60,7 +101,7 @@ fn main() {
60101
// Don't use a C compiler for these targets:
61102
//
62103
// * nvptx - everything is bitcode, not compatible with mixed C/Rust
63-
if !target.contains("nvptx") {
104+
if !target.arch.contains("nvptx") {
64105
#[cfg(feature = "c")]
65106
c::compile(&llvm_target, &target);
66107
}
@@ -86,7 +127,7 @@ fn main() {
86127
println!("cargo::rustc-check-cfg=cfg(kernel_user_helpers)");
87128
if llvm_target[0] == "armv4t"
88129
|| llvm_target[0] == "armv5te"
89-
|| target == "arm-linux-androideabi"
130+
|| target.triple == "arm-linux-androideabi"
90131
{
91132
println!("cargo:rustc-cfg=kernel_user_helpers")
92133
}
@@ -219,6 +260,47 @@ fn configure_check_cfg() {
219260
println!("cargo::rustc-check-cfg=cfg(assert_no_panic)");
220261
}
221262

263+
/// Configure whether or not `f16` and `f128` support should be enabled.
264+
fn configure_f16_f128(target: &Target) {
265+
// Set whether or not `f16` and `f128` are supported at a basic level by LLVM. This only means
266+
// that the backend will not crash when using these types. This does not mean that the
267+
// backend does the right thing, or that the platform doesn't have ABI bugs.
268+
//
269+
// We do this here rather than in `rust-lang/rust` because configuring via cargo features is
270+
// not straightforward.
271+
//
272+
// Original source of this list:
273+
// <https://github.com/rust-lang/compiler-builtins/pull/652#issuecomment-2266151350>
274+
let (f16_ok, f128_ok) = match target.arch.as_str() {
275+
// `f16` and `f128` both crash <https://github.com/llvm/llvm-project/issues/94434>
276+
"arm64ec" => (false, false),
277+
// `f16` crashes <https://github.com/llvm/llvm-project/issues/50374>
278+
"s390x" => (false, true),
279+
// `f128` crashes <https://github.com/llvm/llvm-project/issues/96432>
280+
"mips64" | "mips64r6" => (true, false),
281+
// `f128` crashes <https://github.com/llvm/llvm-project/issues/101545>
282+
"powerpc64" if &target.os == "aix" => (true, false),
283+
// `f128` crashes <https://github.com/llvm/llvm-project/issues/41838>
284+
"sparc" | "sparcv9" => (true, false),
285+
// Most everything else works as of LLVM 19
286+
_ => (true, true),
287+
};
288+
289+
// If the feature is set, disable these types.
290+
let disable_both = env::var_os("CARGO_FEATURE_NO_F16_F128").is_some();
291+
292+
println!("cargo::rustc-check-cfg=cfg(f16_enabled)");
293+
println!("cargo::rustc-check-cfg=cfg(f128_enabled)");
294+
295+
if f16_ok && !disable_both {
296+
println!("cargo::rustc-cfg=f16_enabled");
297+
}
298+
299+
if f128_ok && !disable_both {
300+
println!("cargo::rustc-cfg=f128_enabled");
301+
}
302+
}
303+
222304
#[cfg(feature = "c")]
223305
mod c {
224306
use std::collections::{BTreeMap, HashSet};
@@ -227,6 +309,8 @@ mod c {
227309
use std::io::Write;
228310
use std::path::{Path, PathBuf};
229311

312+
use super::Target;
313+
230314
struct Sources {
231315
// SYMBOL -> PATH TO SOURCE
232316
map: BTreeMap<&'static str, &'static str>,
@@ -267,11 +351,7 @@ mod c {
267351
}
268352

269353
/// Compile intrinsics from the compiler-rt C source code
270-
pub fn compile(llvm_target: &[&str], target: &String) {
271-
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
272-
let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
273-
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
274-
let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap();
354+
pub fn compile(llvm_target: &[&str], target: &Target) {
275355
let mut consider_float_intrinsics = true;
276356
let cfg = &mut cc::Build::new();
277357

@@ -280,8 +360,8 @@ mod c {
280360
//
281361
// Therefore, evaluate if those flags are present and set a boolean that causes any
282362
// compiler-rt intrinsics that contain floating point source to be excluded for this target.
283-
if target_arch == "aarch64" {
284-
let cflags_key = String::from("CFLAGS_") + &(target.to_owned().replace("-", "_"));
363+
if target.arch == "aarch64" {
364+
let cflags_key = String::from("CFLAGS_") + &(target.triple.replace("-", "_"));
285365
if let Ok(cflags_value) = env::var(cflags_key) {
286366
if cflags_value.contains("+nofp") || cflags_value.contains("+nosimd") {
287367
consider_float_intrinsics = false;
@@ -299,7 +379,7 @@ mod c {
299379

300380
cfg.warnings(false);
301381

302-
if target_env == "msvc" {
382+
if target.env == "msvc" {
303383
// Don't pull in extra libraries on MSVC
304384
cfg.flag("/Zl");
305385

@@ -328,7 +408,7 @@ mod c {
328408
// at odds with compiling with `-ffreestanding`, as the header
329409
// may be incompatible or not present. Create a minimal stub
330410
// header to use instead.
331-
if target_os == "uefi" {
411+
if target.os == "uefi" {
332412
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
333413
let include_dir = out_dir.join("include");
334414
if !include_dir.exists() {
@@ -373,7 +453,7 @@ mod c {
373453

374454
// On iOS and 32-bit OSX these are all just empty intrinsics, no need to
375455
// include them.
376-
if target_vendor != "apple" || target_arch != "x86" {
456+
if target.vendor != "apple" || target.arch != "x86" {
377457
sources.extend(&[
378458
("__absvti2", "absvti2.c"),
379459
("__addvti3", "addvti3.c"),
@@ -392,7 +472,7 @@ mod c {
392472
}
393473
}
394474

395-
if target_vendor == "apple" {
475+
if target.vendor == "apple" {
396476
sources.extend(&[
397477
("atomic_flag_clear", "atomic_flag_clear.c"),
398478
("atomic_flag_clear_explicit", "atomic_flag_clear_explicit.c"),
@@ -406,8 +486,8 @@ mod c {
406486
]);
407487
}
408488

409-
if target_env != "msvc" {
410-
if target_arch == "x86" {
489+
if target.env != "msvc" {
490+
if target.arch == "x86" {
411491
sources.extend(&[
412492
("__ashldi3", "i386/ashldi3.S"),
413493
("__ashrdi3", "i386/ashrdi3.S"),
@@ -421,7 +501,7 @@ mod c {
421501
}
422502
}
423503

424-
if target_arch == "arm" && target_vendor != "apple" && target_env != "msvc" {
504+
if target.arch == "arm" && target.vendor != "apple" && target.env != "msvc" {
425505
sources.extend(&[
426506
("__aeabi_div0", "arm/aeabi_div0.c"),
427507
("__aeabi_drsub", "arm/aeabi_drsub.c"),
@@ -441,7 +521,7 @@ mod c {
441521
("__umodsi3", "arm/umodsi3.S"),
442522
]);
443523

444-
if target_os == "freebsd" {
524+
if target.os == "freebsd" {
445525
sources.extend(&[("__clear_cache", "clear_cache.c")]);
446526
}
447527

@@ -513,7 +593,7 @@ mod c {
513593
]);
514594
}
515595

516-
if (target_arch == "aarch64" || target_arch == "arm64ec") && consider_float_intrinsics {
596+
if (target.arch == "aarch64" || target.arch == "arm64ec") && consider_float_intrinsics {
517597
sources.extend(&[
518598
("__comparetf2", "comparetf2.c"),
519599
("__floatditf", "floatditf.c"),
@@ -526,16 +606,16 @@ mod c {
526606
("__fe_raise_inexact", "fp_mode.c"),
527607
]);
528608

529-
if target_os != "windows" {
609+
if target.os != "windows" {
530610
sources.extend(&[("__multc3", "multc3.c")]);
531611
}
532612
}
533613

534-
if target_arch == "mips" || target_arch == "riscv32" || target_arch == "riscv64" {
614+
if target.arch == "mips" || target.arch == "riscv32" || target.arch == "riscv64" {
535615
sources.extend(&[("__bswapsi2", "bswapsi2.c")]);
536616
}
537617

538-
if target_arch == "mips64" {
618+
if target.arch == "mips64" {
539619
sources.extend(&[
540620
("__netf2", "comparetf2.c"),
541621
("__floatsitf", "floatsitf.c"),
@@ -544,7 +624,7 @@ mod c {
544624
]);
545625
}
546626

547-
if target_arch == "loongarch64" {
627+
if target.arch == "loongarch64" {
548628
sources.extend(&[
549629
("__netf2", "comparetf2.c"),
550630
("__floatsitf", "floatsitf.c"),
@@ -554,7 +634,7 @@ mod c {
554634
}
555635

556636
// Remove the assembly implementations that won't compile for the target
557-
if llvm_target[0] == "thumbv6m" || llvm_target[0] == "thumbv8m.base" || target_os == "uefi"
637+
if llvm_target[0] == "thumbv6m" || llvm_target[0] == "thumbv8m.base" || target.os == "uefi"
558638
{
559639
let mut to_remove = Vec::new();
560640
for (k, v) in sources.map.iter() {
@@ -570,7 +650,7 @@ mod c {
570650
}
571651

572652
// Android uses emulated TLS so we need a runtime support function.
573-
if target_os == "android" {
653+
if target.os == "android" {
574654
sources.extend(&[("__emutls_get_address", "emutls.c")]);
575655

576656
// Work around a bug in the NDK headers (fixed in
@@ -580,7 +660,7 @@ mod c {
580660
}
581661

582662
// OpenHarmony also uses emulated TLS.
583-
if target_env == "ohos" {
663+
if target.env == "ohos" {
584664
sources.extend(&[("__emutls_get_address", "emutls.c")]);
585665
}
586666

@@ -607,7 +687,7 @@ mod c {
607687
// sets of flags to the same source file.
608688
// Note: Out-of-line aarch64 atomics are not supported by the msvc toolchain (#430).
609689
let src_dir = root.join("lib/builtins");
610-
if target_arch == "aarch64" && target_env != "msvc" {
690+
if target.arch == "aarch64" && target.env != "msvc" {
611691
// See below for why we're building these as separate libraries.
612692
build_aarch64_out_of_line_atomics_libraries(&src_dir, cfg);
613693

src/float/add.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ intrinsics! {
204204
}
205205

206206
#[ppc_alias = __addkf3]
207-
#[cfg(not(feature = "no-f16-f128"))]
207+
#[cfg(f128_enabled)]
208208
pub extern "C" fn __addtf3(a: f128, b: f128) -> f128 {
209209
add(a, b)
210210
}

src/float/cmp.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ intrinsics! {
172172
}
173173
}
174174

175-
#[cfg(not(feature = "no-f16-f128",))]
175+
#[cfg(f128_enabled)]
176176
intrinsics! {
177177
#[avr_skip]
178178
#[ppc_alias = __lekf2]

0 commit comments

Comments
 (0)