]> git.proxmox.com Git - rustc.git/blob - vendor/compiler_builtins/build.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / vendor / compiler_builtins / build.rs
1 use std::env;
2
3 fn main() {
4 println!("cargo:rerun-if-changed=build.rs");
5
6 let target = env::var("TARGET").unwrap();
7 let cwd = env::current_dir().unwrap();
8
9 println!("cargo:compiler-rt={}", cwd.join("compiler-rt").display());
10
11 // Activate libm's unstable features to make full use of Nightly.
12 println!("cargo:rustc-cfg=feature=\"unstable\"");
13
14 // Emscripten's runtime includes all the builtins
15 if target.contains("emscripten") {
16 return;
17 }
18
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");
22 println!("cargo:rustc-link-lib=compiler_rt");
23 return;
24 }
25
26 // Forcibly enable memory intrinsics on wasm32 & SGX as we don't have a libc to
27 // provide them.
28 if (target.contains("wasm32") && !target.contains("wasi"))
29 || (target.contains("sgx") && target.contains("fortanix"))
30 {
31 println!("cargo:rustc-cfg=feature=\"mem\"");
32 }
33
34 // NOTE we are going to assume that llvm-target, what determines our codegen option, matches the
35 // target triple. This is usually correct for our built-in targets but can break in presence of
36 // custom targets, which can have arbitrary names.
37 let llvm_target = target.split('-').collect::<Vec<_>>();
38
39 // Build missing intrinsics from compiler-rt C source code. If we're
40 // mangling names though we assume that we're also in test mode so we don't
41 // build anything and we rely on the upstream implementation of compiler-rt
42 // functions
43 if !cfg!(feature = "mangled-names") && cfg!(feature = "c") {
44 // Don't use a C compiler for these targets:
45 //
46 // * wasm32 - clang 8 for wasm is somewhat hard to come by and it's
47 // unlikely that the C is really that much better than our own Rust.
48 // * nvptx - everything is bitcode, not compatible with mixed C/Rust
49 // * riscv - the rust-lang/rust distribution container doesn't have a C
50 // compiler nor is cc-rs ready for compilation to riscv (at this
51 // time). This can probably be removed in the future
52 if !target.contains("wasm32") && !target.contains("nvptx") && !target.starts_with("riscv") {
53 #[cfg(feature = "c")]
54 c::compile(&llvm_target);
55 }
56 }
57
58 // To compile intrinsics.rs for thumb targets, where there is no libc
59 if llvm_target[0].starts_with("thumb") {
60 println!("cargo:rustc-cfg=thumb")
61 }
62
63 // compiler-rt `cfg`s away some intrinsics for thumbv6m and thumbv8m.base because
64 // these targets do not have full Thumb-2 support but only original Thumb-1.
65 // We have to cfg our code accordingly.
66 if llvm_target[0] == "thumbv6m" || llvm_target[0] == "thumbv8m.base" {
67 println!("cargo:rustc-cfg=thumb_1")
68 }
69
70 // Only emit the ARM Linux atomic emulation on pre-ARMv6 architectures.
71 if llvm_target[0] == "armv4t" || llvm_target[0] == "armv5te" {
72 println!("cargo:rustc-cfg=kernel_user_helpers")
73 }
74 }
75
76 #[cfg(feature = "c")]
77 mod c {
78 extern crate cc;
79
80 use std::collections::BTreeMap;
81 use std::env;
82 use std::path::PathBuf;
83
84 struct Sources {
85 // SYMBOL -> PATH TO SOURCE
86 map: BTreeMap<&'static str, &'static str>,
87 }
88
89 impl Sources {
90 fn new() -> Sources {
91 Sources {
92 map: BTreeMap::new(),
93 }
94 }
95
96 fn extend(&mut self, sources: &[(&'static str, &'static str)]) {
97 // NOTE Some intrinsics have both a generic implementation (e.g.
98 // `floatdidf.c`) and an arch optimized implementation
99 // (`x86_64/floatdidf.c`). In those cases, we keep the arch optimized
100 // implementation and discard the generic implementation. If we don't
101 // and keep both implementations, the linker will yell at us about
102 // duplicate symbols!
103 for (symbol, src) in sources {
104 if src.contains("/") {
105 // Arch-optimized implementation (preferred)
106 self.map.insert(symbol, src);
107 } else {
108 // Generic implementation
109 if !self.map.contains_key(symbol) {
110 self.map.insert(symbol, src);
111 }
112 }
113 }
114 }
115
116 fn remove(&mut self, symbols: &[&str]) {
117 for symbol in symbols {
118 self.map.remove(*symbol).unwrap();
119 }
120 }
121 }
122
123 /// Compile intrinsics from the compiler-rt C source code
124 pub fn compile(llvm_target: &[&str]) {
125 let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
126 let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
127 let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
128 let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap();
129 let cfg = &mut cc::Build::new();
130
131 cfg.warnings(false);
132
133 if target_env == "msvc" {
134 // Don't pull in extra libraries on MSVC
135 cfg.flag("/Zl");
136
137 // Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP
138 cfg.define("__func__", Some("__FUNCTION__"));
139 } else {
140 // Turn off various features of gcc and such, mostly copying
141 // compiler-rt's build system already
142 cfg.flag("-fno-builtin");
143 cfg.flag("-fvisibility=hidden");
144 cfg.flag("-ffreestanding");
145 // Avoid the following warning appearing once **per file**:
146 // clang: warning: optimization flag '-fomit-frame-pointer' is not supported for target 'armv7' [-Wignored-optimization-argument]
147 //
148 // Note that compiler-rt's build system also checks
149 //
150 // `check_cxx_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG)`
151 //
152 // in https://github.com/rust-lang/compiler-rt/blob/c8fbcb3/cmake/config-ix.cmake#L19.
153 cfg.flag_if_supported("-fomit-frame-pointer");
154 cfg.define("VISIBILITY_HIDDEN", None);
155 }
156
157 let mut sources = Sources::new();
158 sources.extend(&[
159 ("__absvdi2", "absvdi2.c"),
160 ("__absvsi2", "absvsi2.c"),
161 ("__addvdi3", "addvdi3.c"),
162 ("__addvsi3", "addvsi3.c"),
163 ("apple_versioning", "apple_versioning.c"),
164 ("__clzdi2", "clzdi2.c"),
165 ("__clzsi2", "clzsi2.c"),
166 ("__cmpdi2", "cmpdi2.c"),
167 ("__ctzdi2", "ctzdi2.c"),
168 ("__ctzsi2", "ctzsi2.c"),
169 ("__divdc3", "divdc3.c"),
170 ("__divsc3", "divsc3.c"),
171 ("__divxc3", "divxc3.c"),
172 ("__extendhfsf2", "extendhfsf2.c"),
173 ("__int_util", "int_util.c"),
174 ("__muldc3", "muldc3.c"),
175 ("__mulsc3", "mulsc3.c"),
176 ("__mulvdi3", "mulvdi3.c"),
177 ("__mulvsi3", "mulvsi3.c"),
178 ("__mulxc3", "mulxc3.c"),
179 ("__negdf2", "negdf2.c"),
180 ("__negdi2", "negdi2.c"),
181 ("__negsf2", "negsf2.c"),
182 ("__negvdi2", "negvdi2.c"),
183 ("__negvsi2", "negvsi2.c"),
184 ("__paritydi2", "paritydi2.c"),
185 ("__paritysi2", "paritysi2.c"),
186 ("__popcountdi2", "popcountdi2.c"),
187 ("__popcountsi2", "popcountsi2.c"),
188 ("__powixf2", "powixf2.c"),
189 ("__subvdi3", "subvdi3.c"),
190 ("__subvsi3", "subvsi3.c"),
191 ("__truncdfhf2", "truncdfhf2.c"),
192 ("__truncdfsf2", "truncdfsf2.c"),
193 ("__truncsfhf2", "truncsfhf2.c"),
194 ("__ucmpdi2", "ucmpdi2.c"),
195 ]);
196
197 // When compiling in rustbuild (the rust-lang/rust repo) this library
198 // also needs to satisfy intrinsics that jemalloc or C in general may
199 // need, so include a few more that aren't typically needed by
200 // LLVM/Rust.
201 if cfg!(feature = "rustbuild") {
202 sources.extend(&[("__ffsdi2", "ffsdi2.c")]);
203 }
204
205 // On iOS and 32-bit OSX these are all just empty intrinsics, no need to
206 // include them.
207 if target_os != "ios" && (target_vendor != "apple" || target_arch != "x86") {
208 sources.extend(&[
209 ("__absvti2", "absvti2.c"),
210 ("__addvti3", "addvti3.c"),
211 ("__clzti2", "clzti2.c"),
212 ("__cmpti2", "cmpti2.c"),
213 ("__ctzti2", "ctzti2.c"),
214 ("__ffsti2", "ffsti2.c"),
215 ("__mulvti3", "mulvti3.c"),
216 ("__negti2", "negti2.c"),
217 ("__negvti2", "negvti2.c"),
218 ("__parityti2", "parityti2.c"),
219 ("__popcountti2", "popcountti2.c"),
220 ("__subvti3", "subvti3.c"),
221 ("__ucmpti2", "ucmpti2.c"),
222 ]);
223 }
224
225 if target_vendor == "apple" {
226 sources.extend(&[
227 ("atomic_flag_clear", "atomic_flag_clear.c"),
228 ("atomic_flag_clear_explicit", "atomic_flag_clear_explicit.c"),
229 ("atomic_flag_test_and_set", "atomic_flag_test_and_set.c"),
230 (
231 "atomic_flag_test_and_set_explicit",
232 "atomic_flag_test_and_set_explicit.c",
233 ),
234 ("atomic_signal_fence", "atomic_signal_fence.c"),
235 ("atomic_thread_fence", "atomic_thread_fence.c"),
236 ]);
237 }
238
239 if target_env == "msvc" {
240 if target_arch == "x86_64" {
241 sources.extend(&[
242 ("__floatdisf", "x86_64/floatdisf.c"),
243 ("__floatdixf", "x86_64/floatdixf.c"),
244 ]);
245 }
246 } else {
247 // None of these seem to be used on x86_64 windows, and they've all
248 // got the wrong ABI anyway, so we want to avoid them.
249 if target_os != "windows" {
250 if target_arch == "x86_64" {
251 sources.extend(&[
252 ("__floatdisf", "x86_64/floatdisf.c"),
253 ("__floatdixf", "x86_64/floatdixf.c"),
254 ("__floatundidf", "x86_64/floatundidf.S"),
255 ("__floatundisf", "x86_64/floatundisf.S"),
256 ("__floatundixf", "x86_64/floatundixf.S"),
257 ]);
258 }
259 }
260
261 if target_arch == "x86" {
262 sources.extend(&[
263 ("__ashldi3", "i386/ashldi3.S"),
264 ("__ashrdi3", "i386/ashrdi3.S"),
265 ("__divdi3", "i386/divdi3.S"),
266 ("__floatdidf", "i386/floatdidf.S"),
267 ("__floatdisf", "i386/floatdisf.S"),
268 ("__floatdixf", "i386/floatdixf.S"),
269 ("__floatundidf", "i386/floatundidf.S"),
270 ("__floatundisf", "i386/floatundisf.S"),
271 ("__floatundixf", "i386/floatundixf.S"),
272 ("__lshrdi3", "i386/lshrdi3.S"),
273 ("__moddi3", "i386/moddi3.S"),
274 ("__muldi3", "i386/muldi3.S"),
275 ("__udivdi3", "i386/udivdi3.S"),
276 ("__umoddi3", "i386/umoddi3.S"),
277 ]);
278 }
279 }
280
281 if target_arch == "arm" && target_os != "ios" && target_env != "msvc" {
282 sources.extend(&[
283 ("__aeabi_div0", "arm/aeabi_div0.c"),
284 ("__aeabi_drsub", "arm/aeabi_drsub.c"),
285 ("__aeabi_frsub", "arm/aeabi_frsub.c"),
286 ("__bswapdi2", "arm/bswapdi2.S"),
287 ("__bswapsi2", "arm/bswapsi2.S"),
288 ("__clzdi2", "arm/clzdi2.S"),
289 ("__clzsi2", "arm/clzsi2.S"),
290 ("__divmodsi4", "arm/divmodsi4.S"),
291 ("__divsi3", "arm/divsi3.S"),
292 ("__modsi3", "arm/modsi3.S"),
293 ("__switch16", "arm/switch16.S"),
294 ("__switch32", "arm/switch32.S"),
295 ("__switch8", "arm/switch8.S"),
296 ("__switchu8", "arm/switchu8.S"),
297 ("__sync_synchronize", "arm/sync_synchronize.S"),
298 ("__udivmodsi4", "arm/udivmodsi4.S"),
299 ("__udivsi3", "arm/udivsi3.S"),
300 ("__umodsi3", "arm/umodsi3.S"),
301 ]);
302
303 if target_os == "freebsd" {
304 sources.extend(&[("__clear_cache", "clear_cache.c")]);
305 }
306
307 // First of all aeabi_cdcmp and aeabi_cfcmp are never called by LLVM.
308 // Second are little-endian only, so build fail on big-endian targets.
309 // Temporally workaround: exclude these files for big-endian targets.
310 if !llvm_target[0].starts_with("thumbeb") && !llvm_target[0].starts_with("armeb") {
311 sources.extend(&[
312 ("__aeabi_cdcmp", "arm/aeabi_cdcmp.S"),
313 ("__aeabi_cdcmpeq_check_nan", "arm/aeabi_cdcmpeq_check_nan.c"),
314 ("__aeabi_cfcmp", "arm/aeabi_cfcmp.S"),
315 ("__aeabi_cfcmpeq_check_nan", "arm/aeabi_cfcmpeq_check_nan.c"),
316 ]);
317 }
318 }
319
320 if llvm_target[0] == "armv7" {
321 sources.extend(&[
322 ("__sync_fetch_and_add_4", "arm/sync_fetch_and_add_4.S"),
323 ("__sync_fetch_and_add_8", "arm/sync_fetch_and_add_8.S"),
324 ("__sync_fetch_and_and_4", "arm/sync_fetch_and_and_4.S"),
325 ("__sync_fetch_and_and_8", "arm/sync_fetch_and_and_8.S"),
326 ("__sync_fetch_and_max_4", "arm/sync_fetch_and_max_4.S"),
327 ("__sync_fetch_and_max_8", "arm/sync_fetch_and_max_8.S"),
328 ("__sync_fetch_and_min_4", "arm/sync_fetch_and_min_4.S"),
329 ("__sync_fetch_and_min_8", "arm/sync_fetch_and_min_8.S"),
330 ("__sync_fetch_and_nand_4", "arm/sync_fetch_and_nand_4.S"),
331 ("__sync_fetch_and_nand_8", "arm/sync_fetch_and_nand_8.S"),
332 ("__sync_fetch_and_or_4", "arm/sync_fetch_and_or_4.S"),
333 ("__sync_fetch_and_or_8", "arm/sync_fetch_and_or_8.S"),
334 ("__sync_fetch_and_sub_4", "arm/sync_fetch_and_sub_4.S"),
335 ("__sync_fetch_and_sub_8", "arm/sync_fetch_and_sub_8.S"),
336 ("__sync_fetch_and_umax_4", "arm/sync_fetch_and_umax_4.S"),
337 ("__sync_fetch_and_umax_8", "arm/sync_fetch_and_umax_8.S"),
338 ("__sync_fetch_and_umin_4", "arm/sync_fetch_and_umin_4.S"),
339 ("__sync_fetch_and_umin_8", "arm/sync_fetch_and_umin_8.S"),
340 ("__sync_fetch_and_xor_4", "arm/sync_fetch_and_xor_4.S"),
341 ("__sync_fetch_and_xor_8", "arm/sync_fetch_and_xor_8.S"),
342 ]);
343 }
344
345 if llvm_target.last().unwrap().ends_with("eabihf") {
346 if !llvm_target[0].starts_with("thumbv7em")
347 && !llvm_target[0].starts_with("thumbv8m.main")
348 {
349 // The FPU option chosen for these architectures in cc-rs, ie:
350 // -mfpu=fpv4-sp-d16 for thumbv7em
351 // -mfpu=fpv5-sp-d16 for thumbv8m.main
352 // do not support double precision floating points conversions so the files
353 // that include such instructions are not included for these targets.
354 sources.extend(&[
355 ("__fixdfsivfp", "arm/fixdfsivfp.S"),
356 ("__fixunsdfsivfp", "arm/fixunsdfsivfp.S"),
357 ("__floatsidfvfp", "arm/floatsidfvfp.S"),
358 ("__floatunssidfvfp", "arm/floatunssidfvfp.S"),
359 ]);
360 }
361
362 sources.extend(&[
363 ("__fixsfsivfp", "arm/fixsfsivfp.S"),
364 ("__fixunssfsivfp", "arm/fixunssfsivfp.S"),
365 ("__floatsisfvfp", "arm/floatsisfvfp.S"),
366 ("__floatunssisfvfp", "arm/floatunssisfvfp.S"),
367 ("__floatunssisfvfp", "arm/floatunssisfvfp.S"),
368 ("__restore_vfp_d8_d15_regs", "arm/restore_vfp_d8_d15_regs.S"),
369 ("__save_vfp_d8_d15_regs", "arm/save_vfp_d8_d15_regs.S"),
370 ("__negdf2vfp", "arm/negdf2vfp.S"),
371 ("__negsf2vfp", "arm/negsf2vfp.S"),
372 ]);
373 }
374
375 if target_arch == "aarch64" {
376 sources.extend(&[
377 ("__comparetf2", "comparetf2.c"),
378 ("__extenddftf2", "extenddftf2.c"),
379 ("__extendsftf2", "extendsftf2.c"),
380 ("__fixtfdi", "fixtfdi.c"),
381 ("__fixtfsi", "fixtfsi.c"),
382 ("__fixtfti", "fixtfti.c"),
383 ("__fixunstfdi", "fixunstfdi.c"),
384 ("__fixunstfsi", "fixunstfsi.c"),
385 ("__fixunstfti", "fixunstfti.c"),
386 ("__floatditf", "floatditf.c"),
387 ("__floatsitf", "floatsitf.c"),
388 ("__floatunditf", "floatunditf.c"),
389 ("__floatunsitf", "floatunsitf.c"),
390 ("__trunctfdf2", "trunctfdf2.c"),
391 ("__trunctfsf2", "trunctfsf2.c"),
392 ]);
393
394 if target_os != "windows" {
395 sources.extend(&[("__multc3", "multc3.c")]);
396 }
397 }
398
399 // Remove the assembly implementations that won't compile for the target
400 if llvm_target[0] == "thumbv6m" || llvm_target[0] == "thumbv8m.base" {
401 let mut to_remove = Vec::new();
402 for (k, v) in sources.map.iter() {
403 if v.ends_with(".S") {
404 to_remove.push(*k);
405 }
406 }
407 sources.remove(&to_remove);
408
409 // But use some generic implementations where possible
410 sources.extend(&[("__clzdi2", "clzdi2.c"), ("__clzsi2", "clzsi2.c")])
411 }
412
413 if llvm_target[0] == "thumbv7m" || llvm_target[0] == "thumbv7em" {
414 sources.remove(&["__aeabi_cdcmp", "__aeabi_cfcmp"]);
415 }
416
417 // When compiling the C code we require the user to tell us where the
418 // source code is, and this is largely done so when we're compiling as
419 // part of rust-lang/rust we can use the same llvm-project repository as
420 // rust-lang/rust.
421 let root = match env::var_os("RUST_COMPILER_RT_ROOT") {
422 Some(s) => PathBuf::from(s),
423 None => panic!("RUST_COMPILER_RT_ROOT is not set"),
424 };
425 if !root.exists() {
426 panic!("RUST_COMPILER_RT_ROOT={} does not exist", root.display());
427 }
428
429 // Support deterministic builds by remapping the __FILE__ prefix if the
430 // compiler supports it. This fixes the nondeterminism caused by the
431 // use of that macro in lib/builtins/int_util.h in compiler-rt.
432 cfg.flag_if_supported(&format!("-ffile-prefix-map={}=.", root.display()));
433
434 let src_dir = root.join("lib/builtins");
435 for (sym, src) in sources.map.iter() {
436 let src = src_dir.join(src);
437 cfg.file(&src);
438 println!("cargo:rerun-if-changed={}", src.display());
439 println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
440 }
441
442 cfg.compile("libcompiler-rt.a");
443 }
444 }