base.rs 48.9 KB
Newer Older
1
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 3 4 5 6 7 8 9
// 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.
10

I
Irina Popa 已提交
11
//! Codegen the completed AST to the LLVM IR.
12
//!
I
Irina Popa 已提交
13 14 15
//! Some functions here, such as codegen_block and codegen_expr, return a value --
//! the result of the codegen to LLVM -- while others, such as codegen_fn
//! and mono_item, are called only for the side effect of adding a
16 17
//! particular definition to the LLVM IR output we're producing.
//!
I
Irina Popa 已提交
18
//! Hopefully useful general knowledge about codegen:
19
//!
20
//!   * There's no way to find out the Ty type of a Value.  Doing so
21
//!     would be "trying to get the eggs out of an omelette" (credit:
22 23 24
//!     pcwalton).  You can, instead, find out its llvm::Type by calling val_ty,
//!     but one llvm::Type corresponds to many `Ty`s; for instance, tup(int, int,
//!     int) and rec(x=int, y=int, z=int) will have the same llvm::Type.
25

26 27
use super::ModuleLlvm;
use super::ModuleSource;
I
Irina Popa 已提交
28
use super::ModuleCodegen;
29
use super::ModuleKind;
30

31
use abi;
32
use back::link;
33
use back::write::{self, OngoingCodegen};
34
use llvm::{self, TypeKind, get_param};
35
use metadata;
36
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
37
use rustc::middle::lang_items::StartFnLangItem;
38
use rustc::middle::weak_lang_items;
39 40
use rustc::mir::mono::{Linkage, Visibility, Stats};
use rustc::middle::cstore::{EncodedMetadata};
41
use rustc::ty::{self, Ty, TyCtxt};
42
use rustc::ty::layout::{self, Align, TyLayout, LayoutOf};
43
use rustc::ty::query::Providers;
44
use rustc::dep_graph::{DepNode, DepConstructor};
45
use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
46
use rustc::middle::exported_symbols;
47
use rustc::util::common::{time, print_time_passes_entry};
W
Wesley Wiser 已提交
48
use rustc::util::profiling::ProfileCategory;
49
use rustc::session::config::{self, DebugInfo, EntryFnType};
50
use rustc::session::Session;
51
use rustc_incremental;
52
use allocator;
53
use mir::place::PlaceRef;
54
use attributes;
55
use builder::{Builder, MemFlags};
56
use callee;
57
use common::{C_bool, C_bytes_in_context, C_i32, C_usize};
58
use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode};
59
use rustc_mir::monomorphize::item::DefPathBasedNames;
60
use common::{self, C_struct_in_context, C_array, val_ty};
61
use consts;
62
use context::CodegenCx;
M
Mark-Simulacrum 已提交
63
use debuginfo;
64 65 66
use declare;
use meth;
use mir;
67
use monomorphize::Instance;
M
Maik Klein 已提交
68
use monomorphize::partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt};
I
Irina Popa 已提交
69
use rustc_codegen_utils::symbol_names_test;
70
use time_graph;
71
use mono_item::{MonoItem, BaseMonoItemExt, MonoItemExt};
72
use type_::Type;
73
use type_of::LayoutLlvmExt;
74
use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet};
75
use CrateInfo;
76
use rustc_data_structures::sync::Lrc;
J
James Miller 已提交
77

78
use std::any::Any;
79
use std::ffi::CString;
80
use std::sync::Arc;
81
use std::time::{Instant, Duration};
V
varkor 已提交
82 83
use std::i32;
use std::cmp;
84
use std::sync::mpsc;
85
use syntax_pos::Span;
A
Alex Crichton 已提交
86
use syntax_pos::symbol::InternedString;
87
use syntax::attr;
88
use rustc::hir::{self, CodegenFnAttrs};
T
Tim Chevalier 已提交
89

90 91
use value::Value;

92
use mir::operand::OperandValue;
93

B
bjorn3 已提交
94 95
use rustc_codegen_utils::check_for_rustc_errors_attr;

96 97
pub struct StatRecorder<'a, 'll: 'a, 'tcx: 'll> {
    cx: &'a CodegenCx<'ll, 'tcx>,
98
    name: Option<String>,
99
    istart: usize,
100 101
}

102 103
impl StatRecorder<'a, 'll, 'tcx> {
    pub fn new(cx: &'a CodegenCx<'ll, 'tcx>, name: String) -> Self {
104
        let istart = cx.stats.borrow().n_llvm_insns;
105
        StatRecorder {
106
            cx,
107
            name: Some(name),
108
            istart,
109 110 111 112
        }
    }
}

113
impl Drop for StatRecorder<'a, 'll, 'tcx> {
D
Daniel Micay 已提交
114
    fn drop(&mut self) {
I
Irina Popa 已提交
115
        if self.cx.sess().codegen_stats() {
116
            let mut stats = self.cx.stats.borrow_mut();
A
Alex Crichton 已提交
117 118 119
            let iend = stats.n_llvm_insns;
            stats.fn_stats.push((self.name.take().unwrap(), iend - self.istart));
            stats.n_fns += 1;
120
            // Reset LLVM insn count to avoid compound costs.
A
Alex Crichton 已提交
121
            stats.n_llvm_insns = self.istart;
122 123 124 125
        }
    }
}

C
csmoe 已提交
126
pub fn bin_op_to_icmp_predicate(op: hir::BinOpKind,
M
Ms2ger 已提交
127
                                signed: bool)
128 129
                                -> llvm::IntPredicate {
    match op {
C
csmoe 已提交
130 131 132 133 134 135
        hir::BinOpKind::Eq => llvm::IntEQ,
        hir::BinOpKind::Ne => llvm::IntNE,
        hir::BinOpKind::Lt => if signed { llvm::IntSLT } else { llvm::IntULT },
        hir::BinOpKind::Le => if signed { llvm::IntSLE } else { llvm::IntULE },
        hir::BinOpKind::Gt => if signed { llvm::IntSGT } else { llvm::IntUGT },
        hir::BinOpKind::Ge => if signed { llvm::IntSGE } else { llvm::IntUGE },
136
        op => {
137 138 139
            bug!("comparison_op_to_icmp_predicate: expected comparison operator, \
                  found {:?}",
                 op)
140 141 142
        }
    }
}
143

C
csmoe 已提交
144
pub fn bin_op_to_fcmp_predicate(op: hir::BinOpKind) -> llvm::RealPredicate {
145
    match op {
C
csmoe 已提交
146 147 148 149 150 151
        hir::BinOpKind::Eq => llvm::RealOEQ,
        hir::BinOpKind::Ne => llvm::RealUNE,
        hir::BinOpKind::Lt => llvm::RealOLT,
        hir::BinOpKind::Le => llvm::RealOLE,
        hir::BinOpKind::Gt => llvm::RealOGT,
        hir::BinOpKind::Ge => llvm::RealOGE,
152
        op => {
153 154 155
            bug!("comparison_op_to_fcmp_predicate: expected comparison operator, \
                  found {:?}",
                 op);
156 157 158 159
        }
    }
}

160 161
pub fn compare_simd_types(
    bx: &Builder<'a, 'll, 'tcx>,
162 163
    lhs: &'ll Value,
    rhs: &'ll Value,
M
Mark Simulacrum 已提交
164
    t: Ty<'tcx>,
165
    ret_ty: &'ll Type,
C
csmoe 已提交
166
    op: hir::BinOpKind
167
) -> &'ll Value {
168
    let signed = match t.sty {
169
        ty::TyFloat(_) => {
170
            let cmp = bin_op_to_fcmp_predicate(op);
171
            return bx.sext(bx.fcmp(cmp, lhs, rhs), ret_ty);
172
        },
173 174
        ty::TyUint(_) => false,
        ty::TyInt(_) => true,
175
        _ => bug!("compare_simd_types: invalid SIMD type"),
176
    };
177

178
    let cmp = bin_op_to_icmp_predicate(op, signed);
179 180 181 182
    // LLVM outputs an `< size x i1 >`, so we need to perform a sign extension
    // to get the correctly sized type. This will compile to a single instruction
    // once the IR is converted to assembly if the SIMD instruction is supported
    // by the target architecture.
183
    bx.sext(bx.icmp(cmp, lhs, rhs), ret_ty)
184 185
}

A
Ariel Ben-Yehuda 已提交
186 187 188 189
/// Retrieve the information we are losing (making dynamic) in an unsizing
/// adjustment.
///
/// The `old_info` argument is a bit funny. It is intended for use
B
Bastien Orivel 已提交
190
/// in an upcast, where the new vtable for an object will be derived
A
Ariel Ben-Yehuda 已提交
191
/// from the old one.
192 193 194 195 196 197
pub fn unsized_info(
    cx: &CodegenCx<'ll, 'tcx>,
    source: Ty<'tcx>,
    target: Ty<'tcx>,
    old_info: Option<&'ll Value>,
) -> &'ll Value {
198
    let (source, target) = cx.tcx.struct_lockstep_tails(source, target);
A
Ariel Ben-Yehuda 已提交
199
    match (&source.sty, &target.sty) {
200
        (&ty::TyArray(_, len), &ty::TySlice(_)) => {
201
            C_usize(cx, len.unwrap_usize(cx.tcx))
202
        }
203
        (&ty::TyDynamic(..), &ty::TyDynamic(..)) => {
A
Ariel Ben-Yehuda 已提交
204 205 206 207 208
            // For now, upcasts are limited to changes in marker
            // traits, and hence never actually require an actual
            // change to the vtable.
            old_info.expect("unsized_info: missing old info for trait upcast")
        }
209
        (_, &ty::TyDynamic(ref data, ..)) => {
210 211 212 213
            let vtable_ptr = cx.layout_of(cx.tcx.mk_mut_ptr(target))
                .field(cx, abi::FAT_PTR_EXTRA);
            consts::ptrcast(meth::get_vtable(cx, source, data.principal()),
                            vtable_ptr.llvm_type(cx))
A
Ariel Ben-Yehuda 已提交
214
        }
215
        _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}",
A
Ariel Ben-Yehuda 已提交
216
                                     source,
217
                                     target),
A
Ariel Ben-Yehuda 已提交
218 219 220 221
    }
}

/// Coerce `src` to `dst_ty`. `src_ty` must be a thin pointer.
222 223
pub fn unsize_thin_ptr(
    bx: &Builder<'a, 'll, 'tcx>,
224
    src: &'ll Value,
M
Mark Simulacrum 已提交
225 226
    src_ty: Ty<'tcx>,
    dst_ty: Ty<'tcx>
227
) -> (&'ll Value, &'ll Value) {
A
Ariel Ben-Yehuda 已提交
228 229
    debug!("unsize_thin_ptr: {:?} => {:?}", src_ty, dst_ty);
    match (&src_ty.sty, &dst_ty.sty) {
230 231 232
        (&ty::TyRef(_, a, _),
         &ty::TyRef(_, b, _)) |
        (&ty::TyRef(_, a, _),
A
Ariel Ben-Yehuda 已提交
233 234 235
         &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) |
        (&ty::TyRawPtr(ty::TypeAndMut { ty: a, .. }),
         &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) => {
236 237 238
            assert!(bx.cx.type_is_sized(a));
            let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx).ptr_to();
            (bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None))
A
Ariel Ben-Yehuda 已提交
239
        }
240 241
        (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
            let (a, b) = (src_ty.boxed_ty(), dst_ty.boxed_ty());
242 243 244
            assert!(bx.cx.type_is_sized(a));
            let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx).ptr_to();
            (bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None))
245
        }
246 247 248
        (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => {
            assert_eq!(def_a, def_b);

249 250
            let src_layout = bx.cx.layout_of(src_ty);
            let dst_layout = bx.cx.layout_of(dst_ty);
251 252
            let mut result = None;
            for i in 0..src_layout.fields.count() {
253
                let src_f = src_layout.field(bx.cx, i);
254 255 256 257 258 259 260
                assert_eq!(src_layout.fields.offset(i).bytes(), 0);
                assert_eq!(dst_layout.fields.offset(i).bytes(), 0);
                if src_f.is_zst() {
                    continue;
                }
                assert_eq!(src_layout.size, src_f.size);

261
                let dst_f = dst_layout.field(bx.cx, i);
262 263
                assert_ne!(src_f.ty, dst_f.ty);
                assert_eq!(result, None);
264
                result = Some(unsize_thin_ptr(bx, src, src_f.ty, dst_f.ty));
265 266 267
            }
            let (lldata, llextra) = result.unwrap();
            // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
268 269
            (bx.bitcast(lldata, dst_layout.scalar_pair_element_llvm_type(bx.cx, 0, true)),
             bx.bitcast(llextra, dst_layout.scalar_pair_element_llvm_type(bx.cx, 1, true)))
270
        }
271
        _ => bug!("unsize_thin_ptr: called on bad types"),
A
Ariel Ben-Yehuda 已提交
272 273 274 275 276
    }
}

/// Coerce `src`, which is a reference to a value of type `src_ty`,
/// to a value of type `dst_ty` and store the result in `dst`
277 278
pub fn coerce_unsized_into(
    bx: &Builder<'a, 'll, 'tcx>,
279 280
    src: PlaceRef<'ll, 'tcx>,
    dst: PlaceRef<'ll, 'tcx>
281
) {
282 283
    let src_ty = src.layout.ty;
    let dst_ty = dst.layout.ty;
284
    let coerce_ptr = || {
285
        let (base, info) = match src.load(bx).val {
286 287 288 289 290
            OperandValue::Pair(base, info) => {
                // fat-ptr to fat-ptr unsize preserves the vtable
                // i.e. &'a fmt::Debug+Send => &'a fmt::Debug
                // So we need to pointercast the base to ensure
                // the types match up.
291 292
                let thin_ptr = dst.layout.field(bx.cx, abi::FAT_PTR_ADDR);
                (bx.pointercast(base, thin_ptr.llvm_type(bx.cx)), info)
293 294
            }
            OperandValue::Immediate(base) => {
295
                unsize_thin_ptr(bx, base, src_ty, dst_ty)
296 297
            }
            OperandValue::Ref(..) => bug!()
298
        };
299
        OperandValue::Pair(base, info).store(bx, dst);
300
    };
A
Ariel Ben-Yehuda 已提交
301 302 303 304
    match (&src_ty.sty, &dst_ty.sty) {
        (&ty::TyRef(..), &ty::TyRef(..)) |
        (&ty::TyRef(..), &ty::TyRawPtr(..)) |
        (&ty::TyRawPtr(..), &ty::TyRawPtr(..)) => {
305 306 307 308
            coerce_ptr()
        }
        (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
            coerce_ptr()
A
Ariel Ben-Yehuda 已提交
309 310
        }

311
        (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => {
A
Ariel Ben-Yehuda 已提交
312 313
            assert_eq!(def_a, def_b);

314
            for i in 0..def_a.variants[0].fields.len() {
315 316
                let src_f = src.project_field(bx, i);
                let dst_f = dst.project_field(bx, i);
A
Ariel Ben-Yehuda 已提交
317

318
                if dst_f.layout.is_zst() {
M
Ms2ger 已提交
319 320
                    continue;
                }
A
Ariel Ben-Yehuda 已提交
321

322
                if src_f.layout.ty == dst_f.layout.ty {
323
                    memcpy_ty(bx, dst_f.llval, src_f.llval, src_f.layout,
324
                              src_f.align.min(dst_f.align), MemFlags::empty());
A
Ariel Ben-Yehuda 已提交
325
                } else {
326
                    coerce_unsized_into(bx, src_f, dst_f);
A
Ariel Ben-Yehuda 已提交
327 328 329
                }
            }
        }
330 331 332
        _ => bug!("coerce_unsized_into: invalid coercion {:?} -> {:?}",
                  src_ty,
                  dst_ty),
A
Ariel Ben-Yehuda 已提交
333 334 335
    }
}

336
pub fn cast_shift_expr_rhs(
337 338
    cx: &Builder<'_, 'll, '_>, op: hir::BinOpKind, lhs: &'ll Value, rhs: &'ll Value
) -> &'ll Value {
339
    cast_shift_rhs(op, lhs, rhs, |a, b| cx.trunc(a, b), |a, b| cx.zext(a, b))
340 341
}

342
fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind,
343 344
                        lhs: &'ll Value,
                        rhs: &'ll Value,
345 346
                        trunc: F,
                        zext: G)
347 348 349
                        -> &'ll Value
    where F: FnOnce(&'ll Value, &'ll Type) -> &'ll Value,
          G: FnOnce(&'ll Value, &'ll Type) -> &'ll Value
350
{
351
    // Shifts may have any size int on the rhs
352
    if op.is_shift() {
353 354
        let mut rhs_llty = val_ty(rhs);
        let mut lhs_llty = val_ty(lhs);
355
        if rhs_llty.kind() == TypeKind::Vector {
M
Ms2ger 已提交
356 357
            rhs_llty = rhs_llty.element_type()
        }
358
        if lhs_llty.kind() == TypeKind::Vector {
M
Ms2ger 已提交
359 360
            lhs_llty = lhs_llty.element_type()
        }
361 362 363 364 365 366 367 368
        let rhs_sz = rhs_llty.int_width();
        let lhs_sz = lhs_llty.int_width();
        if lhs_sz < rhs_sz {
            trunc(rhs, lhs_llty)
        } else if lhs_sz > rhs_sz {
            // FIXME (#1877: If shifting by negative
            // values becomes not undefined then this is wrong.
            zext(rhs, lhs_llty)
369 370 371
        } else {
            rhs
        }
372 373
    } else {
        rhs
374 375 376
    }
}

377 378 379 380 381 382
/// Returns whether this session's target will use SEH-based unwinding.
///
/// This is only true for MSVC targets, and even then the 64-bit MSVC target
/// currently uses SEH-ish unwinding with DWARF info tables to the side (same as
/// 64-bit MinGW) instead of "full SEH".
pub fn wants_msvc_seh(sess: &Session) -> bool {
383
    sess.target.target.options.is_like_msvc
384 385
}

386
pub fn call_assume(bx: &Builder<'_, 'll, '_>, val: &'ll Value) {
387 388
    let assume_intrinsic = bx.cx.get_intrinsic("llvm.assume");
    bx.call(assume_intrinsic, &[val], None);
389 390
}

391
pub fn from_immediate(bx: &Builder<'_, 'll, '_>, val: &'ll Value) -> &'ll Value {
392 393
    if val_ty(val) == Type::i1(bx.cx) {
        bx.zext(val, Type::i8(bx.cx))
394 395 396 397 398
    } else {
        val
    }
}

399 400 401 402 403
pub fn to_immediate(
    bx: &Builder<'_, 'll, '_>,
    val: &'ll Value,
    layout: layout::TyLayout,
) -> &'ll Value {
404
    if let layout::Abi::Scalar(ref scalar) = layout.abi {
405 406 407 408 409
        return to_immediate_scalar(bx, val, scalar);
    }
    val
}

410 411 412 413 414
pub fn to_immediate_scalar(
    bx: &Builder<'_, 'll, '_>,
    val: &'ll Value,
    scalar: &layout::Scalar,
) -> &'ll Value {
415 416
    if scalar.is_bool() {
        return bx.trunc(val, Type::i1(bx.cx));
417
    }
418
    val
419 420
}

421 422 423 424 425 426 427 428
pub fn call_memcpy(
    bx: &Builder<'_, 'll, '_>,
    dst: &'ll Value,
    src: &'ll Value,
    n_bytes: &'ll Value,
    align: Align,
    flags: MemFlags,
) {
429 430 431 432 433 434 435
    if flags.contains(MemFlags::NONTEMPORAL) {
        // HACK(nox): This is inefficient but there is no nontemporal memcpy.
        let val = bx.load(src, align);
        let ptr = bx.pointercast(dst, val_ty(val).ptr_to());
        bx.store_with_flags(val, ptr, align, flags);
        return;
    }
436
    let cx = bx.cx;
437
    let ptr_width = &cx.sess().target.target.target_pointer_width;
438
    let key = format!("llvm.memcpy.p0i8.p0i8.i{}", ptr_width);
439
    let memcpy = cx.get_intrinsic(&key);
440 441 442
    let src_ptr = bx.pointercast(src, Type::i8p(cx));
    let dst_ptr = bx.pointercast(dst, Type::i8p(cx));
    let size = bx.intcast(n_bytes, cx.isize_ty, false);
443
    let align = C_i32(cx, align.abi() as i32);
444
    let volatile = C_bool(cx, flags.contains(MemFlags::VOLATILE));
445
    bx.call(memcpy, &[dst_ptr, src_ptr, size, align, volatile], None);
446 447
}

448
pub fn memcpy_ty(
449 450 451
    bx: &Builder<'_, 'll, 'tcx>,
    dst: &'ll Value,
    src: &'ll Value,
452
    layout: TyLayout<'tcx>,
453
    align: Align,
454
    flags: MemFlags,
455
) {
456
    let size = layout.size.bytes();
457
    if size == 0 {
458 459 460
        return;
    }

461
    call_memcpy(bx, dst, src, C_usize(bx.cx, size), align, flags);
462 463
}

464
pub fn call_memset(
465 466 467 468 469
    bx: &Builder<'_, 'll, '_>,
    ptr: &'ll Value,
    fill_byte: &'ll Value,
    size: &'ll Value,
    align: &'ll Value,
470
    volatile: bool,
471
) -> &'ll Value {
472
    let ptr_width = &bx.cx.sess().target.target.target_pointer_width;
473
    let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
474 475 476
    let llintrinsicfn = bx.cx.get_intrinsic(&intrinsic_key);
    let volatile = C_bool(bx.cx, volatile);
    bx.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None)
477 478
}

I
Irina Popa 已提交
479 480
pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tcx>) {
    let _s = if cx.sess().codegen_stats() {
481
        let mut instance_name = String::new();
482
        DefPathBasedNames::new(cx.tcx, true, true)
483
            .push_def_path(instance.def_id(), &mut instance_name);
484
        Some(StatRecorder::new(cx, instance_name))
485 486 487 488
    } else {
        None
    };

489 490 491
    // this is an info! to allow collecting monomorphization statistics
    // and to allow finding the last function before LLVM aborts from
    // release builds.
I
Irina Popa 已提交
492
    info!("codegen_instance({})", instance);
493

494 495
    let fn_ty = instance.ty(cx.tcx);
    let sig = common::ty_fn_sig(cx, fn_ty);
496
    let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
497

498
    let lldecl = match cx.instances.borrow().get(&instance) {
499 500 501 502
        Some(&val) => val,
        None => bug!("Instance `{:?}` not already declared", instance)
    };

503
    cx.stats.borrow_mut().n_closures += 1;
504

505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
    // The `uwtable` attribute according to LLVM is:
    //
    //     This attribute indicates that the ABI being targeted requires that an
    //     unwind table entry be produced for this function even if we can show
    //     that no exceptions passes by it. This is normally the case for the
    //     ELF x86-64 abi, but it can be disabled for some compilation units.
    //
    // Typically when we're compiling with `-C panic=abort` (which implies this
    // `no_landing_pads` check) we don't need `uwtable` because we can't
    // generate any exceptions! On Windows, however, exceptions include other
    // events such as illegal instructions, segfaults, etc. This means that on
    // Windows we end up still needing the `uwtable` attribute even if the `-C
    // panic=abort` flag is passed.
    //
    // You can also find more info on why Windows is whitelisted here in:
    //      https://bugzilla.mozilla.org/show_bug.cgi?id=1302078
521
    if !cx.sess().no_landing_pads() ||
522
       cx.sess().target.target.options.requires_uwtable {
523
        attributes::emit_uwtable(lldecl, true);
524
    }
525

526
    let mir = cx.tcx.instance_mir(instance.def);
I
Irina Popa 已提交
527
    mir::codegen_mir(cx, lldecl, &mir, instance, sig);
528 529
}

530
pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) {
531 532 533 534 535 536 537
    let sect = match attrs.link_section {
        Some(name) => name,
        None => return,
    };
    unsafe {
        let buf = CString::new(sect.as_str().as_bytes()).unwrap();
        llvm::LLVMSetSection(llval, buf.as_ptr());
E
Eli Friedman 已提交
538 539 540
    }
}

F
Fourchaux 已提交
541
/// Create the `main` function which will initialize the rust runtime and call
542
/// users main function.
543 544
fn maybe_create_entry_wrapper(cx: &CodegenCx) {
    let (main_def_id, span) = match *cx.sess().entry_fn.borrow() {
545
        Some((id, span, _)) => {
546
            (cx.tcx.hir.local_def_id(id), span)
547 548 549 550
        }
        None => return,
    };

551
    let instance = Instance::mono(cx.tcx, main_def_id);
552

553
    if !cx.codegen_unit.contains_item(&MonoItem::Fn(instance)) {
554 555 556
        // We want to create the wrapper in the same codegen unit as Rust's main
        // function.
        return;
557 558
    }

559
    let main_llfn = callee::get_fn(cx, instance);
560

561
    let et = cx.sess().entry_fn.get().map(|e| e.2);
562
    match et {
563 564
        Some(EntryFnType::Main) => create_entry_fn(cx, span, main_llfn, main_def_id, true),
        Some(EntryFnType::Start) => create_entry_fn(cx, span, main_llfn, main_def_id, false),
565
        None => {}    // Do nothing.
566
    }
567

568 569 570 571 572 573 574
    fn create_entry_fn(
        cx: &CodegenCx<'ll, '_>,
        sp: Span,
        rust_main: &'ll Value,
        rust_main_def_id: DefId,
        use_start_lang_item: bool,
    ) {
575
        let llfty = Type::func(&[Type::c_int(cx), Type::i8p(cx).ptr_to()], Type::c_int(cx));
576

577
        let main_ret_ty = cx.tcx.fn_sig(rust_main_def_id).output();
578 579 580 581 582
        // Given that `main()` has no arguments,
        // then its return type cannot have
        // late-bound regions, since late-bound
        // regions must appear in the argument
        // listing.
583 584 585
        let main_ret_ty = cx.tcx.erase_regions(
            &main_ret_ty.no_late_bound_regions().unwrap(),
        );
K
kyeongwoon 已提交
586

587
        if declare::get_defined_value(cx, "main").is_some() {
S
Simonas Kazlauskas 已提交
588
            // FIXME: We should be smart and show a better diagnostic here.
589
            cx.sess().struct_span_err(sp, "entry symbol `main` defined multiple times")
N
Nick Cameron 已提交
590 591
                      .help("did you use #[no_mangle] on `fn main`? Use #[start] instead")
                      .emit();
592
            cx.sess().abort_if_errors();
593
            bug!();
594
        }
595
        let llfn = declare::declare_cfn(cx, "main", llfty);
596

597
        // `main` should respect same config for frame pointer elimination as rest of code
598
        attributes::set_frame_pointer_elimination(cx, llfn);
599

600
        let bx = Builder::new_block(cx, llfn, "top");
601

602
        debuginfo::gdb::insert_reference_to_gdb_debug_scripts_section_global(&bx);
603

604 605 606
        // Params from native main() used as args for rust start function
        let param_argc = get_param(llfn, 0);
        let param_argv = get_param(llfn, 1);
607
        let arg_argc = bx.intcast(param_argc, cx.isize_ty, true);
608 609
        let arg_argv = param_argv;

M
Mark-Simulacrum 已提交
610
        let (start_fn, args) = if use_start_lang_item {
611
            let start_def_id = cx.tcx.require_lang_item(StartFnLangItem);
612 613 614
            let start_fn = callee::resolve_and_get_fn(
                cx,
                start_def_id,
615
                cx.tcx.intern_substs(&[main_ret_ty.into()]),
616
            );
617
            (start_fn, vec![bx.pointercast(rust_main, Type::i8p(cx).ptr_to()),
618
                            arg_argc, arg_argv])
M
Mark-Simulacrum 已提交
619 620
        } else {
            debug!("using user-defined start fn");
621
            (rust_main, vec![arg_argc, arg_argv])
M
Mark-Simulacrum 已提交
622
        };
623

624 625
        let result = bx.call(start_fn, &args, None);
        bx.ret(bx.intcast(result, Type::c_int(cx), true));
M
Marijn Haverbeke 已提交
626
    }
627 628
}

629
fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
630
                            llvm_module: &ModuleLlvm,
631
                            link_meta: &LinkMeta)
632
                            -> EncodedMetadata {
A
Alex Crichton 已提交
633 634
    use std::io::Write;
    use flate2::Compression;
635
    use flate2::write::DeflateEncoder;
636

637
    let (metadata_llcx, metadata_llmod) = (&*llvm_module.llcx, llvm_module.llmod());
638

N
Nicholas Nethercote 已提交
639 640 641 642 643 644 645
    #[derive(PartialEq, Eq, PartialOrd, Ord)]
    enum MetadataKind {
        None,
        Uncompressed,
        Compressed
    }

646
    let kind = tcx.sess.crate_types.borrow().iter().map(|ty| {
N
Nicholas Nethercote 已提交
647
        match *ty {
648 649 650
            config::CrateType::Executable |
            config::CrateType::Staticlib |
            config::CrateType::Cdylib => MetadataKind::None,
N
Nicholas Nethercote 已提交
651

652
            config::CrateType::Rlib => MetadataKind::Uncompressed,
N
Nicholas Nethercote 已提交
653

654 655
            config::CrateType::Dylib |
            config::CrateType::ProcMacro => MetadataKind::Compressed,
N
Nicholas Nethercote 已提交
656
        }
657
    }).max().unwrap_or(MetadataKind::None);
N
Nicholas Nethercote 已提交
658 659

    if kind == MetadataKind::None {
660
        return EncodedMetadata::new();
661
    }
J
James Miller 已提交
662

663
    let metadata = tcx.encode_metadata(link_meta);
N
Nicholas Nethercote 已提交
664
    if kind == MetadataKind::Uncompressed {
665
        return metadata;
N
Nicholas Nethercote 已提交
666 667 668
    }

    assert!(kind == MetadataKind::Compressed);
669
    let mut compressed = tcx.metadata_encoding_version();
670
    DeflateEncoder::new(&mut compressed, Compression::fast())
A
Alex Crichton 已提交
671
        .write_all(&metadata.raw_data).unwrap();
672

673 674
    let llmeta = C_bytes_in_context(metadata_llcx, &compressed);
    let llconst = C_struct_in_context(metadata_llcx, &[llmeta], false);
675
    let name = exported_symbols::metadata_symbol_name(tcx);
676
    let buf = CString::new(name).unwrap();
A
Alex Crichton 已提交
677
    let llglobal = unsafe {
678
        llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst), buf.as_ptr())
A
Alex Crichton 已提交
679
    };
680 681
    unsafe {
        llvm::LLVMSetInitializer(llglobal, llconst);
682
        let section_name = metadata::metadata_section_name(&tcx.sess.target.target);
683 684 685 686 687 688 689 690
        let name = CString::new(section_name).unwrap();
        llvm::LLVMSetSection(llglobal, name.as_ptr());

        // Also generate a .section directive to force no
        // flags, at least for ELF outputs, so that the
        // metadata doesn't get loaded into memory.
        let directive = format!(".section {}", section_name);
        let directive = CString::new(directive).unwrap();
691
        llvm::LLVMSetModuleInlineAsm(metadata_llmod, directive.as_ptr())
692
    }
693
    return metadata;
694 695
}

696 697 698
pub struct ValueIter<'ll> {
    cur: Option<&'ll Value>,
    step: unsafe extern "C" fn(&'ll Value) -> Option<&'ll Value>,
699
}
700

701 702
impl Iterator for ValueIter<'ll> {
    type Item = &'ll Value;
703

704
    fn next(&mut self) -> Option<&'ll Value> {
705
        let old = self.cur;
706
        if let Some(old) = old {
707
            self.cur = unsafe { (self.step)(old) };
708
        }
709
        old
710
    }
711
}
712

713
pub fn iter_globals(llmod: &'ll llvm::Module) -> ValueIter<'ll> {
714 715 716 717 718 719 720
    unsafe {
        ValueIter {
            cur: llvm::LLVMGetFirstGlobal(llmod),
            step: llvm::LLVMGetNextGlobal,
        }
    }
}
J
Jorge Aparicio 已提交
721

I
Irina Popa 已提交
722
pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
723
                             rx: mpsc::Receiver<Box<dyn Any + Send>>)
I
Irina Popa 已提交
724
                             -> OngoingCodegen {
B
bjorn3 已提交
725

B
bjorn3 已提交
726
    check_for_rustc_errors_attr(tcx);
727

728
    if let Some(true) = tcx.sess.opts.debugging_opts.thinlto {
A
Alex Crichton 已提交
729 730 731 732
        if unsafe { !llvm::LLVMRustThinLTOAvailable() } {
            tcx.sess.fatal("this compiler's LLVM does not support ThinLTO");
        }
    }
733

734 735 736 737 738 739 740
    if (tcx.sess.opts.debugging_opts.pgo_gen.is_some() ||
        !tcx.sess.opts.debugging_opts.pgo_use.is_empty()) &&
        unsafe { !llvm::LLVMRustPGOAvailable() }
    {
        tcx.sess.fatal("this compiler's LLVM does not support PGO");
    }

741
    let crate_hash = tcx.crate_hash(LOCAL_CRATE);
742
    let link_meta = link::build_link_meta(crate_hash);
743

I
Irina Popa 已提交
744
    // Codegen the metadata.
W
Wesley Wiser 已提交
745
    tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen));
746
    let llmod_id = "metadata";
747 748 749 750
    let metadata_llvm_module = ModuleLlvm::new(tcx.sess, llmod_id);
    let metadata = time(tcx.sess, "write metadata", || {
        write_metadata(tcx, &metadata_llvm_module, &link_meta)
    });
W
Wesley Wiser 已提交
751
    tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen));
752

I
Irina Popa 已提交
753
    let metadata_module = ModuleCodegen {
754 755
        name: link::METADATA_MODULE_NAME.to_string(),
        llmod_id: llmod_id.to_string(),
756
        source: ModuleSource::Codegened(metadata_llvm_module),
757
        kind: ModuleKind::Metadata,
758
    };
759

I
Irina Popa 已提交
760
    let time_graph = if tcx.sess.opts.debugging_opts.codegen_time_graph {
761 762 763 764
        Some(time_graph::TimeGraph::new())
    } else {
        None
    };
765

I
Irina Popa 已提交
766 767 768 769
    // Skip crate items and just output metadata in -Z no-codegen mode.
    if tcx.sess.opts.debugging_opts.no_codegen ||
       !tcx.sess.opts.output_types.should_codegen() {
        let ongoing_codegen = write::start_async_codegen(
770
            tcx,
771
            time_graph.clone(),
772
            link_meta,
773
            metadata,
A
Alex Crichton 已提交
774 775
            rx,
            1);
776

I
Irina Popa 已提交
777 778
        ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module);
        ongoing_codegen.codegen_finished(tcx);
779

780
        assert_and_save_dep_graph(tcx);
781

I
Irina Popa 已提交
782
        ongoing_codegen.check_for_errors(tcx.sess);
783

I
Irina Popa 已提交
784
        return ongoing_codegen;
785 786
    }

I
Irina Popa 已提交
787
    // Run the monomorphization collector and partition the collected items into
788
    // codegen units.
789
    let codegen_units =
I
Irina Popa 已提交
790
        tcx.collect_and_partition_mono_items(LOCAL_CRATE).1;
791
    let codegen_units = (*codegen_units).clone();
792

793 794 795 796 797 798 799 800 801 802 803
    // Force all codegen_unit queries so they are already either red or green
    // when compile_codegen_unit accesses them. We are not able to re-execute
    // the codegen_unit query from just the DepNode, so an unknown color would
    // lead to having to re-execute compile_codegen_unit, possibly
    // unnecessarily.
    if tcx.dep_graph.is_fully_enabled() {
        for cgu in &codegen_units {
            tcx.codegen_unit(cgu.name().clone());
        }
    }

I
Irina Popa 已提交
804
    let ongoing_codegen = write::start_async_codegen(
805
        tcx,
806
        time_graph.clone(),
807
        link_meta,
808
        metadata,
A
Alex Crichton 已提交
809 810
        rx,
        codegen_units.len());
811

I
Irina Popa 已提交
812
    // Codegen an allocator shim, if any
813
    let allocator_module = if let Some(kind) = *tcx.sess.allocator_kind.get() {
814 815
        unsafe {
            let llmod_id = "allocator";
816
            let modules = ModuleLlvm::new(tcx.sess, llmod_id);
817
            time(tcx.sess, "write allocator module", || {
I
Irina Popa 已提交
818
                allocator::codegen(tcx, &modules, kind)
819
            });
820

821 822 823 824 825 826 827
            Some(ModuleCodegen {
                name: link::ALLOCATOR_MODULE_NAME.to_string(),
                llmod_id: llmod_id.to_string(),
                source: ModuleSource::Codegened(modules),
                kind: ModuleKind::Allocator,
            })
        }
828 829 830 831 832
    } else {
        None
    };

    if let Some(allocator_module) = allocator_module {
I
Irina Popa 已提交
833
        ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, allocator_module);
834 835
    }

I
Irina Popa 已提交
836
    ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module);
837

838
    // We sort the codegen units by size. This way we can schedule work for LLVM
839
    // a bit more efficiently.
840 841
    let codegen_units = {
        let mut codegen_units = codegen_units;
V
varkor 已提交
842
        codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
843 844 845
        codegen_units
    };

I
Irina Popa 已提交
846
    let mut total_codegen_time = Duration::new(0, 0);
A
Alex Crichton 已提交
847
    let mut all_stats = Stats::default();
848

A
Alex Crichton 已提交
849
    for cgu in codegen_units.into_iter() {
I
Irina Popa 已提交
850 851
        ongoing_codegen.wait_for_signal_to_codegen_item();
        ongoing_codegen.check_for_errors(tcx.sess);
852

853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869
        // First, if incremental compilation is enabled, we try to re-use the
        // codegen unit from the cache.
        if tcx.dep_graph.is_fully_enabled() {
            let cgu_id = cgu.work_product_id();

            // Check whether there is a previous work-product we can
            // re-use.  Not only must the file exist, and the inputs not
            // be dirty, but the hash of the symbols we will generate must
            // be the same.
            if let Some(buf) = tcx.dep_graph.previous_work_product(&cgu_id) {
                let dep_node = &DepNode::new(tcx,
                    DepConstructor::CompileCodegenUnit(cgu.name().clone()));

                // We try to mark the DepNode::CompileCodegenUnit green. If we
                // succeed it means that none of the dependencies has changed
                // and we can safely re-use.
                if let Some(dep_node_index) = tcx.dep_graph.try_mark_green(tcx, dep_node) {
870 871 872 873 874 875 876 877 878 879
                    // Append ".rs" to LLVM module identifier.
                    //
                    // LLVM code generator emits a ".file filename" directive
                    // for ELF backends. Value of the "filename" is set as the
                    // LLVM module identifier.  Due to a LLVM MC bug[1], LLVM
                    // crashes if the module identifier is same as other symbols
                    // such as a function name in the module.
                    // 1. http://llvm.org/bugs/show_bug.cgi?id=11479
                    let llmod_id = format!("{}.rs", cgu.name());

I
Irina Popa 已提交
880
                    let module = ModuleCodegen {
881 882 883
                        name: cgu.name().to_string(),
                        source: ModuleSource::Preexisting(buf),
                        kind: ModuleKind::Regular,
884
                        llmod_id,
885 886
                    };
                    tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true);
I
Irina Popa 已提交
887
                    write::submit_codegened_module_to_llvm(tcx, module, 0);
888 889 890 891 892 893 894 895 896
                    // Continue to next cgu, this one is done.
                    continue
                }
            } else {
                // This can happen if files were  deleted from the cache
                // directory for some reason. We just re-compile then.
            }
        }

897
        let _timing_guard = time_graph.as_ref().map(|time_graph| {
I
Irina Popa 已提交
898 899
            time_graph.start(write::CODEGEN_WORKER_TIMELINE,
                             write::CODEGEN_WORK_PACKAGE_KIND,
900 901
                             &format!("codegen {}", cgu.name()))
        });
902
        let start_time = Instant::now();
A
Alex Crichton 已提交
903
        all_stats.extend(tcx.compile_codegen_unit(*cgu.name()));
I
Irina Popa 已提交
904 905
        total_codegen_time += start_time.elapsed();
        ongoing_codegen.check_for_errors(tcx.sess);
906 907
    }

I
Irina Popa 已提交
908
    ongoing_codegen.codegen_finished(tcx);
A
Alex Crichton 已提交
909

I
Irina Popa 已提交
910
    // Since the main thread is sometimes blocked during codegen, we keep track
911 912
    // -Ztime-passes output manually.
    print_time_passes_entry(tcx.sess.time_passes(),
I
Irina Popa 已提交
913 914
                            "codegen to LLVM IR",
                            total_codegen_time);
915

A
Alex Crichton 已提交
916
    if tcx.sess.opts.incremental.is_some() {
917
        ::rustc_incremental::assert_module_sources::assert_module_sources(tcx);
918 919
    }

N
Niko Matsakis 已提交
920
    symbol_names_test::report_symbol_names(tcx);
921

I
Irina Popa 已提交
922 923
    if tcx.sess.codegen_stats() {
        println!("--- codegen stats ---");
A
Alex Crichton 已提交
924 925 926
        println!("n_glues_created: {}", all_stats.n_glues_created);
        println!("n_null_glues: {}", all_stats.n_null_glues);
        println!("n_real_glues: {}", all_stats.n_real_glues);
927

A
Alex Crichton 已提交
928 929 930
        println!("n_fns: {}", all_stats.n_fns);
        println!("n_inlines: {}", all_stats.n_inlines);
        println!("n_closures: {}", all_stats.n_closures);
931
        println!("fn stats:");
A
Alex Crichton 已提交
932 933 934
        all_stats.fn_stats.sort_by_key(|&(_, insns)| insns);
        for &(ref name, insns) in all_stats.fn_stats.iter() {
            println!("{} insns, {}", insns, *name);
935
        }
J
James Miller 已提交
936
    }
937

938
    if tcx.sess.count_llvm_insns() {
A
Alex Crichton 已提交
939
        for (k, v) in all_stats.llvm_insns.iter() {
A
Alex Crichton 已提交
940
            println!("{:7} {}", *v, *k);
941 942 943
        }
    }

I
Irina Popa 已提交
944
    ongoing_codegen.check_for_errors(tcx.sess);
945

946
    assert_and_save_dep_graph(tcx);
I
Irina Popa 已提交
947
    ongoing_codegen
948
}
949

950
fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
951
    time(tcx.sess,
952 953 954
         "assert dep graph",
         || rustc_incremental::assert_dep_graph(tcx));

955
    time(tcx.sess,
956
         "serialize dep graph",
957
         || rustc_incremental::save_dep_graph(tcx));
958 959
}

I
Irina Popa 已提交
960
fn collect_and_partition_mono_items<'a, 'tcx>(
961 962
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    cnum: CrateNum,
963
) -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>)
964 965
{
    assert_eq!(cnum, LOCAL_CRATE);
966

I
Irina Popa 已提交
967
    let collection_mode = match tcx.sess.opts.debugging_opts.print_mono_items {
968 969 970 971
        Some(ref s) => {
            let mode_string = s.to_lowercase();
            let mode_string = mode_string.trim();
            if mode_string == "eager" {
972
                MonoItemCollectionMode::Eager
973 974 975 976 977
            } else {
                if mode_string != "lazy" {
                    let message = format!("Unknown codegen-item collection mode '{}'. \
                                           Falling back to 'lazy' mode.",
                                           mode_string);
978
                    tcx.sess.warn(&message);
979 980
                }

981
                MonoItemCollectionMode::Lazy
982 983
            }
        }
984 985 986 987 988 989 990
        None => {
            if tcx.sess.opts.cg.link_dead_code {
                MonoItemCollectionMode::Eager
            } else {
                MonoItemCollectionMode::Lazy
            }
        }
991 992
    };

993
    let (items, inlining_map) =
I
Irina Popa 已提交
994
        time(tcx.sess, "monomorphization collection", || {
995
            collector::collect_crate_mono_items(tcx, collection_mode)
996 997
    });

998 999
    tcx.sess.abort_if_errors();

1000
    ::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx, items.iter());
1001

1002
    let strategy = if tcx.sess.opts.incremental.is_some() {
1003 1004
        PartitioningStrategy::PerModule
    } else {
1005
        PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units())
1006 1007
    };

1008
    let codegen_units = time(tcx.sess, "codegen unit partitioning", || {
1009
        partitioning::partition(tcx,
1010 1011
                                items.iter().cloned(),
                                strategy,
1012
                                &inlining_map)
1013 1014 1015
            .into_iter()
            .map(Arc::new)
            .collect::<Vec<_>>()
1016 1017
    });

I
Irina Popa 已提交
1018 1019
    let mono_items: DefIdSet = items.iter().filter_map(|mono_item| {
        match *mono_item {
M
Maik Klein 已提交
1020
            MonoItem::Fn(ref instance) => Some(instance.def_id()),
1021
            MonoItem::Static(def_id) => Some(def_id),
1022 1023 1024
            _ => None,
        }
    }).collect();
1025

I
Irina Popa 已提交
1026
    if tcx.sess.opts.debugging_opts.print_mono_items.is_some() {
1027
        let mut item_to_cgus = FxHashMap();
1028

1029
        for cgu in &codegen_units {
I
Irina Popa 已提交
1030 1031
            for (&mono_item, &linkage) in cgu.items() {
                item_to_cgus.entry(mono_item)
1032
                            .or_insert(Vec::new())
1033
                            .push((cgu.name().clone(), linkage));
1034 1035 1036 1037 1038 1039
            }
        }

        let mut item_keys: Vec<_> = items
            .iter()
            .map(|i| {
1040
                let mut output = i.to_string(tcx);
1041 1042
                output.push_str(" @@");
                let mut empty = Vec::new();
1043
                let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
1044 1045
                cgus.as_mut_slice().sort_by_key(|&(ref name, _)| name.clone());
                cgus.dedup();
1046
                for &(ref cgu_name, (linkage, _)) in cgus.iter() {
1047
                    output.push_str(" ");
1048
                    output.push_str(&cgu_name.as_str());
1049 1050

                    let linkage_abbrev = match linkage {
1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
                        Linkage::External => "External",
                        Linkage::AvailableExternally => "Available",
                        Linkage::LinkOnceAny => "OnceAny",
                        Linkage::LinkOnceODR => "OnceODR",
                        Linkage::WeakAny => "WeakAny",
                        Linkage::WeakODR => "WeakODR",
                        Linkage::Appending => "Appending",
                        Linkage::Internal => "Internal",
                        Linkage::Private => "Private",
                        Linkage::ExternalWeak => "ExternalWeak",
                        Linkage::Common => "Common",
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071
                    };

                    output.push_str("[");
                    output.push_str(linkage_abbrev);
                    output.push_str("]");
                }
                output
            })
            .collect();

1072 1073 1074
        item_keys.sort();

        for item in item_keys {
I
Irina Popa 已提交
1075
            println!("MONO_ITEM {}", item);
1076 1077
        }
    }
1078

I
Irina Popa 已提交
1079
    (Arc::new(mono_items), Arc::new(codegen_units))
1080
}
1081 1082

impl CrateInfo {
1083
    pub fn new(tcx: TyCtxt) -> CrateInfo {
1084 1085 1086 1087 1088 1089
        let mut info = CrateInfo {
            panic_runtime: None,
            compiler_builtins: None,
            profiler_runtime: None,
            sanitizer_runtime: None,
            is_no_builtins: FxHashSet(),
1090
            native_libraries: FxHashMap(),
1091 1092
            used_libraries: tcx.native_libraries(LOCAL_CRATE),
            link_args: tcx.link_args(LOCAL_CRATE),
1093
            crate_name: FxHashMap(),
1094 1095 1096
            used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic),
            used_crates_static: cstore::used_crates(tcx, LinkagePreference::RequireStatic),
            used_crate_source: FxHashMap(),
1097
            wasm_imports: FxHashMap(),
1098 1099
            lang_item_to_crate: FxHashMap(),
            missing_lang_items: FxHashMap(),
1100
        };
1101
        let lang_items = tcx.lang_items();
1102

1103
        let load_wasm_items = tcx.sess.crate_types.borrow()
1104
            .iter()
1105
            .any(|c| *c != config::CrateType::Rlib) &&
1106
            tcx.sess.opts.target_triple.triple() == "wasm32-unknown-unknown";
1107

1108 1109
        if load_wasm_items {
            info.load_wasm_imports(tcx, LOCAL_CRATE);
1110 1111
        }

1112
        for &cnum in tcx.crates().iter() {
1113
            info.native_libraries.insert(cnum, tcx.native_libraries(cnum));
1114
            info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string());
1115
            info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum));
1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130
            if tcx.is_panic_runtime(cnum) {
                info.panic_runtime = Some(cnum);
            }
            if tcx.is_compiler_builtins(cnum) {
                info.compiler_builtins = Some(cnum);
            }
            if tcx.is_profiler_runtime(cnum) {
                info.profiler_runtime = Some(cnum);
            }
            if tcx.is_sanitizer_runtime(cnum) {
                info.sanitizer_runtime = Some(cnum);
            }
            if tcx.is_no_builtins(cnum) {
                info.is_no_builtins.insert(cnum);
            }
1131 1132
            if load_wasm_items {
                info.load_wasm_imports(tcx, cnum);
1133
            }
1134 1135 1136 1137 1138 1139
            let missing = tcx.missing_lang_items(cnum);
            for &item in missing.iter() {
                if let Ok(id) = lang_items.require(item) {
                    info.lang_item_to_crate.insert(item, id.krate);
                }
            }
1140 1141 1142 1143 1144 1145 1146

            // No need to look for lang items that are whitelisted and don't
            // actually need to exist.
            let missing = missing.iter()
                .cloned()
                .filter(|&l| !weak_lang_items::whitelisted(tcx, l))
                .collect();
1147
            info.missing_lang_items.insert(cnum, missing);
1148 1149 1150 1151
        }

        return info
    }
1152 1153 1154 1155 1156 1157 1158 1159

    fn load_wasm_imports(&mut self, tcx: TyCtxt, cnum: CrateNum) {
        for (&id, module) in tcx.wasm_import_module_map(cnum).iter() {
            let instance = Instance::mono(tcx, id);
            let import_name = tcx.symbol_name(instance);
            self.wasm_imports.insert(import_name.to_string(), module.clone());
        }
    }
1160
}
1161

I
Irina Popa 已提交
1162 1163 1164 1165
fn is_codegened_item(tcx: TyCtxt, id: DefId) -> bool {
    let (all_mono_items, _) =
        tcx.collect_and_partition_mono_items(LOCAL_CRATE);
    all_mono_items.contains(&id)
1166 1167
}

A
Alex Crichton 已提交
1168 1169
fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  cgu: InternedString) -> Stats {
1170
    let cgu = tcx.codegen_unit(cgu);
A
Alex Crichton 已提交
1171 1172

    let start_time = Instant::now();
I
Irina Popa 已提交
1173 1174
    let (stats, module) = module_codegen(tcx, cgu);
    let time_to_codegen = start_time.elapsed();
A
Alex Crichton 已提交
1175 1176

    // We assume that the cost to run LLVM on a CGU is proportional to
I
Irina Popa 已提交
1177 1178 1179
    // the time we needed for codegenning it.
    let cost = time_to_codegen.as_secs() * 1_000_000_000 +
               time_to_codegen.subsec_nanos() as u64;
A
Alex Crichton 已提交
1180

I
Irina Popa 已提交
1181
    write::submit_codegened_module_to_llvm(tcx,
A
Alex Crichton 已提交
1182 1183 1184 1185
                                            module,
                                            cost);
    return stats;

I
Irina Popa 已提交
1186
    fn module_codegen<'a, 'tcx>(
1187 1188
        tcx: TyCtxt<'a, 'tcx, 'tcx>,
        cgu: Arc<CodegenUnit<'tcx>>)
I
Irina Popa 已提交
1189
        -> (Stats, ModuleCodegen)
A
Alex Crichton 已提交
1190 1191 1192
    {
        let cgu_name = cgu.name().to_string();

1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205
        // Append ".rs" to LLVM module identifier.
        //
        // LLVM code generator emits a ".file filename" directive
        // for ELF backends. Value of the "filename" is set as the
        // LLVM module identifier.  Due to a LLVM MC bug[1], LLVM
        // crashes if the module identifier is same as other symbols
        // such as a function name in the module.
        // 1. http://llvm.org/bugs/show_bug.cgi?id=11479
        let llmod_id = format!("{}-{}.rs",
                               cgu.name(),
                               tcx.crate_disambiguator(LOCAL_CRATE)
                                   .to_fingerprint().to_hex());

I
Irina Popa 已提交
1206
        // Instantiate monomorphizations without filling out definitions yet...
1207 1208 1209
        let llvm_module = ModuleLlvm::new(tcx.sess, &llmod_id);
        let stats = {
            let cx = CodegenCx::new(tcx, cgu, &llvm_module);
I
Irina Popa 已提交
1210
            let mono_items = cx.codegen_unit
1211
                                 .items_in_deterministic_order(cx.tcx);
I
Irina Popa 已提交
1212 1213
            for &(mono_item, (linkage, visibility)) in &mono_items {
                mono_item.predefine(&cx, linkage, visibility);
A
Alex Crichton 已提交
1214 1215 1216
            }

            // ... and now that we have everything pre-defined, fill out those definitions.
I
Irina Popa 已提交
1217 1218
            for &(mono_item, _) in &mono_items {
                mono_item.define(&cx);
A
Alex Crichton 已提交
1219 1220 1221 1222
            }

            // If this codegen unit contains the main function, also create the
            // wrapper here
1223
            maybe_create_entry_wrapper(&cx);
A
Alex Crichton 已提交
1224 1225

            // Run replace-all-uses-with for statics that need it
1226
            for &(old_g, new_g) in cx.statics_to_rauw.borrow().iter() {
A
Alex Crichton 已提交
1227
                unsafe {
1228
                    let bitcast = llvm::LLVMConstPointerCast(new_g, val_ty(old_g));
A
Alex Crichton 已提交
1229 1230 1231 1232 1233 1234 1235
                    llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
                    llvm::LLVMDeleteGlobal(old_g);
                }
            }

            // Create the llvm.used variable
            // This variable has type [N x i8*] and is stored in the llvm.metadata section
1236
            if !cx.used_statics.borrow().is_empty() {
A
Alex Crichton 已提交
1237 1238
                let name = CString::new("llvm.used").unwrap();
                let section = CString::new("llvm.metadata").unwrap();
1239
                let array = C_array(Type::i8(&cx).ptr_to(), &*cx.used_statics.borrow());
A
Alex Crichton 已提交
1240 1241

                unsafe {
1242
                    let g = llvm::LLVMAddGlobal(cx.llmod,
1243
                                                val_ty(array),
A
Alex Crichton 已提交
1244 1245 1246 1247 1248 1249 1250 1251
                                                name.as_ptr());
                    llvm::LLVMSetInitializer(g, array);
                    llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
                    llvm::LLVMSetSection(g, section.as_ptr());
                }
            }

            // Finalize debuginfo
1252
            if cx.sess().opts.debuginfo != DebugInfo::None {
1253
                debuginfo::finalize(&cx);
A
Alex Crichton 已提交
1254 1255
            }

1256
            cx.stats.into_inner()
A
Alex Crichton 已提交
1257 1258
        };

1259 1260 1261 1262 1263 1264
        (stats, ModuleCodegen {
            name: cgu_name,
            source: ModuleSource::Codegened(llvm_module),
            kind: ModuleKind::Regular,
            llmod_id,
        })
A
Alex Crichton 已提交
1265 1266 1267
    }
}

1268
pub fn provide(providers: &mut Providers) {
I
Irina Popa 已提交
1269 1270
    providers.collect_and_partition_mono_items =
        collect_and_partition_mono_items;
1271

I
Irina Popa 已提交
1272
    providers.is_codegened_item = is_codegened_item;
A
Alex Crichton 已提交
1273 1274

    providers.codegen_unit = |tcx, name| {
I
Irina Popa 已提交
1275
        let (_, all) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
A
Alex Crichton 已提交
1276 1277 1278
        all.iter()
            .find(|cgu| *cgu.name() == name)
            .cloned()
1279
            .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name))
A
Alex Crichton 已提交
1280 1281
    };
    providers.compile_codegen_unit = compile_codegen_unit;
1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314

    provide_extern(providers);
}

pub fn provide_extern(providers: &mut Providers) {
    providers.dllimport_foreign_items = |tcx, krate| {
        let module_map = tcx.foreign_modules(krate);
        let module_map = module_map.iter()
            .map(|lib| (lib.def_id, lib))
            .collect::<FxHashMap<_, _>>();

        let dllimports = tcx.native_libraries(krate)
            .iter()
            .filter(|lib| {
                if lib.kind != cstore::NativeLibraryKind::NativeUnknown {
                    return false
                }
                let cfg = match lib.cfg {
                    Some(ref cfg) => cfg,
                    None => return true,
                };
                attr::cfg_matches(cfg, &tcx.sess.parse_sess, None)
            })
            .filter_map(|lib| lib.foreign_module)
            .map(|id| &module_map[&id])
            .flat_map(|module| module.foreign_items.iter().cloned())
            .collect();
        Lrc::new(dllimports)
    };

    providers.is_dllimport_foreign_item = |tcx, def_id| {
        tcx.dllimport_foreign_items(def_id.krate).contains(&def_id)
    };
1315 1316
}

1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337
pub fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage {
    match linkage {
        Linkage::External => llvm::Linkage::ExternalLinkage,
        Linkage::AvailableExternally => llvm::Linkage::AvailableExternallyLinkage,
        Linkage::LinkOnceAny => llvm::Linkage::LinkOnceAnyLinkage,
        Linkage::LinkOnceODR => llvm::Linkage::LinkOnceODRLinkage,
        Linkage::WeakAny => llvm::Linkage::WeakAnyLinkage,
        Linkage::WeakODR => llvm::Linkage::WeakODRLinkage,
        Linkage::Appending => llvm::Linkage::AppendingLinkage,
        Linkage::Internal => llvm::Linkage::InternalLinkage,
        Linkage::Private => llvm::Linkage::PrivateLinkage,
        Linkage::ExternalWeak => llvm::Linkage::ExternalWeakLinkage,
        Linkage::Common => llvm::Linkage::CommonLinkage,
    }
}

pub fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility {
    match linkage {
        Visibility::Default => llvm::Visibility::Default,
        Visibility::Hidden => llvm::Visibility::Hidden,
        Visibility::Protected => llvm::Visibility::Protected,
1338
    }
1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351
}

// FIXME(mw): Anything that is produced via DepGraph::with_task() must implement
//            the HashStable trait. Normally DepGraph::with_task() calls are
//            hidden behind queries, but CGU creation is a special case in two
//            ways: (1) it's not a query and (2) CGU are output nodes, so their
//            Fingerprints are not actually needed. It remains to be clarified
//            how exactly this case will be handled in the red/green system but
//            for now we content ourselves with providing a no-op HashStable
//            implementation for CGUs.
mod temp_stable_hash_impls {
    use rustc_data_structures::stable_hasher::{StableHasherResult, StableHasher,
                                               HashStable};
I
Irina Popa 已提交
1352
    use ModuleCodegen;
1353

I
Irina Popa 已提交
1354
    impl<HCX> HashStable<HCX> for ModuleCodegen {
1355 1356 1357 1358 1359
        fn hash_stable<W: StableHasherResult>(&self,
                                              _: &mut HCX,
                                              _: &mut StableHasher<W>) {
            // do nothing
        }
1360 1361
    }
}