]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/builder.rs
Rollup merge of #39604 - est31:i128_tests, r=alexcrichton
[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) -> 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)
486     }
487
488     pub fn dynamic_alloca(&self, ty: Type, name: &str) -> ValueRef {
489         self.count_insn("alloca");
490         unsafe {
491             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         }
499     }
500
501     pub fn free(&self, ptr: ValueRef) {
502         self.count_insn("free");
503         unsafe {
504             llvm::LLVMBuildFree(self.llbuilder, ptr);
505         }
506     }
507
508     pub fn load(&self, ptr: ValueRef, align: Option<u32>) -> ValueRef {
509         self.count_insn("load");
510         unsafe {
511             let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
512             if let Some(align) = align {
513                 llvm::LLVMSetAlignment(load, align as c_uint);
514             }
515             load
516         }
517     }
518
519     pub fn volatile_load(&self, ptr: ValueRef) -> ValueRef {
520         self.count_insn("load.volatile");
521         unsafe {
522             let insn = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
523             llvm::LLVMSetVolatile(insn, llvm::True);
524             insn
525         }
526     }
527
528     pub fn atomic_load(&self, ptr: ValueRef, order: AtomicOrdering) -> ValueRef {
529         self.count_insn("load.atomic");
530         unsafe {
531             let ty = Type::from_ref(llvm::LLVMTypeOf(ptr));
532             let align = llalign_of_pref(self.ccx, ty.element_type());
533             llvm::LLVMRustBuildAtomicLoad(self.llbuilder, ptr, noname(), order,
534                                           align as c_uint)
535         }
536     }
537
538
539     pub fn load_range_assert(&self, ptr: ValueRef, lo: u64,
540                              hi: u64, signed: llvm::Bool,
541                              align: Option<u32>) -> ValueRef {
542         let value = self.load(ptr, align);
543
544         unsafe {
545             let t = llvm::LLVMGetElementType(llvm::LLVMTypeOf(ptr));
546             let min = llvm::LLVMConstInt(t, lo, signed);
547             let max = llvm::LLVMConstInt(t, hi, signed);
548
549             let v = [min, max];
550
551             llvm::LLVMSetMetadata(value, llvm::MD_range as c_uint,
552                                   llvm::LLVMMDNodeInContext(self.ccx.llcx(),
553                                                             v.as_ptr(),
554                                                             v.len() as c_uint));
555         }
556
557         value
558     }
559
560     pub fn load_nonnull(&self, ptr: ValueRef, align: Option<u32>) -> ValueRef {
561         let value = self.load(ptr, align);
562         unsafe {
563             llvm::LLVMSetMetadata(value, llvm::MD_nonnull as c_uint,
564                                   llvm::LLVMMDNodeInContext(self.ccx.llcx(), ptr::null(), 0));
565         }
566
567         value
568     }
569
570     pub fn store(&self, val: ValueRef, ptr: ValueRef, align: Option<u32>) -> ValueRef {
571         debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
572         assert!(!self.llbuilder.is_null());
573         self.count_insn("store");
574         let ptr = self.check_store(val, ptr);
575         unsafe {
576             let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
577             if let Some(align) = align {
578                 llvm::LLVMSetAlignment(store, align as c_uint);
579             }
580             store
581         }
582     }
583
584     pub fn volatile_store(&self, val: ValueRef, ptr: ValueRef) -> ValueRef {
585         debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
586         assert!(!self.llbuilder.is_null());
587         self.count_insn("store.volatile");
588         let ptr = self.check_store(val, ptr);
589         unsafe {
590             let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
591             llvm::LLVMSetVolatile(insn, llvm::True);
592             insn
593         }
594     }
595
596     pub fn atomic_store(&self, val: ValueRef, ptr: ValueRef, order: AtomicOrdering) {
597         debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
598         self.count_insn("store.atomic");
599         let ptr = self.check_store(val, ptr);
600         unsafe {
601             let ty = Type::from_ref(llvm::LLVMTypeOf(ptr));
602             let align = llalign_of_pref(self.ccx, ty.element_type());
603             llvm::LLVMRustBuildAtomicStore(self.llbuilder, val, ptr, order, align as c_uint);
604         }
605     }
606
607     pub fn gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef {
608         self.count_insn("gep");
609         unsafe {
610             llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(),
611                                indices.len() as c_uint, noname())
612         }
613     }
614
615     // Simple wrapper around GEP that takes an array of ints and wraps them
616     // in C_i32()
617     #[inline]
618     pub fn gepi(&self, base: ValueRef, ixs: &[usize]) -> ValueRef {
619         // Small vector optimization. This should catch 100% of the cases that
620         // we care about.
621         if ixs.len() < 16 {
622             let mut small_vec = [ C_i32(self.ccx, 0); 16 ];
623             for (small_vec_e, &ix) in small_vec.iter_mut().zip(ixs) {
624                 *small_vec_e = C_i32(self.ccx, ix as i32);
625             }
626             self.inbounds_gep(base, &small_vec[..ixs.len()])
627         } else {
628             let v = ixs.iter().map(|i| C_i32(self.ccx, *i as i32)).collect::<Vec<ValueRef>>();
629             self.count_insn("gepi");
630             self.inbounds_gep(base, &v[..])
631         }
632     }
633
634     pub fn inbounds_gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef {
635         self.count_insn("inboundsgep");
636         unsafe {
637             llvm::LLVMBuildInBoundsGEP(
638                 self.llbuilder, ptr, indices.as_ptr(), indices.len() as c_uint, noname())
639         }
640     }
641
642     pub fn struct_gep(&self, ptr: ValueRef, idx: usize) -> ValueRef {
643         self.count_insn("structgep");
644         unsafe {
645             llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname())
646         }
647     }
648
649     pub fn global_string(&self, _str: *const c_char) -> ValueRef {
650         self.count_insn("globalstring");
651         unsafe {
652             llvm::LLVMBuildGlobalString(self.llbuilder, _str, noname())
653         }
654     }
655
656     pub fn global_string_ptr(&self, _str: *const c_char) -> ValueRef {
657         self.count_insn("globalstringptr");
658         unsafe {
659             llvm::LLVMBuildGlobalStringPtr(self.llbuilder, _str, noname())
660         }
661     }
662
663     /* Casts */
664     pub fn trunc(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
665         self.count_insn("trunc");
666         unsafe {
667             llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty.to_ref(), noname())
668         }
669     }
670
671     pub fn zext(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
672         self.count_insn("zext");
673         unsafe {
674             llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty.to_ref(), noname())
675         }
676     }
677
678     pub fn sext(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
679         self.count_insn("sext");
680         unsafe {
681             llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty.to_ref(), noname())
682         }
683     }
684
685     pub fn fptoui(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
686         self.count_insn("fptoui");
687         unsafe {
688             llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty.to_ref(), noname())
689         }
690     }
691
692     pub fn fptosi(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
693         self.count_insn("fptosi");
694         unsafe {
695             llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty.to_ref(),noname())
696         }
697     }
698
699     pub fn uitofp(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
700         self.count_insn("uitofp");
701         unsafe {
702             llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty.to_ref(), noname())
703         }
704     }
705
706     pub fn sitofp(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
707         self.count_insn("sitofp");
708         unsafe {
709             llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty.to_ref(), noname())
710         }
711     }
712
713     pub fn fptrunc(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
714         self.count_insn("fptrunc");
715         unsafe {
716             llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty.to_ref(), noname())
717         }
718     }
719
720     pub fn fpext(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
721         self.count_insn("fpext");
722         unsafe {
723             llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty.to_ref(), noname())
724         }
725     }
726
727     pub fn ptrtoint(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
728         self.count_insn("ptrtoint");
729         unsafe {
730             llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty.to_ref(), noname())
731         }
732     }
733
734     pub fn inttoptr(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
735         self.count_insn("inttoptr");
736         unsafe {
737             llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty.to_ref(), noname())
738         }
739     }
740
741     pub fn bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
742         self.count_insn("bitcast");
743         unsafe {
744             llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
745         }
746     }
747
748     pub fn zext_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
749         self.count_insn("zextorbitcast");
750         unsafe {
751             llvm::LLVMBuildZExtOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
752         }
753     }
754
755     pub fn sext_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
756         self.count_insn("sextorbitcast");
757         unsafe {
758             llvm::LLVMBuildSExtOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
759         }
760     }
761
762     pub fn trunc_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
763         self.count_insn("truncorbitcast");
764         unsafe {
765             llvm::LLVMBuildTruncOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname())
766         }
767     }
768
769     pub fn cast(&self, op: Opcode, val: ValueRef, dest_ty: Type) -> ValueRef {
770         self.count_insn("cast");
771         unsafe {
772             llvm::LLVMBuildCast(self.llbuilder, op, val, dest_ty.to_ref(), noname())
773         }
774     }
775
776     pub fn pointercast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
777         self.count_insn("pointercast");
778         unsafe {
779             llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty.to_ref(), noname())
780         }
781     }
782
783     pub fn intcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
784         self.count_insn("intcast");
785         unsafe {
786             llvm::LLVMBuildIntCast(self.llbuilder, val, dest_ty.to_ref(), noname())
787         }
788     }
789
790     pub fn fpcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef {
791         self.count_insn("fpcast");
792         unsafe {
793             llvm::LLVMBuildFPCast(self.llbuilder, val, dest_ty.to_ref(), noname())
794         }
795     }
796
797
798     /* Comparisons */
799     pub fn icmp(&self, op: IntPredicate, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
800         self.count_insn("icmp");
801         unsafe {
802             llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
803         }
804     }
805
806     pub fn fcmp(&self, op: RealPredicate, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
807         self.count_insn("fcmp");
808         unsafe {
809             llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
810         }
811     }
812
813     /* Miscellaneous instructions */
814     pub fn empty_phi(&self, ty: Type) -> ValueRef {
815         self.count_insn("emptyphi");
816         unsafe {
817             llvm::LLVMBuildPhi(self.llbuilder, ty.to_ref(), noname())
818         }
819     }
820
821     pub fn phi(&self, ty: Type, vals: &[ValueRef], bbs: &[BasicBlockRef]) -> ValueRef {
822         assert_eq!(vals.len(), bbs.len());
823         let phi = self.empty_phi(ty);
824         self.count_insn("addincoming");
825         unsafe {
826             llvm::LLVMAddIncoming(phi, vals.as_ptr(),
827                                   bbs.as_ptr(),
828                                   vals.len() as c_uint);
829             phi
830         }
831     }
832
833     pub fn add_span_comment(&self, sp: Span, text: &str) {
834         if self.ccx.sess().asm_comments() {
835             let s = format!("{} ({})",
836                             text,
837                             self.ccx.sess().codemap().span_to_string(sp));
838             debug!("{}", &s[..]);
839             self.add_comment(&s[..]);
840         }
841     }
842
843     pub fn add_comment(&self, text: &str) {
844         if self.ccx.sess().asm_comments() {
845             let sanitized = text.replace("$", "");
846             let comment_text = format!("{} {}", "#",
847                                        sanitized.replace("\n", "\n\t# "));
848             self.count_insn("inlineasm");
849             let comment_text = CString::new(comment_text).unwrap();
850             let asm = unsafe {
851                 llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(),
852                                          comment_text.as_ptr(), noname(), False,
853                                          False)
854             };
855             self.call(asm, &[], None);
856         }
857     }
858
859     pub fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char,
860                          inputs: &[ValueRef], output: Type,
861                          volatile: bool, alignstack: bool,
862                          dia: AsmDialect) -> ValueRef {
863         self.count_insn("inlineasm");
864
865         let volatile = if volatile { llvm::True }
866                        else        { llvm::False };
867         let alignstack = if alignstack { llvm::True }
868                          else          { llvm::False };
869
870         let argtys = inputs.iter().map(|v| {
871             debug!("Asm Input Type: {:?}", Value(*v));
872             val_ty(*v)
873         }).collect::<Vec<_>>();
874
875         debug!("Asm Output Type: {:?}", output);
876         let fty = Type::func(&argtys[..], &output);
877         unsafe {
878             let v = llvm::LLVMRustInlineAsm(
879                 fty.to_ref(), asm, cons, volatile, alignstack, dia);
880             self.call(v, inputs, None)
881         }
882     }
883
884     pub fn call(&self, llfn: ValueRef, args: &[ValueRef],
885                 bundle: Option<&OperandBundleDef>) -> ValueRef {
886         self.count_insn("call");
887
888         debug!("Call {:?} with args ({})",
889                Value(llfn),
890                args.iter()
891                    .map(|&v| format!("{:?}", Value(v)))
892                    .collect::<Vec<String>>()
893                    .join(", "));
894
895         let args = self.check_call("call", llfn, args);
896         let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
897
898         unsafe {
899             llvm::LLVMRustBuildCall(self.llbuilder, llfn, args.as_ptr(),
900                                     args.len() as c_uint, bundle, noname())
901         }
902     }
903
904     pub fn select(&self, cond: ValueRef, then_val: ValueRef, else_val: ValueRef) -> ValueRef {
905         self.count_insn("select");
906         unsafe {
907             llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname())
908         }
909     }
910
911     pub fn va_arg(&self, list: ValueRef, ty: Type) -> ValueRef {
912         self.count_insn("vaarg");
913         unsafe {
914             llvm::LLVMBuildVAArg(self.llbuilder, list, ty.to_ref(), noname())
915         }
916     }
917
918     pub fn extract_element(&self, vec: ValueRef, idx: ValueRef) -> ValueRef {
919         self.count_insn("extractelement");
920         unsafe {
921             llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname())
922         }
923     }
924
925     pub fn insert_element(&self, vec: ValueRef, elt: ValueRef, idx: ValueRef) -> ValueRef {
926         self.count_insn("insertelement");
927         unsafe {
928             llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname())
929         }
930     }
931
932     pub fn shuffle_vector(&self, v1: ValueRef, v2: ValueRef, mask: ValueRef) -> ValueRef {
933         self.count_insn("shufflevector");
934         unsafe {
935             llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname())
936         }
937     }
938
939     pub fn vector_splat(&self, num_elts: usize, elt: ValueRef) -> ValueRef {
940         unsafe {
941             let elt_ty = val_ty(elt);
942             let undef = llvm::LLVMGetUndef(Type::vector(&elt_ty, num_elts as u64).to_ref());
943             let vec = self.insert_element(undef, elt, C_i32(self.ccx, 0));
944             let vec_i32_ty = Type::vector(&Type::i32(self.ccx), num_elts as u64);
945             self.shuffle_vector(vec, undef, C_null(vec_i32_ty))
946         }
947     }
948
949     pub fn extract_value(&self, agg_val: ValueRef, idx: usize) -> ValueRef {
950         self.count_insn("extractvalue");
951         unsafe {
952             llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, noname())
953         }
954     }
955
956     pub fn insert_value(&self, agg_val: ValueRef, elt: ValueRef,
957                        idx: usize) -> ValueRef {
958         self.count_insn("insertvalue");
959         unsafe {
960             llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint,
961                                        noname())
962         }
963     }
964
965     pub fn is_null(&self, val: ValueRef) -> ValueRef {
966         self.count_insn("isnull");
967         unsafe {
968             llvm::LLVMBuildIsNull(self.llbuilder, val, noname())
969         }
970     }
971
972     pub fn is_not_null(&self, val: ValueRef) -> ValueRef {
973         self.count_insn("isnotnull");
974         unsafe {
975             llvm::LLVMBuildIsNotNull(self.llbuilder, val, noname())
976         }
977     }
978
979     pub fn ptrdiff(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
980         self.count_insn("ptrdiff");
981         unsafe {
982             llvm::LLVMBuildPtrDiff(self.llbuilder, lhs, rhs, noname())
983         }
984     }
985
986     pub fn trap(&self) {
987         unsafe {
988             let bb: BasicBlockRef = llvm::LLVMGetInsertBlock(self.llbuilder);
989             let fn_: ValueRef = llvm::LLVMGetBasicBlockParent(bb);
990             let m: ModuleRef = llvm::LLVMGetGlobalParent(fn_);
991             let p = "llvm.trap\0".as_ptr();
992             let t: ValueRef = llvm::LLVMGetNamedFunction(m, p as *const _);
993             assert!((t as isize != 0));
994             let args: &[ValueRef] = &[];
995             self.count_insn("trap");
996             llvm::LLVMRustBuildCall(self.llbuilder, t,
997                                     args.as_ptr(), args.len() as c_uint,
998                                     ptr::null_mut(),
999                                     noname());
1000         }
1001     }
1002
1003     pub fn landing_pad(&self, ty: Type, pers_fn: ValueRef,
1004                        num_clauses: usize,
1005                        llfn: ValueRef) -> ValueRef {
1006         self.count_insn("landingpad");
1007         unsafe {
1008             llvm::LLVMRustBuildLandingPad(self.llbuilder, ty.to_ref(), pers_fn,
1009                                           num_clauses as c_uint, noname(), llfn)
1010         }
1011     }
1012
1013     pub fn add_clause(&self, landing_pad: ValueRef, clause: ValueRef) {
1014         unsafe {
1015             llvm::LLVMAddClause(landing_pad, clause);
1016         }
1017     }
1018
1019     pub fn set_cleanup(&self, landing_pad: ValueRef) {
1020         self.count_insn("setcleanup");
1021         unsafe {
1022             llvm::LLVMSetCleanup(landing_pad, llvm::True);
1023         }
1024     }
1025
1026     pub fn resume(&self, exn: ValueRef) -> ValueRef {
1027         self.count_insn("resume");
1028         unsafe {
1029             llvm::LLVMBuildResume(self.llbuilder, exn)
1030         }
1031     }
1032
1033     pub fn cleanup_pad(&self,
1034                        parent: Option<ValueRef>,
1035                        args: &[ValueRef]) -> ValueRef {
1036         self.count_insn("cleanuppad");
1037         let parent = parent.unwrap_or(ptr::null_mut());
1038         let name = CString::new("cleanuppad").unwrap();
1039         let ret = unsafe {
1040             llvm::LLVMRustBuildCleanupPad(self.llbuilder,
1041                                           parent,
1042                                           args.len() as c_uint,
1043                                           args.as_ptr(),
1044                                           name.as_ptr())
1045         };
1046         assert!(!ret.is_null(), "LLVM does not have support for cleanuppad");
1047         return ret
1048     }
1049
1050     pub fn cleanup_ret(&self, cleanup: ValueRef,
1051                        unwind: Option<BasicBlockRef>) -> ValueRef {
1052         self.count_insn("cleanupret");
1053         let unwind = unwind.unwrap_or(ptr::null_mut());
1054         let ret = unsafe {
1055             llvm::LLVMRustBuildCleanupRet(self.llbuilder, cleanup, unwind)
1056         };
1057         assert!(!ret.is_null(), "LLVM does not have support for cleanupret");
1058         return ret
1059     }
1060
1061     pub fn catch_pad(&self,
1062                      parent: ValueRef,
1063                      args: &[ValueRef]) -> ValueRef {
1064         self.count_insn("catchpad");
1065         let name = CString::new("catchpad").unwrap();
1066         let ret = unsafe {
1067             llvm::LLVMRustBuildCatchPad(self.llbuilder, parent,
1068                                         args.len() as c_uint, args.as_ptr(),
1069                                         name.as_ptr())
1070         };
1071         assert!(!ret.is_null(), "LLVM does not have support for catchpad");
1072         return ret
1073     }
1074
1075     pub fn catch_ret(&self, pad: ValueRef, unwind: BasicBlockRef) -> ValueRef {
1076         self.count_insn("catchret");
1077         let ret = unsafe {
1078             llvm::LLVMRustBuildCatchRet(self.llbuilder, pad, unwind)
1079         };
1080         assert!(!ret.is_null(), "LLVM does not have support for catchret");
1081         return ret
1082     }
1083
1084     pub fn catch_switch(&self,
1085                         parent: Option<ValueRef>,
1086                         unwind: Option<BasicBlockRef>,
1087                         num_handlers: usize) -> ValueRef {
1088         self.count_insn("catchswitch");
1089         let parent = parent.unwrap_or(ptr::null_mut());
1090         let unwind = unwind.unwrap_or(ptr::null_mut());
1091         let name = CString::new("catchswitch").unwrap();
1092         let ret = unsafe {
1093             llvm::LLVMRustBuildCatchSwitch(self.llbuilder, parent, unwind,
1094                                            num_handlers as c_uint,
1095                                            name.as_ptr())
1096         };
1097         assert!(!ret.is_null(), "LLVM does not have support for catchswitch");
1098         return ret
1099     }
1100
1101     pub fn add_handler(&self, catch_switch: ValueRef, handler: BasicBlockRef) {
1102         unsafe {
1103             llvm::LLVMRustAddHandler(catch_switch, handler);
1104         }
1105     }
1106
1107     pub fn set_personality_fn(&self, personality: ValueRef) {
1108         unsafe {
1109             llvm::LLVMSetPersonalityFn(self.llfn(), personality);
1110         }
1111     }
1112
1113     // Atomic Operations
1114     pub fn atomic_cmpxchg(&self, dst: ValueRef,
1115                          cmp: ValueRef, src: ValueRef,
1116                          order: AtomicOrdering,
1117                          failure_order: AtomicOrdering,
1118                          weak: llvm::Bool) -> ValueRef {
1119         unsafe {
1120             llvm::LLVMRustBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src,
1121                                          order, failure_order, weak)
1122         }
1123     }
1124     pub fn atomic_rmw(&self, op: AtomicRmwBinOp,
1125                      dst: ValueRef, src: ValueRef,
1126                      order: AtomicOrdering) -> ValueRef {
1127         unsafe {
1128             llvm::LLVMBuildAtomicRMW(self.llbuilder, op, dst, src, order, False)
1129         }
1130     }
1131
1132     pub fn atomic_fence(&self, order: AtomicOrdering, scope: SynchronizationScope) {
1133         unsafe {
1134             llvm::LLVMRustBuildAtomicFence(self.llbuilder, order, scope);
1135         }
1136     }
1137
1138     pub fn add_case(&self, s: ValueRef, on_val: ValueRef, dest: BasicBlockRef) {
1139         unsafe {
1140             if llvm::LLVMIsUndef(s) == llvm::True { return; }
1141             llvm::LLVMAddCase(s, on_val, dest)
1142         }
1143     }
1144
1145     pub fn add_incoming_to_phi(&self, phi: ValueRef, val: ValueRef, bb: BasicBlockRef) {
1146         unsafe {
1147             if llvm::LLVMIsUndef(phi) == llvm::True { return; }
1148             llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
1149         }
1150     }
1151
1152     /// Returns the ptr value that should be used for storing `val`.
1153     fn check_store<'b>(&self,
1154                        val: ValueRef,
1155                        ptr: ValueRef) -> ValueRef {
1156         let dest_ptr_ty = val_ty(ptr);
1157         let stored_ty = val_ty(val);
1158         let stored_ptr_ty = stored_ty.ptr_to();
1159
1160         assert_eq!(dest_ptr_ty.kind(), llvm::TypeKind::Pointer);
1161
1162         if dest_ptr_ty == stored_ptr_ty {
1163             ptr
1164         } else {
1165             debug!("Type mismatch in store. \
1166                     Expected {:?}, got {:?}; inserting bitcast",
1167                    dest_ptr_ty, stored_ptr_ty);
1168             self.bitcast(ptr, stored_ptr_ty)
1169         }
1170     }
1171
1172     /// Returns the args that should be used for a call to `llfn`.
1173     fn check_call<'b>(&self,
1174                       typ: &str,
1175                       llfn: ValueRef,
1176                       args: &'b [ValueRef]) -> Cow<'b, [ValueRef]> {
1177         let mut fn_ty = val_ty(llfn);
1178         // Strip off pointers
1179         while fn_ty.kind() == llvm::TypeKind::Pointer {
1180             fn_ty = fn_ty.element_type();
1181         }
1182
1183         assert!(fn_ty.kind() == llvm::TypeKind::Function,
1184                 "builder::{} not passed a function", typ);
1185
1186         let param_tys = fn_ty.func_params();
1187
1188         let all_args_match = param_tys.iter()
1189             .zip(args.iter().map(|&v| val_ty(v)))
1190             .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
1191
1192         if all_args_match {
1193             return Cow::Borrowed(args);
1194         }
1195
1196         let casted_args: Vec<_> = param_tys.into_iter()
1197             .zip(args.iter())
1198             .enumerate()
1199             .map(|(i, (expected_ty, &actual_val))| {
1200                 let actual_ty = val_ty(actual_val);
1201                 if expected_ty != actual_ty {
1202                     debug!("Type mismatch in function call of {:?}. \
1203                             Expected {:?} for param {}, got {:?}; injecting bitcast",
1204                            Value(llfn),
1205                            expected_ty, i, actual_ty);
1206                     self.bitcast(actual_val, expected_ty)
1207                 } else {
1208                     actual_val
1209                 }
1210             })
1211             .collect();
1212
1213         return Cow::Owned(casted_args);
1214     }
1215 }