Skip to content

Commit 0a99912

Browse files
committed
Adding a bunch of atomic intrinsics.
Adding a test cases for the atomic intrinsics.
1 parent 3b5d76d commit 0a99912

File tree

8 files changed

+166
-3
lines changed

8 files changed

+166
-3
lines changed

src/rustc/lib/llvm.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,31 @@ enum TypeKind {
128128
X86_MMX = 15
129129
}
130130

131+
enum AtomicBinOp {
132+
Xchg = 0,
133+
Add = 1,
134+
Sub = 2,
135+
And = 3,
136+
Nand = 4,
137+
Or = 5,
138+
Xor = 6,
139+
Max = 7,
140+
Min = 8,
141+
UMax = 9,
142+
UMin = 10,
143+
}
144+
145+
enum AtomicOrdering {
146+
NotAtomic = 0,
147+
Unordered = 1,
148+
Monotonic = 2,
149+
// Consume = 3, // Not specified yet.
150+
Acquire = 4,
151+
Release = 5,
152+
AcquireRelease = 6,
153+
SequentiallyConsistent = 7
154+
}
155+
131156
// FIXME: Not used right now, but will be once #2334 is fixed
132157
// Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h)
133158
enum FileType {
@@ -772,6 +797,11 @@ native mod llvm {
772797
fn LLVMBuildPtrDiff(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
773798
Name: *c_char) -> ValueRef;
774799

800+
/* Atomic Operations */
801+
fn LLVMBuildAtomicRMW(B: BuilderRef, ++Op: AtomicBinOp,
802+
LHS: ValueRef, RHS: ValueRef,
803+
++Order: AtomicOrdering) -> ValueRef;
804+
775805
/* Selected entries from the downcasts. */
776806
fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;
777807

src/rustc/middle/trans/build.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import syntax::codemap;
55
import codemap::span;
66
import lib::llvm::{ValueRef, TypeRef, BasicBlockRef, BuilderRef, ModuleRef};
77
import lib::llvm::{Opcode, IntPredicate, RealPredicate, True, False,
8-
CallConv, TypeKind};
8+
CallConv, TypeKind, AtomicBinOp, AtomicOrdering};
99
import common::*;
1010
import driver::session::session;
1111

@@ -807,6 +807,13 @@ fn Resume(cx: block, Exn: ValueRef) -> ValueRef {
807807
ret llvm::LLVMBuildResume(B(cx), Exn);
808808
}
809809

810+
// Atomic Operations
811+
fn AtomicRMW(cx: block, op: AtomicBinOp,
812+
dst: ValueRef, src: ValueRef,
813+
order: AtomicOrdering) -> ValueRef {
814+
llvm::LLVMBuildAtomicRMW(B(cx), op, dst, src, order)
815+
}
816+
810817
//
811818
// Local Variables:
812819
// mode: rust

src/rustc/middle/trans/foreign.rs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import libc::c_uint;
77
import syntax::{attr, ast_map};
88
import lib::llvm::{ llvm, TypeRef, ValueRef,
99
ModuleRef, CallConv, Attribute,
10-
StructRetAttribute, ByValAttribute
10+
StructRetAttribute, ByValAttribute,
11+
SequentiallyConsistent, Acquire, Release,
12+
Xchg, Add, Sub
1113
};
1214
import syntax::{ast, ast_util};
1315
import back::{link, abi};
@@ -806,6 +808,69 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
806808
some(substs), some(item.span));
807809
let mut bcx = top_scope_block(fcx, none), lltop = bcx.llbb;
808810
alt check *item.ident {
811+
"atomic_xchng" {
812+
let old = AtomicRMW(bcx, Xchg,
813+
get_param(decl, first_real_arg),
814+
get_param(decl, first_real_arg + 1u),
815+
SequentiallyConsistent);
816+
Store(bcx, old, fcx.llretptr);
817+
}
818+
"atomic_xchng_acq" {
819+
let old = AtomicRMW(bcx, Xchg,
820+
get_param(decl, first_real_arg),
821+
get_param(decl, first_real_arg + 1u),
822+
Acquire);
823+
Store(bcx, old, fcx.llretptr);
824+
}
825+
"atomic_xchng_rel" {
826+
let old = AtomicRMW(bcx, Xchg,
827+
get_param(decl, first_real_arg),
828+
get_param(decl, first_real_arg + 1u),
829+
Release);
830+
Store(bcx, old, fcx.llretptr);
831+
}
832+
"atomic_add" {
833+
let old = AtomicRMW(bcx, Add,
834+
get_param(decl, first_real_arg),
835+
get_param(decl, first_real_arg + 1u),
836+
SequentiallyConsistent);
837+
Store(bcx, old, fcx.llretptr);
838+
}
839+
"atomic_add_acq" {
840+
let old = AtomicRMW(bcx, Add,
841+
get_param(decl, first_real_arg),
842+
get_param(decl, first_real_arg + 1u),
843+
Acquire);
844+
Store(bcx, old, fcx.llretptr);
845+
}
846+
"atomic_add_rel" {
847+
let old = AtomicRMW(bcx, Add,
848+
get_param(decl, first_real_arg),
849+
get_param(decl, first_real_arg + 1u),
850+
Release);
851+
Store(bcx, old, fcx.llretptr);
852+
}
853+
"atomic_sub" {
854+
let old = AtomicRMW(bcx, Sub,
855+
get_param(decl, first_real_arg),
856+
get_param(decl, first_real_arg + 1u),
857+
SequentiallyConsistent);
858+
Store(bcx, old, fcx.llretptr);
859+
}
860+
"atomic_sub_acq" {
861+
let old = AtomicRMW(bcx, Sub,
862+
get_param(decl, first_real_arg),
863+
get_param(decl, first_real_arg + 1u),
864+
Acquire);
865+
Store(bcx, old, fcx.llretptr);
866+
}
867+
"atomic_sub_rel" {
868+
let old = AtomicRMW(bcx, Sub,
869+
get_param(decl, first_real_arg),
870+
get_param(decl, first_real_arg + 1u),
871+
Release);
872+
Store(bcx, old, fcx.llretptr);
873+
}
809874
"size_of" {
810875
let tp_ty = substs.tys[0];
811876
let lltp_ty = type_of::type_of(ccx, tp_ty);

src/rustc/middle/trans/type_use.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,17 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
7676
abi, _) {
7777
if abi == foreign_abi_rust_intrinsic {
7878
let flags = alt check *i.ident {
79-
"visit_ty" { 3u }
79+
"visit_ty" { use_repr | use_tydesc }
8080
"size_of" | "pref_align_of" | "min_align_of" |
8181
"init" | "reinterpret_cast" | "move_val" | "move_val_init" {
8282
use_repr
8383
}
8484
"get_tydesc" | "needs_drop" { use_tydesc }
85+
"atomic_xchng" | "atomic_add" | "atomic_sub" |
86+
"atomic_xchng_acq" | "atomic_add_acq" | "atomic_sub_acq" |
87+
"atomic_xchng_rel" | "atomic_add_rel" | "atomic_sub_rel" {
88+
0u
89+
}
8590
"forget" | "addr_of" { 0u }
8691
};
8792
for uint::range(0u, n_tps) {|n| cx.uses[n] |= flags;}

src/rustc/middle/typeck/check.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2236,6 +2236,14 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
22362236
}
22372237
"needs_drop" { (1u, ~[], ty::mk_bool(tcx)) }
22382238

2239+
"atomic_xchng" | "atomic_add" | "atomic_sub" |
2240+
"atomic_xchng_acq" | "atomic_add_acq" | "atomic_sub_acq" |
2241+
"atomic_xchng_rel" | "atomic_add_rel" | "atomic_sub_rel" {
2242+
(0u, ~[arg(ast::by_mutbl_ref, ty::mk_int(tcx)),
2243+
arg(ast::by_val, ty::mk_int(tcx))],
2244+
ty::mk_int(tcx))
2245+
}
2246+
22392247
"visit_ty" {
22402248
assert ccx.tcx.intrinsic_ifaces.contains_key(@"ty_visitor");
22412249
let (_, visitor_iface) = ccx.tcx.intrinsic_ifaces.get(@"ty_visitor");

src/rustllvm/RustWrapper.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,13 @@ extern "C" LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) {
172172
extern "C" LLVMTypeRef LLVMMetadataType(void) {
173173
return LLVMMetadataTypeInContext(LLVMGetGlobalContext());
174174
}
175+
176+
extern "C" LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,
177+
AtomicRMWInst::BinOp op,
178+
LLVMValueRef target,
179+
LLVMValueRef source,
180+
AtomicOrdering order) {
181+
return wrap(unwrap(B)->CreateAtomicRMW(op,
182+
unwrap(target), unwrap(source),
183+
order));
184+
}

src/rustllvm/rustllvm.def.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ LLVMArrayType
8282
LLVMBasicBlockAsValue
8383
LLVMBlockAddress
8484
LLVMBuildAShr
85+
LLVMBuildAtomicRMW
8586
LLVMBuildAdd
8687
LLVMBuildAggregateRet
8788
LLVMBuildAlloca
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#[abi = "rust-intrinsic"]
2+
native mod rusti {
3+
fn atomic_xchng(&dst: int, src: int) -> int;
4+
fn atomic_xchng_acq(&dst: int, src: int) -> int;
5+
fn atomic_xchng_rel(&dst: int, src: int) -> int;
6+
7+
fn atomic_add(&dst: int, src: int) -> int;
8+
fn atomic_add_acq(&dst: int, src: int) -> int;
9+
fn atomic_add_rel(&dst: int, src: int) -> int;
10+
11+
fn atomic_sub(&dst: int, src: int) -> int;
12+
fn atomic_sub_acq(&dst: int, src: int) -> int;
13+
fn atomic_sub_rel(&dst: int, src: int) -> int;
14+
}
15+
16+
fn main() {
17+
let mut x = 1;
18+
19+
assert rusti::atomic_xchng(x, 0) == 1;
20+
assert x == 0;
21+
22+
assert rusti::atomic_xchng_acq(x, 1) == 0;
23+
assert x == 1;
24+
25+
assert rusti::atomic_xchng_rel(x, 0) == 1;
26+
assert x == 0;
27+
28+
assert rusti::atomic_add(x, 1) == 0;
29+
assert rusti::atomic_add_acq(x, 1) == 1;
30+
assert rusti::atomic_add_rel(x, 1) == 2;
31+
assert x == 3;
32+
33+
assert rusti::atomic_sub(x, 1) == 3;
34+
assert rusti::atomic_sub_acq(x, 1) == 2;
35+
assert rusti::atomic_sub_rel(x, 1) == 1;
36+
assert x == 0;
37+
}

0 commit comments

Comments
 (0)