]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_llvm/builder.rs
Auto merge of #56462 - Zoxc:query-macro, r=oli-obk
[rust.git] / src / librustc_codegen_llvm / builder.rs
1 use crate::llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
2 use crate::llvm::{self, False, BasicBlock};
3 use crate::common::Funclet;
4 use crate::context::CodegenCx;
5 use crate::type_::Type;
6 use crate::type_of::LayoutLlvmExt;
7 use crate::value::Value;
8 use rustc_codegen_ssa::common::{IntPredicate, TypeKind, RealPredicate};
9 use rustc_codegen_ssa::MemFlags;
10 use libc::{c_uint, c_char};
11 use rustc::ty::{self, Ty, TyCtxt};
12 use rustc::ty::layout::{self, Align, Size, TyLayout};
13 use rustc::hir::def_id::DefId;
14 use rustc::session::config;
15 use rustc_data_structures::small_c_str::SmallCStr;
16 use rustc_codegen_ssa::traits::*;
17 use rustc_codegen_ssa::base::to_immediate;
18 use rustc_codegen_ssa::mir::operand::{OperandValue, OperandRef};
19 use rustc_codegen_ssa::mir::place::PlaceRef;
20 use std::borrow::Cow;
21 use std::ffi::CStr;
22 use std::ops::{Deref, Range};
23 use std::ptr;
24
25 // All Builders must have an llfn associated with them
26 #[must_use]
27 pub struct Builder<'a, 'll: 'a, 'tcx: 'll> {
28     pub llbuilder: &'ll mut llvm::Builder<'ll>,
29     pub cx: &'a CodegenCx<'ll, 'tcx>,
30 }
31
32 impl Drop for Builder<'a, 'll, 'tcx> {
33     fn drop(&mut self) {
34         unsafe {
35             llvm::LLVMDisposeBuilder(&mut *(self.llbuilder as *mut _));
36         }
37     }
38 }
39
40 // This is a really awful way to get a zero-length c-string, but better (and a
41 // lot more efficient) than doing str::as_c_str("", ...) every time.
42 fn noname() -> *const c_char {
43     static CNULL: c_char = 0;
44     &CNULL
45 }
46
47 impl BackendTypes for Builder<'_, 'll, 'tcx> {
48     type Value = <CodegenCx<'ll, 'tcx> as BackendTypes>::Value;
49     type BasicBlock = <CodegenCx<'ll, 'tcx> as BackendTypes>::BasicBlock;
50     type Type = <CodegenCx<'ll, 'tcx> as BackendTypes>::Type;
51     type Funclet = <CodegenCx<'ll, 'tcx> as BackendTypes>::Funclet;
52
53     type DIScope = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIScope;
54 }
55
56 impl ty::layout::HasDataLayout for Builder<'_, '_, '_> {
57     fn data_layout(&self) -> &ty::layout::TargetDataLayout {
58         self.cx.data_layout()
59     }
60 }
61
62 impl ty::layout::HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> {
63     fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
64         self.cx.tcx
65     }
66 }
67
68 impl ty::layout::LayoutOf for Builder<'_, '_, 'tcx> {
69     type Ty = Ty<'tcx>;
70     type TyLayout = TyLayout<'tcx>;
71
72     fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout {
73         self.cx.layout_of(ty)
74     }
75 }
76
77 impl Deref for Builder<'_, 'll, 'tcx> {
78     type Target = CodegenCx<'ll, 'tcx>;
79
80     fn deref(&self) -> &Self::Target {
81         self.cx
82     }
83 }
84
85 impl HasCodegen<'tcx> for Builder<'_, 'll, 'tcx> {
86     type CodegenCx = CodegenCx<'ll, 'tcx>;
87 }
88
89 impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
90     fn new_block<'b>(
91         cx: &'a CodegenCx<'ll, 'tcx>,
92         llfn: &'ll Value,
93         name: &'b str
94     ) -> Self {
95         let mut bx = Builder::with_cx(cx);
96         let llbb = unsafe {
97             let name = SmallCStr::new(name);
98             llvm::LLVMAppendBasicBlockInContext(
99                 cx.llcx,
100                 llfn,
101                 name.as_ptr()
102             )
103         };
104         bx.position_at_end(llbb);
105         bx
106     }
107
108     fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self {
109         // Create a fresh builder from the crate context.
110         let llbuilder = unsafe {
111             llvm::LLVMCreateBuilderInContext(cx.llcx)
112         };
113         Builder {
114             llbuilder,
115             cx,
116         }
117     }
118
119     fn build_sibling_block<'b>(&self, name: &'b str) -> Self {
120         Builder::new_block(self.cx, self.llfn(), name)
121     }
122
123     fn llfn(&self) -> &'ll Value {
124         unsafe {
125             llvm::LLVMGetBasicBlockParent(self.llbb())
126         }
127     }
128
129     fn llbb(&self) -> &'ll BasicBlock {
130         unsafe {
131             llvm::LLVMGetInsertBlock(self.llbuilder)
132         }
133     }
134
135     fn count_insn(&self, category: &str) {
136         if self.sess().codegen_stats() {
137             self.stats.borrow_mut().n_llvm_insns += 1;
138         }
139         if self.sess().count_llvm_insns() {
140             *self.stats
141                       .borrow_mut()
142                       .llvm_insns
143                       .entry(category.to_string())
144                       .or_insert(0) += 1;
145         }
146     }
147
148     fn set_value_name(&mut self, value: &'ll Value, name: &str) {
149         let cname = SmallCStr::new(name);
150         unsafe {
151             llvm::LLVMSetValueName(value, cname.as_ptr());
152         }
153     }
154
155     fn position_at_end(&mut self, llbb: &'ll BasicBlock) {
156         unsafe {
157             llvm::LLVMPositionBuilderAtEnd(self.llbuilder, llbb);
158         }
159     }
160
161     fn position_at_start(&mut self, llbb: &'ll BasicBlock) {
162         unsafe {
163             llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb);
164         }
165     }
166
167     fn ret_void(&mut self) {
168         self.count_insn("retvoid");
169         unsafe {
170             llvm::LLVMBuildRetVoid(self.llbuilder);
171         }
172     }
173
174     fn ret(&mut self, v: &'ll Value) {
175         self.count_insn("ret");
176         unsafe {
177             llvm::LLVMBuildRet(self.llbuilder, v);
178         }
179     }
180
181     fn br(&mut self, dest: &'ll BasicBlock) {
182         self.count_insn("br");
183         unsafe {
184             llvm::LLVMBuildBr(self.llbuilder, dest);
185         }
186     }
187
188     fn cond_br(
189         &mut self,
190         cond: &'ll Value,
191         then_llbb: &'ll BasicBlock,
192         else_llbb: &'ll BasicBlock,
193     ) {
194         self.count_insn("condbr");
195         unsafe {
196             llvm::LLVMBuildCondBr(self.llbuilder, cond, then_llbb, else_llbb);
197         }
198     }
199
200     fn switch(
201         &mut self,
202         v: &'ll Value,
203         else_llbb: &'ll BasicBlock,
204         num_cases: usize,
205     ) -> &'ll Value {
206         unsafe {
207             llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, num_cases as c_uint)
208         }
209     }
210
211     fn invoke(
212         &mut self,
213         llfn: &'ll Value,
214         args: &[&'ll Value],
215         then: &'ll BasicBlock,
216         catch: &'ll BasicBlock,
217         funclet: Option<&Funclet<'ll>>,
218     ) -> &'ll Value {
219         self.count_insn("invoke");
220
221         debug!("Invoke {:?} with args ({:?})",
222                llfn,
223                args);
224
225         let args = self.check_call("invoke", llfn, args);
226         let bundle = funclet.map(|funclet| funclet.bundle());
227         let bundle = bundle.as_ref().map(|b| &*b.raw);
228
229         unsafe {
230             llvm::LLVMRustBuildInvoke(self.llbuilder,
231                                       llfn,
232                                       args.as_ptr(),
233                                       args.len() as c_uint,
234                                       then,
235                                       catch,
236                                       bundle,
237                                       noname())
238         }
239     }
240
241     fn unreachable(&mut self) {
242         self.count_insn("unreachable");
243         unsafe {
244             llvm::LLVMBuildUnreachable(self.llbuilder);
245         }
246     }
247
248     /* Arithmetic */
249     fn add(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
250         self.count_insn("add");
251         unsafe {
252             llvm::LLVMBuildAdd(self.llbuilder, lhs, rhs, noname())
253         }
254     }
255
256     fn fadd(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
257         self.count_insn("fadd");
258         unsafe {
259             llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname())
260         }
261     }
262
263     fn fadd_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
264         self.count_insn("fadd");
265         unsafe {
266             let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname());
267             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
268             instr
269         }
270     }
271
272     fn sub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
273         self.count_insn("sub");
274         unsafe {
275             llvm::LLVMBuildSub(self.llbuilder, lhs, rhs, noname())
276         }
277     }
278
279     fn fsub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
280         self.count_insn("fsub");
281         unsafe {
282             llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname())
283         }
284     }
285
286     fn fsub_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
287         self.count_insn("fsub");
288         unsafe {
289             let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname());
290             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
291             instr
292         }
293     }
294
295     fn mul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
296         self.count_insn("mul");
297         unsafe {
298             llvm::LLVMBuildMul(self.llbuilder, lhs, rhs, noname())
299         }
300     }
301
302     fn fmul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
303         self.count_insn("fmul");
304         unsafe {
305             llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname())
306         }
307     }
308
309     fn fmul_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
310         self.count_insn("fmul");
311         unsafe {
312             let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname());
313             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
314             instr
315         }
316     }
317
318
319     fn udiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
320         self.count_insn("udiv");
321         unsafe {
322             llvm::LLVMBuildUDiv(self.llbuilder, lhs, rhs, noname())
323         }
324     }
325
326     fn exactudiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
327         self.count_insn("exactudiv");
328         unsafe {
329             llvm::LLVMBuildExactUDiv(self.llbuilder, lhs, rhs, noname())
330         }
331     }
332
333     fn sdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
334         self.count_insn("sdiv");
335         unsafe {
336             llvm::LLVMBuildSDiv(self.llbuilder, lhs, rhs, noname())
337         }
338     }
339
340     fn exactsdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
341         self.count_insn("exactsdiv");
342         unsafe {
343             llvm::LLVMBuildExactSDiv(self.llbuilder, lhs, rhs, noname())
344         }
345     }
346
347     fn fdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
348         self.count_insn("fdiv");
349         unsafe {
350             llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname())
351         }
352     }
353
354     fn fdiv_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
355         self.count_insn("fdiv");
356         unsafe {
357             let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname());
358             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
359             instr
360         }
361     }
362
363     fn urem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
364         self.count_insn("urem");
365         unsafe {
366             llvm::LLVMBuildURem(self.llbuilder, lhs, rhs, noname())
367         }
368     }
369
370     fn srem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
371         self.count_insn("srem");
372         unsafe {
373             llvm::LLVMBuildSRem(self.llbuilder, lhs, rhs, noname())
374         }
375     }
376
377     fn frem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
378         self.count_insn("frem");
379         unsafe {
380             llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname())
381         }
382     }
383
384     fn frem_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
385         self.count_insn("frem");
386         unsafe {
387             let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname());
388             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
389             instr
390         }
391     }
392
393     fn shl(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
394         self.count_insn("shl");
395         unsafe {
396             llvm::LLVMBuildShl(self.llbuilder, lhs, rhs, noname())
397         }
398     }
399
400     fn lshr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
401         self.count_insn("lshr");
402         unsafe {
403             llvm::LLVMBuildLShr(self.llbuilder, lhs, rhs, noname())
404         }
405     }
406
407     fn ashr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
408         self.count_insn("ashr");
409         unsafe {
410             llvm::LLVMBuildAShr(self.llbuilder, lhs, rhs, noname())
411         }
412     }
413
414     fn and(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
415         self.count_insn("and");
416         unsafe {
417             llvm::LLVMBuildAnd(self.llbuilder, lhs, rhs, noname())
418         }
419     }
420
421     fn or(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
422         self.count_insn("or");
423         unsafe {
424             llvm::LLVMBuildOr(self.llbuilder, lhs, rhs, noname())
425         }
426     }
427
428     fn xor(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
429         self.count_insn("xor");
430         unsafe {
431             llvm::LLVMBuildXor(self.llbuilder, lhs, rhs, noname())
432         }
433     }
434
435     fn neg(&mut self, v: &'ll Value) -> &'ll Value {
436         self.count_insn("neg");
437         unsafe {
438             llvm::LLVMBuildNeg(self.llbuilder, v, noname())
439         }
440     }
441
442     fn fneg(&mut self, v: &'ll Value) -> &'ll Value {
443         self.count_insn("fneg");
444         unsafe {
445             llvm::LLVMBuildFNeg(self.llbuilder, v, noname())
446         }
447     }
448
449     fn not(&mut self, v: &'ll Value) -> &'ll Value {
450         self.count_insn("not");
451         unsafe {
452             llvm::LLVMBuildNot(self.llbuilder, v, noname())
453         }
454     }
455
456     fn checked_binop(
457         &mut self,
458         oop: OverflowOp,
459         ty: Ty<'_>,
460         lhs: Self::Value,
461         rhs: Self::Value,
462     ) -> (Self::Value, Self::Value) {
463         use syntax::ast::IntTy::*;
464         use syntax::ast::UintTy::*;
465         use rustc::ty::{Int, Uint};
466
467         let new_sty = match ty.sty {
468             Int(Isize) => Int(self.tcx.sess.target.isize_ty),
469             Uint(Usize) => Uint(self.tcx.sess.target.usize_ty),
470             ref t @ Uint(_) | ref t @ Int(_) => t.clone(),
471             _ => panic!("tried to get overflow intrinsic for op applied to non-int type")
472         };
473
474         let name = match oop {
475             OverflowOp::Add => match new_sty {
476                 Int(I8) => "llvm.sadd.with.overflow.i8",
477                 Int(I16) => "llvm.sadd.with.overflow.i16",
478                 Int(I32) => "llvm.sadd.with.overflow.i32",
479                 Int(I64) => "llvm.sadd.with.overflow.i64",
480                 Int(I128) => "llvm.sadd.with.overflow.i128",
481
482                 Uint(U8) => "llvm.uadd.with.overflow.i8",
483                 Uint(U16) => "llvm.uadd.with.overflow.i16",
484                 Uint(U32) => "llvm.uadd.with.overflow.i32",
485                 Uint(U64) => "llvm.uadd.with.overflow.i64",
486                 Uint(U128) => "llvm.uadd.with.overflow.i128",
487
488                 _ => unreachable!(),
489             },
490             OverflowOp::Sub => match new_sty {
491                 Int(I8) => "llvm.ssub.with.overflow.i8",
492                 Int(I16) => "llvm.ssub.with.overflow.i16",
493                 Int(I32) => "llvm.ssub.with.overflow.i32",
494                 Int(I64) => "llvm.ssub.with.overflow.i64",
495                 Int(I128) => "llvm.ssub.with.overflow.i128",
496
497                 Uint(U8) => "llvm.usub.with.overflow.i8",
498                 Uint(U16) => "llvm.usub.with.overflow.i16",
499                 Uint(U32) => "llvm.usub.with.overflow.i32",
500                 Uint(U64) => "llvm.usub.with.overflow.i64",
501                 Uint(U128) => "llvm.usub.with.overflow.i128",
502
503                 _ => unreachable!(),
504             },
505             OverflowOp::Mul => match new_sty {
506                 Int(I8) => "llvm.smul.with.overflow.i8",
507                 Int(I16) => "llvm.smul.with.overflow.i16",
508                 Int(I32) => "llvm.smul.with.overflow.i32",
509                 Int(I64) => "llvm.smul.with.overflow.i64",
510                 Int(I128) => "llvm.smul.with.overflow.i128",
511
512                 Uint(U8) => "llvm.umul.with.overflow.i8",
513                 Uint(U16) => "llvm.umul.with.overflow.i16",
514                 Uint(U32) => "llvm.umul.with.overflow.i32",
515                 Uint(U64) => "llvm.umul.with.overflow.i64",
516                 Uint(U128) => "llvm.umul.with.overflow.i128",
517
518                 _ => unreachable!(),
519             },
520         };
521
522         let intrinsic = self.get_intrinsic(&name);
523         let res = self.call(intrinsic, &[lhs, rhs], None);
524         (
525             self.extract_value(res, 0),
526             self.extract_value(res, 1),
527         )
528     }
529
530     fn alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
531         let mut bx = Builder::with_cx(self.cx);
532         bx.position_at_start(unsafe {
533             llvm::LLVMGetFirstBasicBlock(self.llfn())
534         });
535         bx.dynamic_alloca(ty, name, align)
536     }
537
538     fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
539         self.count_insn("alloca");
540         unsafe {
541             let alloca = if name.is_empty() {
542                 llvm::LLVMBuildAlloca(self.llbuilder, ty, noname())
543             } else {
544                 let name = SmallCStr::new(name);
545                 llvm::LLVMBuildAlloca(self.llbuilder, ty,
546                                       name.as_ptr())
547             };
548             llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
549             alloca
550         }
551     }
552
553     fn array_alloca(&mut self,
554                         ty: &'ll Type,
555                         len: &'ll Value,
556                         name: &str,
557                         align: Align) -> &'ll Value {
558         self.count_insn("alloca");
559         unsafe {
560             let alloca = if name.is_empty() {
561                 llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, noname())
562             } else {
563                 let name = SmallCStr::new(name);
564                 llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len,
565                                            name.as_ptr())
566             };
567             llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
568             alloca
569         }
570     }
571
572     fn load(&mut self, ptr: &'ll Value, align: Align) -> &'ll Value {
573         self.count_insn("load");
574         unsafe {
575             let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
576             llvm::LLVMSetAlignment(load, align.bytes() as c_uint);
577             load
578         }
579     }
580
581     fn volatile_load(&mut self, ptr: &'ll Value) -> &'ll Value {
582         self.count_insn("load.volatile");
583         unsafe {
584             let insn = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
585             llvm::LLVMSetVolatile(insn, llvm::True);
586             insn
587         }
588     }
589
590     fn atomic_load(
591         &mut self,
592         ptr: &'ll Value,
593         order: rustc_codegen_ssa::common::AtomicOrdering,
594         size: Size,
595     ) -> &'ll Value {
596         self.count_insn("load.atomic");
597         unsafe {
598             let load = llvm::LLVMRustBuildAtomicLoad(
599                 self.llbuilder,
600                 ptr,
601                 noname(),
602                 AtomicOrdering::from_generic(order),
603             );
604             // LLVM requires the alignment of atomic loads to be at least the size of the type.
605             llvm::LLVMSetAlignment(load, size.bytes() as c_uint);
606             load
607         }
608     }
609
610     fn load_operand(
611         &mut self,
612         place: PlaceRef<'tcx, &'ll Value>
613     ) -> OperandRef<'tcx, &'ll Value> {
614         debug!("PlaceRef::load: {:?}", place);
615
616         assert_eq!(place.llextra.is_some(), place.layout.is_unsized());
617
618         if place.layout.is_zst() {
619             return OperandRef::new_zst(self.cx(), place.layout);
620         }
621
622         fn scalar_load_metadata<'a, 'll, 'tcx>(
623             bx: &mut Builder<'a, 'll, 'tcx>,
624             load: &'ll Value,
625             scalar: &layout::Scalar
626         ) {
627             let vr = scalar.valid_range.clone();
628             match scalar.value {
629                 layout::Int(..) => {
630                     let range = scalar.valid_range_exclusive(bx);
631                     if range.start != range.end {
632                         bx.range_metadata(load, range);
633                     }
634                 }
635                 layout::Pointer if vr.start() < vr.end() && !vr.contains(&0) => {
636                     bx.nonnull_metadata(load);
637                 }
638                 _ => {}
639             }
640         }
641
642         let val = if let Some(llextra) = place.llextra {
643             OperandValue::Ref(place.llval, Some(llextra), place.align)
644         } else if place.layout.is_llvm_immediate() {
645             let mut const_llval = None;
646             unsafe {
647                 if let Some(global) = llvm::LLVMIsAGlobalVariable(place.llval) {
648                     if llvm::LLVMIsGlobalConstant(global) == llvm::True {
649                         const_llval = llvm::LLVMGetInitializer(global);
650                     }
651                 }
652             }
653             let llval = const_llval.unwrap_or_else(|| {
654                 let load = self.load(place.llval, place.align);
655                 if let layout::Abi::Scalar(ref scalar) = place.layout.abi {
656                     scalar_load_metadata(self, load, scalar);
657                 }
658                 load
659             });
660             OperandValue::Immediate(to_immediate(self, llval, place.layout))
661         } else if let layout::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
662             let b_offset = a.value.size(self).align_to(b.value.align(self).abi);
663
664             let mut load = |i, scalar: &layout::Scalar, align| {
665                 let llptr = self.struct_gep(place.llval, i as u64);
666                 let load = self.load(llptr, align);
667                 scalar_load_metadata(self, load, scalar);
668                 if scalar.is_bool() {
669                     self.trunc(load, self.type_i1())
670                 } else {
671                     load
672                 }
673             };
674
675             OperandValue::Pair(
676                 load(0, a, place.align),
677                 load(1, b, place.align.restrict_for_offset(b_offset)),
678             )
679         } else {
680             OperandValue::Ref(place.llval, None, place.align)
681         };
682
683         OperandRef { val, layout: place.layout }
684     }
685
686
687
688     fn range_metadata(&mut self, load: &'ll Value, range: Range<u128>) {
689         if self.sess().target.target.arch == "amdgpu" {
690             // amdgpu/LLVM does something weird and thinks a i64 value is
691             // split into a v2i32, halving the bitwidth LLVM expects,
692             // tripping an assertion. So, for now, just disable this
693             // optimization.
694             return;
695         }
696
697         unsafe {
698             let llty = self.cx.val_ty(load);
699             let v = [
700                 self.cx.const_uint_big(llty, range.start),
701                 self.cx.const_uint_big(llty, range.end)
702             ];
703
704             llvm::LLVMSetMetadata(load, llvm::MD_range as c_uint,
705                                   llvm::LLVMMDNodeInContext(self.cx.llcx,
706                                                             v.as_ptr(),
707                                                             v.len() as c_uint));
708         }
709     }
710
711     fn nonnull_metadata(&mut self, load: &'ll Value) {
712         unsafe {
713             llvm::LLVMSetMetadata(load, llvm::MD_nonnull as c_uint,
714                                   llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0));
715         }
716     }
717
718     fn store(&mut self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value {
719         self.store_with_flags(val, ptr, align, MemFlags::empty())
720     }
721
722     fn store_with_flags(
723         &mut self,
724         val: &'ll Value,
725         ptr: &'ll Value,
726         align: Align,
727         flags: MemFlags,
728     ) -> &'ll Value {
729         debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags);
730         self.count_insn("store");
731         let ptr = self.check_store(val, ptr);
732         unsafe {
733             let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
734             let align = if flags.contains(MemFlags::UNALIGNED) {
735                 1
736             } else {
737                 align.bytes() as c_uint
738             };
739             llvm::LLVMSetAlignment(store, align);
740             if flags.contains(MemFlags::VOLATILE) {
741                 llvm::LLVMSetVolatile(store, llvm::True);
742             }
743             if flags.contains(MemFlags::NONTEMPORAL) {
744                 // According to LLVM [1] building a nontemporal store must
745                 // *always* point to a metadata value of the integer 1.
746                 //
747                 // [1]: http://llvm.org/docs/LangRef.html#store-instruction
748                 let one = self.cx.const_i32(1);
749                 let node = llvm::LLVMMDNodeInContext(self.cx.llcx, &one, 1);
750                 llvm::LLVMSetMetadata(store, llvm::MD_nontemporal as c_uint, node);
751             }
752             store
753         }
754     }
755
756    fn atomic_store(&mut self, val: &'ll Value, ptr: &'ll Value,
757                    order: rustc_codegen_ssa::common::AtomicOrdering, size: Size) {
758         debug!("Store {:?} -> {:?}", val, ptr);
759         self.count_insn("store.atomic");
760         let ptr = self.check_store(val, ptr);
761         unsafe {
762             let store = llvm::LLVMRustBuildAtomicStore(
763                 self.llbuilder,
764                 val,
765                 ptr,
766                 AtomicOrdering::from_generic(order),
767             );
768             // LLVM requires the alignment of atomic stores to be at least the size of the type.
769             llvm::LLVMSetAlignment(store, size.bytes() as c_uint);
770         }
771     }
772
773     fn gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
774         self.count_insn("gep");
775         unsafe {
776             llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(),
777                                indices.len() as c_uint, noname())
778         }
779     }
780
781     fn inbounds_gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
782         self.count_insn("inboundsgep");
783         unsafe {
784             llvm::LLVMBuildInBoundsGEP(
785                 self.llbuilder, ptr, indices.as_ptr(), indices.len() as c_uint, noname())
786         }
787     }
788
789     /* Casts */
790     fn trunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
791         self.count_insn("trunc");
792         unsafe {
793             llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, noname())
794         }
795     }
796
797     fn sext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
798         self.count_insn("sext");
799         unsafe {
800             llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, noname())
801         }
802     }
803
804     fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
805         self.count_insn("fptoui");
806         unsafe {
807             llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, noname())
808         }
809     }
810
811     fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
812         self.count_insn("fptosi");
813         unsafe {
814             llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,noname())
815         }
816     }
817
818     fn uitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
819         self.count_insn("uitofp");
820         unsafe {
821             llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, noname())
822         }
823     }
824
825     fn sitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
826         self.count_insn("sitofp");
827         unsafe {
828             llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, noname())
829         }
830     }
831
832     fn fptrunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
833         self.count_insn("fptrunc");
834         unsafe {
835             llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, noname())
836         }
837     }
838
839     fn fpext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
840         self.count_insn("fpext");
841         unsafe {
842             llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, noname())
843         }
844     }
845
846     fn ptrtoint(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
847         self.count_insn("ptrtoint");
848         unsafe {
849             llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, noname())
850         }
851     }
852
853     fn inttoptr(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
854         self.count_insn("inttoptr");
855         unsafe {
856             llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, noname())
857         }
858     }
859
860     fn bitcast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
861         self.count_insn("bitcast");
862         unsafe {
863             llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, noname())
864         }
865     }
866
867
868     fn intcast(&mut self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value {
869         self.count_insn("intcast");
870         unsafe {
871             llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed)
872         }
873     }
874
875     fn pointercast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
876         self.count_insn("pointercast");
877         unsafe {
878             llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname())
879         }
880     }
881
882     /* Comparisons */
883     fn icmp(&mut self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
884         self.count_insn("icmp");
885         let op = llvm::IntPredicate::from_generic(op);
886         unsafe {
887             llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
888         }
889     }
890
891     fn fcmp(&mut self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
892         self.count_insn("fcmp");
893         unsafe {
894             llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
895         }
896     }
897
898     /* Miscellaneous instructions */
899     fn empty_phi(&mut self, ty: &'ll Type) -> &'ll Value {
900         self.count_insn("emptyphi");
901         unsafe {
902             llvm::LLVMBuildPhi(self.llbuilder, ty, noname())
903         }
904     }
905
906     fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
907         assert_eq!(vals.len(), bbs.len());
908         let phi = self.empty_phi(ty);
909         self.count_insn("addincoming");
910         unsafe {
911             llvm::LLVMAddIncoming(phi, vals.as_ptr(),
912                                   bbs.as_ptr(),
913                                   vals.len() as c_uint);
914             phi
915         }
916     }
917
918     fn inline_asm_call(&mut self, asm: &CStr, cons: &CStr,
919                        inputs: &[&'ll Value], output: &'ll Type,
920                        volatile: bool, alignstack: bool,
921                        dia: syntax::ast::AsmDialect) -> Option<&'ll Value> {
922         self.count_insn("inlineasm");
923
924         let volatile = if volatile { llvm::True }
925                        else        { llvm::False };
926         let alignstack = if alignstack { llvm::True }
927                          else          { llvm::False };
928
929         let argtys = inputs.iter().map(|v| {
930             debug!("Asm Input Type: {:?}", *v);
931             self.cx.val_ty(*v)
932         }).collect::<Vec<_>>();
933
934         debug!("Asm Output Type: {:?}", output);
935         let fty = self.type_func(&argtys[..], output);
936         unsafe {
937             // Ask LLVM to verify that the constraints are well-formed.
938             let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons.as_ptr());
939             debug!("Constraint verification result: {:?}", constraints_ok);
940             if constraints_ok {
941                 let v = llvm::LLVMRustInlineAsm(
942                     fty,
943                     asm.as_ptr(),
944                     cons.as_ptr(),
945                     volatile,
946                     alignstack,
947                     AsmDialect::from_generic(dia),
948                 );
949                 Some(self.call(v, inputs, None))
950             } else {
951                 // LLVM has detected an issue with our constraints, bail out
952                 None
953             }
954         }
955     }
956
957     fn memcpy(&mut self, dst: &'ll Value, dst_align: Align,
958                   src: &'ll Value, src_align: Align,
959                   size: &'ll Value, flags: MemFlags) {
960         if flags.contains(MemFlags::NONTEMPORAL) {
961             // HACK(nox): This is inefficient but there is no nontemporal memcpy.
962             let val = self.load(src, src_align);
963             let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val)));
964             self.store_with_flags(val, ptr, dst_align, flags);
965             return;
966         }
967         let size = self.intcast(size, self.type_isize(), false);
968         let is_volatile = flags.contains(MemFlags::VOLATILE);
969         let dst = self.pointercast(dst, self.type_i8p());
970         let src = self.pointercast(src, self.type_i8p());
971         unsafe {
972             llvm::LLVMRustBuildMemCpy(self.llbuilder, dst, dst_align.bytes() as c_uint,
973                                       src, src_align.bytes() as c_uint, size, is_volatile);
974         }
975     }
976
977     fn memmove(&mut self, dst: &'ll Value, dst_align: Align,
978                   src: &'ll Value, src_align: Align,
979                   size: &'ll Value, flags: MemFlags) {
980         if flags.contains(MemFlags::NONTEMPORAL) {
981             // HACK(nox): This is inefficient but there is no nontemporal memmove.
982             let val = self.load(src, src_align);
983             let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val)));
984             self.store_with_flags(val, ptr, dst_align, flags);
985             return;
986         }
987         let size = self.intcast(size, self.type_isize(), false);
988         let is_volatile = flags.contains(MemFlags::VOLATILE);
989         let dst = self.pointercast(dst, self.type_i8p());
990         let src = self.pointercast(src, self.type_i8p());
991         unsafe {
992             llvm::LLVMRustBuildMemMove(self.llbuilder, dst, dst_align.bytes() as c_uint,
993                                       src, src_align.bytes() as c_uint, size, is_volatile);
994         }
995     }
996
997     fn memset(
998         &mut self,
999         ptr: &'ll Value,
1000         fill_byte: &'ll Value,
1001         size: &'ll Value,
1002         align: Align,
1003         flags: MemFlags,
1004     ) {
1005         let ptr_width = &self.sess().target.target.target_pointer_width;
1006         let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
1007         let llintrinsicfn = self.get_intrinsic(&intrinsic_key);
1008         let ptr = self.pointercast(ptr, self.type_i8p());
1009         let align = self.const_u32(align.bytes() as u32);
1010         let volatile = self.const_bool(flags.contains(MemFlags::VOLATILE));
1011         self.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None);
1012     }
1013
1014     fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
1015         self.count_insn("minnum");
1016         unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) }
1017     }
1018     fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
1019         self.count_insn("maxnum");
1020         unsafe { llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs) }
1021     }
1022
1023     fn select(
1024         &mut self, cond: &'ll Value,
1025         then_val: &'ll Value,
1026         else_val: &'ll Value,
1027     ) -> &'ll Value {
1028         self.count_insn("select");
1029         unsafe {
1030             llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname())
1031         }
1032     }
1033
1034     #[allow(dead_code)]
1035     fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
1036         self.count_insn("vaarg");
1037         unsafe {
1038             llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
1039         }
1040     }
1041
1042     fn extract_element(&mut self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value {
1043         self.count_insn("extractelement");
1044         unsafe {
1045             llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname())
1046         }
1047     }
1048
1049     fn insert_element(
1050         &mut self, vec: &'ll Value,
1051         elt: &'ll Value,
1052         idx: &'ll Value,
1053     ) -> &'ll Value {
1054         self.count_insn("insertelement");
1055         unsafe {
1056             llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname())
1057         }
1058     }
1059
1060     fn shuffle_vector(&mut self, v1: &'ll Value, v2: &'ll Value, mask: &'ll Value) -> &'ll Value {
1061         self.count_insn("shufflevector");
1062         unsafe {
1063             llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname())
1064         }
1065     }
1066
1067     fn vector_splat(&mut self, num_elts: usize, elt: &'ll Value) -> &'ll Value {
1068         unsafe {
1069             let elt_ty = self.cx.val_ty(elt);
1070             let undef = llvm::LLVMGetUndef(self.type_vector(elt_ty, num_elts as u64));
1071             let vec = self.insert_element(undef, elt, self.cx.const_i32(0));
1072             let vec_i32_ty = self.type_vector(self.type_i32(), num_elts as u64);
1073             self.shuffle_vector(vec, undef, self.const_null(vec_i32_ty))
1074         }
1075     }
1076
1077     fn vector_reduce_fadd_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
1078         self.count_insn("vector.reduce.fadd_fast");
1079         unsafe {
1080             // FIXME: add a non-fast math version once
1081             // https://bugs.llvm.org/show_bug.cgi?id=36732
1082             // is fixed.
1083             let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src);
1084             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
1085             instr
1086         }
1087     }
1088     fn vector_reduce_fmul_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
1089         self.count_insn("vector.reduce.fmul_fast");
1090         unsafe {
1091             // FIXME: add a non-fast math version once
1092             // https://bugs.llvm.org/show_bug.cgi?id=36732
1093             // is fixed.
1094             let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src);
1095             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
1096             instr
1097         }
1098     }
1099     fn vector_reduce_add(&mut self, src: &'ll Value) -> &'ll Value {
1100         self.count_insn("vector.reduce.add");
1101         unsafe { llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) }
1102     }
1103     fn vector_reduce_mul(&mut self, src: &'ll Value) -> &'ll Value {
1104         self.count_insn("vector.reduce.mul");
1105         unsafe { llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) }
1106     }
1107     fn vector_reduce_and(&mut self, src: &'ll Value) -> &'ll Value {
1108         self.count_insn("vector.reduce.and");
1109         unsafe { llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) }
1110     }
1111     fn vector_reduce_or(&mut self, src: &'ll Value) -> &'ll Value {
1112         self.count_insn("vector.reduce.or");
1113         unsafe { llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) }
1114     }
1115     fn vector_reduce_xor(&mut self, src: &'ll Value) -> &'ll Value {
1116         self.count_insn("vector.reduce.xor");
1117         unsafe { llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) }
1118     }
1119     fn vector_reduce_fmin(&mut self, src: &'ll Value) -> &'ll Value {
1120         self.count_insn("vector.reduce.fmin");
1121         unsafe { llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false) }
1122     }
1123     fn vector_reduce_fmax(&mut self, src: &'ll Value) -> &'ll Value {
1124         self.count_insn("vector.reduce.fmax");
1125         unsafe { llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false) }
1126     }
1127     fn vector_reduce_fmin_fast(&mut self, src: &'ll Value) -> &'ll Value {
1128         self.count_insn("vector.reduce.fmin_fast");
1129         unsafe {
1130             let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true);
1131             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
1132             instr
1133         }
1134     }
1135     fn vector_reduce_fmax_fast(&mut self, src: &'ll Value) -> &'ll Value {
1136         self.count_insn("vector.reduce.fmax_fast");
1137         unsafe {
1138             let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true);
1139             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
1140             instr
1141         }
1142     }
1143     fn vector_reduce_min(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value {
1144         self.count_insn("vector.reduce.min");
1145         unsafe { llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) }
1146     }
1147     fn vector_reduce_max(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value {
1148         self.count_insn("vector.reduce.max");
1149         unsafe { llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed) }
1150     }
1151
1152     fn extract_value(&mut self, agg_val: &'ll Value, idx: u64) -> &'ll Value {
1153         self.count_insn("extractvalue");
1154         assert_eq!(idx as c_uint as u64, idx);
1155         unsafe {
1156             llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, noname())
1157         }
1158     }
1159
1160     fn insert_value(&mut self, agg_val: &'ll Value, elt: &'ll Value,
1161                        idx: u64) -> &'ll Value {
1162         self.count_insn("insertvalue");
1163         assert_eq!(idx as c_uint as u64, idx);
1164         unsafe {
1165             llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint,
1166                                        noname())
1167         }
1168     }
1169
1170     fn landing_pad(&mut self, ty: &'ll Type, pers_fn: &'ll Value,
1171                        num_clauses: usize) -> &'ll Value {
1172         self.count_insn("landingpad");
1173         unsafe {
1174             llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn,
1175                                       num_clauses as c_uint, noname())
1176         }
1177     }
1178
1179     fn add_clause(&mut self, landing_pad: &'ll Value, clause: &'ll Value) {
1180         unsafe {
1181             llvm::LLVMAddClause(landing_pad, clause);
1182         }
1183     }
1184
1185     fn set_cleanup(&mut self, landing_pad: &'ll Value) {
1186         self.count_insn("setcleanup");
1187         unsafe {
1188             llvm::LLVMSetCleanup(landing_pad, llvm::True);
1189         }
1190     }
1191
1192     fn resume(&mut self, exn: &'ll Value) -> &'ll Value {
1193         self.count_insn("resume");
1194         unsafe {
1195             llvm::LLVMBuildResume(self.llbuilder, exn)
1196         }
1197     }
1198
1199     fn cleanup_pad(&mut self,
1200                        parent: Option<&'ll Value>,
1201                        args: &[&'ll Value]) -> Funclet<'ll> {
1202         self.count_insn("cleanuppad");
1203         let name = const_cstr!("cleanuppad");
1204         let ret = unsafe {
1205             llvm::LLVMRustBuildCleanupPad(self.llbuilder,
1206                                           parent,
1207                                           args.len() as c_uint,
1208                                           args.as_ptr(),
1209                                           name.as_ptr())
1210         };
1211         Funclet::new(ret.expect("LLVM does not have support for cleanuppad"))
1212     }
1213
1214     fn cleanup_ret(
1215         &mut self, funclet: &Funclet<'ll>,
1216         unwind: Option<&'ll BasicBlock>,
1217     ) -> &'ll Value {
1218         self.count_insn("cleanupret");
1219         let ret = unsafe {
1220             llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind)
1221         };
1222         ret.expect("LLVM does not have support for cleanupret")
1223     }
1224
1225     fn catch_pad(&mut self,
1226                      parent: &'ll Value,
1227                      args: &[&'ll Value]) -> Funclet<'ll> {
1228         self.count_insn("catchpad");
1229         let name = const_cstr!("catchpad");
1230         let ret = unsafe {
1231             llvm::LLVMRustBuildCatchPad(self.llbuilder, parent,
1232                                         args.len() as c_uint, args.as_ptr(),
1233                                         name.as_ptr())
1234         };
1235         Funclet::new(ret.expect("LLVM does not have support for catchpad"))
1236     }
1237
1238     fn catch_ret(&mut self, funclet: &Funclet<'ll>, unwind: &'ll BasicBlock) -> &'ll Value {
1239         self.count_insn("catchret");
1240         let ret = unsafe {
1241             llvm::LLVMRustBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind)
1242         };
1243         ret.expect("LLVM does not have support for catchret")
1244     }
1245
1246     fn catch_switch(
1247         &mut self,
1248         parent: Option<&'ll Value>,
1249         unwind: Option<&'ll BasicBlock>,
1250         num_handlers: usize,
1251     ) -> &'ll Value {
1252         self.count_insn("catchswitch");
1253         let name = const_cstr!("catchswitch");
1254         let ret = unsafe {
1255             llvm::LLVMRustBuildCatchSwitch(self.llbuilder, parent, unwind,
1256                                            num_handlers as c_uint,
1257                                            name.as_ptr())
1258         };
1259         ret.expect("LLVM does not have support for catchswitch")
1260     }
1261
1262     fn add_handler(&mut self, catch_switch: &'ll Value, handler: &'ll BasicBlock) {
1263         unsafe {
1264             llvm::LLVMRustAddHandler(catch_switch, handler);
1265         }
1266     }
1267
1268     fn set_personality_fn(&mut self, personality: &'ll Value) {
1269         unsafe {
1270             llvm::LLVMSetPersonalityFn(self.llfn(), personality);
1271         }
1272     }
1273
1274     // Atomic Operations
1275     fn atomic_cmpxchg(
1276         &mut self,
1277         dst: &'ll Value,
1278         cmp: &'ll Value,
1279         src: &'ll Value,
1280         order: rustc_codegen_ssa::common::AtomicOrdering,
1281         failure_order: rustc_codegen_ssa::common::AtomicOrdering,
1282         weak: bool,
1283     ) -> &'ll Value {
1284         let weak = if weak { llvm::True } else { llvm::False };
1285         unsafe {
1286             llvm::LLVMRustBuildAtomicCmpXchg(
1287                 self.llbuilder,
1288                 dst,
1289                 cmp,
1290                 src,
1291                 AtomicOrdering::from_generic(order),
1292                 AtomicOrdering::from_generic(failure_order),
1293                 weak
1294             )
1295         }
1296     }
1297     fn atomic_rmw(
1298         &mut self,
1299         op: rustc_codegen_ssa::common::AtomicRmwBinOp,
1300         dst: &'ll Value,
1301         src: &'ll Value,
1302         order: rustc_codegen_ssa::common::AtomicOrdering,
1303     ) -> &'ll Value {
1304         unsafe {
1305             llvm::LLVMBuildAtomicRMW(
1306                 self.llbuilder,
1307                 AtomicRmwBinOp::from_generic(op),
1308                 dst,
1309                 src,
1310                 AtomicOrdering::from_generic(order),
1311                 False)
1312         }
1313     }
1314
1315     fn atomic_fence(
1316         &mut self,
1317         order: rustc_codegen_ssa::common::AtomicOrdering,
1318         scope: rustc_codegen_ssa::common::SynchronizationScope
1319     ) {
1320         unsafe {
1321             llvm::LLVMRustBuildAtomicFence(
1322                 self.llbuilder,
1323                 AtomicOrdering::from_generic(order),
1324                 SynchronizationScope::from_generic(scope)
1325             );
1326         }
1327     }
1328
1329     fn add_case(&mut self, s: &'ll Value, on_val: &'ll Value, dest: &'ll BasicBlock) {
1330         unsafe {
1331             llvm::LLVMAddCase(s, on_val, dest)
1332         }
1333     }
1334
1335     fn add_incoming_to_phi(&mut self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) {
1336         self.count_insn("addincoming");
1337         unsafe {
1338             llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
1339         }
1340     }
1341
1342     fn set_invariant_load(&mut self, load: &'ll Value) {
1343         unsafe {
1344             llvm::LLVMSetMetadata(load, llvm::MD_invariant_load as c_uint,
1345                                   llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0));
1346         }
1347     }
1348
1349     fn check_store<'b>(&mut self,
1350                        val: &'ll Value,
1351                        ptr: &'ll Value) -> &'ll Value {
1352         let dest_ptr_ty = self.cx.val_ty(ptr);
1353         let stored_ty = self.cx.val_ty(val);
1354         let stored_ptr_ty = self.cx.type_ptr_to(stored_ty);
1355
1356         assert_eq!(self.cx.type_kind(dest_ptr_ty), TypeKind::Pointer);
1357
1358         if dest_ptr_ty == stored_ptr_ty {
1359             ptr
1360         } else {
1361             debug!("Type mismatch in store. \
1362                     Expected {:?}, got {:?}; inserting bitcast",
1363                    dest_ptr_ty, stored_ptr_ty);
1364             self.bitcast(ptr, stored_ptr_ty)
1365         }
1366     }
1367
1368     fn check_call<'b>(&mut self,
1369                       typ: &str,
1370                       llfn: &'ll Value,
1371                       args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> {
1372         let mut fn_ty = self.cx.val_ty(llfn);
1373         // Strip off pointers
1374         while self.cx.type_kind(fn_ty) == TypeKind::Pointer {
1375             fn_ty = self.cx.element_type(fn_ty);
1376         }
1377
1378         assert!(self.cx.type_kind(fn_ty) == TypeKind::Function,
1379                 "builder::{} not passed a function, but {:?}", typ, fn_ty);
1380
1381         let param_tys = self.cx.func_params_types(fn_ty);
1382
1383         let all_args_match = param_tys.iter()
1384             .zip(args.iter().map(|&v| self.val_ty(v)))
1385             .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
1386
1387         if all_args_match {
1388             return Cow::Borrowed(args);
1389         }
1390
1391         let casted_args: Vec<_> = param_tys.into_iter()
1392             .zip(args.iter())
1393             .enumerate()
1394             .map(|(i, (expected_ty, &actual_val))| {
1395                 let actual_ty = self.val_ty(actual_val);
1396                 if expected_ty != actual_ty {
1397                     debug!("Type mismatch in function call of {:?}. \
1398                             Expected {:?} for param {}, got {:?}; injecting bitcast",
1399                            llfn, expected_ty, i, actual_ty);
1400                     self.bitcast(actual_val, expected_ty)
1401                 } else {
1402                     actual_val
1403                 }
1404             })
1405             .collect();
1406
1407         Cow::Owned(casted_args)
1408     }
1409
1410     fn lifetime_start(&mut self, ptr: &'ll Value, size: Size) {
1411         self.call_lifetime_intrinsic("llvm.lifetime.start", ptr, size);
1412     }
1413
1414     fn lifetime_end(&mut self, ptr: &'ll Value, size: Size) {
1415         self.call_lifetime_intrinsic("llvm.lifetime.end", ptr, size);
1416     }
1417
1418     fn call(
1419         &mut self,
1420         llfn: &'ll Value,
1421         args: &[&'ll Value],
1422         funclet: Option<&Funclet<'ll>>,
1423     ) -> &'ll Value {
1424         self.count_insn("call");
1425
1426         debug!("Call {:?} with args ({:?})",
1427                llfn,
1428                args);
1429
1430         let args = self.check_call("call", llfn, args);
1431         let bundle = funclet.map(|funclet| funclet.bundle());
1432         let bundle = bundle.as_ref().map(|b| &*b.raw);
1433
1434         unsafe {
1435             llvm::LLVMRustBuildCall(
1436                 self.llbuilder,
1437                 llfn,
1438                 args.as_ptr() as *const &llvm::Value,
1439                 args.len() as c_uint,
1440                 bundle, noname()
1441             )
1442         }
1443     }
1444
1445     fn zext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
1446         self.count_insn("zext");
1447         unsafe {
1448             llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, noname())
1449         }
1450     }
1451
1452     fn struct_gep(&mut self, ptr: &'ll Value, idx: u64) -> &'ll Value {
1453         self.count_insn("structgep");
1454         assert_eq!(idx as c_uint as u64, idx);
1455         unsafe {
1456             llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname())
1457         }
1458     }
1459
1460     fn cx(&self) -> &CodegenCx<'ll, 'tcx> {
1461         self.cx
1462     }
1463
1464     unsafe fn delete_basic_block(&mut self, bb: &'ll BasicBlock) {
1465         llvm::LLVMDeleteBasicBlock(bb);
1466     }
1467
1468     fn do_not_inline(&mut self, llret: &'ll Value) {
1469         llvm::Attribute::NoInline.apply_callsite(llvm::AttributePlace::Function, llret);
1470     }
1471 }
1472
1473 impl StaticBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
1474     fn get_static(&self, def_id: DefId) -> &'ll Value {
1475         self.cx().get_static(def_id)
1476     }
1477 }
1478
1479 impl Builder<'a, 'll, 'tcx> {
1480     fn call_lifetime_intrinsic(&mut self, intrinsic: &str, ptr: &'ll Value, size: Size) {
1481         if self.cx.sess().opts.optimize == config::OptLevel::No {
1482             return;
1483         }
1484
1485         let size = size.bytes();
1486         if size == 0 {
1487             return;
1488         }
1489
1490         let lifetime_intrinsic = self.cx.get_intrinsic(intrinsic);
1491
1492         let ptr = self.pointercast(ptr, self.cx.type_i8p());
1493         self.call(lifetime_intrinsic, &[self.cx.const_u64(size), ptr], None);
1494     }
1495 }