Add an atomic fence intrinsic

This commit is contained in:
James Miller 2013-07-28 19:48:16 +12:00
parent 9325535b41
commit 4a1a0fbed5
9 changed files with 62 additions and 2 deletions

View File

@ -1594,6 +1594,9 @@ pub mod llvm {
Order: AtomicOrdering)
-> ValueRef;
pub unsafe fn LLVMBuildAtomicFence(B: BuilderRef, Order: AtomicOrdering);
/* Selected entries from the downcasts. */
#[fast_ffi]
pub unsafe fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;

View File

@ -660,6 +660,11 @@ pub fn CallWithConv(cx: @mut Block, Fn: ValueRef, Args: &[ValueRef],
B(cx).call_with_conv(Fn, Args, Conv)
}
pub fn AtomicFence(cx: @mut Block, order: AtomicOrdering) {
if cx.unreachable { return; }
B(cx).atomic_fence(order)
}
pub fn Select(cx: @mut Block, If: ValueRef, Then: ValueRef, Else: ValueRef) -> ValueRef {
if cx.unreachable { return _Undef(Then); }
B(cx).select(If, Then, Else)

View File

@ -943,4 +943,10 @@ impl Builder {
llvm::LLVMBuildAtomicRMW(self.llbuilder, op, dst, src, order)
}
}
pub fn atomic_fence(&self, order: AtomicOrdering) {
unsafe {
llvm::LLVMBuildAtomicFence(self.llbuilder, order);
}
}
}

View File

@ -661,6 +661,10 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
order);
RetVoid(bcx);
}
"fence" => {
AtomicFence(bcx, order);
RetVoid(bcx);
}
op => {
// These are all AtomicRMW ops
let atom_op = match op {

View File

@ -3521,7 +3521,9 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
ty::re_bound(ty::br_anon(0)),
ty::mk_int()), ty::mk_int() ], ty::mk_int())
}
"fence" => {
(0, ~[], ty::mk_nil())
}
op => {
tcx.sess.span_err(it.span,
fmt!("unrecognized atomic operation function: `%s`",

View File

@ -569,6 +569,33 @@ pub unsafe fn atomic_umin<T>(dst: &mut T, val: T, order: Ordering) -> T {
})
}
/**
* An atomic fence.
*
* A fence 'A' which has `Release` ordering semantics, synchronizes with a
* fence 'B' with (at least) `Aquire` semantics, if and only if there exists
* atomic operations X and Y, bother operating on some atomic object 'M' such
* that A is sequenced before X, Y is synchronized before B and Y obsevers
* the change to M. This provides a happens-before dependence between A and B.
*
* Atomic operations with `Release` or `Acquire` semantics can also synchronize
* with a fence.
*
* A fence with has `SeqCst` ordering, in addition to having both `Acquire` and
* `Release` semantics, participates in the global program order of the other
* `SeqCst` operations and/or fences.
*
* Accepts `Acquire`, `Release`, `AcqRel` and `SeqCst` orderings.
*/
#[inline] #[cfg(not(stage0))]
pub fn fence(order: Ordering) {
match order {
Acquire => intrinsics::atomic_fence_acq(),
Release => intrinsics::atomic_fence_rel(),
AcqRel => intrinsics::atomic_fence_rel(),
_ => intrinsics::atomic_fence(),
}
}
#[cfg(test)]
mod test {

View File

@ -256,6 +256,15 @@ extern "rust-intrinsic" {
pub fn atomic_umax_acqrel(dst: &mut int, src: int) -> int;
pub fn atomic_umax_relaxed(dst: &mut int, src: int) -> int;
#[cfg(not(stage0))]
pub fn atomic_fence();
#[cfg(not(stage0))]
pub fn atomic_fence_acq();
#[cfg(not(stage0))]
pub fn atomic_fence_rel();
#[cfg(not(stage0))]
pub fn atomic_fence_acqrel();
/// The size of a type in bytes.
///
/// This is the exact number of bytes in memory taken up by a

View File

@ -513,6 +513,9 @@ extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
return wrap(unwrap(B)->CreateAtomicCmpXchg(unwrap(target), unwrap(old),
unwrap(source), order));
}
extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B, AtomicOrdering order) {
return wrap(unwrap(B)->CreateFence(order));
}
extern "C" LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,
AtomicRMWInst::BinOp op,
LLVMValueRef target,
@ -838,4 +841,4 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType(
Flags,
unwrapDI<DIArray>(Elements),
RunTimeLang));
}
}

View File

@ -90,6 +90,7 @@ LLVMBuildAtomicLoad
LLVMBuildAtomicStore
LLVMBuildAtomicCmpXchg
LLVMBuildAtomicRMW
LLVMBuildAtomicFence
LLVMBuildAdd
LLVMBuildAggregateRet
LLVMBuildAlloca