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