]>
Commit | Line | Data |
---|---|---|
0531ce1d | 1 | use std::env; |
041b39d2 | 2 | |
0531ce1d XL |
3 | fn 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")] | |
84 | mod 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 | } |