2012-03-22 15:44:20 -05:00
|
|
|
import std::map::{hashmap, str_hash};
|
2012-03-12 22:04:27 -05:00
|
|
|
import libc::{c_uint, c_int};
|
2011-08-24 07:54:55 -05:00
|
|
|
import lib::llvm::llvm;
|
2012-01-12 10:59:49 -06:00
|
|
|
import syntax::codemap;
|
|
|
|
import codemap::span;
|
2012-02-01 04:04:56 -06:00
|
|
|
import lib::llvm::{ValueRef, TypeRef, BasicBlockRef, BuilderRef, ModuleRef};
|
|
|
|
import lib::llvm::{Opcode, IntPredicate, RealPredicate, True, False,
|
2012-06-21 17:01:32 -05:00
|
|
|
CallConv, TypeKind, AtomicBinOp, AtomicOrdering};
|
2012-02-21 07:20:18 -06:00
|
|
|
import common::*;
|
2012-05-17 23:53:49 -05:00
|
|
|
import driver::session::session;
|
2011-08-24 07:54:55 -05:00
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn B(cx: block) -> BuilderRef {
|
2012-06-22 13:53:25 -05:00
|
|
|
let b = cx.fcx.ccx.builder.B;
|
2011-08-30 07:02:20 -05:00
|
|
|
llvm::LLVMPositionBuilderAtEnd(b, cx.llbb);
|
2012-08-01 19:30:05 -05:00
|
|
|
return b;
|
2011-08-30 07:02:20 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn count_insn(cx: block, category: ~str) {
|
2012-05-17 23:53:49 -05:00
|
|
|
if cx.ccx().sess.count_llvm_insns() {
|
2012-03-22 15:44:20 -05:00
|
|
|
|
|
|
|
let h = cx.ccx().stats.llvm_insns;
|
2012-04-26 18:02:01 -05:00
|
|
|
let v = cx.ccx().stats.llvm_insn_ctxt;
|
2012-03-22 15:44:20 -05:00
|
|
|
|
|
|
|
// Build version of path with cycles removed.
|
|
|
|
|
|
|
|
// Pass 1: scan table mapping str -> rightmost pos.
|
|
|
|
let mm = str_hash();
|
|
|
|
let len = vec::len(*v);
|
|
|
|
let mut i = 0u;
|
|
|
|
while i < len {
|
|
|
|
mm.insert(copy v[i], i);
|
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Pass 2: concat strings for each elt, skipping
|
|
|
|
// forwards over any cycles by advancing to rightmost
|
|
|
|
// occurrence of each element in path.
|
2012-07-14 00:57:48 -05:00
|
|
|
let mut s = ~".";
|
2012-03-22 15:44:20 -05:00
|
|
|
i = 0u;
|
|
|
|
while i < len {
|
|
|
|
let e = v[i];
|
|
|
|
i = mm.get(e);
|
2012-07-14 00:57:48 -05:00
|
|
|
s += ~"/";
|
2012-03-22 15:44:20 -05:00
|
|
|
s += e;
|
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
s += ~"/";
|
2012-03-22 15:44:20 -05:00
|
|
|
s += category;
|
|
|
|
|
2012-08-06 14:34:08 -05:00
|
|
|
let n = match h.find(s) {
|
2012-08-03 21:59:04 -05:00
|
|
|
some(n) => n,
|
|
|
|
_ => 0u
|
|
|
|
};
|
2012-03-22 15:44:20 -05:00
|
|
|
h.insert(s, n+1u);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-21 05:40:27 -05:00
|
|
|
// The difference between a block being unreachable and being terminated is
|
|
|
|
// somewhat obscure, and has to do with error checking. When a block is
|
|
|
|
// terminated, we're saying that trying to add any further statements in the
|
|
|
|
// block is an error. On the other hand, if something is unreachable, that
|
|
|
|
// means that the block was terminated in some way that we don't want to check
|
2012-08-01 19:30:05 -05:00
|
|
|
// for (fail/break/return statements, call to diverging functions, etc), and
|
2011-09-21 05:40:27 -05:00
|
|
|
// further instructions to the block should simply be ignored.
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn RetVoid(cx: block) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return; }
|
2011-09-02 17:34:58 -05:00
|
|
|
assert (!cx.terminated);
|
2011-08-24 07:54:55 -05:00
|
|
|
cx.terminated = true;
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"retvoid");
|
2011-12-18 22:32:38 -06:00
|
|
|
llvm::LLVMBuildRetVoid(B(cx));
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Ret(cx: block, V: ValueRef) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return; }
|
2011-09-02 17:34:58 -05:00
|
|
|
assert (!cx.terminated);
|
2011-08-24 07:54:55 -05:00
|
|
|
cx.terminated = true;
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"ret");
|
2011-12-18 22:32:38 -06:00
|
|
|
llvm::LLVMBuildRet(B(cx), V);
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
fn AggregateRet(cx: block, RetVals: ~[ValueRef]) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return; }
|
2011-09-02 17:34:58 -05:00
|
|
|
assert (!cx.terminated);
|
2011-08-24 07:54:55 -05:00
|
|
|
cx.terminated = true;
|
2011-10-07 14:05:38 -05:00
|
|
|
unsafe {
|
2012-02-28 22:43:39 -06:00
|
|
|
llvm::LLVMBuildAggregateRet(B(cx), vec::unsafe::to_ptr(RetVals),
|
2012-02-14 02:10:47 -06:00
|
|
|
RetVals.len() as c_uint);
|
2011-10-07 14:05:38 -05:00
|
|
|
}
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Br(cx: block, Dest: BasicBlockRef) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return; }
|
2011-09-02 17:34:58 -05:00
|
|
|
assert (!cx.terminated);
|
2011-08-24 07:54:55 -05:00
|
|
|
cx.terminated = true;
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"br");
|
2011-12-18 22:32:38 -06:00
|
|
|
llvm::LLVMBuildBr(B(cx), Dest);
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn CondBr(cx: block, If: ValueRef, Then: BasicBlockRef,
|
2011-09-21 05:40:27 -05:00
|
|
|
Else: BasicBlockRef) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return; }
|
2011-09-02 17:34:58 -05:00
|
|
|
assert (!cx.terminated);
|
2011-08-24 07:54:55 -05:00
|
|
|
cx.terminated = true;
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"condbr");
|
2011-12-18 22:32:38 -06:00
|
|
|
llvm::LLVMBuildCondBr(B(cx), If, Then, Else);
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Switch(cx: block, V: ValueRef, Else: BasicBlockRef, NumCases: uint)
|
2011-09-21 05:40:27 -05:00
|
|
|
-> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(V); }
|
2011-09-21 05:40:27 -05:00
|
|
|
assert !cx.terminated;
|
2011-08-24 07:54:55 -05:00
|
|
|
cx.terminated = true;
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildSwitch(B(cx), V, Else, NumCases as c_uint);
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2011-09-21 05:40:27 -05:00
|
|
|
fn AddCase(S: ValueRef, OnVal: ValueRef, Dest: BasicBlockRef) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if llvm::LLVMIsUndef(S) == lib::llvm::True { return; }
|
2011-09-21 05:40:27 -05:00
|
|
|
llvm::LLVMAddCase(S, OnVal, Dest);
|
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn IndirectBr(cx: block, Addr: ValueRef, NumDests: uint) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return; }
|
2011-09-02 17:34:58 -05:00
|
|
|
assert (!cx.terminated);
|
2011-08-24 07:54:55 -05:00
|
|
|
cx.terminated = true;
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"indirectbr");
|
2012-01-16 04:21:01 -06:00
|
|
|
llvm::LLVMBuildIndirectBr(B(cx), Addr, NumDests as c_uint);
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2011-09-21 10:46:11 -05:00
|
|
|
// This is a really awful way to get a zero-length c-string, but better (and a
|
2012-03-14 17:10:34 -05:00
|
|
|
// lot more efficient) than doing str::as_c_str("", ...) every time.
|
|
|
|
fn noname() -> *libc::c_char unsafe {
|
2011-09-21 10:46:11 -05:00
|
|
|
const cnull: uint = 0u;
|
2012-08-01 19:30:05 -05:00
|
|
|
return unsafe::reinterpret_cast(ptr::addr_of(cnull));
|
2011-09-21 10:46:11 -05:00
|
|
|
}
|
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
fn Invoke(cx: block, Fn: ValueRef, Args: ~[ValueRef],
|
2011-09-21 05:40:27 -05:00
|
|
|
Then: BasicBlockRef, Catch: BasicBlockRef) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return; }
|
2011-09-02 17:34:58 -05:00
|
|
|
assert (!cx.terminated);
|
2011-08-24 07:54:55 -05:00
|
|
|
cx.terminated = true;
|
2012-07-30 18:01:07 -05:00
|
|
|
debug!{"Invoke(%s with arguments (%s))",
|
2012-02-21 07:20:18 -06:00
|
|
|
val_str(cx.ccx().tn, Fn),
|
2012-06-30 18:19:07 -05:00
|
|
|
str::connect(vec::map(Args, |a| val_str(cx.ccx().tn, a)),
|
2012-07-30 18:01:07 -05:00
|
|
|
~", ")};
|
2011-10-07 14:05:38 -05:00
|
|
|
unsafe {
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"invoke");
|
2012-02-28 22:43:39 -06:00
|
|
|
llvm::LLVMBuildInvoke(B(cx), Fn, vec::unsafe::to_ptr(Args),
|
2012-02-14 02:10:47 -06:00
|
|
|
Args.len() as c_uint, Then, Catch,
|
2012-01-10 15:26:21 -06:00
|
|
|
noname());
|
2011-10-07 14:05:38 -05:00
|
|
|
}
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
fn FastInvoke(cx: block, Fn: ValueRef, Args: ~[ValueRef],
|
2011-09-21 05:40:27 -05:00
|
|
|
Then: BasicBlockRef, Catch: BasicBlockRef) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return; }
|
2011-09-07 13:46:53 -05:00
|
|
|
assert (!cx.terminated);
|
|
|
|
cx.terminated = true;
|
2011-10-07 14:05:38 -05:00
|
|
|
unsafe {
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"fastinvoke");
|
2012-02-28 22:43:39 -06:00
|
|
|
let v = llvm::LLVMBuildInvoke(B(cx), Fn, vec::unsafe::to_ptr(Args),
|
2012-02-14 02:10:47 -06:00
|
|
|
Args.len() as c_uint,
|
2012-01-16 04:21:01 -06:00
|
|
|
Then, Catch, noname());
|
2012-02-01 04:04:56 -06:00
|
|
|
lib::llvm::SetInstructionCallConv(v, lib::llvm::FastCallConv);
|
2011-10-07 14:05:38 -05:00
|
|
|
}
|
2011-09-07 13:46:53 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Unreachable(cx: block) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return; }
|
2011-09-21 05:40:27 -05:00
|
|
|
cx.unreachable = true;
|
2012-03-22 15:44:20 -05:00
|
|
|
if !cx.terminated {
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"unreachable");
|
2012-03-22 15:44:20 -05:00
|
|
|
llvm::LLVMBuildUnreachable(B(cx));
|
|
|
|
}
|
2011-09-21 05:40:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn _Undef(val: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMGetUndef(val_ty(val));
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Arithmetic */
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Add(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"add");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildAdd(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn NSWAdd(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"nswadd");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildNSWAdd(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn NUWAdd(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"nuwadd");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildNUWAdd(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn FAdd(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"fadd");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildFAdd(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Sub(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"sub");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildSub(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn NSWSub(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"nwsub");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildNSWSub(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn NUWSub(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"nuwsub");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildNUWSub(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn FSub(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"sub");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildFSub(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Mul(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"mul");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildMul(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn NSWMul(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"nswmul");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildNSWMul(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn NUWMul(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"nuwmul");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildNUWMul(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn FMul(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"fmul");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildFMul(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn UDiv(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"udiv");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildUDiv(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn SDiv(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"sdiv");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildSDiv(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn ExactSDiv(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"extractsdiv");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildExactSDiv(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn FDiv(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"fdiv");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildFDiv(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn URem(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"urem");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildURem(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn SRem(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"srem");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildSRem(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn FRem(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"frem");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildFRem(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Shl(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"shl");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildShl(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn LShr(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"lshr");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildLShr(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn AShr(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"ashr");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildAShr(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn And(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"and");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildAnd(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Or(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"or");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildOr(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Xor(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"xor");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildXor(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn BinOp(cx: block, Op: Opcode, LHS: ValueRef, RHS: ValueRef) ->
|
2011-09-02 17:34:58 -05:00
|
|
|
ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(LHS); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"binop");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildBinOp(B(cx), Op, LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Neg(cx: block, V: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(V); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"neg");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildNeg(B(cx), V, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn NSWNeg(cx: block, V: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(V); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"nswneg");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildNSWNeg(B(cx), V, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn NUWNeg(cx: block, V: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(V); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"nuwneg");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildNUWNeg(B(cx), V, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
2012-02-17 06:17:40 -06:00
|
|
|
fn FNeg(cx: block, V: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(V); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"fneg");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildFNeg(B(cx), V, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
2011-08-26 17:36:18 -05:00
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Not(cx: block, V: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(V); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"not");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildNot(B(cx), V, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Memory */
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Malloc(cx: block, Ty: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"malloc");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildMalloc(B(cx), Ty, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn ArrayMalloc(cx: block, Ty: TypeRef, Val: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"arraymalloc");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildArrayMalloc(B(cx), Ty, Val, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Alloca(cx: block, Ty: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(Ty)); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"alloca");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildAlloca(B(cx), Ty, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn ArrayAlloca(cx: block, Ty: TypeRef, Val: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(Ty)); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"arrayalloca");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildArrayAlloca(B(cx), Ty, Val, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Free(cx: block, PointerVal: ValueRef) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return; }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"free");
|
2011-12-18 22:32:38 -06:00
|
|
|
llvm::LLVMBuildFree(B(cx), PointerVal);
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Load(cx: block, PointerVal: ValueRef) -> ValueRef {
|
2012-02-03 02:53:37 -06:00
|
|
|
let ccx = cx.fcx.ccx;
|
2011-09-21 05:40:27 -05:00
|
|
|
if cx.unreachable {
|
|
|
|
let ty = val_ty(PointerVal);
|
2012-05-17 18:17:11 -05:00
|
|
|
let eltty = if llvm::LLVMGetTypeKind(ty) == lib::llvm::Array {
|
2011-10-14 19:00:17 -05:00
|
|
|
llvm::LLVMGetElementType(ty) } else { ccx.int_type };
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMGetUndef(eltty);
|
2011-09-21 05:40:27 -05:00
|
|
|
}
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"load");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildLoad(B(cx), PointerVal, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Store(cx: block, Val: ValueRef, Ptr: ValueRef) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return; }
|
2012-07-30 18:01:07 -05:00
|
|
|
debug!{"Store %s -> %s",
|
2012-02-14 17:21:53 -06:00
|
|
|
val_str(cx.ccx().tn, Val),
|
2012-07-30 18:01:07 -05:00
|
|
|
val_str(cx.ccx().tn, Ptr)};
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"store");
|
2011-12-18 22:32:38 -06:00
|
|
|
llvm::LLVMBuildStore(B(cx), Val, Ptr);
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
fn GEP(cx: block, Pointer: ValueRef, Indices: ~[ValueRef]) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_nil())); }
|
2011-10-07 14:05:38 -05:00
|
|
|
unsafe {
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"gep");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildGEP(B(cx), Pointer, vec::unsafe::to_ptr(Indices),
|
2012-02-14 02:10:47 -06:00
|
|
|
Indices.len() as c_uint, noname());
|
2011-10-07 14:05:38 -05:00
|
|
|
}
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2011-10-26 00:23:28 -05:00
|
|
|
// Simple wrapper around GEP that takes an array of ints and wraps them
|
|
|
|
// in C_i32()
|
2012-06-29 18:26:56 -05:00
|
|
|
fn GEPi(cx: block, base: ValueRef, ixs: ~[uint]) -> ValueRef {
|
|
|
|
let mut v: ~[ValueRef] = ~[];
|
2012-06-30 18:19:07 -05:00
|
|
|
for vec::each(ixs) |i| { vec::push(v, C_i32(i as i32)); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"gepi");
|
2012-08-01 19:30:05 -05:00
|
|
|
return InBoundsGEP(cx, base, v);
|
2011-10-26 00:23:28 -05:00
|
|
|
}
|
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
fn InBoundsGEP(cx: block, Pointer: ValueRef, Indices: ~[ValueRef]) ->
|
2011-09-02 17:34:58 -05:00
|
|
|
ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_nil())); }
|
2011-10-07 14:05:38 -05:00
|
|
|
unsafe {
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"inboundsgep");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildInBoundsGEP(B(cx), Pointer,
|
2012-02-28 22:43:39 -06:00
|
|
|
vec::unsafe::to_ptr(Indices),
|
2012-02-14 02:10:47 -06:00
|
|
|
Indices.len() as c_uint,
|
2012-01-16 04:21:01 -06:00
|
|
|
noname());
|
2011-10-07 14:05:38 -05:00
|
|
|
}
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn StructGEP(cx: block, Pointer: ValueRef, Idx: uint) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_nil())); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"structgep");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildStructGEP(B(cx), Pointer, Idx as c_uint, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-03-14 17:10:34 -05:00
|
|
|
fn GlobalString(cx: block, _Str: *libc::c_char) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"globalstring");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildGlobalString(B(cx), _Str, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-03-14 17:10:34 -05:00
|
|
|
fn GlobalStringPtr(cx: block, _Str: *libc::c_char) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"globalstringptr");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildGlobalStringPtr(B(cx), _Str, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Casts */
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Trunc(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"trunc");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildTrunc(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn ZExt(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"zext");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildZExt(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn SExt(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"sext");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildSExt(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn FPToUI(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"fptoui");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildFPToUI(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn FPToSI(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"fptosi");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildFPToSI(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn UIToFP(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"uitofp");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildUIToFP(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn SIToFP(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"sitofp");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildSIToFP(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn FPTrunc(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"fptrunc");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildFPTrunc(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn FPExt(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"fpext");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildFPExt(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn PtrToInt(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"ptrtoint");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildPtrToInt(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn IntToPtr(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"inttoptr");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildIntToPtr(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn BitCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"bitcast");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildBitCast(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn ZExtOrBitCast(cx: block, Val: ValueRef, DestTy: TypeRef) ->
|
2011-09-02 17:34:58 -05:00
|
|
|
ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"zextorbitcast");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildZExtOrBitCast(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn SExtOrBitCast(cx: block, Val: ValueRef, DestTy: TypeRef) ->
|
2011-09-02 17:34:58 -05:00
|
|
|
ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"sextorbitcast");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildSExtOrBitCast(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn TruncOrBitCast(cx: block, Val: ValueRef, DestTy: TypeRef) ->
|
2011-09-02 17:34:58 -05:00
|
|
|
ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"truncorbitcast");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildTruncOrBitCast(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Cast(cx: block, Op: Opcode, Val: ValueRef, DestTy: TypeRef,
|
2012-03-14 15:56:00 -05:00
|
|
|
_Name: *u8) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"cast");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildCast(B(cx), Op, Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn PointerCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"pointercast");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildPointerCast(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn IntCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"intcast");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildIntCast(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn FPCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"fpcast");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildFPCast(B(cx), Val, DestTy, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Comparisons */
|
2012-02-17 06:17:40 -06:00
|
|
|
fn ICmp(cx: block, Op: IntPredicate, LHS: ValueRef, RHS: ValueRef)
|
2012-02-01 04:04:56 -06:00
|
|
|
-> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(T_i1()); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"icmp");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildICmp(B(cx), Op as c_uint, LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn FCmp(cx: block, Op: RealPredicate, LHS: ValueRef, RHS: ValueRef)
|
2012-02-01 04:04:56 -06:00
|
|
|
-> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(T_i1()); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"fcmp");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildFCmp(B(cx), Op as c_uint, LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Miscellaneous instructions */
|
2012-02-17 06:17:40 -06:00
|
|
|
fn EmptyPhi(cx: block, Ty: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(Ty); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"emptyphi");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildPhi(B(cx), Ty, noname());
|
2011-09-23 14:13:50 -05:00
|
|
|
}
|
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
fn Phi(cx: block, Ty: TypeRef, vals: ~[ValueRef], bbs: ~[BasicBlockRef])
|
2011-09-12 04:27:30 -05:00
|
|
|
-> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(Ty); }
|
2012-02-14 02:10:47 -06:00
|
|
|
assert vals.len() == bbs.len();
|
2011-09-23 14:13:50 -05:00
|
|
|
let phi = EmptyPhi(cx, Ty);
|
2011-10-07 14:05:38 -05:00
|
|
|
unsafe {
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"addincoming");
|
2012-02-28 22:43:39 -06:00
|
|
|
llvm::LLVMAddIncoming(phi, vec::unsafe::to_ptr(vals),
|
|
|
|
vec::unsafe::to_ptr(bbs),
|
2012-02-14 02:10:47 -06:00
|
|
|
vals.len() as c_uint);
|
2012-08-01 19:30:05 -05:00
|
|
|
return phi;
|
2011-10-07 14:05:38 -05:00
|
|
|
}
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2011-09-23 16:20:19 -05:00
|
|
|
fn AddIncomingToPhi(phi: ValueRef, val: ValueRef, bb: BasicBlockRef) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if llvm::LLVMIsUndef(phi) == lib::llvm::True { return; }
|
2011-10-28 16:19:17 -05:00
|
|
|
unsafe {
|
2011-12-13 18:25:51 -06:00
|
|
|
let valptr = unsafe::reinterpret_cast(ptr::addr_of(val));
|
|
|
|
let bbptr = unsafe::reinterpret_cast(ptr::addr_of(bb));
|
2012-01-18 05:29:37 -06:00
|
|
|
llvm::LLVMAddIncoming(phi, valptr, bbptr, 1 as c_uint);
|
2011-10-28 16:19:17 -05:00
|
|
|
}
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn _UndefReturn(cx: block, Fn: ValueRef) -> ValueRef {
|
2012-02-03 02:53:37 -06:00
|
|
|
let ccx = cx.fcx.ccx;
|
2011-09-21 05:40:27 -05:00
|
|
|
let ty = val_ty(Fn);
|
2012-05-17 18:17:11 -05:00
|
|
|
let retty = if llvm::LLVMGetTypeKind(ty) == lib::llvm::Integer {
|
2011-10-14 19:00:17 -05:00
|
|
|
llvm::LLVMGetReturnType(ty) } else { ccx.int_type };
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMGetUndef(retty);
|
2011-09-21 05:40:27 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn add_span_comment(bcx: block, sp: span, text: ~str) {
|
2012-02-21 07:20:18 -06:00
|
|
|
let ccx = bcx.ccx();
|
2012-05-17 23:53:49 -05:00
|
|
|
if !ccx.sess.no_asm_comments() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let s = text + ~" (" + codemap::span_to_str(sp, ccx.sess.codemap)
|
|
|
|
+ ~")";
|
2011-12-22 19:53:53 -06:00
|
|
|
log(debug, s);
|
2011-12-18 22:32:38 -06:00
|
|
|
add_comment(bcx, s);
|
2011-11-14 16:03:20 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn add_comment(bcx: block, text: ~str) {
|
2012-02-21 07:20:18 -06:00
|
|
|
let ccx = bcx.ccx();
|
2012-05-17 23:53:49 -05:00
|
|
|
if !ccx.sess.no_asm_comments() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let sanitized = str::replace(text, ~"$", ~"");
|
2012-07-23 16:18:12 -05:00
|
|
|
let comment_text = ~"# " + str::replace(sanitized, ~"\n", ~"\n\t# ");
|
2012-06-30 18:19:07 -05:00
|
|
|
let asm = str::as_c_str(comment_text, |c| {
|
2012-07-14 00:57:48 -05:00
|
|
|
str::as_c_str(~"", |e| {
|
|
|
|
count_insn(bcx, ~"inlineasm");
|
2012-06-29 18:26:56 -05:00
|
|
|
llvm::LLVMConstInlineAsm(T_fn(~[], T_void()), c, e,
|
2012-02-01 04:04:56 -06:00
|
|
|
False, False)
|
|
|
|
})
|
|
|
|
});
|
2012-06-29 18:26:56 -05:00
|
|
|
Call(bcx, asm, ~[]);
|
2011-11-14 16:03:20 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
fn Call(cx: block, Fn: ValueRef, Args: ~[ValueRef]) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _UndefReturn(cx, Fn); }
|
2011-10-07 14:05:38 -05:00
|
|
|
unsafe {
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"call");
|
2012-05-18 21:02:39 -05:00
|
|
|
|
2012-07-30 18:01:07 -05:00
|
|
|
debug!{"Call(Fn=%s, Args=%?)",
|
2012-05-18 21:02:39 -05:00
|
|
|
val_str(cx.ccx().tn, Fn),
|
2012-07-30 18:01:07 -05:00
|
|
|
Args.map(|arg| val_str(cx.ccx().tn, arg))};
|
2012-05-18 21:02:39 -05:00
|
|
|
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildCall(B(cx), Fn, vec::unsafe::to_ptr(Args),
|
2012-02-14 02:10:47 -06:00
|
|
|
Args.len() as c_uint, noname());
|
2011-10-07 14:05:38 -05:00
|
|
|
}
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
fn FastCall(cx: block, Fn: ValueRef, Args: ~[ValueRef]) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _UndefReturn(cx, Fn); }
|
2011-10-07 14:05:38 -05:00
|
|
|
unsafe {
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"fastcall");
|
2012-02-28 22:43:39 -06:00
|
|
|
let v = llvm::LLVMBuildCall(B(cx), Fn, vec::unsafe::to_ptr(Args),
|
2012-02-14 02:10:47 -06:00
|
|
|
Args.len() as c_uint, noname());
|
2012-02-01 04:04:56 -06:00
|
|
|
lib::llvm::SetInstructionCallConv(v, lib::llvm::FastCallConv);
|
2012-08-01 19:30:05 -05:00
|
|
|
return v;
|
2011-10-07 14:05:38 -05:00
|
|
|
}
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
fn CallWithConv(cx: block, Fn: ValueRef, Args: ~[ValueRef],
|
2012-02-01 04:04:56 -06:00
|
|
|
Conv: CallConv) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _UndefReturn(cx, Fn); }
|
2011-10-07 14:05:38 -05:00
|
|
|
unsafe {
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"callwithconv");
|
2012-02-28 22:43:39 -06:00
|
|
|
let v = llvm::LLVMBuildCall(B(cx), Fn, vec::unsafe::to_ptr(Args),
|
2012-02-14 02:10:47 -06:00
|
|
|
Args.len() as c_uint, noname());
|
2012-02-01 04:04:56 -06:00
|
|
|
lib::llvm::SetInstructionCallConv(v, Conv);
|
2012-08-01 19:30:05 -05:00
|
|
|
return v;
|
2011-10-07 14:05:38 -05:00
|
|
|
}
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Select(cx: block, If: ValueRef, Then: ValueRef, Else: ValueRef) ->
|
2011-09-02 17:34:58 -05:00
|
|
|
ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return _Undef(Then); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"select");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildSelect(B(cx), If, Then, Else, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn VAArg(cx: block, list: ValueRef, Ty: TypeRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(Ty); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"vaarg");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildVAArg(B(cx), list, Ty, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn ExtractElement(cx: block, VecVal: ValueRef, Index: ValueRef) ->
|
2011-09-02 17:34:58 -05:00
|
|
|
ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(T_nil()); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"extractelement");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildExtractElement(B(cx), VecVal, Index, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn InsertElement(cx: block, VecVal: ValueRef, EltVal: ValueRef,
|
2011-09-21 05:40:27 -05:00
|
|
|
Index: ValueRef) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return; }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"insertelement");
|
2011-12-18 22:32:38 -06:00
|
|
|
llvm::LLVMBuildInsertElement(B(cx), VecVal, EltVal, Index, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn ShuffleVector(cx: block, V1: ValueRef, V2: ValueRef,
|
2011-09-21 05:40:27 -05:00
|
|
|
Mask: ValueRef) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return; }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"shufflevector");
|
2011-12-18 22:32:38 -06:00
|
|
|
llvm::LLVMBuildShuffleVector(B(cx), V1, V2, Mask, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn ExtractValue(cx: block, AggVal: ValueRef, Index: uint) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(T_nil()); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"extractvalue");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildExtractValue(
|
|
|
|
B(cx), AggVal, Index as c_uint, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn InsertValue(cx: block, AggVal: ValueRef, EltVal: ValueRef,
|
2011-09-21 05:40:27 -05:00
|
|
|
Index: uint) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return; }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"insertvalue");
|
2012-01-16 04:21:01 -06:00
|
|
|
llvm::LLVMBuildInsertValue(B(cx), AggVal, EltVal, Index as c_uint,
|
|
|
|
noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn IsNull(cx: block, Val: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(T_i1()); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"isnull");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildIsNull(B(cx), Val, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn IsNotNull(cx: block, Val: ValueRef) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(T_i1()); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"isnotnull");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildIsNotNull(B(cx), Val, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn PtrDiff(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
2012-02-03 02:53:37 -06:00
|
|
|
let ccx = cx.fcx.ccx;
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return llvm::LLVMGetUndef(ccx.int_type); }
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"ptrdiff");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildPtrDiff(B(cx), LHS, RHS, noname());
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Trap(cx: block) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if cx.unreachable { return; }
|
2011-08-30 07:02:20 -05:00
|
|
|
let b = B(cx);
|
|
|
|
let BB: BasicBlockRef = llvm::LLVMGetInsertBlock(b);
|
2011-08-24 07:54:55 -05:00
|
|
|
let FN: ValueRef = llvm::LLVMGetBasicBlockParent(BB);
|
|
|
|
let M: ModuleRef = llvm::LLVMGetGlobalParent(FN);
|
2012-07-14 00:57:48 -05:00
|
|
|
let T: ValueRef = str::as_c_str(~"llvm.trap", |buf| {
|
2011-09-21 10:46:11 -05:00
|
|
|
llvm::LLVMGetNamedFunction(M, buf)
|
|
|
|
});
|
2011-08-24 07:54:55 -05:00
|
|
|
assert (T as int != 0);
|
2012-06-29 18:26:56 -05:00
|
|
|
let Args: ~[ValueRef] = ~[];
|
2011-10-07 14:05:38 -05:00
|
|
|
unsafe {
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"trap");
|
2012-02-28 22:43:39 -06:00
|
|
|
llvm::LLVMBuildCall(b, T, vec::unsafe::to_ptr(Args),
|
2012-02-14 02:10:47 -06:00
|
|
|
Args.len() as c_uint, noname());
|
2011-10-07 14:05:38 -05:00
|
|
|
}
|
2011-08-24 07:54:55 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn LandingPad(cx: block, Ty: TypeRef, PersFn: ValueRef,
|
2011-09-07 13:58:49 -05:00
|
|
|
NumClauses: uint) -> ValueRef {
|
2011-09-21 05:40:27 -05:00
|
|
|
assert !cx.terminated && !cx.unreachable;
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"landingpad");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildLandingPad(B(cx), Ty, PersFn,
|
2012-01-16 04:21:01 -06:00
|
|
|
NumClauses as c_uint, noname());
|
2011-09-07 13:58:49 -05:00
|
|
|
}
|
|
|
|
|
2012-03-22 15:44:20 -05:00
|
|
|
fn SetCleanup(cx: block, LandingPad: ValueRef) {
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"setcleanup");
|
2011-09-07 13:58:49 -05:00
|
|
|
llvm::LLVMSetCleanup(LandingPad, lib::llvm::True);
|
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn Resume(cx: block, Exn: ValueRef) -> ValueRef {
|
2011-09-07 16:28:02 -05:00
|
|
|
assert (!cx.terminated);
|
|
|
|
cx.terminated = true;
|
2012-07-14 00:57:48 -05:00
|
|
|
count_insn(cx, ~"resume");
|
2012-08-01 19:30:05 -05:00
|
|
|
return llvm::LLVMBuildResume(B(cx), Exn);
|
2011-09-07 16:28:02 -05:00
|
|
|
}
|
|
|
|
|
2012-06-21 17:01:32 -05:00
|
|
|
// Atomic Operations
|
|
|
|
fn AtomicRMW(cx: block, op: AtomicBinOp,
|
|
|
|
dst: ValueRef, src: ValueRef,
|
|
|
|
order: AtomicOrdering) -> ValueRef {
|
|
|
|
llvm::LLVMBuildAtomicRMW(B(cx), op, dst, src, order)
|
|
|
|
}
|
|
|
|
|
2011-08-24 07:54:55 -05:00
|
|
|
//
|
|
|
|
// Local Variables:
|
|
|
|
// mode: rust
|
|
|
|
// fill-column: 78;
|
|
|
|
// indent-tabs-mode: nil
|
|
|
|
// c-basic-offset: 4
|
|
|
|
// buffer-file-coding-system: utf-8-unix
|
|
|
|
// End:
|
|
|
|
//
|