common.rs 14.5 KB
Newer Older
1
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 3 4 5 6 7 8 9 10
// 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
#![allow(non_camel_case_types, non_snake_case)]
12

I
Irina Popa 已提交
13
//! Code that is useful in various codegen modules.
14

15
use llvm::{self, TypeKind};
16
use llvm::{True, False, Bool, BasicBlock};
17
use rustc::hir::def_id::DefId;
18
use rustc::middle::lang_items::LangItem;
19
use abi;
20 21 22 23 24
use base;
use builder::Builder;
use consts;
use declare;
use type_::Type;
25
use type_of::LayoutLlvmExt;
26
use value::Value;
27
use interfaces::{Backend, CommonMethods, CommonWriteMethods};
28

29
use rustc::ty::{self, Ty, TyCtxt};
30
use rustc::ty::layout::{HasDataLayout, LayoutOf};
31
use rustc::hir;
D
Denis Merigoux 已提交
32
use interfaces::BuilderMethods;
33

34
use libc::{c_uint, c_char};
35

36
use syntax::symbol::LocalInternedString;
37
use syntax_pos::{Span, DUMMY_SP};
38

39
pub use context::CodegenCx;
40

41
pub fn type_needs_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
42
    ty.needs_drop(tcx, ty::ParamEnv::reveal_all())
43 44 45
}

pub fn type_is_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
46
    ty.is_sized(tcx.at(DUMMY_SP), ty::ParamEnv::reveal_all())
47 48 49
}

pub fn type_is_freeze<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
50
    ty.is_freeze(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP)
51 52
}

D
Denis Merigoux 已提交
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
pub struct OperandBundleDef<'a, Value : 'a> {
    pub name: &'a str,
    pub val: Value
}

impl OperandBundleDef<'ll, &'ll Value> {
    pub fn new(name: &'ll str, val: &'ll Value) -> Self {
        OperandBundleDef {
            name,
            val
        }
    }
}

pub enum IntPredicate {
    IntEQ,
    IntNE,
    IntUGT,
    IntUGE,
    IntULT,
    IntULE,
    IntSGT,
    IntSGE,
    IntSLT,
    IntSLE
}

#[allow(dead_code)]
pub enum RealPredicate {
    RealPredicateFalse,
    RealOEQ,
    RealOGT,
    RealOGE,
    RealOLT,
    RealOLE,
    RealONE,
    RealORD,
    RealUNO,
    RealUEQ,
    RealUGT,
    RealUGE,
    RealULT,
    RealULE,
    RealUNE,
    RealPredicateTrue
}

pub enum AtomicRmwBinOp {
    AtomicXchg,
    AtomicAdd,
    AtomicSub,
    AtomicAnd,
    AtomicNand,
    AtomicOr,
    AtomicXor,
    AtomicMax,
    AtomicMin,
    AtomicUMax,
    AtomicUMin
}

pub enum AtomicOrdering {
    #[allow(dead_code)]
    NotAtomic,
    Unordered,
    Monotonic,
    // Consume,  // Not specified yet.
    Acquire,
    Release,
    AcquireRelease,
    SequentiallyConsistent,
}

pub enum SynchronizationScope {
    // FIXME: figure out if this variant is needed at all.
    #[allow(dead_code)]
    Other,
    SingleThread,
    CrossThread,
}

134
/*
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
* A note on nomenclature of linking: "extern", "foreign", and "upcall".
*
* An "extern" is an LLVM symbol we wind up emitting an undefined external
* reference to. This means "we don't have the thing in this compilation unit,
* please make sure you link it in at runtime". This could be a reference to
* C code found in a C library, or rust code found in a rust crate.
*
* Most "externs" are implicitly declared (automatically) as a result of a
* user declaring an extern _module_ dependency; this causes the rust driver
* to locate an extern crate, scan its compilation metadata, and emit extern
* declarations for any symbols used by the declaring crate.
*
* A "foreign" is an extern that references C (or other non-rust ABI) code.
* There is no metadata to scan for extern references so in these cases either
* a header-digester like bindgen, or manual function prototypes, have to
* serve as declarators. So these are usually given explicitly as prototype
* declarations, in rust code, with ABI attributes on them noting which ABI to
* link via.
*
* An "upcall" is a foreign call generated by the compiler (not corresponding
* to any user-written call in the code) into the runtime library, to perform
* some helper task such as bringing a task to life, allocating memory, etc.
*
*/
159

160 161 162 163 164 165 166 167 168 169 170 171 172 173
/// A structure representing an active landing pad for the duration of a basic
/// block.
///
/// Each `Block` may contain an instance of this, indicating whether the block
/// is part of a landing pad or not. This is used to make decision about whether
/// to emit `invoke` instructions (e.g. in a landing pad we don't continue to
/// use `invoke`) and also about various function call metadata.
///
/// For GNU exceptions (`landingpad` + `resume` instructions) this structure is
/// just a bunch of `None` instances (not too interesting), but for MSVC
/// exceptions (`cleanuppad` + `cleanupret` instructions) this contains data.
/// When inside of a landing pad, each function call in LLVM IR needs to be
/// annotated with which landing pad it's a part of. This is accomplished via
/// the `OperandBundleDef` value created for MSVC landing pads.
174 175
pub struct Funclet<'ll> {
    cleanuppad: &'ll Value,
176
    operand: OperandBundleDef<'ll, &'ll Value>,
177 178
}

179 180
impl Funclet<'ll> {
    pub fn new(cleanuppad: &'ll Value) -> Self {
181
        Funclet {
182
            cleanuppad,
183
            operand: OperandBundleDef::new("funclet", cleanuppad),
184
        }
185 186
    }

187
    pub fn cleanuppad(&self) -> &'ll Value {
M
Mark-Simulacrum 已提交
188
        self.cleanuppad
189
    }
190

191
    pub fn bundle(&self) -> &OperandBundleDef<'ll, &'ll Value> {
M
Mark-Simulacrum 已提交
192
        &self.operand
193
    }
194 195
}

196
impl Backend for CodegenCx<'ll, 'tcx> {
197 198 199 200
    type Value = &'ll Value;
    type BasicBlock = &'ll BasicBlock;
    type Type = &'ll Type;
    type Context = &'ll llvm::Context;
201
}
202

203
impl<'ll, 'tcx : 'll> CommonMethods for CodegenCx<'ll, 'tcx> {
204

205
    // LLVM constant constructors.
206
    fn c_null(&self, t: &'ll Type) -> &'ll Value {
207 208 209
        unsafe {
            llvm::LLVMConstNull(t)
        }
210
    }
211

212
    fn c_undef(&self, t: &'ll Type) -> &'ll Value {
213 214 215
        unsafe {
            llvm::LLVMGetUndef(t)
        }
216 217
    }

218
    fn c_int(&self, t: &'ll Type, i: i64) -> &'ll Value {
219 220 221
        unsafe {
            llvm::LLVMConstInt(t, i as u64, True)
        }
222
    }
223

224
    fn c_uint(&self, t: &'ll Type, i: u64) -> &'ll Value {
225 226 227
        unsafe {
            llvm::LLVMConstInt(t, i, False)
        }
228 229
    }

230
    fn c_uint_big(&self, t: &'ll Type, u: u128) -> &'ll Value {
231 232 233 234 235
        unsafe {
            let words = [u as u64, (u >> 64) as u64];
            llvm::LLVMConstIntOfArbitraryPrecision(t, 2, words.as_ptr())
        }
    }
236

237
    fn c_bool(&self, val: bool) -> &'ll Value {
238
        &self.c_uint(Type::i1(&self), val as u64)
239
    }
240

241
    fn c_i32(&self, i: i32) -> &'ll Value {
242
        &self.c_int(Type::i32(&self), i as i64)
243
    }
244

245
    fn c_u32(&self, i: u32) -> &'ll Value {
246
        &self.c_uint(Type::i32(&self), i as u64)
247
    }
248

249
    fn c_u64(&self, i: u64) -> &'ll Value {
250
        &self.c_uint(Type::i64(&self), i)
251
    }
252

253 254 255 256 257
    fn c_usize(&self, i: u64) -> &'ll Value {
        let bit_size = self.data_layout().pointer_size.bits();
        if bit_size < 64 {
            // make sure it doesn't overflow
            assert!(i < (1<<bit_size));
258
        }
259

260
        &self.c_uint(&self.isize_ty, i)
261
    }
262

263
    fn c_u8(&self, i: u8) -> &'ll Value {
264
        &self.c_uint(Type::i8(&self), i as u64)
265
    }
266

267

268 269 270 271 272 273 274 275 276 277 278
    // This is a 'c-like' raw string, which differs from
    // our boxed-and-length-annotated strings.
    fn c_cstr(
        &self,
        s: LocalInternedString,
        null_terminated: bool,
    ) -> &'ll Value {
        unsafe {
            if let Some(&llval) = &self.const_cstr_cache.borrow().get(&s) {
                return llval;
            }
279

280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
            let sc = llvm::LLVMConstStringInContext(&self.llcx,
                                                    s.as_ptr() as *const c_char,
                                                    s.len() as c_uint,
                                                    !null_terminated as Bool);
            let sym = &self.generate_local_symbol_name("str");
            let g = declare::define_global(&self, &sym[..], Self::val_ty(sc)).unwrap_or_else(||{
                bug!("symbol `{}` is already defined", sym);
            });
            llvm::LLVMSetInitializer(g, sc);
            llvm::LLVMSetGlobalConstant(g, True);
            llvm::LLVMRustSetLinkage(g, llvm::Linkage::InternalLinkage);

            &self.const_cstr_cache.borrow_mut().insert(s, g);
            g
        }
295
    }
296

297 298 299 300 301 302 303
    // NB: Do not use `do_spill_noroot` to make this into a constant string, or
    // you will be kicked off fast isel. See issue #4352 for an example of this.
    fn c_str_slice(&self, s: LocalInternedString) -> &'ll Value {
        let len = s.len();
        let cs = consts::ptrcast(&self.c_cstr(s, false),
            &self.layout_of(&self.tcx.mk_str()).llvm_type(&self).ptr_to());
        &self.c_fat_ptr(cs, &self.c_usize(len as u64))
304
    }
P
Patrick Walton 已提交
305

306 307 308 309 310 311 312 313
    fn c_fat_ptr(
        &self,
        ptr: &'ll Value,
        meta: &'ll Value
    ) -> &'ll Value {
        assert_eq!(abi::FAT_PTR_ADDR, 0);
        assert_eq!(abi::FAT_PTR_EXTRA, 1);
        &self.c_struct(&[ptr, meta], false)
314 315
    }

316 317 318 319 320 321 322
    fn c_struct(
        &self,
        elts: &[&'ll Value],
        packed: bool
    ) -> &'ll Value {
        Self::c_struct_in_context(&self.llcx, elts, packed)
    }
323

324 325 326 327 328 329 330 331 332 333
    fn c_struct_in_context(
        llcx: &'a llvm::Context,
        elts: &[&'a Value],
        packed: bool,
    ) -> &'a Value {
        unsafe {
            llvm::LLVMConstStructInContext(llcx,
                                           elts.as_ptr(), elts.len() as c_uint,
                                           packed as Bool)
        }
334
    }
335

336 337 338 339 340
    fn c_array(ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
        unsafe {
            return llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint);
        }
    }
341

342 343 344 345 346
    fn c_vector(elts: &[&'ll Value]) -> &'ll Value {
        unsafe {
            return llvm::LLVMConstVector(elts.as_ptr(), elts.len() as c_uint);
        }
    }
347

348 349
    fn c_bytes(&self, bytes: &[u8]) -> &'ll Value {
        Self::c_bytes_in_context(&self.llcx, bytes)
350
    }
351

352 353 354 355 356 357 358 359 360 361 362
    fn const_get_elt(v: &'ll Value, idx: u64) -> &'ll Value {
        unsafe {
            assert_eq!(idx as c_uint as u64, idx);
            let us = &[idx as c_uint];
            let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint);

            debug!("const_get_elt(v={:?}, idx={}, r={:?})",
                   v, idx, r);

            r
        }
363
    }
364

365 366 367 368 369 370 371 372 373 374 375
    fn const_get_real(v: &'ll Value) -> Option<(f64, bool)> {
        unsafe {
            if Self::is_const_real(v) {
                let mut loses_info: llvm::Bool = ::std::mem::uninitialized();
                let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info);
                let loses_info = if loses_info == 1 { true } else { false };
                Some((r, loses_info))
            } else {
                None
            }
        }
376 377
    }

378 379 380 381
    fn const_to_uint(v: &'ll Value) -> u64 {
        unsafe {
            llvm::LLVMConstIntGetZExtValue(v)
        }
G
gnzlbg 已提交
382 383
    }

384 385 386 387 388
    fn is_const_integral(v: &'ll Value) -> bool {
        unsafe {
            llvm::LLVMIsAConstantInt(v).is_some()
        }
    }
G
gnzlbg 已提交
389

390 391 392 393 394
    fn is_const_real(v: &'ll Value) -> bool {
        unsafe {
            llvm::LLVMIsAConstantFP(v).is_some()
        }
    }
E
est31 已提交
395

396 397 398 399 400 401 402 403 404 405 406
    fn const_to_opt_u128(v: &'ll Value, sign_ext: bool) -> Option<u128> {
        unsafe {
            if Self::is_const_integral(v) {
                let (mut lo, mut hi) = (0u64, 0u64);
                let success = llvm::LLVMRustConstInt128Get(v, sign_ext,
                                                           &mut hi, &mut lo);
                if success {
                    Some(hi_lo_to_u128(lo, hi))
                } else {
                    None
                }
407 408 409
            } else {
                None
            }
410 411 412 413
        }
    }
}

414 415 416 417 418
#[inline]
fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
    ((hi as u128) << 64) | (lo as u128)
}

419
pub fn langcall(tcx: TyCtxt,
420 421 422
                span: Option<Span>,
                msg: &str,
                li: LangItem)
N
Niko Matsakis 已提交
423
                -> DefId {
L
ljedrz 已提交
424 425 426 427 428
    tcx.lang_items().require(li).unwrap_or_else(|s| {
        let msg = format!("{} {}", msg, s);
        match span {
            Some(span) => tcx.sess.span_fatal(span, &msg[..]),
            None => tcx.sess.fatal(&msg[..]),
A
Alex Crichton 已提交
429
        }
L
ljedrz 已提交
430
    })
A
Alex Crichton 已提交
431
}
432

433 434 435 436 437
// To avoid UB from LLVM, these two functions mask RHS with an
// appropriate mask unconditionally (i.e. the fallback behavior for
// all shifts). For 32- and 64-bit types, this matches the semantics
// of Java. (See related discussion on #1877 and #10183.)

438 439
pub fn build_unchecked_lshift(
    bx: &Builder<'a, 'll, 'tcx>,
440 441 442
    lhs: &'ll Value,
    rhs: &'ll Value
) -> &'ll Value {
C
csmoe 已提交
443
    let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shl, lhs, rhs);
444
    // #1877, #10183: Ensure that input is always valid
445 446
    let rhs = shift_mask_rhs(bx, rhs);
    bx.shl(lhs, rhs)
447 448
}

449
pub fn build_unchecked_rshift(
450 451
    bx: &Builder<'a, 'll, 'tcx>, lhs_t: Ty<'tcx>, lhs: &'ll Value, rhs: &'ll Value
) -> &'ll Value {
C
csmoe 已提交
452
    let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shr, lhs, rhs);
453
    // #1877, #10183: Ensure that input is always valid
454
    let rhs = shift_mask_rhs(bx, rhs);
455 456
    let is_signed = lhs_t.is_signed();
    if is_signed {
457
        bx.ashr(lhs, rhs)
458
    } else {
459
        bx.lshr(lhs, rhs)
460 461 462
    }
}

463
fn shift_mask_rhs(bx: &Builder<'a, 'll, 'tcx>, rhs: &'ll Value) -> &'ll Value {
464
    let rhs_llty = CodegenCx::val_ty(rhs);
465
    bx.and(rhs, shift_mask_val(bx, rhs_llty, rhs_llty, false))
466 467
}

468 469 470 471
pub fn shift_mask_val(
    bx: &Builder<'a, 'll, 'tcx>,
    llty: &'ll Type,
    mask_llty: &'ll Type,
472
    invert: bool
473
) -> &'ll Value {
474 475 476 477 478 479
    let kind = llty.kind();
    match kind {
        TypeKind::Integer => {
            // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
            let val = llty.int_width() - 1;
            if invert {
480
                bx.cx.c_int(mask_llty, !val as i64)
481
            } else {
482
                bx.cx.c_uint(mask_llty, val)
483 484 485
            }
        },
        TypeKind::Vector => {
486 487
            let mask = shift_mask_val(bx, llty.element_type(), mask_llty.element_type(), invert);
            bx.vector_splat(mask_llty.vector_length(), mask)
488
        },
489
        _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
490 491
    }
}
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506

impl<'ll, 'tcx : 'll> CommonWriteMethods for CodegenCx<'ll, 'tcx> {
    fn val_ty(v: &'ll Value) -> &'ll Type {
        unsafe {
            llvm::LLVMTypeOf(v)
        }
    }

    fn c_bytes_in_context(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
        unsafe {
            let ptr = bytes.as_ptr() as *const c_char;
            return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True);
        }
    }
}