about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJames Miller <james@aatch.net>2013-07-28 19:48:16 +1200
committerJames Miller <james@aatch.net>2013-07-28 20:26:49 +1200
commit4a1a0fbed5a57958eb7b658bbe3e5257872ae99f (patch)
treefa6f345707b41d6928fc48d30bec705c559c0736
parent9325535b41fa5a7cfac697e86ae86bd1384542e6 (diff)
downloadrust-4a1a0fbed5a57958eb7b658bbe3e5257872ae99f.tar.gz
rust-4a1a0fbed5a57958eb7b658bbe3e5257872ae99f.zip
Add an atomic fence intrinsic
-rw-r--r--src/librustc/lib/llvm.rs3
-rw-r--r--src/librustc/middle/trans/build.rs5
-rw-r--r--src/librustc/middle/trans/builder.rs6
-rw-r--r--src/librustc/middle/trans/foreign.rs4
-rw-r--r--src/librustc/middle/typeck/check/mod.rs4
-rw-r--r--src/libstd/unstable/atomics.rs27
-rw-r--r--src/libstd/unstable/intrinsics.rs9
-rw-r--r--src/rustllvm/RustWrapper.cpp5
-rw-r--r--src/rustllvm/rustllvm.def.in1
9 files changed, 62 insertions, 2 deletions
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index f3bca7a6ab3..57563948b0f 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -1594,6 +1594,9 @@ pub mod llvm {
                                          Order: AtomicOrdering)
                                          -> ValueRef;
 
+        pub unsafe fn LLVMBuildAtomicFence(B: BuilderRef, Order: AtomicOrdering);
+
+
         /* Selected entries from the downcasts. */
         #[fast_ffi]
         pub unsafe fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;
diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs
index 9c34d2a3526..07b774105bb 100644
--- a/src/librustc/middle/trans/build.rs
+++ b/src/librustc/middle/trans/build.rs
@@ -660,6 +660,11 @@ pub fn CallWithConv(cx: @mut Block, Fn: ValueRef, Args: &[ValueRef],
     B(cx).call_with_conv(Fn, Args, Conv)
 }
 
+pub fn AtomicFence(cx: @mut Block, order: AtomicOrdering) {
+    if cx.unreachable { return; }
+    B(cx).atomic_fence(order)
+}
+
 pub fn Select(cx: @mut Block, If: ValueRef, Then: ValueRef, Else: ValueRef) -> ValueRef {
     if cx.unreachable { return _Undef(Then); }
     B(cx).select(If, Then, Else)
diff --git a/src/librustc/middle/trans/builder.rs b/src/librustc/middle/trans/builder.rs
index 1c9161163cc..be9d5a6c118 100644
--- a/src/librustc/middle/trans/builder.rs
+++ b/src/librustc/middle/trans/builder.rs
@@ -943,4 +943,10 @@ impl Builder {
             llvm::LLVMBuildAtomicRMW(self.llbuilder, op, dst, src, order)
         }
     }
+
+    pub fn atomic_fence(&self, order: AtomicOrdering) {
+        unsafe {
+            llvm::LLVMBuildAtomicFence(self.llbuilder, order);
+        }
+    }
 }
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 6e198af448b..080d1f2adb5 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -661,6 +661,10 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
                             order);
                 RetVoid(bcx);
             }
+            "fence" => {
+                AtomicFence(bcx, order);
+                RetVoid(bcx);
+            }
             op => {
                 // These are all AtomicRMW ops
                 let atom_op = match op {
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 0b80c0cb3c6..cffceee88d3 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -3521,7 +3521,9 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
                                       ty::re_bound(ty::br_anon(0)),
                                       ty::mk_int()), ty::mk_int() ], ty::mk_int())
             }
-
+            "fence" => {
+                (0, ~[], ty::mk_nil())
+            }
             op => {
                 tcx.sess.span_err(it.span,
                                   fmt!("unrecognized atomic operation function: `%s`",
diff --git a/src/libstd/unstable/atomics.rs b/src/libstd/unstable/atomics.rs
index 712c32d2436..8b57da32bbd 100644
--- a/src/libstd/unstable/atomics.rs
+++ b/src/libstd/unstable/atomics.rs
@@ -569,6 +569,33 @@ pub unsafe fn atomic_umin<T>(dst: &mut T, val: T, order: Ordering) -> T {
     })
 }
 
+/**
+ * An atomic fence.
+ *
+ * A fence 'A' which has `Release` ordering semantics, synchronizes with a
+ * fence 'B' with (at least) `Aquire` semantics, if and only if there exists
+ * atomic operations X and Y, bother operating on some atomic object 'M' such
+ * that A is sequenced before X, Y is synchronized before B and Y obsevers
+ * the change to M. This provides a happens-before dependence between A and B.
+ *
+ * Atomic operations with `Release` or `Acquire` semantics can also synchronize
+ * with a fence.
+ *
+ * A fence with has `SeqCst` ordering, in addition to having both `Acquire` and
+ * `Release` semantics, participates in the global program order of the other
+ * `SeqCst` operations and/or fences.
+ *
+ * Accepts `Acquire`, `Release`, `AcqRel` and `SeqCst` orderings.
+ */
+#[inline] #[cfg(not(stage0))]
+pub fn fence(order: Ordering) {
+    match order {
+        Acquire => intrinsics::atomic_fence_acq(),
+        Release => intrinsics::atomic_fence_rel(),
+        AcqRel  => intrinsics::atomic_fence_rel(),
+        _       => intrinsics::atomic_fence(),
+    }
+}
 
 #[cfg(test)]
 mod test {
diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs
index 76958fa333f..655ede6b4eb 100644
--- a/src/libstd/unstable/intrinsics.rs
+++ b/src/libstd/unstable/intrinsics.rs
@@ -256,6 +256,15 @@ extern "rust-intrinsic" {
     pub fn atomic_umax_acqrel(dst: &mut int, src: int) -> int;
     pub fn atomic_umax_relaxed(dst: &mut int, src: int) -> int;
 
+    #[cfg(not(stage0))]
+    pub fn atomic_fence();
+    #[cfg(not(stage0))]
+    pub fn atomic_fence_acq();
+    #[cfg(not(stage0))]
+    pub fn atomic_fence_rel();
+    #[cfg(not(stage0))]
+    pub fn atomic_fence_acqrel();
+
     /// The size of a type in bytes.
     ///
     /// This is the exact number of bytes in memory taken up by a
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 2a1f26bf441..beaa7e1daef 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -513,6 +513,9 @@ extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
     return wrap(unwrap(B)->CreateAtomicCmpXchg(unwrap(target), unwrap(old),
                                                unwrap(source), order));
 }
+extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B, AtomicOrdering order) {
+    return wrap(unwrap(B)->CreateFence(order));
+}
 extern "C" LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,
                                            AtomicRMWInst::BinOp op,
                                            LLVMValueRef target,
@@ -838,4 +841,4 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType(
         Flags,
         unwrapDI<DIArray>(Elements),
         RunTimeLang));
-}
\ No newline at end of file
+}
diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in
index 48888760fc6..260a16dab98 100644
--- a/src/rustllvm/rustllvm.def.in
+++ b/src/rustllvm/rustllvm.def.in
@@ -90,6 +90,7 @@ LLVMBuildAtomicLoad
 LLVMBuildAtomicStore
 LLVMBuildAtomicCmpXchg
 LLVMBuildAtomicRMW
+LLVMBuildAtomicFence
 LLVMBuildAdd
 LLVMBuildAggregateRet
 LLVMBuildAlloca