Switch to rust-lang-nursery/compiler-builtins

This commit migrates the in-tree `libcompiler_builtins` to the upstream version
at https://github.com/rust-lang-nursery/compiler-builtins. The upstream version
has a number of intrinsics written in Rust and serves as an in-progress rewrite
of compiler-rt into Rust. Additionally it also contains all the existing
intrinsics defined in `libcompiler_builtins` for 128-bit integers.

It's been the intention since the beginning to make this transition but
previously it just lacked the manpower to get done. As this PR likely shows it
wasn't a trivial integration! Some highlight changes are:

* The PR rust-lang-nursery/compiler-builtins#166 contains a number of fixes
  across platforms and also some refactorings to make the intrinsics easier to
  read. The additional testing added there also fixed a number of integration
  issues when pulling the repository into this tree.

* LTO with the compiler-builtins crate was fixed to link in the entire crate
  after the LTO process as these intrinsics are excluded from LTO.

* Treatment of hidden symbols was updated as previously the
  `#![compiler_builtins]` crate would mark all symbol *imports* as hidden
  whereas it was only intended to mark *exports* as hidden.
This commit is contained in:
Alex Crichton 2017-06-22 13:14:00 -07:00
parent 1d2db7b9e8
commit 7e6c9f3635
25 changed files with 110 additions and 1245 deletions

6
.gitmodules vendored
View File

@ -2,9 +2,6 @@
path = src/llvm
url = https://github.com/rust-lang/llvm.git
branch = master
[submodule "src/compiler-rt"]
path = src/compiler-rt
url = https://github.com/rust-lang/compiler-rt.git
[submodule "src/rt/hoedown"]
path = src/rt/hoedown
url = https://github.com/rust-lang/hoedown.git
@ -33,3 +30,6 @@
[submodule "src/tools/rls"]
path = src/tools/rls
url = https://github.com/rust-lang-nursery/rls.git
[submodule "src/libcompiler_builtins"]
path = src/libcompiler_builtins
url = https://github.com/rust-lang-nursery/compiler-builtins

1
src/Cargo.lock generated
View File

@ -273,7 +273,6 @@ dependencies = [
name = "compiler_builtins"
version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
"core 0.0.0",
"gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
]

View File

@ -142,6 +142,11 @@ fn main() {
}
}
let crate_name = args.windows(2)
.find(|a| &*a[0] == "--crate-name")
.unwrap();
let crate_name = &*crate_name[1];
// If we're compiling specifically the `panic_abort` crate then we pass
// the `-C panic=abort` option. Note that we do not do this for any
// other crate intentionally as this is the only crate for now that we
@ -150,9 +155,7 @@ fn main() {
// This... is a bit of a hack how we detect this. Ideally this
// information should be encoded in the crate I guess? Would likely
// require an RFC amendment to RFC 1513, however.
let is_panic_abort = args.windows(2)
.any(|a| &*a[0] == "--crate-name" && &*a[1] == "panic_abort");
if is_panic_abort {
if crate_name == "panic_abort" {
cmd.arg("-C").arg("panic=abort");
}
@ -167,7 +170,15 @@ fn main() {
Ok(s) => if s == "true" { "y" } else { "n" },
Err(..) => "n",
};
// The compiler builtins are pretty sensitive to symbols referenced in
// libcore and such, so we never compile them with debug assertions.
if crate_name == "compiler_builtins" {
cmd.arg("-C").arg("debug-assertions=no");
} else {
cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions));
}
if let Ok(s) = env::var("RUSTC_CODEGEN_UNITS") {
cmd.arg("-C").arg(format!("codegen-units={}", s));
}

View File

@ -583,7 +583,7 @@ class RustBuild(object):
(self.get_toml('jemalloc') or
self.get_mk('CFG_JEMALLOC_ROOT'))))]
run(["git", "submodule", "update",
"--init"] + submodules,
"--init", "--recursive"] + submodules,
cwd=self.rust_root, verbose=self.verbose)
run(["git", "submodule", "-q", "foreach", "git",
"reset", "-q", "--hard"],

View File

@ -564,10 +564,10 @@ pub fn rust_src(build: &Build) {
"src/libstd",
"src/libstd_unicode",
"src/libunwind",
"src/rustc/compiler_builtins_shim",
"src/rustc/libc_shim",
"src/libtest",
"src/libterm",
"src/compiler-rt",
"src/jemalloc",
"src/libprofiler_builtins",
];

View File

@ -239,7 +239,10 @@ pub fn sanitizer_lib_boilerplate(sanitizer_name: &str) -> Result<NativeLibBoiler
),
_ => return Err(()),
};
native_lib_boilerplate("compiler-rt", sanitizer_name, &link_name, search_path)
native_lib_boilerplate("libcompiler_builtins/compiler-rt",
sanitizer_name,
&link_name,
search_path)
}
fn dir_up_to_date(src: &Path, threshold: &FileTime) -> bool {

View File

@ -67,13 +67,14 @@ for module in $modules; do
mv "src/llvm-$commit" src/llvm
continue
fi
if [ ! -d "$cache_src_dir/$module" ]; then
if [ ! -e "$cache_src_dir/$module/.git" ]; then
echo "WARNING: $module not found in pristine repo"
retry sh -c "git submodule deinit -f $module && git submodule update --init $module"
retry sh -c "git submodule deinit -f $module && \
git submodule update --init --recursive $module"
continue
fi
retry sh -c "git submodule deinit -f $module && \
git submodule update --init --reference $cache_src_dir/$module $module"
git submodule update --init --recursive --reference $cache_src_dir/$module $module"
done
travis_fold end update_submodules

@ -1 +0,0 @@
Subproject commit c8a8767c56ad3d3f4eb45c87b95026936fb9aa35

View File

@ -1,35 +0,0 @@
# `compiler_builtins_lib`
The tracking issue for this feature is: None.
------------------------
This feature is required to link to the `compiler_builtins` crate which contains
"compiler intrinsics". Compiler intrinsics are software implementations of basic
operations like multiplication of `u64`s. These intrinsics are only required on
platforms where these operations don't directly map to a hardware instruction.
You should never need to explicitly link to the `compiler_builtins` crate when
building "std" programs as `compiler_builtins` is already in the dependency
graph of `std`. But you may need it when building `no_std` **binary** crates. If
you get a *linker* error like:
``` text
$PWD/src/main.rs:11: undefined reference to `__aeabi_lmul'
$PWD/src/main.rs:11: undefined reference to `__aeabi_uldivmod'
```
That means that you need to link to this crate.
When you link to this crate, make sure it only appears once in your crate
dependency graph. Also, it doesn't matter where in the dependency graph, you
place the `compiler_builtins` crate.
<!-- NOTE(ignore) doctests don't support `no_std` binaries -->
``` rust,ignore
#![feature(compiler_builtins_lib)]
#![no_std]
extern crate compiler_builtins;
```

@ -0,0 +1 @@
Subproject commit 238647af806470dc73e585c03682083931d29cd5

View File

@ -1,19 +0,0 @@
[package]
authors = ["The Rust Project Developers"]
build = "build.rs"
name = "compiler_builtins"
version = "0.0.0"
[lib]
name = "compiler_builtins"
path = "lib.rs"
test = false
bench = false
doc = false
[dependencies]
core = { path = "../libcore" }
[build-dependencies]
build_helper = { path = "../build_helper" }
gcc = "0.3.50"

View File

@ -1,423 +0,0 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Compiles the `compiler-rt` library, or at least the builtins part of it.
//!
//! Note that while compiler-rt has a build system associated with it, we
//! specifically don't use it here. The compiler-rt build system, written in
//! CMake, is actually *very* difficult to work with in terms of getting it to
//! compile on all the relevant platforms we want it to compile on. In the end
//! it became so much pain to work with local patches, work around the oddities
//! of the build system, etc, that we're just building everything by hand now.
//!
//! In general compiler-rt is just a bunch of intrinsics that are in practice
//! *very* stable. We just need to make sure that all the relevant functions and
//! such are compiled somewhere and placed in an object file somewhere.
//! Eventually, these should all be written in Rust!
//!
//! So below you'll find a listing of every single file in the compiler-rt repo
//! that we're compiling. We just reach in and compile with the `gcc` crate
//! which should have all the relevant flags and such already configured.
//!
//! The risk here is that if we update compiler-rt we may need to compile some
//! new intrinsics, but to be honest we surely don't use all of the intrinsics
//! listed below today so the likelihood of us actually needing a new intrinsic
//! is quite low. The failure case is also just that someone reports a link
//! error (if any) and then we just add it to the list. Overall, that cost is
//! far far less than working with compiler-rt's build system over time.
extern crate build_helper;
extern crate gcc;
use std::collections::BTreeMap;
use std::env;
use std::path::Path;
use build_helper::native_lib_boilerplate;
struct Sources {
// SYMBOL -> PATH TO SOURCE
map: BTreeMap<&'static str, &'static str>,
}
impl Sources {
fn new() -> Sources {
Sources { map: BTreeMap::new() }
}
fn extend(&mut self, sources: &[&'static str]) {
// NOTE Some intrinsics have both a generic implementation (e.g.
// `floatdidf.c`) and an arch optimized implementation
// (`x86_64/floatdidf.c`). In those cases, we keep the arch optimized
// implementation and discard the generic implementation. If we don't
// and keep both implementations, the linker will yell at us about
// duplicate symbols!
for &src in sources {
let symbol = Path::new(src).file_stem().unwrap().to_str().unwrap();
if src.contains("/") {
// Arch-optimized implementation (preferred)
self.map.insert(symbol, src);
} else {
// Generic implementation
if !self.map.contains_key(symbol) {
self.map.insert(symbol, src);
}
}
}
}
}
fn main() {
let target = env::var("TARGET").expect("TARGET was not set");
// Emscripten's runtime includes all the builtins
if target.contains("emscripten") {
return;
}
// Can't reuse `sources` list for the freshness check becuse it doesn't contain header files.
let native = match native_lib_boilerplate("compiler-rt", "compiler-rt", "compiler-rt", ".") {
Ok(native) => native,
_ => return,
};
let cfg = &mut gcc::Config::new();
cfg.out_dir(&native.out_dir);
if target.contains("msvc") {
// Don't pull in extra libraries on MSVC
cfg.flag("/Zl");
// Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP
cfg.define("__func__", Some("__FUNCTION__"));
} else {
// Turn off various features of gcc and such, mostly copying
// compiler-rt's build system already
cfg.flag("-fno-builtin");
cfg.flag("-fvisibility=hidden");
// Accepted practice on Solaris is to never omit frame pointer so that
// system observability tools work as expected. In addition, at least
// on Solaris, -fomit-frame-pointer on sparcv9 appears to generate
// references to data outside of the current stack frame. A search of
// the gcc bug database provides a variety of issues surrounding
// -fomit-frame-pointer on non-x86 platforms.
if !target.contains("solaris") && !target.contains("sparc") {
cfg.flag("-fomit-frame-pointer");
}
cfg.flag("-ffreestanding");
cfg.define("VISIBILITY_HIDDEN", None);
}
let mut sources = Sources::new();
sources.extend(&["absvdi2.c",
"absvsi2.c",
"adddf3.c",
"addsf3.c",
"addvdi3.c",
"addvsi3.c",
"apple_versioning.c",
"ashldi3.c",
"ashrdi3.c",
"clzdi2.c",
"clzsi2.c",
"cmpdi2.c",
"comparedf2.c",
"comparesf2.c",
"ctzdi2.c",
"ctzsi2.c",
"divdc3.c",
"divdf3.c",
"divdi3.c",
"divmoddi4.c",
"divmodsi4.c",
"divsc3.c",
"divsf3.c",
"divsi3.c",
"divxc3.c",
"extendsfdf2.c",
"extendhfsf2.c",
"ffsdi2.c",
"fixdfdi.c",
"fixdfsi.c",
"fixsfdi.c",
"fixsfsi.c",
"fixunsdfdi.c",
"fixunsdfsi.c",
"fixunssfdi.c",
"fixunssfsi.c",
"fixunsxfdi.c",
"fixunsxfsi.c",
"fixxfdi.c",
"floatdidf.c",
"floatdisf.c",
"floatdixf.c",
"floatsidf.c",
"floatsisf.c",
"floatundidf.c",
"floatundisf.c",
"floatundixf.c",
"floatunsidf.c",
"floatunsisf.c",
"int_util.c",
"lshrdi3.c",
"moddi3.c",
"modsi3.c",
"muldc3.c",
"muldf3.c",
"muldi3.c",
"mulodi4.c",
"mulosi4.c",
"muloti4.c",
"mulsc3.c",
"mulsf3.c",
"mulvdi3.c",
"mulvsi3.c",
"mulxc3.c",
"negdf2.c",
"negdi2.c",
"negsf2.c",
"negvdi2.c",
"negvsi2.c",
"paritydi2.c",
"paritysi2.c",
"popcountdi2.c",
"popcountsi2.c",
"powidf2.c",
"powisf2.c",
"powixf2.c",
"subdf3.c",
"subsf3.c",
"subvdi3.c",
"subvsi3.c",
"truncdfhf2.c",
"truncdfsf2.c",
"truncsfhf2.c",
"ucmpdi2.c",
"udivdi3.c",
"udivmoddi4.c",
"udivmodsi4.c",
"udivsi3.c",
"umoddi3.c",
"umodsi3.c"]);
if !target.contains("ios") {
sources.extend(&["absvti2.c",
"addvti3.c",
"ashlti3.c",
"ashrti3.c",
"clzti2.c",
"cmpti2.c",
"ctzti2.c",
"divti3.c",
"ffsti2.c",
"fixdfti.c",
"fixsfti.c",
"fixunsdfti.c",
"fixunssfti.c",
"fixunsxfti.c",
"fixxfti.c",
"floattidf.c",
"floattisf.c",
"floattixf.c",
"floatuntidf.c",
"floatuntisf.c",
"floatuntixf.c",
"lshrti3.c",
"modti3.c",
"multi3.c",
"mulvti3.c",
"negti2.c",
"negvti2.c",
"parityti2.c",
"popcountti2.c",
"subvti3.c",
"ucmpti2.c",
"udivmodti4.c",
"udivti3.c",
"umodti3.c"]);
}
if target.contains("apple") {
sources.extend(&["atomic_flag_clear.c",
"atomic_flag_clear_explicit.c",
"atomic_flag_test_and_set.c",
"atomic_flag_test_and_set_explicit.c",
"atomic_signal_fence.c",
"atomic_thread_fence.c"]);
}
if target.contains("msvc") {
if target.contains("x86_64") {
sources.extend(&["x86_64/floatdidf.c", "x86_64/floatdisf.c", "x86_64/floatdixf.c"]);
}
} else {
if !target.contains("freebsd") && !target.contains("netbsd") {
sources.extend(&["gcc_personality_v0.c"]);
}
if target.contains("x86_64") {
sources.extend(&["x86_64/chkstk.S",
"x86_64/chkstk2.S",
"x86_64/floatdidf.c",
"x86_64/floatdisf.c",
"x86_64/floatdixf.c",
"x86_64/floatundidf.S",
"x86_64/floatundisf.S",
"x86_64/floatundixf.S"]);
}
if target.contains("i386") || target.contains("i586") || target.contains("i686") {
sources.extend(&["i386/ashldi3.S",
"i386/ashrdi3.S",
"i386/chkstk.S",
"i386/chkstk2.S",
"i386/divdi3.S",
"i386/floatdidf.S",
"i386/floatdisf.S",
"i386/floatdixf.S",
"i386/floatundidf.S",
"i386/floatundisf.S",
"i386/floatundixf.S",
"i386/lshrdi3.S",
"i386/moddi3.S",
"i386/muldi3.S",
"i386/udivdi3.S",
"i386/umoddi3.S"]);
}
}
if target.contains("arm") && !target.contains("ios") {
// (At least) udivsi3.S is broken for Thumb 1 which our gcc uses by
// default, we don't want Thumb 2 since it isn't supported on some
// devices, so disable thumb entirely.
// Upstream bug: https://bugs.llvm.org/show_bug.cgi?id=32492
cfg.define("__ARM_ARCH_ISA_THUMB", Some("0"));
sources.extend(&["arm/aeabi_cdcmp.S",
"arm/aeabi_cdcmpeq_check_nan.c",
"arm/aeabi_cfcmp.S",
"arm/aeabi_cfcmpeq_check_nan.c",
"arm/aeabi_dcmp.S",
"arm/aeabi_div0.c",
"arm/aeabi_drsub.c",
"arm/aeabi_fcmp.S",
"arm/aeabi_frsub.c",
"arm/aeabi_idivmod.S",
"arm/aeabi_ldivmod.S",
"arm/aeabi_memcmp.S",
"arm/aeabi_memcpy.S",
"arm/aeabi_memmove.S",
"arm/aeabi_memset.S",
"arm/aeabi_uidivmod.S",
"arm/aeabi_uldivmod.S",
"arm/bswapdi2.S",
"arm/bswapsi2.S",
"arm/clzdi2.S",
"arm/clzsi2.S",
"arm/comparesf2.S",
"arm/divmodsi4.S",
"arm/divsi3.S",
"arm/modsi3.S",
"arm/switch16.S",
"arm/switch32.S",
"arm/switch8.S",
"arm/switchu8.S",
"arm/sync_synchronize.S",
"arm/udivmodsi4.S",
"arm/udivsi3.S",
"arm/umodsi3.S"]);
}
if target.contains("armv7") {
sources.extend(&["arm/sync_fetch_and_add_4.S",
"arm/sync_fetch_and_add_8.S",
"arm/sync_fetch_and_and_4.S",
"arm/sync_fetch_and_and_8.S",
"arm/sync_fetch_and_max_4.S",
"arm/sync_fetch_and_max_8.S",
"arm/sync_fetch_and_min_4.S",
"arm/sync_fetch_and_min_8.S",
"arm/sync_fetch_and_nand_4.S",
"arm/sync_fetch_and_nand_8.S",
"arm/sync_fetch_and_or_4.S",
"arm/sync_fetch_and_or_8.S",
"arm/sync_fetch_and_sub_4.S",
"arm/sync_fetch_and_sub_8.S",
"arm/sync_fetch_and_umax_4.S",
"arm/sync_fetch_and_umax_8.S",
"arm/sync_fetch_and_umin_4.S",
"arm/sync_fetch_and_umin_8.S",
"arm/sync_fetch_and_xor_4.S",
"arm/sync_fetch_and_xor_8.S"]);
}
if target.contains("eabihf") {
sources.extend(&["arm/adddf3vfp.S",
"arm/addsf3vfp.S",
"arm/divdf3vfp.S",
"arm/divsf3vfp.S",
"arm/eqdf2vfp.S",
"arm/eqsf2vfp.S",
"arm/extendsfdf2vfp.S",
"arm/fixdfsivfp.S",
"arm/fixsfsivfp.S",
"arm/fixunsdfsivfp.S",
"arm/fixunssfsivfp.S",
"arm/floatsidfvfp.S",
"arm/floatsisfvfp.S",
"arm/floatunssidfvfp.S",
"arm/floatunssisfvfp.S",
"arm/gedf2vfp.S",
"arm/gesf2vfp.S",
"arm/gtdf2vfp.S",
"arm/gtsf2vfp.S",
"arm/ledf2vfp.S",
"arm/lesf2vfp.S",
"arm/ltdf2vfp.S",
"arm/ltsf2vfp.S",
"arm/muldf3vfp.S",
"arm/mulsf3vfp.S",
"arm/negdf2vfp.S",
"arm/negsf2vfp.S",
"arm/nedf2vfp.S",
"arm/nesf2vfp.S",
"arm/restore_vfp_d8_d15_regs.S",
"arm/save_vfp_d8_d15_regs.S",
"arm/subdf3vfp.S",
"arm/subsf3vfp.S",
"arm/truncdfsf2vfp.S",
"arm/unorddf2vfp.S",
"arm/unordsf2vfp.S"]);
}
if target.contains("aarch64") {
sources.extend(&["comparetf2.c",
"extenddftf2.c",
"extendsftf2.c",
"fixtfdi.c",
"fixtfsi.c",
"fixtfti.c",
"fixunstfdi.c",
"fixunstfsi.c",
"fixunstfti.c",
"floatditf.c",
"floatsitf.c",
"floatunditf.c",
"floatunsitf.c",
"multc3.c",
"trunctfdf2.c",
"trunctfsf2.c"]);
}
for src in sources.map.values() {
cfg.file(Path::new("../compiler-rt/lib/builtins").join(src));
}
cfg.compile("libcompiler-rt.a");
}

View File

@ -1,721 +0,0 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(compiler_builtins)]
#![no_std]
#![compiler_builtins]
#![unstable(feature = "compiler_builtins_lib",
reason = "internal implementation detail of rustc right now",
issue = "0")]
#![crate_name = "compiler_builtins"]
#![crate_type = "rlib"]
#![allow(unused_features)]
#![feature(staged_api, core_intrinsics, repr_simd,
i128_type, core_float, abi_unadjusted, associated_consts)]
#![allow(non_camel_case_types, unused_variables, unused_imports)]
#[cfg(any(target_pointer_width="32", target_pointer_width="16", target_os="windows",
target_arch="mips64"))]
pub mod reimpls {
#![allow(unused_comparisons)]
use core::intrinsics::unchecked_div;
use core::intrinsics::unchecked_rem;
use core::ptr;
macro_rules! ashl {
($a:expr, $b:expr, $ty:ty) => {{
let (a, b) = ($a, $b);
let bits = ::core::mem::size_of::<$ty>().wrapping_mul(8) as $ty;
let half_bits = bits.wrapping_shr(1);
if b & half_bits != 0 {
<$ty>::from_parts(0, a.low().wrapping_shl(
b.wrapping_sub(half_bits) as u32))
} else if b == 0 {
a
} else {
<$ty>::from_parts(a.low().wrapping_shl(b as u32),
a.high().wrapping_shl(b as u32)
| a.low()
.wrapping_shr(half_bits.wrapping_sub(b) as u32))
}
}}
}
#[export_name="__ashlti3"]
pub extern "C" fn shl(a: u128, b: u128) -> u128 {
ashl!(a, b, u128)
}
macro_rules! ashr {
($a: expr, $b: expr, $ty:ty) => {{
let (a, b) = ($a, $b);
let bits = ::core::mem::size_of::<$ty>().wrapping_mul(8) as $ty;
let half_bits = bits.wrapping_shr(1);
if b & half_bits != 0 {
<$ty>::from_parts(a.high().wrapping_shr(b.wrapping_sub(half_bits) as u32)
as <$ty as LargeInt>::LowHalf,
a.high().wrapping_shr(half_bits.wrapping_sub(1) as u32))
} else if b == 0 {
a
} else {
let high_unsigned = a.high() as <$ty as LargeInt>::LowHalf;
<$ty>::from_parts(high_unsigned.wrapping_shl(half_bits.wrapping_sub(b) as u32)
| a.low().wrapping_shr(b as u32),
a.high().wrapping_shr(b as u32))
}
}}
}
#[export_name="__ashrti3"]
pub extern "C" fn shr(a: i128, b: i128) -> i128 {
ashr!(a, b, i128)
}
macro_rules! lshr {
($a: expr, $b: expr, $ty:ty) => {{
let (a, b) = ($a, $b);
let bits = ::core::mem::size_of::<$ty>().wrapping_mul(8) as $ty;
let half_bits = bits.wrapping_shr(1);
if b & half_bits != 0 {
<$ty>::from_parts(a.high().wrapping_shr(b.wrapping_sub(half_bits) as u32), 0)
} else if b == 0 {
a
} else {
<$ty>::from_parts(a.high().wrapping_shl(half_bits.wrapping_sub(b) as u32)
| a.low().wrapping_shr(b as u32),
a.high().wrapping_shr(b as u32))
}
}}
}
#[export_name="__lshrti3"]
pub extern "C" fn lshr(a: u128, b: u128) -> u128 {
lshr!(a, b, u128)
}
pub extern "C" fn u128_div_mod(n: u128, d: u128, rem: *mut u128) -> u128 {
// Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide
unsafe {
// special cases, X is unknown, K != 0
if n.high() == 0 {
if d.high() == 0 {
// 0 X
// ---
// 0 X
if !rem.is_null() {
*rem = u128::from(unchecked_rem(n.low(), d.low()));
}
return u128::from(unchecked_div(n.low(), d.low()));
} else {
// 0 X
// ---
// K X
if !rem.is_null() {
*rem = n;
}
return 0;
};
}
let mut sr;
let mut q;
let mut r;
if d.low() == 0 {
if d.high() == 0 {
// K X
// ---
// 0 0
if !rem.is_null() {
*rem = u128::from(unchecked_rem(n.high(), d.low()));
}
return u128::from(unchecked_div(n.high(), d.low()));
}
if n.low() == 0 {
// K 0
// ---
// K 0
if !rem.is_null() {
*rem = u128::from_parts(0, unchecked_rem(n.high(), d.high()));
}
return u128::from(unchecked_div(n.high(), d.high()));
}
// K K
// ---
// K 0
if d.high().is_power_of_two() {
if !rem.is_null() {
*rem = u128::from_parts(n.low(),
n.high() & (d.high().wrapping_sub(1)));
}
return u128::from(n.high().wrapping_shr(d.high().trailing_zeros()));
}
// K K
// ---
// K 0
sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());
// D > N
if sr > 64 - 2 {
if !rem.is_null() {
*rem = n;
}
return 0;
}
sr = sr.wrapping_add(1);
// 1 <= sr <= u64::bits() - 1
q = n.wrapping_shl(128u32.wrapping_sub(sr));
r = n.wrapping_shr(sr);
} else {
if d.high() == 0 {
// K X
// ---
// 0 K
if d.low().is_power_of_two() {
if !rem.is_null() {
*rem = u128::from(n.low() & (d.low().wrapping_sub(1)));
}
if d.low() == 1 {
return n;
} else {
let sr = d.low().trailing_zeros();
return n.wrapping_shr(sr);
};
}
sr = (1 + 64u32)
.wrapping_add(d.low().leading_zeros())
.wrapping_sub(n.high().leading_zeros());
// 2 <= sr <= u64::bits() - 1
q = n.wrapping_shl(128u32.wrapping_sub(sr));
r = n.wrapping_shr(sr);
// FIXME the C compiler-rt implementation has something here
// that looks like a speed optimisation.
// It would be worth a try to port it to Rust too and
// compare the speed.
} else {
// K X
// ---
// K K
sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());
// D > N
if sr > 64 - 1 {
if !rem.is_null() {
*rem = n;
}
return 0;
}
sr = sr.wrapping_add(1);
// 1 <= sr <= u32::bits()
q = n.wrapping_shl(128u32.wrapping_sub(sr));
r = n.wrapping_shr(sr);
}
}
// Not a special case
// q and r are initialized with
// q = n << (u64::bits() - sr)
// r = n >> sr
// 1 <= sr <= u64::bits() - 1
let mut carry = 0;
// FIXME: replace this with a for loop
// (atm not doable as this generates call to
// eh_personality when optimisations are turned off,
// which in turn gives a linker error in later
// compilation steps)
while sr > 0 {
// r:q = ((r:q) << 1) | carry
r = r.wrapping_shl(1) | q.wrapping_shr(128 - 1);
q = q.wrapping_shl(1) | carry as u128;
// carry = 0
// if r >= d {
// r -= d;
// carry = 1;
// }
let s = ((d.wrapping_sub(r).wrapping_sub(1)) as i128).wrapping_shr(128 - 1);
carry = (s & 1) as u64;
r = r.wrapping_sub(d & s as u128);
sr = sr.wrapping_sub(1);
}
if !rem.is_null() {
*rem = r;
}
(q.wrapping_shl(1)) | carry as u128
}
}
fn i128_mod(a: i128, b: i128) -> i128 {
let b = b.uabs();
let sa = a.signum();
let a = a.uabs();
unsafe {
let mut r = ::core::mem::zeroed();
u128_div_mod(a, b, &mut r);
if sa == -1 { (r as i128).unchecked_neg() } else { r as i128 }
}
}
fn i128_div(a: i128, b: i128) -> i128 {
let sa = a.signum();
let sb = b.signum();
let a = a.uabs();
let b = b.uabs();
let sr = sa.wrapping_mul(sb); // sign of quotient
(if sr == -1 {
(u128_div_mod(a, b, ptr::null_mut()) as i128).unchecked_neg()
} else {
u128_div_mod(a, b, ptr::null_mut()) as i128
})
}
macro_rules! mulo {
($a:expr, $b:expr, $o: expr, $ty: ty) => {{
let (a, b, overflow) = ($a, $b, $o);
*overflow = 0;
let result = a.wrapping_mul(b);
if a == <$ty>::min_value() {
if b != 0 && b != 1 {
*overflow = 1;
}
return result;
}
if b == <$ty>::min_value() {
if a != 0 && a != 1 {
*overflow = 1;
}
return result;
}
let sa = a.signum();
let abs_a = a.iabs();
let sb = b.signum();
let abs_b = b.iabs();
if abs_a < 2 || abs_b < 2 {
return result;
}
if sa == sb {
if abs_a > unchecked_div(<$ty>::max_value(), abs_b) {
*overflow = 1;
}
} else {
if abs_a > unchecked_div(<$ty>::min_value(), abs_b.unchecked_neg()) {
*overflow = 1;
}
}
result
}}
}
pub trait LargeInt {
type LowHalf;
type HighHalf;
fn low(self) -> Self::LowHalf;
fn high(self) -> Self::HighHalf;
fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self;
}
impl LargeInt for u128 {
type LowHalf = u64;
type HighHalf = u64;
fn low(self) -> u64 {
self as u64
}
fn high(self) -> u64 {
self.wrapping_shr(64) as u64
}
fn from_parts(low: u64, high: u64) -> u128 {
(high as u128).wrapping_shl(64) | low as u128
}
}
impl LargeInt for i128 {
type LowHalf = u64;
type HighHalf = i64;
fn low(self) -> u64 {
self as u64
}
fn high(self) -> i64 {
self.wrapping_shr(64) as i64
}
fn from_parts(low: u64, high: i64) -> i128 {
u128::from_parts(low, high as u64) as i128
}
}
macro_rules! mul {
($a:expr, $b:expr, $ty: ty, $tyh: ty) => {{
let (a, b) = ($a, $b);
let half_bits = ::core::mem::size_of::<$tyh>().wrapping_mul(4) as u32;
let lower_mask = (!0u64).wrapping_shr(half_bits);
let mut low = (a.low() & lower_mask).wrapping_mul(b.low() & lower_mask);
let mut t = low.wrapping_shr(half_bits);
low &= lower_mask;
t = t.wrapping_add(a.low().wrapping_shr(half_bits)
.wrapping_mul(b.low() & lower_mask));
low = low.wrapping_add((t & lower_mask).wrapping_shl(half_bits));
let mut high = t.wrapping_shr(half_bits) as $tyh;
t = low.wrapping_shr(half_bits);
low &= lower_mask;
t = t.wrapping_add(b.low().wrapping_shr(half_bits)
.wrapping_mul(a.low() & lower_mask));
low = low.wrapping_add((t & lower_mask).wrapping_shl(half_bits));
high = high.wrapping_add(t.wrapping_shr(half_bits) as $tyh);
high = high.wrapping_add(a.low().wrapping_shr(half_bits)
.wrapping_mul(b.low().wrapping_shr(half_bits)) as $tyh);
high = high
.wrapping_add(a.high()
.wrapping_mul(b.low() as $tyh))
.wrapping_add((a.low() as $tyh)
.wrapping_mul(b.high()));
<$ty>::from_parts(low, high)
}}
}
#[export_name="__multi3"]
pub extern "C" fn u128_mul(a: i128, b: i128) -> i128 {
mul!(a, b, i128, i64)
}
trait AbsExt: Sized {
fn uabs(self) -> u128;
fn iabs(self) -> i128;
}
impl AbsExt for i128 {
fn uabs(self) -> u128 {
self.iabs() as u128
}
fn iabs(self) -> i128 {
let s = self.wrapping_shr(127);
((self ^ s).wrapping_sub(s))
}
}
trait NegExt: Sized {
fn unchecked_neg(self) -> i128;
}
impl NegExt for i128 {
fn unchecked_neg(self) -> i128 {
(!self).wrapping_add(1)
}
}
trait FloatStuff: Sized {
type ToBytes;
const MANTISSA_BITS: u32;
const MAX_EXP: i32;
const EXP_MASK: Self::ToBytes;
const MANTISSA_MASK: Self::ToBytes;
const MANTISSA_LEAD_BIT: Self::ToBytes;
fn to_bytes(self) -> Self::ToBytes;
fn get_exponent(self) -> i32;
}
impl FloatStuff for f32 {
type ToBytes = u32;
const MANTISSA_BITS: u32 = 23;
const MAX_EXP: i32 = 127;
const EXP_MASK: u32 = 0x7F80_0000;
const MANTISSA_MASK: u32 = 0x007F_FFFF;
const MANTISSA_LEAD_BIT: u32 = 0x0080_0000;
fn to_bytes(self) -> u32 { unsafe { ::core::mem::transmute(self) } }
fn get_exponent(self) -> i32 {
((self.to_bytes() & Self::EXP_MASK).wrapping_shr(Self::MANTISSA_BITS) as i32)
.wrapping_sub(Self::MAX_EXP)
}
}
impl FloatStuff for f64 {
type ToBytes = u64;
const MANTISSA_BITS: u32 = 52;
const MAX_EXP: i32 = 1023;
const EXP_MASK: u64 = 0x7FF0_0000_0000_0000;
const MANTISSA_MASK: u64 = 0x000F_FFFF_FFFF_FFFF;
const MANTISSA_LEAD_BIT: u64 = 0x0010_0000_0000_0000;
fn to_bytes(self) -> u64 { unsafe { ::core::mem::transmute(self) } }
fn get_exponent(self) -> i32 {
((self.to_bytes() & Self::EXP_MASK).wrapping_shr(Self::MANTISSA_BITS) as i32)
.wrapping_sub(Self::MAX_EXP)
}
}
macro_rules! float_as_unsigned {
($from: expr, $fromty: ty, $outty: ty) => { {
use core::num::Float;
let repr = $from.to_bytes();
let sign = $from.signum();
let exponent = $from.get_exponent();
let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK;
let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT;
if sign == -1.0 || exponent < 0 { return 0 as u128; }
if exponent > ::core::mem::size_of::<$outty>().wrapping_mul(8) as i32 {
return !(0 as u128);
}
(if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 {
(mantissa as $outty)
.wrapping_shr((<$fromty as FloatStuff>::MANTISSA_BITS as i32)
.wrapping_sub(exponent) as u32)
} else {
(mantissa as $outty)
.wrapping_shl(exponent.wrapping_sub(
<$fromty as FloatStuff>::MANTISSA_BITS as i32) as u32)
})
} }
}
macro_rules! float_as_signed {
($from: expr, $fromty: ty, $outty: ty) => {{
use core::num::Float;
let repr = $from.to_bytes();
let sign = $from.signum();
let exponent = $from.get_exponent();
let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK;
let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT;
if exponent < 0 { return 0 as i128; }
if exponent > ::core::mem::size_of::<$outty>().wrapping_mul(8) as i32 {
let ret = if sign > 0.0 { <$outty>::max_value() } else { <$outty>::min_value() };
return ret
}
let r = if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 {
(mantissa as $outty)
.wrapping_shr((<$fromty as FloatStuff>::MANTISSA_BITS as i32)
.wrapping_sub(exponent) as u32)
} else {
(mantissa as $outty)
.wrapping_shl(exponent.wrapping_sub(
<$fromty as FloatStuff>::MANTISSA_BITS as i32) as u32)
};
(if sign >= 0.0 { r } else { r.unchecked_neg() })
}}
}
fn i128_as_f64(a: i128) -> f64 {
match a.signum() {
1 => u128_as_f64(a.uabs()),
0 => 0.0,
_ => -u128_as_f64(a.uabs()),
}
}
fn i128_as_f32(a: i128) -> f32 {
match a.signum() {
1 => u128_as_f32(a.uabs()),
0 => 0.0,
_ => -u128_as_f32(a.uabs()),
}
}
fn u128_as_f64(mut a: u128) -> f64 {
use ::core::f64::MANTISSA_DIGITS;
if a == 0 { return 0.0; }
let sd = 128u32.wrapping_sub(a.leading_zeros());
let mut e = sd.wrapping_sub(1);
const MD1 : u32 = MANTISSA_DIGITS + 1;
const MD2 : u32 = MANTISSA_DIGITS + 2;
let negn = !0u128;
if sd > MANTISSA_DIGITS {
a = match sd {
MD1 => a.wrapping_shl(1),
MD2 => a,
_ => a.wrapping_shr(sd.wrapping_sub(MANTISSA_DIGITS + 2)) |
(if (a & (negn.wrapping_shr(128 + MANTISSA_DIGITS + 2)
.wrapping_sub(sd as u128))) == 0 { 0 } else { 1 })
};
a |= if (a & 4) == 0 { 0 } else { 1 };
a = a.wrapping_add(1);
a = a.wrapping_shr(2);
if a & (1 << MANTISSA_DIGITS) != 0 {
a = a.wrapping_shr(1);
e = e.wrapping_add(1);
}
} else {
a = a.wrapping_shl(MANTISSA_DIGITS.wrapping_sub(sd));
}
unsafe {
::core::mem::transmute((e as u64).wrapping_add(1023).wrapping_shl(52)
| (a as u64 & 0x000f_ffff_ffff_ffff))
}
}
fn u128_as_f32(mut a: u128) -> f32 {
use ::core::f32::MANTISSA_DIGITS;
if a == 0 { return 0.0; }
let sd = 128u32.wrapping_sub(a.leading_zeros());
let mut e = sd.wrapping_sub(1);
const MD1 : u32 = MANTISSA_DIGITS + 1;
const MD2 : u32 = MANTISSA_DIGITS + 2;
let negn = !0u128;
if sd > MANTISSA_DIGITS {
a = match sd {
MD1 => a.wrapping_shl(1),
MD2 => a,
_ => a.wrapping_shr(sd.wrapping_sub(MANTISSA_DIGITS + 2)) |
(if (a & (negn.wrapping_shr(128 + MANTISSA_DIGITS + 2)
.wrapping_sub(sd as u128))) == 0 { 0 } else { 1 })
};
a |= if (a & 4) == 0 { 0 } else { 1 };
a = a.wrapping_add(1);
a = a.wrapping_shr(2);
if a & (1 << MANTISSA_DIGITS) != 0 {
a = a.wrapping_shr(1);
e = e.wrapping_add(1);
}
} else {
a = a.wrapping_shl(MANTISSA_DIGITS.wrapping_sub(sd));
}
unsafe {
::core::mem::transmute((e as u32).wrapping_add(127).wrapping_shl(23)
| (a as u32 & 0x007f_ffff))
}
}
macro_rules! why_are_abi_strings_checked_by_parser { ($cret:ty, $conv:expr, $unadj:tt) => {
mod imp {
use super::{LargeInt, FloatStuff, NegExt, AbsExt};
use super::{i128_as_f64, i128_as_f32, u128_as_f64, u128_as_f32,
i128_div, i128_mod, u128_div_mod, unchecked_div, ptr};
// For x64
// rdx:rcx, r9:r8, stack -> rdx:rax
// aka.
// define i128 @__muloti4(i128, i128, i32*)
#[export_name="__muloti4"]
pub unsafe extern $unadj fn i128_mul_oflow(a: i128, b: i128, o: *mut i32) -> i128 {
mulo!(a, b, o, i128)
}
// For x64
// rdx:rax -> xmm0
// aka.
// define double @__muloti4(i128)
#[export_name="__floattidf"]
pub extern $unadj fn i128_as_f64_(a: i128) -> f64 {
i128_as_f64(a)
}
#[export_name="__floattisf"]
pub extern $unadj fn i128_as_f32_(a: i128) -> f32 {
i128_as_f32(a)
}
#[export_name="__floatuntidf"]
pub extern $unadj fn u128_as_f64_(a: u128) -> f64 {
u128_as_f64(a)
}
#[export_name="__floatuntisf"]
pub extern $unadj fn u128_as_f32_(a: u128) -> f32 {
u128_as_f32(a)
}
// For x64
// xmm0 -> rdx:rax
// aka.
// define i128 @stuff(double)
#[export_name="__fixunsdfti"]
pub extern $unadj fn f64_as_u128(a: f64) -> u128 {
float_as_unsigned!(a, f64, u128)
}
#[export_name="__fixunssfti"]
pub extern $unadj fn f32_as_u128(a: f32) -> u128 {
float_as_unsigned!(a, f32, u128)
}
#[export_name="__fixdfti"]
pub extern $unadj fn f64_as_i128(a: f64) -> i128 {
float_as_signed!(a, f64, i128)
}
#[export_name="__fixsfti"]
pub extern $unadj fn f32_as_i128(a: f32) -> i128 {
float_as_signed!(a, f32, i128)
}
#[repr(simd)]
pub struct u64x2(u64, u64);
// For x64
// pointers -> xmm0
// aka.
// define <2 x u64> @stuff(i128*, i128*, i128*)
//
// That almost matches the C ABI, so we simply use the C ABI
#[export_name="__udivmodti4"]
pub extern "C" fn u128_div_mod_(n: u128, d: u128, rem: *mut u128) -> $cret {
let x = u128_div_mod(n, d, rem);
($conv)(x)
}
#[export_name="__udivti3"]
pub extern "C" fn u128_div_(a: u128, b: u128) -> $cret {
let x = u128_div_mod(a, b, ptr::null_mut());
($conv)(x)
}
#[export_name="__umodti3"]
pub extern "C" fn u128_mod_(a: u128, b: u128) -> $cret {
unsafe {
let mut r = ::core::mem::zeroed();
u128_div_mod(a, b, &mut r);
($conv)(r)
}
}
#[export_name="__divti3"]
pub extern "C" fn i128_div_(a: i128, b: i128) -> $cret {
let x = i128_div(a, b);
($conv)(x as u128)
}
#[export_name="__modti3"]
pub extern "C" fn i128_mod_(a: i128, b: i128) -> $cret {
let x = i128_mod(a, b);
($conv)(x as u128)
}
}
} }
// LLVM expectations for ABI on windows x64 are pure madness.
#[cfg(all(windows, target_pointer_width="64"))]
why_are_abi_strings_checked_by_parser!(u64x2,
|i: u128| u64x2(i.low(), i.high()),
"unadjusted");
#[cfg(not(all(windows, target_pointer_width="64")))]
why_are_abi_strings_checked_by_parser!(u128, |i|{ i }, "C");
pub use self::imp::*;
}

View File

@ -53,7 +53,7 @@ fn main() {
}
for src in profile_sources {
cfg.file(Path::new("../compiler-rt/lib/profile").join(src));
cfg.file(Path::new("../libcompiler_builtins/compiler-rt/lib/profile").join(src));
}
cfg.compile("libprofiler-rt.a");

View File

@ -13,7 +13,7 @@
use llvm::{self, Attribute, ValueRef};
use llvm::AttributePlace::Function;
pub use syntax::attr::InlineAttr;
pub use syntax::attr::{self, InlineAttr};
use syntax::ast;
use context::CrateContext;

View File

@ -363,6 +363,24 @@ pub fn each_linked_rlib(sess: &Session,
Ok(())
}
/// Returns a boolean indicating whether the specified crate should be ignored
/// during LTO.
///
/// Crates ignored during LTO are not lumped together in the "massive object
/// file" that we create and are linked in their normal rlib states. See
/// comments below for what crates do not participate in LTO.
///
/// It's unusual for a crate to not participate in LTO. Typically only
/// compiler-specific and unstable crates have a reason to not participate in
/// LTO.
pub fn ignored_for_lto(sess: &Session, cnum: CrateNum) -> bool {
// `#![no_builtins]` crates don't participate in LTO because the state
// of builtins gets messed up (our crate isn't tagged with no builtins).
// Similarly `#![compiler_builtins]` doesn't participate because we want
// those builtins!
sess.cstore.is_no_builtins(cnum) || sess.cstore.is_compiler_builtins(cnum)
}
fn out_filename(sess: &Session,
crate_type: config::CrateType,
outputs: &OutputFilenames,
@ -698,7 +716,10 @@ fn link_staticlib(sess: &Session, objects: &[PathBuf], out_filename: &Path,
let skip_object_files = native_libs.iter().any(|lib| {
lib.kind == NativeLibraryKind::NativeStatic && !relevant_lib(sess, lib)
});
ab.add_rlib(path, &name.as_str(), sess.lto(), skip_object_files).unwrap();
ab.add_rlib(path,
&name.as_str(),
sess.lto() && !ignored_for_lto(sess, cnum),
skip_object_files).unwrap();
all_native_libs.extend(sess.cstore.native_libraries(cnum));
});
@ -1247,7 +1268,9 @@ fn add_static_crate(cmd: &mut Linker,
lib.kind == NativeLibraryKind::NativeStatic && !relevant_lib(sess, lib)
});
if !sess.lto() && crate_type != config::CrateTypeDylib && !skip_native {
if (!sess.lto() || ignored_for_lto(sess, cnum)) &&
crate_type != config::CrateTypeDylib &&
!skip_native {
cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath));
return
}

View File

@ -1200,8 +1200,7 @@ fn spawn_work<'a>(sess: &'a Session,
let crate_types = sess.crate_types.borrow().clone();
let mut each_linked_rlib_for_lto = Vec::new();
drop(link::each_linked_rlib(sess, &mut |cnum, path| {
// `#![no_builtins]` crates don't participate in LTO.
if sess.cstore.is_no_builtins(cnum) {
if link::ignored_for_lto(sess, cnum) {
return
}
each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));

View File

@ -30,7 +30,6 @@
use common;
use type_::Type;
use value::Value;
use syntax::attr;
use std::ffi::CString;
@ -88,16 +87,6 @@ fn declare_raw_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty:
}
}
// If we're compiling the compiler-builtins crate, e.g. the equivalent of
// compiler-rt, then we want to implicitly compile everything with hidden
// visibility as we're going to link this object all over the place but
// don't want the symbols to get exported.
if attr::contains_name(ccx.tcx().hir.krate_attrs(), "compiler_builtins") {
unsafe {
llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
}
}
match ccx.tcx().sess.opts.cg.opt_level.as_ref().map(String::as_ref) {
Some("s") => {
llvm::Attribute::OptimizeForSize.apply_llfn(Function, llfn);

View File

@ -162,6 +162,18 @@ fn predefine_fn(ccx: &CrateContext<'a, 'tcx>,
llvm::SetUniqueComdat(ccx.llmod(), lldecl);
}
// If we're compiling the compiler-builtins crate, e.g. the equivalent of
// compiler-rt, then we want to implicitly compile everything with hidden
// visibility as we're going to link this object all over the place but
// don't want the symbols to get exported.
if linkage != llvm::Linkage::InternalLinkage &&
linkage != llvm::Linkage::PrivateLinkage &&
attr::contains_name(ccx.tcx().hir.krate_attrs(), "compiler_builtins") {
unsafe {
llvm::LLVMRustSetVisibility(lldecl, llvm::Visibility::Hidden);
}
}
debug!("predefine_fn: mono_ty = {:?} instance = {:?}", mono_ty, instance);
if common::is_inline_instance(ccx.tcx(), &instance) {
attributes::inline(lldecl, attributes::InlineAttr::Hint);

View File

@ -19,7 +19,7 @@ collections = { path = "../libcollections" }
core = { path = "../libcore" }
libc = { path = "../rustc/libc_shim" }
rand = { path = "../librand" }
compiler_builtins = { path = "../libcompiler_builtins" }
compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
profiler_builtins = { path = "../libprofiler_builtins", optional = true }
std_unicode = { path = "../libstd_unicode" }
unwind = { path = "../libunwind" }

View File

@ -0,0 +1,24 @@
# See libc_shim/Cargo.toml for why this exists
[package]
name = "compiler_builtins"
authors = ["The Rust Project Developers"]
version = "0.0.0"
build = "../../libcompiler_builtins/build.rs"
[lib]
path = "../../libcompiler_builtins/src/lib.rs"
test = false
doctest = false
[dependencies]
core = { path = "../../libcore" }
[build-dependencies]
gcc = "0.3"
[features]
c = []
default = ["c", "rustbuild", "compiler-builtins"]
rustbuild = []
compiler-builtins = []

View File

@ -1,4 +1,4 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -8,8 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// no-prefer-dynamic
#![crate_type = "staticlib"]
#![deny(warnings)]
#[no_mangle]
pub extern "C" fn foo(x:i32) -> i32 { x }
// See comments in Cargo.toml for why this exists
fn main() {
println!("cargo:rustc-cfg=stdbuild");
println!("cargo:rerun-if-changed=build.rs");
}

View File

@ -8,16 +8,15 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:clibrary.rs
// compile-flags: -lclibrary
// compile-flags: -lrust_test_helpers
#[link(name = "clibrary", kind = "static")]
#[link(name = "rust_test_helpers", kind = "static")]
extern "C" {
pub fn foo(x:i32) -> i32;
pub fn rust_dbg_extern_identity_u32(x: u32) -> u32;
}
fn main() {
unsafe {
foo(42);
rust_dbg_extern_identity_u32(42);
}
}

View File

@ -8,16 +8,15 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:clibrary.rs
// compile-flags: -lstatic=wronglibrary:clibrary
// compile-flags: -lstatic=wronglibrary:rust_test_helpers
#[link(name = "wronglibrary", kind = "dylib")]
extern "C" {
pub fn foo(x:i32) -> i32;
pub fn rust_dbg_extern_identity_u32(x: u32) -> u32;
}
fn main() {
unsafe {
foo(42);
rust_dbg_extern_identity_u32(42);
}
}

View File

@ -54,6 +54,7 @@ fn filter_dirs(path: &Path) -> bool {
"src/jemalloc",
"src/llvm",
"src/libbacktrace",
"src/libcompiler_builtins",
"src/compiler-rt",
"src/rustllvm",
"src/liblibc",