Adding a bunch of atomic intrinsics.

Adding a test cases for the atomic intrinsics.
This commit is contained in:
Eric Holk 2012-06-21 15:01:32 -07:00
parent 3b5d76d1e3
commit 0a99912cdd
8 changed files with 166 additions and 3 deletions

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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;}

View file

@ -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");

View file

@ -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));
}

View file

@ -82,6 +82,7 @@ LLVMArrayType
LLVMBasicBlockAsValue
LLVMBlockAddress
LLVMBuildAShr
LLVMBuildAtomicRMW
LLVMBuildAdd
LLVMBuildAggregateRet
LLVMBuildAlloca

View 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;
}