]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_llvm/builder.rs
Beginning of moving all backend-agnostic code to rustc_codegen_ssa
[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;
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::session::config;
24 use rustc_data_structures::small_c_str::SmallCStr;
25 use interfaces::*;
26 use syntax;
27 use base;
28 use mir::operand::{OperandValue, OperandRef};
29 use mir::place::PlaceRef;
30 use std::borrow::Cow;
31 use std::ops::Range;
32 use std::ptr;
33
34 // All Builders must have an llfn associated with them
35 #[must_use]
36 pub struct Builder<'a, 'll: 'a, 'tcx: 'll, V: 'll = &'ll Value> {
37     pub llbuilder: &'ll mut llvm::Builder<'ll>,
38     pub cx: &'a CodegenCx<'ll, 'tcx, V>,
39 }
40
41 impl<V> Drop for Builder<'a, 'll, 'tcx, V> {
42     fn drop(&mut self) {
43         unsafe {
44             llvm::LLVMDisposeBuilder(&mut *(self.llbuilder as *mut _));
45         }
46     }
47 }
48
49 // This is a really awful way to get a zero-length c-string, but better (and a
50 // lot more efficient) than doing str::as_c_str("", ...) every time.
51 fn noname() -> *const c_char {
52     static CNULL: c_char = 0;
53     &CNULL
54 }
55
56 bitflags! {
57     pub struct MemFlags: u8 {
58         const VOLATILE = 1 << 0;
59         const NONTEMPORAL = 1 << 1;
60         const UNALIGNED = 1 << 2;
61     }
62 }
63
64 impl BackendTypes for Builder<'_, 'll, 'tcx> {
65     type Value = <CodegenCx<'ll, 'tcx> as BackendTypes>::Value;
66     type BasicBlock = <CodegenCx<'ll, 'tcx> as BackendTypes>::BasicBlock;
67     type Type = <CodegenCx<'ll, 'tcx> as BackendTypes>::Type;
68     type Context = <CodegenCx<'ll, 'tcx> as BackendTypes>::Context;
69     type Funclet = <CodegenCx<'ll, 'tcx> as BackendTypes>::Funclet;
70
71     type DIScope = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIScope;
72 }
73
74 impl ty::layout::HasDataLayout for Builder<'_, '_, '_> {
75     fn data_layout(&self) -> &ty::layout::TargetDataLayout {
76         self.cx.data_layout()
77     }
78 }
79
80 impl ty::layout::HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> {
81     fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
82         self.cx.tcx
83     }
84 }
85
86 impl ty::layout::LayoutOf for Builder<'_, '_, 'tcx> {
87     type Ty = Ty<'tcx>;
88     type TyLayout = TyLayout<'tcx>;
89
90     fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout {
91         self.cx.layout_of(ty)
92     }
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 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.cx().sess().codegen_stats() {
148             self.cx().stats.borrow_mut().n_llvm_insns += 1;
149         }
150         if self.cx().sess().count_llvm_insns() {
151             *self.cx().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(&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(&self, llbb: &'ll BasicBlock) {
167         unsafe {
168             llvm::LLVMPositionBuilderAtEnd(self.llbuilder, llbb);
169         }
170     }
171
172     fn position_at_start(&self, llbb: &'ll BasicBlock) {
173         unsafe {
174             llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb);
175         }
176     }
177
178     fn ret_void(&self) {
179         self.count_insn("retvoid");
180         unsafe {
181             llvm::LLVMBuildRetVoid(self.llbuilder);
182         }
183     }
184
185     fn ret(&self, v: &'ll Value) {
186         self.count_insn("ret");
187         unsafe {
188             llvm::LLVMBuildRet(self.llbuilder, v);
189         }
190     }
191
192     fn br(&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         &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         &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         &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(&self) {
253         self.count_insn("unreachable");
254         unsafe {
255             llvm::LLVMBuildUnreachable(self.llbuilder);
256         }
257     }
258
259     /* Arithmetic */
260     fn add(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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 alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
468         let bx = Builder::with_cx(self.cx);
469         bx.position_at_start(unsafe {
470             llvm::LLVMGetFirstBasicBlock(self.llfn())
471         });
472         bx.dynamic_alloca(ty, name, align)
473     }
474
475     fn dynamic_alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
476         self.count_insn("alloca");
477         unsafe {
478             let alloca = if name.is_empty() {
479                 llvm::LLVMBuildAlloca(self.llbuilder, ty, noname())
480             } else {
481                 let name = SmallCStr::new(name);
482                 llvm::LLVMBuildAlloca(self.llbuilder, ty,
483                                       name.as_ptr())
484             };
485             llvm::LLVMSetAlignment(alloca, align.abi() as c_uint);
486             alloca
487         }
488     }
489
490     fn array_alloca(&self,
491                         ty: &'ll Type,
492                         len: &'ll Value,
493                         name: &str,
494                         align: Align) -> &'ll Value {
495         self.count_insn("alloca");
496         unsafe {
497             let alloca = if name.is_empty() {
498                 llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, noname())
499             } else {
500                 let name = SmallCStr::new(name);
501                 llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len,
502                                            name.as_ptr())
503             };
504             llvm::LLVMSetAlignment(alloca, align.abi() as c_uint);
505             alloca
506         }
507     }
508
509     fn load(&self, ptr: &'ll Value, align: Align) -> &'ll Value {
510         self.count_insn("load");
511         unsafe {
512             let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
513             llvm::LLVMSetAlignment(load, align.abi() as c_uint);
514             load
515         }
516     }
517
518     fn volatile_load(&self, ptr: &'ll Value) -> &'ll Value {
519         self.count_insn("load.volatile");
520         unsafe {
521             let insn = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
522             llvm::LLVMSetVolatile(insn, llvm::True);
523             insn
524         }
525     }
526
527     fn atomic_load(
528         &self,
529         ptr: &'ll Value,
530         order: rustc_codegen_ssa::common::AtomicOrdering,
531         size: Size,
532     ) -> &'ll Value {
533         self.count_insn("load.atomic");
534         unsafe {
535             let load = llvm::LLVMRustBuildAtomicLoad(
536                 self.llbuilder,
537                 ptr,
538                 noname(),
539                 AtomicOrdering::from_generic(order),
540             );
541             // LLVM requires the alignment of atomic loads to be at least the size of the type.
542             llvm::LLVMSetAlignment(load, size.bytes() as c_uint);
543             load
544         }
545     }
546
547     fn load_operand(
548         &self,
549         place: PlaceRef<'tcx, &'ll Value>
550     ) -> OperandRef<'tcx, &'ll Value> {
551         debug!("PlaceRef::load: {:?}", place);
552
553         assert_eq!(place.llextra.is_some(), place.layout.is_unsized());
554
555         if place.layout.is_zst() {
556             return OperandRef::new_zst(self.cx(), place.layout);
557         }
558
559         let scalar_load_metadata = |load, scalar: &layout::Scalar| {
560             let vr = scalar.valid_range.clone();
561             match scalar.value {
562                 layout::Int(..) => {
563                     let range = scalar.valid_range_exclusive(self.cx());
564                     if range.start != range.end {
565                         self.range_metadata(load, range);
566                     }
567                 }
568                 layout::Pointer if vr.start() < vr.end() && !vr.contains(&0) => {
569                     self.nonnull_metadata(load);
570                 }
571                 _ => {}
572             }
573         };
574
575         let val = if let Some(llextra) = place.llextra {
576             OperandValue::Ref(place.llval, Some(llextra), place.align)
577         } else if place.layout.is_llvm_immediate() {
578             let mut const_llval = None;
579             unsafe {
580                 if let Some(global) = llvm::LLVMIsAGlobalVariable(place.llval) {
581                     if llvm::LLVMIsGlobalConstant(global) == llvm::True {
582                         const_llval = llvm::LLVMGetInitializer(global);
583                     }
584                 }
585             }
586             let llval = const_llval.unwrap_or_else(|| {
587                 let load = self.load(place.llval, place.align);
588                 if let layout::Abi::Scalar(ref scalar) = place.layout.abi {
589                     scalar_load_metadata(load, scalar);
590                 }
591                 load
592             });
593             OperandValue::Immediate(base::to_immediate(self, llval, place.layout))
594         } else if let layout::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
595             let load = |i, scalar: &layout::Scalar| {
596                 let llptr = self.struct_gep(place.llval, i as u64);
597                 let load = self.load(llptr, place.align);
598                 scalar_load_metadata(load, scalar);
599                 if scalar.is_bool() {
600                     self.trunc(load, self.cx().type_i1())
601                 } else {
602                     load
603                 }
604             };
605             OperandValue::Pair(load(0, a), load(1, b))
606         } else {
607             OperandValue::Ref(place.llval, None, place.align)
608         };
609
610         OperandRef { val, layout: place.layout }
611     }
612
613
614
615     fn range_metadata(&self, load: &'ll Value, range: Range<u128>) {
616         if self.cx().sess().target.target.arch == "amdgpu" {
617             // amdgpu/LLVM does something weird and thinks a i64 value is
618             // split into a v2i32, halving the bitwidth LLVM expects,
619             // tripping an assertion. So, for now, just disable this
620             // optimization.
621             return;
622         }
623
624         unsafe {
625             let llty = self.cx.val_ty(load);
626             let v = [
627                 self.cx.const_uint_big(llty, range.start),
628                 self.cx.const_uint_big(llty, range.end)
629             ];
630
631             llvm::LLVMSetMetadata(load, llvm::MD_range as c_uint,
632                                   llvm::LLVMMDNodeInContext(self.cx.llcx,
633                                                             v.as_ptr(),
634                                                             v.len() as c_uint));
635         }
636     }
637
638     fn nonnull_metadata(&self, load: &'ll Value) {
639         unsafe {
640             llvm::LLVMSetMetadata(load, llvm::MD_nonnull as c_uint,
641                                   llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0));
642         }
643     }
644
645     fn store(&self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value {
646         self.store_with_flags(val, ptr, align, MemFlags::empty())
647     }
648
649     fn store_with_flags(
650         &self,
651         val: &'ll Value,
652         ptr: &'ll Value,
653         align: Align,
654         flags: MemFlags,
655     ) -> &'ll Value {
656         debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags);
657         self.count_insn("store");
658         let ptr = self.check_store(val, ptr);
659         unsafe {
660             let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
661             let align = if flags.contains(MemFlags::UNALIGNED) {
662                 1
663             } else {
664                 align.abi() as c_uint
665             };
666             llvm::LLVMSetAlignment(store, align);
667             if flags.contains(MemFlags::VOLATILE) {
668                 llvm::LLVMSetVolatile(store, llvm::True);
669             }
670             if flags.contains(MemFlags::NONTEMPORAL) {
671                 // According to LLVM [1] building a nontemporal store must
672                 // *always* point to a metadata value of the integer 1.
673                 //
674                 // [1]: http://llvm.org/docs/LangRef.html#store-instruction
675                 let one = self.cx.const_i32(1);
676                 let node = llvm::LLVMMDNodeInContext(self.cx.llcx, &one, 1);
677                 llvm::LLVMSetMetadata(store, llvm::MD_nontemporal as c_uint, node);
678             }
679             store
680         }
681     }
682
683    fn atomic_store(&self, val: &'ll Value, ptr: &'ll Value,
684                    order: rustc_codegen_ssa::common::AtomicOrdering, size: Size) {
685         debug!("Store {:?} -> {:?}", val, ptr);
686         self.count_insn("store.atomic");
687         let ptr = self.check_store(val, ptr);
688         unsafe {
689             let store = llvm::LLVMRustBuildAtomicStore(
690                 self.llbuilder,
691                 val,
692                 ptr,
693                 AtomicOrdering::from_generic(order),
694             );
695             // LLVM requires the alignment of atomic stores to be at least the size of the type.
696             llvm::LLVMSetAlignment(store, size.bytes() as c_uint);
697         }
698     }
699
700     fn gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
701         self.count_insn("gep");
702         unsafe {
703             llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(),
704                                indices.len() as c_uint, noname())
705         }
706     }
707
708     fn inbounds_gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
709         self.count_insn("inboundsgep");
710         unsafe {
711             llvm::LLVMBuildInBoundsGEP(
712                 self.llbuilder, ptr, indices.as_ptr(), indices.len() as c_uint, noname())
713         }
714     }
715
716     /* Casts */
717     fn trunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
718         self.count_insn("trunc");
719         unsafe {
720             llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, noname())
721         }
722     }
723
724     fn sext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
725         self.count_insn("sext");
726         unsafe {
727             llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, noname())
728         }
729     }
730
731     fn fptoui(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
732         self.count_insn("fptoui");
733         unsafe {
734             llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, noname())
735         }
736     }
737
738     fn fptosi(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
739         self.count_insn("fptosi");
740         unsafe {
741             llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,noname())
742         }
743     }
744
745     fn uitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
746         self.count_insn("uitofp");
747         unsafe {
748             llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, noname())
749         }
750     }
751
752     fn sitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
753         self.count_insn("sitofp");
754         unsafe {
755             llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, noname())
756         }
757     }
758
759     fn fptrunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
760         self.count_insn("fptrunc");
761         unsafe {
762             llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, noname())
763         }
764     }
765
766     fn fpext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
767         self.count_insn("fpext");
768         unsafe {
769             llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, noname())
770         }
771     }
772
773     fn ptrtoint(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
774         self.count_insn("ptrtoint");
775         unsafe {
776             llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, noname())
777         }
778     }
779
780     fn inttoptr(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
781         self.count_insn("inttoptr");
782         unsafe {
783             llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, noname())
784         }
785     }
786
787     fn bitcast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
788         self.count_insn("bitcast");
789         unsafe {
790             llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, noname())
791         }
792     }
793
794
795     fn intcast(&self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value {
796         self.count_insn("intcast");
797         unsafe {
798             llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed)
799         }
800     }
801
802     fn pointercast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
803         self.count_insn("pointercast");
804         unsafe {
805             llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname())
806         }
807     }
808
809     /* Comparisons */
810     fn icmp(&self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
811         self.count_insn("icmp");
812         let op = llvm::IntPredicate::from_generic(op);
813         unsafe {
814             llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
815         }
816     }
817
818     fn fcmp(&self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
819         self.count_insn("fcmp");
820         unsafe {
821             llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
822         }
823     }
824
825     /* Miscellaneous instructions */
826     fn empty_phi(&self, ty: &'ll Type) -> &'ll Value {
827         self.count_insn("emptyphi");
828         unsafe {
829             llvm::LLVMBuildPhi(self.llbuilder, ty, noname())
830         }
831     }
832
833     fn phi(&self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
834         assert_eq!(vals.len(), bbs.len());
835         let phi = self.empty_phi(ty);
836         self.count_insn("addincoming");
837         unsafe {
838             llvm::LLVMAddIncoming(phi, vals.as_ptr(),
839                                   bbs.as_ptr(),
840                                   vals.len() as c_uint);
841             phi
842         }
843     }
844
845     fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char,
846                        inputs: &[&'ll Value], output: &'ll Type,
847                        volatile: bool, alignstack: bool,
848                        dia: syntax::ast::AsmDialect) -> Option<&'ll Value> {
849         self.count_insn("inlineasm");
850
851         let volatile = if volatile { llvm::True }
852                        else        { llvm::False };
853         let alignstack = if alignstack { llvm::True }
854                          else          { llvm::False };
855
856         let argtys = inputs.iter().map(|v| {
857             debug!("Asm Input Type: {:?}", *v);
858             self.cx.val_ty(*v)
859         }).collect::<Vec<_>>();
860
861         debug!("Asm Output Type: {:?}", output);
862         let fty = self.cx().type_func(&argtys[..], output);
863         unsafe {
864             // Ask LLVM to verify that the constraints are well-formed.
865             let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons);
866             debug!("Constraint verification result: {:?}", constraints_ok);
867             if constraints_ok {
868                 let v = llvm::LLVMRustInlineAsm(
869                     fty, asm, cons, volatile, alignstack, AsmDialect::from_generic(dia));
870                 Some(self.call(v, inputs, None))
871             } else {
872                 // LLVM has detected an issue with our constraints, bail out
873                 None
874             }
875         }
876     }
877
878     fn memcpy(&self, dst: &'ll Value, dst_align: Align,
879                   src: &'ll Value, src_align: Align,
880                   size: &'ll Value, flags: MemFlags) {
881         if flags.contains(MemFlags::NONTEMPORAL) {
882             // HACK(nox): This is inefficient but there is no nontemporal memcpy.
883             let val = self.load(src, src_align);
884             let ptr = self.pointercast(dst, self.cx().type_ptr_to(self.cx().val_ty(val)));
885             self.store_with_flags(val, ptr, dst_align, flags);
886             return;
887         }
888         let size = self.intcast(size, self.cx().type_isize(), false);
889         let is_volatile = flags.contains(MemFlags::VOLATILE);
890         let dst = self.pointercast(dst, self.cx().type_i8p());
891         let src = self.pointercast(src, self.cx().type_i8p());
892         unsafe {
893             llvm::LLVMRustBuildMemCpy(self.llbuilder, dst, dst_align.abi() as c_uint,
894                                       src, src_align.abi() as c_uint, size, is_volatile);
895         }
896     }
897
898     fn memmove(&self, dst: &'ll Value, dst_align: Align,
899                   src: &'ll Value, src_align: Align,
900                   size: &'ll Value, flags: MemFlags) {
901         if flags.contains(MemFlags::NONTEMPORAL) {
902             // HACK(nox): This is inefficient but there is no nontemporal memmove.
903             let val = self.load(src, src_align);
904             let ptr = self.pointercast(dst, self.cx().type_ptr_to(self.cx().val_ty(val)));
905             self.store_with_flags(val, ptr, dst_align, flags);
906             return;
907         }
908         let size = self.intcast(size, self.cx().type_isize(), false);
909         let is_volatile = flags.contains(MemFlags::VOLATILE);
910         let dst = self.pointercast(dst, self.cx().type_i8p());
911         let src = self.pointercast(src, self.cx().type_i8p());
912         unsafe {
913             llvm::LLVMRustBuildMemMove(self.llbuilder, dst, dst_align.abi() as c_uint,
914                                       src, src_align.abi() as c_uint, size, is_volatile);
915         }
916     }
917
918     fn memset(
919         &self,
920         ptr: &'ll Value,
921         fill_byte: &'ll Value,
922         size: &'ll Value,
923         align: Align,
924         flags: MemFlags,
925     ) {
926         let ptr_width = &self.cx().sess().target.target.target_pointer_width;
927         let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
928         let llintrinsicfn = self.cx().get_intrinsic(&intrinsic_key);
929         let ptr = self.pointercast(ptr, self.cx().type_i8p());
930         let align = self.cx().const_u32(align.abi() as u32);
931         let volatile = self.cx().const_bool(flags.contains(MemFlags::VOLATILE));
932         self.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None);
933     }
934
935     fn minnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
936         self.count_insn("minnum");
937         unsafe {
938             let instr = llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs);
939             instr.expect("LLVMRustBuildMinNum is not available in LLVM version < 6.0")
940         }
941     }
942     fn maxnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
943         self.count_insn("maxnum");
944         unsafe {
945             let instr = llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs);
946             instr.expect("LLVMRustBuildMaxNum is not available in LLVM version < 6.0")
947         }
948     }
949
950     fn select(
951         &self, cond: &'ll Value,
952         then_val: &'ll Value,
953         else_val: &'ll Value,
954     ) -> &'ll Value {
955         self.count_insn("select");
956         unsafe {
957             llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname())
958         }
959     }
960
961     #[allow(dead_code)]
962     fn va_arg(&self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
963         self.count_insn("vaarg");
964         unsafe {
965             llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
966         }
967     }
968
969     fn extract_element(&self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value {
970         self.count_insn("extractelement");
971         unsafe {
972             llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname())
973         }
974     }
975
976     fn insert_element(
977         &self, vec: &'ll Value,
978         elt: &'ll Value,
979         idx: &'ll Value,
980     ) -> &'ll Value {
981         self.count_insn("insertelement");
982         unsafe {
983             llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname())
984         }
985     }
986
987     fn shuffle_vector(&self, v1: &'ll Value, v2: &'ll Value, mask: &'ll Value) -> &'ll Value {
988         self.count_insn("shufflevector");
989         unsafe {
990             llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname())
991         }
992     }
993
994     fn vector_splat(&self, num_elts: usize, elt: &'ll Value) -> &'ll Value {
995         unsafe {
996             let elt_ty = self.cx.val_ty(elt);
997             let undef = llvm::LLVMGetUndef(self.cx().type_vector(elt_ty, num_elts as u64));
998             let vec = self.insert_element(undef, elt, self.cx.const_i32(0));
999             let vec_i32_ty = self.cx().type_vector(self.cx().type_i32(), num_elts as u64);
1000             self.shuffle_vector(vec, undef, self.cx().const_null(vec_i32_ty))
1001         }
1002     }
1003
1004     fn vector_reduce_fadd_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
1005         self.count_insn("vector.reduce.fadd_fast");
1006         unsafe {
1007             // FIXME: add a non-fast math version once
1008             // https://bugs.llvm.org/show_bug.cgi?id=36732
1009             // is fixed.
1010             let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src);
1011             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
1012             instr
1013         }
1014     }
1015     fn vector_reduce_fmul_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
1016         self.count_insn("vector.reduce.fmul_fast");
1017         unsafe {
1018             // FIXME: add a non-fast math version once
1019             // https://bugs.llvm.org/show_bug.cgi?id=36732
1020             // is fixed.
1021             let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src);
1022             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
1023             instr
1024         }
1025     }
1026     fn vector_reduce_add(&self, src: &'ll Value) -> &'ll Value {
1027         self.count_insn("vector.reduce.add");
1028         unsafe { llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) }
1029     }
1030     fn vector_reduce_mul(&self, src: &'ll Value) -> &'ll Value {
1031         self.count_insn("vector.reduce.mul");
1032         unsafe { llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) }
1033     }
1034     fn vector_reduce_and(&self, src: &'ll Value) -> &'ll Value {
1035         self.count_insn("vector.reduce.and");
1036         unsafe { llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) }
1037     }
1038     fn vector_reduce_or(&self, src: &'ll Value) -> &'ll Value {
1039         self.count_insn("vector.reduce.or");
1040         unsafe { llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) }
1041     }
1042     fn vector_reduce_xor(&self, src: &'ll Value) -> &'ll Value {
1043         self.count_insn("vector.reduce.xor");
1044         unsafe { llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) }
1045     }
1046     fn vector_reduce_fmin(&self, src: &'ll Value) -> &'ll Value {
1047         self.count_insn("vector.reduce.fmin");
1048         unsafe { llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false) }
1049     }
1050     fn vector_reduce_fmax(&self, src: &'ll Value) -> &'ll Value {
1051         self.count_insn("vector.reduce.fmax");
1052         unsafe { llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false) }
1053     }
1054     fn vector_reduce_fmin_fast(&self, src: &'ll Value) -> &'ll Value {
1055         self.count_insn("vector.reduce.fmin_fast");
1056         unsafe {
1057             let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true);
1058             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
1059             instr
1060         }
1061     }
1062     fn vector_reduce_fmax_fast(&self, src: &'ll Value) -> &'ll Value {
1063         self.count_insn("vector.reduce.fmax_fast");
1064         unsafe {
1065             let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true);
1066             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
1067             instr
1068         }
1069     }
1070     fn vector_reduce_min(&self, src: &'ll Value, is_signed: bool) -> &'ll Value {
1071         self.count_insn("vector.reduce.min");
1072         unsafe { llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) }
1073     }
1074     fn vector_reduce_max(&self, src: &'ll Value, is_signed: bool) -> &'ll Value {
1075         self.count_insn("vector.reduce.max");
1076         unsafe { llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed) }
1077     }
1078
1079     fn extract_value(&self, agg_val: &'ll Value, idx: u64) -> &'ll Value {
1080         self.count_insn("extractvalue");
1081         assert_eq!(idx as c_uint as u64, idx);
1082         unsafe {
1083             llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, noname())
1084         }
1085     }
1086
1087     fn insert_value(&self, agg_val: &'ll Value, elt: &'ll Value,
1088                        idx: u64) -> &'ll Value {
1089         self.count_insn("insertvalue");
1090         assert_eq!(idx as c_uint as u64, idx);
1091         unsafe {
1092             llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint,
1093                                        noname())
1094         }
1095     }
1096
1097     fn landing_pad(&self, ty: &'ll Type, pers_fn: &'ll Value,
1098                        num_clauses: usize) -> &'ll Value {
1099         self.count_insn("landingpad");
1100         unsafe {
1101             llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn,
1102                                       num_clauses as c_uint, noname())
1103         }
1104     }
1105
1106     fn add_clause(&self, landing_pad: &'ll Value, clause: &'ll Value) {
1107         unsafe {
1108             llvm::LLVMAddClause(landing_pad, clause);
1109         }
1110     }
1111
1112     fn set_cleanup(&self, landing_pad: &'ll Value) {
1113         self.count_insn("setcleanup");
1114         unsafe {
1115             llvm::LLVMSetCleanup(landing_pad, llvm::True);
1116         }
1117     }
1118
1119     fn resume(&self, exn: &'ll Value) -> &'ll Value {
1120         self.count_insn("resume");
1121         unsafe {
1122             llvm::LLVMBuildResume(self.llbuilder, exn)
1123         }
1124     }
1125
1126     fn cleanup_pad(&self,
1127                        parent: Option<&'ll Value>,
1128                        args: &[&'ll Value]) -> Funclet<'ll> {
1129         self.count_insn("cleanuppad");
1130         let name = const_cstr!("cleanuppad");
1131         let ret = unsafe {
1132             llvm::LLVMRustBuildCleanupPad(self.llbuilder,
1133                                           parent,
1134                                           args.len() as c_uint,
1135                                           args.as_ptr(),
1136                                           name.as_ptr())
1137         };
1138         Funclet::new(ret.expect("LLVM does not have support for cleanuppad"))
1139     }
1140
1141     fn cleanup_ret(
1142         &self, funclet: &Funclet<'ll>,
1143         unwind: Option<&'ll BasicBlock>,
1144     ) -> &'ll Value {
1145         self.count_insn("cleanupret");
1146         let ret = unsafe {
1147             llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind)
1148         };
1149         ret.expect("LLVM does not have support for cleanupret")
1150     }
1151
1152     fn catch_pad(&self,
1153                      parent: &'ll Value,
1154                      args: &[&'ll Value]) -> Funclet<'ll> {
1155         self.count_insn("catchpad");
1156         let name = const_cstr!("catchpad");
1157         let ret = unsafe {
1158             llvm::LLVMRustBuildCatchPad(self.llbuilder, parent,
1159                                         args.len() as c_uint, args.as_ptr(),
1160                                         name.as_ptr())
1161         };
1162         Funclet::new(ret.expect("LLVM does not have support for catchpad"))
1163     }
1164
1165     fn catch_ret(&self, funclet: &Funclet<'ll>, unwind: &'ll BasicBlock) -> &'ll Value {
1166         self.count_insn("catchret");
1167         let ret = unsafe {
1168             llvm::LLVMRustBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind)
1169         };
1170         ret.expect("LLVM does not have support for catchret")
1171     }
1172
1173     fn catch_switch(
1174         &self,
1175         parent: Option<&'ll Value>,
1176         unwind: Option<&'ll BasicBlock>,
1177         num_handlers: usize,
1178     ) -> &'ll Value {
1179         self.count_insn("catchswitch");
1180         let name = const_cstr!("catchswitch");
1181         let ret = unsafe {
1182             llvm::LLVMRustBuildCatchSwitch(self.llbuilder, parent, unwind,
1183                                            num_handlers as c_uint,
1184                                            name.as_ptr())
1185         };
1186         ret.expect("LLVM does not have support for catchswitch")
1187     }
1188
1189     fn add_handler(&self, catch_switch: &'ll Value, handler: &'ll BasicBlock) {
1190         unsafe {
1191             llvm::LLVMRustAddHandler(catch_switch, handler);
1192         }
1193     }
1194
1195     fn set_personality_fn(&self, personality: &'ll Value) {
1196         unsafe {
1197             llvm::LLVMSetPersonalityFn(self.llfn(), personality);
1198         }
1199     }
1200
1201     // Atomic Operations
1202     fn atomic_cmpxchg(
1203         &self,
1204         dst: &'ll Value,
1205         cmp: &'ll Value,
1206         src: &'ll Value,
1207         order: rustc_codegen_ssa::common::AtomicOrdering,
1208         failure_order: rustc_codegen_ssa::common::AtomicOrdering,
1209         weak: bool,
1210     ) -> &'ll Value {
1211         let weak = if weak { llvm::True } else { llvm::False };
1212         unsafe {
1213             llvm::LLVMRustBuildAtomicCmpXchg(
1214                 self.llbuilder,
1215                 dst,
1216                 cmp,
1217                 src,
1218                 AtomicOrdering::from_generic(order),
1219                 AtomicOrdering::from_generic(failure_order),
1220                 weak
1221             )
1222         }
1223     }
1224     fn atomic_rmw(
1225         &self,
1226         op: rustc_codegen_ssa::common::AtomicRmwBinOp,
1227         dst: &'ll Value,
1228         src: &'ll Value,
1229         order: rustc_codegen_ssa::common::AtomicOrdering,
1230     ) -> &'ll Value {
1231         unsafe {
1232             llvm::LLVMBuildAtomicRMW(
1233                 self.llbuilder,
1234                 AtomicRmwBinOp::from_generic(op),
1235                 dst,
1236                 src,
1237                 AtomicOrdering::from_generic(order),
1238                 False)
1239         }
1240     }
1241
1242     fn atomic_fence(
1243         &self,
1244         order: rustc_codegen_ssa::common::AtomicOrdering,
1245         scope: rustc_codegen_ssa::common::SynchronizationScope
1246     ) {
1247         unsafe {
1248             llvm::LLVMRustBuildAtomicFence(
1249                 self.llbuilder,
1250                 AtomicOrdering::from_generic(order),
1251                 SynchronizationScope::from_generic(scope)
1252             );
1253         }
1254     }
1255
1256     fn add_case(&self, s: &'ll Value, on_val: &'ll Value, dest: &'ll BasicBlock) {
1257         unsafe {
1258             llvm::LLVMAddCase(s, on_val, dest)
1259         }
1260     }
1261
1262     fn add_incoming_to_phi(&self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) {
1263         self.count_insn("addincoming");
1264         unsafe {
1265             llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
1266         }
1267     }
1268
1269     fn set_invariant_load(&self, load: &'ll Value) {
1270         unsafe {
1271             llvm::LLVMSetMetadata(load, llvm::MD_invariant_load as c_uint,
1272                                   llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0));
1273         }
1274     }
1275
1276     fn check_store<'b>(&self,
1277                        val: &'ll Value,
1278                        ptr: &'ll Value) -> &'ll Value {
1279         let dest_ptr_ty = self.cx.val_ty(ptr);
1280         let stored_ty = self.cx.val_ty(val);
1281         let stored_ptr_ty = self.cx.type_ptr_to(stored_ty);
1282
1283         assert_eq!(self.cx.type_kind(dest_ptr_ty), TypeKind::Pointer);
1284
1285         if dest_ptr_ty == stored_ptr_ty {
1286             ptr
1287         } else {
1288             debug!("Type mismatch in store. \
1289                     Expected {:?}, got {:?}; inserting bitcast",
1290                    dest_ptr_ty, stored_ptr_ty);
1291             self.bitcast(ptr, stored_ptr_ty)
1292         }
1293     }
1294
1295     fn check_call<'b>(&self,
1296                       typ: &str,
1297                       llfn: &'ll Value,
1298                       args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> {
1299         let mut fn_ty = self.cx.val_ty(llfn);
1300         // Strip off pointers
1301         while self.cx.type_kind(fn_ty) == TypeKind::Pointer {
1302             fn_ty = self.cx.element_type(fn_ty);
1303         }
1304
1305         assert!(self.cx.type_kind(fn_ty) == TypeKind::Function,
1306                 "builder::{} not passed a function, but {:?}", typ, fn_ty);
1307
1308         let param_tys = self.cx.func_params_types(fn_ty);
1309
1310         let all_args_match = param_tys.iter()
1311             .zip(args.iter().map(|&v| self.cx().val_ty(v)))
1312             .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
1313
1314         if all_args_match {
1315             return Cow::Borrowed(args);
1316         }
1317
1318         let casted_args: Vec<_> = param_tys.into_iter()
1319             .zip(args.iter())
1320             .enumerate()
1321             .map(|(i, (expected_ty, &actual_val))| {
1322                 let actual_ty = self.cx().val_ty(actual_val);
1323                 if expected_ty != actual_ty {
1324                     debug!("Type mismatch in function call of {:?}. \
1325                             Expected {:?} for param {}, got {:?}; injecting bitcast",
1326                            llfn, expected_ty, i, actual_ty);
1327                     self.bitcast(actual_val, expected_ty)
1328                 } else {
1329                     actual_val
1330                 }
1331             })
1332             .collect();
1333
1334         Cow::Owned(casted_args)
1335     }
1336
1337     fn lifetime_start(&self, ptr: &'ll Value, size: Size) {
1338         self.call_lifetime_intrinsic("llvm.lifetime.start", ptr, size);
1339     }
1340
1341     fn lifetime_end(&self, ptr: &'ll Value, size: Size) {
1342         self.call_lifetime_intrinsic("llvm.lifetime.end", ptr, size);
1343     }
1344
1345     fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: &'ll Value, size: Size) {
1346         if self.cx.sess().opts.optimize == config::OptLevel::No {
1347             return;
1348         }
1349
1350         let size = size.bytes();
1351         if size == 0 {
1352             return;
1353         }
1354
1355         let lifetime_intrinsic = self.cx.get_intrinsic(intrinsic);
1356
1357         let ptr = self.pointercast(ptr, self.cx.type_i8p());
1358         self.call(lifetime_intrinsic, &[self.cx.const_u64(size), ptr], None);
1359     }
1360
1361     fn call(
1362         &self,
1363         llfn: &'ll Value,
1364         args: &[&'ll Value],
1365         funclet: Option<&Funclet<'ll>>,
1366     ) -> &'ll Value {
1367         self.count_insn("call");
1368
1369         debug!("Call {:?} with args ({:?})",
1370                llfn,
1371                args);
1372
1373         let args = self.check_call("call", llfn, args);
1374         let bundle = funclet.map(|funclet| funclet.bundle());
1375         let bundle = bundle.as_ref().map(|b| &*b.raw);
1376
1377         unsafe {
1378             llvm::LLVMRustBuildCall(
1379                 self.llbuilder,
1380                 llfn,
1381                 args.as_ptr() as *const &llvm::Value,
1382                 args.len() as c_uint,
1383                 bundle, noname()
1384             )
1385         }
1386     }
1387
1388     fn zext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
1389         self.count_insn("zext");
1390         unsafe {
1391             llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, noname())
1392         }
1393     }
1394
1395     fn struct_gep(&self, ptr: &'ll Value, idx: u64) -> &'ll Value {
1396         self.count_insn("structgep");
1397         assert_eq!(idx as c_uint as u64, idx);
1398         unsafe {
1399             llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname())
1400         }
1401     }
1402
1403     fn cx(&self) -> &CodegenCx<'ll, 'tcx> {
1404         self.cx
1405     }
1406
1407     fn delete_basic_block(&self, bb: &'ll BasicBlock) {
1408         unsafe {
1409             llvm::LLVMDeleteBasicBlock(bb);
1410         }
1411     }
1412
1413     fn do_not_inline(&self, llret: &'ll Value) {
1414         llvm::Attribute::NoInline.apply_callsite(llvm::AttributePlace::Function, llret);
1415     }
1416 }