Skip to content

Commit 1bf2f68

Browse files
committed
auto merge of #6437 : Thiez/rust/atomic, r=Aatch
This pull request adds 4 atomic intrinsics to the compiler, in preparation for #5042. * `atomic_load(src: &int) -> int` performs an atomic sequentially consistent load. * `atomic_load_acq(src: &int) -> int` performs an atomic acquiring load. * `atomic_store(dst: &mut int, val: int)` performs an atomic sequentially consistent store. * `atomic_store_rel(dst: &mut int, val: int)` performs an atomic releasing store. For more information about the whole acquire/release thing: http://llvm.org/docs/Atomics.html r?
2 parents 2774392 + 852af34 commit 1bf2f68

File tree

9 files changed

+136
-5
lines changed

9 files changed

+136
-5
lines changed

src/libcore/unstable/intrinsics.rs

+10
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ pub extern "rust-intrinsic" {
2020
pub fn atomic_cxchg_acq(dst: &mut int, old: int, src: int) -> int;
2121
pub fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int;
2222

23+
#[cfg(not(stage0))]
24+
pub fn atomic_load(src: &int) -> int;
25+
#[cfg(not(stage0))]
26+
pub fn atomic_load_acq(src: &int) -> int;
27+
28+
#[cfg(not(stage0))]
29+
pub fn atomic_store(dst: &mut int, val: int);
30+
#[cfg(not(stage0))]
31+
pub fn atomic_store_rel(dst: &mut int, val: int);
32+
2333
pub fn atomic_xchg(dst: &mut int, src: int) -> int;
2434
pub fn atomic_xchg_acq(dst: &mut int, src: int) -> int;
2535
pub fn atomic_xchg_rel(dst: &mut int, src: int) -> int;

src/librustc/lib/llvm.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -1339,13 +1339,16 @@ pub mod llvm {
13391339
PointerVal: ValueRef) -> ValueRef;
13401340
#[fast_ffi]
13411341
pub unsafe fn LLVMBuildLoad(B: BuilderRef,
1342-
PointerVal: ValueRef,
1343-
Name: *c_char)
1344-
-> ValueRef;
1342+
PointerVal: ValueRef,
1343+
Name: *c_char)
1344+
-> ValueRef;
1345+
13451346
#[fast_ffi]
13461347
pub unsafe fn LLVMBuildStore(B: BuilderRef,
13471348
Val: ValueRef,
1348-
Ptr: ValueRef) -> ValueRef;
1349+
Ptr: ValueRef)
1350+
-> ValueRef;
1351+
13491352
#[fast_ffi]
13501353
pub unsafe fn LLVMBuildGEP(B: BuilderRef,
13511354
Pointer: ValueRef,
@@ -1561,6 +1564,17 @@ pub mod llvm {
15611564
Name: *c_char) -> ValueRef;
15621565

15631566
/* Atomic Operations */
1567+
pub unsafe fn LLVMBuildAtomicLoad(B: BuilderRef,
1568+
PointerVal: ValueRef,
1569+
Order: AtomicOrdering)
1570+
-> ValueRef;
1571+
1572+
pub unsafe fn LLVMBuildAtomicStore(B: BuilderRef,
1573+
Val: ValueRef,
1574+
Ptr: ValueRef,
1575+
Order: AtomicOrdering)
1576+
-> ValueRef;
1577+
15641578
pub unsafe fn LLVMBuildAtomicCmpXchg(B: BuilderRef,
15651579
LHS: ValueRef,
15661580
CMP: ValueRef,

src/librustc/middle/trans/build.rs

+23
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,18 @@ pub fn Load(cx: block, PointerVal: ValueRef) -> ValueRef {
537537
}
538538
}
539539
540+
pub fn AtomicLoad(cx: block, PointerVal: ValueRef, order: AtomicOrdering) -> ValueRef {
541+
unsafe {
542+
let ccx = cx.fcx.ccx;
543+
if cx.unreachable {
544+
return llvm::LLVMGetUndef(ccx.int_type);
545+
}
546+
count_insn(cx, "load.atomic");
547+
return llvm::LLVMBuildAtomicLoad(B(cx), PointerVal, order);
548+
}
549+
}
550+
551+
540552
pub fn LoadRangeAssert(cx: block, PointerVal: ValueRef, lo: c_ulonglong,
541553
hi: c_ulonglong, signed: lib::llvm::Bool) -> ValueRef {
542554
let value = Load(cx, PointerVal);
@@ -567,6 +579,17 @@ pub fn Store(cx: block, Val: ValueRef, Ptr: ValueRef) {
567579
}
568580
}
569581
582+
pub fn AtomicStore(cx: block, Val: ValueRef, Ptr: ValueRef, order: AtomicOrdering) {
583+
unsafe {
584+
if cx.unreachable { return; }
585+
debug!("Store %s -> %s",
586+
val_str(cx.ccx().tn, Val),
587+
val_str(cx.ccx().tn, Ptr));
588+
count_insn(cx, "store.atomic");
589+
llvm::LLVMBuildAtomicStore(B(cx), Val, Ptr, order);
590+
}
591+
}
592+
570593
pub fn GEP(cx: block, Pointer: ValueRef, Indices: &[ValueRef]) -> ValueRef {
571594
unsafe {
572595
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_nil())); }

src/librustc/middle/trans/foreign.rs

+24
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,30 @@ pub fn trans_intrinsic(ccx: @CrateContext,
592592
Release);
593593
Store(bcx, old, fcx.llretptr.get());
594594
}
595+
~"atomic_load" => {
596+
let old = AtomicLoad(bcx,
597+
get_param(decl, first_real_arg),
598+
SequentiallyConsistent);
599+
Store(bcx, old, fcx.llretptr.get());
600+
}
601+
~"atomic_load_acq" => {
602+
let old = AtomicLoad(bcx,
603+
get_param(decl, first_real_arg),
604+
Acquire);
605+
Store(bcx, old, fcx.llretptr.get());
606+
}
607+
~"atomic_store" => {
608+
AtomicStore(bcx,
609+
get_param(decl, first_real_arg + 1u),
610+
get_param(decl, first_real_arg),
611+
SequentiallyConsistent);
612+
}
613+
~"atomic_store_rel" => {
614+
AtomicStore(bcx,
615+
get_param(decl, first_real_arg + 1u),
616+
get_param(decl, first_real_arg),
617+
Release);
618+
}
595619
~"atomic_xchg" => {
596620
let old = AtomicRMW(bcx, Xchg,
597621
get_param(decl, first_real_arg),

src/librustc/middle/trans/type_use.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,9 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint)
124124
~"get_tydesc" | ~"needs_drop" => use_tydesc,
125125

126126
~"atomic_cxchg" | ~"atomic_cxchg_acq"|
127-
~"atomic_cxchg_rel"| ~"atomic_xchg" |
127+
~"atomic_cxchg_rel"| ~"atomic_load" |
128+
~"atomic_load_acq" | ~"atomic_store" |
129+
~"atomic_store_rel"| ~"atomic_xchg" |
128130
~"atomic_xadd" | ~"atomic_xsub" |
129131
~"atomic_xchg_acq" | ~"atomic_xadd_acq" |
130132
~"atomic_xsub_acq" | ~"atomic_xchg_rel" |

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

+19
Original file line numberDiff line numberDiff line change
@@ -3486,6 +3486,25 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
34863486
],
34873487
ty::mk_int())
34883488
}
3489+
~"atomic_load" | ~"atomic_load_acq" => {
3490+
(0,
3491+
~[
3492+
arg(ty::mk_imm_rptr(tcx,
3493+
ty::re_bound(ty::br_anon(0)),
3494+
ty::mk_int()))
3495+
],
3496+
ty::mk_int())
3497+
}
3498+
~"atomic_store" | ~"atomic_store_rel" => {
3499+
(0,
3500+
~[
3501+
arg(ty::mk_mut_rptr(tcx,
3502+
ty::re_bound(ty::br_anon(0)),
3503+
ty::mk_int())),
3504+
arg(ty::mk_int())
3505+
],
3506+
ty::mk_nil())
3507+
}
34893508
~"atomic_xchg" | ~"atomic_xadd" | ~"atomic_xsub" |
34903509
~"atomic_xchg_acq" | ~"atomic_xadd_acq" | ~"atomic_xsub_acq" |
34913510
~"atomic_xchg_rel" | ~"atomic_xadd_rel" | ~"atomic_xsub_rel" => {

src/rustllvm/RustWrapper.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,28 @@ extern "C" LLVMTypeRef LLVMMetadataType(void) {
545545
return LLVMMetadataTypeInContext(LLVMGetGlobalContext());
546546
}
547547

548+
extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B,
549+
LLVMValueRef source,
550+
const char* Name,
551+
AtomicOrdering order) {
552+
LoadInst* li = new LoadInst(unwrap(source),0);
553+
li->setVolatile(true);
554+
li->setAtomic(order);
555+
li->setAlignment(sizeof(intptr_t));
556+
return wrap(unwrap(B)->Insert(li));
557+
}
558+
559+
extern "C" LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B,
560+
LLVMValueRef val,
561+
LLVMValueRef target,
562+
AtomicOrdering order) {
563+
StoreInst* si = new StoreInst(unwrap(val),unwrap(target));
564+
si->setVolatile(true);
565+
si->setAtomic(order);
566+
si->setAlignment(sizeof(intptr_t));
567+
return wrap(unwrap(B)->Insert(si));
568+
}
569+
548570
extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
549571
LLVMValueRef target,
550572
LLVMValueRef old,

src/rustllvm/rustllvm.def.in

+2
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ LLVMArrayType
8484
LLVMBasicBlockAsValue
8585
LLVMBlockAddress
8686
LLVMBuildAShr
87+
LLVMBuildAtomicLoad
88+
LLVMBuildAtomicStore
8789
LLVMBuildAtomicCmpXchg
8890
LLVMBuildAtomicRMW
8991
LLVMBuildAdd

src/test/run-pass/intrinsic-atomics.rs

+15
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ mod rusti {
1515
pub fn atomic_cxchg_acq(dst: &mut int, old: int, src: int) -> int;
1616
pub fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int;
1717

18+
pub fn atomic_load(src: &int) -> int;
19+
pub fn atomic_load_acq(src: &int) -> int;
20+
21+
pub fn atomic_store(dst: &mut int, val: int);
22+
pub fn atomic_store_rel(dst: &mut int, val: int);
23+
1824
pub fn atomic_xchg(dst: &mut int, src: int) -> int;
1925
pub fn atomic_xchg_acq(dst: &mut int, src: int) -> int;
2026
pub fn atomic_xchg_rel(dst: &mut int, src: int) -> int;
@@ -33,6 +39,15 @@ pub fn main() {
3339
unsafe {
3440
let mut x = ~1;
3541

42+
assert!(rusti::atomic_load(x) == 1);
43+
*x = 5;
44+
assert!(rusti::atomic_load_acq(x) == 5);
45+
46+
rusti::atomic_store(x,3);
47+
assert!(*x == 3);
48+
rusti::atomic_store_rel(x,1);
49+
assert!(*x == 1);
50+
3651
assert!(rusti::atomic_cxchg(x, 1, 2) == 1);
3752
assert!(*x == 2);
3853

0 commit comments

Comments
 (0)