about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Marheine <peter@taricorp.net>2015-02-14 23:48:10 -0700
committerPeter Marheine <peter@taricorp.net>2015-04-25 19:41:21 -0600
commit998c10d6b64f9a37d4cab33e09b9dfd551c76b92 (patch)
treed3272508b6aa37ce49b633ede17dc8ce29b6fea4
parent0d8309ec0b13ebad02bbc76f93eff39edf4af2d0 (diff)
downloadrust-998c10d6b64f9a37d4cab33e09b9dfd551c76b92.tar.gz
rust-998c10d6b64f9a37d4cab33e09b9dfd551c76b92.zip
Add singlethreaded fence intrinsics.
These new intrinsics are comparable to `atomic_signal_fence` in C++,
ensuring the compiler will not reorder memory accesses across the
barrier, nor will it emit any machine instructions for it.

Closes #24118, implementing RFC 888.
-rw-r--r--src/libcore/intrinsics.rs15
-rw-r--r--src/librustc_llvm/lib.rs12
-rw-r--r--src/librustc_trans/trans/build.rs6
-rw-r--r--src/librustc_trans/trans/builder.rs6
-rw-r--r--src/librustc_trans/trans/intrinsic.rs7
-rw-r--r--src/librustc_typeck/check/mod.rs2
-rw-r--r--src/rustllvm/RustWrapper.cpp6
7 files changed, 43 insertions, 11 deletions
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 8ed89adec5b..d525ff64cac 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -139,6 +139,21 @@ extern "rust-intrinsic" {
     pub fn atomic_fence_rel();
     pub fn atomic_fence_acqrel();
 
+    /// A compiler-only memory barrier.
+    ///
+    /// Memory accesses will never be reordered across this barrier by the compiler,
+    /// but no instructions will be emitted for it. This is appropriate for operations
+    /// on the same thread that may be preempted, such as when interacting with signal
+    /// handlers.
+    #[cfg(not(stage0))]     // SNAP 5520801
+    pub fn atomic_singlethreadfence();
+    #[cfg(not(stage0))]     // SNAP 5520801
+    pub fn atomic_singlethreadfence_acq();
+    #[cfg(not(stage0))]     // SNAP 5520801
+    pub fn atomic_singlethreadfence_rel();
+    #[cfg(not(stage0))]     // SNAP 5520801
+    pub fn atomic_singlethreadfence_acqrel();
+
     /// Aborts the execution of the process.
     pub fn abort() -> !;
 
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 80e01154655..f4cf2844717 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -43,6 +43,7 @@ pub use self::RealPredicate::*;
 pub use self::TypeKind::*;
 pub use self::AtomicBinOp::*;
 pub use self::AtomicOrdering::*;
+pub use self::SynchronizationScope::*;
 pub use self::FileType::*;
 pub use self::MetadataType::*;
 pub use self::AsmDialect::*;
@@ -361,6 +362,13 @@ pub enum AtomicOrdering {
     SequentiallyConsistent = 7
 }
 
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub enum SynchronizationScope {
+    SingleThread = 0,
+    CrossThread = 1
+}
+
 // Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h)
 #[repr(C)]
 #[derive(Copy, Clone)]
@@ -1534,7 +1542,9 @@ extern {
                               SingleThreaded: Bool)
                               -> ValueRef;
 
-    pub fn LLVMBuildAtomicFence(B: BuilderRef, Order: AtomicOrdering);
+    pub fn LLVMBuildAtomicFence(B: BuilderRef,
+                                Order: AtomicOrdering,
+                                Scope: SynchronizationScope);
 
 
     /* Selected entries from the downcasts. */
diff --git a/src/librustc_trans/trans/build.rs b/src/librustc_trans/trans/build.rs
index 32d73e50e6b..d6ac412a4fa 100644
--- a/src/librustc_trans/trans/build.rs
+++ b/src/librustc_trans/trans/build.rs
@@ -12,7 +12,7 @@
 #![allow(non_snake_case)]
 
 use llvm;
-use llvm::{CallConv, AtomicBinOp, AtomicOrdering, AsmDialect, AttrBuilder};
+use llvm::{CallConv, AtomicBinOp, AtomicOrdering, SynchronizationScope, AsmDialect, AttrBuilder};
 use llvm::{Opcode, IntPredicate, RealPredicate};
 use llvm::{ValueRef, BasicBlockRef};
 use trans::common::*;
@@ -965,9 +965,9 @@ pub fn CallWithConv(cx: Block,
     B(cx).call_with_conv(fn_, args, conv, attributes)
 }
 
-pub fn AtomicFence(cx: Block, order: AtomicOrdering) {
+pub fn AtomicFence(cx: Block, order: AtomicOrdering, scope: SynchronizationScope) {
     if cx.unreachable.get() { return; }
-    B(cx).atomic_fence(order)
+    B(cx).atomic_fence(order, scope)
 }
 
 pub fn Select(cx: Block, if_: ValueRef, then: ValueRef, else_: ValueRef) -> ValueRef {
diff --git a/src/librustc_trans/trans/builder.rs b/src/librustc_trans/trans/builder.rs
index 3febd41bdce..497e0ae422c 100644
--- a/src/librustc_trans/trans/builder.rs
+++ b/src/librustc_trans/trans/builder.rs
@@ -11,7 +11,7 @@
 #![allow(dead_code)] // FFI wrappers
 
 use llvm;
-use llvm::{CallConv, AtomicBinOp, AtomicOrdering, AsmDialect, AttrBuilder};
+use llvm::{CallConv, AtomicBinOp, AtomicOrdering, SynchronizationScope, AsmDialect, AttrBuilder};
 use llvm::{Opcode, IntPredicate, RealPredicate, False};
 use llvm::{ValueRef, BasicBlockRef, BuilderRef, ModuleRef};
 use trans::base;
@@ -989,9 +989,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn atomic_fence(&self, order: AtomicOrdering) {
+    pub fn atomic_fence(&self, order: AtomicOrdering, scope: SynchronizationScope) {
         unsafe {
-            llvm::LLVMBuildAtomicFence(self.llbuilder, order);
+            llvm::LLVMBuildAtomicFence(self.llbuilder, order, scope);
         }
     }
 }
diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs
index 6bfa80f9c40..0667a51ecf7 100644
--- a/src/librustc_trans/trans/intrinsic.rs
+++ b/src/librustc_trans/trans/intrinsic.rs
@@ -763,7 +763,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                 }
 
                 "fence" => {
-                    AtomicFence(bcx, order);
+                    AtomicFence(bcx, order, llvm::CrossThread);
+                    C_nil(ccx)
+                }
+
+                "singlethreadfence" => {
+                    AtomicFence(bcx, order, llvm::SingleThread);
                     C_nil(ccx)
                 }
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index e87deba2808..1f04ed444da 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4812,7 +4812,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
                  param(ccx, 0))
             }
-            "fence" => {
+            "fence" | "singlethreadfence" => {
                 (0, Vec::new(), ty::mk_nil(tcx))
             }
             op => {
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index fe0a7b454c1..375c5fc746c 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -189,8 +189,10 @@ extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
                                                failure_order
                                                ));
 }
-extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B, AtomicOrdering order) {
-    return wrap(unwrap(B)->CreateFence(order));
+extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B,
+                                             AtomicOrdering order,
+                                             SynchronizationScope scope) {
+    return wrap(unwrap(B)->CreateFence(order, scope));
 }
 
 extern "C" void LLVMSetDebug(int Enabled) {