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