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