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.
11 #![allow(dead_code)] // FFI wrappers
14 use llvm
::{CallConv, AtomicBinOp, AtomicOrdering, SynchronizationScope, AsmDialect, AttrBuilder}
;
15 use llvm
::{Opcode, IntPredicate, RealPredicate, False}
;
16 use llvm
::{ValueRef, BasicBlockRef, BuilderRef, ModuleRef}
;
19 use trans
::machine
::llalign_of_pref
;
20 use trans
::type_
::Type
;
21 use util
::nodemap
::FnvHashMap
;
22 use libc
::{c_uint, c_char}
;
24 use std
::ffi
::CString
;
26 use syntax
::codemap
::Span
;
28 pub struct Builder
<'a
, 'tcx
: 'a
> {
29 pub llbuilder
: BuilderRef
,
30 pub ccx
: &'a CrateContext
<'a
, 'tcx
>,
33 // This is a really awful way to get a zero-length c-string, but better (and a
34 // lot more efficient) than doing str::as_c_str("", ...) every time.
35 pub fn noname() -> *const c_char
{
36 static CNULL
: c_char
= 0;
40 impl<'a
, 'tcx
> Builder
<'a
, 'tcx
> {
41 pub fn new(ccx
: &'a CrateContext
<'a
, 'tcx
>) -> Builder
<'a
, 'tcx
> {
43 llbuilder
: ccx
.raw_builder(),
48 pub fn count_insn(&self, category
: &str) {
49 if self.ccx
.sess().trans_stats() {
50 self.ccx
.stats().n_llvm_insns
.set(self.ccx
55 self.ccx
.count_llvm_insn();
56 if self.ccx
.sess().count_llvm_insns() {
57 base
::with_insn_ctxt(|v
| {
58 let mut h
= self.ccx
.stats().llvm_insns
.borrow_mut();
60 // Build version of path with cycles removed.
62 // Pass 1: scan table mapping str -> rightmost pos.
63 let mut mm
= FnvHashMap();
71 // Pass 2: concat strings for each elt, skipping
72 // forwards over any cycles by advancing to rightmost
73 // occurrence of each element in path.
74 let mut s
= String
::from(".");
86 let n
= match h
.get(&s
) {
95 pub fn position_before(&self, insn
: ValueRef
) {
97 llvm
::LLVMPositionBuilderBefore(self.llbuilder
, insn
);
101 pub fn position_at_end(&self, llbb
: BasicBlockRef
) {
103 llvm
::LLVMPositionBuilderAtEnd(self.llbuilder
, llbb
);
107 pub fn ret_void(&self) {
108 self.count_insn("retvoid");
110 llvm
::LLVMBuildRetVoid(self.llbuilder
);
114 pub fn ret(&self, v
: ValueRef
) {
115 self.count_insn("ret");
117 llvm
::LLVMBuildRet(self.llbuilder
, v
);
121 pub fn aggregate_ret(&self, ret_vals
: &[ValueRef
]) {
123 llvm
::LLVMBuildAggregateRet(self.llbuilder
,
125 ret_vals
.len() as c_uint
);
129 pub fn br(&self, dest
: BasicBlockRef
) {
130 self.count_insn("br");
132 llvm
::LLVMBuildBr(self.llbuilder
, dest
);
136 pub fn cond_br(&self, cond
: ValueRef
, then_llbb
: BasicBlockRef
, else_llbb
: BasicBlockRef
) {
137 self.count_insn("condbr");
139 llvm
::LLVMBuildCondBr(self.llbuilder
, cond
, then_llbb
, else_llbb
);
143 pub fn switch(&self, v
: ValueRef
, else_llbb
: BasicBlockRef
, num_cases
: usize) -> ValueRef
{
145 llvm
::LLVMBuildSwitch(self.llbuilder
, v
, else_llbb
, num_cases
as c_uint
)
149 pub fn indirect_br(&self, addr
: ValueRef
, num_dests
: usize) {
150 self.count_insn("indirectbr");
152 llvm
::LLVMBuildIndirectBr(self.llbuilder
, addr
, num_dests
as c_uint
);
160 catch: BasicBlockRef
,
161 attributes
: Option
<AttrBuilder
>)
163 self.count_insn("invoke");
165 debug
!("Invoke {} with args ({})",
166 self.ccx
.tn().val_to_string(llfn
),
168 .map(|&v
| self.ccx
.tn().val_to_string(v
))
169 .collect
::<Vec
<String
>>()
173 let v
= llvm
::LLVMBuildInvoke(self.llbuilder
,
176 args
.len() as c_uint
,
181 Some(a
) => a
.apply_callsite(v
),
188 pub fn unreachable(&self) {
189 self.count_insn("unreachable");
191 llvm
::LLVMBuildUnreachable(self.llbuilder
);
196 pub fn add(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
197 self.count_insn("add");
199 llvm
::LLVMBuildAdd(self.llbuilder
, lhs
, rhs
, noname())
203 pub fn nswadd(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
204 self.count_insn("nswadd");
206 llvm
::LLVMBuildNSWAdd(self.llbuilder
, lhs
, rhs
, noname())
210 pub fn nuwadd(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
211 self.count_insn("nuwadd");
213 llvm
::LLVMBuildNUWAdd(self.llbuilder
, lhs
, rhs
, noname())
217 pub fn fadd(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
218 self.count_insn("fadd");
220 llvm
::LLVMBuildFAdd(self.llbuilder
, lhs
, rhs
, noname())
224 pub fn sub(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
225 self.count_insn("sub");
227 llvm
::LLVMBuildSub(self.llbuilder
, lhs
, rhs
, noname())
231 pub fn nswsub(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
232 self.count_insn("nwsub");
234 llvm
::LLVMBuildNSWSub(self.llbuilder
, lhs
, rhs
, noname())
238 pub fn nuwsub(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
239 self.count_insn("nuwsub");
241 llvm
::LLVMBuildNUWSub(self.llbuilder
, lhs
, rhs
, noname())
245 pub fn fsub(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
246 self.count_insn("sub");
248 llvm
::LLVMBuildFSub(self.llbuilder
, lhs
, rhs
, noname())
252 pub fn mul(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
253 self.count_insn("mul");
255 llvm
::LLVMBuildMul(self.llbuilder
, lhs
, rhs
, noname())
259 pub fn nswmul(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
260 self.count_insn("nswmul");
262 llvm
::LLVMBuildNSWMul(self.llbuilder
, lhs
, rhs
, noname())
266 pub fn nuwmul(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
267 self.count_insn("nuwmul");
269 llvm
::LLVMBuildNUWMul(self.llbuilder
, lhs
, rhs
, noname())
273 pub fn fmul(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
274 self.count_insn("fmul");
276 llvm
::LLVMBuildFMul(self.llbuilder
, lhs
, rhs
, noname())
280 pub fn udiv(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
281 self.count_insn("udiv");
283 llvm
::LLVMBuildUDiv(self.llbuilder
, lhs
, rhs
, noname())
287 pub fn sdiv(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
288 self.count_insn("sdiv");
290 llvm
::LLVMBuildSDiv(self.llbuilder
, lhs
, rhs
, noname())
294 pub fn exactsdiv(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
295 self.count_insn("exactsdiv");
297 llvm
::LLVMBuildExactSDiv(self.llbuilder
, lhs
, rhs
, noname())
301 pub fn fdiv(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
302 self.count_insn("fdiv");
304 llvm
::LLVMBuildFDiv(self.llbuilder
, lhs
, rhs
, noname())
308 pub fn urem(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
309 self.count_insn("urem");
311 llvm
::LLVMBuildURem(self.llbuilder
, lhs
, rhs
, noname())
315 pub fn srem(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
316 self.count_insn("srem");
318 llvm
::LLVMBuildSRem(self.llbuilder
, lhs
, rhs
, noname())
322 pub fn frem(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
323 self.count_insn("frem");
325 llvm
::LLVMBuildFRem(self.llbuilder
, lhs
, rhs
, noname())
329 pub fn shl(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
330 self.count_insn("shl");
332 llvm
::LLVMBuildShl(self.llbuilder
, lhs
, rhs
, noname())
336 pub fn lshr(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
337 self.count_insn("lshr");
339 llvm
::LLVMBuildLShr(self.llbuilder
, lhs
, rhs
, noname())
343 pub fn ashr(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
344 self.count_insn("ashr");
346 llvm
::LLVMBuildAShr(self.llbuilder
, lhs
, rhs
, noname())
350 pub fn and(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
351 self.count_insn("and");
353 llvm
::LLVMBuildAnd(self.llbuilder
, lhs
, rhs
, noname())
357 pub fn or(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
358 self.count_insn("or");
360 llvm
::LLVMBuildOr(self.llbuilder
, lhs
, rhs
, noname())
364 pub fn xor(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
365 self.count_insn("xor");
367 llvm
::LLVMBuildXor(self.llbuilder
, lhs
, rhs
, noname())
371 pub fn binop(&self, op
: Opcode
, lhs
: ValueRef
, rhs
: ValueRef
)
373 self.count_insn("binop");
375 llvm
::LLVMBuildBinOp(self.llbuilder
, op
, lhs
, rhs
, noname())
379 pub fn neg(&self, v
: ValueRef
) -> ValueRef
{
380 self.count_insn("neg");
382 llvm
::LLVMBuildNeg(self.llbuilder
, v
, noname())
386 pub fn nswneg(&self, v
: ValueRef
) -> ValueRef
{
387 self.count_insn("nswneg");
389 llvm
::LLVMBuildNSWNeg(self.llbuilder
, v
, noname())
393 pub fn nuwneg(&self, v
: ValueRef
) -> ValueRef
{
394 self.count_insn("nuwneg");
396 llvm
::LLVMBuildNUWNeg(self.llbuilder
, v
, noname())
399 pub fn fneg(&self, v
: ValueRef
) -> ValueRef
{
400 self.count_insn("fneg");
402 llvm
::LLVMBuildFNeg(self.llbuilder
, v
, noname())
406 pub fn not(&self, v
: ValueRef
) -> ValueRef
{
407 self.count_insn("not");
409 llvm
::LLVMBuildNot(self.llbuilder
, v
, noname())
413 pub fn alloca(&self, ty
: Type
, name
: &str) -> ValueRef
{
414 self.count_insn("alloca");
417 llvm
::LLVMBuildAlloca(self.llbuilder
, ty
.to_ref(), noname())
419 let name
= CString
::new(name
).unwrap();
420 llvm
::LLVMBuildAlloca(self.llbuilder
, ty
.to_ref(),
426 pub fn free(&self, ptr
: ValueRef
) {
427 self.count_insn("free");
429 llvm
::LLVMBuildFree(self.llbuilder
, ptr
);
433 pub fn load(&self, ptr
: ValueRef
) -> ValueRef
{
434 self.count_insn("load");
436 llvm
::LLVMBuildLoad(self.llbuilder
, ptr
, noname())
440 pub fn volatile_load(&self, ptr
: ValueRef
) -> ValueRef
{
441 self.count_insn("load.volatile");
443 let insn
= llvm
::LLVMBuildLoad(self.llbuilder
, ptr
, noname());
444 llvm
::LLVMSetVolatile(insn
, llvm
::True
);
449 pub fn atomic_load(&self, ptr
: ValueRef
, order
: AtomicOrdering
) -> ValueRef
{
450 self.count_insn("load.atomic");
452 let ty
= Type
::from_ref(llvm
::LLVMTypeOf(ptr
));
453 let align
= llalign_of_pref(self.ccx
, ty
.element_type());
454 llvm
::LLVMBuildAtomicLoad(self.llbuilder
, ptr
, noname(), order
,
460 pub fn load_range_assert(&self, ptr
: ValueRef
, lo
: u64,
461 hi
: u64, signed
: llvm
::Bool
) -> ValueRef
{
462 let value
= self.load(ptr
);
465 let t
= llvm
::LLVMGetElementType(llvm
::LLVMTypeOf(ptr
));
466 let min
= llvm
::LLVMConstInt(t
, lo
, signed
);
467 let max
= llvm
::LLVMConstInt(t
, hi
, signed
);
471 llvm
::LLVMSetMetadata(value
, llvm
::MD_range
as c_uint
,
472 llvm
::LLVMMDNodeInContext(self.ccx
.llcx(),
480 pub fn load_nonnull(&self, ptr
: ValueRef
) -> ValueRef
{
481 let value
= self.load(ptr
);
483 llvm
::LLVMSetMetadata(value
, llvm
::MD_nonnull
as c_uint
,
484 llvm
::LLVMMDNodeInContext(self.ccx
.llcx(), ptr
::null(), 0));
490 pub fn store(&self, val
: ValueRef
, ptr
: ValueRef
) -> ValueRef
{
491 debug
!("Store {} -> {}",
492 self.ccx
.tn().val_to_string(val
),
493 self.ccx
.tn().val_to_string(ptr
));
494 assert
!(!self.llbuilder
.is_null());
495 self.count_insn("store");
497 llvm
::LLVMBuildStore(self.llbuilder
, val
, ptr
)
501 pub fn volatile_store(&self, val
: ValueRef
, ptr
: ValueRef
) -> ValueRef
{
502 debug
!("Store {} -> {}",
503 self.ccx
.tn().val_to_string(val
),
504 self.ccx
.tn().val_to_string(ptr
));
505 assert
!(!self.llbuilder
.is_null());
506 self.count_insn("store.volatile");
508 let insn
= llvm
::LLVMBuildStore(self.llbuilder
, val
, ptr
);
509 llvm
::LLVMSetVolatile(insn
, llvm
::True
);
514 pub fn atomic_store(&self, val
: ValueRef
, ptr
: ValueRef
, order
: AtomicOrdering
) {
515 debug
!("Store {} -> {}",
516 self.ccx
.tn().val_to_string(val
),
517 self.ccx
.tn().val_to_string(ptr
));
518 self.count_insn("store.atomic");
520 let ty
= Type
::from_ref(llvm
::LLVMTypeOf(ptr
));
521 let align
= llalign_of_pref(self.ccx
, ty
.element_type());
522 llvm
::LLVMBuildAtomicStore(self.llbuilder
, val
, ptr
, order
, align
as c_uint
);
526 pub fn gep(&self, ptr
: ValueRef
, indices
: &[ValueRef
]) -> ValueRef
{
527 self.count_insn("gep");
529 llvm
::LLVMBuildGEP(self.llbuilder
, ptr
, indices
.as_ptr(),
530 indices
.len() as c_uint
, noname())
534 // Simple wrapper around GEP that takes an array of ints and wraps them
537 pub fn gepi(&self, base
: ValueRef
, ixs
: &[usize]) -> ValueRef
{
538 // Small vector optimization. This should catch 100% of the cases that
541 let mut small_vec
= [ C_i32(self.ccx
, 0); 16 ];
542 for (small_vec_e
, &ix
) in small_vec
.iter_mut().zip(ixs
) {
543 *small_vec_e
= C_i32(self.ccx
, ix
as i32);
545 self.inbounds_gep(base
, &small_vec
[..ixs
.len()])
547 let v
= ixs
.iter().map(|i
| C_i32(self.ccx
, *i
as i32)).collect
::<Vec
<ValueRef
>>();
548 self.count_insn("gepi");
549 self.inbounds_gep(base
, &v
[..])
553 pub fn inbounds_gep(&self, ptr
: ValueRef
, indices
: &[ValueRef
]) -> ValueRef
{
554 self.count_insn("inboundsgep");
556 llvm
::LLVMBuildInBoundsGEP(
557 self.llbuilder
, ptr
, indices
.as_ptr(), indices
.len() as c_uint
, noname())
561 pub fn struct_gep(&self, ptr
: ValueRef
, idx
: usize) -> ValueRef
{
562 self.count_insn("structgep");
564 llvm
::LLVMBuildStructGEP(self.llbuilder
, ptr
, idx
as c_uint
, noname())
568 pub fn global_string(&self, _str
: *const c_char
) -> ValueRef
{
569 self.count_insn("globalstring");
571 llvm
::LLVMBuildGlobalString(self.llbuilder
, _str
, noname())
575 pub fn global_string_ptr(&self, _str
: *const c_char
) -> ValueRef
{
576 self.count_insn("globalstringptr");
578 llvm
::LLVMBuildGlobalStringPtr(self.llbuilder
, _str
, noname())
583 pub fn trunc(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
584 self.count_insn("trunc");
586 llvm
::LLVMBuildTrunc(self.llbuilder
, val
, dest_ty
.to_ref(), noname())
590 pub fn zext(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
591 self.count_insn("zext");
593 llvm
::LLVMBuildZExt(self.llbuilder
, val
, dest_ty
.to_ref(), noname())
597 pub fn sext(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
598 self.count_insn("sext");
600 llvm
::LLVMBuildSExt(self.llbuilder
, val
, dest_ty
.to_ref(), noname())
604 pub fn fptoui(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
605 self.count_insn("fptoui");
607 llvm
::LLVMBuildFPToUI(self.llbuilder
, val
, dest_ty
.to_ref(), noname())
611 pub fn fptosi(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
612 self.count_insn("fptosi");
614 llvm
::LLVMBuildFPToSI(self.llbuilder
, val
, dest_ty
.to_ref(),noname())
618 pub fn uitofp(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
619 self.count_insn("uitofp");
621 llvm
::LLVMBuildUIToFP(self.llbuilder
, val
, dest_ty
.to_ref(), noname())
625 pub fn sitofp(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
626 self.count_insn("sitofp");
628 llvm
::LLVMBuildSIToFP(self.llbuilder
, val
, dest_ty
.to_ref(), noname())
632 pub fn fptrunc(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
633 self.count_insn("fptrunc");
635 llvm
::LLVMBuildFPTrunc(self.llbuilder
, val
, dest_ty
.to_ref(), noname())
639 pub fn fpext(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
640 self.count_insn("fpext");
642 llvm
::LLVMBuildFPExt(self.llbuilder
, val
, dest_ty
.to_ref(), noname())
646 pub fn ptrtoint(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
647 self.count_insn("ptrtoint");
649 llvm
::LLVMBuildPtrToInt(self.llbuilder
, val
, dest_ty
.to_ref(), noname())
653 pub fn inttoptr(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
654 self.count_insn("inttoptr");
656 llvm
::LLVMBuildIntToPtr(self.llbuilder
, val
, dest_ty
.to_ref(), noname())
660 pub fn bitcast(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
661 self.count_insn("bitcast");
663 llvm
::LLVMBuildBitCast(self.llbuilder
, val
, dest_ty
.to_ref(), noname())
667 pub fn zext_or_bitcast(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
668 self.count_insn("zextorbitcast");
670 llvm
::LLVMBuildZExtOrBitCast(self.llbuilder
, val
, dest_ty
.to_ref(), noname())
674 pub fn sext_or_bitcast(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
675 self.count_insn("sextorbitcast");
677 llvm
::LLVMBuildSExtOrBitCast(self.llbuilder
, val
, dest_ty
.to_ref(), noname())
681 pub fn trunc_or_bitcast(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
682 self.count_insn("truncorbitcast");
684 llvm
::LLVMBuildTruncOrBitCast(self.llbuilder
, val
, dest_ty
.to_ref(), noname())
688 pub fn cast(&self, op
: Opcode
, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
689 self.count_insn("cast");
691 llvm
::LLVMBuildCast(self.llbuilder
, op
, val
, dest_ty
.to_ref(), noname())
695 pub fn pointercast(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
696 self.count_insn("pointercast");
698 llvm
::LLVMBuildPointerCast(self.llbuilder
, val
, dest_ty
.to_ref(), noname())
702 pub fn intcast(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
703 self.count_insn("intcast");
705 llvm
::LLVMBuildIntCast(self.llbuilder
, val
, dest_ty
.to_ref(), noname())
709 pub fn fpcast(&self, val
: ValueRef
, dest_ty
: Type
) -> ValueRef
{
710 self.count_insn("fpcast");
712 llvm
::LLVMBuildFPCast(self.llbuilder
, val
, dest_ty
.to_ref(), noname())
718 pub fn icmp(&self, op
: IntPredicate
, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
719 self.count_insn("icmp");
721 llvm
::LLVMBuildICmp(self.llbuilder
, op
as c_uint
, lhs
, rhs
, noname())
725 pub fn fcmp(&self, op
: RealPredicate
, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
726 self.count_insn("fcmp");
728 llvm
::LLVMBuildFCmp(self.llbuilder
, op
as c_uint
, lhs
, rhs
, noname())
732 /* Miscellaneous instructions */
733 pub fn empty_phi(&self, ty
: Type
) -> ValueRef
{
734 self.count_insn("emptyphi");
736 llvm
::LLVMBuildPhi(self.llbuilder
, ty
.to_ref(), noname())
740 pub fn phi(&self, ty
: Type
, vals
: &[ValueRef
], bbs
: &[BasicBlockRef
]) -> ValueRef
{
741 assert_eq
!(vals
.len(), bbs
.len());
742 let phi
= self.empty_phi(ty
);
743 self.count_insn("addincoming");
745 llvm
::LLVMAddIncoming(phi
, vals
.as_ptr(),
747 vals
.len() as c_uint
);
752 pub fn add_span_comment(&self, sp
: Span
, text
: &str) {
753 if self.ccx
.sess().asm_comments() {
754 let s
= format
!("{} ({})",
756 self.ccx
.sess().codemap().span_to_string(sp
));
757 debug
!("{}", &s
[..]);
758 self.add_comment(&s
[..]);
762 pub fn add_comment(&self, text
: &str) {
763 if self.ccx
.sess().asm_comments() {
764 let sanitized
= text
.replace("$", "");
765 let comment_text
= format
!("{} {}", "#",
766 sanitized
.replace("\n", "\n\t# "));
767 self.count_insn("inlineasm");
768 let comment_text
= CString
::new(comment_text
).unwrap();
770 llvm
::LLVMConstInlineAsm(Type
::func(&[], &Type
::void(self.ccx
)).to_ref(),
771 comment_text
.as_ptr(), noname(), False
,
774 self.call(asm
, &[], None
);
778 pub fn inline_asm_call(&self, asm
: *const c_char
, cons
: *const c_char
,
779 inputs
: &[ValueRef
], output
: Type
,
780 volatile
: bool
, alignstack
: bool
,
781 dia
: AsmDialect
) -> ValueRef
{
782 self.count_insn("inlineasm");
784 let volatile
= if volatile { llvm::True }
785 else { llvm::False }
;
786 let alignstack
= if alignstack { llvm::True }
787 else { llvm::False }
;
789 let argtys
= inputs
.iter().map(|v
| {
790 debug
!("Asm Input Type: {}", self.ccx
.tn().val_to_string(*v
));
792 }).collect
::<Vec
<_
>>();
794 debug
!("Asm Output Type: {}", self.ccx
.tn().type_to_string(output
));
795 let fty
= Type
::func(&argtys
[..], &output
);
797 let v
= llvm
::LLVMInlineAsm(
798 fty
.to_ref(), asm
, cons
, volatile
, alignstack
, dia
as c_uint
);
799 self.call(v
, inputs
, None
)
803 pub fn call(&self, llfn
: ValueRef
, args
: &[ValueRef
],
804 attributes
: Option
<AttrBuilder
>) -> ValueRef
{
805 self.count_insn("call");
807 debug
!("Call {} with args ({})",
808 self.ccx
.tn().val_to_string(llfn
),
810 .map(|&v
| self.ccx
.tn().val_to_string(v
))
811 .collect
::<Vec
<String
>>()
815 let v
= llvm
::LLVMBuildCall(self.llbuilder
, llfn
, args
.as_ptr(),
816 args
.len() as c_uint
, noname());
818 Some(a
) => a
.apply_callsite(v
),
825 pub fn call_with_conv(&self, llfn
: ValueRef
, args
: &[ValueRef
],
826 conv
: CallConv
, attributes
: Option
<AttrBuilder
>) -> ValueRef
{
827 self.count_insn("callwithconv");
828 let v
= self.call(llfn
, args
, attributes
);
829 llvm
::SetInstructionCallConv(v
, conv
);
833 pub fn select(&self, cond
: ValueRef
, then_val
: ValueRef
, else_val
: ValueRef
) -> ValueRef
{
834 self.count_insn("select");
836 llvm
::LLVMBuildSelect(self.llbuilder
, cond
, then_val
, else_val
, noname())
840 pub fn va_arg(&self, list
: ValueRef
, ty
: Type
) -> ValueRef
{
841 self.count_insn("vaarg");
843 llvm
::LLVMBuildVAArg(self.llbuilder
, list
, ty
.to_ref(), noname())
847 pub fn extract_element(&self, vec
: ValueRef
, idx
: ValueRef
) -> ValueRef
{
848 self.count_insn("extractelement");
850 llvm
::LLVMBuildExtractElement(self.llbuilder
, vec
, idx
, noname())
854 pub fn insert_element(&self, vec
: ValueRef
, elt
: ValueRef
, idx
: ValueRef
) -> ValueRef
{
855 self.count_insn("insertelement");
857 llvm
::LLVMBuildInsertElement(self.llbuilder
, vec
, elt
, idx
, noname())
861 pub fn shuffle_vector(&self, v1
: ValueRef
, v2
: ValueRef
, mask
: ValueRef
) -> ValueRef
{
862 self.count_insn("shufflevector");
864 llvm
::LLVMBuildShuffleVector(self.llbuilder
, v1
, v2
, mask
, noname())
868 pub fn vector_splat(&self, num_elts
: usize, elt
: ValueRef
) -> ValueRef
{
870 let elt_ty
= val_ty(elt
);
871 let undef
= llvm
::LLVMGetUndef(Type
::vector(&elt_ty
, num_elts
as u64).to_ref());
872 let vec
= self.insert_element(undef
, elt
, C_i32(self.ccx
, 0));
873 let vec_i32_ty
= Type
::vector(&Type
::i32(self.ccx
), num_elts
as u64);
874 self.shuffle_vector(vec
, undef
, C_null(vec_i32_ty
))
878 pub fn extract_value(&self, agg_val
: ValueRef
, idx
: usize) -> ValueRef
{
879 self.count_insn("extractvalue");
881 llvm
::LLVMBuildExtractValue(self.llbuilder
, agg_val
, idx
as c_uint
, noname())
885 pub fn insert_value(&self, agg_val
: ValueRef
, elt
: ValueRef
,
886 idx
: usize) -> ValueRef
{
887 self.count_insn("insertvalue");
889 llvm
::LLVMBuildInsertValue(self.llbuilder
, agg_val
, elt
, idx
as c_uint
,
894 pub fn is_null(&self, val
: ValueRef
) -> ValueRef
{
895 self.count_insn("isnull");
897 llvm
::LLVMBuildIsNull(self.llbuilder
, val
, noname())
901 pub fn is_not_null(&self, val
: ValueRef
) -> ValueRef
{
902 self.count_insn("isnotnull");
904 llvm
::LLVMBuildIsNotNull(self.llbuilder
, val
, noname())
908 pub fn ptrdiff(&self, lhs
: ValueRef
, rhs
: ValueRef
) -> ValueRef
{
909 self.count_insn("ptrdiff");
911 llvm
::LLVMBuildPtrDiff(self.llbuilder
, lhs
, rhs
, noname())
917 let bb
: BasicBlockRef
= llvm
::LLVMGetInsertBlock(self.llbuilder
);
918 let fn_
: ValueRef
= llvm
::LLVMGetBasicBlockParent(bb
);
919 let m
: ModuleRef
= llvm
::LLVMGetGlobalParent(fn_
);
920 let p
= "llvm.trap\0".as_ptr();
921 let t
: ValueRef
= llvm
::LLVMGetNamedFunction(m
, p
as *const _
);
922 assert
!((t
as isize != 0));
923 let args
: &[ValueRef
] = &[];
924 self.count_insn("trap");
926 self.llbuilder
, t
, args
.as_ptr(), args
.len() as c_uint
, noname());
930 pub fn landing_pad(&self, ty
: Type
, pers_fn
: ValueRef
,
932 llfn
: ValueRef
) -> ValueRef
{
933 self.count_insn("landingpad");
935 llvm
::LLVMRustBuildLandingPad(self.llbuilder
, ty
.to_ref(), pers_fn
,
936 num_clauses
as c_uint
, noname(), llfn
)
940 pub fn add_clause(&self, landing_pad
: ValueRef
, clause
: ValueRef
) {
942 llvm
::LLVMAddClause(landing_pad
, clause
);
946 pub fn set_cleanup(&self, landing_pad
: ValueRef
) {
947 self.count_insn("setcleanup");
949 llvm
::LLVMSetCleanup(landing_pad
, llvm
::True
);
953 pub fn resume(&self, exn
: ValueRef
) -> ValueRef
{
954 self.count_insn("resume");
956 llvm
::LLVMBuildResume(self.llbuilder
, exn
)
961 pub fn atomic_cmpxchg(&self, dst
: ValueRef
,
962 cmp
: ValueRef
, src
: ValueRef
,
963 order
: AtomicOrdering
,
964 failure_order
: AtomicOrdering
) -> ValueRef
{
966 llvm
::LLVMBuildAtomicCmpXchg(self.llbuilder
, dst
, cmp
, src
,
967 order
, failure_order
)
970 pub fn atomic_rmw(&self, op
: AtomicBinOp
,
971 dst
: ValueRef
, src
: ValueRef
,
972 order
: AtomicOrdering
) -> ValueRef
{
974 llvm
::LLVMBuildAtomicRMW(self.llbuilder
, op
, dst
, src
, order
, False
)
978 pub fn atomic_fence(&self, order
: AtomicOrdering
, scope
: SynchronizationScope
) {
980 llvm
::LLVMBuildAtomicFence(self.llbuilder
, order
, scope
);