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