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