]> git.proxmox.com Git - rustc.git/blame - vendor/compiler_builtins/build.rs
New upstream version 1.55.0+dfsg1
[rustc.git] / vendor / compiler_builtins / build.rs
CommitLineData
0531ce1d 1use std::env;
041b39d2 2
0531ce1d
XL
3fn main() {
4 println!("cargo:rerun-if-changed=build.rs");
041b39d2 5
0531ce1d 6 let target = env::var("TARGET").unwrap();
0731742a
XL
7 let cwd = env::current_dir().unwrap();
8
9 println!("cargo:compiler-rt={}", cwd.join("compiler-rt").display());
041b39d2 10
60c5eb7d
XL
11 // Activate libm's unstable features to make full use of Nightly.
12 println!("cargo:rustc-cfg=feature=\"unstable\"");
13
0531ce1d
XL
14 // Emscripten's runtime includes all the builtins
15 if target.contains("emscripten") {
16 return;
041b39d2
XL
17 }
18
94b46f34
XL
19 // OpenBSD provides compiler_rt by default, use it instead of rebuilding it from source
20 if target.contains("openbsd") {
21 println!("cargo:rustc-link-search=native=/usr/lib");
8faf50e0 22 println!("cargo:rustc-link-lib=compiler_rt");
94b46f34
XL
23 return;
24 }
25
0731742a 26 // Forcibly enable memory intrinsics on wasm32 & SGX as we don't have a libc to
0531ce1d 27 // provide them.
48663c56
XL
28 if (target.contains("wasm32") && !target.contains("wasi"))
29 || (target.contains("sgx") && target.contains("fortanix"))
f9f354fc
XL
30 || target.contains("-none")
31 || target.contains("nvptx")
48663c56 32 {
0531ce1d 33 println!("cargo:rustc-cfg=feature=\"mem\"");
041b39d2
XL
34 }
35
0531ce1d
XL
36 // NOTE we are going to assume that llvm-target, what determines our codegen option, matches the
37 // target triple. This is usually correct for our built-in targets but can break in presence of
38 // custom targets, which can have arbitrary names.
39 let llvm_target = target.split('-').collect::<Vec<_>>();
abe05a73 40
0531ce1d
XL
41 // Build missing intrinsics from compiler-rt C source code. If we're
42 // mangling names though we assume that we're also in test mode so we don't
43 // build anything and we rely on the upstream implementation of compiler-rt
44 // functions
45 if !cfg!(feature = "mangled-names") && cfg!(feature = "c") {
48663c56
XL
46 // Don't use a C compiler for these targets:
47 //
48 // * wasm32 - clang 8 for wasm is somewhat hard to come by and it's
49 // unlikely that the C is really that much better than our own Rust.
50 // * nvptx - everything is bitcode, not compatible with mixed C/Rust
51 // * riscv - the rust-lang/rust distribution container doesn't have a C
52 // compiler nor is cc-rs ready for compilation to riscv (at this
53 // time). This can probably be removed in the future
54 if !target.contains("wasm32") && !target.contains("nvptx") && !target.starts_with("riscv") {
0531ce1d 55 #[cfg(feature = "c")]
ba9703b0 56 c::compile(&llvm_target, &target);
abe05a73
XL
57 }
58 }
59
0531ce1d
XL
60 // To compile intrinsics.rs for thumb targets, where there is no libc
61 if llvm_target[0].starts_with("thumb") {
62 println!("cargo:rustc-cfg=thumb")
041b39d2
XL
63 }
64
532ac7d7
XL
65 // compiler-rt `cfg`s away some intrinsics for thumbv6m and thumbv8m.base because
66 // these targets do not have full Thumb-2 support but only original Thumb-1.
67 // We have to cfg our code accordingly.
68 if llvm_target[0] == "thumbv6m" || llvm_target[0] == "thumbv8m.base" {
69 println!("cargo:rustc-cfg=thumb_1")
041b39d2
XL
70 }
71
17df50a5
XL
72 // Only emit the ARM Linux atomic emulation on pre-ARMv6 architectures. This
73 // includes the old androideabi. It is deprecated but it is available as a
74 // rustc target (arm-linux-androideabi).
75 if llvm_target[0] == "armv4t"
76 || llvm_target[0] == "armv5te"
77 || llvm_target.get(2) == Some(&"androideabi")
78 {
0531ce1d 79 println!("cargo:rustc-cfg=kernel_user_helpers")
041b39d2
XL
80 }
81}
82
83#[cfg(feature = "c")]
84mod c {
ea8adc8c 85 extern crate cc;
041b39d2 86
136023e0 87 use std::collections::{BTreeMap, HashSet};
041b39d2 88 use std::env;
17df50a5 89 use std::path::{Path, PathBuf};
041b39d2
XL
90
91 struct Sources {
92 // SYMBOL -> PATH TO SOURCE
93 map: BTreeMap<&'static str, &'static str>,
94 }
95
96 impl Sources {
97 fn new() -> Sources {
48663c56
XL
98 Sources {
99 map: BTreeMap::new(),
100 }
041b39d2
XL
101 }
102
48663c56 103 fn extend(&mut self, sources: &[(&'static str, &'static str)]) {
041b39d2
XL
104 // NOTE Some intrinsics have both a generic implementation (e.g.
105 // `floatdidf.c`) and an arch optimized implementation
106 // (`x86_64/floatdidf.c`). In those cases, we keep the arch optimized
107 // implementation and discard the generic implementation. If we don't
108 // and keep both implementations, the linker will yell at us about
109 // duplicate symbols!
48663c56 110 for (symbol, src) in sources {
041b39d2
XL
111 if src.contains("/") {
112 // Arch-optimized implementation (preferred)
113 self.map.insert(symbol, src);
114 } else {
115 // Generic implementation
116 if !self.map.contains_key(symbol) {
117 self.map.insert(symbol, src);
118 }
119 }
120 }
121 }
122
123 fn remove(&mut self, symbols: &[&str]) {
124 for symbol in symbols {
125 self.map.remove(*symbol).unwrap();
126 }
127 }
128 }
8bb4bdeb 129
041b39d2 130 /// Compile intrinsics from the compiler-rt C source code
ba9703b0 131 pub fn compile(llvm_target: &[&str], target: &String) {
041b39d2
XL
132 let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
133 let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
134 let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
135 let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap();
ba9703b0 136 let mut consider_float_intrinsics = true;
ea8adc8c
XL
137 let cfg = &mut cc::Build::new();
138
ba9703b0
XL
139 // AArch64 GCCs exit with an error condition when they encounter any kind of floating point
140 // code if the `nofp` and/or `nosimd` compiler flags have been set.
141 //
142 // Therefore, evaluate if those flags are present and set a boolean that causes any
143 // compiler-rt intrinsics that contain floating point source to be excluded for this target.
144 if target_arch == "aarch64" {
145 let cflags_key = String::from("CFLAGS_") + &(target.to_owned().replace("-", "_"));
146 if let Ok(cflags_value) = env::var(cflags_key) {
147 if cflags_value.contains("+nofp") || cflags_value.contains("+nosimd") {
148 consider_float_intrinsics = false;
149 }
150 }
151 }
152
ea8adc8c 153 cfg.warnings(false);
041b39d2
XL
154
155 if target_env == "msvc" {
156 // Don't pull in extra libraries on MSVC
157 cfg.flag("/Zl");
158
159 // Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP
160 cfg.define("__func__", Some("__FUNCTION__"));
161 } else {
162 // Turn off various features of gcc and such, mostly copying
163 // compiler-rt's build system already
164 cfg.flag("-fno-builtin");
165 cfg.flag("-fvisibility=hidden");
041b39d2 166 cfg.flag("-ffreestanding");
ff7c6d11
XL
167 // Avoid the following warning appearing once **per file**:
168 // clang: warning: optimization flag '-fomit-frame-pointer' is not supported for target 'armv7' [-Wignored-optimization-argument]
169 //
170 // Note that compiler-rt's build system also checks
171 //
172 // `check_cxx_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG)`
173 //
174 // in https://github.com/rust-lang/compiler-rt/blob/c8fbcb3/cmake/config-ix.cmake#L19.
175 cfg.flag_if_supported("-fomit-frame-pointer");
041b39d2
XL
176 cfg.define("VISIBILITY_HIDDEN", None);
177 }
178
041b39d2 179 let mut sources = Sources::new();
48663c56
XL
180 sources.extend(&[
181 ("__absvdi2", "absvdi2.c"),
182 ("__absvsi2", "absvsi2.c"),
183 ("__addvdi3", "addvdi3.c"),
184 ("__addvsi3", "addvsi3.c"),
185 ("apple_versioning", "apple_versioning.c"),
186 ("__clzdi2", "clzdi2.c"),
187 ("__clzsi2", "clzsi2.c"),
188 ("__cmpdi2", "cmpdi2.c"),
189 ("__ctzdi2", "ctzdi2.c"),
190 ("__ctzsi2", "ctzsi2.c"),
48663c56 191 ("__int_util", "int_util.c"),
48663c56
XL
192 ("__mulvdi3", "mulvdi3.c"),
193 ("__mulvsi3", "mulvsi3.c"),
48663c56 194 ("__negdi2", "negdi2.c"),
48663c56
XL
195 ("__negvdi2", "negvdi2.c"),
196 ("__negvsi2", "negvsi2.c"),
197 ("__paritydi2", "paritydi2.c"),
198 ("__paritysi2", "paritysi2.c"),
199 ("__popcountdi2", "popcountdi2.c"),
200 ("__popcountsi2", "popcountsi2.c"),
48663c56
XL
201 ("__subvdi3", "subvdi3.c"),
202 ("__subvsi3", "subvsi3.c"),
48663c56
XL
203 ("__ucmpdi2", "ucmpdi2.c"),
204 ]);
041b39d2 205
ba9703b0
XL
206 if consider_float_intrinsics {
207 sources.extend(&[
208 ("__divdc3", "divdc3.c"),
209 ("__divsc3", "divsc3.c"),
210 ("__divxc3", "divxc3.c"),
211 ("__extendhfsf2", "extendhfsf2.c"),
212 ("__muldc3", "muldc3.c"),
213 ("__mulsc3", "mulsc3.c"),
214 ("__mulxc3", "mulxc3.c"),
215 ("__negdf2", "negdf2.c"),
216 ("__negsf2", "negsf2.c"),
217 ("__powixf2", "powixf2.c"),
218 ("__truncdfhf2", "truncdfhf2.c"),
219 ("__truncdfsf2", "truncdfsf2.c"),
220 ("__truncsfhf2", "truncsfhf2.c"),
221 ]);
222 }
223
041b39d2
XL
224 // When compiling in rustbuild (the rust-lang/rust repo) this library
225 // also needs to satisfy intrinsics that jemalloc or C in general may
226 // need, so include a few more that aren't typically needed by
227 // LLVM/Rust.
ea8adc8c 228 if cfg!(feature = "rustbuild") {
48663c56 229 sources.extend(&[("__ffsdi2", "ffsdi2.c")]);
ea8adc8c 230 }
041b39d2 231
ea8adc8c
XL
232 // On iOS and 32-bit OSX these are all just empty intrinsics, no need to
233 // include them.
234 if target_os != "ios" && (target_vendor != "apple" || target_arch != "x86") {
48663c56
XL
235 sources.extend(&[
236 ("__absvti2", "absvti2.c"),
237 ("__addvti3", "addvti3.c"),
238 ("__clzti2", "clzti2.c"),
239 ("__cmpti2", "cmpti2.c"),
240 ("__ctzti2", "ctzti2.c"),
241 ("__ffsti2", "ffsti2.c"),
242 ("__mulvti3", "mulvti3.c"),
243 ("__negti2", "negti2.c"),
48663c56
XL
244 ("__parityti2", "parityti2.c"),
245 ("__popcountti2", "popcountti2.c"),
246 ("__subvti3", "subvti3.c"),
247 ("__ucmpti2", "ucmpti2.c"),
248 ]);
ba9703b0
XL
249
250 if consider_float_intrinsics {
251 sources.extend(&[("__negvti2", "negvti2.c")]);
252 }
041b39d2
XL
253 }
254
255 if target_vendor == "apple" {
48663c56
XL
256 sources.extend(&[
257 ("atomic_flag_clear", "atomic_flag_clear.c"),
258 ("atomic_flag_clear_explicit", "atomic_flag_clear_explicit.c"),
259 ("atomic_flag_test_and_set", "atomic_flag_test_and_set.c"),
260 (
261 "atomic_flag_test_and_set_explicit",
041b39d2 262 "atomic_flag_test_and_set_explicit.c",
48663c56
XL
263 ),
264 ("atomic_signal_fence", "atomic_signal_fence.c"),
265 ("atomic_thread_fence", "atomic_thread_fence.c"),
266 ]);
041b39d2
XL
267 }
268
269 if target_env == "msvc" {
270 if target_arch == "x86_64" {
48663c56
XL
271 sources.extend(&[
272 ("__floatdisf", "x86_64/floatdisf.c"),
273 ("__floatdixf", "x86_64/floatdixf.c"),
274 ]);
041b39d2
XL
275 }
276 } else {
277 // None of these seem to be used on x86_64 windows, and they've all
278 // got the wrong ABI anyway, so we want to avoid them.
279 if target_os != "windows" {
280 if target_arch == "x86_64" {
48663c56
XL
281 sources.extend(&[
282 ("__floatdisf", "x86_64/floatdisf.c"),
283 ("__floatdixf", "x86_64/floatdixf.c"),
284 ("__floatundidf", "x86_64/floatundidf.S"),
285 ("__floatundisf", "x86_64/floatundisf.S"),
286 ("__floatundixf", "x86_64/floatundixf.S"),
287 ]);
041b39d2
XL
288 }
289 }
290
291 if target_arch == "x86" {
48663c56
XL
292 sources.extend(&[
293 ("__ashldi3", "i386/ashldi3.S"),
294 ("__ashrdi3", "i386/ashrdi3.S"),
295 ("__divdi3", "i386/divdi3.S"),
296 ("__floatdidf", "i386/floatdidf.S"),
297 ("__floatdisf", "i386/floatdisf.S"),
298 ("__floatdixf", "i386/floatdixf.S"),
299 ("__floatundidf", "i386/floatundidf.S"),
300 ("__floatundisf", "i386/floatundisf.S"),
301 ("__floatundixf", "i386/floatundixf.S"),
302 ("__lshrdi3", "i386/lshrdi3.S"),
303 ("__moddi3", "i386/moddi3.S"),
304 ("__muldi3", "i386/muldi3.S"),
305 ("__udivdi3", "i386/udivdi3.S"),
306 ("__umoddi3", "i386/umoddi3.S"),
307 ]);
041b39d2
XL
308 }
309 }
310
a1dfa0c6 311 if target_arch == "arm" && target_os != "ios" && target_env != "msvc" {
48663c56
XL
312 sources.extend(&[
313 ("__aeabi_div0", "arm/aeabi_div0.c"),
314 ("__aeabi_drsub", "arm/aeabi_drsub.c"),
315 ("__aeabi_frsub", "arm/aeabi_frsub.c"),
316 ("__bswapdi2", "arm/bswapdi2.S"),
317 ("__bswapsi2", "arm/bswapsi2.S"),
318 ("__clzdi2", "arm/clzdi2.S"),
319 ("__clzsi2", "arm/clzsi2.S"),
320 ("__divmodsi4", "arm/divmodsi4.S"),
321 ("__divsi3", "arm/divsi3.S"),
322 ("__modsi3", "arm/modsi3.S"),
323 ("__switch16", "arm/switch16.S"),
324 ("__switch32", "arm/switch32.S"),
325 ("__switch8", "arm/switch8.S"),
326 ("__switchu8", "arm/switchu8.S"),
327 ("__sync_synchronize", "arm/sync_synchronize.S"),
328 ("__udivmodsi4", "arm/udivmodsi4.S"),
329 ("__udivsi3", "arm/udivsi3.S"),
330 ("__umodsi3", "arm/umodsi3.S"),
331 ]);
2c00a5a8 332
532ac7d7 333 if target_os == "freebsd" {
48663c56 334 sources.extend(&[("__clear_cache", "clear_cache.c")]);
532ac7d7
XL
335 }
336
2c00a5a8
XL
337 // First of all aeabi_cdcmp and aeabi_cfcmp are never called by LLVM.
338 // Second are little-endian only, so build fail on big-endian targets.
339 // Temporally workaround: exclude these files for big-endian targets.
48663c56
XL
340 if !llvm_target[0].starts_with("thumbeb") && !llvm_target[0].starts_with("armeb") {
341 sources.extend(&[
342 ("__aeabi_cdcmp", "arm/aeabi_cdcmp.S"),
343 ("__aeabi_cdcmpeq_check_nan", "arm/aeabi_cdcmpeq_check_nan.c"),
344 ("__aeabi_cfcmp", "arm/aeabi_cfcmp.S"),
345 ("__aeabi_cfcmpeq_check_nan", "arm/aeabi_cfcmpeq_check_nan.c"),
346 ]);
2c00a5a8 347 }
041b39d2
XL
348 }
349
350 if llvm_target[0] == "armv7" {
48663c56
XL
351 sources.extend(&[
352 ("__sync_fetch_and_add_4", "arm/sync_fetch_and_add_4.S"),
353 ("__sync_fetch_and_add_8", "arm/sync_fetch_and_add_8.S"),
354 ("__sync_fetch_and_and_4", "arm/sync_fetch_and_and_4.S"),
355 ("__sync_fetch_and_and_8", "arm/sync_fetch_and_and_8.S"),
356 ("__sync_fetch_and_max_4", "arm/sync_fetch_and_max_4.S"),
357 ("__sync_fetch_and_max_8", "arm/sync_fetch_and_max_8.S"),
358 ("__sync_fetch_and_min_4", "arm/sync_fetch_and_min_4.S"),
359 ("__sync_fetch_and_min_8", "arm/sync_fetch_and_min_8.S"),
360 ("__sync_fetch_and_nand_4", "arm/sync_fetch_and_nand_4.S"),
361 ("__sync_fetch_and_nand_8", "arm/sync_fetch_and_nand_8.S"),
362 ("__sync_fetch_and_or_4", "arm/sync_fetch_and_or_4.S"),
363 ("__sync_fetch_and_or_8", "arm/sync_fetch_and_or_8.S"),
364 ("__sync_fetch_and_sub_4", "arm/sync_fetch_and_sub_4.S"),
365 ("__sync_fetch_and_sub_8", "arm/sync_fetch_and_sub_8.S"),
366 ("__sync_fetch_and_umax_4", "arm/sync_fetch_and_umax_4.S"),
367 ("__sync_fetch_and_umax_8", "arm/sync_fetch_and_umax_8.S"),
368 ("__sync_fetch_and_umin_4", "arm/sync_fetch_and_umin_4.S"),
369 ("__sync_fetch_and_umin_8", "arm/sync_fetch_and_umin_8.S"),
370 ("__sync_fetch_and_xor_4", "arm/sync_fetch_and_xor_4.S"),
371 ("__sync_fetch_and_xor_8", "arm/sync_fetch_and_xor_8.S"),
372 ]);
041b39d2
XL
373 }
374
375 if llvm_target.last().unwrap().ends_with("eabihf") {
48663c56
XL
376 if !llvm_target[0].starts_with("thumbv7em")
377 && !llvm_target[0].starts_with("thumbv8m.main")
378 {
532ac7d7
XL
379 // The FPU option chosen for these architectures in cc-rs, ie:
380 // -mfpu=fpv4-sp-d16 for thumbv7em
381 // -mfpu=fpv5-sp-d16 for thumbv8m.main
382 // do not support double precision floating points conversions so the files
383 // that include such instructions are not included for these targets.
48663c56
XL
384 sources.extend(&[
385 ("__fixdfsivfp", "arm/fixdfsivfp.S"),
386 ("__fixunsdfsivfp", "arm/fixunsdfsivfp.S"),
387 ("__floatsidfvfp", "arm/floatsidfvfp.S"),
388 ("__floatunssidfvfp", "arm/floatunssidfvfp.S"),
389 ]);
041b39d2
XL
390 }
391
48663c56
XL
392 sources.extend(&[
393 ("__fixsfsivfp", "arm/fixsfsivfp.S"),
394 ("__fixunssfsivfp", "arm/fixunssfsivfp.S"),
395 ("__floatsisfvfp", "arm/floatsisfvfp.S"),
396 ("__floatunssisfvfp", "arm/floatunssisfvfp.S"),
397 ("__floatunssisfvfp", "arm/floatunssisfvfp.S"),
398 ("__restore_vfp_d8_d15_regs", "arm/restore_vfp_d8_d15_regs.S"),
399 ("__save_vfp_d8_d15_regs", "arm/save_vfp_d8_d15_regs.S"),
400 ("__negdf2vfp", "arm/negdf2vfp.S"),
401 ("__negsf2vfp", "arm/negsf2vfp.S"),
402 ]);
041b39d2
XL
403 }
404
ba9703b0 405 if target_arch == "aarch64" && consider_float_intrinsics {
48663c56
XL
406 sources.extend(&[
407 ("__comparetf2", "comparetf2.c"),
408 ("__extenddftf2", "extenddftf2.c"),
409 ("__extendsftf2", "extendsftf2.c"),
410 ("__fixtfdi", "fixtfdi.c"),
411 ("__fixtfsi", "fixtfsi.c"),
412 ("__fixtfti", "fixtfti.c"),
413 ("__fixunstfdi", "fixunstfdi.c"),
414 ("__fixunstfsi", "fixunstfsi.c"),
415 ("__fixunstfti", "fixunstfti.c"),
416 ("__floatditf", "floatditf.c"),
417 ("__floatsitf", "floatsitf.c"),
418 ("__floatunditf", "floatunditf.c"),
419 ("__floatunsitf", "floatunsitf.c"),
420 ("__trunctfdf2", "trunctfdf2.c"),
421 ("__trunctfsf2", "trunctfsf2.c"),
136023e0
XL
422 ("__addtf3", "addtf3.c"),
423 ("__multf3", "multf3.c"),
424 ("__subtf3", "subtf3.c"),
425 ("__divtf3", "divtf3.c"),
426 ("__powitf2", "powitf2.c"),
427 ("__fe_getround", "fp_mode.c"),
428 ("__fe_raise_inexact", "fp_mode.c"),
48663c56 429 ]);
8faf50e0
XL
430
431 if target_os != "windows" {
48663c56 432 sources.extend(&[("__multc3", "multc3.c")]);
8faf50e0 433 }
1b1a35ee
XL
434 }
435
436 if target_arch == "mips" {
437 sources.extend(&[("__bswapsi2", "bswapsi2.c")]);
438 }
439
440 if target_arch == "mips64" {
441 sources.extend(&[
442 ("__extenddftf2", "extenddftf2.c"),
443 ("__netf2", "comparetf2.c"),
444 ("__addtf3", "addtf3.c"),
445 ("__multf3", "multf3.c"),
446 ("__subtf3", "subtf3.c"),
447 ("__fixtfsi", "fixtfsi.c"),
448 ("__floatsitf", "floatsitf.c"),
449 ("__fixunstfsi", "fixunstfsi.c"),
450 ("__floatunsitf", "floatunsitf.c"),
451 ("__fe_getround", "fp_mode.c"),
17df50a5
XL
452 ("__divtf3", "divtf3.c"),
453 ("__trunctfdf2", "trunctfdf2.c"),
1b1a35ee 454 ]);
041b39d2
XL
455 }
456
457 // Remove the assembly implementations that won't compile for the target
532ac7d7 458 if llvm_target[0] == "thumbv6m" || llvm_target[0] == "thumbv8m.base" {
48663c56
XL
459 let mut to_remove = Vec::new();
460 for (k, v) in sources.map.iter() {
461 if v.ends_with(".S") {
462 to_remove.push(*k);
463 }
464 }
465 sources.remove(&to_remove);
041b39d2
XL
466
467 // But use some generic implementations where possible
48663c56 468 sources.extend(&[("__clzdi2", "clzdi2.c"), ("__clzsi2", "clzsi2.c")])
041b39d2
XL
469 }
470
471 if llvm_target[0] == "thumbv7m" || llvm_target[0] == "thumbv7em" {
48663c56 472 sources.remove(&["__aeabi_cdcmp", "__aeabi_cfcmp"]);
041b39d2
XL
473 }
474
dc9dc135
XL
475 // When compiling the C code we require the user to tell us where the
476 // source code is, and this is largely done so when we're compiling as
477 // part of rust-lang/rust we can use the same llvm-project repository as
478 // rust-lang/rust.
479 let root = match env::var_os("RUST_COMPILER_RT_ROOT") {
480 Some(s) => PathBuf::from(s),
481 None => panic!("RUST_COMPILER_RT_ROOT is not set"),
041b39d2 482 };
dc9dc135
XL
483 if !root.exists() {
484 panic!("RUST_COMPILER_RT_ROOT={} does not exist", root.display());
485 }
041b39d2 486
60c5eb7d
XL
487 // Support deterministic builds by remapping the __FILE__ prefix if the
488 // compiler supports it. This fixes the nondeterminism caused by the
489 // use of that macro in lib/builtins/int_util.h in compiler-rt.
490 cfg.flag_if_supported(&format!("-ffile-prefix-map={}=.", root.display()));
491
17df50a5
XL
492 // Include out-of-line atomics for aarch64, which are all generated by supplying different
493 // sets of flags to the same source file.
136023e0 494 // Note: Out-of-line aarch64 atomics are not supported by the msvc toolchain (#430).
dc9dc135 495 let src_dir = root.join("lib/builtins");
136023e0 496 if target_arch == "aarch64" && target_env != "msvc" {
17df50a5
XL
497 // See below for why we're building these as separate libraries.
498 build_aarch64_out_of_line_atomics_libraries(&src_dir, cfg);
499
500 // Some run-time CPU feature detection is necessary, as well.
501 sources.extend(&[("__aarch64_have_lse_atomics", "cpu_model.c")]);
502 }
503
136023e0 504 let mut added_sources = HashSet::new();
48663c56 505 for (sym, src) in sources.map.iter() {
041b39d2 506 let src = src_dir.join(src);
136023e0
XL
507 if added_sources.insert(src.clone()) {
508 cfg.file(&src);
509 println!("cargo:rerun-if-changed={}", src.display());
510 }
48663c56 511 println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
8bb4bdeb 512 }
041b39d2
XL
513
514 cfg.compile("libcompiler-rt.a");
515 }
17df50a5
XL
516
517 fn build_aarch64_out_of_line_atomics_libraries(builtins_dir: &Path, cfg: &cc::Build) {
518 // NOTE: because we're recompiling the same source file in N different ways, building
519 // serially is necessary. If we want to lift this restriction, we can either:
520 // - create symlinks to lse.S and build those_(though we'd still need to pass special
521 // #define-like flags to each of these), or
522 // - synthesizing tiny .S files in out/ with the proper #defines, which ultimately #include
523 // lse.S.
524 // That said, it's unclear how useful this added complexity will be, so just do the simple
525 // thing for now.
526 let outlined_atomics_file = builtins_dir.join("aarch64/lse.S");
527 println!("cargo:rerun-if-changed={}", outlined_atomics_file.display());
528
529 // Ideally, this would be a Vec of object files, but cc doesn't make it *entirely*
530 // trivial to build an individual object.
531 for instruction_type in &["cas", "swp", "ldadd", "ldclr", "ldeor", "ldset"] {
532 for size in &[1, 2, 4, 8, 16] {
533 if *size == 16 && *instruction_type != "cas" {
534 continue;
535 }
536
537 for (model_number, model_name) in
538 &[(1, "relax"), (2, "acq"), (3, "rel"), (4, "acq_rel")]
539 {
540 let library_name = format!(
541 "liboutline_atomic_helper_{}{}_{}.a",
542 instruction_type, size, model_name
543 );
544 let sym = format!("__aarch64_{}{}_{}", instruction_type, size, model_name);
545 let mut cfg = cfg.clone();
546
547 cfg.include(&builtins_dir)
548 .define(&format!("L_{}", instruction_type), None)
549 .define("SIZE", size.to_string().as_str())
550 .define("MODEL", model_number.to_string().as_str())
551 .file(&outlined_atomics_file);
552 cfg.compile(&library_name);
553
554 println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
555 }
556 }
557 }
558 }
9e0c209e 559}