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