builder.rs 49.4 KB
Newer Older
T
Taiki Endo 已提交
1 2 3 4 5 6 7
use crate::llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
use crate::llvm::{self, False, BasicBlock};
use crate::common::Funclet;
use crate::context::CodegenCx;
use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
8
use rustc_codegen_ssa::common::{IntPredicate, TypeKind, RealPredicate};
T
Taiki Endo 已提交
9
use rustc_codegen_ssa::MemFlags;
10
use libc::{c_uint, c_char};
D
Denis Merigoux 已提交
11
use rustc::ty::{self, Ty, TyCtxt};
12
use rustc::ty::layout::{self, Align, Size, TyLayout};
B
bjorn3 已提交
13
use rustc::hir::def_id::DefId;
14
use rustc::session::config;
15
use rustc_data_structures::small_c_str::SmallCStr;
16
use rustc_codegen_ssa::traits::*;
17 18 19
use rustc_codegen_ssa::base::to_immediate;
use rustc_codegen_ssa::mir::operand::{OperandValue, OperandRef};
use rustc_codegen_ssa::mir::place::PlaceRef;
20
use std::borrow::Cow;
21
use std::ffi::CStr;
B
bjorn3 已提交
22
use std::ops::{Deref, Range};
23
use std::ptr;
24

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

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

40 41
// This is a really awful way to get a zero-length c-string, but better (and a
// lot more efficient) than doing str::as_c_str("", ...) every time.
M
Mark-Simulacrum 已提交
42
fn noname() -> *const c_char {
43
    static CNULL: c_char = 0;
44
    &CNULL
45 46
}

47 48 49 50
impl BackendTypes for Builder<'_, 'll, 'tcx> {
    type Value = <CodegenCx<'ll, 'tcx> as BackendTypes>::Value;
    type BasicBlock = <CodegenCx<'ll, 'tcx> as BackendTypes>::BasicBlock;
    type Type = <CodegenCx<'ll, 'tcx> as BackendTypes>::Type;
51
    type Funclet = <CodegenCx<'ll, 'tcx> as BackendTypes>::Funclet;
52 53

    type DIScope = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIScope;
D
Denis Merigoux 已提交
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
}

impl ty::layout::HasDataLayout for Builder<'_, '_, '_> {
    fn data_layout(&self) -> &ty::layout::TargetDataLayout {
        self.cx.data_layout()
    }
}

impl ty::layout::HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> {
    fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
        self.cx.tcx
    }
}

impl ty::layout::LayoutOf for Builder<'_, '_, 'tcx> {
    type Ty = Ty<'tcx>;
    type TyLayout = TyLayout<'tcx>;

    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout {
        self.cx.layout_of(ty)
    }
}

B
bjorn3 已提交
77 78 79 80 81 82 83
impl Deref for Builder<'_, 'll, 'tcx> {
    type Target = CodegenCx<'ll, 'tcx>;

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

impl HasCodegen<'tcx> for Builder<'_, 'll, 'tcx> {
D
Denis Merigoux 已提交
86
    type CodegenCx = CodegenCx<'ll, 'tcx>;
87
}
88

89
impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
90 91
    fn new_block<'b>(
        cx: &'a CodegenCx<'ll, 'tcx>,
92
        llfn: &'ll Value,
93 94
        name: &'b str
    ) -> Self {
95
        let mut bx = Builder::with_cx(cx);
96
        let llbb = unsafe {
97
            let name = SmallCStr::new(name);
98
            llvm::LLVMAppendBasicBlockInContext(
99
                cx.llcx,
100 101 102 103
                llfn,
                name.as_ptr()
            )
        };
104 105
        bx.position_at_end(llbb);
        bx
106 107
    }

108
    fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self {
M
Mark-Simulacrum 已提交
109 110
        // Create a fresh builder from the crate context.
        let llbuilder = unsafe {
111
            llvm::LLVMCreateBuilderInContext(cx.llcx)
M
Mark-Simulacrum 已提交
112
        };
113
        Builder {
114
            llbuilder,
115
            cx,
116 117 118
        }
    }

119
    fn build_sibling_block<'b>(&self, name: &'b str) -> Self {
120
        Builder::new_block(self.cx, self.llfn(), name)
121 122
    }

123
    fn llfn(&self) -> &'ll Value {
124 125 126 127 128
        unsafe {
            llvm::LLVMGetBasicBlockParent(self.llbb())
        }
    }

129
    fn llbb(&self) -> &'ll BasicBlock {
130 131 132 133 134
        unsafe {
            llvm::LLVMGetInsertBlock(self.llbuilder)
        }
    }

M
Mark-Simulacrum 已提交
135
    fn count_insn(&self, category: &str) {
136 137
        if self.sess().codegen_stats() {
            self.stats.borrow_mut().n_llvm_insns += 1;
138
        }
139 140
        if self.sess().count_llvm_insns() {
            *self.stats
141 142 143 144
                      .borrow_mut()
                      .llvm_insns
                      .entry(category.to_string())
                      .or_insert(0) += 1;
145 146 147
        }
    }

148
    fn set_value_name(&mut self, value: &'ll Value, name: &str) {
149
        let cname = SmallCStr::new(name);
150 151 152 153 154
        unsafe {
            llvm::LLVMSetValueName(value, cname.as_ptr());
        }
    }

155
    fn position_at_end(&mut self, llbb: &'ll BasicBlock) {
156 157 158 159 160
        unsafe {
            llvm::LLVMPositionBuilderAtEnd(self.llbuilder, llbb);
        }
    }

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

167
    fn ret_void(&mut self) {
168 169 170 171 172 173
        self.count_insn("retvoid");
        unsafe {
            llvm::LLVMBuildRetVoid(self.llbuilder);
        }
    }

174
    fn ret(&mut self, v: &'ll Value) {
175 176 177 178 179 180
        self.count_insn("ret");
        unsafe {
            llvm::LLVMBuildRet(self.llbuilder, v);
        }
    }

181
    fn br(&mut self, dest: &'ll BasicBlock) {
182 183 184 185 186 187
        self.count_insn("br");
        unsafe {
            llvm::LLVMBuildBr(self.llbuilder, dest);
        }
    }

188
    fn cond_br(
189
        &mut self,
190 191 192
        cond: &'ll Value,
        then_llbb: &'ll BasicBlock,
        else_llbb: &'ll BasicBlock,
193
    ) {
194 195 196 197 198 199
        self.count_insn("condbr");
        unsafe {
            llvm::LLVMBuildCondBr(self.llbuilder, cond, then_llbb, else_llbb);
        }
    }

200
    fn switch(
201
        &mut self,
202 203
        v: &'ll Value,
        else_llbb: &'ll BasicBlock,
204
        num_cases: usize,
205
    ) -> &'ll Value {
206 207 208 209 210
        unsafe {
            llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, num_cases as c_uint)
        }
    }

211
    fn invoke(
212
        &mut self,
213 214 215 216 217 218
        llfn: &'ll Value,
        args: &[&'ll Value],
        then: &'ll BasicBlock,
        catch: &'ll BasicBlock,
        funclet: Option<&Funclet<'ll>>,
    ) -> &'ll Value {
219
        self.count_insn("invoke");
220

221 222 223
        debug!("Invoke {:?} with args ({:?})",
               llfn,
               args);
224

225
        let args = self.check_call("invoke", llfn, args);
226
        let bundle = funclet.map(|funclet| funclet.bundle());
227
        let bundle = bundle.as_ref().map(|b| &*b.raw);
228

229
        unsafe {
230 231 232 233 234 235 236 237
            llvm::LLVMRustBuildInvoke(self.llbuilder,
                                      llfn,
                                      args.as_ptr(),
                                      args.len() as c_uint,
                                      then,
                                      catch,
                                      bundle,
                                      noname())
238
        }
239 240
    }

241
    fn unreachable(&mut self) {
242 243 244 245 246 247 248
        self.count_insn("unreachable");
        unsafe {
            llvm::LLVMBuildUnreachable(self.llbuilder);
        }
    }

    /* Arithmetic */
249
    fn add(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
250 251 252 253 254 255
        self.count_insn("add");
        unsafe {
            llvm::LLVMBuildAdd(self.llbuilder, lhs, rhs, noname())
        }
    }

256
    fn fadd(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
257 258 259 260 261 262
        self.count_insn("fadd");
        unsafe {
            llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname())
        }
    }

263
    fn fadd_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
264 265 266 267 268 269 270 271
        self.count_insn("fadd");
        unsafe {
            let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname());
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }

272
    fn sub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
273 274 275 276 277 278
        self.count_insn("sub");
        unsafe {
            llvm::LLVMBuildSub(self.llbuilder, lhs, rhs, noname())
        }
    }

279
    fn fsub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
B
Ben Harris 已提交
280
        self.count_insn("fsub");
281 282 283 284 285
        unsafe {
            llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname())
        }
    }

286
    fn fsub_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
B
Ben Harris 已提交
287
        self.count_insn("fsub");
288 289 290 291 292 293 294
        unsafe {
            let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname());
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }

295
    fn mul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
296 297 298 299 300 301
        self.count_insn("mul");
        unsafe {
            llvm::LLVMBuildMul(self.llbuilder, lhs, rhs, noname())
        }
    }

302
    fn fmul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
303 304 305 306 307 308
        self.count_insn("fmul");
        unsafe {
            llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname())
        }
    }

309
    fn fmul_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
310 311 312 313 314 315 316 317 318
        self.count_insn("fmul");
        unsafe {
            let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname());
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }


319
    fn udiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
320 321 322 323 324 325
        self.count_insn("udiv");
        unsafe {
            llvm::LLVMBuildUDiv(self.llbuilder, lhs, rhs, noname())
        }
    }

326
    fn exactudiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
327 328 329 330 331 332
        self.count_insn("exactudiv");
        unsafe {
            llvm::LLVMBuildExactUDiv(self.llbuilder, lhs, rhs, noname())
        }
    }

333
    fn sdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
334 335 336 337 338 339
        self.count_insn("sdiv");
        unsafe {
            llvm::LLVMBuildSDiv(self.llbuilder, lhs, rhs, noname())
        }
    }

340
    fn exactsdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
341 342 343 344 345 346
        self.count_insn("exactsdiv");
        unsafe {
            llvm::LLVMBuildExactSDiv(self.llbuilder, lhs, rhs, noname())
        }
    }

347
    fn fdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
348 349 350 351 352 353
        self.count_insn("fdiv");
        unsafe {
            llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname())
        }
    }

354
    fn fdiv_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
355 356 357 358 359 360 361 362
        self.count_insn("fdiv");
        unsafe {
            let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname());
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }

363
    fn urem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
364 365 366 367 368 369
        self.count_insn("urem");
        unsafe {
            llvm::LLVMBuildURem(self.llbuilder, lhs, rhs, noname())
        }
    }

370
    fn srem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
371 372 373 374 375 376
        self.count_insn("srem");
        unsafe {
            llvm::LLVMBuildSRem(self.llbuilder, lhs, rhs, noname())
        }
    }

377
    fn frem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
378 379 380 381 382 383
        self.count_insn("frem");
        unsafe {
            llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname())
        }
    }

384
    fn frem_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
385 386 387 388 389 390 391 392
        self.count_insn("frem");
        unsafe {
            let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname());
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }

393
    fn shl(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
394 395 396 397 398 399
        self.count_insn("shl");
        unsafe {
            llvm::LLVMBuildShl(self.llbuilder, lhs, rhs, noname())
        }
    }

400
    fn lshr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
401 402 403 404 405 406
        self.count_insn("lshr");
        unsafe {
            llvm::LLVMBuildLShr(self.llbuilder, lhs, rhs, noname())
        }
    }

407
    fn ashr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
408 409 410 411 412 413
        self.count_insn("ashr");
        unsafe {
            llvm::LLVMBuildAShr(self.llbuilder, lhs, rhs, noname())
        }
    }

414
    fn and(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
415 416 417 418 419 420
        self.count_insn("and");
        unsafe {
            llvm::LLVMBuildAnd(self.llbuilder, lhs, rhs, noname())
        }
    }

421
    fn or(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
422 423 424 425 426 427
        self.count_insn("or");
        unsafe {
            llvm::LLVMBuildOr(self.llbuilder, lhs, rhs, noname())
        }
    }

428
    fn xor(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
429 430 431 432 433 434
        self.count_insn("xor");
        unsafe {
            llvm::LLVMBuildXor(self.llbuilder, lhs, rhs, noname())
        }
    }

435
    fn neg(&mut self, v: &'ll Value) -> &'ll Value {
436 437
        self.count_insn("neg");
        unsafe {
438
            llvm::LLVMBuildNeg(self.llbuilder, v, noname())
439 440 441
        }
    }

442
    fn fneg(&mut self, v: &'ll Value) -> &'ll Value {
443 444
        self.count_insn("fneg");
        unsafe {
445
            llvm::LLVMBuildFNeg(self.llbuilder, v, noname())
446 447 448
        }
    }

449
    fn not(&mut self, v: &'ll Value) -> &'ll Value {
450 451
        self.count_insn("not");
        unsafe {
452
            llvm::LLVMBuildNot(self.llbuilder, v, noname())
453 454 455
        }
    }

456 457 458
    fn checked_binop(
        &mut self,
        oop: OverflowOp,
459
        ty: Ty<'_>,
460 461 462 463 464 465 466 467
        lhs: Self::Value,
        rhs: Self::Value,
    ) -> (Self::Value, Self::Value) {
        use syntax::ast::IntTy::*;
        use syntax::ast::UintTy::*;
        use rustc::ty::{Int, Uint};

        let new_sty = match ty.sty {
468 469
            Int(Isize) => Int(self.tcx.sess.target.isize_ty),
            Uint(Usize) => Uint(self.tcx.sess.target.usize_ty),
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
            ref t @ Uint(_) | ref t @ Int(_) => t.clone(),
            _ => panic!("tried to get overflow intrinsic for op applied to non-int type")
        };

        let name = match oop {
            OverflowOp::Add => match new_sty {
                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!(),
            },
            OverflowOp::Sub => match new_sty {
                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!(),
            },
            OverflowOp::Mul => match new_sty {
                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!(),
            },
        };

522
        let intrinsic = self.get_intrinsic(&name);
523 524 525 526 527 528 529
        let res = self.call(intrinsic, &[lhs, rhs], None);
        (
            self.extract_value(res, 0),
            self.extract_value(res, 1),
        )
    }

530
    fn alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
531
        let mut bx = Builder::with_cx(self.cx);
532
        bx.position_at_start(unsafe {
533 534
            llvm::LLVMGetFirstBasicBlock(self.llfn())
        });
535
        bx.dynamic_alloca(ty, name, align)
536 537
    }

538
    fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
539 540
        self.count_insn("alloca");
        unsafe {
541
            let alloca = if name.is_empty() {
542
                llvm::LLVMBuildAlloca(self.llbuilder, ty, noname())
543
            } else {
544
                let name = SmallCStr::new(name);
545
                llvm::LLVMBuildAlloca(self.llbuilder, ty,
A
Alex Crichton 已提交
546
                                      name.as_ptr())
547
            };
548
            llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
549
            alloca
550 551 552
        }
    }

553
    fn array_alloca(&mut self,
554
                        ty: &'ll Type,
555
                        len: &'ll Value,
M
Masaki Hara 已提交
556
                        name: &str,
557
                        align: Align) -> &'ll Value {
M
Masaki Hara 已提交
558 559 560 561 562 563 564 565 566
        self.count_insn("alloca");
        unsafe {
            let alloca = if name.is_empty() {
                llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, noname())
            } else {
                let name = SmallCStr::new(name);
                llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len,
                                           name.as_ptr())
            };
567
            llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
M
Masaki Hara 已提交
568 569 570 571
            alloca
        }
    }

572
    fn load(&mut self, ptr: &'ll Value, align: Align) -> &'ll Value {
573 574
        self.count_insn("load");
        unsafe {
575
            let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
576
            llvm::LLVMSetAlignment(load, align.bytes() as c_uint);
577
            load
578 579 580
        }
    }

581
    fn volatile_load(&mut self, ptr: &'ll Value) -> &'ll Value {
582 583 584
        self.count_insn("load.volatile");
        unsafe {
            let insn = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
585
            llvm::LLVMSetVolatile(insn, llvm::True);
586 587 588 589
            insn
        }
    }

590
    fn atomic_load(
591
        &mut self,
592
        ptr: &'ll Value,
593
        order: rustc_codegen_ssa::common::AtomicOrdering,
594
        size: Size,
595
    ) -> &'ll Value {
596 597
        self.count_insn("load.atomic");
        unsafe {
598 599 600 601 602 603
            let load = llvm::LLVMRustBuildAtomicLoad(
                self.llbuilder,
                ptr,
                noname(),
                AtomicOrdering::from_generic(order),
            );
604 605
            // LLVM requires the alignment of atomic loads to be at least the size of the type.
            llvm::LLVMSetAlignment(load, size.bytes() as c_uint);
606
            load
607 608 609
        }
    }

610
    fn load_operand(
611
        &mut self,
612 613 614 615 616 617 618 619 620 621
        place: PlaceRef<'tcx, &'ll Value>
    ) -> OperandRef<'tcx, &'ll Value> {
        debug!("PlaceRef::load: {:?}", place);

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

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

622 623 624 625 626
        fn scalar_load_metadata<'a, 'll, 'tcx>(
            bx: &mut Builder<'a, 'll, 'tcx>,
            load: &'ll Value,
            scalar: &layout::Scalar
        ) {
627 628 629
            let vr = scalar.valid_range.clone();
            match scalar.value {
                layout::Int(..) => {
630
                    let range = scalar.valid_range_exclusive(bx);
631
                    if range.start != range.end {
632
                        bx.range_metadata(load, range);
633 634 635
                    }
                }
                layout::Pointer if vr.start() < vr.end() && !vr.contains(&0) => {
636
                    bx.nonnull_metadata(load);
637 638 639
                }
                _ => {}
            }
640
        }
641 642 643 644 645 646 647 648 649 650 651 652 653 654 655

        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);
                if let layout::Abi::Scalar(ref scalar) = place.layout.abi {
656
                    scalar_load_metadata(self, load, scalar);
657 658 659
                }
                load
            });
660
            OperandValue::Immediate(to_immediate(self, llval, place.layout))
661
        } else if let layout::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
662 663 664
            let b_offset = a.value.size(self).align_to(b.value.align(self).abi);

            let mut load = |i, scalar: &layout::Scalar, align| {
665
                let llptr = self.struct_gep(place.llval, i as u64);
666
                let load = self.load(llptr, align);
667
                scalar_load_metadata(self, load, scalar);
668
                if scalar.is_bool() {
669
                    self.trunc(load, self.type_i1())
670 671 672 673
                } else {
                    load
                }
            };
674 675 676 677 678

            OperandValue::Pair(
                load(0, a, place.align),
                load(1, b, place.align.restrict_for_offset(b_offset)),
            )
679 680 681 682 683 684 685 686
        } else {
            OperandValue::Ref(place.llval, None, place.align)
        };

        OperandRef { val, layout: place.layout }
    }


687

688
    fn range_metadata(&mut self, load: &'ll Value, range: Range<u128>) {
689
        if self.sess().target.target.arch == "amdgpu" {
690 691 692 693 694 695 696
            // 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;
        }

697
        unsafe {
698
            let llty = self.cx.val_ty(load);
699
            let v = [
700 701
                self.cx.const_uint_big(llty, range.start),
                self.cx.const_uint_big(llty, range.end)
702
            ];
703

704
            llvm::LLVMSetMetadata(load, llvm::MD_range as c_uint,
705
                                  llvm::LLVMMDNodeInContext(self.cx.llcx,
706 707
                                                            v.as_ptr(),
                                                            v.len() as c_uint));
708 709 710
        }
    }

711
    fn nonnull_metadata(&mut self, load: &'ll Value) {
712
        unsafe {
713
            llvm::LLVMSetMetadata(load, llvm::MD_nonnull as c_uint,
714
                                  llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0));
715 716 717
        }
    }

718
    fn store(&mut self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value {
719 720 721
        self.store_with_flags(val, ptr, align, MemFlags::empty())
    }

722
    fn store_with_flags(
723
        &mut self,
724 725
        val: &'ll Value,
        ptr: &'ll Value,
726
        align: Align,
727
        flags: MemFlags,
728
    ) -> &'ll Value {
729
        debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags);
730
        self.count_insn("store");
731
        let ptr = self.check_store(val, ptr);
732
        unsafe {
733
            let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
734 735 736
            let align = if flags.contains(MemFlags::UNALIGNED) {
                1
            } else {
737
                align.bytes() as c_uint
738 739
            };
            llvm::LLVMSetAlignment(store, align);
740 741 742 743 744 745 746 747
            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
748
                let one = self.cx.const_i32(1);
749 750 751
                let node = llvm::LLVMMDNodeInContext(self.cx.llcx, &one, 1);
                llvm::LLVMSetMetadata(store, llvm::MD_nontemporal as c_uint, node);
            }
752
            store
753 754 755
        }
    }

756
   fn atomic_store(&mut self, val: &'ll Value, ptr: &'ll Value,
757
                   order: rustc_codegen_ssa::common::AtomicOrdering, size: Size) {
758
        debug!("Store {:?} -> {:?}", val, ptr);
759
        self.count_insn("store.atomic");
760
        let ptr = self.check_store(val, ptr);
761
        unsafe {
762 763 764 765 766 767
            let store = llvm::LLVMRustBuildAtomicStore(
                self.llbuilder,
                val,
                ptr,
                AtomicOrdering::from_generic(order),
            );
768 769
            // LLVM requires the alignment of atomic stores to be at least the size of the type.
            llvm::LLVMSetAlignment(store, size.bytes() as c_uint);
770 771 772
        }
    }

773
    fn gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
774 775
        self.count_insn("gep");
        unsafe {
776
            llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(),
777 778 779 780
                               indices.len() as c_uint, noname())
        }
    }

781
    fn inbounds_gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
782 783 784
        self.count_insn("inboundsgep");
        unsafe {
            llvm::LLVMBuildInBoundsGEP(
785
                self.llbuilder, ptr, indices.as_ptr(), indices.len() as c_uint, noname())
786 787 788 789
        }
    }

    /* Casts */
790
    fn trunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
791 792
        self.count_insn("trunc");
        unsafe {
793
            llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, noname())
794 795 796
        }
    }

797
    fn sext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
798 799
        self.count_insn("sext");
        unsafe {
800
            llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, noname())
801 802 803
        }
    }

804
    fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
805 806
        self.count_insn("fptoui");
        unsafe {
807
            llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, noname())
808 809 810
        }
    }

811
    fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
812 813
        self.count_insn("fptosi");
        unsafe {
814
            llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,noname())
815 816 817
        }
    }

818
    fn uitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
819 820
        self.count_insn("uitofp");
        unsafe {
821
            llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, noname())
822 823 824
        }
    }

825
    fn sitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
826 827
        self.count_insn("sitofp");
        unsafe {
828
            llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, noname())
829 830 831
        }
    }

832
    fn fptrunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
833 834
        self.count_insn("fptrunc");
        unsafe {
835
            llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, noname())
836 837 838
        }
    }

839
    fn fpext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
840 841
        self.count_insn("fpext");
        unsafe {
842
            llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, noname())
843 844 845
        }
    }

846
    fn ptrtoint(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
847 848
        self.count_insn("ptrtoint");
        unsafe {
849
            llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, noname())
850 851 852
        }
    }

853
    fn inttoptr(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
854 855
        self.count_insn("inttoptr");
        unsafe {
856
            llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, noname())
857 858 859
        }
    }

860
    fn bitcast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
861 862
        self.count_insn("bitcast");
        unsafe {
863
            llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, noname())
864 865 866
        }
    }

867

868
    fn intcast(&mut self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value {
869
        self.count_insn("intcast");
870
        unsafe {
871
            llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed)
872 873 874
        }
    }

875
    fn pointercast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
876
        self.count_insn("pointercast");
877
        unsafe {
878
            llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname())
879 880 881 882
        }
    }

    /* Comparisons */
883
    fn icmp(&mut self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
884
        self.count_insn("icmp");
885
        let op = llvm::IntPredicate::from_generic(op);
886 887 888 889 890
        unsafe {
            llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
        }
    }

891
    fn fcmp(&mut self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
892 893 894 895 896 897 898
        self.count_insn("fcmp");
        unsafe {
            llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
        }
    }

    /* Miscellaneous instructions */
899
    fn empty_phi(&mut self, ty: &'ll Type) -> &'ll Value {
900 901
        self.count_insn("emptyphi");
        unsafe {
902
            llvm::LLVMBuildPhi(self.llbuilder, ty, noname())
903 904 905
        }
    }

906
    fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
907 908 909 910
        assert_eq!(vals.len(), bbs.len());
        let phi = self.empty_phi(ty);
        self.count_insn("addincoming");
        unsafe {
911 912
            llvm::LLVMAddIncoming(phi, vals.as_ptr(),
                                  bbs.as_ptr(),
913 914 915 916 917
                                  vals.len() as c_uint);
            phi
        }
    }

918
    fn inline_asm_call(&mut self, asm: &CStr, cons: &CStr,
919
                       inputs: &[&'ll Value], output: &'ll Type,
920
                       volatile: bool, alignstack: bool,
921
                       dia: syntax::ast::AsmDialect) -> Option<&'ll Value> {
922 923
        self.count_insn("inlineasm");

924 925 926 927
        let volatile = if volatile { llvm::True }
                       else        { llvm::False };
        let alignstack = if alignstack { llvm::True }
                         else          { llvm::False };
928

929
        let argtys = inputs.iter().map(|v| {
930
            debug!("Asm Input Type: {:?}", *v);
931
            self.cx.val_ty(*v)
932
        }).collect::<Vec<_>>();
933

934
        debug!("Asm Output Type: {:?}", output);
935
        let fty = self.type_func(&argtys[..], output);
936
        unsafe {
937
            // Ask LLVM to verify that the constraints are well-formed.
938
            let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons.as_ptr());
939
            debug!("Constraint verification result: {:?}", constraints_ok);
940
            if constraints_ok {
941
                let v = llvm::LLVMRustInlineAsm(
942 943 944 945 946 947 948
                    fty,
                    asm.as_ptr(),
                    cons.as_ptr(),
                    volatile,
                    alignstack,
                    AsmDialect::from_generic(dia),
                );
949 950
                Some(self.call(v, inputs, None))
            } else {
M
Matthias Krüger 已提交
951
                // LLVM has detected an issue with our constraints, bail out
952 953
                None
            }
954 955 956
        }
    }

957 958
    fn memcpy(&mut self, dst: &'ll Value, dst_align: Align,
                  src: &'ll Value, src_align: Align,
959 960 961 962
                  size: &'ll Value, flags: MemFlags) {
        if flags.contains(MemFlags::NONTEMPORAL) {
            // HACK(nox): This is inefficient but there is no nontemporal memcpy.
            let val = self.load(src, src_align);
963
            let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val)));
964 965 966
            self.store_with_flags(val, ptr, dst_align, flags);
            return;
        }
967
        let size = self.intcast(size, self.type_isize(), false);
968
        let is_volatile = flags.contains(MemFlags::VOLATILE);
969 970
        let dst = self.pointercast(dst, self.type_i8p());
        let src = self.pointercast(src, self.type_i8p());
971
        unsafe {
972 973
            llvm::LLVMRustBuildMemCpy(self.llbuilder, dst, dst_align.bytes() as c_uint,
                                      src, src_align.bytes() as c_uint, size, is_volatile);
974 975 976
        }
    }

977 978
    fn memmove(&mut self, dst: &'ll Value, dst_align: Align,
                  src: &'ll Value, src_align: Align,
979 980 981 982
                  size: &'ll Value, flags: MemFlags) {
        if flags.contains(MemFlags::NONTEMPORAL) {
            // HACK(nox): This is inefficient but there is no nontemporal memmove.
            let val = self.load(src, src_align);
983
            let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val)));
984 985 986
            self.store_with_flags(val, ptr, dst_align, flags);
            return;
        }
987
        let size = self.intcast(size, self.type_isize(), false);
988
        let is_volatile = flags.contains(MemFlags::VOLATILE);
989 990
        let dst = self.pointercast(dst, self.type_i8p());
        let src = self.pointercast(src, self.type_i8p());
991
        unsafe {
992 993
            llvm::LLVMRustBuildMemMove(self.llbuilder, dst, dst_align.bytes() as c_uint,
                                      src, src_align.bytes() as c_uint, size, is_volatile);
994 995 996
        }
    }

997
    fn memset(
998
        &mut self,
999 1000 1001
        ptr: &'ll Value,
        fill_byte: &'ll Value,
        size: &'ll Value,
1002
        align: Align,
1003 1004
        flags: MemFlags,
    ) {
1005
        let ptr_width = &self.sess().target.target.target_pointer_width;
1006
        let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
1007 1008 1009 1010
        let llintrinsicfn = self.get_intrinsic(&intrinsic_key);
        let ptr = self.pointercast(ptr, self.type_i8p());
        let align = self.const_u32(align.bytes() as u32);
        let volatile = self.const_bool(flags.contains(MemFlags::VOLATILE));
1011 1012 1013
        self.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None);
    }

1014
    fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
G
gnzlbg 已提交
1015
        self.count_insn("minnum");
1016
        unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) }
G
gnzlbg 已提交
1017
    }
1018
    fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
G
gnzlbg 已提交
1019
        self.count_insn("maxnum");
1020
        unsafe { llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs) }
G
gnzlbg 已提交
1021 1022
    }

1023
    fn select(
1024
        &mut self, cond: &'ll Value,
1025 1026 1027
        then_val: &'ll Value,
        else_val: &'ll Value,
    ) -> &'ll Value {
1028 1029 1030 1031 1032 1033
        self.count_insn("select");
        unsafe {
            llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname())
        }
    }

1034
    #[allow(dead_code)]
1035
    fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
1036 1037
        self.count_insn("vaarg");
        unsafe {
1038
            llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
1039 1040 1041
        }
    }

1042
    fn extract_element(&mut self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value {
1043 1044 1045 1046 1047 1048
        self.count_insn("extractelement");
        unsafe {
            llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname())
        }
    }

1049
    fn insert_element(
1050
        &mut self, vec: &'ll Value,
1051 1052 1053
        elt: &'ll Value,
        idx: &'ll Value,
    ) -> &'ll Value {
1054 1055 1056 1057 1058 1059
        self.count_insn("insertelement");
        unsafe {
            llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname())
        }
    }

1060
    fn shuffle_vector(&mut self, v1: &'ll Value, v2: &'ll Value, mask: &'ll Value) -> &'ll Value {
1061 1062 1063 1064 1065 1066
        self.count_insn("shufflevector");
        unsafe {
            llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname())
        }
    }

1067
    fn vector_splat(&mut self, num_elts: usize, elt: &'ll Value) -> &'ll Value {
1068
        unsafe {
1069
            let elt_ty = self.cx.val_ty(elt);
1070
            let undef = llvm::LLVMGetUndef(self.type_vector(elt_ty, num_elts as u64));
1071
            let vec = self.insert_element(undef, elt, self.cx.const_i32(0));
1072 1073
            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))
1074 1075 1076
        }
    }

1077
    fn vector_reduce_fadd_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
1078 1079
        self.count_insn("vector.reduce.fadd_fast");
        unsafe {
1080 1081 1082
            // FIXME: add a non-fast math version once
            // https://bugs.llvm.org/show_bug.cgi?id=36732
            // is fixed.
1083
            let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src);
1084 1085 1086 1087
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }
1088
    fn vector_reduce_fmul_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
1089 1090
        self.count_insn("vector.reduce.fmul_fast");
        unsafe {
1091 1092 1093
            // FIXME: add a non-fast math version once
            // https://bugs.llvm.org/show_bug.cgi?id=36732
            // is fixed.
1094
            let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src);
1095 1096 1097 1098
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }
1099
    fn vector_reduce_add(&mut self, src: &'ll Value) -> &'ll Value {
1100
        self.count_insn("vector.reduce.add");
1101
        unsafe { llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) }
1102
    }
1103
    fn vector_reduce_mul(&mut self, src: &'ll Value) -> &'ll Value {
1104
        self.count_insn("vector.reduce.mul");
1105
        unsafe { llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) }
1106
    }
1107
    fn vector_reduce_and(&mut self, src: &'ll Value) -> &'ll Value {
1108
        self.count_insn("vector.reduce.and");
1109
        unsafe { llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) }
1110
    }
1111
    fn vector_reduce_or(&mut self, src: &'ll Value) -> &'ll Value {
1112
        self.count_insn("vector.reduce.or");
1113
        unsafe { llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) }
1114
    }
1115
    fn vector_reduce_xor(&mut self, src: &'ll Value) -> &'ll Value {
1116
        self.count_insn("vector.reduce.xor");
1117
        unsafe { llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) }
1118
    }
1119
    fn vector_reduce_fmin(&mut self, src: &'ll Value) -> &'ll Value {
1120
        self.count_insn("vector.reduce.fmin");
1121
        unsafe { llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false) }
1122
    }
1123
    fn vector_reduce_fmax(&mut self, src: &'ll Value) -> &'ll Value {
1124
        self.count_insn("vector.reduce.fmax");
1125
        unsafe { llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false) }
1126
    }
1127
    fn vector_reduce_fmin_fast(&mut self, src: &'ll Value) -> &'ll Value {
1128 1129
        self.count_insn("vector.reduce.fmin_fast");
        unsafe {
1130
            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true);
1131 1132 1133 1134
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }
1135
    fn vector_reduce_fmax_fast(&mut self, src: &'ll Value) -> &'ll Value {
1136 1137
        self.count_insn("vector.reduce.fmax_fast");
        unsafe {
1138
            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true);
1139 1140 1141 1142
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }
1143
    fn vector_reduce_min(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value {
1144
        self.count_insn("vector.reduce.min");
1145
        unsafe { llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) }
1146
    }
1147
    fn vector_reduce_max(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value {
1148
        self.count_insn("vector.reduce.max");
1149
        unsafe { llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed) }
1150 1151
    }

1152
    fn extract_value(&mut self, agg_val: &'ll Value, idx: u64) -> &'ll Value {
1153
        self.count_insn("extractvalue");
1154
        assert_eq!(idx as c_uint as u64, idx);
1155 1156 1157 1158 1159
        unsafe {
            llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, noname())
        }
    }

1160
    fn insert_value(&mut self, agg_val: &'ll Value, elt: &'ll Value,
1161
                       idx: u64) -> &'ll Value {
1162
        self.count_insn("insertvalue");
1163
        assert_eq!(idx as c_uint as u64, idx);
1164 1165
        unsafe {
            llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint,
1166
                                       noname())
1167 1168 1169
        }
    }

1170
    fn landing_pad(&mut self, ty: &'ll Type, pers_fn: &'ll Value,
1171
                       num_clauses: usize) -> &'ll Value {
1172 1173
        self.count_insn("landingpad");
        unsafe {
1174
            llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn,
1175
                                      num_clauses as c_uint, noname())
1176 1177 1178
        }
    }

1179
    fn add_clause(&mut self, landing_pad: &'ll Value, clause: &'ll Value) {
1180 1181 1182 1183 1184
        unsafe {
            llvm::LLVMAddClause(landing_pad, clause);
        }
    }

1185
    fn set_cleanup(&mut self, landing_pad: &'ll Value) {
1186 1187
        self.count_insn("setcleanup");
        unsafe {
1188
            llvm::LLVMSetCleanup(landing_pad, llvm::True);
1189 1190 1191
        }
    }

1192
    fn resume(&mut self, exn: &'ll Value) -> &'ll Value {
1193 1194 1195 1196 1197 1198
        self.count_insn("resume");
        unsafe {
            llvm::LLVMBuildResume(self.llbuilder, exn)
        }
    }

1199
    fn cleanup_pad(&mut self,
1200
                       parent: Option<&'ll Value>,
1201
                       args: &[&'ll Value]) -> Funclet<'ll> {
1202
        self.count_insn("cleanuppad");
1203
        let name = const_cstr!("cleanuppad");
1204 1205 1206 1207 1208 1209 1210
        let ret = unsafe {
            llvm::LLVMRustBuildCleanupPad(self.llbuilder,
                                          parent,
                                          args.len() as c_uint,
                                          args.as_ptr(),
                                          name.as_ptr())
        };
1211
        Funclet::new(ret.expect("LLVM does not have support for cleanuppad"))
1212 1213
    }

1214
    fn cleanup_ret(
1215
        &mut self, funclet: &Funclet<'ll>,
1216 1217
        unwind: Option<&'ll BasicBlock>,
    ) -> &'ll Value {
1218 1219
        self.count_insn("cleanupret");
        let ret = unsafe {
1220
            llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind)
1221
        };
1222
        ret.expect("LLVM does not have support for cleanupret")
1223 1224
    }

1225
    fn catch_pad(&mut self,
1226
                     parent: &'ll Value,
1227
                     args: &[&'ll Value]) -> Funclet<'ll> {
1228
        self.count_insn("catchpad");
1229
        let name = const_cstr!("catchpad");
1230 1231 1232 1233 1234
        let ret = unsafe {
            llvm::LLVMRustBuildCatchPad(self.llbuilder, parent,
                                        args.len() as c_uint, args.as_ptr(),
                                        name.as_ptr())
        };
1235
        Funclet::new(ret.expect("LLVM does not have support for catchpad"))
1236 1237
    }

1238
    fn catch_ret(&mut self, funclet: &Funclet<'ll>, unwind: &'ll BasicBlock) -> &'ll Value {
1239 1240
        self.count_insn("catchret");
        let ret = unsafe {
1241
            llvm::LLVMRustBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind)
1242
        };
1243
        ret.expect("LLVM does not have support for catchret")
1244 1245
    }

1246
    fn catch_switch(
1247
        &mut self,
1248 1249
        parent: Option<&'ll Value>,
        unwind: Option<&'ll BasicBlock>,
1250
        num_handlers: usize,
1251
    ) -> &'ll Value {
1252
        self.count_insn("catchswitch");
1253
        let name = const_cstr!("catchswitch");
1254 1255 1256 1257 1258
        let ret = unsafe {
            llvm::LLVMRustBuildCatchSwitch(self.llbuilder, parent, unwind,
                                           num_handlers as c_uint,
                                           name.as_ptr())
        };
1259
        ret.expect("LLVM does not have support for catchswitch")
1260 1261
    }

1262
    fn add_handler(&mut self, catch_switch: &'ll Value, handler: &'ll BasicBlock) {
1263 1264 1265 1266 1267
        unsafe {
            llvm::LLVMRustAddHandler(catch_switch, handler);
        }
    }

1268
    fn set_personality_fn(&mut self, personality: &'ll Value) {
1269
        unsafe {
1270
            llvm::LLVMSetPersonalityFn(self.llfn(), personality);
1271 1272 1273
        }
    }

1274
    // Atomic Operations
1275
    fn atomic_cmpxchg(
1276
        &mut self,
1277 1278 1279
        dst: &'ll Value,
        cmp: &'ll Value,
        src: &'ll Value,
1280 1281
        order: rustc_codegen_ssa::common::AtomicOrdering,
        failure_order: rustc_codegen_ssa::common::AtomicOrdering,
1282
        weak: bool,
1283
    ) -> &'ll Value {
1284
        let weak = if weak { llvm::True } else { llvm::False };
1285
        unsafe {
1286 1287 1288 1289 1290 1291 1292 1293 1294
            llvm::LLVMRustBuildAtomicCmpXchg(
                self.llbuilder,
                dst,
                cmp,
                src,
                AtomicOrdering::from_generic(order),
                AtomicOrdering::from_generic(failure_order),
                weak
            )
1295 1296
        }
    }
1297
    fn atomic_rmw(
1298
        &mut self,
1299
        op: rustc_codegen_ssa::common::AtomicRmwBinOp,
1300 1301
        dst: &'ll Value,
        src: &'ll Value,
1302
        order: rustc_codegen_ssa::common::AtomicOrdering,
1303
    ) -> &'ll Value {
1304
        unsafe {
1305 1306 1307 1308 1309
            llvm::LLVMBuildAtomicRMW(
                self.llbuilder,
                AtomicRmwBinOp::from_generic(op),
                dst,
                src,
1310
                AtomicOrdering::from_generic(order),
1311
                False)
1312 1313
        }
    }
J
James Miller 已提交
1314

D
Denis Merigoux 已提交
1315
    fn atomic_fence(
1316
        &mut self,
1317 1318
        order: rustc_codegen_ssa::common::AtomicOrdering,
        scope: rustc_codegen_ssa::common::SynchronizationScope
D
Denis Merigoux 已提交
1319
    ) {
J
James Miller 已提交
1320
        unsafe {
1321 1322 1323
            llvm::LLVMRustBuildAtomicFence(
                self.llbuilder,
                AtomicOrdering::from_generic(order),
1324
                SynchronizationScope::from_generic(scope)
1325
            );
J
James Miller 已提交
1326 1327
        }
    }
1328

1329
    fn add_case(&mut self, s: &'ll Value, on_val: &'ll Value, dest: &'ll BasicBlock) {
1330 1331 1332 1333 1334
        unsafe {
            llvm::LLVMAddCase(s, on_val, dest)
        }
    }

1335
    fn add_incoming_to_phi(&mut self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) {
B
Ben Harris 已提交
1336
        self.count_insn("addincoming");
1337 1338 1339 1340 1341
        unsafe {
            llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
        }
    }

1342
    fn set_invariant_load(&mut self, load: &'ll Value) {
1343 1344
        unsafe {
            llvm::LLVMSetMetadata(load, llvm::MD_invariant_load as c_uint,
1345
                                  llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0));
1346 1347 1348
        }
    }

1349
    fn check_store<'b>(&mut self,
1350 1351
                       val: &'ll Value,
                       ptr: &'ll Value) -> &'ll Value {
1352 1353
        let dest_ptr_ty = self.cx.val_ty(ptr);
        let stored_ty = self.cx.val_ty(val);
1354
        let stored_ptr_ty = self.cx.type_ptr_to(stored_ty);
1355

D
Denis Merigoux 已提交
1356
        assert_eq!(self.cx.type_kind(dest_ptr_ty), TypeKind::Pointer);
1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367

        if dest_ptr_ty == stored_ptr_ty {
            ptr
        } else {
            debug!("Type mismatch in store. \
                    Expected {:?}, got {:?}; inserting bitcast",
                   dest_ptr_ty, stored_ptr_ty);
            self.bitcast(ptr, stored_ptr_ty)
        }
    }

1368
    fn check_call<'b>(&mut self,
1369
                      typ: &str,
1370 1371
                      llfn: &'ll Value,
                      args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> {
1372
        let mut fn_ty = self.cx.val_ty(llfn);
1373
        // Strip off pointers
D
Denis Merigoux 已提交
1374
        while self.cx.type_kind(fn_ty) == TypeKind::Pointer {
D
Denis Merigoux 已提交
1375
            fn_ty = self.cx.element_type(fn_ty);
1376 1377
        }

D
Denis Merigoux 已提交
1378
        assert!(self.cx.type_kind(fn_ty) == TypeKind::Function,
1379
                "builder::{} not passed a function, but {:?}", typ, fn_ty);
1380

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

1383
        let all_args_match = param_tys.iter()
1384
            .zip(args.iter().map(|&v| self.val_ty(v)))
1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
            .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);

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

        let casted_args: Vec<_> = param_tys.into_iter()
            .zip(args.iter())
            .enumerate()
            .map(|(i, (expected_ty, &actual_val))| {
1395
                let actual_ty = self.val_ty(actual_val);
1396 1397 1398
                if expected_ty != actual_ty {
                    debug!("Type mismatch in function call of {:?}. \
                            Expected {:?} for param {}, got {:?}; injecting bitcast",
1399
                           llfn, expected_ty, i, actual_ty);
1400 1401 1402 1403 1404 1405
                    self.bitcast(actual_val, expected_ty)
                } else {
                    actual_val
                }
            })
            .collect();
1406

L
ljedrz 已提交
1407
        Cow::Owned(casted_args)
1408
    }
1409

1410
    fn lifetime_start(&mut self, ptr: &'ll Value, size: Size) {
1411 1412 1413
        self.call_lifetime_intrinsic("llvm.lifetime.start", ptr, size);
    }

1414
    fn lifetime_end(&mut self, ptr: &'ll Value, size: Size) {
1415 1416 1417
        self.call_lifetime_intrinsic("llvm.lifetime.end", ptr, size);
    }

1418
    fn call(
1419
        &mut self,
1420 1421 1422 1423
        llfn: &'ll Value,
        args: &[&'ll Value],
        funclet: Option<&Funclet<'ll>>,
    ) -> &'ll Value {
1424 1425 1426 1427 1428 1429 1430
        self.count_insn("call");

        debug!("Call {:?} with args ({:?})",
               llfn,
               args);

        let args = self.check_call("call", llfn, args);
1431
        let bundle = funclet.map(|funclet| funclet.bundle());
1432
        let bundle = bundle.as_ref().map(|b| &*b.raw);
1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444

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

1445
    fn zext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
1446 1447 1448 1449 1450 1451
        self.count_insn("zext");
        unsafe {
            llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, noname())
        }
    }

1452
    fn struct_gep(&mut self, ptr: &'ll Value, idx: u64) -> &'ll Value {
1453 1454 1455 1456 1457 1458 1459
        self.count_insn("structgep");
        assert_eq!(idx as c_uint as u64, idx);
        unsafe {
            llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname())
        }
    }

1460
    fn cx(&self) -> &CodegenCx<'ll, 'tcx> {
1461
        self.cx
1462
    }
1463

1464 1465
    unsafe fn delete_basic_block(&mut self, bb: &'ll BasicBlock) {
        llvm::LLVMDeleteBasicBlock(bb);
1466 1467
    }

1468
    fn do_not_inline(&mut self, llret: &'ll Value) {
1469 1470
        llvm::Attribute::NoInline.apply_callsite(llvm::AttributePlace::Function, llret);
    }
1471
}
1472

B
bjorn3 已提交
1473 1474 1475 1476 1477 1478
impl StaticBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
    fn get_static(&self, def_id: DefId) -> &'ll Value {
        self.cx().get_static(def_id)
    }
}

1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495
impl Builder<'a, 'll, 'tcx> {
    fn call_lifetime_intrinsic(&mut self, intrinsic: &str, ptr: &'ll Value, size: Size) {
        if self.cx.sess().opts.optimize == config::OptLevel::No {
            return;
        }

        let size = size.bytes();
        if size == 0 {
            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);
    }
}