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