about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/rustc/lib/llvm.rs3
-rw-r--r--src/rustc/middle/trans/build.rs5
-rw-r--r--src/rustc/middle/trans/foreign.rs24
-rw-r--r--src/rustc/middle/trans/type_use.rs11
-rw-r--r--src/rustc/middle/typeck/check.rs10
-rw-r--r--src/rustllvm/RustWrapper.cpp8
-rw-r--r--src/rustllvm/rustllvm.def.in1
-rw-r--r--src/test/auxiliary/cci_intrinsic.rs4
-rw-r--r--src/test/run-pass/intrinsic-atomics.rs13
9 files changed, 73 insertions, 6 deletions
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 @@ extern mod llvm {
                         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 check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
       }
       ~"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 @@ extern mod rusti {
 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;