diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index bea08366db392..448b9e30dcd3d 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -1771,6 +1771,7 @@ pub mod llvm { pub fn LLVMRustDestroyArchive(AR: ArchiveRef); pub fn LLVMRustSetDLLExportStorageClass(V: ValueRef); + pub fn LLVMVersionMinor() -> c_int; } } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index f838bcf9c5ec2..bd4ef16d19d79 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2286,8 +2286,6 @@ pub fn declare_intrinsics(llmod: ModuleRef) -> HashMap<&'static str, ValueRef> { ifn!(intrinsics, "llvm.fabs.f32", [Type::f32()], Type::f32()); ifn!(intrinsics, "llvm.fabs.f64", [Type::f64()], Type::f64()); - ifn!(intrinsics, "llvm.copysign.f32", [Type::f32(), Type::f32()], Type::f32()); - ifn!(intrinsics, "llvm.copysign.f64", [Type::f64(), Type::f64()], Type::f64()); ifn!(intrinsics, "llvm.floor.f32",[Type::f32()], Type::f32()); ifn!(intrinsics, "llvm.floor.f64",[Type::f64()], Type::f64()); @@ -2300,8 +2298,6 @@ pub fn declare_intrinsics(llmod: ModuleRef) -> HashMap<&'static str, ValueRef> { ifn!(intrinsics, "llvm.rint.f64", [Type::f64()], Type::f64()); ifn!(intrinsics, "llvm.nearbyint.f32", [Type::f32()], Type::f32()); ifn!(intrinsics, "llvm.nearbyint.f64", [Type::f64()], Type::f64()); - ifn!(intrinsics, "llvm.round.f32", [Type::f32()], Type::f32()); - ifn!(intrinsics, "llvm.round.f64", [Type::f64()], Type::f64()); ifn!(intrinsics, "llvm.ctpop.i8", [Type::i8()], Type::i8()); ifn!(intrinsics, "llvm.ctpop.i16",[Type::i16()], Type::i16()); @@ -2378,6 +2374,32 @@ pub fn declare_intrinsics(llmod: ModuleRef) -> HashMap<&'static str, ValueRef> { ifn!(intrinsics, "llvm.expect.i1", [Type::i1(), Type::i1()], Type::i1()); + // Some intrinsics were introduced in later versions of LLVM, but they have + // fallbacks in libc or libm and such. Currently, all of these intrinsics + // were introduced in LLVM 3.4, so we case on that. + macro_rules! compatible_ifn ( + ($intrinsics:ident, $name:expr, $cname:expr, $args:expr, $ret:expr) => ({ + let name = $name; + if unsafe { llvm::LLVMVersionMinor() >= 4 } { + ifn!($intrinsics, $name, $args, $ret); + } else { + let f = decl_cdecl_fn(llmod, $cname, + Type::func($args, &$ret), + ty::mk_nil()); + $intrinsics.insert(name, f); + } + }) + ) + + compatible_ifn!(intrinsics, "llvm.copysign.f32", "copysignf", + [Type::f32(), Type::f32()], Type::f32()); + compatible_ifn!(intrinsics, "llvm.copysign.f64", "copysign", + [Type::f64(), Type::f64()], Type::f64()); + compatible_ifn!(intrinsics, "llvm.round.f32", "roundf", + [Type::f32()], Type::f32()); + compatible_ifn!(intrinsics, "llvm.round.f64", "round", + [Type::f64()], Type::f64()); + return intrinsics; } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index d8fc5b15850e1..aaaf512bcf3fe 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -652,3 +652,8 @@ LLVMRustSetDLLExportStorageClass(LLVMValueRef Value) { LLVMSetLinkage(Value, LLVMDLLExportLinkage); } #endif + +extern "C" int +LLVMVersionMinor() { + return LLVM_VERSION_MINOR; +}