Skip to content

Commit 4a1a0fb

Browse files
committed
Add an atomic fence intrinsic
1 parent 9325535 commit 4a1a0fb

File tree

9 files changed

+62
-2
lines changed

9 files changed

+62
-2
lines changed

src/librustc/lib/llvm.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,6 +1594,9 @@ pub mod llvm {
15941594
Order: AtomicOrdering)
15951595
-> ValueRef;
15961596

1597+
pub unsafe fn LLVMBuildAtomicFence(B: BuilderRef, Order: AtomicOrdering);
1598+
1599+
15971600
/* Selected entries from the downcasts. */
15981601
#[fast_ffi]
15991602
pub unsafe fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;

src/librustc/middle/trans/build.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,11 @@ pub fn CallWithConv(cx: @mut Block, Fn: ValueRef, Args: &[ValueRef],
660660
B(cx).call_with_conv(Fn, Args, Conv)
661661
}
662662

663+
pub fn AtomicFence(cx: @mut Block, order: AtomicOrdering) {
664+
if cx.unreachable { return; }
665+
B(cx).atomic_fence(order)
666+
}
667+
663668
pub fn Select(cx: @mut Block, If: ValueRef, Then: ValueRef, Else: ValueRef) -> ValueRef {
664669
if cx.unreachable { return _Undef(Then); }
665670
B(cx).select(If, Then, Else)

src/librustc/middle/trans/builder.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,4 +943,10 @@ impl Builder {
943943
llvm::LLVMBuildAtomicRMW(self.llbuilder, op, dst, src, order)
944944
}
945945
}
946+
947+
pub fn atomic_fence(&self, order: AtomicOrdering) {
948+
unsafe {
949+
llvm::LLVMBuildAtomicFence(self.llbuilder, order);
950+
}
951+
}
946952
}

src/librustc/middle/trans/foreign.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,10 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
661661
order);
662662
RetVoid(bcx);
663663
}
664+
"fence" => {
665+
AtomicFence(bcx, order);
666+
RetVoid(bcx);
667+
}
664668
op => {
665669
// These are all AtomicRMW ops
666670
let atom_op = match op {

src/librustc/middle/typeck/check/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3521,7 +3521,9 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
35213521
ty::re_bound(ty::br_anon(0)),
35223522
ty::mk_int()), ty::mk_int() ], ty::mk_int())
35233523
}
3524-
3524+
"fence" => {
3525+
(0, ~[], ty::mk_nil())
3526+
}
35253527
op => {
35263528
tcx.sess.span_err(it.span,
35273529
fmt!("unrecognized atomic operation function: `%s`",

src/libstd/unstable/atomics.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,33 @@ pub unsafe fn atomic_umin<T>(dst: &mut T, val: T, order: Ordering) -> T {
569569
})
570570
}
571571

572+
/**
573+
* An atomic fence.
574+
*
575+
* A fence 'A' which has `Release` ordering semantics, synchronizes with a
576+
* fence 'B' with (at least) `Aquire` semantics, if and only if there exists
577+
* atomic operations X and Y, bother operating on some atomic object 'M' such
578+
* that A is sequenced before X, Y is synchronized before B and Y obsevers
579+
* the change to M. This provides a happens-before dependence between A and B.
580+
*
581+
* Atomic operations with `Release` or `Acquire` semantics can also synchronize
582+
* with a fence.
583+
*
584+
* A fence with has `SeqCst` ordering, in addition to having both `Acquire` and
585+
* `Release` semantics, participates in the global program order of the other
586+
* `SeqCst` operations and/or fences.
587+
*
588+
* Accepts `Acquire`, `Release`, `AcqRel` and `SeqCst` orderings.
589+
*/
590+
#[inline] #[cfg(not(stage0))]
591+
pub fn fence(order: Ordering) {
592+
match order {
593+
Acquire => intrinsics::atomic_fence_acq(),
594+
Release => intrinsics::atomic_fence_rel(),
595+
AcqRel => intrinsics::atomic_fence_rel(),
596+
_ => intrinsics::atomic_fence(),
597+
}
598+
}
572599

573600
#[cfg(test)]
574601
mod test {

src/libstd/unstable/intrinsics.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,15 @@ extern "rust-intrinsic" {
256256
pub fn atomic_umax_acqrel(dst: &mut int, src: int) -> int;
257257
pub fn atomic_umax_relaxed(dst: &mut int, src: int) -> int;
258258

259+
#[cfg(not(stage0))]
260+
pub fn atomic_fence();
261+
#[cfg(not(stage0))]
262+
pub fn atomic_fence_acq();
263+
#[cfg(not(stage0))]
264+
pub fn atomic_fence_rel();
265+
#[cfg(not(stage0))]
266+
pub fn atomic_fence_acqrel();
267+
259268
/// The size of a type in bytes.
260269
///
261270
/// This is the exact number of bytes in memory taken up by a

src/rustllvm/RustWrapper.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,9 @@ extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
513513
return wrap(unwrap(B)->CreateAtomicCmpXchg(unwrap(target), unwrap(old),
514514
unwrap(source), order));
515515
}
516+
extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B, AtomicOrdering order) {
517+
return wrap(unwrap(B)->CreateFence(order));
518+
}
516519
extern "C" LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,
517520
AtomicRMWInst::BinOp op,
518521
LLVMValueRef target,
@@ -838,4 +841,4 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType(
838841
Flags,
839842
unwrapDI<DIArray>(Elements),
840843
RunTimeLang));
841-
}
844+
}

src/rustllvm/rustllvm.def.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ LLVMBuildAtomicLoad
9090
LLVMBuildAtomicStore
9191
LLVMBuildAtomicCmpXchg
9292
LLVMBuildAtomicRMW
93+
LLVMBuildAtomicFence
9394
LLVMBuildAdd
9495
LLVMBuildAggregateRet
9596
LLVMBuildAlloca

0 commit comments

Comments
 (0)