diff options
| author | Peter Marheine <peter@taricorp.net> | 2015-02-14 23:48:10 -0700 |
|---|---|---|
| committer | Peter Marheine <peter@taricorp.net> | 2015-04-25 19:41:21 -0600 |
| commit | 998c10d6b64f9a37d4cab33e09b9dfd551c76b92 (patch) | |
| tree | d3272508b6aa37ce49b633ede17dc8ce29b6fea4 | |
| parent | 0d8309ec0b13ebad02bbc76f93eff39edf4af2d0 (diff) | |
| download | rust-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.rs | 15 | ||||
| -rw-r--r-- | src/librustc_llvm/lib.rs | 12 | ||||
| -rw-r--r-- | src/librustc_trans/trans/build.rs | 6 | ||||
| -rw-r--r-- | src/librustc_trans/trans/builder.rs | 6 | ||||
| -rw-r--r-- | src/librustc_trans/trans/intrinsic.rs | 7 | ||||
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 2 | ||||
| -rw-r--r-- | src/rustllvm/RustWrapper.cpp | 6 |
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) { |
