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_;
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;
D
Denis Merigoux 已提交
22
use interfaces::{BuilderMethods, Backend, CommonMethods, CommonWriteMethods, 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 60 61 62
impl Backend for Builder<'a, 'll, 'tcx>  {
        type Value = &'ll Value;
        type BasicBlock = &'ll BasicBlock;
        type Type = &'ll type_::Type;
D
Denis Merigoux 已提交
63
        type TypeKind = llvm::TypeKind;
64
        type Context = &'ll llvm::Context;
65
}
66

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

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

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

101
    fn sess(&self) -> &Session {
102
        self.cx.sess()
103 104
    }

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

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

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

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

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

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

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

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

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

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

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

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

197
    fn invoke(&self,
198 199 200 201
                  llfn: &'ll Value,
                  args: &[&'ll Value],
                  then: &'ll BasicBlock,
                  catch: &'ll BasicBlock,
D
Denis Merigoux 已提交
202
                  bundle: Option<&common::OperandBundleDef<'ll, &'ll Value>>) -> &'ll Value {
203
        self.count_insn("invoke");
204

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

463
    fn array_alloca(&self,
464
                        ty: Self::Type,
465
                        len: &'ll Value,
M
Masaki Hara 已提交
466
                        name: &str,
467
                        align: Align) -> &'ll Value {
M
Masaki Hara 已提交
468 469 470 471 472 473 474 475 476 477 478 479 480 481
        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
        }
    }

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

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

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


521
    fn range_metadata(&self, load: &'ll Value, range: Range<u128>) {
522 523 524 525 526 527 528 529
        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;
        }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

700

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

861
    fn vector_splat(&self, num_elts: usize, elt: &'ll Value) -> &'ll Value {
862
        unsafe {
863
            let elt_ty = self.cx.val_ty(elt);
D
Denis Merigoux 已提交
864
            let undef = llvm::LLVMGetUndef(&self.cx().vector(elt_ty, num_elts as u64));
865
            let vec = self.insert_element(undef, elt, self.cx.c_i32(0));
D
Denis Merigoux 已提交
866 867
            let vec_i32_ty = &self.cx().vector(&self.cx().i32(), num_elts as u64);
            self.shuffle_vector(vec, undef, self.cx().c_null(vec_i32_ty))
868 869 870
        }
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1139 1140
    /// Returns the ptr value that should be used for storing `val`.
    fn check_store<'b>(&self,
1141 1142
                       val: &'ll Value,
                       ptr: &'ll Value) -> &'ll Value {
1143 1144
        let dest_ptr_ty = self.cx.val_ty(ptr);
        let stored_ty = self.cx.val_ty(val);
D
Denis Merigoux 已提交
1145
        let stored_ptr_ty = self.cx.ptr_to(stored_ty);
1146

D
Denis Merigoux 已提交
1147
        assert_eq!(self.cx.kind(dest_ptr_ty), llvm::TypeKind::Pointer);
1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159

        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`.
1160 1161
    fn check_call<'b>(&self,
                      typ: &str,
1162 1163
                      llfn: &'ll Value,
                      args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> {
1164
        let mut fn_ty = self.cx.val_ty(llfn);
1165
        // Strip off pointers
D
Denis Merigoux 已提交
1166 1167
        while self.cx.kind(fn_ty) == llvm::TypeKind::Pointer {
            fn_ty = self.cx.element_type(fn_ty);
1168 1169
        }

D
Denis Merigoux 已提交
1170
        assert!(self.cx.kind(fn_ty) == llvm::TypeKind::Function,
1171
                "builder::{} not passed a function, but {:?}", typ, fn_ty);
1172

D
Denis Merigoux 已提交
1173
        let param_tys = self.cx.func_params(fn_ty);
1174

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

L
ljedrz 已提交
1199
        Cow::Owned(casted_args)
1200
    }
1201

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

1206
    fn lifetime_end(&self, ptr: &'ll Value, size: Size) {
1207 1208 1209 1210 1211 1212 1213
        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
1214
    /// block of generated code is targeted for the intrinsic.
1215 1216 1217
    ///
    /// If LLVM lifetime intrinsic support is disabled (i.e.  optimizations
    /// off) or `ptr` is zero-sized, then no-op (does not call `emit`).
1218
    fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: &'ll Value, size: Size) {
1219
        if self.cx.sess().opts.optimize == config::OptLevel::No {
1220 1221 1222 1223 1224 1225 1226 1227
            return;
        }

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

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

D
Denis Merigoux 已提交
1230
        let ptr = self.pointercast(ptr, self.cx.i8p());
1231
        self.call(lifetime_intrinsic, &[self.cx.c_u64(size), ptr], None);
1232
    }
1233

1234
    fn call(&self, llfn: &'ll Value, args: &[&'ll Value],
D
Denis Merigoux 已提交
1235
                bundle: Option<&common::OperandBundleDef<'ll, &'ll Value>>) -> &'ll Value {
1236 1237 1238 1239 1240 1241 1242
        self.count_insn("call");

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

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

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

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

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

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