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