diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 8ed89adec5b69..59008d5db11ef 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 857ef6e + pub fn atomic_singlethreadfence(); + #[cfg(not(stage0))] // SNAP 857ef6e + pub fn atomic_singlethreadfence_acq(); + #[cfg(not(stage0))] // SNAP 857ef6e + pub fn atomic_singlethreadfence_rel(); + #[cfg(not(stage0))] // SNAP 857ef6e + 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 80e01154655e7..f4cf28447175c 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 32d73e50e6b6b..d6ac412a4faea 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 3febd41bdce2e..497e0ae422c1f 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 6bfa80f9c40b3..0667a51ecf705 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 e87deba280804..1f04ed444da9c 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 fe0a7b454c17d..375c5fc746c5b 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) {