base.rs 49.7 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
        attributes::apply_target_cpu_attr(cx, llfn);
600

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

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

605 606 607
        // 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);
608
        let arg_argc = bx.intcast(param_argc, cx.isize_ty, true);
609 610
        let arg_argv = param_argv;

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

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

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

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

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

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

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

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

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

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

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

674 675
    let llmeta = C_bytes_in_context(metadata_llcx, &compressed);
    let llconst = C_struct_in_context(metadata_llcx, &[llmeta], false);
676
    let name = exported_symbols::metadata_symbol_name(tcx);
677
    let buf = CString::new(name).unwrap();
A
Alex Crichton 已提交
678
    let llglobal = unsafe {
679
        llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst), buf.as_ptr())
A
Alex Crichton 已提交
680
    };
681 682
    unsafe {
        llvm::LLVMSetInitializer(llglobal, llconst);
683
        let section_name = metadata::metadata_section_name(&tcx.sess.target.target);
684 685 686 687 688 689 690 691
        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();
692
        llvm::LLVMSetModuleInlineAsm(metadata_llmod, directive.as_ptr())
693
    }
694
    return metadata;
695 696
}

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

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

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

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

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

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

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

735 736 737 738 739 740 741
    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");
    }

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

I
Irina Popa 已提交
745
    // Codegen the metadata.
W
Wesley Wiser 已提交
746
    tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen));
747
    let llmod_id = "metadata";
748 749 750 751
    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 已提交
752
    tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen));
753

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

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

I
Irina Popa 已提交
767 768 769 770
    // 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(
771
            tcx,
772
            time_graph.clone(),
773
            link_meta,
774
            metadata,
A
Alex Crichton 已提交
775 776
            rx,
            1);
777

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

781
        assert_and_save_dep_graph(tcx);
782

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

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

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

794 795 796 797 798 799 800 801 802 803 804
    // 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 已提交
805
    let ongoing_codegen = write::start_async_codegen(
806
        tcx,
807
        time_graph.clone(),
808
        link_meta,
809
        metadata,
A
Alex Crichton 已提交
810 811
        rx,
        codegen_units.len());
812

813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834
    // Codegen an allocator shim, if necessary.
    //
    // If the crate doesn't have an `allocator_kind` set then there's definitely
    // no shim to generate. Otherwise we also check our dependency graph for all
    // our output crate types. If anything there looks like its a `Dynamic`
    // linkage, then it's already got an allocator shim and we'll be using that
    // one instead. If nothing exists then it's our job to generate the
    // allocator!
    let any_dynamic_crate = tcx.sess.dependency_formats.borrow()
        .iter()
        .any(|(_, list)| {
            use rustc::middle::dependency_format::Linkage;
            list.iter().any(|linkage| {
                match linkage {
                    Linkage::Dynamic => true,
                    _ => false,
                }
            })
        });
    let allocator_module = if any_dynamic_crate {
        None
    } else if let Some(kind) = *tcx.sess.allocator_kind.get() {
835 836
        unsafe {
            let llmod_id = "allocator";
837
            let modules = ModuleLlvm::new(tcx.sess, llmod_id);
838
            time(tcx.sess, "write allocator module", || {
I
Irina Popa 已提交
839
                allocator::codegen(tcx, &modules, kind)
840
            });
841

842 843 844 845 846 847 848
            Some(ModuleCodegen {
                name: link::ALLOCATOR_MODULE_NAME.to_string(),
                llmod_id: llmod_id.to_string(),
                source: ModuleSource::Codegened(modules),
                kind: ModuleKind::Allocator,
            })
        }
849 850 851 852 853
    } else {
        None
    };

    if let Some(allocator_module) = allocator_module {
I
Irina Popa 已提交
854
        ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, allocator_module);
855 856
    }

I
Irina Popa 已提交
857
    ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module);
858

859
    // We sort the codegen units by size. This way we can schedule work for LLVM
860
    // a bit more efficiently.
861 862
    let codegen_units = {
        let mut codegen_units = codegen_units;
V
varkor 已提交
863
        codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
864 865 866
        codegen_units
    };

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

A
Alex Crichton 已提交
870
    for cgu in codegen_units.into_iter() {
I
Irina Popa 已提交
871 872
        ongoing_codegen.wait_for_signal_to_codegen_item();
        ongoing_codegen.check_for_errors(tcx.sess);
873

874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890
        // 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) {
891 892 893 894 895 896 897 898 899 900
                    // 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 已提交
901
                    let module = ModuleCodegen {
902 903 904
                        name: cgu.name().to_string(),
                        source: ModuleSource::Preexisting(buf),
                        kind: ModuleKind::Regular,
905
                        llmod_id,
906 907
                    };
                    tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true);
I
Irina Popa 已提交
908
                    write::submit_codegened_module_to_llvm(tcx, module, 0);
909 910 911 912 913 914 915 916 917
                    // 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.
            }
        }

918
        let _timing_guard = time_graph.as_ref().map(|time_graph| {
I
Irina Popa 已提交
919 920
            time_graph.start(write::CODEGEN_WORKER_TIMELINE,
                             write::CODEGEN_WORK_PACKAGE_KIND,
921 922
                             &format!("codegen {}", cgu.name()))
        });
923
        let start_time = Instant::now();
A
Alex Crichton 已提交
924
        all_stats.extend(tcx.compile_codegen_unit(*cgu.name()));
I
Irina Popa 已提交
925 926
        total_codegen_time += start_time.elapsed();
        ongoing_codegen.check_for_errors(tcx.sess);
927 928
    }

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

I
Irina Popa 已提交
931
    // Since the main thread is sometimes blocked during codegen, we keep track
932 933
    // -Ztime-passes output manually.
    print_time_passes_entry(tcx.sess.time_passes(),
I
Irina Popa 已提交
934 935
                            "codegen to LLVM IR",
                            total_codegen_time);
936

A
Alex Crichton 已提交
937
    if tcx.sess.opts.incremental.is_some() {
938
        ::rustc_incremental::assert_module_sources::assert_module_sources(tcx);
939 940
    }

N
Niko Matsakis 已提交
941
    symbol_names_test::report_symbol_names(tcx);
942

I
Irina Popa 已提交
943 944
    if tcx.sess.codegen_stats() {
        println!("--- codegen stats ---");
A
Alex Crichton 已提交
945 946 947
        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);
948

A
Alex Crichton 已提交
949 950 951
        println!("n_fns: {}", all_stats.n_fns);
        println!("n_inlines: {}", all_stats.n_inlines);
        println!("n_closures: {}", all_stats.n_closures);
952
        println!("fn stats:");
A
Alex Crichton 已提交
953 954 955
        all_stats.fn_stats.sort_by_key(|&(_, insns)| insns);
        for &(ref name, insns) in all_stats.fn_stats.iter() {
            println!("{} insns, {}", insns, *name);
956
        }
J
James Miller 已提交
957
    }
958

959
    if tcx.sess.count_llvm_insns() {
A
Alex Crichton 已提交
960
        for (k, v) in all_stats.llvm_insns.iter() {
A
Alex Crichton 已提交
961
            println!("{:7} {}", *v, *k);
962 963 964
        }
    }

I
Irina Popa 已提交
965
    ongoing_codegen.check_for_errors(tcx.sess);
966

967
    assert_and_save_dep_graph(tcx);
I
Irina Popa 已提交
968
    ongoing_codegen
969
}
970

971
fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
972
    time(tcx.sess,
973 974 975
         "assert dep graph",
         || rustc_incremental::assert_dep_graph(tcx));

976
    time(tcx.sess,
977
         "serialize dep graph",
978
         || rustc_incremental::save_dep_graph(tcx));
979 980
}

I
Irina Popa 已提交
981
fn collect_and_partition_mono_items<'a, 'tcx>(
982 983
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    cnum: CrateNum,
984
) -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>)
985 986
{
    assert_eq!(cnum, LOCAL_CRATE);
987

I
Irina Popa 已提交
988
    let collection_mode = match tcx.sess.opts.debugging_opts.print_mono_items {
989 990 991 992
        Some(ref s) => {
            let mode_string = s.to_lowercase();
            let mode_string = mode_string.trim();
            if mode_string == "eager" {
993
                MonoItemCollectionMode::Eager
994 995 996 997 998
            } else {
                if mode_string != "lazy" {
                    let message = format!("Unknown codegen-item collection mode '{}'. \
                                           Falling back to 'lazy' mode.",
                                           mode_string);
999
                    tcx.sess.warn(&message);
1000 1001
                }

1002
                MonoItemCollectionMode::Lazy
1003 1004
            }
        }
1005 1006 1007 1008 1009 1010 1011
        None => {
            if tcx.sess.opts.cg.link_dead_code {
                MonoItemCollectionMode::Eager
            } else {
                MonoItemCollectionMode::Lazy
            }
        }
1012 1013
    };

1014
    let (items, inlining_map) =
I
Irina Popa 已提交
1015
        time(tcx.sess, "monomorphization collection", || {
1016
            collector::collect_crate_mono_items(tcx, collection_mode)
1017 1018
    });

1019 1020
    tcx.sess.abort_if_errors();

1021
    ::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx, items.iter());
1022

1023
    let strategy = if tcx.sess.opts.incremental.is_some() {
1024 1025
        PartitioningStrategy::PerModule
    } else {
1026
        PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units())
1027 1028
    };

1029
    let codegen_units = time(tcx.sess, "codegen unit partitioning", || {
1030
        partitioning::partition(tcx,
1031 1032
                                items.iter().cloned(),
                                strategy,
1033
                                &inlining_map)
1034 1035 1036
            .into_iter()
            .map(Arc::new)
            .collect::<Vec<_>>()
1037 1038
    });

I
Irina Popa 已提交
1039 1040
    let mono_items: DefIdSet = items.iter().filter_map(|mono_item| {
        match *mono_item {
M
Maik Klein 已提交
1041
            MonoItem::Fn(ref instance) => Some(instance.def_id()),
1042
            MonoItem::Static(def_id) => Some(def_id),
1043 1044 1045
            _ => None,
        }
    }).collect();
1046

I
Irina Popa 已提交
1047
    if tcx.sess.opts.debugging_opts.print_mono_items.is_some() {
1048
        let mut item_to_cgus = FxHashMap();
1049

1050
        for cgu in &codegen_units {
I
Irina Popa 已提交
1051 1052
            for (&mono_item, &linkage) in cgu.items() {
                item_to_cgus.entry(mono_item)
1053
                            .or_insert(Vec::new())
1054
                            .push((cgu.name().clone(), linkage));
1055 1056 1057 1058 1059 1060
            }
        }

        let mut item_keys: Vec<_> = items
            .iter()
            .map(|i| {
1061
                let mut output = i.to_string(tcx);
1062 1063
                output.push_str(" @@");
                let mut empty = Vec::new();
1064
                let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
1065 1066
                cgus.as_mut_slice().sort_by_key(|&(ref name, _)| name.clone());
                cgus.dedup();
1067
                for &(ref cgu_name, (linkage, _)) in cgus.iter() {
1068
                    output.push_str(" ");
1069
                    output.push_str(&cgu_name.as_str());
1070 1071

                    let linkage_abbrev = match linkage {
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082
                        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",
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092
                    };

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

1093 1094 1095
        item_keys.sort();

        for item in item_keys {
I
Irina Popa 已提交
1096
            println!("MONO_ITEM {}", item);
1097 1098
        }
    }
1099

I
Irina Popa 已提交
1100
    (Arc::new(mono_items), Arc::new(codegen_units))
1101
}
1102 1103

impl CrateInfo {
1104
    pub fn new(tcx: TyCtxt) -> CrateInfo {
1105 1106 1107 1108 1109 1110
        let mut info = CrateInfo {
            panic_runtime: None,
            compiler_builtins: None,
            profiler_runtime: None,
            sanitizer_runtime: None,
            is_no_builtins: FxHashSet(),
1111
            native_libraries: FxHashMap(),
1112 1113
            used_libraries: tcx.native_libraries(LOCAL_CRATE),
            link_args: tcx.link_args(LOCAL_CRATE),
1114
            crate_name: FxHashMap(),
1115 1116 1117
            used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic),
            used_crates_static: cstore::used_crates(tcx, LinkagePreference::RequireStatic),
            used_crate_source: FxHashMap(),
1118
            wasm_imports: FxHashMap(),
1119 1120
            lang_item_to_crate: FxHashMap(),
            missing_lang_items: FxHashMap(),
1121
        };
1122
        let lang_items = tcx.lang_items();
1123

1124
        let load_wasm_items = tcx.sess.crate_types.borrow()
1125
            .iter()
1126
            .any(|c| *c != config::CrateType::Rlib) &&
1127
            tcx.sess.opts.target_triple.triple() == "wasm32-unknown-unknown";
1128

1129 1130
        if load_wasm_items {
            info.load_wasm_imports(tcx, LOCAL_CRATE);
1131 1132
        }

1133
        for &cnum in tcx.crates().iter() {
1134
            info.native_libraries.insert(cnum, tcx.native_libraries(cnum));
1135
            info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string());
1136
            info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum));
1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151
            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);
            }
1152 1153
            if load_wasm_items {
                info.load_wasm_imports(tcx, cnum);
1154
            }
1155 1156 1157 1158 1159 1160
            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);
                }
            }
1161 1162 1163 1164 1165 1166 1167

            // 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();
1168
            info.missing_lang_items.insert(cnum, missing);
1169 1170 1171 1172
        }

        return info
    }
1173 1174 1175 1176 1177 1178 1179 1180

    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());
        }
    }
1181
}
1182

I
Irina Popa 已提交
1183 1184 1185 1186
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)
1187 1188
}

A
Alex Crichton 已提交
1189 1190
fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  cgu: InternedString) -> Stats {
1191
    let cgu = tcx.codegen_unit(cgu);
A
Alex Crichton 已提交
1192 1193

    let start_time = Instant::now();
I
Irina Popa 已提交
1194 1195
    let (stats, module) = module_codegen(tcx, cgu);
    let time_to_codegen = start_time.elapsed();
A
Alex Crichton 已提交
1196 1197

    // We assume that the cost to run LLVM on a CGU is proportional to
I
Irina Popa 已提交
1198 1199 1200
    // 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 已提交
1201

I
Irina Popa 已提交
1202
    write::submit_codegened_module_to_llvm(tcx,
A
Alex Crichton 已提交
1203 1204 1205 1206
                                            module,
                                            cost);
    return stats;

I
Irina Popa 已提交
1207
    fn module_codegen<'a, 'tcx>(
1208 1209
        tcx: TyCtxt<'a, 'tcx, 'tcx>,
        cgu: Arc<CodegenUnit<'tcx>>)
I
Irina Popa 已提交
1210
        -> (Stats, ModuleCodegen)
A
Alex Crichton 已提交
1211 1212 1213
    {
        let cgu_name = cgu.name().to_string();

1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226
        // 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 已提交
1227
        // Instantiate monomorphizations without filling out definitions yet...
1228 1229 1230
        let llvm_module = ModuleLlvm::new(tcx.sess, &llmod_id);
        let stats = {
            let cx = CodegenCx::new(tcx, cgu, &llvm_module);
I
Irina Popa 已提交
1231
            let mono_items = cx.codegen_unit
1232
                                 .items_in_deterministic_order(cx.tcx);
I
Irina Popa 已提交
1233 1234
            for &(mono_item, (linkage, visibility)) in &mono_items {
                mono_item.predefine(&cx, linkage, visibility);
A
Alex Crichton 已提交
1235 1236 1237
            }

            // ... and now that we have everything pre-defined, fill out those definitions.
I
Irina Popa 已提交
1238 1239
            for &(mono_item, _) in &mono_items {
                mono_item.define(&cx);
A
Alex Crichton 已提交
1240 1241 1242 1243
            }

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

            // Run replace-all-uses-with for statics that need it
1247
            for &(old_g, new_g) in cx.statics_to_rauw.borrow().iter() {
A
Alex Crichton 已提交
1248
                unsafe {
1249
                    let bitcast = llvm::LLVMConstPointerCast(new_g, val_ty(old_g));
A
Alex Crichton 已提交
1250 1251 1252 1253 1254 1255 1256
                    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
1257
            if !cx.used_statics.borrow().is_empty() {
1258 1259
                let name = const_cstr!("llvm.used");
                let section = const_cstr!("llvm.metadata");
1260
                let array = C_array(Type::i8(&cx).ptr_to(), &*cx.used_statics.borrow());
A
Alex Crichton 已提交
1261 1262

                unsafe {
1263
                    let g = llvm::LLVMAddGlobal(cx.llmod,
1264
                                                val_ty(array),
A
Alex Crichton 已提交
1265 1266 1267 1268 1269 1270 1271 1272
                                                name.as_ptr());
                    llvm::LLVMSetInitializer(g, array);
                    llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
                    llvm::LLVMSetSection(g, section.as_ptr());
                }
            }

            // Finalize debuginfo
1273
            if cx.sess().opts.debuginfo != DebugInfo::None {
1274
                debuginfo::finalize(&cx);
A
Alex Crichton 已提交
1275 1276
            }

1277
            cx.stats.into_inner()
A
Alex Crichton 已提交
1278 1279
        };

1280 1281 1282 1283 1284 1285
        (stats, ModuleCodegen {
            name: cgu_name,
            source: ModuleSource::Codegened(llvm_module),
            kind: ModuleKind::Regular,
            llmod_id,
        })
A
Alex Crichton 已提交
1286 1287 1288
    }
}

1289
pub fn provide(providers: &mut Providers) {
I
Irina Popa 已提交
1290 1291
    providers.collect_and_partition_mono_items =
        collect_and_partition_mono_items;
1292

I
Irina Popa 已提交
1293
    providers.is_codegened_item = is_codegened_item;
A
Alex Crichton 已提交
1294 1295

    providers.codegen_unit = |tcx, name| {
I
Irina Popa 已提交
1296
        let (_, all) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
A
Alex Crichton 已提交
1297 1298 1299
        all.iter()
            .find(|cgu| *cgu.name() == name)
            .cloned()
1300
            .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name))
A
Alex Crichton 已提交
1301 1302
    };
    providers.compile_codegen_unit = compile_codegen_unit;
1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335

    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)
    };
1336 1337
}

1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358
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,
1359
    }
1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372
}

// 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 已提交
1373
    use ModuleCodegen;
1374

I
Irina Popa 已提交
1375
    impl<HCX> HashStable<HCX> for ModuleCodegen {
1376 1377 1378 1379 1380
        fn hash_stable<W: StableHasherResult>(&self,
                                              _: &mut HCX,
                                              _: &mut StableHasher<W>) {
            // do nothing
        }
1381 1382
    }
}