builder.rs 43.1 KB
Newer Older
T
Taiki Endo 已提交
1 2
use crate::common::Funclet;
use crate::context::CodegenCx;
M
Mark Rousskov 已提交
3 4
use crate::llvm::{self, BasicBlock, False};
use crate::llvm::{AtomicOrdering, AtomicRmwBinOp, SynchronizationScope};
T
Taiki Endo 已提交
5 6 7
use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
M
Mark Rousskov 已提交
8 9
use libc::{c_char, c_uint};
use log::debug;
10
use rustc_codegen_ssa::base::to_immediate;
M
Mark Rousskov 已提交
11 12
use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, TypeKind};
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
13
use rustc_codegen_ssa::mir::place::PlaceRef;
M
Mark Rousskov 已提交
14 15 16 17
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::MemFlags;
use rustc_data_structures::const_cstr;
use rustc_data_structures::small_c_str::SmallCStr;
18
use rustc_hir::def_id::DefId;
19
use rustc_middle::ty::layout::TyAndLayout;
M
Mazdak Farrokhzad 已提交
20
use rustc_middle::ty::{self, Ty, TyCtxt};
21
use rustc_target::abi::{self, Align, Size};
S
Saleem Jaffer 已提交
22
use rustc_target::spec::{HasTargetSpec, Target};
23
use std::borrow::Cow;
24
use std::ffi::CStr;
M
Mark Rousskov 已提交
25
use std::iter::TrustedLen;
B
bjorn3 已提交
26
use std::ops::{Deref, Range};
27
use std::ptr;
28

29 30
// All Builders must have an llfn associated with them
#[must_use]
31
pub struct Builder<'a, 'll, 'tcx> {
32
    pub llbuilder: &'ll mut llvm::Builder<'ll>,
33
    pub cx: &'a CodegenCx<'ll, 'tcx>,
34 35
}

36
impl Drop for Builder<'a, 'll, 'tcx> {
M
Mark-Simulacrum 已提交
37 38
    fn drop(&mut self) {
        unsafe {
39
            llvm::LLVMDisposeBuilder(&mut *(self.llbuilder as *mut _));
M
Mark-Simulacrum 已提交
40 41 42 43
        }
    }
}

44
// FIXME(eddyb) use a checked constructor when they become `const fn`.
M
Mark Rousskov 已提交
45
const EMPTY_C_STR: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"\0") };
46 47 48 49 50

/// Empty string, to be used where LLVM expects an instruction name, indicating
/// that the instruction is to be left unnamed (i.e. numbered, in textual IR).
// FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer.
const UNNAMED: *const c_char = EMPTY_C_STR.as_ptr();
51

52 53
impl BackendTypes for Builder<'_, 'll, 'tcx> {
    type Value = <CodegenCx<'ll, 'tcx> as BackendTypes>::Value;
B
bjorn3 已提交
54
    type Function = <CodegenCx<'ll, 'tcx> as BackendTypes>::Function;
55 56
    type BasicBlock = <CodegenCx<'ll, 'tcx> as BackendTypes>::BasicBlock;
    type Type = <CodegenCx<'ll, 'tcx> as BackendTypes>::Type;
57
    type Funclet = <CodegenCx<'ll, 'tcx> as BackendTypes>::Funclet;
58 59

    type DIScope = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIScope;
60
    type DIVariable = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIVariable;
D
Denis Merigoux 已提交
61 62
}

63 64
impl abi::HasDataLayout for Builder<'_, '_, '_> {
    fn data_layout(&self) -> &abi::TargetDataLayout {
D
Denis Merigoux 已提交
65 66 67 68 69
        self.cx.data_layout()
    }
}

impl ty::layout::HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> {
70
    fn tcx(&self) -> TyCtxt<'tcx> {
D
Denis Merigoux 已提交
71 72 73 74
        self.cx.tcx
    }
}

S
Saleem Jaffer 已提交
75 76 77 78 79 80
impl ty::layout::HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> {
    fn param_env(&self) -> ty::ParamEnv<'tcx> {
        self.cx.param_env()
    }
}

S
Saleem Jaffer 已提交
81 82 83 84 85 86
impl HasTargetSpec for Builder<'_, '_, 'tcx> {
    fn target_spec(&self) -> &Target {
        &self.cx.target_spec()
    }
}

87
impl abi::LayoutOf for Builder<'_, '_, 'tcx> {
D
Denis Merigoux 已提交
88
    type Ty = Ty<'tcx>;
89
    type TyAndLayout = TyAndLayout<'tcx>;
D
Denis Merigoux 已提交
90

91
    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
D
Denis Merigoux 已提交
92 93 94 95
        self.cx.layout_of(ty)
    }
}

B
bjorn3 已提交
96 97 98 99 100 101 102
impl Deref for Builder<'_, 'll, 'tcx> {
    type Target = CodegenCx<'ll, 'tcx>;

    fn deref(&self) -> &Self::Target {
        self.cx
    }
}
D
Denis Merigoux 已提交
103 104

impl HasCodegen<'tcx> for Builder<'_, 'll, 'tcx> {
D
Denis Merigoux 已提交
105
    type CodegenCx = CodegenCx<'ll, 'tcx>;
106
}
107

108 109 110 111
macro_rules! builder_methods_for_value_instructions {
    ($($name:ident($($arg:ident),*) => $llvm_capi:ident),+ $(,)?) => {
        $(fn $name(&mut self, $($arg: &'ll Value),*) -> &'ll Value {
            unsafe {
112
                llvm::$llvm_capi(self.llbuilder, $($arg,)* UNNAMED)
113
            }
114
        })+
115 116 117
    }
}

118
impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
M
Mark Rousskov 已提交
119
    fn new_block<'b>(cx: &'a CodegenCx<'ll, 'tcx>, llfn: &'ll Value, name: &'b str) -> Self {
120
        let mut bx = Builder::with_cx(cx);
121
        let llbb = unsafe {
122
            let name = SmallCStr::new(name);
M
Mark Rousskov 已提交
123
            llvm::LLVMAppendBasicBlockInContext(cx.llcx, llfn, name.as_ptr())
124
        };
125 126
        bx.position_at_end(llbb);
        bx
127 128
    }

129
    fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self {
M
Mark-Simulacrum 已提交
130
        // Create a fresh builder from the crate context.
M
Mark Rousskov 已提交
131 132
        let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(cx.llcx) };
        Builder { llbuilder, cx }
133 134
    }

J
Jeremy Stucki 已提交
135
    fn build_sibling_block(&self, name: &str) -> Self {
136
        Builder::new_block(self.cx, self.llfn(), name)
137 138
    }

139
    fn llbb(&self) -> &'ll BasicBlock {
M
Mark Rousskov 已提交
140
        unsafe { llvm::LLVMGetInsertBlock(self.llbuilder) }
141 142
    }

143
    fn position_at_end(&mut self, llbb: &'ll BasicBlock) {
144 145 146 147 148
        unsafe {
            llvm::LLVMPositionBuilderAtEnd(self.llbuilder, llbb);
        }
    }

149
    fn ret_void(&mut self) {
150 151 152 153 154
        unsafe {
            llvm::LLVMBuildRetVoid(self.llbuilder);
        }
    }

155
    fn ret(&mut self, v: &'ll Value) {
156 157 158 159 160
        unsafe {
            llvm::LLVMBuildRet(self.llbuilder, v);
        }
    }

161
    fn br(&mut self, dest: &'ll BasicBlock) {
162 163 164 165 166
        unsafe {
            llvm::LLVMBuildBr(self.llbuilder, dest);
        }
    }

167
    fn cond_br(
168
        &mut self,
169 170 171
        cond: &'ll Value,
        then_llbb: &'ll BasicBlock,
        else_llbb: &'ll BasicBlock,
172
    ) {
173 174 175 176 177
        unsafe {
            llvm::LLVMBuildCondBr(self.llbuilder, cond, then_llbb, else_llbb);
        }
    }

178
    fn switch(
179
        &mut self,
180 181
        v: &'ll Value,
        else_llbb: &'ll BasicBlock,
182
        cases: impl ExactSizeIterator<Item = (u128, &'ll BasicBlock)> + TrustedLen,
B
bjorn3 已提交
183
    ) {
M
Mark Rousskov 已提交
184 185
        let switch =
            unsafe { llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, cases.len() as c_uint) };
B
bjorn3 已提交
186 187
        for (on_val, dest) in cases {
            let on_val = self.const_uint_big(self.val_ty(v), on_val);
M
Mark Rousskov 已提交
188
            unsafe { llvm::LLVMAddCase(switch, on_val, dest) }
189 190 191
        }
    }

192
    fn invoke(
193
        &mut self,
194 195 196 197 198 199
        llfn: &'ll Value,
        args: &[&'ll Value],
        then: &'ll BasicBlock,
        catch: &'ll BasicBlock,
        funclet: Option<&Funclet<'ll>>,
    ) -> &'ll Value {
M
Mark Rousskov 已提交
200
        debug!("invoke {:?} with args ({:?})", llfn, args);
201

202
        let args = self.check_call("invoke", llfn, args);
203
        let bundle = funclet.map(|funclet| funclet.bundle());
204
        let bundle = bundle.as_ref().map(|b| &*b.raw);
205

206
        unsafe {
M
Mark Rousskov 已提交
207 208 209 210 211 212 213 214 215 216
            llvm::LLVMRustBuildInvoke(
                self.llbuilder,
                llfn,
                args.as_ptr(),
                args.len() as c_uint,
                then,
                catch,
                bundle,
                UNNAMED,
            )
217
        }
218 219
    }

220
    fn unreachable(&mut self) {
221 222 223 224 225
        unsafe {
            llvm::LLVMBuildUnreachable(self.llbuilder);
        }
    }

226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
    builder_methods_for_value_instructions! {
        add(a, b) => LLVMBuildAdd,
        fadd(a, b) => LLVMBuildFAdd,
        sub(a, b) => LLVMBuildSub,
        fsub(a, b) => LLVMBuildFSub,
        mul(a, b) => LLVMBuildMul,
        fmul(a, b) => LLVMBuildFMul,
        udiv(a, b) => LLVMBuildUDiv,
        exactudiv(a, b) => LLVMBuildExactUDiv,
        sdiv(a, b) => LLVMBuildSDiv,
        exactsdiv(a, b) => LLVMBuildExactSDiv,
        fdiv(a, b) => LLVMBuildFDiv,
        urem(a, b) => LLVMBuildURem,
        srem(a, b) => LLVMBuildSRem,
        frem(a, b) => LLVMBuildFRem,
        shl(a, b) => LLVMBuildShl,
        lshr(a, b) => LLVMBuildLShr,
        ashr(a, b) => LLVMBuildAShr,
        and(a, b) => LLVMBuildAnd,
        or(a, b) => LLVMBuildOr,
        xor(a, b) => LLVMBuildXor,
        neg(x) => LLVMBuildNeg,
        fneg(x) => LLVMBuildFNeg,
        not(x) => LLVMBuildNot,
250 251 252 253 254 255
        unchecked_sadd(x, y) => LLVMBuildNSWAdd,
        unchecked_uadd(x, y) => LLVMBuildNUWAdd,
        unchecked_ssub(x, y) => LLVMBuildNSWSub,
        unchecked_usub(x, y) => LLVMBuildNUWSub,
        unchecked_smul(x, y) => LLVMBuildNSWMul,
        unchecked_umul(x, y) => LLVMBuildNUWMul,
256 257
    }

258
    fn fadd_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
259
        unsafe {
260
            let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, UNNAMED);
261 262 263 264 265
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }

266
    fn fsub_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
267
        unsafe {
268
            let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, UNNAMED);
269 270 271 272 273
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }

274
    fn fmul_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
275
        unsafe {
276
            let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, UNNAMED);
277 278 279 280 281
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }

282
    fn fdiv_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
283
        unsafe {
284
            let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, UNNAMED);
285 286 287 288 289
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }

290
    fn frem_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
291
        unsafe {
292
            let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, UNNAMED);
293 294 295 296 297
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }

298 299 300
    fn checked_binop(
        &mut self,
        oop: OverflowOp,
301
        ty: Ty<'_>,
302 303 304
        lhs: Self::Value,
        rhs: Self::Value,
    ) -> (Self::Value, Self::Value) {
305 306
        use rustc_ast::ast::IntTy::*;
        use rustc_ast::ast::UintTy::*;
M
Mazdak Farrokhzad 已提交
307
        use rustc_middle::ty::{Int, Uint};
308

V
varkor 已提交
309
        let new_kind = match ty.kind {
M
Mark Rousskov 已提交
310 311
            Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.ptr_width)),
            Uint(t @ Usize) => Uint(t.normalize(self.tcx.sess.target.ptr_width)),
312
            ref t @ (Uint(_) | Int(_)) => t.clone(),
M
Mark Rousskov 已提交
313
            _ => panic!("tried to get overflow intrinsic for op applied to non-int type"),
314 315 316
        };

        let name = match oop {
V
varkor 已提交
317
            OverflowOp::Add => match new_kind {
318 319 320 321 322 323 324 325 326 327 328 329 330 331
                Int(I8) => "llvm.sadd.with.overflow.i8",
                Int(I16) => "llvm.sadd.with.overflow.i16",
                Int(I32) => "llvm.sadd.with.overflow.i32",
                Int(I64) => "llvm.sadd.with.overflow.i64",
                Int(I128) => "llvm.sadd.with.overflow.i128",

                Uint(U8) => "llvm.uadd.with.overflow.i8",
                Uint(U16) => "llvm.uadd.with.overflow.i16",
                Uint(U32) => "llvm.uadd.with.overflow.i32",
                Uint(U64) => "llvm.uadd.with.overflow.i64",
                Uint(U128) => "llvm.uadd.with.overflow.i128",

                _ => unreachable!(),
            },
V
varkor 已提交
332
            OverflowOp::Sub => match new_kind {
333 334 335 336 337 338 339 340 341 342 343 344 345 346
                Int(I8) => "llvm.ssub.with.overflow.i8",
                Int(I16) => "llvm.ssub.with.overflow.i16",
                Int(I32) => "llvm.ssub.with.overflow.i32",
                Int(I64) => "llvm.ssub.with.overflow.i64",
                Int(I128) => "llvm.ssub.with.overflow.i128",

                Uint(U8) => "llvm.usub.with.overflow.i8",
                Uint(U16) => "llvm.usub.with.overflow.i16",
                Uint(U32) => "llvm.usub.with.overflow.i32",
                Uint(U64) => "llvm.usub.with.overflow.i64",
                Uint(U128) => "llvm.usub.with.overflow.i128",

                _ => unreachable!(),
            },
V
varkor 已提交
347
            OverflowOp::Mul => match new_kind {
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
                Int(I8) => "llvm.smul.with.overflow.i8",
                Int(I16) => "llvm.smul.with.overflow.i16",
                Int(I32) => "llvm.smul.with.overflow.i32",
                Int(I64) => "llvm.smul.with.overflow.i64",
                Int(I128) => "llvm.smul.with.overflow.i128",

                Uint(U8) => "llvm.umul.with.overflow.i8",
                Uint(U16) => "llvm.umul.with.overflow.i16",
                Uint(U32) => "llvm.umul.with.overflow.i32",
                Uint(U64) => "llvm.umul.with.overflow.i64",
                Uint(U128) => "llvm.umul.with.overflow.i128",

                _ => unreachable!(),
            },
        };

364
        let intrinsic = self.get_intrinsic(&name);
365
        let res = self.call(intrinsic, &[lhs, rhs], None);
M
Mark Rousskov 已提交
366
        (self.extract_value(res, 0), self.extract_value(res, 1))
367 368
    }

369
    fn alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value {
370
        let mut bx = Builder::with_cx(self.cx);
M
Mark Rousskov 已提交
371
        bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) });
372
        bx.dynamic_alloca(ty, align)
373 374
    }

375
    fn dynamic_alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value {
376
        unsafe {
377
            let alloca = llvm::LLVMBuildAlloca(self.llbuilder, ty, UNNAMED);
378
            llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
379
            alloca
380 381 382
        }
    }

M
Mark Rousskov 已提交
383
    fn array_alloca(&mut self, ty: &'ll Type, len: &'ll Value, align: Align) -> &'ll Value {
M
Masaki Hara 已提交
384
        unsafe {
385
            let alloca = llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, UNNAMED);
386
            llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
M
Masaki Hara 已提交
387 388 389 390
            alloca
        }
    }

391
    fn load(&mut self, ptr: &'ll Value, align: Align) -> &'ll Value {
392
        unsafe {
393
            let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, UNNAMED);
394
            llvm::LLVMSetAlignment(load, align.bytes() as c_uint);
395
            load
396 397 398
        }
    }

399
    fn volatile_load(&mut self, ptr: &'ll Value) -> &'ll Value {
400
        unsafe {
401
            let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, UNNAMED);
402 403
            llvm::LLVMSetVolatile(load, llvm::True);
            load
404 405 406
        }
    }

407
    fn atomic_load(
408
        &mut self,
409
        ptr: &'ll Value,
410
        order: rustc_codegen_ssa::common::AtomicOrdering,
411
        size: Size,
412
    ) -> &'ll Value {
413
        unsafe {
414 415 416
            let load = llvm::LLVMRustBuildAtomicLoad(
                self.llbuilder,
                ptr,
417
                UNNAMED,
418 419
                AtomicOrdering::from_generic(order),
            );
420 421
            // LLVM requires the alignment of atomic loads to be at least the size of the type.
            llvm::LLVMSetAlignment(load, size.bytes() as c_uint);
422
            load
423 424 425
        }
    }

M
Mark Rousskov 已提交
426
    fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> {
427 428 429 430 431
        debug!("PlaceRef::load: {:?}", place);

        assert_eq!(place.llextra.is_some(), place.layout.is_unsized());

        if place.layout.is_zst() {
432
            return OperandRef::new_zst(self, place.layout);
433 434
        }

435 436 437
        fn scalar_load_metadata<'a, 'll, 'tcx>(
            bx: &mut Builder<'a, 'll, 'tcx>,
            load: &'ll Value,
438
            scalar: &abi::Scalar,
439
        ) {
440 441
            let vr = scalar.valid_range.clone();
            match scalar.value {
442
                abi::Int(..) => {
443
                    let range = scalar.valid_range_exclusive(bx);
444
                    if range.start != range.end {
445
                        bx.range_metadata(load, range);
446 447
                    }
                }
448
                abi::Pointer if vr.start() < vr.end() && !vr.contains(&0) => {
449
                    bx.nonnull_metadata(load);
450 451 452
                }
                _ => {}
            }
453
        }
454 455 456 457 458 459 460 461 462 463 464 465 466 467

        let val = if let Some(llextra) = place.llextra {
            OperandValue::Ref(place.llval, Some(llextra), place.align)
        } else if place.layout.is_llvm_immediate() {
            let mut const_llval = None;
            unsafe {
                if let Some(global) = llvm::LLVMIsAGlobalVariable(place.llval) {
                    if llvm::LLVMIsGlobalConstant(global) == llvm::True {
                        const_llval = llvm::LLVMGetInitializer(global);
                    }
                }
            }
            let llval = const_llval.unwrap_or_else(|| {
                let load = self.load(place.llval, place.align);
468
                if let abi::Abi::Scalar(ref scalar) = place.layout.abi {
469
                    scalar_load_metadata(self, load, scalar);
470 471 472
                }
                load
            });
473
            OperandValue::Immediate(to_immediate(self, llval, place.layout))
474
        } else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
475 476
            let b_offset = a.value.size(self).align_to(b.value.align(self).abi);

477
            let mut load = |i, scalar: &abi::Scalar, align| {
478
                let llptr = self.struct_gep(place.llval, i as u64);
479
                let load = self.load(llptr, align);
480
                scalar_load_metadata(self, load, scalar);
M
Mark Rousskov 已提交
481
                if scalar.is_bool() { self.trunc(load, self.type_i1()) } else { load }
482
            };
483 484 485 486 487

            OperandValue::Pair(
                load(0, a, place.align),
                load(1, b, place.align.restrict_for_offset(b_offset)),
            )
488 489 490 491 492 493 494
        } else {
            OperandValue::Ref(place.llval, None, place.align)
        };

        OperandRef { val, layout: place.layout }
    }

495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
    fn write_operand_repeatedly(
        mut self,
        cg_elem: OperandRef<'tcx, &'ll Value>,
        count: u64,
        dest: PlaceRef<'tcx, &'ll Value>,
    ) -> Self {
        let zero = self.const_usize(0);
        let count = self.const_usize(count);
        let start = dest.project_index(&mut self, zero).llval;
        let end = dest.project_index(&mut self, count).llval;

        let mut header_bx = self.build_sibling_block("repeat_loop_header");
        let mut body_bx = self.build_sibling_block("repeat_loop_body");
        let next_bx = self.build_sibling_block("repeat_loop_next");

        self.br(header_bx.llbb());
        let current = header_bx.phi(self.val_ty(start), &[start], &[self.llbb()]);

        let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
        header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
515

516
        let align = dest.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size);
M
Mark Rousskov 已提交
517 518 519
        cg_elem
            .val
            .store(&mut body_bx, PlaceRef::new_sized_aligned(current, cg_elem.layout, align));
520 521 522 523 524 525 526

        let next = body_bx.inbounds_gep(current, &[self.const_usize(1)]);
        body_bx.br(header_bx.llbb());
        header_bx.add_incoming_to_phi(current, next, body_bx.llbb());

        next_bx
    }
527

528
    fn range_metadata(&mut self, load: &'ll Value, range: Range<u128>) {
529
        if self.sess().target.target.arch == "amdgpu" {
530 531 532 533 534 535 536
            // amdgpu/LLVM does something weird and thinks a i64 value is
            // split into a v2i32, halving the bitwidth LLVM expects,
            // tripping an assertion. So, for now, just disable this
            // optimization.
            return;
        }

537
        unsafe {
538
            let llty = self.cx.val_ty(load);
539
            let v = [
540
                self.cx.const_uint_big(llty, range.start),
M
Mark Rousskov 已提交
541
                self.cx.const_uint_big(llty, range.end),
542
            ];
543

M
Mark Rousskov 已提交
544 545 546 547 548
            llvm::LLVMSetMetadata(
                load,
                llvm::MD_range as c_uint,
                llvm::LLVMMDNodeInContext(self.cx.llcx, v.as_ptr(), v.len() as c_uint),
            );
549 550 551
        }
    }

552
    fn nonnull_metadata(&mut self, load: &'ll Value) {
553
        unsafe {
M
Mark Rousskov 已提交
554 555 556 557 558
            llvm::LLVMSetMetadata(
                load,
                llvm::MD_nonnull as c_uint,
                llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0),
            );
559 560 561
        }
    }

562
    fn store(&mut self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value {
563 564 565
        self.store_with_flags(val, ptr, align, MemFlags::empty())
    }

566
    fn store_with_flags(
567
        &mut self,
568 569
        val: &'ll Value,
        ptr: &'ll Value,
570
        align: Align,
571
        flags: MemFlags,
572
    ) -> &'ll Value {
573
        debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags);
574
        let ptr = self.check_store(val, ptr);
575
        unsafe {
576
            let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
M
Mark Rousskov 已提交
577 578
            let align =
                if flags.contains(MemFlags::UNALIGNED) { 1 } else { align.bytes() as c_uint };
579
            llvm::LLVMSetAlignment(store, align);
580 581 582 583 584 585 586 587
            if flags.contains(MemFlags::VOLATILE) {
                llvm::LLVMSetVolatile(store, llvm::True);
            }
            if flags.contains(MemFlags::NONTEMPORAL) {
                // According to LLVM [1] building a nontemporal store must
                // *always* point to a metadata value of the integer 1.
                //
                // [1]: http://llvm.org/docs/LangRef.html#store-instruction
588
                let one = self.cx.const_i32(1);
589 590 591
                let node = llvm::LLVMMDNodeInContext(self.cx.llcx, &one, 1);
                llvm::LLVMSetMetadata(store, llvm::MD_nontemporal as c_uint, node);
            }
592
            store
593 594 595
        }
    }

M
Mark Rousskov 已提交
596 597 598 599 600 601 602
    fn atomic_store(
        &mut self,
        val: &'ll Value,
        ptr: &'ll Value,
        order: rustc_codegen_ssa::common::AtomicOrdering,
        size: Size,
    ) {
603
        debug!("Store {:?} -> {:?}", val, ptr);
604
        let ptr = self.check_store(val, ptr);
605
        unsafe {
606 607 608 609 610 611
            let store = llvm::LLVMRustBuildAtomicStore(
                self.llbuilder,
                val,
                ptr,
                AtomicOrdering::from_generic(order),
            );
612 613
            // LLVM requires the alignment of atomic stores to be at least the size of the type.
            llvm::LLVMSetAlignment(store, size.bytes() as c_uint);
614 615 616
        }
    }

617
    fn gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
618
        unsafe {
M
Mark Rousskov 已提交
619 620 621 622 623 624 625
            llvm::LLVMBuildGEP(
                self.llbuilder,
                ptr,
                indices.as_ptr(),
                indices.len() as c_uint,
                UNNAMED,
            )
626 627 628
        }
    }

629
    fn inbounds_gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
630 631
        unsafe {
            llvm::LLVMBuildInBoundsGEP(
M
Mark Rousskov 已提交
632 633 634 635 636 637
                self.llbuilder,
                ptr,
                indices.as_ptr(),
                indices.len() as c_uint,
                UNNAMED,
            )
638 639 640
        }
    }

B
bjorn3 已提交
641 642
    fn struct_gep(&mut self, ptr: &'ll Value, idx: u64) -> &'ll Value {
        assert_eq!(idx as c_uint as u64, idx);
M
Mark Rousskov 已提交
643
        unsafe { llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, UNNAMED) }
B
bjorn3 已提交
644 645
    }

646
    /* Casts */
647
    fn trunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
M
Mark Rousskov 已提交
648
        unsafe { llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, UNNAMED) }
649 650
    }

651
    fn sext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
M
Mark Rousskov 已提交
652
        unsafe { llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, UNNAMED) }
653 654
    }

655
    fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
M
Mark Rousskov 已提交
656
        unsafe { llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, UNNAMED) }
657 658
    }

659
    fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
M
Mark Rousskov 已提交
660
        unsafe { llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty, UNNAMED) }
661 662
    }

663
    fn uitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
M
Mark Rousskov 已提交
664
        unsafe { llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, UNNAMED) }
665 666
    }

667
    fn sitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
M
Mark Rousskov 已提交
668
        unsafe { llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, UNNAMED) }
669 670
    }

671
    fn fptrunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
M
Mark Rousskov 已提交
672
        unsafe { llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, UNNAMED) }
673 674
    }

675
    fn fpext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
M
Mark Rousskov 已提交
676
        unsafe { llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, UNNAMED) }
677 678
    }

679
    fn ptrtoint(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
M
Mark Rousskov 已提交
680
        unsafe { llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, UNNAMED) }
681 682
    }

683
    fn inttoptr(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
M
Mark Rousskov 已提交
684
        unsafe { llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, UNNAMED) }
685 686
    }

687
    fn bitcast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
M
Mark Rousskov 已提交
688
        unsafe { llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, UNNAMED) }
689 690
    }

691
    fn intcast(&mut self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value {
M
Mark Rousskov 已提交
692
        unsafe { llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed) }
693 694
    }

695
    fn pointercast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
M
Mark Rousskov 已提交
696
        unsafe { llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, UNNAMED) }
697 698 699
    }

    /* Comparisons */
700
    fn icmp(&mut self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
701
        let op = llvm::IntPredicate::from_generic(op);
M
Mark Rousskov 已提交
702
        unsafe { llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, UNNAMED) }
703 704
    }

705
    fn fcmp(&mut self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
M
Mark Rousskov 已提交
706
        unsafe { llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, UNNAMED) }
707 708 709
    }

    /* Miscellaneous instructions */
M
Mark Rousskov 已提交
710 711 712 713 714 715 716 717 718
    fn memcpy(
        &mut self,
        dst: &'ll Value,
        dst_align: Align,
        src: &'ll Value,
        src_align: Align,
        size: &'ll Value,
        flags: MemFlags,
    ) {
719 720 721
        if flags.contains(MemFlags::NONTEMPORAL) {
            // HACK(nox): This is inefficient but there is no nontemporal memcpy.
            let val = self.load(src, src_align);
722
            let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val)));
723 724 725
            self.store_with_flags(val, ptr, dst_align, flags);
            return;
        }
726
        let size = self.intcast(size, self.type_isize(), false);
727
        let is_volatile = flags.contains(MemFlags::VOLATILE);
728 729
        let dst = self.pointercast(dst, self.type_i8p());
        let src = self.pointercast(src, self.type_i8p());
730
        unsafe {
M
Mark Rousskov 已提交
731 732 733 734 735 736 737 738 739
            llvm::LLVMRustBuildMemCpy(
                self.llbuilder,
                dst,
                dst_align.bytes() as c_uint,
                src,
                src_align.bytes() as c_uint,
                size,
                is_volatile,
            );
740 741 742
        }
    }

M
Mark Rousskov 已提交
743 744 745 746 747 748 749 750 751
    fn memmove(
        &mut self,
        dst: &'ll Value,
        dst_align: Align,
        src: &'ll Value,
        src_align: Align,
        size: &'ll Value,
        flags: MemFlags,
    ) {
752 753 754
        if flags.contains(MemFlags::NONTEMPORAL) {
            // HACK(nox): This is inefficient but there is no nontemporal memmove.
            let val = self.load(src, src_align);
755
            let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val)));
756 757 758
            self.store_with_flags(val, ptr, dst_align, flags);
            return;
        }
759
        let size = self.intcast(size, self.type_isize(), false);
760
        let is_volatile = flags.contains(MemFlags::VOLATILE);
761 762
        let dst = self.pointercast(dst, self.type_i8p());
        let src = self.pointercast(src, self.type_i8p());
763
        unsafe {
M
Mark Rousskov 已提交
764 765 766 767 768 769 770 771 772
            llvm::LLVMRustBuildMemMove(
                self.llbuilder,
                dst,
                dst_align.bytes() as c_uint,
                src,
                src_align.bytes() as c_uint,
                size,
                is_volatile,
            );
773 774 775
        }
    }

776
    fn memset(
777
        &mut self,
778 779 780
        ptr: &'ll Value,
        fill_byte: &'ll Value,
        size: &'ll Value,
781
        align: Align,
782 783
        flags: MemFlags,
    ) {
N
Nikita Popov 已提交
784
        let is_volatile = flags.contains(MemFlags::VOLATILE);
785
        let ptr = self.pointercast(ptr, self.type_i8p());
N
Nikita Popov 已提交
786 787 788 789 790 791 792 793 794 795
        unsafe {
            llvm::LLVMRustBuildMemSet(
                self.llbuilder,
                ptr,
                align.bytes() as c_uint,
                fill_byte,
                size,
                is_volatile,
            );
        }
796 797
    }

798
    fn select(
M
Mark Rousskov 已提交
799 800
        &mut self,
        cond: &'ll Value,
801 802 803
        then_val: &'ll Value,
        else_val: &'ll Value,
    ) -> &'ll Value {
M
Mark Rousskov 已提交
804
        unsafe { llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, UNNAMED) }
805 806
    }

B
bjorn3 已提交
807 808
    #[allow(dead_code)]
    fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
M
Mark Rousskov 已提交
809
        unsafe { llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED) }
B
bjorn3 已提交
810 811
    }

812
    fn extract_element(&mut self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value {
M
Mark Rousskov 已提交
813
        unsafe { llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, UNNAMED) }
814 815
    }

816
    fn vector_splat(&mut self, num_elts: usize, elt: &'ll Value) -> &'ll Value {
817
        unsafe {
818
            let elt_ty = self.cx.val_ty(elt);
819
            let undef = llvm::LLVMGetUndef(self.type_vector(elt_ty, num_elts as u64));
820
            let vec = self.insert_element(undef, elt, self.cx.const_i32(0));
821 822
            let vec_i32_ty = self.type_vector(self.type_i32(), num_elts as u64);
            self.shuffle_vector(vec, undef, self.const_null(vec_i32_ty))
823 824 825
        }
    }

826
    fn extract_value(&mut self, agg_val: &'ll Value, idx: u64) -> &'ll Value {
827
        assert_eq!(idx as c_uint as u64, idx);
M
Mark Rousskov 已提交
828
        unsafe { llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, UNNAMED) }
829 830
    }

M
Mark Rousskov 已提交
831
    fn insert_value(&mut self, agg_val: &'ll Value, elt: &'ll Value, idx: u64) -> &'ll Value {
832
        assert_eq!(idx as c_uint as u64, idx);
M
Mark Rousskov 已提交
833
        unsafe { llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint, UNNAMED) }
834 835
    }

M
Mark Rousskov 已提交
836 837 838 839 840 841
    fn landing_pad(
        &mut self,
        ty: &'ll Type,
        pers_fn: &'ll Value,
        num_clauses: usize,
    ) -> &'ll Value {
842
        unsafe {
M
Mark Rousskov 已提交
843
            llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn, num_clauses as c_uint, UNNAMED)
844 845 846
        }
    }

847
    fn set_cleanup(&mut self, landing_pad: &'ll Value) {
848
        unsafe {
849
            llvm::LLVMSetCleanup(landing_pad, llvm::True);
850 851 852
        }
    }

853
    fn resume(&mut self, exn: &'ll Value) -> &'ll Value {
M
Mark Rousskov 已提交
854
        unsafe { llvm::LLVMBuildResume(self.llbuilder, exn) }
855 856
    }

M
Mark Rousskov 已提交
857
    fn cleanup_pad(&mut self, parent: Option<&'ll Value>, args: &[&'ll Value]) -> Funclet<'ll> {
858
        let name = const_cstr!("cleanuppad");
859
        let ret = unsafe {
M
Mark Rousskov 已提交
860 861 862 863 864 865 866
            llvm::LLVMRustBuildCleanupPad(
                self.llbuilder,
                parent,
                args.len() as c_uint,
                args.as_ptr(),
                name.as_ptr(),
            )
867
        };
868
        Funclet::new(ret.expect("LLVM does not have support for cleanuppad"))
869 870
    }

871
    fn cleanup_ret(
M
Mark Rousskov 已提交
872 873
        &mut self,
        funclet: &Funclet<'ll>,
874 875
        unwind: Option<&'ll BasicBlock>,
    ) -> &'ll Value {
M
Mark Rousskov 已提交
876 877
        let ret =
            unsafe { llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind) };
878
        ret.expect("LLVM does not have support for cleanupret")
879 880
    }

M
Mark Rousskov 已提交
881
    fn catch_pad(&mut self, parent: &'ll Value, args: &[&'ll Value]) -> Funclet<'ll> {
882
        let name = const_cstr!("catchpad");
883
        let ret = unsafe {
M
Mark Rousskov 已提交
884 885 886 887 888 889 890
            llvm::LLVMRustBuildCatchPad(
                self.llbuilder,
                parent,
                args.len() as c_uint,
                args.as_ptr(),
                name.as_ptr(),
            )
891
        };
892
        Funclet::new(ret.expect("LLVM does not have support for catchpad"))
893 894
    }

895
    fn catch_switch(
896
        &mut self,
897 898
        parent: Option<&'ll Value>,
        unwind: Option<&'ll BasicBlock>,
899
        num_handlers: usize,
900
    ) -> &'ll Value {
901
        let name = const_cstr!("catchswitch");
902
        let ret = unsafe {
M
Mark Rousskov 已提交
903 904 905 906 907 908 909
            llvm::LLVMRustBuildCatchSwitch(
                self.llbuilder,
                parent,
                unwind,
                num_handlers as c_uint,
                name.as_ptr(),
            )
910
        };
911
        ret.expect("LLVM does not have support for catchswitch")
912 913
    }

914
    fn add_handler(&mut self, catch_switch: &'ll Value, handler: &'ll BasicBlock) {
915 916 917 918 919
        unsafe {
            llvm::LLVMRustAddHandler(catch_switch, handler);
        }
    }

920
    fn set_personality_fn(&mut self, personality: &'ll Value) {
921
        unsafe {
922
            llvm::LLVMSetPersonalityFn(self.llfn(), personality);
923 924 925
        }
    }

926
    // Atomic Operations
927
    fn atomic_cmpxchg(
928
        &mut self,
929 930 931
        dst: &'ll Value,
        cmp: &'ll Value,
        src: &'ll Value,
932 933
        order: rustc_codegen_ssa::common::AtomicOrdering,
        failure_order: rustc_codegen_ssa::common::AtomicOrdering,
934
        weak: bool,
935
    ) -> &'ll Value {
936
        let weak = if weak { llvm::True } else { llvm::False };
937
        unsafe {
938 939 940 941 942 943 944
            llvm::LLVMRustBuildAtomicCmpXchg(
                self.llbuilder,
                dst,
                cmp,
                src,
                AtomicOrdering::from_generic(order),
                AtomicOrdering::from_generic(failure_order),
M
Mark Rousskov 已提交
945
                weak,
946
            )
947 948
        }
    }
949
    fn atomic_rmw(
950
        &mut self,
951
        op: rustc_codegen_ssa::common::AtomicRmwBinOp,
952 953
        dst: &'ll Value,
        src: &'ll Value,
954
        order: rustc_codegen_ssa::common::AtomicOrdering,
955
    ) -> &'ll Value {
956
        unsafe {
957 958 959 960 961
            llvm::LLVMBuildAtomicRMW(
                self.llbuilder,
                AtomicRmwBinOp::from_generic(op),
                dst,
                src,
962
                AtomicOrdering::from_generic(order),
M
Mark Rousskov 已提交
963 964
                False,
            )
965 966
        }
    }
J
James Miller 已提交
967

D
Denis Merigoux 已提交
968
    fn atomic_fence(
969
        &mut self,
970
        order: rustc_codegen_ssa::common::AtomicOrdering,
M
Mark Rousskov 已提交
971
        scope: rustc_codegen_ssa::common::SynchronizationScope,
D
Denis Merigoux 已提交
972
    ) {
J
James Miller 已提交
973
        unsafe {
974 975 976
            llvm::LLVMRustBuildAtomicFence(
                self.llbuilder,
                AtomicOrdering::from_generic(order),
M
Mark Rousskov 已提交
977
                SynchronizationScope::from_generic(scope),
978
            );
J
James Miller 已提交
979 980
        }
    }
981

982
    fn set_invariant_load(&mut self, load: &'ll Value) {
983
        unsafe {
M
Mark Rousskov 已提交
984 985 986 987 988
            llvm::LLVMSetMetadata(
                load,
                llvm::MD_invariant_load as c_uint,
                llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0),
            );
989 990 991
        }
    }

992
    fn lifetime_start(&mut self, ptr: &'ll Value, size: Size) {
993
        self.call_lifetime_intrinsic("llvm.lifetime.start.p0i8", ptr, size);
994 995
    }

996
    fn lifetime_end(&mut self, ptr: &'ll Value, size: Size) {
997
        self.call_lifetime_intrinsic("llvm.lifetime.end.p0i8", ptr, size);
998 999
    }

1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
    fn instrprof_increment(
        &mut self,
        fn_name: &'ll Value,
        hash: &'ll Value,
        num_counters: &'ll Value,
        index: &'ll Value,
    ) -> &'ll Value {
        debug!(
            "instrprof_increment() with args ({:?}, {:?}, {:?}, {:?})",
            fn_name, hash, num_counters, index
        );

        let llfn = unsafe { llvm::LLVMRustGetInstrprofIncrementIntrinsic(self.cx().llmod) };
        let args = &[fn_name, hash, num_counters, index];
        let args = self.check_call("call", llfn, args);

        unsafe {
            llvm::LLVMRustBuildCall(
                self.llbuilder,
                llfn,
                args.as_ptr() as *const &llvm::Value,
                args.len() as c_uint,
                None,
            )
        }
    }

1027
    fn call(
1028
        &mut self,
1029 1030 1031 1032
        llfn: &'ll Value,
        args: &[&'ll Value],
        funclet: Option<&Funclet<'ll>>,
    ) -> &'ll Value {
M
Mark Rousskov 已提交
1033
        debug!("call {:?} with args ({:?})", llfn, args);
1034 1035

        let args = self.check_call("call", llfn, args);
1036
        let bundle = funclet.map(|funclet| funclet.bundle());
1037
        let bundle = bundle.as_ref().map(|b| &*b.raw);
1038 1039 1040 1041 1042 1043 1044

        unsafe {
            llvm::LLVMRustBuildCall(
                self.llbuilder,
                llfn,
                args.as_ptr() as *const &llvm::Value,
                args.len() as c_uint,
M
Mark Rousskov 已提交
1045
                bundle,
1046 1047 1048 1049
            )
        }
    }

1050
    fn zext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
M
Mark Rousskov 已提交
1051
        unsafe { llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, UNNAMED) }
1052 1053
    }

1054
    fn cx(&self) -> &CodegenCx<'ll, 'tcx> {
1055
        self.cx
1056
    }
1057

1058 1059
    unsafe fn delete_basic_block(&mut self, bb: &'ll BasicBlock) {
        llvm::LLVMDeleteBasicBlock(bb);
1060 1061
    }

1062
    fn do_not_inline(&mut self, llret: &'ll Value) {
1063 1064
        llvm::Attribute::NoInline.apply_callsite(llvm::AttributePlace::Function, llret);
    }
1065
}
1066

1067 1068
impl StaticBuilderMethods for Builder<'a, 'll, 'tcx> {
    fn get_static(&mut self, def_id: DefId) -> &'ll Value {
B
bjorn3 已提交
1069
        // Forward to the `get_static` method of `CodegenCx`
B
bjorn3 已提交
1070 1071 1072 1073
        self.cx().get_static(def_id)
    }
}

1074
impl Builder<'a, 'll, 'tcx> {
B
bjorn3 已提交
1075
    pub fn llfn(&self) -> &'ll Value {
M
Mark Rousskov 已提交
1076
        unsafe { llvm::LLVMGetBasicBlockParent(self.llbb()) }
B
bjorn3 已提交
1077 1078
    }

1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
    fn position_at_start(&mut self, llbb: &'ll BasicBlock) {
        unsafe {
            llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb);
        }
    }

    pub fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
        unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) }
    }

    pub fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
        unsafe { llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs) }
    }

    pub fn insert_element(
M
Mark Rousskov 已提交
1094 1095
        &mut self,
        vec: &'ll Value,
1096 1097 1098
        elt: &'ll Value,
        idx: &'ll Value,
    ) -> &'ll Value {
M
Mark Rousskov 已提交
1099
        unsafe { llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, UNNAMED) }
1100 1101 1102 1103 1104 1105 1106 1107
    }

    pub fn shuffle_vector(
        &mut self,
        v1: &'ll Value,
        v2: &'ll Value,
        mask: &'ll Value,
    ) -> &'ll Value {
M
Mark Rousskov 已提交
1108
        unsafe { llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, UNNAMED) }
1109 1110
    }

1111 1112 1113 1114 1115 1116
    pub fn vector_reduce_fadd(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
        unsafe { llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src) }
    }
    pub fn vector_reduce_fmul(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
        unsafe { llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src) }
    }
1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
    pub fn vector_reduce_fadd_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
        unsafe {
            let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src);
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }
    pub fn vector_reduce_fmul_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
        unsafe {
            let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src);
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }
    pub fn vector_reduce_add(&mut self, src: &'ll Value) -> &'ll Value {
        unsafe { llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) }
    }
    pub fn vector_reduce_mul(&mut self, src: &'ll Value) -> &'ll Value {
        unsafe { llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) }
    }
    pub fn vector_reduce_and(&mut self, src: &'ll Value) -> &'ll Value {
        unsafe { llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) }
    }
    pub fn vector_reduce_or(&mut self, src: &'ll Value) -> &'ll Value {
        unsafe { llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) }
    }
    pub fn vector_reduce_xor(&mut self, src: &'ll Value) -> &'ll Value {
        unsafe { llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) }
    }
    pub fn vector_reduce_fmin(&mut self, src: &'ll Value) -> &'ll Value {
M
Mark Rousskov 已提交
1147 1148 1149
        unsafe {
            llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false)
        }
1150 1151
    }
    pub fn vector_reduce_fmax(&mut self, src: &'ll Value) -> &'ll Value {
M
Mark Rousskov 已提交
1152 1153 1154
        unsafe {
            llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false)
        }
1155 1156 1157
    }
    pub fn vector_reduce_fmin_fast(&mut self, src: &'ll Value) -> &'ll Value {
        unsafe {
M
Mark Rousskov 已提交
1158 1159
            let instr =
                llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true);
1160 1161 1162 1163 1164 1165
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }
    pub fn vector_reduce_fmax_fast(&mut self, src: &'ll Value) -> &'ll Value {
        unsafe {
M
Mark Rousskov 已提交
1166 1167
            let instr =
                llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true);
1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }
    pub fn vector_reduce_min(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value {
        unsafe { llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) }
    }
    pub fn vector_reduce_max(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value {
        unsafe { llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed) }
    }

    pub fn add_clause(&mut self, landing_pad: &'ll Value, clause: &'ll Value) {
        unsafe {
            llvm::LLVMAddClause(landing_pad, clause);
        }
    }

    pub fn catch_ret(&mut self, funclet: &Funclet<'ll>, unwind: &'ll BasicBlock) -> &'ll Value {
M
Mark Rousskov 已提交
1186 1187
        let ret =
            unsafe { llvm::LLVMRustBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind) };
1188 1189 1190
        ret.expect("LLVM does not have support for catchret")
    }

1191
    fn check_store(&mut self, val: &'ll Value, ptr: &'ll Value) -> &'ll Value {
1192 1193 1194 1195 1196 1197 1198 1199 1200
        let dest_ptr_ty = self.cx.val_ty(ptr);
        let stored_ty = self.cx.val_ty(val);
        let stored_ptr_ty = self.cx.type_ptr_to(stored_ty);

        assert_eq!(self.cx.type_kind(dest_ptr_ty), TypeKind::Pointer);

        if dest_ptr_ty == stored_ptr_ty {
            ptr
        } else {
M
Mark Rousskov 已提交
1201 1202
            debug!(
                "type mismatch in store. \
1203
                    Expected {:?}, got {:?}; inserting bitcast",
M
Mark Rousskov 已提交
1204 1205
                dest_ptr_ty, stored_ptr_ty
            );
1206 1207 1208 1209
            self.bitcast(ptr, stored_ptr_ty)
        }
    }

M
Mark Rousskov 已提交
1210 1211 1212 1213 1214 1215
    fn check_call<'b>(
        &mut self,
        typ: &str,
        llfn: &'ll Value,
        args: &'b [&'ll Value],
    ) -> Cow<'b, [&'ll Value]> {
1216 1217 1218 1219 1220 1221
        let mut fn_ty = self.cx.val_ty(llfn);
        // Strip off pointers
        while self.cx.type_kind(fn_ty) == TypeKind::Pointer {
            fn_ty = self.cx.element_type(fn_ty);
        }

M
Mark Rousskov 已提交
1222 1223 1224 1225 1226 1227
        assert!(
            self.cx.type_kind(fn_ty) == TypeKind::Function,
            "builder::{} not passed a function, but {:?}",
            typ,
            fn_ty
        );
1228 1229 1230

        let param_tys = self.cx.func_params_types(fn_ty);

M
Mark Rousskov 已提交
1231 1232
        let all_args_match = param_tys
            .iter()
1233 1234 1235 1236 1237 1238 1239
            .zip(args.iter().map(|&v| self.val_ty(v)))
            .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);

        if all_args_match {
            return Cow::Borrowed(args);
        }

M
Mark Rousskov 已提交
1240 1241
        let casted_args: Vec<_> = param_tys
            .into_iter()
1242 1243 1244 1245 1246
            .zip(args.iter())
            .enumerate()
            .map(|(i, (expected_ty, &actual_val))| {
                let actual_ty = self.val_ty(actual_val);
                if expected_ty != actual_ty {
M
Mark Rousskov 已提交
1247 1248
                    debug!(
                        "type mismatch in function call of {:?}. \
1249
                            Expected {:?} for param {}, got {:?}; injecting bitcast",
M
Mark Rousskov 已提交
1250 1251
                        llfn, expected_ty, i, actual_ty
                    );
1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262
                    self.bitcast(actual_val, expected_ty)
                } else {
                    actual_val
                }
            })
            .collect();

        Cow::Owned(casted_args)
    }

    pub fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
M
Mark Rousskov 已提交
1263
        unsafe { llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED) }
1264 1265
    }

1266
    fn call_lifetime_intrinsic(&mut self, intrinsic: &str, ptr: &'ll Value, size: Size) {
1267 1268
        let size = size.bytes();
        if size == 0 {
1269 1270 1271
            return;
        }

1272
        if !self.cx().sess().emit_lifetime_markers() {
1273 1274 1275 1276 1277 1278 1279 1280
            return;
        }

        let lifetime_intrinsic = self.cx.get_intrinsic(intrinsic);

        let ptr = self.pointercast(ptr, self.cx.type_i8p());
        self.call(lifetime_intrinsic, &[self.cx.const_u64(size), ptr], None);
    }
1281 1282 1283

    fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
        assert_eq!(vals.len(), bbs.len());
M
Mark Rousskov 已提交
1284
        let phi = unsafe { llvm::LLVMBuildPhi(self.llbuilder, ty, UNNAMED) };
1285
        unsafe {
M
Mark Rousskov 已提交
1286
            llvm::LLVMAddIncoming(phi, vals.as_ptr(), bbs.as_ptr(), vals.len() as c_uint);
1287 1288 1289 1290 1291 1292 1293 1294 1295
            phi
        }
    }

    fn add_incoming_to_phi(&mut self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) {
        unsafe {
            llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
        }
    }
1296
}