From 1be9e6f055fbcd6bfcf0a1f9e9ef0e86abe54f02 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Sat, 30 May 2015 09:50:12 -0400 Subject: [PATCH 1/3] Remove useless `const` --- src/rustllvm/RustWrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 66db7326d21bf..b1e2d2f9fc821 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -233,7 +233,7 @@ DIT unwrapDI(LLVMMetadataRef ref) { return DIT(ref ? unwrap(ref) : NULL); } -extern "C" const uint32_t LLVMRustDebugMetadataVersion() { +extern "C" uint32_t LLVMRustDebugMetadataVersion() { return DEBUG_METADATA_VERSION; } From ce32f6412e1937c0844aa48e5b4e876b96dcd66d Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Sat, 24 Jan 2015 12:00:35 +0100 Subject: [PATCH 2/3] rustc_trans: don't hardcode llvm version for conditional intrinsics This commit introduce a third parameter for compatible_ifn!, as new intrinsics are being added in recent LLVM releases and there is no need to hardcode a specific case. Signed-off-by: Luca Bruno --- src/librustc_llvm/lib.rs | 2 ++ src/librustc_trans/trans/context.rs | 27 +++++++++++++++++---------- src/rustllvm/RustWrapper.cpp | 8 ++++++++ 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index a3b9a0e846700..379a7da459fdb 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -1772,6 +1772,8 @@ extern { -> ValueRef; pub fn LLVMRustDebugMetadataVersion() -> u32; + pub fn LLVMVersionMajor() -> u32; + pub fn LLVMVersionMinor() -> u32; pub fn LLVMRustAddModuleFlag(M: ModuleRef, name: *const c_char, diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index 51db0adf5b775..f2de949ccd53e 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -870,6 +870,11 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option t_f32); ifn!("llvm.trunc.f64", fn(t_f64) -> t_f64); + ifn!("llvm.copysign.f32", fn(t_f32, t_f32) -> t_f32); + ifn!("llvm.copysign.f64", fn(t_f64, t_f64) -> t_f64); + ifn!("llvm.round.f32", fn(t_f32) -> t_f32); + ifn!("llvm.round.f64", fn(t_f64) -> t_f64); + ifn!("llvm.rint.f32", fn(t_f32) -> t_f32); ifn!("llvm.rint.f64", fn(t_f64) -> t_f64); ifn!("llvm.nearbyint.f32", fn(t_f32) -> t_f32); @@ -931,20 +936,22 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option void); // 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. + // fallbacks in libc or libm and such. macro_rules! compatible_ifn { - ($name:expr, $cname:ident ($($arg:expr),*) -> $ret:expr) => ( - ifn!($name, fn($($arg),*) -> $ret); + ($name:expr, $cname:ident ($($arg:expr),*) -> $ret:expr, $llvm_version:expr) => ( + if unsafe { llvm::LLVMVersionMinor() >= $llvm_version } { + // The `if key == $name` is already in ifn! + ifn!($name, fn($($arg),*) -> $ret); + } else if *key == $name { + let f = declare::declare_cfn(ccx, stringify!($cname), + Type::func(&[$($arg),*], &$ret), + ty::mk_nil(ccx.tcx())); + ccx.intrinsics().borrow_mut().insert($name, f.clone()); + return Some(f); + } ) } - compatible_ifn!("llvm.copysign.f32", copysignf(t_f32, t_f32) -> t_f32); - compatible_ifn!("llvm.copysign.f64", copysign(t_f64, t_f64) -> t_f64); - compatible_ifn!("llvm.round.f32", roundf(t_f32) -> t_f32); - compatible_ifn!("llvm.round.f64", round(t_f64) -> t_f64); - - if ccx.sess().opts.debuginfo != NoDebugInfo { ifn!("llvm.dbg.declare", fn(Type::metadata(ccx), Type::metadata(ccx)) -> void); ifn!("llvm.dbg.value", fn(Type::metadata(ccx), t_i64, Type::metadata(ccx)) -> void); diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index b1e2d2f9fc821..ad6533e5480b1 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -237,6 +237,14 @@ extern "C" uint32_t LLVMRustDebugMetadataVersion() { return DEBUG_METADATA_VERSION; } +extern "C" uint32_t LLVMVersionMinor() { + return LLVM_VERSION_MINOR; +} + +extern "C" uint32_t LLVMVersionMajor() { + return LLVM_VERSION_MAJOR; +} + extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *name, uint32_t value) { From e36e97ba51f512de2fd05e3250db4a7b72caae04 Mon Sep 17 00:00:00 2001 From: David Voit Date: Sat, 23 May 2015 23:33:37 +0200 Subject: [PATCH 3/3] rustc_trans: 'assume' intrinsic is only available on LLVM >= 3.6 Based on the patch from Luca Bruno. Instead of creating an empty C function in the rt, this version creates an shim noop function using llvm. This function is declared as internal, and the unsupported assume intrinsic and the shim gets completly removed by the optimizer. --- src/librustc_trans/trans/context.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index f2de949ccd53e..42e2efa906252 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -933,11 +933,33 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option void); ifn!("llvm.expect.i1", fn(i1, i1) -> i1); - ifn!("llvm.assume", fn(i1) -> void); // Some intrinsics were introduced in later versions of LLVM, but they have // fallbacks in libc or libm and such. macro_rules! compatible_ifn { + ($name:expr, noop($cname:ident ($($arg:expr),*) -> void), $llvm_version:expr) => ( + if unsafe { llvm::LLVMVersionMinor() >= $llvm_version } { + // The `if key == $name` is already in ifn! + ifn!($name, fn($($arg),*) -> void); + } else if *key == $name { + let f = declare::declare_cfn(ccx, stringify!($cname), + Type::func(&[$($arg),*], &void), + ty::mk_nil(ccx.tcx())); + llvm::SetLinkage(f, llvm::InternalLinkage); + + let bld = ccx.builder(); + let llbb = unsafe { + llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), f, + "entry-block\0".as_ptr() as *const _) + }; + + bld.position_at_end(llbb); + bld.ret_void(); + + ccx.intrinsics().borrow_mut().insert($name, f.clone()); + return Some(f); + } + ); ($name:expr, $cname:ident ($($arg:expr),*) -> $ret:expr, $llvm_version:expr) => ( if unsafe { llvm::LLVMVersionMinor() >= $llvm_version } { // The `if key == $name` is already in ifn! @@ -952,6 +974,8 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option void), 6); + if ccx.sess().opts.debuginfo != NoDebugInfo { ifn!("llvm.dbg.declare", fn(Type::metadata(ccx), Type::metadata(ccx)) -> void); ifn!("llvm.dbg.value", fn(Type::metadata(ccx), t_i64, Type::metadata(ccx)) -> void);