about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Voit <david.voit@gmail.com>2015-05-23 23:33:37 +0200
committerTamir Duberstein <tamird@gmail.com>2015-06-07 22:47:01 -0400
commite36e97ba51f512de2fd05e3250db4a7b72caae04 (patch)
tree6975e5f661bed7a634d78da346e3b6e67ac30884
parentce32f6412e1937c0844aa48e5b4e876b96dcd66d (diff)
downloadrust-e36e97ba51f512de2fd05e3250db4a7b72caae04.tar.gz
rust-e36e97ba51f512de2fd05e3250db4a7b72caae04.zip
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.
-rw-r--r--src/librustc_trans/trans/context.rs26
1 files changed, 25 insertions, 1 deletions
diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs
index f2de949ccd5..42e2efa9062 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<ValueRef
     ifn!("llvm.lifetime.end", fn(t_i64, i8p) -> 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<ValueRef
         )
     }
 
+    compatible_ifn!("llvm.assume", noop(llvmcompat_assume(i1) -> 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);