Adding a bunch of atomic intrinsics.
Adding a test cases for the atomic intrinsics.
This commit is contained in:
parent
3b5d76d1e3
commit
0a99912cdd
src
rustc
rustllvm
test/run-pass
@ -128,6 +128,31 @@ enum TypeKind {
|
||||
X86_MMX = 15
|
||||
}
|
||||
|
||||
enum AtomicBinOp {
|
||||
Xchg = 0,
|
||||
Add = 1,
|
||||
Sub = 2,
|
||||
And = 3,
|
||||
Nand = 4,
|
||||
Or = 5,
|
||||
Xor = 6,
|
||||
Max = 7,
|
||||
Min = 8,
|
||||
UMax = 9,
|
||||
UMin = 10,
|
||||
}
|
||||
|
||||
enum AtomicOrdering {
|
||||
NotAtomic = 0,
|
||||
Unordered = 1,
|
||||
Monotonic = 2,
|
||||
// Consume = 3, // Not specified yet.
|
||||
Acquire = 4,
|
||||
Release = 5,
|
||||
AcquireRelease = 6,
|
||||
SequentiallyConsistent = 7
|
||||
}
|
||||
|
||||
// FIXME: Not used right now, but will be once #2334 is fixed
|
||||
// Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h)
|
||||
enum FileType {
|
||||
@ -772,6 +797,11 @@ native mod llvm {
|
||||
fn LLVMBuildPtrDiff(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
|
||||
Name: *c_char) -> ValueRef;
|
||||
|
||||
/* Atomic Operations */
|
||||
fn LLVMBuildAtomicRMW(B: BuilderRef, ++Op: AtomicBinOp,
|
||||
LHS: ValueRef, RHS: ValueRef,
|
||||
++Order: AtomicOrdering) -> ValueRef;
|
||||
|
||||
/* Selected entries from the downcasts. */
|
||||
fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;
|
||||
|
||||
|
@ -5,7 +5,7 @@ import syntax::codemap;
|
||||
import codemap::span;
|
||||
import lib::llvm::{ValueRef, TypeRef, BasicBlockRef, BuilderRef, ModuleRef};
|
||||
import lib::llvm::{Opcode, IntPredicate, RealPredicate, True, False,
|
||||
CallConv, TypeKind};
|
||||
CallConv, TypeKind, AtomicBinOp, AtomicOrdering};
|
||||
import common::*;
|
||||
import driver::session::session;
|
||||
|
||||
@ -807,6 +807,13 @@ fn Resume(cx: block, Exn: ValueRef) -> ValueRef {
|
||||
ret llvm::LLVMBuildResume(B(cx), Exn);
|
||||
}
|
||||
|
||||
// Atomic Operations
|
||||
fn AtomicRMW(cx: block, op: AtomicBinOp,
|
||||
dst: ValueRef, src: ValueRef,
|
||||
order: AtomicOrdering) -> ValueRef {
|
||||
llvm::LLVMBuildAtomicRMW(B(cx), op, dst, src, order)
|
||||
}
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
// mode: rust
|
||||
|
@ -7,7 +7,9 @@ import libc::c_uint;
|
||||
import syntax::{attr, ast_map};
|
||||
import lib::llvm::{ llvm, TypeRef, ValueRef,
|
||||
ModuleRef, CallConv, Attribute,
|
||||
StructRetAttribute, ByValAttribute
|
||||
StructRetAttribute, ByValAttribute,
|
||||
SequentiallyConsistent, Acquire, Release,
|
||||
Xchg, Add, Sub
|
||||
};
|
||||
import syntax::{ast, ast_util};
|
||||
import back::{link, abi};
|
||||
@ -806,6 +808,69 @@ 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;
|
||||
alt check *item.ident {
|
||||
"atomic_xchng" {
|
||||
let old = AtomicRMW(bcx, Xchg,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
SequentiallyConsistent);
|
||||
Store(bcx, old, fcx.llretptr);
|
||||
}
|
||||
"atomic_xchng_acq" {
|
||||
let old = AtomicRMW(bcx, Xchg,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
Acquire);
|
||||
Store(bcx, old, fcx.llretptr);
|
||||
}
|
||||
"atomic_xchng_rel" {
|
||||
let old = AtomicRMW(bcx, Xchg,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
Release);
|
||||
Store(bcx, old, fcx.llretptr);
|
||||
}
|
||||
"atomic_add" {
|
||||
let old = AtomicRMW(bcx, Add,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
SequentiallyConsistent);
|
||||
Store(bcx, old, fcx.llretptr);
|
||||
}
|
||||
"atomic_add_acq" {
|
||||
let old = AtomicRMW(bcx, Add,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
Acquire);
|
||||
Store(bcx, old, fcx.llretptr);
|
||||
}
|
||||
"atomic_add_rel" {
|
||||
let old = AtomicRMW(bcx, Add,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
Release);
|
||||
Store(bcx, old, fcx.llretptr);
|
||||
}
|
||||
"atomic_sub" {
|
||||
let old = AtomicRMW(bcx, Sub,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
SequentiallyConsistent);
|
||||
Store(bcx, old, fcx.llretptr);
|
||||
}
|
||||
"atomic_sub_acq" {
|
||||
let old = AtomicRMW(bcx, Sub,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
Acquire);
|
||||
Store(bcx, old, fcx.llretptr);
|
||||
}
|
||||
"atomic_sub_rel" {
|
||||
let old = AtomicRMW(bcx, Sub,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
Release);
|
||||
Store(bcx, old, fcx.llretptr);
|
||||
}
|
||||
"size_of" {
|
||||
let tp_ty = substs.tys[0];
|
||||
let lltp_ty = type_of::type_of(ccx, tp_ty);
|
||||
|
@ -76,12 +76,17 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
|
||||
abi, _) {
|
||||
if abi == foreign_abi_rust_intrinsic {
|
||||
let flags = alt check *i.ident {
|
||||
"visit_ty" { 3u }
|
||||
"visit_ty" { use_repr | use_tydesc }
|
||||
"size_of" | "pref_align_of" | "min_align_of" |
|
||||
"init" | "reinterpret_cast" | "move_val" | "move_val_init" {
|
||||
use_repr
|
||||
}
|
||||
"get_tydesc" | "needs_drop" { use_tydesc }
|
||||
"atomic_xchng" | "atomic_add" | "atomic_sub" |
|
||||
"atomic_xchng_acq" | "atomic_add_acq" | "atomic_sub_acq" |
|
||||
"atomic_xchng_rel" | "atomic_add_rel" | "atomic_sub_rel" {
|
||||
0u
|
||||
}
|
||||
"forget" | "addr_of" { 0u }
|
||||
};
|
||||
for uint::range(0u, n_tps) {|n| cx.uses[n] |= flags;}
|
||||
|
@ -2236,6 +2236,14 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
|
||||
}
|
||||
"needs_drop" { (1u, ~[], ty::mk_bool(tcx)) }
|
||||
|
||||
"atomic_xchng" | "atomic_add" | "atomic_sub" |
|
||||
"atomic_xchng_acq" | "atomic_add_acq" | "atomic_sub_acq" |
|
||||
"atomic_xchng_rel" | "atomic_add_rel" | "atomic_sub_rel" {
|
||||
(0u, ~[arg(ast::by_mutbl_ref, ty::mk_int(tcx)),
|
||||
arg(ast::by_val, ty::mk_int(tcx))],
|
||||
ty::mk_int(tcx))
|
||||
}
|
||||
|
||||
"visit_ty" {
|
||||
assert ccx.tcx.intrinsic_ifaces.contains_key(@"ty_visitor");
|
||||
let (_, visitor_iface) = ccx.tcx.intrinsic_ifaces.get(@"ty_visitor");
|
||||
|
@ -172,3 +172,13 @@ extern "C" LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) {
|
||||
extern "C" LLVMTypeRef LLVMMetadataType(void) {
|
||||
return LLVMMetadataTypeInContext(LLVMGetGlobalContext());
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,
|
||||
AtomicRMWInst::BinOp op,
|
||||
LLVMValueRef target,
|
||||
LLVMValueRef source,
|
||||
AtomicOrdering order) {
|
||||
return wrap(unwrap(B)->CreateAtomicRMW(op,
|
||||
unwrap(target), unwrap(source),
|
||||
order));
|
||||
}
|
||||
|
@ -82,6 +82,7 @@ LLVMArrayType
|
||||
LLVMBasicBlockAsValue
|
||||
LLVMBlockAddress
|
||||
LLVMBuildAShr
|
||||
LLVMBuildAtomicRMW
|
||||
LLVMBuildAdd
|
||||
LLVMBuildAggregateRet
|
||||
LLVMBuildAlloca
|
||||
|
37
src/test/run-pass/intrinsic-atomics.rs
Normal file
37
src/test/run-pass/intrinsic-atomics.rs
Normal file
@ -0,0 +1,37 @@
|
||||
#[abi = "rust-intrinsic"]
|
||||
native mod rusti {
|
||||
fn atomic_xchng(&dst: int, src: int) -> int;
|
||||
fn atomic_xchng_acq(&dst: int, src: int) -> int;
|
||||
fn atomic_xchng_rel(&dst: int, src: int) -> int;
|
||||
|
||||
fn atomic_add(&dst: int, src: int) -> int;
|
||||
fn atomic_add_acq(&dst: int, src: int) -> int;
|
||||
fn atomic_add_rel(&dst: int, src: int) -> int;
|
||||
|
||||
fn atomic_sub(&dst: int, src: int) -> int;
|
||||
fn atomic_sub_acq(&dst: int, src: int) -> int;
|
||||
fn atomic_sub_rel(&dst: int, src: int) -> int;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut x = 1;
|
||||
|
||||
assert rusti::atomic_xchng(x, 0) == 1;
|
||||
assert x == 0;
|
||||
|
||||
assert rusti::atomic_xchng_acq(x, 1) == 0;
|
||||
assert x == 1;
|
||||
|
||||
assert rusti::atomic_xchng_rel(x, 0) == 1;
|
||||
assert x == 0;
|
||||
|
||||
assert rusti::atomic_add(x, 1) == 0;
|
||||
assert rusti::atomic_add_acq(x, 1) == 1;
|
||||
assert rusti::atomic_add_rel(x, 1) == 2;
|
||||
assert x == 3;
|
||||
|
||||
assert rusti::atomic_sub(x, 1) == 3;
|
||||
assert rusti::atomic_sub_acq(x, 1) == 2;
|
||||
assert rusti::atomic_sub_rel(x, 1) == 1;
|
||||
assert x == 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user