diff --git a/src/rustc/lib/llvm.rs b/src/rustc/lib/llvm.rs index 0d92c19b952..f1397006b16 100644 --- a/src/rustc/lib/llvm.rs +++ b/src/rustc/lib/llvm.rs @@ -843,6 +843,9 @@ fn LLVMBuildPtrDiff(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; /* Atomic Operations */ + fn LLVMBuildAtomicCmpXchg(B: BuilderRef, LHS: ValueRef, + CMP: ValueRef, RHS: ValueRef, + ++Order: AtomicOrdering) -> ValueRef; fn LLVMBuildAtomicRMW(B: BuilderRef, ++Op: AtomicBinOp, LHS: ValueRef, RHS: ValueRef, ++Order: AtomicOrdering) -> ValueRef; diff --git a/src/rustc/middle/trans/build.rs b/src/rustc/middle/trans/build.rs index ea992600ae1..f7690b7bc93 100644 --- a/src/rustc/middle/trans/build.rs +++ b/src/rustc/middle/trans/build.rs @@ -813,6 +813,11 @@ fn Resume(cx: block, Exn: ValueRef) -> ValueRef { } // Atomic Operations +fn AtomicCmpXchg(cx: block, dst: ValueRef, + cmp: ValueRef, src: ValueRef, + order: AtomicOrdering) -> ValueRef { + llvm::LLVMBuildAtomicCmpXchg(B(cx), dst, cmp, src, order) +} fn AtomicRMW(cx: block, op: AtomicBinOp, dst: ValueRef, src: ValueRef, order: AtomicOrdering) -> ValueRef { diff --git a/src/rustc/middle/trans/foreign.rs b/src/rustc/middle/trans/foreign.rs index d307fcb5dca..8fa23ef8fab 100644 --- a/src/rustc/middle/trans/foreign.rs +++ b/src/rustc/middle/trans/foreign.rs @@ -799,6 +799,30 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item, Some(substs), Some(item.span)); let mut bcx = top_scope_block(fcx, None), lltop = bcx.llbb; match ccx.sess.str_of(item.ident) { + ~"atomic_cxchg" => { + let old = AtomicCmpXchg(bcx, + get_param(decl, first_real_arg), + get_param(decl, first_real_arg + 1u), + get_param(decl, first_real_arg + 2u), + SequentiallyConsistent); + Store(bcx, old, fcx.llretptr); + } + ~"atomic_cxchg_acq" => { + let old = AtomicCmpXchg(bcx, + get_param(decl, first_real_arg), + get_param(decl, first_real_arg + 1u), + get_param(decl, first_real_arg + 2u), + Acquire); + Store(bcx, old, fcx.llretptr); + } + ~"atomic_cxchg_rel" => { + let old = AtomicCmpXchg(bcx, + get_param(decl, first_real_arg), + get_param(decl, first_real_arg + 1u), + get_param(decl, first_real_arg + 2u), + Release); + Store(bcx, old, fcx.llretptr); + } ~"atomic_xchg" => { let old = AtomicRMW(bcx, Xchg, get_param(decl, first_real_arg), diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index 8b2efacd4d1..ddd50d47c08 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -98,11 +98,12 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) ~"get_tydesc" | ~"needs_drop" => use_tydesc, - ~"atomic_xchg" | ~"atomic_xadd" | - ~"atomic_xsub" | ~"atomic_xchg_acq" | - ~"atomic_xadd_acq" | ~"atomic_xsub_acq" | - ~"atomic_xchg_rel" | ~"atomic_xadd_rel" | - ~"atomic_xsub_rel" => 0, + ~"atomic_cxchg" | ~"atomic_cxchg_acq"| + ~"atomic_cxchg_rel"| ~"atomic_xchg" | + ~"atomic_xadd" | ~"atomic_xsub" | + ~"atomic_xchg_acq" | ~"atomic_xadd_acq" | + ~"atomic_xsub_acq" | ~"atomic_xchg_rel" | + ~"atomic_xadd_rel" | ~"atomic_xsub_rel" => 0, ~"visit_tydesc" | ~"forget" | ~"addr_of" | ~"frame_address" | ~"morestack_addr" => 0, diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 5f9e584fa7b..f4764c5d595 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -2605,7 +2605,15 @@ fn arg(m: ast::rmode, ty: ty::t) -> ty::arg { } ~"needs_drop" => (1u, ~[], ty::mk_bool(tcx)), - ~"atomic_xchg" | ~"atomic_xadd" | ~"atomic_xsub" | + ~"atomic_cxchg" | ~"atomic_cxchg_acq"| ~"atomic_cxchg_rel" => { + (0u, ~[arg(ast::by_copy, + ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), + ty::mk_int(tcx))), + arg(ast::by_copy, ty::mk_int(tcx)), + arg(ast::by_copy, ty::mk_int(tcx))], + ty::mk_int(tcx)) + } + ~"atomic_xchg" | ~"atomic_xadd" | ~"atomic_xsub" | ~"atomic_xchg_acq" | ~"atomic_xadd_acq" | ~"atomic_xsub_acq" | ~"atomic_xchg_rel" | ~"atomic_xadd_rel" | ~"atomic_xsub_rel" => { (0u, ~[arg(ast::by_copy, diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 498a4e137f0..39a707ad320 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -482,6 +482,14 @@ extern "C" LLVMTypeRef LLVMMetadataType(void) { return LLVMMetadataTypeInContext(LLVMGetGlobalContext()); } +extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, + LLVMValueRef target, + LLVMValueRef old, + LLVMValueRef source, + AtomicOrdering order) { + return wrap(unwrap(B)->CreateAtomicCmpXchg(unwrap(target), unwrap(old), + unwrap(source), order)); +} extern "C" LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B, AtomicRMWInst::BinOp op, LLVMValueRef target, diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index 36833e5175e..44636f4f36b 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -84,6 +84,7 @@ LLVMArrayType LLVMBasicBlockAsValue LLVMBlockAddress LLVMBuildAShr +LLVMBuildAtomicCmpXchg LLVMBuildAtomicRMW LLVMBuildAdd LLVMBuildAggregateRet diff --git a/src/test/auxiliary/cci_intrinsic.rs b/src/test/auxiliary/cci_intrinsic.rs index 1cde1a049fe..f3ea9fd531c 100644 --- a/src/test/auxiliary/cci_intrinsic.rs +++ b/src/test/auxiliary/cci_intrinsic.rs @@ -2,6 +2,10 @@ #[abi = "rust-intrinsic"] extern mod rusti { #[legacy_exports]; + fn atomic_cxchg(dst: &mut int, old: int, src: int) -> int; + fn atomic_cxchg_acq(dst: &mut int, old: int, src: int) -> int; + fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int; + fn atomic_xchg(dst: &mut int, src: int) -> int; fn atomic_xchg_acq(dst: &mut int, src: int) -> int; fn atomic_xchg_rel(dst: &mut int, src: int) -> int; diff --git a/src/test/run-pass/intrinsic-atomics.rs b/src/test/run-pass/intrinsic-atomics.rs index 2629afa4909..8438ecf383e 100644 --- a/src/test/run-pass/intrinsic-atomics.rs +++ b/src/test/run-pass/intrinsic-atomics.rs @@ -1,6 +1,10 @@ #[abi = "rust-intrinsic"] extern mod rusti { #[legacy_exports]; + fn atomic_cxchg(dst: &mut int, old: int, src: int) -> int; + fn atomic_cxchg_acq(dst: &mut int, old: int, src: int) -> int; + fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int; + fn atomic_xchg(dst: &mut int, src: int) -> int; fn atomic_xchg_acq(dst: &mut int, src: int) -> int; fn atomic_xchg_rel(dst: &mut int, src: int) -> int; @@ -17,6 +21,15 @@ fn main() { let x = ~mut 1; + assert rusti::atomic_cxchg(x, 1, 2) == 1; + assert *x == 2; + + assert rusti::atomic_cxchg_acq(x, 1, 3) == 2; + assert *x == 2; + + assert rusti::atomic_cxchg_rel(x, 2, 1) == 2; + assert *x == 1; + assert rusti::atomic_xchg(x, 0) == 1; assert *x == 0;