diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 050c144b74299..3c52b8718a179 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -157,6 +157,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 ac134f7 + pub fn atomic_singlethreadfence(); + #[cfg(not(stage0))] // SNAP ac134f7 + pub fn atomic_singlethreadfence_acq(); + #[cfg(not(stage0))] // SNAP ac134f7 + pub fn atomic_singlethreadfence_rel(); + #[cfg(not(stage0))] // SNAP ac134f7 + pub fn atomic_singlethreadfence_acqrel(); + /// Abort the execution of the process. pub fn abort() -> !; diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 878070e98e7e8..c3f5ce974cff5 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -44,6 +44,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::*; @@ -362,6 +363,13 @@ pub enum AtomicOrdering { SequentiallyConsistent = 7 } +#[repr(C)] +#[derive(Copy)] +pub enum SynchronizationScope { + SingleThread = 0, + CrossThread = 1 +} + // Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h) #[repr(C)] #[derive(Copy)] @@ -1504,7 +1512,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 2fcfc5e43931d..4d0726d8e31fb 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 e268c2f0d5cc2..80c9a88c8f51d 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; @@ -988,9 +988,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 5687247561e9c..89f64f63d0595 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -725,7 +725,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 d12b23187b80b..e237deb41eb65 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5241,7 +5241,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 aaf6d8df29cad..120a310477335 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -205,8 +205,10 @@ extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, #endif )); } -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) {