about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-05-13 05:04:41 -0700
committerbors <bors@rust-lang.org>2013-05-13 05:04:41 -0700
commit1bf2f68bb255cc6833d4253c4f6d071af9e05648 (patch)
tree7ed14f8a52d842e64bbf258f9a2bcc3a8ca1cb34
parent2774392b41af806028d9946f42e84495d58a33d6 (diff)
parent852af346d346e0119af8336c88ee1b113346ac7c (diff)
downloadrust-1bf2f68bb255cc6833d4253c4f6d071af9e05648.tar.gz
rust-1bf2f68bb255cc6833d4253c4f6d071af9e05648.zip
auto merge of #6437 : Thiez/rust/atomic, r=Aatch
This pull request adds 4 atomic intrinsics to the compiler, in preparation for #5042.

* `atomic_load(src: &int) -> int` performs an atomic sequentially consistent load.
* `atomic_load_acq(src: &int) -> int` performs an atomic acquiring load.
* `atomic_store(dst: &mut int, val: int)` performs an atomic sequentially consistent store.
* `atomic_store_rel(dst: &mut int, val: int)` performs an atomic releasing store.

For more information about the whole acquire/release thing: http://llvm.org/docs/Atomics.html

r?
-rw-r--r--src/libcore/unstable/intrinsics.rs10
-rw-r--r--src/librustc/lib/llvm.rs22
-rw-r--r--src/librustc/middle/trans/build.rs23
-rw-r--r--src/librustc/middle/trans/foreign.rs24
-rw-r--r--src/librustc/middle/trans/type_use.rs4
-rw-r--r--src/librustc/middle/typeck/check/mod.rs19
-rw-r--r--src/rustllvm/RustWrapper.cpp22
-rw-r--r--src/rustllvm/rustllvm.def.in2
-rw-r--r--src/test/run-pass/intrinsic-atomics.rs15
9 files changed, 136 insertions, 5 deletions
diff --git a/src/libcore/unstable/intrinsics.rs b/src/libcore/unstable/intrinsics.rs
index a820c5d15a8..b8c0c4e4a92 100644
--- a/src/libcore/unstable/intrinsics.rs
+++ b/src/libcore/unstable/intrinsics.rs
@@ -20,6 +20,16 @@ pub extern "rust-intrinsic" {
     pub fn atomic_cxchg_acq(dst: &mut int, old: int, src: int) -> int;
     pub fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int;
 
+    #[cfg(not(stage0))]
+    pub fn atomic_load(src: &int) -> int;
+    #[cfg(not(stage0))]
+    pub fn atomic_load_acq(src: &int) -> int;
+
+    #[cfg(not(stage0))]
+    pub fn atomic_store(dst: &mut int, val: int);
+    #[cfg(not(stage0))]
+    pub fn atomic_store_rel(dst: &mut int, val: int);
+
     pub fn atomic_xchg(dst: &mut int, src: int) -> int;
     pub fn atomic_xchg_acq(dst: &mut int, src: int) -> int;
     pub fn atomic_xchg_rel(dst: &mut int, src: int) -> int;
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index 36d5a8e3cfe..4c61c42a339 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -1339,13 +1339,16 @@ pub mod llvm {
                                     PointerVal: ValueRef) -> ValueRef;
         #[fast_ffi]
         pub unsafe fn LLVMBuildLoad(B: BuilderRef,
-                                PointerVal: ValueRef,
-                                Name: *c_char)
-                             -> ValueRef;
+                                    PointerVal: ValueRef,
+                                    Name: *c_char)
+                                 -> ValueRef;
+
         #[fast_ffi]
         pub unsafe fn LLVMBuildStore(B: BuilderRef,
                                      Val: ValueRef,
-                                     Ptr: ValueRef) -> ValueRef;
+                                     Ptr: ValueRef)
+                                  -> ValueRef;
+
         #[fast_ffi]
         pub unsafe fn LLVMBuildGEP(B: BuilderRef,
                                Pointer: ValueRef,
@@ -1561,6 +1564,17 @@ pub mod llvm {
                                        Name: *c_char) -> ValueRef;
 
         /* Atomic Operations */
+        pub unsafe fn LLVMBuildAtomicLoad(B: BuilderRef,
+                                          PointerVal: ValueRef,
+                                          Order: AtomicOrdering)
+                                       -> ValueRef;
+
+        pub unsafe fn LLVMBuildAtomicStore(B: BuilderRef,
+                                           Val: ValueRef,
+                                           Ptr: ValueRef,
+                                           Order: AtomicOrdering)
+                                        -> ValueRef;
+
         pub unsafe fn LLVMBuildAtomicCmpXchg(B: BuilderRef,
                                              LHS: ValueRef,
                                              CMP: ValueRef,
diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs
index 29fd90edce8..b2af91887ec 100644
--- a/src/librustc/middle/trans/build.rs
+++ b/src/librustc/middle/trans/build.rs
@@ -537,6 +537,18 @@ pub fn Load(cx: block, PointerVal: ValueRef) -> ValueRef {
     }
 }
 
+pub fn AtomicLoad(cx: block, PointerVal: ValueRef, order: AtomicOrdering) -> ValueRef {
+    unsafe {
+        let ccx = cx.fcx.ccx;
+        if cx.unreachable {
+            return llvm::LLVMGetUndef(ccx.int_type);
+        }
+        count_insn(cx, "load.atomic");
+        return llvm::LLVMBuildAtomicLoad(B(cx), PointerVal, order);
+    }
+}
+
+
 pub fn LoadRangeAssert(cx: block, PointerVal: ValueRef, lo: c_ulonglong,
                        hi: c_ulonglong, signed: lib::llvm::Bool) -> ValueRef {
     let value = Load(cx, PointerVal);
@@ -567,6 +579,17 @@ pub fn Store(cx: block, Val: ValueRef, Ptr: ValueRef) {
     }
 }
 
+pub fn AtomicStore(cx: block, Val: ValueRef, Ptr: ValueRef, order: AtomicOrdering) {
+    unsafe {
+        if cx.unreachable { return; }
+        debug!("Store %s -> %s",
+               val_str(cx.ccx().tn, Val),
+               val_str(cx.ccx().tn, Ptr));
+        count_insn(cx, "store.atomic");
+        llvm::LLVMBuildAtomicStore(B(cx), Val, Ptr, order);
+    }
+}
+
 pub fn GEP(cx: block, Pointer: ValueRef, Indices: &[ValueRef]) -> ValueRef {
     unsafe {
         if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_nil())); }
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 26654cf31f8..30db63e9c19 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -592,6 +592,30 @@ pub fn trans_intrinsic(ccx: @CrateContext,
                                     Release);
             Store(bcx, old, fcx.llretptr.get());
         }
+        ~"atomic_load" => {
+            let old = AtomicLoad(bcx,
+                                 get_param(decl, first_real_arg),
+                                 SequentiallyConsistent);
+            Store(bcx, old, fcx.llretptr.get());
+        }
+        ~"atomic_load_acq" => {
+            let old = AtomicLoad(bcx,
+                                 get_param(decl, first_real_arg),
+                                 Acquire);
+            Store(bcx, old, fcx.llretptr.get());
+        }
+        ~"atomic_store" => {
+            AtomicStore(bcx,
+                        get_param(decl, first_real_arg + 1u),
+                        get_param(decl, first_real_arg),
+                        SequentiallyConsistent);
+        }
+        ~"atomic_store_rel" => {
+            AtomicStore(bcx,
+                        get_param(decl, first_real_arg + 1u),
+                        get_param(decl, first_real_arg),
+                        Release);
+        }
         ~"atomic_xchg" => {
             let old = AtomicRMW(bcx, Xchg,
                                 get_param(decl, first_real_arg),
diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs
index 3c2738d3ae8..6a271f979ca 100644
--- a/src/librustc/middle/trans/type_use.rs
+++ b/src/librustc/middle/trans/type_use.rs
@@ -124,7 +124,9 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint)
                 ~"get_tydesc" | ~"needs_drop" => use_tydesc,
 
                 ~"atomic_cxchg"    | ~"atomic_cxchg_acq"|
-                ~"atomic_cxchg_rel"| ~"atomic_xchg"     |
+                ~"atomic_cxchg_rel"| ~"atomic_load"     |
+                ~"atomic_load_acq" | ~"atomic_store"    |
+                ~"atomic_store_rel"| ~"atomic_xchg"     |
                 ~"atomic_xadd"     | ~"atomic_xsub"     |
                 ~"atomic_xchg_acq" | ~"atomic_xadd_acq" |
                 ~"atomic_xsub_acq" | ~"atomic_xchg_rel" |
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 7c79693a8b2..7f73ed94c03 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -3486,6 +3486,25 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
          ],
          ty::mk_int())
       }
+      ~"atomic_load"     | ~"atomic_load_acq" => {
+        (0,
+         ~[
+            arg(ty::mk_imm_rptr(tcx,
+                            ty::re_bound(ty::br_anon(0)),
+                            ty::mk_int()))
+         ],
+        ty::mk_int())
+      }
+      ~"atomic_store"    | ~"atomic_store_rel" => {
+        (0,
+         ~[
+            arg(ty::mk_mut_rptr(tcx,
+                                ty::re_bound(ty::br_anon(0)),
+                                ty::mk_int())),
+            arg(ty::mk_int())
+         ],
+         ty::mk_nil())
+      }
       ~"atomic_xchg"     | ~"atomic_xadd"     | ~"atomic_xsub"     |
       ~"atomic_xchg_acq" | ~"atomic_xadd_acq" | ~"atomic_xsub_acq" |
       ~"atomic_xchg_rel" | ~"atomic_xadd_rel" | ~"atomic_xsub_rel" => {
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 04e616de223..8c081858d60 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -545,6 +545,28 @@ extern "C" LLVMTypeRef LLVMMetadataType(void) {
   return LLVMMetadataTypeInContext(LLVMGetGlobalContext());
 }
 
+extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B,
+                                            LLVMValueRef source,
+                                            const char* Name,
+                                            AtomicOrdering order) {
+    LoadInst* li = new LoadInst(unwrap(source),0);
+    li->setVolatile(true);
+    li->setAtomic(order);
+    li->setAlignment(sizeof(intptr_t));
+    return wrap(unwrap(B)->Insert(li));
+}
+
+extern "C" LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B,
+                                            LLVMValueRef val,
+                                            LLVMValueRef target,
+                                            AtomicOrdering order) {
+    StoreInst* si = new StoreInst(unwrap(val),unwrap(target));
+    si->setVolatile(true);
+    si->setAtomic(order);
+    si->setAlignment(sizeof(intptr_t));
+    return wrap(unwrap(B)->Insert(si));
+}
+
 extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
                                                LLVMValueRef target,
                                                LLVMValueRef old,
diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in
index 73bf1af90cd..dd5dc7102d1 100644
--- a/src/rustllvm/rustllvm.def.in
+++ b/src/rustllvm/rustllvm.def.in
@@ -84,6 +84,8 @@ LLVMArrayType
 LLVMBasicBlockAsValue
 LLVMBlockAddress
 LLVMBuildAShr
+LLVMBuildAtomicLoad
+LLVMBuildAtomicStore
 LLVMBuildAtomicCmpXchg
 LLVMBuildAtomicRMW
 LLVMBuildAdd
diff --git a/src/test/run-pass/intrinsic-atomics.rs b/src/test/run-pass/intrinsic-atomics.rs
index 42d4f5e4d20..d4701f74488 100644
--- a/src/test/run-pass/intrinsic-atomics.rs
+++ b/src/test/run-pass/intrinsic-atomics.rs
@@ -15,6 +15,12 @@ mod rusti {
         pub fn atomic_cxchg_acq(dst: &mut int, old: int, src: int) -> int;
         pub fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int;
 
+        pub fn atomic_load(src: &int) -> int;
+        pub fn atomic_load_acq(src: &int) -> int;
+        
+        pub fn atomic_store(dst: &mut int, val: int);
+        pub fn atomic_store_rel(dst: &mut int, val: int);
+
         pub fn atomic_xchg(dst: &mut int, src: int) -> int;
         pub fn atomic_xchg_acq(dst: &mut int, src: int) -> int;
         pub fn atomic_xchg_rel(dst: &mut int, src: int) -> int;
@@ -33,6 +39,15 @@ pub fn main() {
     unsafe {
         let mut x = ~1;
 
+        assert!(rusti::atomic_load(x) == 1);
+        *x = 5;
+        assert!(rusti::atomic_load_acq(x) == 5);
+        
+        rusti::atomic_store(x,3);
+        assert!(*x == 3);
+        rusti::atomic_store_rel(x,1);
+        assert!(*x == 1);
+
         assert!(rusti::atomic_cxchg(x, 1, 2) == 1);
         assert!(*x == 2);