From 93964525922f5b13cbc3b0a28175082acf50f587 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 5 Mar 2014 15:14:16 -0800 Subject: [PATCH] rustc: Fix support for LLVM 3.3 The llvm.copysign and llvm.round intrinsics weren't added until LLVM 3.4, so if we're on LLVM 3.3 we lower these to calls in libm instead of LLVM intrinsics. This should fix our travis failures. --- src/librustc/lib/llvm.rs | 1 + src/librustc/middle/trans/base.rs | 30 ++++++++++++++++++++++++++---- src/rustllvm/RustWrapper.cpp | 5 +++++ 3 files changed, 32 insertions(+), 4 deletions(-) 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; +}