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