1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 use lib::llvm::{CallConv, AtomicBinOp, AtomicOrdering, AsmDialect};
14 use lib::llvm::{Opcode, IntPredicate, RealPredicate, False};
15 use lib::llvm::{ValueRef, BasicBlockRef, BuilderRef, ModuleRef};
16 use middle::trans::base;
17 use middle::trans::common::*;
18 use middle::trans::machine::llalign_of_min;
19 use middle::trans::type_::Type;
21 use std::hashmap::HashMap;
22 use std::libc::{c_uint, c_ulonglong, c_char};
24 use syntax::codemap::span;
27 llbuilder: BuilderRef,
28 ccx: @mut CrateContext,
31 // This is a really awful way to get a zero-length c-string, but better (and a
32 // lot more efficient) than doing str::as_c_str("", ...) every time.
33 pub fn noname() -> *c_char {
35 static cnull: uint = 0u;
36 cast::transmute(&cnull)
41 pub fn new(ccx: @mut CrateContext) -> Builder {
43 llbuilder: ccx.builder.B,
48 pub fn count_insn(&self, category: &str) {
49 if self.ccx.sess.trans_stats() {
50 self.ccx.stats.n_llvm_insns += 1;
52 if self.ccx.sess.count_llvm_insns() {
53 do base::with_insn_ctxt |v| {
54 let h = &mut self.ccx.stats.llvm_insns;
56 // Build version of path with cycles removed.
58 // Pass 1: scan table mapping str -> rightmost pos.
59 let mut mm = HashMap::new();
67 // Pass 2: concat strings for each elt, skipping
68 // forwards over any cycles by advancing to rightmost
69 // occurrence of each element in path.
82 let n = match h.find(&s) {
91 pub fn position_before(&self, insn: ValueRef) {
93 llvm::LLVMPositionBuilderBefore(self.llbuilder, insn);
97 pub fn position_at_end(&self, llbb: BasicBlockRef) {
99 llvm::LLVMPositionBuilderAtEnd(self.llbuilder, llbb);
103 pub fn ret_void(&self) {
104 self.count_insn("retvoid");
106 llvm::LLVMBuildRetVoid(self.llbuilder);
110 pub fn ret(&self, v: ValueRef) {
111 self.count_insn("ret");
113 llvm::LLVMBuildRet(self.llbuilder, v);
117 pub fn aggregate_ret(&self, ret_vals: &[ValueRef]) {
119 llvm::LLVMBuildAggregateRet(self.llbuilder,
120 vec::raw::to_ptr(ret_vals),
121 ret_vals.len() as c_uint);
125 pub fn br(&self, dest: BasicBlockRef) {
126 self.count_insn("br");
128 llvm::LLVMBuildBr(self.llbuilder, dest);
132 pub fn cond_br(&self, cond: ValueRef, then_llbb: BasicBlockRef, else_llbb: BasicBlockRef) {
133 self.count_insn("condbr");
135 llvm::LLVMBuildCondBr(self.llbuilder, cond, then_llbb, else_llbb);
139 pub fn switch(&self, v: ValueRef, else_llbb: BasicBlockRef, num_cases: uint) -> ValueRef {
141 llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, num_cases as c_uint)
145 pub fn indirect_br(&self, addr: ValueRef, num_dests: uint) {
146 self.count_insn("indirectbr");
148 llvm::LLVMBuildIndirectBr(self.llbuilder, addr, num_dests as c_uint);
156 catch: BasicBlockRef)
158 self.count_insn("invoke");
160 llvm::LLVMBuildInvoke(self.llbuilder,
162 vec::raw::to_ptr(args),
163 args.len() as c_uint,
170 pub fn fast_invoke(&self,
174 catch: BasicBlockRef) {
175 self.count_insn("fastinvoke");
176 let v = self.invoke(llfn, args, then, catch);
177 lib::llvm::SetInstructionCallConv(v, lib::llvm::FastCallConv);
180 pub fn unreachable(&self) {
181 self.count_insn("unreachable");
183 llvm::LLVMBuildUnreachable(self.llbuilder);
188 pub fn add(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
189 self.count_insn("add");
191 llvm::LLVMBuildAdd(self.llbuilder, lhs, rhs, noname())
195 pub fn nswadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
196 self.count_insn("nswadd");
198 llvm::LLVMBuildNSWAdd(self.llbuilder, lhs, rhs, noname())
202 pub fn nuwadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
203 self.count_insn("nuwadd");
205 llvm::LLVMBuildNUWAdd(self.llbuilder, lhs, rhs, noname())
209 pub fn fadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
210 self.count_insn("fadd");
212 llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname())
216 pub fn sub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
217 self.count_insn("sub");
219 llvm::LLVMBuildSub(self.llbuilder, lhs, rhs, noname())
223 pub fn nswsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
224 self.count_insn("nwsub");
226 llvm::LLVMBuildNSWSub(self.llbuilder, lhs, rhs, noname())
230 pub fn nuwsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
231 self.count_insn("nuwsub");
233 llvm::LLVMBuildNUWSub(self.llbuilder, lhs, rhs, noname())
237 pub fn fsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
238 self.count_insn("sub");
240 llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname())
244 pub fn mul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
245 self.count_insn("mul");
247 llvm::LLVMBuildMul(self.llbuilder, lhs, rhs, noname())
251 pub fn nswmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
252 self.count_insn("nswmul");
254 llvm::LLVMBuildNSWMul(self.llbuilder, lhs, rhs, noname())
258 pub fn nuwmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
259 self.count_insn("nuwmul");
261 llvm::LLVMBuildNUWMul(self.llbuilder, lhs, rhs, noname())
265 pub fn fmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
266 self.count_insn("fmul");
268 llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname())
272 pub fn udiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
273 self.count_insn("udiv");
275 llvm::LLVMBuildUDiv(self.llbuilder, lhs, rhs, noname())
279 pub fn sdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
280 self.count_insn("sdiv");
282 llvm::LLVMBuildSDiv(self.llbuilder, lhs, rhs, noname())
286 pub fn exactsdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
287 self.count_insn("exactsdiv");
289 llvm::LLVMBuildExactSDiv(self.llbuilder, lhs, rhs, noname())
293 pub fn fdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
294 self.count_insn("fdiv");
296 llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname())
300 pub fn urem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
301 self.count_insn("urem");
303 llvm::LLVMBuildURem(self.llbuilder, lhs, rhs, noname())
307 pub fn srem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
308 self.count_insn("srem");
310 llvm::LLVMBuildSRem(self.llbuilder, lhs, rhs, noname())
314 pub fn frem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
315 self.count_insn("frem");
317 llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname())
321 pub fn shl(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
322 self.count_insn("shl");
324 llvm::LLVMBuildShl(self.llbuilder, lhs, rhs, noname())
328 pub fn lshr(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
329 self.count_insn("lshr");
331 llvm::LLVMBuildLShr(self.llbuilder, lhs, rhs, noname())
335 pub fn ashr(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
336 self.count_insn("ashr");
338 llvm::LLVMBuildAShr(self.llbuilder, lhs, rhs, noname())
342 pub fn and(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
343 self.count_insn("and");
345 llvm::LLVMBuildAnd(self.llbuilder, lhs, rhs, noname())
349 pub fn or(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
350 self.count_insn("or");
352 llvm::LLVMBuildOr(self.llbuilder, lhs, rhs, noname())
356 pub fn xor(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
357 self.count_insn("xor");
359 llvm::LLVMBuildXor(self.llbuilder, lhs, rhs, noname())
363 pub fn binop(&self, op: Opcode, lhs: ValueRef, rhs: ValueRef)
365 self.count_insn("binop");
367 llvm::LLVMBuildBinOp(self.llbuilder, op, lhs, rhs, noname())
371 pub fn neg(&self, V: ValueRef) -> ValueRef {
372 self.count_insn("neg");
374 llvm::LLVMBuildNeg(self.llbuilder, V, noname())
378 pub fn nswneg(&self, V: ValueRef) -> ValueRef {
379 self.count_insn("nswneg");
381 llvm::LLVMBuildNSWNeg(self.llbuilder, V, noname())
385 pub fn nuwneg(&self, V: ValueRef) -> ValueRef {
386 self.count_insn("nuwneg");
388 llvm::LLVMBuildNUWNeg(self.llbuilder, V, noname())
391 pub fn fneg(&self, V: ValueRef) -> ValueRef {
392 self.count_insn("fneg");
394 llvm::LLVMBuildFNeg(self.llbuilder, V, noname())
398 pub fn not(&self, V: ValueRef) -> ValueRef {
399 self.count_insn("not");
401 llvm::LLVMBuildNot(self.llbuilder, V, noname())
406 pub fn malloc(&self, ty: Type) -> ValueRef {
407 self.count_insn("malloc");
409 llvm::LLVMBuildMalloc(self.llbuilder, ty.to_ref(), noname())
413 pub fn array_malloc(&self, ty: Type, val: ValueRef) -> ValueRef {
414 self.count_insn("arraymalloc");
416 llvm::LLVMBuildArrayMalloc(self.llbuilder, ty.to_ref(), val, noname())
420 pub fn alloca(&self, ty: Type, name: &str) -> ValueRef {
421 self.count_insn("alloca");
424 llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname())
426 do name.as_c_str |c| {
427 llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), c)
433 pub fn array_alloca(&self, ty: Type, val: ValueRef) -> ValueRef {
434 self.count_insn("arrayalloca");
436 llvm::LLVMBuildArrayAlloca(self.llbuilder, ty.to_ref(), val, noname())
440 pub fn free(&self, ptr: ValueRef) {
441 self.count_insn("free");
443 llvm::LLVMBuildFree(self.llbuilder, ptr);
447 pub fn load(&self, ptr: ValueRef) -> ValueRef {
448 self.count_insn("load");
450 llvm::LLVMBuildLoad(self.llbuilder, ptr, noname())
454 pub fn atomic_load(&self, ptr: ValueRef, order: AtomicOrdering) -> ValueRef {
455 self.count_insn("load.atomic");
457 let align = llalign_of_min(self.ccx, self.ccx.int_type);
458 llvm::LLVMBuildAtomicLoad(self.llbuilder, ptr, noname(), order, align as c_uint)
463 pub fn load_range_assert(&self, ptr: ValueRef, lo: c_ulonglong,
464 hi: c_ulonglong, signed: lib::llvm::Bool) -> ValueRef {
465 let value = self.load(ptr);
468 let t = llvm::LLVMGetElementType(llvm::LLVMTypeOf(ptr));
469 let min = llvm::LLVMConstInt(t, lo, signed);
470 let max = llvm::LLVMConstInt(t, hi, signed);
472 do [min, max].as_imm_buf |ptr, len| {
473 llvm::LLVMSetMetadata(value, lib::llvm::MD_range as c_uint,
474 llvm::LLVMMDNodeInContext(self.ccx.llcx,
475 ptr, len as c_uint));
482 pub fn store(&self, val: ValueRef, ptr: ValueRef) {
483 debug!("Store %s -> %s",
484 self.ccx.tn.val_to_str(val),
485 self.ccx.tn.val_to_str(ptr));
486 self.count_insn("store");
488 llvm::LLVMBuildStore(self.llbuilder, val, ptr);
492 pub fn atomic_store(&self, val: ValueRef, ptr: ValueRef, order: AtomicOrdering) {
493 debug!("Store %s -> %s",
494 self.ccx.tn.val_to_str(val),
495 self.ccx.tn.val_to_str(ptr));
496 self.count_insn("store.atomic");
497 let align = llalign_of_min(self.ccx, self.ccx.int_type);
499 llvm::LLVMBuildAtomicStore(self.llbuilder, val, ptr, order, align as c_uint);
503 pub fn gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef {
504 self.count_insn("gep");
506 llvm::LLVMBuildGEP(self.llbuilder, ptr, vec::raw::to_ptr(indices),
507 indices.len() as c_uint, noname())
511 // Simple wrapper around GEP that takes an array of ints and wraps them
514 pub fn gepi(&self, base: ValueRef, ixs: &[uint]) -> ValueRef {
515 // Small vector optimization. This should catch 100% of the cases that
518 let mut small_vec = [ C_i32(0), ..16 ];
519 for small_vec.mut_iter().zip(ixs.iter()).advance |(small_vec_e, &ix)| {
520 *small_vec_e = C_i32(ix as i32);
522 self.inbounds_gep(base, small_vec.slice(0, ixs.len()))
524 let v = do ixs.iter().transform |i| { C_i32(*i as i32) }.collect::<~[ValueRef]>();
525 self.count_insn("gepi");
526 self.inbounds_gep(base, v)
530 pub fn inbounds_gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef {
531 self.count_insn("inboundsgep");
533 llvm::LLVMBuildInBoundsGEP(
534 self.llbuilder, ptr, vec::raw::to_ptr(indices), indices.len() as c_uint, noname())
538 pub fn struct_gep(&self, ptr: ValueRef, idx: uint) -> ValueRef {
539 self.count_insn("structgep");
541 llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname())
545 pub fn global_string(&self, _Str: *c_char) -> ValueRef {
546 self.count_insn("globalstring");
548 llvm::LLVMBuildGlobalString(self.llbuilder, _Str, noname())
552 pub fn global_string_ptr(&self, _Str: *c_char) -> ValueRef {
553 self.count_insn("globalstringptr");
555 llvm::LLVMBuildGlobalStringPtr(self.llbuilder, _Str, noname())
560 pub fn trunc(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
561 self.count_insn("trunc");
563 llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty.to_ref(), noname())
567 pub fn zext(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
568 self.count_insn("zext");
570 llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty.to_ref(), noname())
574 pub fn sext(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
575 self.count_insn("sext");
577 llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty.to_ref(), noname())
581 pub fn fptoui(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
582 self.count_insn("fptoui");
584 llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty.to_ref(), noname())
588 pub fn fptosi(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
589 self.count_insn("fptosi");
591 llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty.to_ref(),noname())
595 pub fn uitofp(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
596 self.count_insn("uitofp");
598 llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty.to_ref(), noname())
602 pub fn sitofp(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
603 self.count_insn("sitofp");
605 llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty.to_ref(), noname())
609 pub fn fptrunc(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
610 self.count_insn("fptrunc");
612 llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty.to_ref(), noname())
616 pub fn fpext(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
617 self.count_insn("fpext");
619 llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty.to_ref(), noname())
623 pub fn ptrtoint(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
624 self.count_insn("ptrtoint");
626 llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty.to_ref(), noname())
630 pub fn inttoptr(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
631 self.count_insn("inttoptr");
633 llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty.to_ref(), noname())
637 pub fn bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
638 self.count_insn("bitcast");
640 llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
644 pub fn zext_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
645 self.count_insn("zextorbitcast");
647 llvm::LLVMBuildZExtOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
651 pub fn sext_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
652 self.count_insn("sextorbitcast");
654 llvm::LLVMBuildSExtOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
658 pub fn trunc_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
659 self.count_insn("truncorbitcast");
661 llvm::LLVMBuildTruncOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
665 pub fn cast(&self, op: Opcode, val: ValueRef, dest_ty: Type) -> ValueRef {
666 self.count_insn("cast");
668 llvm::LLVMBuildCast(self.llbuilder, op, val, dest_ty.to_ref(), noname())
672 pub fn pointercast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
673 self.count_insn("pointercast");
675 llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty.to_ref(), noname())
679 pub fn intcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
680 self.count_insn("intcast");
682 llvm::LLVMBuildIntCast(self.llbuilder, val, dest_ty.to_ref(), noname())
686 pub fn fpcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
687 self.count_insn("fpcast");
689 llvm::LLVMBuildFPCast(self.llbuilder, val, dest_ty.to_ref(), noname())
695 pub fn icmp(&self, op: IntPredicate, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
696 self.count_insn("icmp");
698 llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
702 pub fn fcmp(&self, op: RealPredicate, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
703 self.count_insn("fcmp");
705 llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
709 /* Miscellaneous instructions */
710 pub fn empty_phi(&self, ty: Type) -> ValueRef {
711 self.count_insn("emptyphi");
713 llvm::LLVMBuildPhi(self.llbuilder, ty.to_ref(), noname())
717 pub fn phi(&self, ty: Type, vals: &[ValueRef], bbs: &[BasicBlockRef]) -> ValueRef {
718 assert_eq!(vals.len(), bbs.len());
719 let phi = self.empty_phi(ty);
720 self.count_insn("addincoming");
722 llvm::LLVMAddIncoming(phi, vec::raw::to_ptr(vals),
723 vec::raw::to_ptr(bbs),
724 vals.len() as c_uint);
729 pub fn add_span_comment(&self, sp: span, text: &str) {
730 if self.ccx.sess.asm_comments() {
731 let s = fmt!("%s (%s)", text, self.ccx.sess.codemap.span_to_str(sp));
737 pub fn add_comment(&self, text: &str) {
738 if self.ccx.sess.asm_comments() {
739 let sanitized = text.replace("$", "");
740 let comment_text = fmt!("# %s", sanitized.replace("\n", "\n\t# "));
741 self.count_insn("inlineasm");
742 let asm = do comment_text.as_c_str |c| {
744 llvm::LLVMConstInlineAsm(Type::func([], &Type::void()).to_ref(),
745 c, noname(), False, False)
752 pub fn inline_asm_call(&self, asm: *c_char, cons: *c_char,
753 inputs: &[ValueRef], output: Type,
754 volatile: bool, alignstack: bool,
755 dia: AsmDialect) -> ValueRef {
756 self.count_insn("inlineasm");
758 let volatile = if volatile { lib::llvm::True }
759 else { lib::llvm::False };
760 let alignstack = if alignstack { lib::llvm::True }
761 else { lib::llvm::False };
763 let argtys = do inputs.map |v| {
764 debug!("Asm Input Type: %?", self.ccx.tn.val_to_str(*v));
768 debug!("Asm Output Type: %?", self.ccx.tn.type_to_str(output));
769 let fty = Type::func(argtys, &output);
771 let v = llvm::LLVMInlineAsm(
772 fty.to_ref(), asm, cons, volatile, alignstack, dia as c_uint);
777 pub fn call(&self, llfn: ValueRef, args: &[ValueRef]) -> ValueRef {
778 self.count_insn("call");
780 debug!("Call(llfn=%s, args=%?)",
781 self.ccx.tn.val_to_str(llfn),
782 args.map(|arg| self.ccx.tn.val_to_str(*arg)));
784 do args.as_imm_buf |ptr, len| {
786 llvm::LLVMBuildCall(self.llbuilder, llfn, ptr, len as c_uint, noname())
791 pub fn fastcall(&self, llfn: ValueRef, args: &[ValueRef]) -> ValueRef {
792 self.count_insn("fastcall");
794 let v = llvm::LLVMBuildCall(self.llbuilder, llfn, vec::raw::to_ptr(args),
795 args.len() as c_uint, noname());
796 lib::llvm::SetInstructionCallConv(v, lib::llvm::FastCallConv);
801 pub fn call_with_conv(&self, llfn: ValueRef, args: &[ValueRef],
802 conv: CallConv) -> ValueRef {
803 self.count_insn("callwithconv");
805 let v = llvm::LLVMBuildCall(self.llbuilder, llfn, vec::raw::to_ptr(args),
806 args.len() as c_uint, noname());
807 lib::llvm::SetInstructionCallConv(v, conv);
812 pub fn select(&self, cond: ValueRef, then_val: ValueRef, else_val: ValueRef) -> ValueRef {
813 self.count_insn("select");
815 llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname())
819 pub fn va_arg(&self, list: ValueRef, ty: Type) -> ValueRef {
820 self.count_insn("vaarg");
822 llvm::LLVMBuildVAArg(self.llbuilder, list, ty.to_ref(), noname())
826 pub fn extract_element(&self, vec: ValueRef, idx: ValueRef) -> ValueRef {
827 self.count_insn("extractelement");
829 llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname())
833 pub fn insert_element(&self, vec: ValueRef, elt: ValueRef, idx: ValueRef) -> ValueRef {
834 self.count_insn("insertelement");
836 llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname())
840 pub fn shuffle_vector(&self, v1: ValueRef, v2: ValueRef, mask: ValueRef) -> ValueRef {
841 self.count_insn("shufflevector");
843 llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname())
847 pub fn vector_splat(&self, num_elts: uint, elt: ValueRef) -> ValueRef {
849 let elt_ty = val_ty(elt);
850 let Undef = llvm::LLVMGetUndef(Type::vector(&elt_ty, num_elts as u64).to_ref());
851 let vec = self.insert_element(Undef, elt, C_i32(0));
852 self.shuffle_vector(vec, Undef, C_null(Type::vector(&Type::i32(), num_elts as u64)))
856 pub fn extract_value(&self, agg_val: ValueRef, idx: uint) -> ValueRef {
857 self.count_insn("extractvalue");
859 llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, noname())
863 pub fn insert_value(&self, agg_val: ValueRef, elt: ValueRef,
865 self.count_insn("insertvalue");
867 llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint,
872 pub fn is_null(&self, val: ValueRef) -> ValueRef {
873 self.count_insn("isnull");
875 llvm::LLVMBuildIsNull(self.llbuilder, val, noname())
879 pub fn is_not_null(&self, val: ValueRef) -> ValueRef {
880 self.count_insn("isnotnull");
882 llvm::LLVMBuildIsNotNull(self.llbuilder, val, noname())
886 pub fn ptrdiff(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
887 self.count_insn("ptrdiff");
889 llvm::LLVMBuildPtrDiff(self.llbuilder, lhs, rhs, noname())
895 let BB: BasicBlockRef = llvm::LLVMGetInsertBlock(self.llbuilder);
896 let FN: ValueRef = llvm::LLVMGetBasicBlockParent(BB);
897 let M: ModuleRef = llvm::LLVMGetGlobalParent(FN);
898 let T: ValueRef = do "llvm.trap".as_c_str |buf| {
899 llvm::LLVMGetNamedFunction(M, buf)
901 assert!((T as int != 0));
902 let args: &[ValueRef] = [];
903 self.count_insn("trap");
905 self.llbuilder, T, vec::raw::to_ptr(args), args.len() as c_uint, noname());
909 pub fn landing_pad(&self, ty: Type, pers_fn: ValueRef, num_clauses: uint) -> ValueRef {
910 self.count_insn("landingpad");
912 llvm::LLVMBuildLandingPad(
913 self.llbuilder, ty.to_ref(), pers_fn, num_clauses as c_uint, noname())
917 pub fn set_cleanup(&self, landing_pad: ValueRef) {
918 self.count_insn("setcleanup");
920 llvm::LLVMSetCleanup(landing_pad, lib::llvm::True);
924 pub fn resume(&self, exn: ValueRef) -> ValueRef {
925 self.count_insn("resume");
927 llvm::LLVMBuildResume(self.llbuilder, exn)
932 pub fn atomic_cmpxchg(&self, dst: ValueRef,
933 cmp: ValueRef, src: ValueRef,
934 order: AtomicOrdering) -> ValueRef {
936 llvm::LLVMBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src, order)
939 pub fn atomic_rmw(&self, op: AtomicBinOp,
940 dst: ValueRef, src: ValueRef,
941 order: AtomicOrdering) -> ValueRef {
943 llvm::LLVMBuildAtomicRMW(self.llbuilder, op, dst, src, order)