builder.rs 41.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

11
use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
12
use llvm::{self, False, OperandBundleDef, BasicBlock};
D
Denis Merigoux 已提交
13
use common::{self, *};
14
use context::CodegenCx;
15
use type_::Type;
16
use value::Value;
17
use libc::{c_uint, c_char};
18
use rustc::ty::TyCtxt;
19 20
use rustc::ty::layout::{Align, Size};
use rustc::session::{config, Session};
21
use rustc_data_structures::small_c_str::SmallCStr;
22
use interfaces::{BuilderMethods, Backend, ConstMethods, TypeMethods};
23
use syntax;
A
Alex Crichton 已提交
24

25
use std::borrow::Cow;
26
use std::ops::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: 'a, 'tcx: 'll, V: 'll = &'ll Value> {
32
    pub llbuilder: &'ll mut llvm::Builder<'ll>,
D
Denis Merigoux 已提交
33
    pub cx: &'a CodegenCx<'ll, 'tcx, V>,
34 35
}

36
impl<V> Drop for Builder<'a, 'll, 'tcx, V> {
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 45
// 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 已提交
46
fn noname() -> *const c_char {
47
    static CNULL: c_char = 0;
48
    &CNULL
49 50
}

51 52 53 54
bitflags! {
    pub struct MemFlags: u8 {
        const VOLATILE = 1 << 0;
        const NONTEMPORAL = 1 << 1;
55
        const UNALIGNED = 1 << 2;
56 57 58
    }
}

59
impl Backend for Builder<'a, 'll, 'tcx>  {
60 61 62 63 64
    type Value = &'ll Value;
    type BasicBlock = &'ll BasicBlock;
    type Type = &'ll Type;
    type TypeKind = llvm::TypeKind;
    type Context = &'ll llvm::Context;
65
}
66

67 68 69
impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
    type CodegenCx = CodegenCx<'ll, 'tcx>;

70 71
    fn new_block<'b>(
        cx: &'a CodegenCx<'ll, 'tcx>,
72
        llfn: &'ll Value,
73 74
        name: &'b str
    ) -> Self {
75
        let bx = Builder::with_cx(cx);
76
        let llbb = unsafe {
77
            let name = SmallCStr::new(name);
78
            llvm::LLVMAppendBasicBlockInContext(
79
                cx.llcx,
80 81 82 83
                llfn,
                name.as_ptr()
            )
        };
84 85
        bx.position_at_end(llbb);
        bx
86 87
    }

88
    fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self {
M
Mark-Simulacrum 已提交
89 90
        // Create a fresh builder from the crate context.
        let llbuilder = unsafe {
91
            llvm::LLVMCreateBuilderInContext(cx.llcx)
M
Mark-Simulacrum 已提交
92
        };
93
        Builder {
94
            llbuilder,
95
            cx,
96 97 98
        }
    }

99
    fn build_sibling_block<'b>(&self, name: &'b str) -> Self {
100
        Builder::new_block(self.cx, self.llfn(), name)
101 102
    }

103
    fn sess(&self) -> &Session {
104
        self.cx.sess()
105 106
    }

107
    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
108
        self.cx.tcx
109 110
    }

111
    fn llfn(&self) -> &'ll Value {
112 113 114 115 116
        unsafe {
            llvm::LLVMGetBasicBlockParent(self.llbb())
        }
    }

117
    fn llbb(&self) -> &'ll BasicBlock {
118 119 120 121 122
        unsafe {
            llvm::LLVMGetInsertBlock(self.llbuilder)
        }
    }

M
Mark-Simulacrum 已提交
123
    fn count_insn(&self, category: &str) {
124 125
        if self.cx().sess().codegen_stats() {
            self.cx().stats.borrow_mut().n_llvm_insns += 1;
126
        }
127 128 129 130 131 132
        if self.cx().sess().count_llvm_insns() {
            *self.cx().stats
                      .borrow_mut()
                      .llvm_insns
                      .entry(category.to_string())
                      .or_insert(0) += 1;
133 134 135
        }
    }

136
    fn set_value_name(&self, value: &'ll Value, name: &str) {
137
        let cname = SmallCStr::new(name);
138 139 140 141 142
        unsafe {
            llvm::LLVMSetValueName(value, cname.as_ptr());
        }
    }

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

149
    fn position_at_start(&self, llbb: &'ll BasicBlock) {
150 151 152 153 154
        unsafe {
            llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb);
        }
    }

155
    fn ret_void(&self) {
156 157 158 159 160 161
        self.count_insn("retvoid");
        unsafe {
            llvm::LLVMBuildRetVoid(self.llbuilder);
        }
    }

162
    fn ret(&self, v: &'ll Value) {
163 164 165 166 167 168
        self.count_insn("ret");
        unsafe {
            llvm::LLVMBuildRet(self.llbuilder, v);
        }
    }

169
    fn br(&self, dest: &'ll BasicBlock) {
170 171 172 173 174 175
        self.count_insn("br");
        unsafe {
            llvm::LLVMBuildBr(self.llbuilder, dest);
        }
    }

176
    fn cond_br(
177
        &self,
178 179 180
        cond: &'ll Value,
        then_llbb: &'ll BasicBlock,
        else_llbb: &'ll BasicBlock,
181
    ) {
182 183 184 185 186 187
        self.count_insn("condbr");
        unsafe {
            llvm::LLVMBuildCondBr(self.llbuilder, cond, then_llbb, else_llbb);
        }
    }

188
    fn switch(
189
        &self,
190 191
        v: &'ll Value,
        else_llbb: &'ll BasicBlock,
192
        num_cases: usize,
193
    ) -> &'ll Value {
194 195 196 197 198
        unsafe {
            llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, num_cases as c_uint)
        }
    }

199
    fn invoke(&self,
200 201 202 203
                  llfn: &'ll Value,
                  args: &[&'ll Value],
                  then: &'ll BasicBlock,
                  catch: &'ll BasicBlock,
204
                  bundle: Option<&common::OperandBundleDef<&'ll Value>>) -> &'ll Value {
205
        self.count_insn("invoke");
206

207 208 209
        debug!("Invoke {:?} with args ({:?})",
               llfn,
               args);
210

211
        let args = self.check_call("invoke", llfn, args);
212 213
        let bundle = bundle.map(OperandBundleDef::from_generic);
        let bundle = bundle.as_ref().map(|b| &*b.raw);
214

215
        unsafe {
216 217 218 219 220 221 222 223
            llvm::LLVMRustBuildInvoke(self.llbuilder,
                                      llfn,
                                      args.as_ptr(),
                                      args.len() as c_uint,
                                      then,
                                      catch,
                                      bundle,
                                      noname())
224
        }
225 226
    }

227
    fn unreachable(&self) {
228 229 230 231 232 233 234
        self.count_insn("unreachable");
        unsafe {
            llvm::LLVMBuildUnreachable(self.llbuilder);
        }
    }

    /* Arithmetic */
235
    fn add(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
236 237 238 239 240 241
        self.count_insn("add");
        unsafe {
            llvm::LLVMBuildAdd(self.llbuilder, lhs, rhs, noname())
        }
    }

242
    fn fadd(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
243 244 245 246 247 248
        self.count_insn("fadd");
        unsafe {
            llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname())
        }
    }

249
    fn fadd_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
250 251 252 253 254 255 256 257
        self.count_insn("fadd");
        unsafe {
            let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname());
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }

258
    fn sub(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
259 260 261 262 263 264
        self.count_insn("sub");
        unsafe {
            llvm::LLVMBuildSub(self.llbuilder, lhs, rhs, noname())
        }
    }

265
    fn fsub(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
B
Ben Harris 已提交
266
        self.count_insn("fsub");
267 268 269 270 271
        unsafe {
            llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname())
        }
    }

272
    fn fsub_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
B
Ben Harris 已提交
273
        self.count_insn("fsub");
274 275 276 277 278 279 280
        unsafe {
            let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname());
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }

281
    fn mul(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
282 283 284 285 286 287
        self.count_insn("mul");
        unsafe {
            llvm::LLVMBuildMul(self.llbuilder, lhs, rhs, noname())
        }
    }

288
    fn fmul(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
289 290 291 292 293 294
        self.count_insn("fmul");
        unsafe {
            llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname())
        }
    }

295
    fn fmul_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
296 297 298 299 300 301 302 303 304
        self.count_insn("fmul");
        unsafe {
            let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname());
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }


305
    fn udiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
306 307 308 309 310 311
        self.count_insn("udiv");
        unsafe {
            llvm::LLVMBuildUDiv(self.llbuilder, lhs, rhs, noname())
        }
    }

312
    fn exactudiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
313 314 315 316 317 318
        self.count_insn("exactudiv");
        unsafe {
            llvm::LLVMBuildExactUDiv(self.llbuilder, lhs, rhs, noname())
        }
    }

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

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

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

340
    fn fdiv_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
341 342 343 344 345 346 347 348
        self.count_insn("fdiv");
        unsafe {
            let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname());
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }

349
    fn urem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
350 351 352 353 354 355
        self.count_insn("urem");
        unsafe {
            llvm::LLVMBuildURem(self.llbuilder, lhs, rhs, noname())
        }
    }

356
    fn srem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
357 358 359 360 361 362
        self.count_insn("srem");
        unsafe {
            llvm::LLVMBuildSRem(self.llbuilder, lhs, rhs, noname())
        }
    }

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

370
    fn frem_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
371 372 373 374 375 376 377 378
        self.count_insn("frem");
        unsafe {
            let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname());
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }

379
    fn shl(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
380 381 382 383 384 385
        self.count_insn("shl");
        unsafe {
            llvm::LLVMBuildShl(self.llbuilder, lhs, rhs, noname())
        }
    }

386
    fn lshr(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
387 388 389 390 391 392
        self.count_insn("lshr");
        unsafe {
            llvm::LLVMBuildLShr(self.llbuilder, lhs, rhs, noname())
        }
    }

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

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

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

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

421
    fn neg(&self, v: &'ll Value) -> &'ll Value {
422 423
        self.count_insn("neg");
        unsafe {
424
            llvm::LLVMBuildNeg(self.llbuilder, v, noname())
425 426 427
        }
    }

428
    fn fneg(&self, v: &'ll Value) -> &'ll Value {
429 430
        self.count_insn("fneg");
        unsafe {
431
            llvm::LLVMBuildFNeg(self.llbuilder, v, noname())
432 433 434
        }
    }

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

442
    fn alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
443 444
        let bx = Builder::with_cx(self.cx);
        bx.position_at_start(unsafe {
445 446
            llvm::LLVMGetFirstBasicBlock(self.llfn())
        });
447
        bx.dynamic_alloca(ty, name, align)
448 449
    }

450
    fn dynamic_alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
451 452
        self.count_insn("alloca");
        unsafe {
453
            let alloca = if name.is_empty() {
454
                llvm::LLVMBuildAlloca(self.llbuilder, ty, noname())
455
            } else {
456
                let name = SmallCStr::new(name);
457
                llvm::LLVMBuildAlloca(self.llbuilder, ty,
A
Alex Crichton 已提交
458
                                      name.as_ptr())
459
            };
460
            llvm::LLVMSetAlignment(alloca, align.abi() as c_uint);
461
            alloca
462 463 464
        }
    }

465
    fn array_alloca(&self,
466
                        ty: &'ll Type,
467
                        len: &'ll Value,
M
Masaki Hara 已提交
468
                        name: &str,
469
                        align: Align) -> &'ll Value {
M
Masaki Hara 已提交
470 471 472 473 474 475 476 477 478 479 480 481 482 483
        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())
            };
            llvm::LLVMSetAlignment(alloca, align.abi() as c_uint);
            alloca
        }
    }

484
    fn load(&self, ptr: &'ll Value, align: Align) -> &'ll Value {
485 486
        self.count_insn("load");
        unsafe {
487
            let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
488
            llvm::LLVMSetAlignment(load, align.abi() as c_uint);
489
            load
490 491 492
        }
    }

493
    fn volatile_load(&self, ptr: &'ll Value) -> &'ll Value {
494 495 496
        self.count_insn("load.volatile");
        unsafe {
            let insn = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
497
            llvm::LLVMSetVolatile(insn, llvm::True);
498 499 500 501
            insn
        }
    }

502 503
    fn atomic_load(
        &self,
504
        ptr: &'ll Value,
D
Denis Merigoux 已提交
505
        order: common::AtomicOrdering,
506
        size: Size,
507
    ) -> &'ll Value {
508 509
        self.count_insn("load.atomic");
        unsafe {
510 511 512 513 514 515
            let load = llvm::LLVMRustBuildAtomicLoad(
                self.llbuilder,
                ptr,
                noname(),
                AtomicOrdering::from_generic(order),
            );
516 517
            // LLVM requires the alignment of atomic loads to be at least the size of the type.
            llvm::LLVMSetAlignment(load, size.bytes() as c_uint);
518
            load
519 520 521 522
        }
    }


523
    fn range_metadata(&self, load: &'ll Value, range: Range<u128>) {
524 525 526 527 528 529 530 531
        if self.sess().target.target.arch == "amdgpu" {
            // 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;
        }

532
        unsafe {
533
            let llty = self.cx.val_ty(load);
534
            let v = [
535 536
                self.cx.const_uint_big(llty, range.start),
                self.cx.const_uint_big(llty, range.end)
537
            ];
538

539
            llvm::LLVMSetMetadata(load, llvm::MD_range as c_uint,
540
                                  llvm::LLVMMDNodeInContext(self.cx.llcx,
541 542
                                                            v.as_ptr(),
                                                            v.len() as c_uint));
543 544 545
        }
    }

546
    fn nonnull_metadata(&self, load: &'ll Value) {
547
        unsafe {
548
            llvm::LLVMSetMetadata(load, llvm::MD_nonnull as c_uint,
549
                                  llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0));
550 551 552
        }
    }

553
    fn store(&self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value {
554 555 556
        self.store_with_flags(val, ptr, align, MemFlags::empty())
    }

557
    fn store_with_flags(
558
        &self,
559 560
        val: &'ll Value,
        ptr: &'ll Value,
561 562
        align: Align,
        flags: MemFlags,
563
    ) -> &'ll Value {
564
        debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags);
565
        self.count_insn("store");
566
        let ptr = self.check_store(val, ptr);
567
        unsafe {
568
            let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
569 570 571 572 573 574
            let align = if flags.contains(MemFlags::UNALIGNED) {
                1
            } else {
                align.abi() as c_uint
            };
            llvm::LLVMSetAlignment(store, align);
575 576 577 578 579 580 581 582
            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
583
                let one = self.cx.const_i32(1);
584 585 586
                let node = llvm::LLVMMDNodeInContext(self.cx.llcx, &one, 1);
                llvm::LLVMSetMetadata(store, llvm::MD_nontemporal as c_uint, node);
            }
587
            store
588 589 590
        }
    }

591
   fn atomic_store(&self, val: &'ll Value, ptr: &'ll Value,
D
Denis Merigoux 已提交
592
                   order: common::AtomicOrdering, size: Size) {
593
        debug!("Store {:?} -> {:?}", val, ptr);
594
        self.count_insn("store.atomic");
595
        let ptr = self.check_store(val, ptr);
596
        unsafe {
597 598 599 600 601 602
            let store = llvm::LLVMRustBuildAtomicStore(
                self.llbuilder,
                val,
                ptr,
                AtomicOrdering::from_generic(order),
            );
603 604
            // LLVM requires the alignment of atomic stores to be at least the size of the type.
            llvm::LLVMSetAlignment(store, size.bytes() as c_uint);
605 606 607
        }
    }

608
    fn gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
609 610
        self.count_insn("gep");
        unsafe {
611
            llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(),
612 613 614 615
                               indices.len() as c_uint, noname())
        }
    }

616
    fn inbounds_gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
617 618 619
        self.count_insn("inboundsgep");
        unsafe {
            llvm::LLVMBuildInBoundsGEP(
620
                self.llbuilder, ptr, indices.as_ptr(), indices.len() as c_uint, noname())
621 622 623 624
        }
    }

    /* Casts */
625
    fn trunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
626 627
        self.count_insn("trunc");
        unsafe {
628
            llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, noname())
629 630 631
        }
    }

632
    fn sext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
633 634
        self.count_insn("sext");
        unsafe {
635
            llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, noname())
636 637 638
        }
    }

639
    fn fptoui(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
640 641
        self.count_insn("fptoui");
        unsafe {
642
            llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, noname())
643 644 645
        }
    }

646
    fn fptosi(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
647 648
        self.count_insn("fptosi");
        unsafe {
649
            llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,noname())
650 651 652
        }
    }

653
    fn uitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
654 655
        self.count_insn("uitofp");
        unsafe {
656
            llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, noname())
657 658 659
        }
    }

660
    fn sitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
661 662
        self.count_insn("sitofp");
        unsafe {
663
            llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, noname())
664 665 666
        }
    }

667
    fn fptrunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
668 669
        self.count_insn("fptrunc");
        unsafe {
670
            llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, noname())
671 672 673
        }
    }

674
    fn fpext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
675 676
        self.count_insn("fpext");
        unsafe {
677
            llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, noname())
678 679 680
        }
    }

681
    fn ptrtoint(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
682 683
        self.count_insn("ptrtoint");
        unsafe {
684
            llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, noname())
685 686 687
        }
    }

688
    fn inttoptr(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
689 690
        self.count_insn("inttoptr");
        unsafe {
691
            llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, noname())
692 693 694
        }
    }

695
    fn bitcast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
696 697
        self.count_insn("bitcast");
        unsafe {
698
            llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, noname())
699 700 701
        }
    }

702

703
    fn intcast(&self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value {
704
        self.count_insn("intcast");
705
        unsafe {
706
            llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed)
707 708 709
        }
    }

710
    fn pointercast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
711
        self.count_insn("pointercast");
712
        unsafe {
713
            llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname())
714 715 716 717
        }
    }

    /* Comparisons */
D
Denis Merigoux 已提交
718
    fn icmp(&self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
719
        self.count_insn("icmp");
720
        let op = llvm::IntPredicate::from_generic(op);
721 722 723 724 725
        unsafe {
            llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
        }
    }

D
Denis Merigoux 已提交
726
    fn fcmp(&self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
727 728 729 730 731 732 733
        self.count_insn("fcmp");
        unsafe {
            llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
        }
    }

    /* Miscellaneous instructions */
734
    fn empty_phi(&self, ty: &'ll Type) -> &'ll Value {
735 736
        self.count_insn("emptyphi");
        unsafe {
737
            llvm::LLVMBuildPhi(self.llbuilder, ty, noname())
738 739 740
        }
    }

741
    fn phi(&self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
742 743 744 745
        assert_eq!(vals.len(), bbs.len());
        let phi = self.empty_phi(ty);
        self.count_insn("addincoming");
        unsafe {
746 747
            llvm::LLVMAddIncoming(phi, vals.as_ptr(),
                                  bbs.as_ptr(),
748 749 750 751 752
                                  vals.len() as c_uint);
            phi
        }
    }

753
    fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char,
754
                       inputs: &[&'ll Value], output: &'ll Type,
755
                       volatile: bool, alignstack: bool,
756
                       dia: syntax::ast::AsmDialect) -> Option<&'ll Value> {
757 758
        self.count_insn("inlineasm");

759 760 761 762
        let volatile = if volatile { llvm::True }
                       else        { llvm::False };
        let alignstack = if alignstack { llvm::True }
                         else          { llvm::False };
763

764
        let argtys = inputs.iter().map(|v| {
765
            debug!("Asm Input Type: {:?}", *v);
766
            self.cx.val_ty(*v)
767
        }).collect::<Vec<_>>();
768

769
        debug!("Asm Output Type: {:?}", output);
770
        let fty = &self.cx().type_func(&argtys[..], output);
771
        unsafe {
772 773 774
            // Ask LLVM to verify that the constraints are well-formed.
            let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons);
            debug!("Constraint verification result: {:?}", constraints_ok);
775
            if constraints_ok {
776
                let v = llvm::LLVMRustInlineAsm(
777
                    fty, asm, cons, volatile, alignstack, AsmDialect::from_generic(dia));
778 779
                Some(self.call(v, inputs, None))
            } else {
M
Matthias Krüger 已提交
780
                // LLVM has detected an issue with our constraints, bail out
781 782
                None
            }
783 784 785
        }
    }

786 787 788
    fn memcpy(&self, dst: &'ll Value, dst_align: u64,
                  src: &'ll Value, src_align: u64,
                  size: &'ll Value, is_volatile: bool) -> &'ll Value {
789 790 791 792 793 794
        unsafe {
            llvm::LLVMRustBuildMemCpy(self.llbuilder, dst, dst_align as c_uint,
                                      src, src_align as c_uint, size, is_volatile)
        }
    }

795 796 797
    fn memmove(&self, dst: &'ll Value, dst_align: u64,
                  src: &'ll Value, src_align: u64,
                  size: &'ll Value, is_volatile: bool) -> &'ll Value {
798 799 800 801 802 803
        unsafe {
            llvm::LLVMRustBuildMemMove(self.llbuilder, dst, dst_align as c_uint,
                                      src, src_align as c_uint, size, is_volatile)
        }
    }

804
    fn minnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
G
gnzlbg 已提交
805 806
        self.count_insn("minnum");
        unsafe {
G
gnzlbg 已提交
807
            let instr = llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs);
808
            instr.expect("LLVMRustBuildMinNum is not available in LLVM version < 6.0")
G
gnzlbg 已提交
809 810
        }
    }
811
    fn maxnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
G
gnzlbg 已提交
812 813
        self.count_insn("maxnum");
        unsafe {
G
gnzlbg 已提交
814
            let instr = llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs);
815
            instr.expect("LLVMRustBuildMaxNum is not available in LLVM version < 6.0")
G
gnzlbg 已提交
816 817 818
        }
    }

819
    fn select(
820 821 822 823
        &self, cond: &'ll Value,
        then_val: &'ll Value,
        else_val: &'ll Value,
    ) -> &'ll Value {
824 825 826 827 828 829
        self.count_insn("select");
        unsafe {
            llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname())
        }
    }

830
    #[allow(dead_code)]
831
    fn va_arg(&self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
832 833
        self.count_insn("vaarg");
        unsafe {
834
            llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
835 836 837
        }
    }

838
    fn extract_element(&self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value {
839 840 841 842 843 844
        self.count_insn("extractelement");
        unsafe {
            llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname())
        }
    }

845
    fn insert_element(
846 847 848 849
        &self, vec: &'ll Value,
        elt: &'ll Value,
        idx: &'ll Value,
    ) -> &'ll Value {
850 851 852 853 854 855
        self.count_insn("insertelement");
        unsafe {
            llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname())
        }
    }

856
    fn shuffle_vector(&self, v1: &'ll Value, v2: &'ll Value, mask: &'ll Value) -> &'ll Value {
857 858 859 860 861 862
        self.count_insn("shufflevector");
        unsafe {
            llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname())
        }
    }

863
    fn vector_splat(&self, num_elts: usize, elt: &'ll Value) -> &'ll Value {
864
        unsafe {
865
            let elt_ty = self.cx.val_ty(elt);
866
            let undef = llvm::LLVMGetUndef(&self.cx().type_vector(elt_ty, num_elts as u64));
867
            let vec = self.insert_element(undef, elt, self.cx.const_i32(0));
868
            let vec_i32_ty = &self.cx().type_vector(&self.cx().type_i32(), num_elts as u64);
869
            self.shuffle_vector(vec, undef, self.cx().const_null(vec_i32_ty))
870 871 872
        }
    }

873
    fn vector_reduce_fadd_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
874 875
        self.count_insn("vector.reduce.fadd_fast");
        unsafe {
876 877 878
            // FIXME: add a non-fast math version once
            // https://bugs.llvm.org/show_bug.cgi?id=36732
            // is fixed.
879
            let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src);
880 881 882 883
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }
884
    fn vector_reduce_fmul_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
885 886
        self.count_insn("vector.reduce.fmul_fast");
        unsafe {
887 888 889
            // FIXME: add a non-fast math version once
            // https://bugs.llvm.org/show_bug.cgi?id=36732
            // is fixed.
890
            let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src);
891 892 893 894
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }
895
    fn vector_reduce_add(&self, src: &'ll Value) -> &'ll Value {
896
        self.count_insn("vector.reduce.add");
897
        unsafe { llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) }
898
    }
899
    fn vector_reduce_mul(&self, src: &'ll Value) -> &'ll Value {
900
        self.count_insn("vector.reduce.mul");
901
        unsafe { llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) }
902
    }
903
    fn vector_reduce_and(&self, src: &'ll Value) -> &'ll Value {
904
        self.count_insn("vector.reduce.and");
905
        unsafe { llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) }
906
    }
907
    fn vector_reduce_or(&self, src: &'ll Value) -> &'ll Value {
908
        self.count_insn("vector.reduce.or");
909
        unsafe { llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) }
910
    }
911
    fn vector_reduce_xor(&self, src: &'ll Value) -> &'ll Value {
912
        self.count_insn("vector.reduce.xor");
913
        unsafe { llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) }
914
    }
915
    fn vector_reduce_fmin(&self, src: &'ll Value) -> &'ll Value {
916
        self.count_insn("vector.reduce.fmin");
917
        unsafe { llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false) }
918
    }
919
    fn vector_reduce_fmax(&self, src: &'ll Value) -> &'ll Value {
920
        self.count_insn("vector.reduce.fmax");
921
        unsafe { llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false) }
922
    }
923
    fn vector_reduce_fmin_fast(&self, src: &'ll Value) -> &'ll Value {
924 925
        self.count_insn("vector.reduce.fmin_fast");
        unsafe {
926
            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true);
927 928 929 930
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }
931
    fn vector_reduce_fmax_fast(&self, src: &'ll Value) -> &'ll Value {
932 933
        self.count_insn("vector.reduce.fmax_fast");
        unsafe {
934
            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true);
935 936 937 938
            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
            instr
        }
    }
939
    fn vector_reduce_min(&self, src: &'ll Value, is_signed: bool) -> &'ll Value {
940
        self.count_insn("vector.reduce.min");
941
        unsafe { llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) }
942
    }
943
    fn vector_reduce_max(&self, src: &'ll Value, is_signed: bool) -> &'ll Value {
944
        self.count_insn("vector.reduce.max");
945
        unsafe { llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed) }
946 947
    }

948
    fn extract_value(&self, agg_val: &'ll Value, idx: u64) -> &'ll Value {
949
        self.count_insn("extractvalue");
950
        assert_eq!(idx as c_uint as u64, idx);
951 952 953 954 955
        unsafe {
            llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, noname())
        }
    }

956 957
    fn insert_value(&self, agg_val: &'ll Value, elt: &'ll Value,
                       idx: u64) -> &'ll Value {
958
        self.count_insn("insertvalue");
959
        assert_eq!(idx as c_uint as u64, idx);
960 961
        unsafe {
            llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint,
962
                                       noname())
963 964 965
        }
    }

966
    fn landing_pad(&self, ty: &'ll Type, pers_fn: &'ll Value,
967
                       num_clauses: usize) -> &'ll Value {
968 969
        self.count_insn("landingpad");
        unsafe {
970
            llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn,
971
                                      num_clauses as c_uint, noname())
972 973 974
        }
    }

975
    fn add_clause(&self, landing_pad: &'ll Value, clause: &'ll Value) {
976 977 978 979 980
        unsafe {
            llvm::LLVMAddClause(landing_pad, clause);
        }
    }

981
    fn set_cleanup(&self, landing_pad: &'ll Value) {
982 983
        self.count_insn("setcleanup");
        unsafe {
984
            llvm::LLVMSetCleanup(landing_pad, llvm::True);
985 986 987
        }
    }

988
    fn resume(&self, exn: &'ll Value) -> &'ll Value {
989 990 991 992 993 994
        self.count_insn("resume");
        unsafe {
            llvm::LLVMBuildResume(self.llbuilder, exn)
        }
    }

995
    fn cleanup_pad(&self,
996 997
                       parent: Option<&'ll Value>,
                       args: &[&'ll Value]) -> &'ll Value {
998
        self.count_insn("cleanuppad");
999
        let name = const_cstr!("cleanuppad");
1000 1001 1002 1003 1004 1005 1006
        let ret = unsafe {
            llvm::LLVMRustBuildCleanupPad(self.llbuilder,
                                          parent,
                                          args.len() as c_uint,
                                          args.as_ptr(),
                                          name.as_ptr())
        };
1007
        ret.expect("LLVM does not have support for cleanuppad")
1008 1009
    }

1010
    fn cleanup_ret(
1011 1012 1013
        &self, cleanup: &'ll Value,
        unwind: Option<&'ll BasicBlock>,
    ) -> &'ll Value {
1014 1015 1016 1017
        self.count_insn("cleanupret");
        let ret = unsafe {
            llvm::LLVMRustBuildCleanupRet(self.llbuilder, cleanup, unwind)
        };
1018
        ret.expect("LLVM does not have support for cleanupret")
1019 1020
    }

1021
    fn catch_pad(&self,
1022 1023
                     parent: &'ll Value,
                     args: &[&'ll Value]) -> &'ll Value {
1024
        self.count_insn("catchpad");
1025
        let name = const_cstr!("catchpad");
1026 1027 1028 1029 1030
        let ret = unsafe {
            llvm::LLVMRustBuildCatchPad(self.llbuilder, parent,
                                        args.len() as c_uint, args.as_ptr(),
                                        name.as_ptr())
        };
1031
        ret.expect("LLVM does not have support for catchpad")
1032 1033
    }

1034
    fn catch_ret(&self, pad: &'ll Value, unwind: &'ll BasicBlock) -> &'ll Value {
1035 1036 1037 1038
        self.count_insn("catchret");
        let ret = unsafe {
            llvm::LLVMRustBuildCatchRet(self.llbuilder, pad, unwind)
        };
1039
        ret.expect("LLVM does not have support for catchret")
1040 1041
    }

1042
    fn catch_switch(
1043
        &self,
1044 1045
        parent: Option<&'ll Value>,
        unwind: Option<&'ll BasicBlock>,
1046
        num_handlers: usize,
1047
    ) -> &'ll Value {
1048
        self.count_insn("catchswitch");
1049
        let name = const_cstr!("catchswitch");
1050 1051 1052 1053 1054
        let ret = unsafe {
            llvm::LLVMRustBuildCatchSwitch(self.llbuilder, parent, unwind,
                                           num_handlers as c_uint,
                                           name.as_ptr())
        };
1055
        ret.expect("LLVM does not have support for catchswitch")
1056 1057
    }

1058
    fn add_handler(&self, catch_switch: &'ll Value, handler: &'ll BasicBlock) {
1059 1060 1061 1062 1063
        unsafe {
            llvm::LLVMRustAddHandler(catch_switch, handler);
        }
    }

1064
    fn set_personality_fn(&self, personality: &'ll Value) {
1065
        unsafe {
1066
            llvm::LLVMSetPersonalityFn(self.llfn(), personality);
1067 1068 1069
        }
    }

1070
    // Atomic Operations
1071
    fn atomic_cmpxchg(
1072
        &self,
1073 1074 1075
        dst: &'ll Value,
        cmp: &'ll Value,
        src: &'ll Value,
D
Denis Merigoux 已提交
1076 1077
        order: common::AtomicOrdering,
        failure_order: common::AtomicOrdering,
1078
        weak: bool,
1079
    ) -> &'ll Value {
1080
        let weak = if weak { llvm::True } else { llvm::False };
1081
        unsafe {
1082 1083 1084 1085 1086 1087 1088 1089 1090
            llvm::LLVMRustBuildAtomicCmpXchg(
                self.llbuilder,
                dst,
                cmp,
                src,
                AtomicOrdering::from_generic(order),
                AtomicOrdering::from_generic(failure_order),
                weak
            )
1091 1092
        }
    }
1093
    fn atomic_rmw(
1094
        &self,
D
Denis Merigoux 已提交
1095
        op: common::AtomicRmwBinOp,
1096 1097
        dst: &'ll Value,
        src: &'ll Value,
D
Denis Merigoux 已提交
1098
        order: common::AtomicOrdering,
1099
    ) -> &'ll Value {
1100
        unsafe {
1101 1102 1103 1104 1105
            llvm::LLVMBuildAtomicRMW(
                self.llbuilder,
                AtomicRmwBinOp::from_generic(op),
                dst,
                src,
1106
                AtomicOrdering::from_generic(order),
1107
                False)
1108 1109
        }
    }
J
James Miller 已提交
1110

D
Denis Merigoux 已提交
1111
    fn atomic_fence(&self, order: common::AtomicOrdering, scope: common::SynchronizationScope) {
J
James Miller 已提交
1112
        unsafe {
1113 1114 1115
            llvm::LLVMRustBuildAtomicFence(
                self.llbuilder,
                AtomicOrdering::from_generic(order),
1116
                SynchronizationScope::from_generic(scope)
1117
            );
J
James Miller 已提交
1118 1119
        }
    }
1120

1121
    fn add_case(&self, s: &'ll Value, on_val: &'ll Value, dest: &'ll BasicBlock) {
1122 1123 1124 1125 1126
        unsafe {
            llvm::LLVMAddCase(s, on_val, dest)
        }
    }

1127
    fn add_incoming_to_phi(&self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) {
B
Ben Harris 已提交
1128
        self.count_insn("addincoming");
1129 1130 1131 1132 1133
        unsafe {
            llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
        }
    }

1134
    fn set_invariant_load(&self, load: &'ll Value) {
1135 1136
        unsafe {
            llvm::LLVMSetMetadata(load, llvm::MD_invariant_load as c_uint,
1137
                                  llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0));
1138 1139 1140
        }
    }

1141 1142
    /// Returns the ptr value that should be used for storing `val`.
    fn check_store<'b>(&self,
1143 1144
                       val: &'ll Value,
                       ptr: &'ll Value) -> &'ll Value {
1145 1146
        let dest_ptr_ty = self.cx.val_ty(ptr);
        let stored_ty = self.cx.val_ty(val);
1147
        let stored_ptr_ty = self.cx.type_ptr_to(stored_ty);
1148

1149
        assert_eq!(self.cx.type_kind(dest_ptr_ty), llvm::TypeKind::Pointer);
1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161

        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)
        }
    }

    /// Returns the args that should be used for a call to `llfn`.
1162 1163
    fn check_call<'b>(&self,
                      typ: &str,
1164 1165
                      llfn: &'ll Value,
                      args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> {
1166
        let mut fn_ty = self.cx.val_ty(llfn);
1167
        // Strip off pointers
1168
        while self.cx.type_kind(fn_ty) == llvm::TypeKind::Pointer {
D
Denis Merigoux 已提交
1169
            fn_ty = self.cx.element_type(fn_ty);
1170 1171
        }

1172
        assert!(self.cx.type_kind(fn_ty) == llvm::TypeKind::Function,
1173
                "builder::{} not passed a function, but {:?}", typ, fn_ty);
1174

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

1177
        let all_args_match = param_tys.iter()
1178
            .zip(args.iter().map(|&v| self.cx().val_ty(v)))
1179 1180 1181 1182 1183 1184 1185 1186 1187 1188
            .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))| {
1189
                let actual_ty = self.cx().val_ty(actual_val);
1190 1191 1192
                if expected_ty != actual_ty {
                    debug!("Type mismatch in function call of {:?}. \
                            Expected {:?} for param {}, got {:?}; injecting bitcast",
1193
                           llfn, expected_ty, i, actual_ty);
1194 1195 1196 1197 1198 1199
                    self.bitcast(actual_val, expected_ty)
                } else {
                    actual_val
                }
            })
            .collect();
1200

L
ljedrz 已提交
1201
        Cow::Owned(casted_args)
1202
    }
1203

1204
    fn lifetime_start(&self, ptr: &'ll Value, size: Size) {
1205 1206 1207
        self.call_lifetime_intrinsic("llvm.lifetime.start", ptr, size);
    }

1208
    fn lifetime_end(&self, ptr: &'ll Value, size: Size) {
1209 1210 1211 1212 1213 1214 1215
        self.call_lifetime_intrinsic("llvm.lifetime.end", ptr, size);
    }

    /// If LLVM lifetime intrinsic support is enabled (i.e. optimizations
    /// on), and `ptr` is nonzero-sized, then extracts the size of `ptr`
    /// and the intrinsic for `lt` and passes them to `emit`, which is in
    /// charge of generating code to call the passed intrinsic on whatever
1216
    /// block of generated code is targeted for the intrinsic.
1217 1218 1219
    ///
    /// If LLVM lifetime intrinsic support is disabled (i.e.  optimizations
    /// off) or `ptr` is zero-sized, then no-op (does not call `emit`).
1220
    fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: &'ll Value, size: Size) {
1221
        if self.cx.sess().opts.optimize == config::OptLevel::No {
1222 1223 1224 1225 1226 1227 1228 1229
            return;
        }

        let size = size.bytes();
        if size == 0 {
            return;
        }

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

1232
        let ptr = self.pointercast(ptr, self.cx.type_i8p());
1233
        self.call(lifetime_intrinsic, &[self.cx.const_u64(size), ptr], None);
1234
    }
1235

1236
    fn call(&self, llfn: &'ll Value, args: &[&'ll Value],
1237
                bundle: Option<&common::OperandBundleDef<&'ll Value>>) -> &'ll Value {
1238 1239 1240 1241 1242 1243 1244
        self.count_insn("call");

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

        let args = self.check_call("call", llfn, args);
1245 1246
        let bundle = bundle.map(OperandBundleDef::from_generic);
        let bundle = bundle.as_ref().map(|b| &*b.raw);
1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258

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

1259
    fn zext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
1260 1261 1262 1263 1264 1265
        self.count_insn("zext");
        unsafe {
            llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, noname())
        }
    }

1266
    fn struct_gep(&self, ptr: &'ll Value, idx: u64) -> &'ll Value {
1267 1268 1269 1270 1271 1272 1273
        self.count_insn("structgep");
        assert_eq!(idx as c_uint as u64, idx);
        unsafe {
            llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname())
        }
    }

1274
    fn cx(&self) -> &'a CodegenCx<'ll, 'tcx> {
1275 1276
        &self.cx
    }
1277
}