]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/builder.rs
Use `ptr::{null, null_mut}` instead of `0 as *{const, mut}`
[rust.git] / src / librustc_trans / builder.rs
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.
4 //
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.
10
11 #![allow(dead_code)] // FFI wrappers
12
13 use llvm;
14 use llvm::{AtomicBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
15 use llvm::{Opcode, IntPredicate, RealPredicate, False, OperandBundleDef};
16 use llvm::{ValueRef, BasicBlockRef, BuilderRef, ModuleRef};
17 use base;
18 use common::*;
19 use machine::llalign_of_pref;
20 use type_::Type;
21 use value::Value;
22 use util::nodemap::FnvHashMap;
23 use libc::{c_uint, c_char};
24
25 use std::ffi::CString;
26 use std::ptr;
27 use syntax_pos::Span;
28
29 pub struct Builder<'a, 'tcx: 'a> {
30     pub llbuilder: BuilderRef,
31     pub ccx: &'a CrateContext<'a, 'tcx>,
32 }
33
34 // This is a really awful way to get a zero-length c-string, but better (and a
35 // lot more efficient) than doing str::as_c_str("", ...) every time.
36 pub fn noname() -> *const c_char {
37     static CNULL: c_char = 0;
38     &CNULL
39 }
40
41 impl<'a, 'tcx> Builder<'a, 'tcx> {
42     pub fn new(ccx: &'a CrateContext<'a, 'tcx>) -> Builder<'a, 'tcx> {
43         Builder {
44             llbuilder: ccx.raw_builder(),
45             ccx: ccx,
46         }
47     }
48
49     pub fn count_insn(&self, category: &str) {
50         if self.ccx.sess().trans_stats() {
51             self.ccx.stats().n_llvm_insns.set(self.ccx
52                                                 .stats()
53                                                 .n_llvm_insns
54                                                 .get() + 1);
55         }
56         self.ccx.count_llvm_insn();
57         if self.ccx.sess().count_llvm_insns() {
58             base::with_insn_ctxt(|v| {
59                 let mut h = self.ccx.stats().llvm_insns.borrow_mut();
60
61                 // Build version of path with cycles removed.
62
63                 // Pass 1: scan table mapping str -> rightmost pos.
64                 let mut mm = FnvHashMap();
65                 let len = v.len();
66                 let mut i = 0;
67                 while i < len {
68                     mm.insert(v[i], i);
69                     i += 1;
70                 }
71
72                 // Pass 2: concat strings for each elt, skipping
73                 // forwards over any cycles by advancing to rightmost
74                 // occurrence of each element in path.
75                 let mut s = String::from(".");
76                 i = 0;
77                 while i < len {
78                     i = mm[v[i]];
79                     s.push('/');
80                     s.push_str(v[i]);
81                     i += 1;
82                 }
83
84                 s.push('/');
85                 s.push_str(category);
86
87                 let n = match h.get(&s) {
88                     Some(&n) => n,
89                     _ => 0
90                 };
91                 h.insert(s, n+1);
92             })
93         }
94     }
95
96     pub fn position_before(&self, insn: ValueRef) {
97         unsafe {
98             llvm::LLVMPositionBuilderBefore(self.llbuilder, insn);
99         }
100     }
101
102     pub fn position_at_end(&self, llbb: BasicBlockRef) {
103         unsafe {
104             llvm::LLVMPositionBuilderAtEnd(self.llbuilder, llbb);
105         }
106     }
107
108     pub fn position_at_start(&self, llbb: BasicBlockRef) {
109         unsafe {
110             llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb);
111         }
112     }
113
114     pub fn ret_void(&self) {
115         self.count_insn("retvoid");
116         unsafe {
117             llvm::LLVMBuildRetVoid(self.llbuilder);
118         }
119     }
120
121     pub fn ret(&self, v: ValueRef) {
122         self.count_insn("ret");
123         unsafe {
124             llvm::LLVMBuildRet(self.llbuilder, v);
125         }
126     }
127
128     pub fn aggregate_ret(&self, ret_vals: &[ValueRef]) {
129         unsafe {
130             llvm::LLVMBuildAggregateRet(self.llbuilder,
131                                         ret_vals.as_ptr(),
132                                         ret_vals.len() as c_uint);
133         }
134     }
135
136     pub fn br(&self, dest: BasicBlockRef) {
137         self.count_insn("br");
138         unsafe {
139             llvm::LLVMBuildBr(self.llbuilder, dest);
140         }
141     }
142
143     pub fn cond_br(&self, cond: ValueRef, then_llbb: BasicBlockRef, else_llbb: BasicBlockRef) {
144         self.count_insn("condbr");
145         unsafe {
146             llvm::LLVMBuildCondBr(self.llbuilder, cond, then_llbb, else_llbb);
147         }
148     }
149
150     pub fn switch(&self, v: ValueRef, else_llbb: BasicBlockRef, num_cases: usize) -> ValueRef {
151         unsafe {
152             llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, num_cases as c_uint)
153         }
154     }
155
156     pub fn indirect_br(&self, addr: ValueRef, num_dests: usize) {
157         self.count_insn("indirectbr");
158         unsafe {
159             llvm::LLVMBuildIndirectBr(self.llbuilder, addr, num_dests as c_uint);
160         }
161     }
162
163     pub fn invoke(&self,
164                   llfn: ValueRef,
165                   args: &[ValueRef],
166                   then: BasicBlockRef,
167                   catch: BasicBlockRef,
168                   bundle: Option<&OperandBundleDef>) -> ValueRef {
169         self.count_insn("invoke");
170
171         debug!("Invoke {:?} with args ({})",
172                Value(llfn),
173                args.iter()
174                    .map(|&v| format!("{:?}", Value(v)))
175                    .collect::<Vec<String>>()
176                    .join(", "));
177
178         check_call("invoke", llfn, args);
179
180         let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
181
182         unsafe {
183             llvm::LLVMRustBuildInvoke(self.llbuilder,
184                                       llfn,
185                                       args.as_ptr(),
186                                       args.len() as c_uint,
187                                       then,
188                                       catch,
189                                       bundle,
190                                       noname())
191         }
192     }
193
194     pub fn unreachable(&self) {
195         self.count_insn("unreachable");
196         unsafe {
197             llvm::LLVMBuildUnreachable(self.llbuilder);
198         }
199     }
200
201     /* Arithmetic */
202     pub fn add(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
203         self.count_insn("add");
204         unsafe {
205             llvm::LLVMBuildAdd(self.llbuilder, lhs, rhs, noname())
206         }
207     }
208
209     pub fn nswadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
210         self.count_insn("nswadd");
211         unsafe {
212             llvm::LLVMBuildNSWAdd(self.llbuilder, lhs, rhs, noname())
213         }
214     }
215
216     pub fn nuwadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
217         self.count_insn("nuwadd");
218         unsafe {
219             llvm::LLVMBuildNUWAdd(self.llbuilder, lhs, rhs, noname())
220         }
221     }
222
223     pub fn fadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
224         self.count_insn("fadd");
225         unsafe {
226             llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname())
227         }
228     }
229
230     pub fn fadd_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
231         self.count_insn("fadd");
232         unsafe {
233             let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname());
234             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
235             instr
236         }
237     }
238
239     pub fn sub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
240         self.count_insn("sub");
241         unsafe {
242             llvm::LLVMBuildSub(self.llbuilder, lhs, rhs, noname())
243         }
244     }
245
246     pub fn nswsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
247         self.count_insn("nwsub");
248         unsafe {
249             llvm::LLVMBuildNSWSub(self.llbuilder, lhs, rhs, noname())
250         }
251     }
252
253     pub fn nuwsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
254         self.count_insn("nuwsub");
255         unsafe {
256             llvm::LLVMBuildNUWSub(self.llbuilder, lhs, rhs, noname())
257         }
258     }
259
260     pub fn fsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
261         self.count_insn("sub");
262         unsafe {
263             llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname())
264         }
265     }
266
267     pub fn fsub_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
268         self.count_insn("sub");
269         unsafe {
270             let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname());
271             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
272             instr
273         }
274     }
275
276     pub fn mul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
277         self.count_insn("mul");
278         unsafe {
279             llvm::LLVMBuildMul(self.llbuilder, lhs, rhs, noname())
280         }
281     }
282
283     pub fn nswmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
284         self.count_insn("nswmul");
285         unsafe {
286             llvm::LLVMBuildNSWMul(self.llbuilder, lhs, rhs, noname())
287         }
288     }
289
290     pub fn nuwmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
291         self.count_insn("nuwmul");
292         unsafe {
293             llvm::LLVMBuildNUWMul(self.llbuilder, lhs, rhs, noname())
294         }
295     }
296
297     pub fn fmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
298         self.count_insn("fmul");
299         unsafe {
300             llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname())
301         }
302     }
303
304     pub fn fmul_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
305         self.count_insn("fmul");
306         unsafe {
307             let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname());
308             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
309             instr
310         }
311     }
312
313
314     pub fn udiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
315         self.count_insn("udiv");
316         unsafe {
317             llvm::LLVMBuildUDiv(self.llbuilder, lhs, rhs, noname())
318         }
319     }
320
321     pub fn sdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
322         self.count_insn("sdiv");
323         unsafe {
324             llvm::LLVMBuildSDiv(self.llbuilder, lhs, rhs, noname())
325         }
326     }
327
328     pub fn exactsdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
329         self.count_insn("exactsdiv");
330         unsafe {
331             llvm::LLVMBuildExactSDiv(self.llbuilder, lhs, rhs, noname())
332         }
333     }
334
335     pub fn fdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
336         self.count_insn("fdiv");
337         unsafe {
338             llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname())
339         }
340     }
341
342     pub fn fdiv_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
343         self.count_insn("fdiv");
344         unsafe {
345             let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname());
346             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
347             instr
348         }
349     }
350
351     pub fn urem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
352         self.count_insn("urem");
353         unsafe {
354             llvm::LLVMBuildURem(self.llbuilder, lhs, rhs, noname())
355         }
356     }
357
358     pub fn srem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
359         self.count_insn("srem");
360         unsafe {
361             llvm::LLVMBuildSRem(self.llbuilder, lhs, rhs, noname())
362         }
363     }
364
365     pub fn frem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
366         self.count_insn("frem");
367         unsafe {
368             llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname())
369         }
370     }
371
372     pub fn frem_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
373         self.count_insn("frem");
374         unsafe {
375             let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname());
376             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
377             instr
378         }
379     }
380
381     pub fn shl(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
382         self.count_insn("shl");
383         unsafe {
384             llvm::LLVMBuildShl(self.llbuilder, lhs, rhs, noname())
385         }
386     }
387
388     pub fn lshr(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
389         self.count_insn("lshr");
390         unsafe {
391             llvm::LLVMBuildLShr(self.llbuilder, lhs, rhs, noname())
392         }
393     }
394
395     pub fn ashr(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
396         self.count_insn("ashr");
397         unsafe {
398             llvm::LLVMBuildAShr(self.llbuilder, lhs, rhs, noname())
399         }
400     }
401
402     pub fn and(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
403         self.count_insn("and");
404         unsafe {
405             llvm::LLVMBuildAnd(self.llbuilder, lhs, rhs, noname())
406         }
407     }
408
409     pub fn or(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
410         self.count_insn("or");
411         unsafe {
412             llvm::LLVMBuildOr(self.llbuilder, lhs, rhs, noname())
413         }
414     }
415
416     pub fn xor(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
417         self.count_insn("xor");
418         unsafe {
419             llvm::LLVMBuildXor(self.llbuilder, lhs, rhs, noname())
420         }
421     }
422
423     pub fn binop(&self, op: Opcode, lhs: ValueRef, rhs: ValueRef)
424               -> ValueRef {
425         self.count_insn("binop");
426         unsafe {
427             llvm::LLVMBuildBinOp(self.llbuilder, op, lhs, rhs, noname())
428         }
429     }
430
431     pub fn neg(&self, v: ValueRef) -> ValueRef {
432         self.count_insn("neg");
433         unsafe {
434             llvm::LLVMBuildNeg(self.llbuilder, v, noname())
435         }
436     }
437
438     pub fn nswneg(&self, v: ValueRef) -> ValueRef {
439         self.count_insn("nswneg");
440         unsafe {
441             llvm::LLVMBuildNSWNeg(self.llbuilder, v, noname())
442         }
443     }
444
445     pub fn nuwneg(&self, v: ValueRef) -> ValueRef {
446         self.count_insn("nuwneg");
447         unsafe {
448             llvm::LLVMBuildNUWNeg(self.llbuilder, v, noname())
449         }
450     }
451     pub fn fneg(&self, v: ValueRef) -> ValueRef {
452         self.count_insn("fneg");
453         unsafe {
454             llvm::LLVMBuildFNeg(self.llbuilder, v, noname())
455         }
456     }
457
458     pub fn not(&self, v: ValueRef) -> ValueRef {
459         self.count_insn("not");
460         unsafe {
461             llvm::LLVMBuildNot(self.llbuilder, v, noname())
462         }
463     }
464
465     pub fn alloca(&self, ty: Type, name: &str) -> ValueRef {
466         self.count_insn("alloca");
467         unsafe {
468             if name.is_empty() {
469                 llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname())
470             } else {
471                 let name = CString::new(name).unwrap();
472                 llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(),
473                                       name.as_ptr())
474             }
475         }
476     }
477
478     pub fn free(&self, ptr: ValueRef) {
479         self.count_insn("free");
480         unsafe {
481             llvm::LLVMBuildFree(self.llbuilder, ptr);
482         }
483     }
484
485     pub fn load(&self, ptr: ValueRef) -> ValueRef {
486         self.count_insn("load");
487         unsafe {
488             llvm::LLVMBuildLoad(self.llbuilder, ptr, noname())
489         }
490     }
491
492     pub fn volatile_load(&self, ptr: ValueRef) -> ValueRef {
493         self.count_insn("load.volatile");
494         unsafe {
495             let insn = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
496             llvm::LLVMSetVolatile(insn, llvm::True);
497             insn
498         }
499     }
500
501     pub fn atomic_load(&self, ptr: ValueRef, order: AtomicOrdering) -> ValueRef {
502         self.count_insn("load.atomic");
503         unsafe {
504             let ty = Type::from_ref(llvm::LLVMTypeOf(ptr));
505             let align = llalign_of_pref(self.ccx, ty.element_type());
506             llvm::LLVMBuildAtomicLoad(self.llbuilder, ptr, noname(), order,
507                                       align as c_uint)
508         }
509     }
510
511
512     pub fn load_range_assert(&self, ptr: ValueRef, lo: u64,
513                              hi: u64, signed: llvm::Bool) -> ValueRef {
514         let value = self.load(ptr);
515
516         unsafe {
517             let t = llvm::LLVMGetElementType(llvm::LLVMTypeOf(ptr));
518             let min = llvm::LLVMConstInt(t, lo, signed);
519             let max = llvm::LLVMConstInt(t, hi, signed);
520
521             let v = [min, max];
522
523             llvm::LLVMSetMetadata(value, llvm::MD_range as c_uint,
524                                   llvm::LLVMMDNodeInContext(self.ccx.llcx(),
525                                                             v.as_ptr(),
526                                                             v.len() as c_uint));
527         }
528
529         value
530     }
531
532     pub fn load_nonnull(&self, ptr: ValueRef) -> ValueRef {
533         let value = self.load(ptr);
534         unsafe {
535             llvm::LLVMSetMetadata(value, llvm::MD_nonnull as c_uint,
536                                   llvm::LLVMMDNodeInContext(self.ccx.llcx(), ptr::null(), 0));
537         }
538
539         value
540     }
541
542     pub fn store(&self, val: ValueRef, ptr: ValueRef) -> ValueRef {
543         debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
544         assert!(!self.llbuilder.is_null());
545         self.count_insn("store");
546         unsafe {
547             llvm::LLVMBuildStore(self.llbuilder, val, ptr)
548         }
549     }
550
551     pub fn volatile_store(&self, val: ValueRef, ptr: ValueRef) -> ValueRef {
552         debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
553         assert!(!self.llbuilder.is_null());
554         self.count_insn("store.volatile");
555         unsafe {
556             let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
557             llvm::LLVMSetVolatile(insn, llvm::True);
558             insn
559         }
560     }
561
562     pub fn atomic_store(&self, val: ValueRef, ptr: ValueRef, order: AtomicOrdering) {
563         debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
564         self.count_insn("store.atomic");
565         unsafe {
566             let ty = Type::from_ref(llvm::LLVMTypeOf(ptr));
567             let align = llalign_of_pref(self.ccx, ty.element_type());
568             llvm::LLVMBuildAtomicStore(self.llbuilder, val, ptr, order, align as c_uint);
569         }
570     }
571
572     pub fn gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef {
573         self.count_insn("gep");
574         unsafe {
575             llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(),
576                                indices.len() as c_uint, noname())
577         }
578     }
579
580     // Simple wrapper around GEP that takes an array of ints and wraps them
581     // in C_i32()
582     #[inline]
583     pub fn gepi(&self, base: ValueRef, ixs: &[usize]) -> ValueRef {
584         // Small vector optimization. This should catch 100% of the cases that
585         // we care about.
586         if ixs.len() < 16 {
587             let mut small_vec = [ C_i32(self.ccx, 0); 16 ];
588             for (small_vec_e, &ix) in small_vec.iter_mut().zip(ixs) {
589                 *small_vec_e = C_i32(self.ccx, ix as i32);
590             }
591             self.inbounds_gep(base, &small_vec[..ixs.len()])
592         } else {
593             let v = ixs.iter().map(|i| C_i32(self.ccx, *i as i32)).collect::<Vec<ValueRef>>();
594             self.count_insn("gepi");
595             self.inbounds_gep(base, &v[..])
596         }
597     }
598
599     pub fn inbounds_gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef {
600         self.count_insn("inboundsgep");
601         unsafe {
602             llvm::LLVMBuildInBoundsGEP(
603                 self.llbuilder, ptr, indices.as_ptr(), indices.len() as c_uint, noname())
604         }
605     }
606
607     pub fn struct_gep(&self, ptr: ValueRef, idx: usize) -> ValueRef {
608         self.count_insn("structgep");
609         unsafe {
610             llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname())
611         }
612     }
613
614     pub fn global_string(&self, _str: *const c_char) -> ValueRef {
615         self.count_insn("globalstring");
616         unsafe {
617             llvm::LLVMBuildGlobalString(self.llbuilder, _str, noname())
618         }
619     }
620
621     pub fn global_string_ptr(&self, _str: *const c_char) -> ValueRef {
622         self.count_insn("globalstringptr");
623         unsafe {
624             llvm::LLVMBuildGlobalStringPtr(self.llbuilder, _str, noname())
625         }
626     }
627
628     /* Casts */
629     pub fn trunc(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
630         self.count_insn("trunc");
631         unsafe {
632             llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty.to_ref(), noname())
633         }
634     }
635
636     pub fn zext(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
637         self.count_insn("zext");
638         unsafe {
639             llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty.to_ref(), noname())
640         }
641     }
642
643     pub fn sext(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
644         self.count_insn("sext");
645         unsafe {
646             llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty.to_ref(), noname())
647         }
648     }
649
650     pub fn fptoui(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
651         self.count_insn("fptoui");
652         unsafe {
653             llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty.to_ref(), noname())
654         }
655     }
656
657     pub fn fptosi(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
658         self.count_insn("fptosi");
659         unsafe {
660             llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty.to_ref(),noname())
661         }
662     }
663
664     pub fn uitofp(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
665         self.count_insn("uitofp");
666         unsafe {
667             llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty.to_ref(), noname())
668         }
669     }
670
671     pub fn sitofp(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
672         self.count_insn("sitofp");
673         unsafe {
674             llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty.to_ref(), noname())
675         }
676     }
677
678     pub fn fptrunc(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
679         self.count_insn("fptrunc");
680         unsafe {
681             llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty.to_ref(), noname())
682         }
683     }
684
685     pub fn fpext(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
686         self.count_insn("fpext");
687         unsafe {
688             llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty.to_ref(), noname())
689         }
690     }
691
692     pub fn ptrtoint(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
693         self.count_insn("ptrtoint");
694         unsafe {
695             llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty.to_ref(), noname())
696         }
697     }
698
699     pub fn inttoptr(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
700         self.count_insn("inttoptr");
701         unsafe {
702             llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty.to_ref(), noname())
703         }
704     }
705
706     pub fn bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
707         self.count_insn("bitcast");
708         unsafe {
709             llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
710         }
711     }
712
713     pub fn zext_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
714         self.count_insn("zextorbitcast");
715         unsafe {
716             llvm::LLVMBuildZExtOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
717         }
718     }
719
720     pub fn sext_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
721         self.count_insn("sextorbitcast");
722         unsafe {
723             llvm::LLVMBuildSExtOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
724         }
725     }
726
727     pub fn trunc_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
728         self.count_insn("truncorbitcast");
729         unsafe {
730             llvm::LLVMBuildTruncOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
731         }
732     }
733
734     pub fn cast(&self, op: Opcode, val: ValueRef, dest_ty: Type) -> ValueRef {
735         self.count_insn("cast");
736         unsafe {
737             llvm::LLVMBuildCast(self.llbuilder, op, val, dest_ty.to_ref(), noname())
738         }
739     }
740
741     pub fn pointercast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
742         self.count_insn("pointercast");
743         unsafe {
744             llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty.to_ref(), noname())
745         }
746     }
747
748     pub fn intcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
749         self.count_insn("intcast");
750         unsafe {
751             llvm::LLVMBuildIntCast(self.llbuilder, val, dest_ty.to_ref(), noname())
752         }
753     }
754
755     pub fn fpcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
756         self.count_insn("fpcast");
757         unsafe {
758             llvm::LLVMBuildFPCast(self.llbuilder, val, dest_ty.to_ref(), noname())
759         }
760     }
761
762
763     /* Comparisons */
764     pub fn icmp(&self, op: IntPredicate, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
765         self.count_insn("icmp");
766         unsafe {
767             llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
768         }
769     }
770
771     pub fn fcmp(&self, op: RealPredicate, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
772         self.count_insn("fcmp");
773         unsafe {
774             llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
775         }
776     }
777
778     /* Miscellaneous instructions */
779     pub fn empty_phi(&self, ty: Type) -> ValueRef {
780         self.count_insn("emptyphi");
781         unsafe {
782             llvm::LLVMBuildPhi(self.llbuilder, ty.to_ref(), noname())
783         }
784     }
785
786     pub fn phi(&self, ty: Type, vals: &[ValueRef], bbs: &[BasicBlockRef]) -> ValueRef {
787         assert_eq!(vals.len(), bbs.len());
788         let phi = self.empty_phi(ty);
789         self.count_insn("addincoming");
790         unsafe {
791             llvm::LLVMAddIncoming(phi, vals.as_ptr(),
792                                   bbs.as_ptr(),
793                                   vals.len() as c_uint);
794             phi
795         }
796     }
797
798     pub fn add_span_comment(&self, sp: Span, text: &str) {
799         if self.ccx.sess().asm_comments() {
800             let s = format!("{} ({})",
801                             text,
802                             self.ccx.sess().codemap().span_to_string(sp));
803             debug!("{}", &s[..]);
804             self.add_comment(&s[..]);
805         }
806     }
807
808     pub fn add_comment(&self, text: &str) {
809         if self.ccx.sess().asm_comments() {
810             let sanitized = text.replace("$", "");
811             let comment_text = format!("{} {}", "#",
812                                        sanitized.replace("\n", "\n\t# "));
813             self.count_insn("inlineasm");
814             let comment_text = CString::new(comment_text).unwrap();
815             let asm = unsafe {
816                 llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(),
817                                          comment_text.as_ptr(), noname(), False,
818                                          False)
819             };
820             self.call(asm, &[], None);
821         }
822     }
823
824     pub fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char,
825                          inputs: &[ValueRef], output: Type,
826                          volatile: bool, alignstack: bool,
827                          dia: AsmDialect) -> ValueRef {
828         self.count_insn("inlineasm");
829
830         let volatile = if volatile { llvm::True }
831                        else        { llvm::False };
832         let alignstack = if alignstack { llvm::True }
833                          else          { llvm::False };
834
835         let argtys = inputs.iter().map(|v| {
836             debug!("Asm Input Type: {:?}", Value(*v));
837             val_ty(*v)
838         }).collect::<Vec<_>>();
839
840         debug!("Asm Output Type: {:?}", output);
841         let fty = Type::func(&argtys[..], &output);
842         unsafe {
843             let v = llvm::LLVMInlineAsm(
844                 fty.to_ref(), asm, cons, volatile, alignstack, dia as c_uint);
845             self.call(v, inputs, None)
846         }
847     }
848
849     pub fn call(&self, llfn: ValueRef, args: &[ValueRef],
850                 bundle: Option<&OperandBundleDef>) -> ValueRef {
851         self.count_insn("call");
852
853         debug!("Call {:?} with args ({})",
854                Value(llfn),
855                args.iter()
856                    .map(|&v| format!("{:?}", Value(v)))
857                    .collect::<Vec<String>>()
858                    .join(", "));
859
860         check_call("call", llfn, args);
861
862         let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
863
864         unsafe {
865             llvm::LLVMRustBuildCall(self.llbuilder, llfn, args.as_ptr(),
866                                     args.len() as c_uint, bundle, noname())
867         }
868     }
869
870     pub fn select(&self, cond: ValueRef, then_val: ValueRef, else_val: ValueRef) -> ValueRef {
871         self.count_insn("select");
872         unsafe {
873             llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname())
874         }
875     }
876
877     pub fn va_arg(&self, list: ValueRef, ty: Type) -> ValueRef {
878         self.count_insn("vaarg");
879         unsafe {
880             llvm::LLVMBuildVAArg(self.llbuilder, list, ty.to_ref(), noname())
881         }
882     }
883
884     pub fn extract_element(&self, vec: ValueRef, idx: ValueRef) -> ValueRef {
885         self.count_insn("extractelement");
886         unsafe {
887             llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname())
888         }
889     }
890
891     pub fn insert_element(&self, vec: ValueRef, elt: ValueRef, idx: ValueRef) -> ValueRef {
892         self.count_insn("insertelement");
893         unsafe {
894             llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname())
895         }
896     }
897
898     pub fn shuffle_vector(&self, v1: ValueRef, v2: ValueRef, mask: ValueRef) -> ValueRef {
899         self.count_insn("shufflevector");
900         unsafe {
901             llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname())
902         }
903     }
904
905     pub fn vector_splat(&self, num_elts: usize, elt: ValueRef) -> ValueRef {
906         unsafe {
907             let elt_ty = val_ty(elt);
908             let undef = llvm::LLVMGetUndef(Type::vector(&elt_ty, num_elts as u64).to_ref());
909             let vec = self.insert_element(undef, elt, C_i32(self.ccx, 0));
910             let vec_i32_ty = Type::vector(&Type::i32(self.ccx), num_elts as u64);
911             self.shuffle_vector(vec, undef, C_null(vec_i32_ty))
912         }
913     }
914
915     pub fn extract_value(&self, agg_val: ValueRef, idx: usize) -> ValueRef {
916         self.count_insn("extractvalue");
917         unsafe {
918             llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, noname())
919         }
920     }
921
922     pub fn insert_value(&self, agg_val: ValueRef, elt: ValueRef,
923                        idx: usize) -> ValueRef {
924         self.count_insn("insertvalue");
925         unsafe {
926             llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint,
927                                        noname())
928         }
929     }
930
931     pub fn is_null(&self, val: ValueRef) -> ValueRef {
932         self.count_insn("isnull");
933         unsafe {
934             llvm::LLVMBuildIsNull(self.llbuilder, val, noname())
935         }
936     }
937
938     pub fn is_not_null(&self, val: ValueRef) -> ValueRef {
939         self.count_insn("isnotnull");
940         unsafe {
941             llvm::LLVMBuildIsNotNull(self.llbuilder, val, noname())
942         }
943     }
944
945     pub fn ptrdiff(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
946         self.count_insn("ptrdiff");
947         unsafe {
948             llvm::LLVMBuildPtrDiff(self.llbuilder, lhs, rhs, noname())
949         }
950     }
951
952     pub fn trap(&self) {
953         unsafe {
954             let bb: BasicBlockRef = llvm::LLVMGetInsertBlock(self.llbuilder);
955             let fn_: ValueRef = llvm::LLVMGetBasicBlockParent(bb);
956             let m: ModuleRef = llvm::LLVMGetGlobalParent(fn_);
957             let p = "llvm.trap\0".as_ptr();
958             let t: ValueRef = llvm::LLVMGetNamedFunction(m, p as *const _);
959             assert!((t as isize != 0));
960             let args: &[ValueRef] = &[];
961             self.count_insn("trap");
962             llvm::LLVMRustBuildCall(self.llbuilder, t,
963                                     args.as_ptr(), args.len() as c_uint,
964                                     ptr::null_mut(),
965                                     noname());
966         }
967     }
968
969     pub fn landing_pad(&self, ty: Type, pers_fn: ValueRef,
970                        num_clauses: usize,
971                        llfn: ValueRef) -> ValueRef {
972         self.count_insn("landingpad");
973         unsafe {
974             llvm::LLVMRustBuildLandingPad(self.llbuilder, ty.to_ref(), pers_fn,
975                                           num_clauses as c_uint, noname(), llfn)
976         }
977     }
978
979     pub fn add_clause(&self, landing_pad: ValueRef, clause: ValueRef) {
980         unsafe {
981             llvm::LLVMAddClause(landing_pad, clause);
982         }
983     }
984
985     pub fn set_cleanup(&self, landing_pad: ValueRef) {
986         self.count_insn("setcleanup");
987         unsafe {
988             llvm::LLVMSetCleanup(landing_pad, llvm::True);
989         }
990     }
991
992     pub fn resume(&self, exn: ValueRef) -> ValueRef {
993         self.count_insn("resume");
994         unsafe {
995             llvm::LLVMBuildResume(self.llbuilder, exn)
996         }
997     }
998
999     pub fn cleanup_pad(&self,
1000                        parent: Option<ValueRef>,
1001                        args: &[ValueRef]) -> ValueRef {
1002         self.count_insn("cleanuppad");
1003         let parent = parent.unwrap_or(ptr::null_mut());
1004         let name = CString::new("cleanuppad").unwrap();
1005         let ret = unsafe {
1006             llvm::LLVMRustBuildCleanupPad(self.llbuilder,
1007                                           parent,
1008                                           args.len() as c_uint,
1009                                           args.as_ptr(),
1010                                           name.as_ptr())
1011         };
1012         assert!(!ret.is_null(), "LLVM does not have support for cleanuppad");
1013         return ret
1014     }
1015
1016     pub fn cleanup_ret(&self, cleanup: ValueRef,
1017                        unwind: Option<BasicBlockRef>) -> ValueRef {
1018         self.count_insn("cleanupret");
1019         let unwind = unwind.unwrap_or(ptr::null_mut());
1020         let ret = unsafe {
1021             llvm::LLVMRustBuildCleanupRet(self.llbuilder, cleanup, unwind)
1022         };
1023         assert!(!ret.is_null(), "LLVM does not have support for cleanupret");
1024         return ret
1025     }
1026
1027     pub fn catch_pad(&self,
1028                      parent: ValueRef,
1029                      args: &[ValueRef]) -> ValueRef {
1030         self.count_insn("catchpad");
1031         let name = CString::new("catchpad").unwrap();
1032         let ret = unsafe {
1033             llvm::LLVMRustBuildCatchPad(self.llbuilder, parent,
1034                                         args.len() as c_uint, args.as_ptr(),
1035                                         name.as_ptr())
1036         };
1037         assert!(!ret.is_null(), "LLVM does not have support for catchpad");
1038         return ret
1039     }
1040
1041     pub fn catch_ret(&self, pad: ValueRef, unwind: BasicBlockRef) -> ValueRef {
1042         self.count_insn("catchret");
1043         let ret = unsafe {
1044             llvm::LLVMRustBuildCatchRet(self.llbuilder, pad, unwind)
1045         };
1046         assert!(!ret.is_null(), "LLVM does not have support for catchret");
1047         return ret
1048     }
1049
1050     pub fn catch_switch(&self,
1051                         parent: Option<ValueRef>,
1052                         unwind: Option<BasicBlockRef>,
1053                         num_handlers: usize) -> ValueRef {
1054         self.count_insn("catchswitch");
1055         let parent = parent.unwrap_or(ptr::null_mut());
1056         let unwind = unwind.unwrap_or(ptr::null_mut());
1057         let name = CString::new("catchswitch").unwrap();
1058         let ret = unsafe {
1059             llvm::LLVMRustBuildCatchSwitch(self.llbuilder, parent, unwind,
1060                                            num_handlers as c_uint,
1061                                            name.as_ptr())
1062         };
1063         assert!(!ret.is_null(), "LLVM does not have support for catchswitch");
1064         return ret
1065     }
1066
1067     pub fn add_handler(&self, catch_switch: ValueRef, handler: BasicBlockRef) {
1068         unsafe {
1069             llvm::LLVMRustAddHandler(catch_switch, handler);
1070         }
1071     }
1072
1073     pub fn set_personality_fn(&self, personality: ValueRef) {
1074         unsafe {
1075             llvm::LLVMRustSetPersonalityFn(self.llbuilder, personality);
1076         }
1077     }
1078
1079     // Atomic Operations
1080     pub fn atomic_cmpxchg(&self, dst: ValueRef,
1081                          cmp: ValueRef, src: ValueRef,
1082                          order: AtomicOrdering,
1083                          failure_order: AtomicOrdering,
1084                          weak: llvm::Bool) -> ValueRef {
1085         unsafe {
1086             llvm::LLVMBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src,
1087                                          order, failure_order, weak)
1088         }
1089     }
1090     pub fn atomic_rmw(&self, op: AtomicBinOp,
1091                      dst: ValueRef, src: ValueRef,
1092                      order: AtomicOrdering) -> ValueRef {
1093         unsafe {
1094             llvm::LLVMBuildAtomicRMW(self.llbuilder, op, dst, src, order, False)
1095         }
1096     }
1097
1098     pub fn atomic_fence(&self, order: AtomicOrdering, scope: SynchronizationScope) {
1099         unsafe {
1100             llvm::LLVMBuildAtomicFence(self.llbuilder, order, scope);
1101         }
1102     }
1103 }
1104
1105 fn check_call(typ: &str, llfn: ValueRef, args: &[ValueRef]) {
1106     if cfg!(debug_assertions) {
1107         let mut fn_ty = val_ty(llfn);
1108         // Strip off pointers
1109         while fn_ty.kind() == llvm::TypeKind::Pointer {
1110             fn_ty = fn_ty.element_type();
1111         }
1112
1113         assert!(fn_ty.kind() == llvm::TypeKind::Function,
1114                 "builder::{} not passed a function", typ);
1115
1116         let param_tys = fn_ty.func_params();
1117
1118         let iter = param_tys.into_iter()
1119             .zip(args.iter().map(|&v| val_ty(v)));
1120         for (i, (expected_ty, actual_ty)) in iter.enumerate() {
1121             if expected_ty != actual_ty {
1122                 bug!("Type mismatch in function call of {:?}. \
1123                       Expected {:?} for param {}, got {:?}",
1124                      Value(llfn),
1125                      expected_ty, i, actual_ty);
1126
1127             }
1128         }
1129     }
1130 }