base.rs 48.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 21
//!
//!   * There's no way to find out the Ty type of a ValueRef.  Doing so
//!     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::{TypeKind, ValueRef, get_param};
35
use llvm;
36
use metadata;
37
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
38
use rustc::middle::lang_items::StartFnLangItem;
39
use rustc::middle::weak_lang_items;
40 41
use rustc::mir::mono::{Linkage, Visibility, Stats};
use rustc::middle::cstore::{EncodedMetadata};
42
use rustc::ty::{self, Ty, TyCtxt};
43
use rustc::ty::layout::{self, Align, TyLayout, LayoutOf};
44
use rustc::ty::query::Providers;
45
use rustc::dep_graph::{DepNode, DepConstructor};
46
use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
47
use rustc::middle::exported_symbols;
48
use rustc::util::common::{time, print_time_passes_entry};
A
Alex Crichton 已提交
49
use rustc::session::config::{self, NoDebugInfo};
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
use mir::operand::OperandValue;
91

B
bjorn3 已提交
92 93
use rustc_codegen_utils::check_for_rustc_errors_attr;

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

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

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

C
csmoe 已提交
124
pub fn bin_op_to_icmp_predicate(op: hir::BinOpKind,
M
Ms2ger 已提交
125
                                signed: bool)
126 127
                                -> llvm::IntPredicate {
    match op {
C
csmoe 已提交
128 129 130 131 132 133
        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 },
134
        op => {
135 136 137
            bug!("comparison_op_to_icmp_predicate: expected comparison operator, \
                  found {:?}",
                 op)
138 139 140
        }
    }
}
141

C
csmoe 已提交
142
pub fn bin_op_to_fcmp_predicate(op: hir::BinOpKind) -> llvm::RealPredicate {
143
    match op {
C
csmoe 已提交
144 145 146 147 148 149
        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,
150
        op => {
151 152 153
            bug!("comparison_op_to_fcmp_predicate: expected comparison operator, \
                  found {:?}",
                 op);
154 155 156 157
        }
    }
}

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

176
    let cmp = bin_op_to_icmp_predicate(op, signed);
177 178 179 180
    // 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.
181
    bx.sext(bx.icmp(cmp, lhs, rhs), ret_ty)
182 183
}

A
Ariel Ben-Yehuda 已提交
184 185 186 187
/// 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 已提交
188
/// in an upcast, where the new vtable for an object will be derived
A
Ariel Ben-Yehuda 已提交
189
/// from the old one.
190
pub fn unsized_info<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>,
A
Ariel Ben-Yehuda 已提交
191 192
                                source: Ty<'tcx>,
                                target: Ty<'tcx>,
193
                                old_info: Option<ValueRef>)
A
Ariel Ben-Yehuda 已提交
194
                                -> ValueRef {
195
    let (source, target) = cx.tcx.struct_lockstep_tails(source, target);
A
Ariel Ben-Yehuda 已提交
196
    match (&source.sty, &target.sty) {
197
        (&ty::TyArray(_, len), &ty::TySlice(_)) => {
198
            C_usize(cx, len.unwrap_usize(cx.tcx))
199
        }
200
        (&ty::TyDynamic(..), &ty::TyDynamic(..)) => {
A
Ariel Ben-Yehuda 已提交
201 202 203 204 205
            // 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")
        }
206
        (_, &ty::TyDynamic(ref data, ..)) => {
207 208 209 210
            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 已提交
211
        }
212
        _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}",
A
Ariel Ben-Yehuda 已提交
213
                                     source,
214
                                     target),
A
Ariel Ben-Yehuda 已提交
215 216 217 218
    }
}

/// Coerce `src` to `dst_ty`. `src_ty` must be a thin pointer.
219 220
pub fn unsize_thin_ptr(
    bx: &Builder<'a, 'll, 'tcx>,
M
Mark Simulacrum 已提交
221 222 223 224
    src: ValueRef,
    src_ty: Ty<'tcx>,
    dst_ty: Ty<'tcx>
) -> (ValueRef, ValueRef) {
A
Ariel Ben-Yehuda 已提交
225 226
    debug!("unsize_thin_ptr: {:?} => {:?}", src_ty, dst_ty);
    match (&src_ty.sty, &dst_ty.sty) {
227 228 229
        (&ty::TyRef(_, a, _),
         &ty::TyRef(_, b, _)) |
        (&ty::TyRef(_, a, _),
A
Ariel Ben-Yehuda 已提交
230 231 232
         &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) |
        (&ty::TyRawPtr(ty::TypeAndMut { ty: a, .. }),
         &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) => {
233 234 235
            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 已提交
236
        }
237 238
        (&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());
239 240 241
            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))
242
        }
243 244 245
        (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => {
            assert_eq!(def_a, def_b);

246 247
            let src_layout = bx.cx.layout_of(src_ty);
            let dst_layout = bx.cx.layout_of(dst_ty);
248 249
            let mut result = None;
            for i in 0..src_layout.fields.count() {
250
                let src_f = src_layout.field(bx.cx, i);
251 252 253 254 255 256 257
                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);

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

/// 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`
274 275 276 277 278
pub fn coerce_unsized_into(
    bx: &Builder<'a, 'll, 'tcx>,
    src: PlaceRef<'tcx>,
    dst: PlaceRef<'tcx>
) {
279 280
    let src_ty = src.layout.ty;
    let dst_ty = dst.layout.ty;
281
    let coerce_ptr = || {
282
        let (base, info) = match src.load(bx).val {
283 284 285 286 287
            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.
288 289
                let thin_ptr = dst.layout.field(bx.cx, abi::FAT_PTR_ADDR);
                (bx.pointercast(base, thin_ptr.llvm_type(bx.cx)), info)
290 291
            }
            OperandValue::Immediate(base) => {
292
                unsize_thin_ptr(bx, base, src_ty, dst_ty)
293 294
            }
            OperandValue::Ref(..) => bug!()
295
        };
296
        OperandValue::Pair(base, info).store(bx, dst);
297
    };
A
Ariel Ben-Yehuda 已提交
298 299 300 301
    match (&src_ty.sty, &dst_ty.sty) {
        (&ty::TyRef(..), &ty::TyRef(..)) |
        (&ty::TyRef(..), &ty::TyRawPtr(..)) |
        (&ty::TyRawPtr(..), &ty::TyRawPtr(..)) => {
302 303 304 305
            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 已提交
306 307
        }

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

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

315
                if dst_f.layout.is_zst() {
M
Ms2ger 已提交
316 317
                    continue;
                }
A
Ariel Ben-Yehuda 已提交
318

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

333
pub fn cast_shift_expr_rhs(
C
csmoe 已提交
334
    cx: &Builder, op: hir::BinOpKind, lhs: ValueRef, rhs: ValueRef
335 336
) -> ValueRef {
    cast_shift_rhs(op, lhs, rhs, |a, b| cx.trunc(a, b), |a, b| cx.zext(a, b))
337 338
}

339
fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind,
340 341 342 343
                        lhs: ValueRef,
                        rhs: ValueRef,
                        trunc: F,
                        zext: G)
M
Ms2ger 已提交
344
                        -> ValueRef
345 346
    where F: FnOnce(ValueRef, &'ll Type) -> ValueRef,
          G: FnOnce(ValueRef, &'ll Type) -> ValueRef
347
{
348
    // Shifts may have any size int on the rhs
349
    if op.is_shift() {
350 351
        let mut rhs_llty = val_ty(rhs);
        let mut lhs_llty = val_ty(lhs);
352
        if rhs_llty.kind() == TypeKind::Vector {
M
Ms2ger 已提交
353 354
            rhs_llty = rhs_llty.element_type()
        }
355
        if lhs_llty.kind() == TypeKind::Vector {
M
Ms2ger 已提交
356 357
            lhs_llty = lhs_llty.element_type()
        }
358 359 360 361 362 363 364 365
        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)
366 367 368
        } else {
            rhs
        }
369 370
    } else {
        rhs
371 372 373
    }
}

374 375 376 377 378 379
/// 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 {
380
    sess.target.target.options.is_like_msvc
381 382
}

383
pub fn call_assume(bx: &Builder<'a, 'll, 'tcx>, val: ValueRef) {
384 385
    let assume_intrinsic = bx.cx.get_intrinsic("llvm.assume");
    bx.call(assume_intrinsic, &[val], None);
386 387
}

388 389 390
pub fn from_immediate(bx: &Builder, val: ValueRef) -> ValueRef {
    if val_ty(val) == Type::i1(bx.cx) {
        bx.zext(val, Type::i8(bx.cx))
391 392 393 394 395
    } else {
        val
    }
}

396
pub fn to_immediate(bx: &Builder, val: ValueRef, layout: layout::TyLayout) -> ValueRef {
397
    if let layout::Abi::Scalar(ref scalar) = layout.abi {
398 399 400 401 402 403 404 405
        return to_immediate_scalar(bx, val, scalar);
    }
    val
}

pub fn to_immediate_scalar(bx: &Builder, val: ValueRef, scalar: &layout::Scalar) -> ValueRef {
    if scalar.is_bool() {
        return bx.trunc(val, Type::i1(bx.cx));
406
    }
407
    val
408 409
}

410
pub fn call_memcpy(bx: &Builder,
411 412 413
                   dst: ValueRef,
                   src: ValueRef,
                   n_bytes: ValueRef,
414
                   align: Align,
415 416 417 418 419 420 421 422
                   flags: MemFlags) {
    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;
    }
423
    let cx = bx.cx;
424
    let ptr_width = &cx.sess().target.target.target_pointer_width;
425
    let key = format!("llvm.memcpy.p0i8.p0i8.i{}", ptr_width);
426
    let memcpy = cx.get_intrinsic(&key);
427 428 429
    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);
430
    let align = C_i32(cx, align.abi() as i32);
431
    let volatile = C_bool(cx, flags.contains(MemFlags::VOLATILE));
432
    bx.call(memcpy, &[dst_ptr, src_ptr, size, align, volatile], None);
433 434
}

435 436
pub fn memcpy_ty(
    bx: &Builder<'a, 'll, 'tcx>,
437 438
    dst: ValueRef,
    src: ValueRef,
439
    layout: TyLayout<'tcx>,
440
    align: Align,
441
    flags: MemFlags,
442
) {
443
    let size = layout.size.bytes();
444
    if size == 0 {
445 446 447
        return;
    }

448
    call_memcpy(bx, dst, src, C_usize(bx.cx, size), align, flags);
449 450
}

451 452 453 454 455 456 457 458
pub fn call_memset(
    bx: &Builder<'a, 'll, 'tcx>,
    ptr: ValueRef,
    fill_byte: ValueRef,
    size: ValueRef,
    align: ValueRef,
    volatile: bool,
) -> ValueRef {
459
    let ptr_width = &bx.cx.sess().target.target.target_pointer_width;
460
    let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
461 462 463
    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)
464 465
}

I
Irina Popa 已提交
466 467
pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tcx>) {
    let _s = if cx.sess().codegen_stats() {
468
        let mut instance_name = String::new();
469
        DefPathBasedNames::new(cx.tcx, true, true)
470
            .push_def_path(instance.def_id(), &mut instance_name);
471
        Some(StatRecorder::new(cx, instance_name))
472 473 474 475
    } else {
        None
    };

476 477 478
    // 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 已提交
479
    info!("codegen_instance({})", instance);
480

481 482
    let fn_ty = instance.ty(cx.tcx);
    let sig = common::ty_fn_sig(cx, fn_ty);
483
    let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
484

485
    let lldecl = match cx.instances.borrow().get(&instance) {
486 487 488 489
        Some(&val) => val,
        None => bug!("Instance `{:?}` not already declared", instance)
    };

490
    cx.stats.borrow_mut().n_closures += 1;
491

492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
    // 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
508
    if !cx.sess().no_landing_pads() ||
509
       cx.sess().target.target.options.requires_uwtable {
510
        attributes::emit_uwtable(lldecl, true);
511
    }
512

513
    let mir = cx.tcx.instance_mir(instance.def);
I
Irina Popa 已提交
514
    mir::codegen_mir(cx, lldecl, &mir, instance, sig);
515 516
}

517 518 519 520 521 522 523 524
pub fn set_link_section(llval: ValueRef, attrs: &CodegenFnAttrs) {
    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 已提交
525 526 527
    }
}

F
Fourchaux 已提交
528
/// Create the `main` function which will initialize the rust runtime and call
529
/// users main function.
530 531
fn maybe_create_entry_wrapper(cx: &CodegenCx) {
    let (main_def_id, span) = match *cx.sess().entry_fn.borrow() {
532
        Some((id, span, _)) => {
533
            (cx.tcx.hir.local_def_id(id), span)
534 535 536 537
        }
        None => return,
    };

538
    let instance = Instance::mono(cx.tcx, main_def_id);
539

540
    if !cx.codegen_unit.contains_item(&MonoItem::Fn(instance)) {
541 542 543
        // We want to create the wrapper in the same codegen unit as Rust's main
        // function.
        return;
544 545
    }

546
    let main_llfn = callee::get_fn(cx, instance);
547

548
    let et = cx.sess().entry_fn.get().map(|e| e.2);
549
    match et {
550 551 552
        Some(config::EntryMain) => create_entry_fn(cx, span, main_llfn, main_def_id, true),
        Some(config::EntryStart) => create_entry_fn(cx, span, main_llfn, main_def_id, false),
        None => {}    // Do nothing.
553
    }
554

555
    fn create_entry_fn<'cx>(cx: &'cx CodegenCx,
S
Simonas Kazlauskas 已提交
556
                       sp: Span,
557
                       rust_main: ValueRef,
558
                       rust_main_def_id: DefId,
559
                       use_start_lang_item: bool) {
560
        let llfty = Type::func(&[Type::c_int(cx), Type::i8p(cx).ptr_to()], Type::c_int(cx));
561

562
        let main_ret_ty = cx.tcx.fn_sig(rust_main_def_id).output();
563 564 565 566 567
        // 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.
568 569 570
        let main_ret_ty = cx.tcx.erase_regions(
            &main_ret_ty.no_late_bound_regions().unwrap(),
        );
K
kyeongwoon 已提交
571

572
        if declare::get_defined_value(cx, "main").is_some() {
S
Simonas Kazlauskas 已提交
573
            // FIXME: We should be smart and show a better diagnostic here.
574
            cx.sess().struct_span_err(sp, "entry symbol `main` defined multiple times")
N
Nick Cameron 已提交
575 576
                      .help("did you use #[no_mangle] on `fn main`? Use #[start] instead")
                      .emit();
577
            cx.sess().abort_if_errors();
578
            bug!();
579
        }
580
        let llfn = declare::declare_cfn(cx, "main", llfty);
581

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

585
        let bx = Builder::new_block(cx, llfn, "top");
586

587
        debuginfo::gdb::insert_reference_to_gdb_debug_scripts_section_global(&bx);
588

589 590 591
        // 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);
592
        let arg_argc = bx.intcast(param_argc, cx.isize_ty, true);
593 594
        let arg_argv = param_argv;

M
Mark-Simulacrum 已提交
595
        let (start_fn, args) = if use_start_lang_item {
596
            let start_def_id = cx.tcx.require_lang_item(StartFnLangItem);
597 598 599
            let start_fn = callee::resolve_and_get_fn(
                cx,
                start_def_id,
600
                cx.tcx.intern_substs(&[main_ret_ty.into()]),
601
            );
602
            (start_fn, vec![bx.pointercast(rust_main, Type::i8p(cx).ptr_to()),
603
                            arg_argc, arg_argv])
M
Mark-Simulacrum 已提交
604 605
        } else {
            debug!("using user-defined start fn");
606
            (rust_main, vec![arg_argc, arg_argv])
M
Mark-Simulacrum 已提交
607
        };
608

609 610
        let result = bx.call(start_fn, &args, None);
        bx.ret(bx.intcast(result, Type::c_int(cx), true));
M
Marijn Haverbeke 已提交
611
    }
612 613
}

614
fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
615
                            llvm_module: &ModuleLlvm,
616
                            link_meta: &LinkMeta)
617
                            -> EncodedMetadata {
A
Alex Crichton 已提交
618 619
    use std::io::Write;
    use flate2::Compression;
620
    use flate2::write::DeflateEncoder;
621

622
    let (metadata_llcx, metadata_llmod) = (&*llvm_module.llcx, llvm_module.llmod());
623

N
Nicholas Nethercote 已提交
624 625 626 627 628 629 630
    #[derive(PartialEq, Eq, PartialOrd, Ord)]
    enum MetadataKind {
        None,
        Uncompressed,
        Compressed
    }

631
    let kind = tcx.sess.crate_types.borrow().iter().map(|ty| {
N
Nicholas Nethercote 已提交
632 633 634 635 636
        match *ty {
            config::CrateTypeExecutable |
            config::CrateTypeStaticlib |
            config::CrateTypeCdylib => MetadataKind::None,

637
            config::CrateTypeRlib => MetadataKind::Uncompressed,
N
Nicholas Nethercote 已提交
638 639 640 641

            config::CrateTypeDylib |
            config::CrateTypeProcMacro => MetadataKind::Compressed,
        }
642
    }).max().unwrap_or(MetadataKind::None);
N
Nicholas Nethercote 已提交
643 644

    if kind == MetadataKind::None {
645
        return EncodedMetadata::new();
646
    }
J
James Miller 已提交
647

648
    let metadata = tcx.encode_metadata(link_meta);
N
Nicholas Nethercote 已提交
649
    if kind == MetadataKind::Uncompressed {
650
        return metadata;
N
Nicholas Nethercote 已提交
651 652 653
    }

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

658 659
    let llmeta = C_bytes_in_context(metadata_llcx, &compressed);
    let llconst = C_struct_in_context(metadata_llcx, &[llmeta], false);
660
    let name = exported_symbols::metadata_symbol_name(tcx);
661
    let buf = CString::new(name).unwrap();
A
Alex Crichton 已提交
662
    let llglobal = unsafe {
663
        llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst), buf.as_ptr())
A
Alex Crichton 已提交
664
    };
665 666
    unsafe {
        llvm::LLVMSetInitializer(llglobal, llconst);
667
        let section_name = metadata::metadata_section_name(&tcx.sess.target.target);
668 669 670 671 672 673 674 675
        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();
676
        llvm::LLVMSetModuleInlineAsm(metadata_llmod, directive.as_ptr())
677
    }
678
    return metadata;
679 680
}

681
pub struct ValueIter {
682 683 684
    cur: ValueRef,
    step: unsafe extern "C" fn(ValueRef) -> ValueRef,
}
685

686 687
impl Iterator for ValueIter {
    type Item = ValueRef;
688

689 690 691
    fn next(&mut self) -> Option<ValueRef> {
        let old = self.cur;
        if !old.is_null() {
692
            self.cur = unsafe { (self.step)(old) };
693 694 695 696
            Some(old)
        } else {
            None
        }
697
    }
698
}
699

700
pub fn iter_globals(llmod: &llvm::Module) -> ValueIter {
701 702 703 704 705 706 707
    unsafe {
        ValueIter {
            cur: llvm::LLVMGetFirstGlobal(llmod),
            step: llvm::LLVMGetNextGlobal,
        }
    }
}
J
Jorge Aparicio 已提交
708

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

B
bjorn3 已提交
713
    check_for_rustc_errors_attr(tcx);
714

715
    if let Some(true) = tcx.sess.opts.debugging_opts.thinlto {
A
Alex Crichton 已提交
716 717 718 719
        if unsafe { !llvm::LLVMRustThinLTOAvailable() } {
            tcx.sess.fatal("this compiler's LLVM does not support ThinLTO");
        }
    }
720

721 722 723 724 725 726 727
    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");
    }

728
    let crate_hash = tcx.crate_hash(LOCAL_CRATE);
729
    let link_meta = link::build_link_meta(crate_hash);
730

I
Irina Popa 已提交
731
    // Codegen the metadata.
732
    let llmod_id = "metadata";
733 734 735 736
    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)
    });
737

I
Irina Popa 已提交
738
    let metadata_module = ModuleCodegen {
739 740
        name: link::METADATA_MODULE_NAME.to_string(),
        llmod_id: llmod_id.to_string(),
741
        source: ModuleSource::Codegened(metadata_llvm_module),
742
        kind: ModuleKind::Metadata,
743
    };
744

I
Irina Popa 已提交
745
    let time_graph = if tcx.sess.opts.debugging_opts.codegen_time_graph {
746 747 748 749
        Some(time_graph::TimeGraph::new())
    } else {
        None
    };
750

I
Irina Popa 已提交
751 752 753 754
    // 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(
755
            tcx,
756
            time_graph.clone(),
757
            link_meta,
758
            metadata,
A
Alex Crichton 已提交
759 760
            rx,
            1);
761

I
Irina Popa 已提交
762 763
        ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module);
        ongoing_codegen.codegen_finished(tcx);
764

765
        assert_and_save_dep_graph(tcx);
766

I
Irina Popa 已提交
767
        ongoing_codegen.check_for_errors(tcx.sess);
768

I
Irina Popa 已提交
769
        return ongoing_codegen;
770 771
    }

I
Irina Popa 已提交
772
    // Run the monomorphization collector and partition the collected items into
773
    // codegen units.
774
    let codegen_units =
I
Irina Popa 已提交
775
        tcx.collect_and_partition_mono_items(LOCAL_CRATE).1;
776
    let codegen_units = (*codegen_units).clone();
777

778 779 780 781 782 783 784 785 786 787 788
    // 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 已提交
789
    let ongoing_codegen = write::start_async_codegen(
790
        tcx,
791
        time_graph.clone(),
792
        link_meta,
793
        metadata,
A
Alex Crichton 已提交
794 795
        rx,
        codegen_units.len());
796

I
Irina Popa 已提交
797
    // Codegen an allocator shim, if any
798
    let allocator_module = if let Some(kind) = *tcx.sess.allocator_kind.get() {
799 800
        unsafe {
            let llmod_id = "allocator";
801
            let modules = ModuleLlvm::new(tcx.sess, llmod_id);
802
            time(tcx.sess, "write allocator module", || {
I
Irina Popa 已提交
803
                allocator::codegen(tcx, &modules, kind)
804
            });
805

806 807 808 809 810 811 812
            Some(ModuleCodegen {
                name: link::ALLOCATOR_MODULE_NAME.to_string(),
                llmod_id: llmod_id.to_string(),
                source: ModuleSource::Codegened(modules),
                kind: ModuleKind::Allocator,
            })
        }
813 814 815 816 817
    } else {
        None
    };

    if let Some(allocator_module) = allocator_module {
I
Irina Popa 已提交
818
        ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, allocator_module);
819 820
    }

I
Irina Popa 已提交
821
    ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module);
822

823
    // We sort the codegen units by size. This way we can schedule work for LLVM
824
    // a bit more efficiently.
825 826
    let codegen_units = {
        let mut codegen_units = codegen_units;
V
varkor 已提交
827
        codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
828 829 830
        codegen_units
    };

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

A
Alex Crichton 已提交
834
    for cgu in codegen_units.into_iter() {
I
Irina Popa 已提交
835 836
        ongoing_codegen.wait_for_signal_to_codegen_item();
        ongoing_codegen.check_for_errors(tcx.sess);
837

838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854
        // 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) {
855 856 857 858 859 860 861 862 863 864
                    // 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 已提交
865
                    let module = ModuleCodegen {
866 867 868
                        name: cgu.name().to_string(),
                        source: ModuleSource::Preexisting(buf),
                        kind: ModuleKind::Regular,
869
                        llmod_id,
870 871
                    };
                    tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true);
I
Irina Popa 已提交
872
                    write::submit_codegened_module_to_llvm(tcx, module, 0);
873 874 875 876 877 878 879 880 881
                    // 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.
            }
        }

882
        let _timing_guard = time_graph.as_ref().map(|time_graph| {
I
Irina Popa 已提交
883 884
            time_graph.start(write::CODEGEN_WORKER_TIMELINE,
                             write::CODEGEN_WORK_PACKAGE_KIND,
885 886
                             &format!("codegen {}", cgu.name()))
        });
887
        let start_time = Instant::now();
A
Alex Crichton 已提交
888
        all_stats.extend(tcx.compile_codegen_unit(*cgu.name()));
I
Irina Popa 已提交
889 890
        total_codegen_time += start_time.elapsed();
        ongoing_codegen.check_for_errors(tcx.sess);
891 892
    }

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

I
Irina Popa 已提交
895
    // Since the main thread is sometimes blocked during codegen, we keep track
896 897
    // -Ztime-passes output manually.
    print_time_passes_entry(tcx.sess.time_passes(),
I
Irina Popa 已提交
898 899
                            "codegen to LLVM IR",
                            total_codegen_time);
900

A
Alex Crichton 已提交
901
    if tcx.sess.opts.incremental.is_some() {
902
        ::rustc_incremental::assert_module_sources::assert_module_sources(tcx);
903 904
    }

N
Niko Matsakis 已提交
905
    symbol_names_test::report_symbol_names(tcx);
906

I
Irina Popa 已提交
907 908
    if tcx.sess.codegen_stats() {
        println!("--- codegen stats ---");
A
Alex Crichton 已提交
909 910 911
        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);
912

A
Alex Crichton 已提交
913 914 915
        println!("n_fns: {}", all_stats.n_fns);
        println!("n_inlines: {}", all_stats.n_inlines);
        println!("n_closures: {}", all_stats.n_closures);
916
        println!("fn stats:");
A
Alex Crichton 已提交
917 918 919
        all_stats.fn_stats.sort_by_key(|&(_, insns)| insns);
        for &(ref name, insns) in all_stats.fn_stats.iter() {
            println!("{} insns, {}", insns, *name);
920
        }
J
James Miller 已提交
921
    }
922

923
    if tcx.sess.count_llvm_insns() {
A
Alex Crichton 已提交
924
        for (k, v) in all_stats.llvm_insns.iter() {
A
Alex Crichton 已提交
925
            println!("{:7} {}", *v, *k);
926 927 928
        }
    }

I
Irina Popa 已提交
929
    ongoing_codegen.check_for_errors(tcx.sess);
930

931
    assert_and_save_dep_graph(tcx);
I
Irina Popa 已提交
932
    ongoing_codegen
933
}
934

935
fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
936
    time(tcx.sess,
937 938 939
         "assert dep graph",
         || rustc_incremental::assert_dep_graph(tcx));

940
    time(tcx.sess,
941
         "serialize dep graph",
942
         || rustc_incremental::save_dep_graph(tcx));
943 944
}

I
Irina Popa 已提交
945
fn collect_and_partition_mono_items<'a, 'tcx>(
946 947
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    cnum: CrateNum,
948
) -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>)
949 950
{
    assert_eq!(cnum, LOCAL_CRATE);
951

I
Irina Popa 已提交
952
    let collection_mode = match tcx.sess.opts.debugging_opts.print_mono_items {
953 954 955 956
        Some(ref s) => {
            let mode_string = s.to_lowercase();
            let mode_string = mode_string.trim();
            if mode_string == "eager" {
957
                MonoItemCollectionMode::Eager
958 959 960 961 962
            } else {
                if mode_string != "lazy" {
                    let message = format!("Unknown codegen-item collection mode '{}'. \
                                           Falling back to 'lazy' mode.",
                                           mode_string);
963
                    tcx.sess.warn(&message);
964 965
                }

966
                MonoItemCollectionMode::Lazy
967 968
            }
        }
969 970 971 972 973 974 975
        None => {
            if tcx.sess.opts.cg.link_dead_code {
                MonoItemCollectionMode::Eager
            } else {
                MonoItemCollectionMode::Lazy
            }
        }
976 977
    };

978
    let (items, inlining_map) =
I
Irina Popa 已提交
979
        time(tcx.sess, "monomorphization collection", || {
980
            collector::collect_crate_mono_items(tcx, collection_mode)
981 982
    });

983 984
    tcx.sess.abort_if_errors();

985
    ::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx, items.iter());
986

987
    let strategy = if tcx.sess.opts.incremental.is_some() {
988 989
        PartitioningStrategy::PerModule
    } else {
990
        PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units())
991 992
    };

993
    let codegen_units = time(tcx.sess, "codegen unit partitioning", || {
994
        partitioning::partition(tcx,
995 996
                                items.iter().cloned(),
                                strategy,
997
                                &inlining_map)
998 999 1000
            .into_iter()
            .map(Arc::new)
            .collect::<Vec<_>>()
1001 1002
    });

I
Irina Popa 已提交
1003 1004
    let mono_items: DefIdSet = items.iter().filter_map(|mono_item| {
        match *mono_item {
M
Maik Klein 已提交
1005
            MonoItem::Fn(ref instance) => Some(instance.def_id()),
1006
            MonoItem::Static(def_id) => Some(def_id),
1007 1008 1009
            _ => None,
        }
    }).collect();
1010

I
Irina Popa 已提交
1011
    if tcx.sess.opts.debugging_opts.print_mono_items.is_some() {
1012
        let mut item_to_cgus = FxHashMap();
1013

1014
        for cgu in &codegen_units {
I
Irina Popa 已提交
1015 1016
            for (&mono_item, &linkage) in cgu.items() {
                item_to_cgus.entry(mono_item)
1017
                            .or_insert(Vec::new())
1018
                            .push((cgu.name().clone(), linkage));
1019 1020 1021 1022 1023 1024
            }
        }

        let mut item_keys: Vec<_> = items
            .iter()
            .map(|i| {
1025
                let mut output = i.to_string(tcx);
1026 1027
                output.push_str(" @@");
                let mut empty = Vec::new();
1028
                let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
1029 1030
                cgus.as_mut_slice().sort_by_key(|&(ref name, _)| name.clone());
                cgus.dedup();
1031
                for &(ref cgu_name, (linkage, _)) in cgus.iter() {
1032
                    output.push_str(" ");
1033
                    output.push_str(&cgu_name.as_str());
1034 1035

                    let linkage_abbrev = match linkage {
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
                        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",
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
                    };

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

1057 1058 1059
        item_keys.sort();

        for item in item_keys {
I
Irina Popa 已提交
1060
            println!("MONO_ITEM {}", item);
1061 1062
        }
    }
1063

I
Irina Popa 已提交
1064
    (Arc::new(mono_items), Arc::new(codegen_units))
1065
}
1066 1067

impl CrateInfo {
1068
    pub fn new(tcx: TyCtxt) -> CrateInfo {
1069 1070 1071 1072 1073 1074
        let mut info = CrateInfo {
            panic_runtime: None,
            compiler_builtins: None,
            profiler_runtime: None,
            sanitizer_runtime: None,
            is_no_builtins: FxHashSet(),
1075
            native_libraries: FxHashMap(),
1076 1077
            used_libraries: tcx.native_libraries(LOCAL_CRATE),
            link_args: tcx.link_args(LOCAL_CRATE),
1078
            crate_name: FxHashMap(),
1079 1080 1081
            used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic),
            used_crates_static: cstore::used_crates(tcx, LinkagePreference::RequireStatic),
            used_crate_source: FxHashMap(),
1082
            wasm_imports: FxHashMap(),
1083 1084
            lang_item_to_crate: FxHashMap(),
            missing_lang_items: FxHashMap(),
1085
        };
1086
        let lang_items = tcx.lang_items();
1087

1088
        let load_wasm_items = tcx.sess.crate_types.borrow()
1089 1090
            .iter()
            .any(|c| *c != config::CrateTypeRlib) &&
1091
            tcx.sess.opts.target_triple.triple() == "wasm32-unknown-unknown";
1092

1093 1094
        if load_wasm_items {
            info.load_wasm_imports(tcx, LOCAL_CRATE);
1095 1096
        }

1097
        for &cnum in tcx.crates().iter() {
1098
            info.native_libraries.insert(cnum, tcx.native_libraries(cnum));
1099
            info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string());
1100
            info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum));
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115
            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);
            }
1116 1117
            if load_wasm_items {
                info.load_wasm_imports(tcx, cnum);
1118
            }
1119 1120 1121 1122 1123 1124
            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);
                }
            }
1125 1126 1127 1128 1129 1130 1131

            // 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();
1132
            info.missing_lang_items.insert(cnum, missing);
1133 1134 1135 1136
        }

        return info
    }
1137 1138 1139 1140 1141 1142 1143 1144

    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());
        }
    }
1145
}
1146

I
Irina Popa 已提交
1147 1148 1149 1150
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)
1151 1152
}

A
Alex Crichton 已提交
1153 1154
fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  cgu: InternedString) -> Stats {
1155
    let cgu = tcx.codegen_unit(cgu);
A
Alex Crichton 已提交
1156 1157

    let start_time = Instant::now();
I
Irina Popa 已提交
1158 1159
    let (stats, module) = module_codegen(tcx, cgu);
    let time_to_codegen = start_time.elapsed();
A
Alex Crichton 已提交
1160 1161

    // We assume that the cost to run LLVM on a CGU is proportional to
I
Irina Popa 已提交
1162 1163 1164
    // 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 已提交
1165

I
Irina Popa 已提交
1166
    write::submit_codegened_module_to_llvm(tcx,
A
Alex Crichton 已提交
1167 1168 1169 1170
                                            module,
                                            cost);
    return stats;

I
Irina Popa 已提交
1171
    fn module_codegen<'a, 'tcx>(
1172 1173
        tcx: TyCtxt<'a, 'tcx, 'tcx>,
        cgu: Arc<CodegenUnit<'tcx>>)
I
Irina Popa 已提交
1174
        -> (Stats, ModuleCodegen)
A
Alex Crichton 已提交
1175 1176 1177
    {
        let cgu_name = cgu.name().to_string();

1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
        // 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 已提交
1191
        // Instantiate monomorphizations without filling out definitions yet...
1192 1193 1194
        let llvm_module = ModuleLlvm::new(tcx.sess, &llmod_id);
        let stats = {
            let cx = CodegenCx::new(tcx, cgu, &llvm_module);
I
Irina Popa 已提交
1195
            let mono_items = cx.codegen_unit
1196
                                 .items_in_deterministic_order(cx.tcx);
I
Irina Popa 已提交
1197 1198
            for &(mono_item, (linkage, visibility)) in &mono_items {
                mono_item.predefine(&cx, linkage, visibility);
A
Alex Crichton 已提交
1199 1200 1201
            }

            // ... and now that we have everything pre-defined, fill out those definitions.
I
Irina Popa 已提交
1202 1203
            for &(mono_item, _) in &mono_items {
                mono_item.define(&cx);
A
Alex Crichton 已提交
1204 1205 1206 1207
            }

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

            // Run replace-all-uses-with for statics that need it
1211
            for &(old_g, new_g) in cx.statics_to_rauw.borrow().iter() {
A
Alex Crichton 已提交
1212
                unsafe {
1213
                    let bitcast = llvm::LLVMConstPointerCast(new_g, val_ty(old_g));
A
Alex Crichton 已提交
1214 1215 1216 1217 1218 1219 1220
                    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
1221
            if !cx.used_statics.borrow().is_empty() {
A
Alex Crichton 已提交
1222 1223
                let name = CString::new("llvm.used").unwrap();
                let section = CString::new("llvm.metadata").unwrap();
1224
                let array = C_array(Type::i8(&cx).ptr_to(), &*cx.used_statics.borrow());
A
Alex Crichton 已提交
1225 1226

                unsafe {
1227
                    let g = llvm::LLVMAddGlobal(cx.llmod,
1228
                                                val_ty(array),
A
Alex Crichton 已提交
1229 1230 1231 1232 1233 1234 1235 1236
                                                name.as_ptr());
                    llvm::LLVMSetInitializer(g, array);
                    llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
                    llvm::LLVMSetSection(g, section.as_ptr());
                }
            }

            // Finalize debuginfo
1237 1238
            if cx.sess().opts.debuginfo != NoDebugInfo {
                debuginfo::finalize(&cx);
A
Alex Crichton 已提交
1239 1240
            }

1241
            cx.stats.into_inner()
A
Alex Crichton 已提交
1242 1243
        };

1244 1245 1246 1247 1248 1249
        (stats, ModuleCodegen {
            name: cgu_name,
            source: ModuleSource::Codegened(llvm_module),
            kind: ModuleKind::Regular,
            llmod_id,
        })
A
Alex Crichton 已提交
1250 1251 1252
    }
}

1253
pub fn provide(providers: &mut Providers) {
I
Irina Popa 已提交
1254 1255
    providers.collect_and_partition_mono_items =
        collect_and_partition_mono_items;
1256

I
Irina Popa 已提交
1257
    providers.is_codegened_item = is_codegened_item;
A
Alex Crichton 已提交
1258 1259

    providers.codegen_unit = |tcx, name| {
I
Irina Popa 已提交
1260
        let (_, all) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
A
Alex Crichton 已提交
1261 1262 1263
        all.iter()
            .find(|cgu| *cgu.name() == name)
            .cloned()
1264
            .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name))
A
Alex Crichton 已提交
1265 1266
    };
    providers.compile_codegen_unit = compile_codegen_unit;
1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299

    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)
    };
1300 1301
}

1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322
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,
1323
    }
1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336
}

// 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 已提交
1337
    use ModuleCodegen;
1338

I
Irina Popa 已提交
1339
    impl<HCX> HashStable<HCX> for ModuleCodegen {
1340 1341 1342 1343 1344
        fn hash_stable<W: StableHasherResult>(&self,
                                              _: &mut HCX,
                                              _: &mut StableHasher<W>) {
            // do nothing
        }
1345 1346
    }
}