1
1
use std:: { collections:: BTreeMap , env, path:: PathBuf , sync:: atomic:: Ordering } ;
2
2
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
+
3
43
fn main ( ) {
4
44
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 ( ) ;
8
46
let cwd = env:: current_dir ( ) . unwrap ( ) ;
9
47
48
+ configure_check_cfg ( ) ;
49
+ configure_f16_f128 ( & target) ;
50
+
10
51
println ! ( "cargo:compiler-rt={}" , cwd. join( "compiler-rt" ) . display( ) ) ;
11
52
12
53
// Activate libm's unstable features to make full use of Nightly.
13
54
println ! ( "cargo::rustc-check-cfg=cfg(feature, values(\" unstable\" ))" ) ;
14
55
println ! ( "cargo:rustc-cfg=feature=\" unstable\" " ) ;
15
56
16
57
// Emscripten's runtime includes all the builtins
17
- if target. contains ( "emscripten" ) {
58
+ if target. env == "emscripten" {
18
59
return ;
19
60
}
20
61
21
62
// OpenBSD provides compiler_rt by default, use it instead of rebuilding it from source
22
- if target. contains ( "openbsd" ) {
63
+ if target. os == "openbsd" {
23
64
println ! ( "cargo:rustc-link-search=native=/usr/lib" ) ;
24
65
println ! ( "cargo:rustc-link-lib=compiler_rt" ) ;
25
66
return ;
26
67
}
27
68
28
69
// Forcibly enable memory intrinsics on wasm & SGX as we don't have a libc to
29
70
// 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" )
36
77
{
37
78
println ! ( "cargo:rustc-cfg=feature=\" mem\" " ) ;
38
79
}
39
80
40
81
// These targets have hardware unaligned access support.
41
82
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" )
46
87
{
47
88
println ! ( "cargo:rustc-cfg=feature=\" mem-unaligned\" " ) ;
48
89
}
49
90
50
91
// NOTE we are going to assume that llvm-target, what determines our codegen option, matches the
51
92
// target triple. This is usually correct for our built-in targets but can break in presence of
52
93
// custom targets, which can have arbitrary names.
53
- let llvm_target = target. split ( '-' ) . collect :: < Vec < _ > > ( ) ;
94
+ let llvm_target = target. triple . split ( '-' ) . collect :: < Vec < _ > > ( ) ;
54
95
55
96
// Build missing intrinsics from compiler-rt C source code. If we're
56
97
// mangling names though we assume that we're also in test mode so we don't
@@ -60,7 +101,7 @@ fn main() {
60
101
// Don't use a C compiler for these targets:
61
102
//
62
103
// * nvptx - everything is bitcode, not compatible with mixed C/Rust
63
- if !target. contains ( "nvptx" ) {
104
+ if !target. arch . contains ( "nvptx" ) {
64
105
#[ cfg( feature = "c" ) ]
65
106
c:: compile ( & llvm_target, & target) ;
66
107
}
@@ -86,7 +127,7 @@ fn main() {
86
127
println ! ( "cargo::rustc-check-cfg=cfg(kernel_user_helpers)" ) ;
87
128
if llvm_target[ 0 ] == "armv4t"
88
129
|| llvm_target[ 0 ] == "armv5te"
89
- || target == "arm-linux-androideabi"
130
+ || target. triple == "arm-linux-androideabi"
90
131
{
91
132
println ! ( "cargo:rustc-cfg=kernel_user_helpers" )
92
133
}
@@ -219,6 +260,47 @@ fn configure_check_cfg() {
219
260
println ! ( "cargo::rustc-check-cfg=cfg(assert_no_panic)" ) ;
220
261
}
221
262
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
+
222
304
#[ cfg( feature = "c" ) ]
223
305
mod c {
224
306
use std:: collections:: { BTreeMap , HashSet } ;
@@ -227,6 +309,8 @@ mod c {
227
309
use std:: io:: Write ;
228
310
use std:: path:: { Path , PathBuf } ;
229
311
312
+ use super :: Target ;
313
+
230
314
struct Sources {
231
315
// SYMBOL -> PATH TO SOURCE
232
316
map : BTreeMap < & ' static str , & ' static str > ,
@@ -267,11 +351,7 @@ mod c {
267
351
}
268
352
269
353
/// 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 ) {
275
355
let mut consider_float_intrinsics = true ;
276
356
let cfg = & mut cc:: Build :: new ( ) ;
277
357
@@ -280,8 +360,8 @@ mod c {
280
360
//
281
361
// Therefore, evaluate if those flags are present and set a boolean that causes any
282
362
// 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 ( "-" , "_" ) ) ;
285
365
if let Ok ( cflags_value) = env:: var ( cflags_key) {
286
366
if cflags_value. contains ( "+nofp" ) || cflags_value. contains ( "+nosimd" ) {
287
367
consider_float_intrinsics = false ;
@@ -299,7 +379,7 @@ mod c {
299
379
300
380
cfg. warnings ( false ) ;
301
381
302
- if target_env == "msvc" {
382
+ if target . env == "msvc" {
303
383
// Don't pull in extra libraries on MSVC
304
384
cfg. flag ( "/Zl" ) ;
305
385
@@ -328,7 +408,7 @@ mod c {
328
408
// at odds with compiling with `-ffreestanding`, as the header
329
409
// may be incompatible or not present. Create a minimal stub
330
410
// header to use instead.
331
- if target_os == "uefi" {
411
+ if target . os == "uefi" {
332
412
let out_dir = PathBuf :: from ( env:: var ( "OUT_DIR" ) . unwrap ( ) ) ;
333
413
let include_dir = out_dir. join ( "include" ) ;
334
414
if !include_dir. exists ( ) {
@@ -373,7 +453,7 @@ mod c {
373
453
374
454
// On iOS and 32-bit OSX these are all just empty intrinsics, no need to
375
455
// include them.
376
- if target_vendor != "apple" || target_arch != "x86" {
456
+ if target . vendor != "apple" || target . arch != "x86" {
377
457
sources. extend ( & [
378
458
( "__absvti2" , "absvti2.c" ) ,
379
459
( "__addvti3" , "addvti3.c" ) ,
@@ -392,7 +472,7 @@ mod c {
392
472
}
393
473
}
394
474
395
- if target_vendor == "apple" {
475
+ if target . vendor == "apple" {
396
476
sources. extend ( & [
397
477
( "atomic_flag_clear" , "atomic_flag_clear.c" ) ,
398
478
( "atomic_flag_clear_explicit" , "atomic_flag_clear_explicit.c" ) ,
@@ -406,8 +486,8 @@ mod c {
406
486
] ) ;
407
487
}
408
488
409
- if target_env != "msvc" {
410
- if target_arch == "x86" {
489
+ if target . env != "msvc" {
490
+ if target . arch == "x86" {
411
491
sources. extend ( & [
412
492
( "__ashldi3" , "i386/ashldi3.S" ) ,
413
493
( "__ashrdi3" , "i386/ashrdi3.S" ) ,
@@ -421,7 +501,7 @@ mod c {
421
501
}
422
502
}
423
503
424
- if target_arch == "arm" && target_vendor != "apple" && target_env != "msvc" {
504
+ if target . arch == "arm" && target . vendor != "apple" && target . env != "msvc" {
425
505
sources. extend ( & [
426
506
( "__aeabi_div0" , "arm/aeabi_div0.c" ) ,
427
507
( "__aeabi_drsub" , "arm/aeabi_drsub.c" ) ,
@@ -441,7 +521,7 @@ mod c {
441
521
( "__umodsi3" , "arm/umodsi3.S" ) ,
442
522
] ) ;
443
523
444
- if target_os == "freebsd" {
524
+ if target . os == "freebsd" {
445
525
sources. extend ( & [ ( "__clear_cache" , "clear_cache.c" ) ] ) ;
446
526
}
447
527
@@ -513,7 +593,7 @@ mod c {
513
593
] ) ;
514
594
}
515
595
516
- if ( target_arch == "aarch64" || target_arch == "arm64ec" ) && consider_float_intrinsics {
596
+ if ( target . arch == "aarch64" || target . arch == "arm64ec" ) && consider_float_intrinsics {
517
597
sources. extend ( & [
518
598
( "__comparetf2" , "comparetf2.c" ) ,
519
599
( "__floatditf" , "floatditf.c" ) ,
@@ -526,16 +606,16 @@ mod c {
526
606
( "__fe_raise_inexact" , "fp_mode.c" ) ,
527
607
] ) ;
528
608
529
- if target_os != "windows" {
609
+ if target . os != "windows" {
530
610
sources. extend ( & [ ( "__multc3" , "multc3.c" ) ] ) ;
531
611
}
532
612
}
533
613
534
- if target_arch == "mips" || target_arch == "riscv32" || target_arch == "riscv64" {
614
+ if target . arch == "mips" || target . arch == "riscv32" || target . arch == "riscv64" {
535
615
sources. extend ( & [ ( "__bswapsi2" , "bswapsi2.c" ) ] ) ;
536
616
}
537
617
538
- if target_arch == "mips64" {
618
+ if target . arch == "mips64" {
539
619
sources. extend ( & [
540
620
( "__netf2" , "comparetf2.c" ) ,
541
621
( "__floatsitf" , "floatsitf.c" ) ,
@@ -544,7 +624,7 @@ mod c {
544
624
] ) ;
545
625
}
546
626
547
- if target_arch == "loongarch64" {
627
+ if target . arch == "loongarch64" {
548
628
sources. extend ( & [
549
629
( "__netf2" , "comparetf2.c" ) ,
550
630
( "__floatsitf" , "floatsitf.c" ) ,
@@ -554,7 +634,7 @@ mod c {
554
634
}
555
635
556
636
// 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"
558
638
{
559
639
let mut to_remove = Vec :: new ( ) ;
560
640
for ( k, v) in sources. map . iter ( ) {
@@ -570,7 +650,7 @@ mod c {
570
650
}
571
651
572
652
// Android uses emulated TLS so we need a runtime support function.
573
- if target_os == "android" {
653
+ if target . os == "android" {
574
654
sources. extend ( & [ ( "__emutls_get_address" , "emutls.c" ) ] ) ;
575
655
576
656
// Work around a bug in the NDK headers (fixed in
@@ -580,7 +660,7 @@ mod c {
580
660
}
581
661
582
662
// OpenHarmony also uses emulated TLS.
583
- if target_env == "ohos" {
663
+ if target . env == "ohos" {
584
664
sources. extend ( & [ ( "__emutls_get_address" , "emutls.c" ) ] ) ;
585
665
}
586
666
@@ -607,7 +687,7 @@ mod c {
607
687
// sets of flags to the same source file.
608
688
// Note: Out-of-line aarch64 atomics are not supported by the msvc toolchain (#430).
609
689
let src_dir = root. join ( "lib/builtins" ) ;
610
- if target_arch == "aarch64" && target_env != "msvc" {
690
+ if target . arch == "aarch64" && target . env != "msvc" {
611
691
// See below for why we're building these as separate libraries.
612
692
build_aarch64_out_of_line_atomics_libraries ( & src_dir, cfg) ;
613
693
0 commit comments