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