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