Skip to content

Commit d754333

Browse files
committed
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.
1 parent 5be210c commit d754333

File tree

7 files changed

+43
-11
lines changed

7 files changed

+43
-11
lines changed

src/libcore/intrinsics.rs

+15
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,21 @@ extern "rust-intrinsic" {
157157
pub fn atomic_fence_rel();
158158
pub fn atomic_fence_acqrel();
159159

160+
/// A compiler-only memory barrier.
161+
///
162+
/// Memory accesses will never be reordered across this barrier by the compiler,
163+
/// but no instructions will be emitted for it. This is appropriate for operations
164+
/// on the same thread that may be preempted, such as when interacting with signal
165+
/// handlers.
166+
#[cfg(not(stage0))] // SNAP ac134f7
167+
pub fn atomic_singlethreadfence();
168+
#[cfg(not(stage0))] // SNAP ac134f7
169+
pub fn atomic_singlethreadfence_acq();
170+
#[cfg(not(stage0))] // SNAP ac134f7
171+
pub fn atomic_singlethreadfence_rel();
172+
#[cfg(not(stage0))] // SNAP ac134f7
173+
pub fn atomic_singlethreadfence_acqrel();
174+
160175
/// Abort the execution of the process.
161176
pub fn abort() -> !;
162177

src/librustc_llvm/lib.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ pub use self::RealPredicate::*;
4444
pub use self::TypeKind::*;
4545
pub use self::AtomicBinOp::*;
4646
pub use self::AtomicOrdering::*;
47+
pub use self::SynchronizationScope::*;
4748
pub use self::FileType::*;
4849
pub use self::MetadataType::*;
4950
pub use self::AsmDialect::*;
@@ -362,6 +363,13 @@ pub enum AtomicOrdering {
362363
SequentiallyConsistent = 7
363364
}
364365

366+
#[repr(C)]
367+
#[derive(Copy)]
368+
pub enum SynchronizationScope {
369+
SingleThread = 0,
370+
CrossThread = 1
371+
}
372+
365373
// Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h)
366374
#[repr(C)]
367375
#[derive(Copy)]
@@ -1504,7 +1512,9 @@ extern {
15041512
SingleThreaded: Bool)
15051513
-> ValueRef;
15061514

1507-
pub fn LLVMBuildAtomicFence(B: BuilderRef, Order: AtomicOrdering);
1515+
pub fn LLVMBuildAtomicFence(B: BuilderRef,
1516+
Order: AtomicOrdering,
1517+
Scope: SynchronizationScope);
15081518

15091519

15101520
/* Selected entries from the downcasts. */

src/librustc_trans/trans/build.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#![allow(non_snake_case)]
1313

1414
use llvm;
15-
use llvm::{CallConv, AtomicBinOp, AtomicOrdering, AsmDialect, AttrBuilder};
15+
use llvm::{CallConv, AtomicBinOp, AtomicOrdering, SynchronizationScope, AsmDialect, AttrBuilder};
1616
use llvm::{Opcode, IntPredicate, RealPredicate};
1717
use llvm::{ValueRef, BasicBlockRef};
1818
use trans::common::*;
@@ -965,9 +965,9 @@ pub fn CallWithConv(cx: Block,
965965
B(cx).call_with_conv(fn_, args, conv, attributes)
966966
}
967967

968-
pub fn AtomicFence(cx: Block, order: AtomicOrdering) {
968+
pub fn AtomicFence(cx: Block, order: AtomicOrdering, scope: SynchronizationScope) {
969969
if cx.unreachable.get() { return; }
970-
B(cx).atomic_fence(order)
970+
B(cx).atomic_fence(order, scope)
971971
}
972972

973973
pub fn Select(cx: Block, if_: ValueRef, then: ValueRef, else_: ValueRef) -> ValueRef {

src/librustc_trans/trans/builder.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#![allow(dead_code)] // FFI wrappers
1212

1313
use llvm;
14-
use llvm::{CallConv, AtomicBinOp, AtomicOrdering, AsmDialect, AttrBuilder};
14+
use llvm::{CallConv, AtomicBinOp, AtomicOrdering, SynchronizationScope, AsmDialect, AttrBuilder};
1515
use llvm::{Opcode, IntPredicate, RealPredicate, False};
1616
use llvm::{ValueRef, BasicBlockRef, BuilderRef, ModuleRef};
1717
use trans::base;
@@ -988,9 +988,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
988988
}
989989
}
990990

991-
pub fn atomic_fence(&self, order: AtomicOrdering) {
991+
pub fn atomic_fence(&self, order: AtomicOrdering, scope: SynchronizationScope) {
992992
unsafe {
993-
llvm::LLVMBuildAtomicFence(self.llbuilder, order);
993+
llvm::LLVMBuildAtomicFence(self.llbuilder, order, scope);
994994
}
995995
}
996996
}

src/librustc_trans/trans/intrinsic.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -725,7 +725,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
725725
}
726726

727727
"fence" => {
728-
AtomicFence(bcx, order);
728+
AtomicFence(bcx, order, llvm::CrossThread);
729+
C_nil(ccx)
730+
}
731+
732+
"singlethreadfence" => {
733+
AtomicFence(bcx, order, llvm::SingleThread);
729734
C_nil(ccx)
730735
}
731736

src/librustc_typeck/check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5241,7 +5241,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
52415241
(1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
52425242
param(ccx, 0))
52435243
}
5244-
"fence" => {
5244+
"fence" | "singlethreadfence" => {
52455245
(0, Vec::new(), ty::mk_nil(tcx))
52465246
}
52475247
op => {

src/rustllvm/RustWrapper.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,10 @@ extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
205205
#endif
206206
));
207207
}
208-
extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B, AtomicOrdering order) {
209-
return wrap(unwrap(B)->CreateFence(order));
208+
extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B,
209+
AtomicOrdering order,
210+
SynchronizationScope scope) {
211+
return wrap(unwrap(B)->CreateFence(order, scope));
210212
}
211213

212214
extern "C" void LLVMSetDebug(int Enabled) {

0 commit comments

Comments
 (0)