1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Compiles the `compiler-rt` library, or at least the builtins part of it.
13 //! Note that while compiler-rt has a build system associated with it, we
14 //! specifically don't use it here. The compiler-rt build system, written in
15 //! CMake, is actually *very* difficult to work with in terms of getting it to
16 //! compile on all the relevant platforms we want it to compile on. In the end
17 //! it became so much pain to work with local patches, work around the oddities
18 //! of the build system, etc, that we're just building everything by hand now.
20 //! In general compiler-rt is just a bunch of intrinsics that are in practice
21 //! *very* stable. We just need to make sure that all the relevant functions and
22 //! such are compiled somewhere and placed in an object file somewhere.
23 //! Eventually, these should all be written in Rust!
25 //! So below you'll find a listing of every single file in the compiler-rt repo
26 //! that we're compiling. We just reach in and compile with the `gcc` crate
27 //! which should have all the relevant flags and such already configured.
29 //! The risk here is that if we update compiler-rt we may need to compile some
30 //! new intrinsics, but to be honest we surely don't use all of the intrinsics
31 //! listed below today so the likelihood of us actually needing a new intrinsic
32 //! is quite low. The failure case is also just that someone reports a link
33 //! error (if any) and then we just add it to the list. Overall, that cost is
34 //! far far less than working with compiler-rt's build system over time.
36 extern crate build_helper;
39 use std::collections::BTreeMap;
42 use build_helper::native_lib_boilerplate;
45 // SYMBOL -> PATH TO SOURCE
46 map: BTreeMap<&'static str, &'static str>,
51 Sources { map: BTreeMap::new() }
54 fn extend(&mut self, sources: &[&'static str]) {
55 // NOTE Some intrinsics have both a generic implementation (e.g.
56 // `floatdidf.c`) and an arch optimized implementation
57 // (`x86_64/floatdidf.c`). In those cases, we keep the arch optimized
58 // implementation and discard the generic implementation. If we don't
59 // and keep both implementations, the linker will yell at us about
62 let symbol = Path::new(src).file_stem().unwrap().to_str().unwrap();
63 if src.contains("/") {
64 // Arch-optimized implementation (preferred)
65 self.map.insert(symbol, src);
67 // Generic implementation
68 if !self.map.contains_key(symbol) {
69 self.map.insert(symbol, src);
77 let target = env::var("TARGET").expect("TARGET was not set");
79 // Emscripten's runtime includes all the builtins
80 if target.contains("emscripten") {
84 // Can't reuse `sources` list for the freshness check becuse it doesn't contain header files.
85 let native = match native_lib_boilerplate("compiler-rt", "compiler-rt", "compiler-rt", ".") {
90 let cfg = &mut gcc::Config::new();
91 cfg.out_dir(&native.out_dir);
93 if target.contains("msvc") {
94 // Don't pull in extra libraries on MSVC
97 // Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP
98 cfg.define("__func__", Some("__FUNCTION__"));
100 // Turn off various features of gcc and such, mostly copying
101 // compiler-rt's build system already
102 cfg.flag("-fno-builtin");
103 cfg.flag("-fvisibility=hidden");
104 // Accepted practice on Solaris is to never omit frame pointer so that
105 // system observability tools work as expected. In addition, at least
106 // on Solaris, -fomit-frame-pointer on sparcv9 appears to generate
107 // references to data outside of the current stack frame. A search of
108 // the gcc bug database provides a variety of issues surrounding
109 // -fomit-frame-pointer on non-x86 platforms.
110 if !target.contains("solaris") && !target.contains("sparc") {
111 cfg.flag("-fomit-frame-pointer");
113 cfg.flag("-ffreestanding");
114 cfg.define("VISIBILITY_HIDDEN", None);
117 let mut sources = Sources::new();
118 sources.extend(&["absvdi2.c",
124 "apple_versioning.c",
209 if !target.contains("ios") {
210 sources.extend(&["absvti2.c",
246 if target.contains("apple") {
247 sources.extend(&["atomic_flag_clear.c",
248 "atomic_flag_clear_explicit.c",
249 "atomic_flag_test_and_set.c",
250 "atomic_flag_test_and_set_explicit.c",
251 "atomic_signal_fence.c",
252 "atomic_thread_fence.c"]);
255 if target.contains("msvc") {
256 if target.contains("x86_64") {
257 sources.extend(&["x86_64/floatdidf.c", "x86_64/floatdisf.c", "x86_64/floatdixf.c"]);
260 if !target.contains("freebsd") && !target.contains("netbsd") {
261 sources.extend(&["gcc_personality_v0.c"]);
264 if target.contains("x86_64") {
265 sources.extend(&["x86_64/chkstk.S",
267 "x86_64/floatdidf.c",
268 "x86_64/floatdisf.c",
269 "x86_64/floatdixf.c",
270 "x86_64/floatundidf.S",
271 "x86_64/floatundisf.S",
272 "x86_64/floatundixf.S"]);
275 if target.contains("i386") || target.contains("i586") || target.contains("i686") {
276 sources.extend(&["i386/ashldi3.S",
284 "i386/floatundidf.S",
285 "i386/floatundisf.S",
286 "i386/floatundixf.S",
295 if target.contains("arm") && !target.contains("ios") {
296 sources.extend(&["arm/aeabi_cdcmp.S",
297 "arm/aeabi_cdcmpeq_check_nan.c",
299 "arm/aeabi_cfcmpeq_check_nan.c",
305 "arm/aeabi_idivmod.S",
306 "arm/aeabi_ldivmod.S",
307 "arm/aeabi_memcmp.S",
308 "arm/aeabi_memcpy.S",
309 "arm/aeabi_memmove.S",
310 "arm/aeabi_memset.S",
311 "arm/aeabi_uidivmod.S",
312 "arm/aeabi_uldivmod.S",
325 "arm/sync_synchronize.S",
331 if target.contains("armv7") {
332 sources.extend(&["arm/sync_fetch_and_add_4.S",
333 "arm/sync_fetch_and_add_8.S",
334 "arm/sync_fetch_and_and_4.S",
335 "arm/sync_fetch_and_and_8.S",
336 "arm/sync_fetch_and_max_4.S",
337 "arm/sync_fetch_and_max_8.S",
338 "arm/sync_fetch_and_min_4.S",
339 "arm/sync_fetch_and_min_8.S",
340 "arm/sync_fetch_and_nand_4.S",
341 "arm/sync_fetch_and_nand_8.S",
342 "arm/sync_fetch_and_or_4.S",
343 "arm/sync_fetch_and_or_8.S",
344 "arm/sync_fetch_and_sub_4.S",
345 "arm/sync_fetch_and_sub_8.S",
346 "arm/sync_fetch_and_umax_4.S",
347 "arm/sync_fetch_and_umax_8.S",
348 "arm/sync_fetch_and_umin_4.S",
349 "arm/sync_fetch_and_umin_8.S",
350 "arm/sync_fetch_and_xor_4.S",
351 "arm/sync_fetch_and_xor_8.S"]);
354 if target.contains("eabihf") {
355 sources.extend(&["arm/adddf3vfp.S",
361 "arm/extendsfdf2vfp.S",
364 "arm/fixunsdfsivfp.S",
365 "arm/fixunssfsivfp.S",
366 "arm/floatsidfvfp.S",
367 "arm/floatsisfvfp.S",
368 "arm/floatunssidfvfp.S",
369 "arm/floatunssisfvfp.S",
384 "arm/restore_vfp_d8_d15_regs.S",
385 "arm/save_vfp_d8_d15_regs.S",
388 "arm/truncdfsf2vfp.S",
390 "arm/unordsf2vfp.S"]);
393 if target.contains("aarch64") {
394 sources.extend(&["comparetf2.c",
412 for src in sources.map.values() {
413 cfg.file(Path::new("../compiler-rt/lib/builtins").join(src));
416 cfg.compile("libcompiler-rt.a");