]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/trans/base.rs
unit-test symbol-names and item-paths
[rust.git] / src / librustc_trans / trans / base.rs
1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Translate the completed AST to the LLVM IR.
12 //!
13 //! Some functions here, such as trans_block and trans_expr, return a value --
14 //! the result of the translation to LLVM -- while others, such as trans_fn
15 //! and trans_item, are called only for the side effect of adding a
16 //! particular definition to the LLVM IR output we're producing.
17 //!
18 //! Hopefully useful general knowledge about trans:
19 //!
20 //!   * There's no way to find out the Ty type of a ValueRef.  Doing so
21 //!     would be "trying to get the eggs out of an omelette" (credit:
22 //!     pcwalton).  You can, instead, find out its TypeRef by calling val_ty,
23 //!     but one TypeRef corresponds to many `Ty`s; for instance, tup(int, int,
24 //!     int) and rec(x=int, y=int, z=int) will have the same TypeRef.
25
26 #![allow(non_camel_case_types)]
27
28 pub use self::ValueOrigin::*;
29
30 use super::CrateTranslation;
31 use super::ModuleTranslation;
32
33 use back::{link, symbol_names};
34 use lint;
35 use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param};
36 use llvm;
37 use middle::cfg;
38 use middle::cstore::CrateStore;
39 use middle::def_id::DefId;
40 use middle::infer;
41 use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
42 use middle::weak_lang_items;
43 use middle::pat_util::simple_name;
44 use middle::subst::{self, Substs};
45 use middle::traits;
46 use middle::ty::{self, Ty, TyCtxt, TypeFoldable};
47 use middle::ty::adjustment::CustomCoerceUnsized;
48 use rustc::dep_graph::DepNode;
49 use rustc::front::map as hir_map;
50 use rustc::util::common::time;
51 use rustc::mir::mir_map::MirMap;
52 use session::config::{self, NoDebugInfo, FullDebugInfo};
53 use session::Session;
54 use trans::_match;
55 use trans::abi::{self, Abi, FnType};
56 use trans::adt;
57 use trans::assert_dep_graph;
58 use trans::attributes;
59 use trans::build::*;
60 use trans::builder::{Builder, noname};
61 use trans::callee::{Callee, CallArgs, ArgExprs, ArgVals};
62 use trans::cleanup::{self, CleanupMethods, DropHint};
63 use trans::closure;
64 use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_int, C_uint, C_integral};
65 use trans::collector::{self, TransItem, TransItemState, TransItemCollectionMode};
66 use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef};
67 use trans::common::{CrateContext, DropFlagHintsMap, Field, FunctionContext};
68 use trans::common::{Result, NodeIdAndSpan, VariantInfo};
69 use trans::common::{node_id_type, fulfill_obligation};
70 use trans::common::{type_is_immediate, type_is_zero_size, val_ty};
71 use trans::common;
72 use trans::consts;
73 use trans::context::SharedCrateContext;
74 use trans::controlflow;
75 use trans::datum;
76 use trans::debuginfo::{self, DebugLoc, ToDebugLoc};
77 use trans::declare;
78 use trans::expr;
79 use trans::glue;
80 use trans::inline;
81 use trans::intrinsic;
82 use trans::link_guard;
83 use trans::machine;
84 use trans::machine::{llalign_of_min, llsize_of, llsize_of_real};
85 use trans::meth;
86 use trans::mir;
87 use trans::monomorphize::{self, Instance};
88 use trans::symbol_names_test;
89 use trans::tvec;
90 use trans::type_::Type;
91 use trans::type_of;
92 use trans::type_of::*;
93 use trans::value::Value;
94 use trans::Disr;
95 use util::common::indenter;
96 use util::sha2::Sha256;
97 use util::nodemap::{NodeMap, NodeSet};
98
99 use arena::TypedArena;
100 use libc::c_uint;
101 use std::ffi::{CStr, CString};
102 use std::cell::{Cell, RefCell};
103 use std::collections::{HashMap, HashSet};
104 use std::str;
105 use std::{i8, i16, i32, i64};
106 use syntax::codemap::{Span, DUMMY_SP};
107 use syntax::parse::token::InternedString;
108 use syntax::attr::AttrMetaMethods;
109 use syntax::attr;
110 use rustc_front;
111 use rustc_front::intravisit::{self, Visitor};
112 use rustc_front::hir;
113 use syntax::ast;
114
115 thread_local! {
116     static TASK_LOCAL_INSN_KEY: RefCell<Option<Vec<&'static str>>> = {
117         RefCell::new(None)
118     }
119 }
120
121 pub fn with_insn_ctxt<F>(blk: F)
122     where F: FnOnce(&[&'static str])
123 {
124     TASK_LOCAL_INSN_KEY.with(move |slot| {
125         slot.borrow().as_ref().map(move |s| blk(s));
126     })
127 }
128
129 pub fn init_insn_ctxt() {
130     TASK_LOCAL_INSN_KEY.with(|slot| {
131         *slot.borrow_mut() = Some(Vec::new());
132     });
133 }
134
135 pub struct _InsnCtxt {
136     _cannot_construct_outside_of_this_module: (),
137 }
138
139 impl Drop for _InsnCtxt {
140     fn drop(&mut self) {
141         TASK_LOCAL_INSN_KEY.with(|slot| {
142             match slot.borrow_mut().as_mut() {
143                 Some(ctx) => {
144                     ctx.pop();
145                 }
146                 None => {}
147             }
148         })
149     }
150 }
151
152 pub fn push_ctxt(s: &'static str) -> _InsnCtxt {
153     debug!("new InsnCtxt: {}", s);
154     TASK_LOCAL_INSN_KEY.with(|slot| {
155         if let Some(ctx) = slot.borrow_mut().as_mut() {
156             ctx.push(s)
157         }
158     });
159     _InsnCtxt {
160         _cannot_construct_outside_of_this_module: (),
161     }
162 }
163
164 pub struct StatRecorder<'a, 'tcx: 'a> {
165     ccx: &'a CrateContext<'a, 'tcx>,
166     name: Option<String>,
167     istart: usize,
168 }
169
170 impl<'a, 'tcx> StatRecorder<'a, 'tcx> {
171     pub fn new(ccx: &'a CrateContext<'a, 'tcx>, name: String) -> StatRecorder<'a, 'tcx> {
172         let istart = ccx.stats().n_llvm_insns.get();
173         StatRecorder {
174             ccx: ccx,
175             name: Some(name),
176             istart: istart,
177         }
178     }
179 }
180
181 impl<'a, 'tcx> Drop for StatRecorder<'a, 'tcx> {
182     fn drop(&mut self) {
183         if self.ccx.sess().trans_stats() {
184             let iend = self.ccx.stats().n_llvm_insns.get();
185             self.ccx
186                 .stats()
187                 .fn_stats
188                 .borrow_mut()
189                 .push((self.name.take().unwrap(), iend - self.istart));
190             self.ccx.stats().n_fns.set(self.ccx.stats().n_fns.get() + 1);
191             // Reset LLVM insn count to avoid compound costs.
192             self.ccx.stats().n_llvm_insns.set(self.istart);
193         }
194     }
195 }
196
197 pub fn kind_for_closure(ccx: &CrateContext, closure_id: DefId) -> ty::ClosureKind {
198     *ccx.tcx().tables.borrow().closure_kinds.get(&closure_id).unwrap()
199 }
200
201 fn require_alloc_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, info_ty: Ty<'tcx>, it: LangItem) -> DefId {
202     match bcx.tcx().lang_items.require(it) {
203         Ok(id) => id,
204         Err(s) => {
205             bcx.sess().fatal(&format!("allocation of `{}` {}", info_ty, s));
206         }
207     }
208 }
209
210 // The following malloc_raw_dyn* functions allocate a box to contain
211 // a given type, but with a potentially dynamic size.
212
213 pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
214                                   llty_ptr: Type,
215                                   info_ty: Ty<'tcx>,
216                                   size: ValueRef,
217                                   align: ValueRef,
218                                   debug_loc: DebugLoc)
219                                   -> Result<'blk, 'tcx> {
220     let _icx = push_ctxt("malloc_raw_exchange");
221
222     // Allocate space:
223     let def_id = require_alloc_fn(bcx, info_ty, ExchangeMallocFnLangItem);
224     let r = Callee::def(bcx.ccx(), def_id, bcx.tcx().mk_substs(Substs::empty()))
225         .call(bcx, debug_loc, ArgVals(&[size, align]), None);
226
227     Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr))
228 }
229
230
231 pub fn bin_op_to_icmp_predicate(ccx: &CrateContext,
232                                 op: hir::BinOp_,
233                                 signed: bool)
234                                 -> llvm::IntPredicate {
235     match op {
236         hir::BiEq => llvm::IntEQ,
237         hir::BiNe => llvm::IntNE,
238         hir::BiLt => if signed { llvm::IntSLT } else { llvm::IntULT },
239         hir::BiLe => if signed { llvm::IntSLE } else { llvm::IntULE },
240         hir::BiGt => if signed { llvm::IntSGT } else { llvm::IntUGT },
241         hir::BiGe => if signed { llvm::IntSGE } else { llvm::IntUGE },
242         op => {
243             ccx.sess()
244                .bug(&format!("comparison_op_to_icmp_predicate: expected comparison operator, \
245                               found {:?}",
246                              op));
247         }
248     }
249 }
250
251 pub fn bin_op_to_fcmp_predicate(ccx: &CrateContext, op: hir::BinOp_) -> llvm::RealPredicate {
252     match op {
253         hir::BiEq => llvm::RealOEQ,
254         hir::BiNe => llvm::RealUNE,
255         hir::BiLt => llvm::RealOLT,
256         hir::BiLe => llvm::RealOLE,
257         hir::BiGt => llvm::RealOGT,
258         hir::BiGe => llvm::RealOGE,
259         op => {
260             ccx.sess()
261                .bug(&format!("comparison_op_to_fcmp_predicate: expected comparison operator, \
262                               found {:?}",
263                              op));
264         }
265     }
266 }
267
268 pub fn compare_fat_ptrs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
269                                     lhs_addr: ValueRef,
270                                     lhs_extra: ValueRef,
271                                     rhs_addr: ValueRef,
272                                     rhs_extra: ValueRef,
273                                     _t: Ty<'tcx>,
274                                     op: hir::BinOp_,
275                                     debug_loc: DebugLoc)
276                                     -> ValueRef {
277     match op {
278         hir::BiEq => {
279             let addr_eq = ICmp(bcx, llvm::IntEQ, lhs_addr, rhs_addr, debug_loc);
280             let extra_eq = ICmp(bcx, llvm::IntEQ, lhs_extra, rhs_extra, debug_loc);
281             And(bcx, addr_eq, extra_eq, debug_loc)
282         }
283         hir::BiNe => {
284             let addr_eq = ICmp(bcx, llvm::IntNE, lhs_addr, rhs_addr, debug_loc);
285             let extra_eq = ICmp(bcx, llvm::IntNE, lhs_extra, rhs_extra, debug_loc);
286             Or(bcx, addr_eq, extra_eq, debug_loc)
287         }
288         hir::BiLe | hir::BiLt | hir::BiGe | hir::BiGt => {
289             // a OP b ~ a.0 STRICT(OP) b.0 | (a.0 == b.0 && a.1 OP a.1)
290             let (op, strict_op) = match op {
291                 hir::BiLt => (llvm::IntULT, llvm::IntULT),
292                 hir::BiLe => (llvm::IntULE, llvm::IntULT),
293                 hir::BiGt => (llvm::IntUGT, llvm::IntUGT),
294                 hir::BiGe => (llvm::IntUGE, llvm::IntUGT),
295                 _ => unreachable!(),
296             };
297
298             let addr_eq = ICmp(bcx, llvm::IntEQ, lhs_addr, rhs_addr, debug_loc);
299             let extra_op = ICmp(bcx, op, lhs_extra, rhs_extra, debug_loc);
300             let addr_eq_extra_op = And(bcx, addr_eq, extra_op, debug_loc);
301
302             let addr_strict = ICmp(bcx, strict_op, lhs_addr, rhs_addr, debug_loc);
303             Or(bcx, addr_strict, addr_eq_extra_op, debug_loc)
304         }
305         _ => {
306             bcx.tcx().sess.bug("unexpected fat ptr binop");
307         }
308     }
309 }
310
311 pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
312                                         lhs: ValueRef,
313                                         rhs: ValueRef,
314                                         t: Ty<'tcx>,
315                                         op: hir::BinOp_,
316                                         debug_loc: DebugLoc)
317                                         -> ValueRef {
318     match t.sty {
319         ty::TyTuple(ref tys) if tys.is_empty() => {
320             // We don't need to do actual comparisons for nil.
321             // () == () holds but () < () does not.
322             match op {
323                 hir::BiEq | hir::BiLe | hir::BiGe => return C_bool(bcx.ccx(), true),
324                 hir::BiNe | hir::BiLt | hir::BiGt => return C_bool(bcx.ccx(), false),
325                 // refinements would be nice
326                 _ => bcx.sess().bug("compare_scalar_types: must be a comparison operator"),
327             }
328         }
329         ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyBool | ty::TyUint(_) | ty::TyChar => {
330             ICmp(bcx,
331                  bin_op_to_icmp_predicate(bcx.ccx(), op, false),
332                  lhs,
333                  rhs,
334                  debug_loc)
335         }
336         ty::TyRawPtr(mt) if common::type_is_sized(bcx.tcx(), mt.ty) => {
337             ICmp(bcx,
338                  bin_op_to_icmp_predicate(bcx.ccx(), op, false),
339                  lhs,
340                  rhs,
341                  debug_loc)
342         }
343         ty::TyRawPtr(_) => {
344             let lhs_addr = Load(bcx, GEPi(bcx, lhs, &[0, abi::FAT_PTR_ADDR]));
345             let lhs_extra = Load(bcx, GEPi(bcx, lhs, &[0, abi::FAT_PTR_EXTRA]));
346
347             let rhs_addr = Load(bcx, GEPi(bcx, rhs, &[0, abi::FAT_PTR_ADDR]));
348             let rhs_extra = Load(bcx, GEPi(bcx, rhs, &[0, abi::FAT_PTR_EXTRA]));
349             compare_fat_ptrs(bcx,
350                              lhs_addr,
351                              lhs_extra,
352                              rhs_addr,
353                              rhs_extra,
354                              t,
355                              op,
356                              debug_loc)
357         }
358         ty::TyInt(_) => {
359             ICmp(bcx,
360                  bin_op_to_icmp_predicate(bcx.ccx(), op, true),
361                  lhs,
362                  rhs,
363                  debug_loc)
364         }
365         ty::TyFloat(_) => {
366             FCmp(bcx,
367                  bin_op_to_fcmp_predicate(bcx.ccx(), op),
368                  lhs,
369                  rhs,
370                  debug_loc)
371         }
372         // Should never get here, because t is scalar.
373         _ => bcx.sess().bug("non-scalar type passed to compare_scalar_types"),
374     }
375 }
376
377 pub fn compare_simd_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
378                                       lhs: ValueRef,
379                                       rhs: ValueRef,
380                                       t: Ty<'tcx>,
381                                       ret_ty: Type,
382                                       op: hir::BinOp_,
383                                       debug_loc: DebugLoc)
384                                       -> ValueRef {
385     let signed = match t.sty {
386         ty::TyFloat(_) => {
387             let cmp = bin_op_to_fcmp_predicate(bcx.ccx(), op);
388             return SExt(bcx, FCmp(bcx, cmp, lhs, rhs, debug_loc), ret_ty);
389         },
390         ty::TyUint(_) => false,
391         ty::TyInt(_) => true,
392         _ => bcx.sess().bug("compare_simd_types: invalid SIMD type"),
393     };
394
395     let cmp = bin_op_to_icmp_predicate(bcx.ccx(), op, signed);
396     // LLVM outputs an `< size x i1 >`, so we need to perform a sign extension
397     // to get the correctly sized type. This will compile to a single instruction
398     // once the IR is converted to assembly if the SIMD instruction is supported
399     // by the target architecture.
400     SExt(bcx, ICmp(bcx, cmp, lhs, rhs, debug_loc), ret_ty)
401 }
402
403 // Iterates through the elements of a structural type.
404 pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
405                                          av: ValueRef,
406                                          t: Ty<'tcx>,
407                                          mut f: F)
408                                          -> Block<'blk, 'tcx>
409     where F: FnMut(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>
410 {
411     let _icx = push_ctxt("iter_structural_ty");
412
413     fn iter_variant<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
414                                    repr: &adt::Repr<'tcx>,
415                                    av: adt::MaybeSizedValue,
416                                    variant: ty::VariantDef<'tcx>,
417                                    substs: &Substs<'tcx>,
418                                    f: &mut F)
419                                    -> Block<'blk, 'tcx>
420         where F: FnMut(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>
421     {
422         let _icx = push_ctxt("iter_variant");
423         let tcx = cx.tcx();
424         let mut cx = cx;
425
426         for (i, field) in variant.fields.iter().enumerate() {
427             let arg = monomorphize::field_ty(tcx, substs, field);
428             cx = f(cx,
429                    adt::trans_field_ptr(cx, repr, av, Disr::from(variant.disr_val), i),
430                    arg);
431         }
432         return cx;
433     }
434
435     let value = if common::type_is_sized(cx.tcx(), t) {
436         adt::MaybeSizedValue::sized(av)
437     } else {
438         let data = Load(cx, expr::get_dataptr(cx, av));
439         let info = Load(cx, expr::get_meta(cx, av));
440         adt::MaybeSizedValue::unsized_(data, info)
441     };
442
443     let mut cx = cx;
444     match t.sty {
445         ty::TyStruct(..) => {
446             let repr = adt::represent_type(cx.ccx(), t);
447             let VariantInfo { fields, discr } = VariantInfo::from_ty(cx.tcx(), t, None);
448             for (i, &Field(_, field_ty)) in fields.iter().enumerate() {
449                 let llfld_a = adt::trans_field_ptr(cx, &repr, value, Disr::from(discr), i);
450
451                 let val = if common::type_is_sized(cx.tcx(), field_ty) {
452                     llfld_a
453                 } else {
454                     let scratch = datum::rvalue_scratch_datum(cx, field_ty, "__fat_ptr_iter");
455                     Store(cx, llfld_a, expr::get_dataptr(cx, scratch.val));
456                     Store(cx, value.meta, expr::get_meta(cx, scratch.val));
457                     scratch.val
458                 };
459                 cx = f(cx, val, field_ty);
460             }
461         }
462         ty::TyClosure(_, ref substs) => {
463             let repr = adt::represent_type(cx.ccx(), t);
464             for (i, upvar_ty) in substs.upvar_tys.iter().enumerate() {
465                 let llupvar = adt::trans_field_ptr(cx, &repr, value, Disr(0), i);
466                 cx = f(cx, llupvar, upvar_ty);
467             }
468         }
469         ty::TyArray(_, n) => {
470             let (base, len) = tvec::get_fixed_base_and_len(cx, value.value, n);
471             let unit_ty = t.sequence_element_type(cx.tcx());
472             cx = tvec::iter_vec_raw(cx, base, unit_ty, len, f);
473         }
474         ty::TySlice(_) | ty::TyStr => {
475             let unit_ty = t.sequence_element_type(cx.tcx());
476             cx = tvec::iter_vec_raw(cx, value.value, unit_ty, value.meta, f);
477         }
478         ty::TyTuple(ref args) => {
479             let repr = adt::represent_type(cx.ccx(), t);
480             for (i, arg) in args.iter().enumerate() {
481                 let llfld_a = adt::trans_field_ptr(cx, &repr, value, Disr(0), i);
482                 cx = f(cx, llfld_a, *arg);
483             }
484         }
485         ty::TyEnum(en, substs) => {
486             let fcx = cx.fcx;
487             let ccx = fcx.ccx;
488
489             let repr = adt::represent_type(ccx, t);
490             let n_variants = en.variants.len();
491
492             // NB: we must hit the discriminant first so that structural
493             // comparison know not to proceed when the discriminants differ.
494
495             match adt::trans_switch(cx, &repr, av, false) {
496                 (_match::Single, None) => {
497                     if n_variants != 0 {
498                         assert!(n_variants == 1);
499                         cx = iter_variant(cx, &repr, adt::MaybeSizedValue::sized(av),
500                                           &en.variants[0], substs, &mut f);
501                     }
502                 }
503                 (_match::Switch, Some(lldiscrim_a)) => {
504                     cx = f(cx, lldiscrim_a, cx.tcx().types.isize);
505
506                     // Create a fall-through basic block for the "else" case of
507                     // the switch instruction we're about to generate. Note that
508                     // we do **not** use an Unreachable instruction here, even
509                     // though most of the time this basic block will never be hit.
510                     //
511                     // When an enum is dropped it's contents are currently
512                     // overwritten to DTOR_DONE, which means the discriminant
513                     // could have changed value to something not within the actual
514                     // range of the discriminant. Currently this function is only
515                     // used for drop glue so in this case we just return quickly
516                     // from the outer function, and any other use case will only
517                     // call this for an already-valid enum in which case the `ret
518                     // void` will never be hit.
519                     let ret_void_cx = fcx.new_temp_block("enum-iter-ret-void");
520                     RetVoid(ret_void_cx, DebugLoc::None);
521                     let llswitch = Switch(cx, lldiscrim_a, ret_void_cx.llbb, n_variants);
522                     let next_cx = fcx.new_temp_block("enum-iter-next");
523
524                     for variant in &en.variants {
525                         let variant_cx = fcx.new_temp_block(&format!("enum-iter-variant-{}",
526                                                                      &variant.disr_val
527                                                                              .to_string()));
528                         let case_val = adt::trans_case(cx, &repr, Disr::from(variant.disr_val));
529                         AddCase(llswitch, case_val, variant_cx.llbb);
530                         let variant_cx = iter_variant(variant_cx,
531                                                       &repr,
532                                                       value,
533                                                       variant,
534                                                       substs,
535                                                       &mut f);
536                         Br(variant_cx, next_cx.llbb, DebugLoc::None);
537                     }
538                     cx = next_cx;
539                 }
540                 _ => ccx.sess().unimpl("value from adt::trans_switch in iter_structural_ty"),
541             }
542         }
543         _ => {
544             cx.sess().unimpl(&format!("type in iter_structural_ty: {}", t))
545         }
546     }
547     return cx;
548 }
549
550
551 /// Retrieve the information we are losing (making dynamic) in an unsizing
552 /// adjustment.
553 ///
554 /// The `old_info` argument is a bit funny. It is intended for use
555 /// in an upcast, where the new vtable for an object will be drived
556 /// from the old one.
557 pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
558                                 source: Ty<'tcx>,
559                                 target: Ty<'tcx>,
560                                 old_info: Option<ValueRef>)
561                                 -> ValueRef {
562     let (source, target) = ccx.tcx().struct_lockstep_tails(source, target);
563     match (&source.sty, &target.sty) {
564         (&ty::TyArray(_, len), &ty::TySlice(_)) => C_uint(ccx, len),
565         (&ty::TyTrait(_), &ty::TyTrait(_)) => {
566             // For now, upcasts are limited to changes in marker
567             // traits, and hence never actually require an actual
568             // change to the vtable.
569             old_info.expect("unsized_info: missing old info for trait upcast")
570         }
571         (_, &ty::TyTrait(box ty::TraitTy { ref principal, .. })) => {
572             // Note that we preserve binding levels here:
573             let substs = principal.0.substs.with_self_ty(source).erase_regions();
574             let substs = ccx.tcx().mk_substs(substs);
575             let trait_ref = ty::Binder(ty::TraitRef {
576                 def_id: principal.def_id(),
577                 substs: substs,
578             });
579             consts::ptrcast(meth::get_vtable(ccx, trait_ref),
580                             Type::vtable_ptr(ccx))
581         }
582         _ => ccx.sess().bug(&format!("unsized_info: invalid unsizing {:?} -> {:?}",
583                                      source,
584                                      target)),
585     }
586 }
587
588 /// Coerce `src` to `dst_ty`. `src_ty` must be a thin pointer.
589 pub fn unsize_thin_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
590                                    src: ValueRef,
591                                    src_ty: Ty<'tcx>,
592                                    dst_ty: Ty<'tcx>)
593                                    -> (ValueRef, ValueRef) {
594     debug!("unsize_thin_ptr: {:?} => {:?}", src_ty, dst_ty);
595     match (&src_ty.sty, &dst_ty.sty) {
596         (&ty::TyBox(a), &ty::TyBox(b)) |
597         (&ty::TyRef(_, ty::TypeAndMut { ty: a, .. }),
598          &ty::TyRef(_, ty::TypeAndMut { ty: b, .. })) |
599         (&ty::TyRef(_, ty::TypeAndMut { ty: a, .. }),
600          &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) |
601         (&ty::TyRawPtr(ty::TypeAndMut { ty: a, .. }),
602          &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) => {
603             assert!(common::type_is_sized(bcx.tcx(), a));
604             let ptr_ty = type_of::in_memory_type_of(bcx.ccx(), b).ptr_to();
605             (PointerCast(bcx, src, ptr_ty),
606              unsized_info(bcx.ccx(), a, b, None))
607         }
608         _ => bcx.sess().bug("unsize_thin_ptr: called on bad types"),
609     }
610 }
611
612 /// Coerce `src`, which is a reference to a value of type `src_ty`,
613 /// to a value of type `dst_ty` and store the result in `dst`
614 pub fn coerce_unsized_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
615                                        src: ValueRef,
616                                        src_ty: Ty<'tcx>,
617                                        dst: ValueRef,
618                                        dst_ty: Ty<'tcx>) {
619     match (&src_ty.sty, &dst_ty.sty) {
620         (&ty::TyBox(..), &ty::TyBox(..)) |
621         (&ty::TyRef(..), &ty::TyRef(..)) |
622         (&ty::TyRef(..), &ty::TyRawPtr(..)) |
623         (&ty::TyRawPtr(..), &ty::TyRawPtr(..)) => {
624             let (base, info) = if common::type_is_fat_ptr(bcx.tcx(), src_ty) {
625                 // fat-ptr to fat-ptr unsize preserves the vtable
626                 load_fat_ptr(bcx, src, src_ty)
627             } else {
628                 let base = load_ty(bcx, src, src_ty);
629                 unsize_thin_ptr(bcx, base, src_ty, dst_ty)
630             };
631             store_fat_ptr(bcx, base, info, dst, dst_ty);
632         }
633
634         // This can be extended to enums and tuples in the future.
635         // (&ty::TyEnum(def_id_a, _), &ty::TyEnum(def_id_b, _)) |
636         (&ty::TyStruct(def_a, _), &ty::TyStruct(def_b, _)) => {
637             assert_eq!(def_a, def_b);
638
639             let src_repr = adt::represent_type(bcx.ccx(), src_ty);
640             let src_fields = match &*src_repr {
641                 &adt::Repr::Univariant(ref s, _) => &s.fields,
642                 _ => bcx.sess().bug("struct has non-univariant repr"),
643             };
644             let dst_repr = adt::represent_type(bcx.ccx(), dst_ty);
645             let dst_fields = match &*dst_repr {
646                 &adt::Repr::Univariant(ref s, _) => &s.fields,
647                 _ => bcx.sess().bug("struct has non-univariant repr"),
648             };
649
650             let src = adt::MaybeSizedValue::sized(src);
651             let dst = adt::MaybeSizedValue::sized(dst);
652
653             let iter = src_fields.iter().zip(dst_fields).enumerate();
654             for (i, (src_fty, dst_fty)) in iter {
655                 if type_is_zero_size(bcx.ccx(), dst_fty) {
656                     continue;
657                 }
658
659                 let src_f = adt::trans_field_ptr(bcx, &src_repr, src, Disr(0), i);
660                 let dst_f = adt::trans_field_ptr(bcx, &dst_repr, dst, Disr(0), i);
661                 if src_fty == dst_fty {
662                     memcpy_ty(bcx, dst_f, src_f, src_fty);
663                 } else {
664                     coerce_unsized_into(bcx, src_f, src_fty, dst_f, dst_fty);
665                 }
666             }
667         }
668         _ => bcx.sess().bug(&format!("coerce_unsized_into: invalid coercion {:?} -> {:?}",
669                                      src_ty,
670                                      dst_ty)),
671     }
672 }
673
674 pub fn custom_coerce_unsize_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
675                                              source_ty: Ty<'tcx>,
676                                              target_ty: Ty<'tcx>)
677                                              -> CustomCoerceUnsized {
678     let trait_substs = Substs::new(subst::VecPerParamSpace::new(vec![target_ty],
679                                                                 vec![source_ty],
680                                                                 Vec::new()),
681                                    subst::VecPerParamSpace::empty());
682
683     let trait_ref = ty::Binder(ty::TraitRef {
684         def_id: ccx.tcx().lang_items.coerce_unsized_trait().unwrap(),
685         substs: ccx.tcx().mk_substs(trait_substs)
686     });
687
688     match fulfill_obligation(ccx, DUMMY_SP, trait_ref) {
689         traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
690             ccx.tcx().custom_coerce_unsized_kind(impl_def_id)
691         }
692         vtable => {
693             ccx.sess().bug(&format!("invalid CoerceUnsized vtable: {:?}",
694                                     vtable));
695         }
696     }
697 }
698
699 pub fn cast_shift_expr_rhs(cx: Block, op: hir::BinOp_, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
700     cast_shift_rhs(op, lhs, rhs, |a, b| Trunc(cx, a, b), |a, b| ZExt(cx, a, b))
701 }
702
703 pub fn cast_shift_const_rhs(op: hir::BinOp_, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
704     cast_shift_rhs(op,
705                    lhs,
706                    rhs,
707                    |a, b| unsafe { llvm::LLVMConstTrunc(a, b.to_ref()) },
708                    |a, b| unsafe { llvm::LLVMConstZExt(a, b.to_ref()) })
709 }
710
711 fn cast_shift_rhs<F, G>(op: hir::BinOp_,
712                         lhs: ValueRef,
713                         rhs: ValueRef,
714                         trunc: F,
715                         zext: G)
716                         -> ValueRef
717     where F: FnOnce(ValueRef, Type) -> ValueRef,
718           G: FnOnce(ValueRef, Type) -> ValueRef
719 {
720     // Shifts may have any size int on the rhs
721     if rustc_front::util::is_shift_binop(op) {
722         let mut rhs_llty = val_ty(rhs);
723         let mut lhs_llty = val_ty(lhs);
724         if rhs_llty.kind() == Vector {
725             rhs_llty = rhs_llty.element_type()
726         }
727         if lhs_llty.kind() == Vector {
728             lhs_llty = lhs_llty.element_type()
729         }
730         let rhs_sz = rhs_llty.int_width();
731         let lhs_sz = lhs_llty.int_width();
732         if lhs_sz < rhs_sz {
733             trunc(rhs, lhs_llty)
734         } else if lhs_sz > rhs_sz {
735             // FIXME (#1877: If shifting by negative
736             // values becomes not undefined then this is wrong.
737             zext(rhs, lhs_llty)
738         } else {
739             rhs
740         }
741     } else {
742         rhs
743     }
744 }
745
746 pub fn llty_and_min_for_signed_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
747                                               val_t: Ty<'tcx>)
748                                               -> (Type, u64) {
749     match val_t.sty {
750         ty::TyInt(t) => {
751             let llty = Type::int_from_ty(cx.ccx(), t);
752             let min = match t {
753                 ast::IntTy::Is if llty == Type::i32(cx.ccx()) => i32::MIN as u64,
754                 ast::IntTy::Is => i64::MIN as u64,
755                 ast::IntTy::I8 => i8::MIN as u64,
756                 ast::IntTy::I16 => i16::MIN as u64,
757                 ast::IntTy::I32 => i32::MIN as u64,
758                 ast::IntTy::I64 => i64::MIN as u64,
759             };
760             (llty, min)
761         }
762         _ => unreachable!(),
763     }
764 }
765
766 pub fn fail_if_zero_or_overflows<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
767                                              call_info: NodeIdAndSpan,
768                                              divrem: hir::BinOp,
769                                              lhs: ValueRef,
770                                              rhs: ValueRef,
771                                              rhs_t: Ty<'tcx>)
772                                              -> Block<'blk, 'tcx> {
773     let (zero_text, overflow_text) = if divrem.node == hir::BiDiv {
774         ("attempted to divide by zero",
775          "attempted to divide with overflow")
776     } else {
777         ("attempted remainder with a divisor of zero",
778          "attempted remainder with overflow")
779     };
780     let debug_loc = call_info.debug_loc();
781
782     let (is_zero, is_signed) = match rhs_t.sty {
783         ty::TyInt(t) => {
784             let zero = C_integral(Type::int_from_ty(cx.ccx(), t), 0, false);
785             (ICmp(cx, llvm::IntEQ, rhs, zero, debug_loc), true)
786         }
787         ty::TyUint(t) => {
788             let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0, false);
789             (ICmp(cx, llvm::IntEQ, rhs, zero, debug_loc), false)
790         }
791         ty::TyStruct(def, _) if def.is_simd() => {
792             let mut res = C_bool(cx.ccx(), false);
793             for i in 0..rhs_t.simd_size(cx.tcx()) {
794                 res = Or(cx,
795                          res,
796                          IsNull(cx, ExtractElement(cx, rhs, C_int(cx.ccx(), i as i64))),
797                          debug_loc);
798             }
799             (res, false)
800         }
801         _ => {
802             cx.sess().bug(&format!("fail-if-zero on unexpected type: {}", rhs_t));
803         }
804     };
805     let bcx = with_cond(cx, is_zero, |bcx| {
806         controlflow::trans_fail(bcx, call_info, InternedString::new(zero_text))
807     });
808
809     // To quote LLVM's documentation for the sdiv instruction:
810     //
811     //      Division by zero leads to undefined behavior. Overflow also leads
812     //      to undefined behavior; this is a rare case, but can occur, for
813     //      example, by doing a 32-bit division of -2147483648 by -1.
814     //
815     // In order to avoid undefined behavior, we perform runtime checks for
816     // signed division/remainder which would trigger overflow. For unsigned
817     // integers, no action beyond checking for zero need be taken.
818     if is_signed {
819         let (llty, min) = llty_and_min_for_signed_ty(cx, rhs_t);
820         let minus_one = ICmp(bcx,
821                              llvm::IntEQ,
822                              rhs,
823                              C_integral(llty, !0, false),
824                              debug_loc);
825         with_cond(bcx, minus_one, |bcx| {
826             let is_min = ICmp(bcx,
827                               llvm::IntEQ,
828                               lhs,
829                               C_integral(llty, min, true),
830                               debug_loc);
831             with_cond(bcx, is_min, |bcx| {
832                 controlflow::trans_fail(bcx, call_info, InternedString::new(overflow_text))
833             })
834         })
835     } else {
836         bcx
837     }
838 }
839
840 pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
841                           llfn: ValueRef,
842                           llargs: &[ValueRef],
843                           debug_loc: DebugLoc)
844                           -> (ValueRef, Block<'blk, 'tcx>) {
845     let _icx = push_ctxt("invoke_");
846     if bcx.unreachable.get() {
847         return (C_null(Type::i8(bcx.ccx())), bcx);
848     }
849
850     match bcx.opt_node_id {
851         None => {
852             debug!("invoke at ???");
853         }
854         Some(id) => {
855             debug!("invoke at {}", bcx.tcx().map.node_to_string(id));
856         }
857     }
858
859     if need_invoke(bcx) {
860         debug!("invoking {:?} at {:?}", Value(llfn), bcx.llbb);
861         for &llarg in llargs {
862             debug!("arg: {:?}", Value(llarg));
863         }
864         let normal_bcx = bcx.fcx.new_temp_block("normal-return");
865         let landing_pad = bcx.fcx.get_landing_pad();
866
867         let llresult = Invoke(bcx,
868                               llfn,
869                               &llargs[..],
870                               normal_bcx.llbb,
871                               landing_pad,
872                               debug_loc);
873         return (llresult, normal_bcx);
874     } else {
875         debug!("calling {:?} at {:?}", Value(llfn), bcx.llbb);
876         for &llarg in llargs {
877             debug!("arg: {:?}", Value(llarg));
878         }
879
880         let llresult = Call(bcx, llfn, &llargs[..], debug_loc);
881         return (llresult, bcx);
882     }
883 }
884
885 /// Returns whether this session's target will use SEH-based unwinding.
886 ///
887 /// This is only true for MSVC targets, and even then the 64-bit MSVC target
888 /// currently uses SEH-ish unwinding with DWARF info tables to the side (same as
889 /// 64-bit MinGW) instead of "full SEH".
890 pub fn wants_msvc_seh(sess: &Session) -> bool {
891     sess.target.target.options.is_like_msvc
892 }
893
894 pub fn avoid_invoke(bcx: Block) -> bool {
895     bcx.sess().no_landing_pads() || bcx.lpad().is_some()
896 }
897
898 pub fn need_invoke(bcx: Block) -> bool {
899     if avoid_invoke(bcx) {
900         false
901     } else {
902         bcx.fcx.needs_invoke()
903     }
904 }
905
906 pub fn load_if_immediate<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, t: Ty<'tcx>) -> ValueRef {
907     let _icx = push_ctxt("load_if_immediate");
908     if type_is_immediate(cx.ccx(), t) {
909         return load_ty(cx, v, t);
910     }
911     return v;
912 }
913
914 /// Helper for loading values from memory. Does the necessary conversion if the in-memory type
915 /// differs from the type used for SSA values. Also handles various special cases where the type
916 /// gives us better information about what we are loading.
917 pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ptr: ValueRef, t: Ty<'tcx>) -> ValueRef {
918     if cx.unreachable.get() {
919         return C_undef(type_of::type_of(cx.ccx(), t));
920     }
921     load_ty_builder(&B(cx), ptr, t)
922 }
923
924 pub fn load_ty_builder<'a, 'tcx>(b: &Builder<'a, 'tcx>, ptr: ValueRef, t: Ty<'tcx>) -> ValueRef {
925     let ccx = b.ccx;
926     if type_is_zero_size(ccx, t) {
927         return C_undef(type_of::type_of(ccx, t));
928     }
929
930     unsafe {
931         let global = llvm::LLVMIsAGlobalVariable(ptr);
932         if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True {
933             let val = llvm::LLVMGetInitializer(global);
934             if !val.is_null() {
935                 if t.is_bool() {
936                     return llvm::LLVMConstTrunc(val, Type::i1(ccx).to_ref());
937                 }
938                 return val;
939             }
940         }
941     }
942
943     if t.is_bool() {
944         b.trunc(b.load_range_assert(ptr, 0, 2, llvm::False), Type::i1(ccx))
945     } else if t.is_char() {
946         // a char is a Unicode codepoint, and so takes values from 0
947         // to 0x10FFFF inclusive only.
948         b.load_range_assert(ptr, 0, 0x10FFFF + 1, llvm::False)
949     } else if (t.is_region_ptr() || t.is_unique()) &&
950               !common::type_is_fat_ptr(ccx.tcx(), t) {
951         b.load_nonnull(ptr)
952     } else {
953         b.load(ptr)
954     }
955 }
956
957 /// Helper for storing values in memory. Does the necessary conversion if the in-memory type
958 /// differs from the type used for SSA values.
959 pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t: Ty<'tcx>) {
960     if cx.unreachable.get() {
961         return;
962     }
963
964     debug!("store_ty: {:?} : {:?} <- {:?}", Value(dst), t, Value(v));
965
966     if common::type_is_fat_ptr(cx.tcx(), t) {
967         Store(cx,
968               ExtractValue(cx, v, abi::FAT_PTR_ADDR),
969               expr::get_dataptr(cx, dst));
970         Store(cx,
971               ExtractValue(cx, v, abi::FAT_PTR_EXTRA),
972               expr::get_meta(cx, dst));
973     } else {
974         Store(cx, from_immediate(cx, v), dst);
975     }
976 }
977
978 pub fn store_fat_ptr<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
979                                  data: ValueRef,
980                                  extra: ValueRef,
981                                  dst: ValueRef,
982                                  _ty: Ty<'tcx>) {
983     // FIXME: emit metadata
984     Store(cx, data, expr::get_dataptr(cx, dst));
985     Store(cx, extra, expr::get_meta(cx, dst));
986 }
987
988 pub fn load_fat_ptr<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
989                                 src: ValueRef,
990                                 _ty: Ty<'tcx>)
991                                 -> (ValueRef, ValueRef) {
992     // FIXME: emit metadata
993     (Load(cx, expr::get_dataptr(cx, src)),
994      Load(cx, expr::get_meta(cx, src)))
995 }
996
997 pub fn from_immediate(bcx: Block, val: ValueRef) -> ValueRef {
998     if val_ty(val) == Type::i1(bcx.ccx()) {
999         ZExt(bcx, val, Type::i8(bcx.ccx()))
1000     } else {
1001         val
1002     }
1003 }
1004
1005 pub fn to_immediate(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
1006     if ty.is_bool() {
1007         Trunc(bcx, val, Type::i1(bcx.ccx()))
1008     } else {
1009         val
1010     }
1011 }
1012
1013 pub fn init_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, local: &hir::Local) -> Block<'blk, 'tcx> {
1014     debug!("init_local(bcx={}, local.id={})", bcx.to_str(), local.id);
1015     let _indenter = indenter();
1016     let _icx = push_ctxt("init_local");
1017     _match::store_local(bcx, local)
1018 }
1019
1020 pub fn raw_block<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>,
1021                              llbb: BasicBlockRef)
1022                              -> Block<'blk, 'tcx> {
1023     common::BlockS::new(llbb, None, fcx)
1024 }
1025
1026 pub fn with_cond<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, val: ValueRef, f: F) -> Block<'blk, 'tcx>
1027     where F: FnOnce(Block<'blk, 'tcx>) -> Block<'blk, 'tcx>
1028 {
1029     let _icx = push_ctxt("with_cond");
1030
1031     if bcx.unreachable.get() || common::const_to_opt_uint(val) == Some(0) {
1032         return bcx;
1033     }
1034
1035     let fcx = bcx.fcx;
1036     let next_cx = fcx.new_temp_block("next");
1037     let cond_cx = fcx.new_temp_block("cond");
1038     CondBr(bcx, val, cond_cx.llbb, next_cx.llbb, DebugLoc::None);
1039     let after_cx = f(cond_cx);
1040     if !after_cx.terminated.get() {
1041         Br(after_cx, next_cx.llbb, DebugLoc::None);
1042     }
1043     next_cx
1044 }
1045
1046 enum Lifetime { Start, End }
1047
1048 // If LLVM lifetime intrinsic support is enabled (i.e. optimizations
1049 // on), and `ptr` is nonzero-sized, then extracts the size of `ptr`
1050 // and the intrinsic for `lt` and passes them to `emit`, which is in
1051 // charge of generating code to call the passed intrinsic on whatever
1052 // block of generated code is targetted for the intrinsic.
1053 //
1054 // If LLVM lifetime intrinsic support is disabled (i.e.  optimizations
1055 // off) or `ptr` is zero-sized, then no-op (does not call `emit`).
1056 fn core_lifetime_emit<'blk, 'tcx, F>(ccx: &'blk CrateContext<'blk, 'tcx>,
1057                                      ptr: ValueRef,
1058                                      lt: Lifetime,
1059                                      emit: F)
1060     where F: FnOnce(&'blk CrateContext<'blk, 'tcx>, machine::llsize, ValueRef)
1061 {
1062     if ccx.sess().opts.optimize == config::OptLevel::No {
1063         return;
1064     }
1065
1066     let _icx = push_ctxt(match lt {
1067         Lifetime::Start => "lifetime_start",
1068         Lifetime::End => "lifetime_end"
1069     });
1070
1071     let size = machine::llsize_of_alloc(ccx, val_ty(ptr).element_type());
1072     if size == 0 {
1073         return;
1074     }
1075
1076     let lifetime_intrinsic = ccx.get_intrinsic(match lt {
1077         Lifetime::Start => "llvm.lifetime.start",
1078         Lifetime::End => "llvm.lifetime.end"
1079     });
1080     emit(ccx, size, lifetime_intrinsic)
1081 }
1082
1083 pub fn call_lifetime_start(cx: Block, ptr: ValueRef) {
1084     core_lifetime_emit(cx.ccx(), ptr, Lifetime::Start, |ccx, size, lifetime_start| {
1085         let ptr = PointerCast(cx, ptr, Type::i8p(ccx));
1086         Call(cx,
1087              lifetime_start,
1088              &[C_u64(ccx, size), ptr],
1089              DebugLoc::None);
1090     })
1091 }
1092
1093 pub fn call_lifetime_end(cx: Block, ptr: ValueRef) {
1094     core_lifetime_emit(cx.ccx(), ptr, Lifetime::End, |ccx, size, lifetime_end| {
1095         let ptr = PointerCast(cx, ptr, Type::i8p(ccx));
1096         Call(cx,
1097              lifetime_end,
1098              &[C_u64(ccx, size), ptr],
1099              DebugLoc::None);
1100     })
1101 }
1102
1103 // Generates code for resumption of unwind at the end of a landing pad.
1104 pub fn trans_unwind_resume(bcx: Block, lpval: ValueRef) {
1105     if !bcx.sess().target.target.options.custom_unwind_resume {
1106         Resume(bcx, lpval);
1107     } else {
1108         let exc_ptr = ExtractValue(bcx, lpval, 0);
1109         bcx.fcx.eh_unwind_resume()
1110             .call(bcx, DebugLoc::None, ArgVals(&[exc_ptr]), None);
1111     }
1112 }
1113
1114 pub fn call_memcpy<'bcx, 'tcx>(b: &Builder<'bcx, 'tcx>,
1115                                dst: ValueRef,
1116                                src: ValueRef,
1117                                n_bytes: ValueRef,
1118                                align: u32) {
1119     let _icx = push_ctxt("call_memcpy");
1120     let ccx = b.ccx;
1121     let ptr_width = &ccx.sess().target.target.target_pointer_width[..];
1122     let key = format!("llvm.memcpy.p0i8.p0i8.i{}", ptr_width);
1123     let memcpy = ccx.get_intrinsic(&key);
1124     let src_ptr = b.pointercast(src, Type::i8p(ccx));
1125     let dst_ptr = b.pointercast(dst, Type::i8p(ccx));
1126     let size = b.intcast(n_bytes, ccx.int_type());
1127     let align = C_i32(ccx, align as i32);
1128     let volatile = C_bool(ccx, false);
1129     b.call(memcpy, &[dst_ptr, src_ptr, size, align, volatile], None);
1130 }
1131
1132 pub fn memcpy_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, dst: ValueRef, src: ValueRef, t: Ty<'tcx>) {
1133     let _icx = push_ctxt("memcpy_ty");
1134     let ccx = bcx.ccx();
1135
1136     if type_is_zero_size(ccx, t) || bcx.unreachable.get() {
1137         return;
1138     }
1139
1140     if t.is_structural() {
1141         let llty = type_of::type_of(ccx, t);
1142         let llsz = llsize_of(ccx, llty);
1143         let llalign = type_of::align_of(ccx, t);
1144         call_memcpy(&B(bcx), dst, src, llsz, llalign as u32);
1145     } else if common::type_is_fat_ptr(bcx.tcx(), t) {
1146         let (data, extra) = load_fat_ptr(bcx, src, t);
1147         store_fat_ptr(bcx, data, extra, dst, t);
1148     } else {
1149         store_ty(bcx, load_ty(bcx, src, t), dst, t);
1150     }
1151 }
1152
1153 pub fn drop_done_fill_mem<'blk, 'tcx>(cx: Block<'blk, 'tcx>, llptr: ValueRef, t: Ty<'tcx>) {
1154     if cx.unreachable.get() {
1155         return;
1156     }
1157     let _icx = push_ctxt("drop_done_fill_mem");
1158     let bcx = cx;
1159     memfill(&B(bcx), llptr, t, adt::DTOR_DONE);
1160 }
1161
1162 pub fn init_zero_mem<'blk, 'tcx>(cx: Block<'blk, 'tcx>, llptr: ValueRef, t: Ty<'tcx>) {
1163     if cx.unreachable.get() {
1164         return;
1165     }
1166     let _icx = push_ctxt("init_zero_mem");
1167     let bcx = cx;
1168     memfill(&B(bcx), llptr, t, 0);
1169 }
1170
1171 // Always use this function instead of storing a constant byte to the memory
1172 // in question. e.g. if you store a zero constant, LLVM will drown in vreg
1173 // allocation for large data structures, and the generated code will be
1174 // awful. (A telltale sign of this is large quantities of
1175 // `mov [byte ptr foo],0` in the generated code.)
1176 fn memfill<'a, 'tcx>(b: &Builder<'a, 'tcx>, llptr: ValueRef, ty: Ty<'tcx>, byte: u8) {
1177     let _icx = push_ctxt("memfill");
1178     let ccx = b.ccx;
1179     let llty = type_of::type_of(ccx, ty);
1180     let llptr = b.pointercast(llptr, Type::i8(ccx).ptr_to());
1181     let llzeroval = C_u8(ccx, byte);
1182     let size = machine::llsize_of(ccx, llty);
1183     let align = C_i32(ccx, type_of::align_of(ccx, ty) as i32);
1184     call_memset(b, llptr, llzeroval, size, align, false);
1185 }
1186
1187 pub fn call_memset<'bcx, 'tcx>(b: &Builder<'bcx, 'tcx>,
1188                                ptr: ValueRef,
1189                                fill_byte: ValueRef,
1190                                size: ValueRef,
1191                                align: ValueRef,
1192                                volatile: bool) {
1193     let ccx = b.ccx;
1194     let ptr_width = &ccx.sess().target.target.target_pointer_width[..];
1195     let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
1196     let llintrinsicfn = ccx.get_intrinsic(&intrinsic_key);
1197     let volatile = C_bool(ccx, volatile);
1198     b.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None);
1199 }
1200
1201
1202 /// In general, when we create an scratch value in an alloca, the
1203 /// creator may not know if the block (that initializes the scratch
1204 /// with the desired value) actually dominates the cleanup associated
1205 /// with the scratch value.
1206 ///
1207 /// To deal with this, when we do an alloca (at the *start* of whole
1208 /// function body), we optionally can also set the associated
1209 /// dropped-flag state of the alloca to "dropped."
1210 #[derive(Copy, Clone, Debug)]
1211 pub enum InitAlloca {
1212     /// Indicates that the state should have its associated drop flag
1213     /// set to "dropped" at the point of allocation.
1214     Dropped,
1215     /// Indicates the value of the associated drop flag is irrelevant.
1216     /// The embedded string literal is a programmer provided argument
1217     /// for why. This is a safeguard forcing compiler devs to
1218     /// document; it might be a good idea to also emit this as a
1219     /// comment with the alloca itself when emitting LLVM output.ll.
1220     Uninit(&'static str),
1221 }
1222
1223
1224 pub fn alloc_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1225                             t: Ty<'tcx>,
1226                             name: &str) -> ValueRef {
1227     // pnkfelix: I do not know why alloc_ty meets the assumptions for
1228     // passing Uninit, but it was never needed (even back when we had
1229     // the original boolean `zero` flag on `lvalue_scratch_datum`).
1230     alloc_ty_init(bcx, t, InitAlloca::Uninit("all alloc_ty are uninit"), name)
1231 }
1232
1233 /// This variant of `fn alloc_ty` does not necessarily assume that the
1234 /// alloca should be created with no initial value. Instead the caller
1235 /// controls that assumption via the `init` flag.
1236 ///
1237 /// Note that if the alloca *is* initialized via `init`, then we will
1238 /// also inject an `llvm.lifetime.start` before that initialization
1239 /// occurs, and thus callers should not call_lifetime_start
1240 /// themselves.  But if `init` says "uninitialized", then callers are
1241 /// in charge of choosing where to call_lifetime_start and
1242 /// subsequently populate the alloca.
1243 ///
1244 /// (See related discussion on PR #30823.)
1245 pub fn alloc_ty_init<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1246                              t: Ty<'tcx>,
1247                              init: InitAlloca,
1248                              name: &str) -> ValueRef {
1249     let _icx = push_ctxt("alloc_ty");
1250     let ccx = bcx.ccx();
1251     let ty = type_of::type_of(ccx, t);
1252     assert!(!t.has_param_types());
1253     match init {
1254         InitAlloca::Dropped => alloca_dropped(bcx, t, name),
1255         InitAlloca::Uninit(_) => alloca(bcx, ty, name),
1256     }
1257 }
1258
1259 pub fn alloca_dropped<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ty: Ty<'tcx>, name: &str) -> ValueRef {
1260     let _icx = push_ctxt("alloca_dropped");
1261     let llty = type_of::type_of(cx.ccx(), ty);
1262     if cx.unreachable.get() {
1263         unsafe { return llvm::LLVMGetUndef(llty.ptr_to().to_ref()); }
1264     }
1265     let p = alloca(cx, llty, name);
1266     let b = cx.fcx.ccx.builder();
1267     b.position_before(cx.fcx.alloca_insert_pt.get().unwrap());
1268
1269     // This is just like `call_lifetime_start` (but latter expects a
1270     // Block, which we do not have for `alloca_insert_pt`).
1271     core_lifetime_emit(cx.ccx(), p, Lifetime::Start, |ccx, size, lifetime_start| {
1272         let ptr = b.pointercast(p, Type::i8p(ccx));
1273         b.call(lifetime_start, &[C_u64(ccx, size), ptr], None);
1274     });
1275     memfill(&b, p, ty, adt::DTOR_DONE);
1276     p
1277 }
1278
1279 pub fn alloca(cx: Block, ty: Type, name: &str) -> ValueRef {
1280     let _icx = push_ctxt("alloca");
1281     if cx.unreachable.get() {
1282         unsafe {
1283             return llvm::LLVMGetUndef(ty.ptr_to().to_ref());
1284         }
1285     }
1286     debuginfo::clear_source_location(cx.fcx);
1287     Alloca(cx, ty, name)
1288 }
1289
1290 pub fn set_value_name(val: ValueRef, name: &str) {
1291     unsafe {
1292         let name = CString::new(name).unwrap();
1293         llvm::LLVMSetValueName(val, name.as_ptr());
1294     }
1295 }
1296
1297 struct FindNestedReturn {
1298     found: bool,
1299 }
1300
1301 impl FindNestedReturn {
1302     fn new() -> FindNestedReturn {
1303         FindNestedReturn {
1304             found: false,
1305         }
1306     }
1307 }
1308
1309 impl<'v> Visitor<'v> for FindNestedReturn {
1310     fn visit_expr(&mut self, e: &hir::Expr) {
1311         match e.node {
1312             hir::ExprRet(..) => {
1313                 self.found = true;
1314             }
1315             _ => intravisit::walk_expr(self, e),
1316         }
1317     }
1318 }
1319
1320 fn build_cfg(tcx: &TyCtxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>) {
1321     let blk = match tcx.map.find(id) {
1322         Some(hir_map::NodeItem(i)) => {
1323             match i.node {
1324                 hir::ItemFn(_, _, _, _, _, ref blk) => {
1325                     blk
1326                 }
1327                 _ => tcx.sess.bug("unexpected item variant in has_nested_returns"),
1328             }
1329         }
1330         Some(hir_map::NodeTraitItem(trait_item)) => {
1331             match trait_item.node {
1332                 hir::MethodTraitItem(_, Some(ref body)) => body,
1333                 _ => {
1334                     tcx.sess.bug("unexpected variant: trait item other than a provided method in \
1335                                   has_nested_returns")
1336                 }
1337             }
1338         }
1339         Some(hir_map::NodeImplItem(impl_item)) => {
1340             match impl_item.node {
1341                 hir::ImplItemKind::Method(_, ref body) => body,
1342                 _ => {
1343                     tcx.sess.bug("unexpected variant: non-method impl item in has_nested_returns")
1344                 }
1345             }
1346         }
1347         Some(hir_map::NodeExpr(e)) => {
1348             match e.node {
1349                 hir::ExprClosure(_, _, ref blk) => blk,
1350                 _ => tcx.sess.bug("unexpected expr variant in has_nested_returns"),
1351             }
1352         }
1353         Some(hir_map::NodeVariant(..)) |
1354         Some(hir_map::NodeStructCtor(..)) => return (ast::DUMMY_NODE_ID, None),
1355
1356         // glue, shims, etc
1357         None if id == ast::DUMMY_NODE_ID => return (ast::DUMMY_NODE_ID, None),
1358
1359         _ => tcx.sess.bug(&format!("unexpected variant in has_nested_returns: {}",
1360                                    tcx.map.path_to_string(id))),
1361     };
1362
1363     (blk.id, Some(cfg::CFG::new(tcx, blk)))
1364 }
1365
1366 // Checks for the presence of "nested returns" in a function.
1367 // Nested returns are when the inner expression of a return expression
1368 // (the 'expr' in 'return expr') contains a return expression. Only cases
1369 // where the outer return is actually reachable are considered. Implicit
1370 // returns from the end of blocks are considered as well.
1371 //
1372 // This check is needed to handle the case where the inner expression is
1373 // part of a larger expression that may have already partially-filled the
1374 // return slot alloca. This can cause errors related to clean-up due to
1375 // the clobbering of the existing value in the return slot.
1376 fn has_nested_returns(tcx: &TyCtxt, cfg: &cfg::CFG, blk_id: ast::NodeId) -> bool {
1377     for index in cfg.graph.depth_traverse(cfg.entry) {
1378         let n = cfg.graph.node_data(index);
1379         match tcx.map.find(n.id()) {
1380             Some(hir_map::NodeExpr(ex)) => {
1381                 if let hir::ExprRet(Some(ref ret_expr)) = ex.node {
1382                     let mut visitor = FindNestedReturn::new();
1383                     intravisit::walk_expr(&mut visitor, &ret_expr);
1384                     if visitor.found {
1385                         return true;
1386                     }
1387                 }
1388             }
1389             Some(hir_map::NodeBlock(blk)) if blk.id == blk_id => {
1390                 let mut visitor = FindNestedReturn::new();
1391                 walk_list!(&mut visitor, visit_expr, &blk.expr);
1392                 if visitor.found {
1393                     return true;
1394                 }
1395             }
1396             _ => {}
1397         }
1398     }
1399
1400     return false;
1401 }
1402
1403 impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
1404     /// Create a function context for the given function.
1405     /// Beware that you must call `fcx.init` or `fcx.bind_args`
1406     /// before doing anything with the returned function context.
1407     pub fn new(ccx: &'blk CrateContext<'blk, 'tcx>,
1408                llfndecl: ValueRef,
1409                fn_ty: FnType,
1410                def_id: Option<DefId>,
1411                param_substs: &'tcx Substs<'tcx>,
1412                block_arena: &'blk TypedArena<common::BlockS<'blk, 'tcx>>)
1413                -> FunctionContext<'blk, 'tcx> {
1414         common::validate_substs(param_substs);
1415
1416         let inlined_did = def_id.and_then(|def_id| inline::get_local_instance(ccx, def_id));
1417         let inlined_id = inlined_did.and_then(|id| ccx.tcx().map.as_local_node_id(id));
1418         let local_id = def_id.and_then(|id| ccx.tcx().map.as_local_node_id(id));
1419
1420         debug!("FunctionContext::new(path={}, def_id={:?}, param_substs={:?})",
1421             inlined_id.map_or(String::new(), |id| {
1422                 ccx.tcx().map.path_to_string(id).to_string()
1423             }),
1424             def_id,
1425             param_substs);
1426
1427         let debug_context = debuginfo::create_function_debug_context(ccx,
1428             inlined_id.unwrap_or(ast::DUMMY_NODE_ID), param_substs, llfndecl);
1429
1430         let cfg = inlined_id.map(|id| build_cfg(ccx.tcx(), id));
1431         let nested_returns = if let Some((blk_id, Some(ref cfg))) = cfg {
1432             has_nested_returns(ccx.tcx(), cfg, blk_id)
1433         } else {
1434             false
1435         };
1436
1437         let check_attrs = |attrs: &[ast::Attribute]| {
1438             let default_to_mir = ccx.sess().opts.debugging_opts.orbit;
1439             let invert = if default_to_mir { "rustc_no_mir" } else { "rustc_mir" };
1440             default_to_mir ^ attrs.iter().any(|item| item.check_name(invert))
1441         };
1442
1443         let use_mir = if let Some(id) = local_id {
1444             check_attrs(ccx.tcx().map.attrs(id))
1445         } else if let Some(def_id) = def_id {
1446             check_attrs(&ccx.sess().cstore.item_attrs(def_id))
1447         } else {
1448             check_attrs(&[])
1449         };
1450
1451         let mir = if use_mir {
1452             def_id.and_then(|id| ccx.get_mir(id))
1453         } else {
1454             None
1455         };
1456
1457         FunctionContext {
1458             needs_ret_allocas: nested_returns && mir.is_none(),
1459             mir: mir,
1460             llfn: llfndecl,
1461             llretslotptr: Cell::new(None),
1462             param_env: ccx.tcx().empty_parameter_environment(),
1463             alloca_insert_pt: Cell::new(None),
1464             llreturn: Cell::new(None),
1465             landingpad_alloca: Cell::new(None),
1466             lllocals: RefCell::new(NodeMap()),
1467             llupvars: RefCell::new(NodeMap()),
1468             lldropflag_hints: RefCell::new(DropFlagHintsMap::new()),
1469             fn_ty: fn_ty,
1470             param_substs: param_substs,
1471             span: inlined_id.and_then(|id| ccx.tcx().map.opt_span(id)),
1472             block_arena: block_arena,
1473             lpad_arena: TypedArena::new(),
1474             ccx: ccx,
1475             debug_context: debug_context,
1476             scopes: RefCell::new(Vec::new()),
1477             cfg: cfg.and_then(|(_, cfg)| cfg)
1478         }
1479     }
1480
1481     /// Performs setup on a newly created function, creating the entry
1482     /// scope block and allocating space for the return pointer.
1483     pub fn init(&'blk self, skip_retptr: bool, fn_did: Option<DefId>)
1484                 -> Block<'blk, 'tcx> {
1485         let entry_bcx = self.new_temp_block("entry-block");
1486
1487         // Use a dummy instruction as the insertion point for all allocas.
1488         // This is later removed in FunctionContext::cleanup.
1489         self.alloca_insert_pt.set(Some(unsafe {
1490             Load(entry_bcx, C_null(Type::i8p(self.ccx)));
1491             llvm::LLVMGetFirstInstruction(entry_bcx.llbb)
1492         }));
1493
1494         if !self.fn_ty.ret.is_ignore() && !skip_retptr {
1495             // We normally allocate the llretslotptr, unless we
1496             // have been instructed to skip it for immediate return
1497             // values, or there is nothing to return at all.
1498
1499             // We create an alloca to hold a pointer of type `ret.original_ty`
1500             // which will hold the pointer to the right alloca which has the
1501             // final ret value
1502             let llty = self.fn_ty.ret.memory_ty(self.ccx);
1503             let slot = if self.needs_ret_allocas {
1504                 // Let's create the stack slot
1505                 let slot = AllocaFcx(self, llty.ptr_to(), "llretslotptr");
1506
1507                 // and if we're using an out pointer, then store that in our newly made slot
1508                 if self.fn_ty.ret.is_indirect() {
1509                     let outptr = get_param(self.llfn, 0);
1510
1511                     let b = self.ccx.builder();
1512                     b.position_before(self.alloca_insert_pt.get().unwrap());
1513                     b.store(outptr, slot);
1514                 }
1515
1516                 slot
1517             } else {
1518                 // But if there are no nested returns, we skip the indirection
1519                 // and have a single retslot
1520                 if self.fn_ty.ret.is_indirect() {
1521                     get_param(self.llfn, 0)
1522                 } else {
1523                     AllocaFcx(self, llty, "sret_slot")
1524                 }
1525             };
1526
1527             self.llretslotptr.set(Some(slot));
1528         }
1529
1530         // Create the drop-flag hints for every unfragmented path in the function.
1531         let tcx = self.ccx.tcx();
1532         let tables = tcx.tables.borrow();
1533         let mut hints = self.lldropflag_hints.borrow_mut();
1534         let fragment_infos = tcx.fragment_infos.borrow();
1535
1536         // Intern table for drop-flag hint datums.
1537         let mut seen = HashMap::new();
1538
1539         let fragment_infos = fn_did.and_then(|did| fragment_infos.get(&did));
1540         if let Some(fragment_infos) = fragment_infos {
1541             for &info in fragment_infos {
1542
1543                 let make_datum = |id| {
1544                     let init_val = C_u8(self.ccx, adt::DTOR_NEEDED_HINT);
1545                     let llname = &format!("dropflag_hint_{}", id);
1546                     debug!("adding hint {}", llname);
1547                     let ty = tcx.types.u8;
1548                     let ptr = alloc_ty(entry_bcx, ty, llname);
1549                     Store(entry_bcx, init_val, ptr);
1550                     let flag = datum::Lvalue::new_dropflag_hint("FunctionContext::init");
1551                     datum::Datum::new(ptr, ty, flag)
1552                 };
1553
1554                 let (var, datum) = match info {
1555                     ty::FragmentInfo::Moved { var, .. } |
1556                     ty::FragmentInfo::Assigned { var, .. } => {
1557                         let opt_datum = seen.get(&var).cloned().unwrap_or_else(|| {
1558                             let ty = tables.node_types[&var];
1559                             if self.type_needs_drop(ty) {
1560                                 let datum = make_datum(var);
1561                                 seen.insert(var, Some(datum.clone()));
1562                                 Some(datum)
1563                             } else {
1564                                 // No drop call needed, so we don't need a dropflag hint
1565                                 None
1566                             }
1567                         });
1568                         if let Some(datum) = opt_datum {
1569                             (var, datum)
1570                         } else {
1571                             continue
1572                         }
1573                     }
1574                 };
1575                 match info {
1576                     ty::FragmentInfo::Moved { move_expr: expr_id, .. } => {
1577                         debug!("FragmentInfo::Moved insert drop hint for {}", expr_id);
1578                         hints.insert(expr_id, DropHint::new(var, datum));
1579                     }
1580                     ty::FragmentInfo::Assigned { assignee_id: expr_id, .. } => {
1581                         debug!("FragmentInfo::Assigned insert drop hint for {}", expr_id);
1582                         hints.insert(expr_id, DropHint::new(var, datum));
1583                     }
1584                 }
1585             }
1586         }
1587
1588         entry_bcx
1589     }
1590
1591     /// Creates lvalue datums for each of the incoming function arguments,
1592     /// matches all argument patterns against them to produce bindings,
1593     /// and returns the entry block (see FunctionContext::init).
1594     fn bind_args(&'blk self,
1595                  args: &[hir::Arg],
1596                  abi: Abi,
1597                  id: ast::NodeId,
1598                  closure_env: closure::ClosureEnv,
1599                  arg_scope: cleanup::CustomScopeIndex)
1600                  -> Block<'blk, 'tcx> {
1601         let _icx = push_ctxt("FunctionContext::bind_args");
1602         let fn_did = self.ccx.tcx().map.local_def_id(id);
1603         let mut bcx = self.init(false, Some(fn_did));
1604         let arg_scope_id = cleanup::CustomScope(arg_scope);
1605
1606         let mut idx = 0;
1607         let mut llarg_idx = self.fn_ty.ret.is_indirect() as usize;
1608
1609         let has_tupled_arg = match closure_env {
1610             closure::ClosureEnv::NotClosure => abi == Abi::RustCall,
1611             closure::ClosureEnv::Closure(..) => {
1612                 closure_env.load(bcx, arg_scope_id);
1613                 let env_arg = &self.fn_ty.args[idx];
1614                 idx += 1;
1615                 if env_arg.pad.is_some() {
1616                     llarg_idx += 1;
1617                 }
1618                 if !env_arg.is_ignore() {
1619                     llarg_idx += 1;
1620                 }
1621                 false
1622             }
1623         };
1624         let tupled_arg_id = if has_tupled_arg {
1625             args[args.len() - 1].id
1626         } else {
1627             ast::DUMMY_NODE_ID
1628         };
1629
1630         // Return an array wrapping the ValueRefs that we get from `get_param` for
1631         // each argument into datums.
1632         //
1633         // For certain mode/type combinations, the raw llarg values are passed
1634         // by value.  However, within the fn body itself, we want to always
1635         // have all locals and arguments be by-ref so that we can cancel the
1636         // cleanup and for better interaction with LLVM's debug info.  So, if
1637         // the argument would be passed by value, we store it into an alloca.
1638         // This alloca should be optimized away by LLVM's mem-to-reg pass in
1639         // the event it's not truly needed.
1640         let uninit_reason = InitAlloca::Uninit("fn_arg populate dominates dtor");
1641         for hir_arg in args {
1642             let arg_ty = node_id_type(bcx, hir_arg.id);
1643             let arg_datum = if hir_arg.id != tupled_arg_id {
1644                 let arg = &self.fn_ty.args[idx];
1645                 idx += 1;
1646                 if arg.is_indirect() && bcx.sess().opts.debuginfo != FullDebugInfo {
1647                     // Don't copy an indirect argument to an alloca, the caller
1648                     // already put it in a temporary alloca and gave it up, unless
1649                     // we emit extra-debug-info, which requires local allocas :(.
1650                     let llarg = get_param(self.llfn, llarg_idx as c_uint);
1651                     llarg_idx += 1;
1652                     self.schedule_lifetime_end(arg_scope_id, llarg);
1653                     self.schedule_drop_mem(arg_scope_id, llarg, arg_ty, None);
1654
1655                     datum::Datum::new(llarg,
1656                                     arg_ty,
1657                                     datum::Lvalue::new("FunctionContext::bind_args"))
1658                 } else {
1659                     unpack_datum!(bcx, datum::lvalue_scratch_datum(bcx, arg_ty, "",
1660                                                                    uninit_reason,
1661                                                                    arg_scope_id, |bcx, dst| {
1662                         debug!("FunctionContext::bind_args: {:?}: {:?}", hir_arg, arg_ty);
1663                         let b = &bcx.build();
1664                         if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
1665                             let meta = &self.fn_ty.args[idx];
1666                             idx += 1;
1667                             arg.store_fn_arg(b, &mut llarg_idx, expr::get_dataptr(bcx, dst));
1668                             meta.store_fn_arg(b, &mut llarg_idx, expr::get_meta(bcx, dst));
1669                         } else {
1670                             arg.store_fn_arg(b, &mut llarg_idx, dst);
1671                         }
1672                         bcx
1673                     }))
1674                 }
1675             } else {
1676                 // FIXME(pcwalton): Reduce the amount of code bloat this is responsible for.
1677                 let tupled_arg_tys = match arg_ty.sty {
1678                     ty::TyTuple(ref tys) => tys,
1679                     _ => unreachable!("last argument of `rust-call` fn isn't a tuple?!")
1680                 };
1681
1682                 unpack_datum!(bcx, datum::lvalue_scratch_datum(bcx,
1683                                                             arg_ty,
1684                                                             "tupled_args",
1685                                                             uninit_reason,
1686                                                             arg_scope_id,
1687                                                             |bcx, llval| {
1688                     debug!("FunctionContext::bind_args: tupled {:?}: {:?}", hir_arg, arg_ty);
1689                     for (j, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() {
1690                         let dst = StructGEP(bcx, llval, j);
1691                         let arg = &self.fn_ty.args[idx];
1692                         idx += 1;
1693                         let b = &bcx.build();
1694                         if common::type_is_fat_ptr(bcx.tcx(), tupled_arg_ty) {
1695                             let meta = &self.fn_ty.args[idx];
1696                             idx += 1;
1697                             arg.store_fn_arg(b, &mut llarg_idx, expr::get_dataptr(bcx, dst));
1698                             meta.store_fn_arg(b, &mut llarg_idx, expr::get_meta(bcx, dst));
1699                         } else {
1700                             arg.store_fn_arg(b, &mut llarg_idx, dst);
1701                         }
1702                     }
1703                     bcx
1704                 }))
1705             };
1706
1707             let pat = &hir_arg.pat;
1708             bcx = if let Some(name) = simple_name(pat) {
1709                 // Generate nicer LLVM for the common case of fn a pattern
1710                 // like `x: T`
1711                 set_value_name(arg_datum.val, &bcx.name(name));
1712                 self.lllocals.borrow_mut().insert(pat.id, arg_datum);
1713                 bcx
1714             } else {
1715                 // General path. Copy out the values that are used in the
1716                 // pattern.
1717                 _match::bind_irrefutable_pat(bcx, pat, arg_datum.match_input(), arg_scope_id)
1718             };
1719             debuginfo::create_argument_metadata(bcx, hir_arg);
1720         }
1721
1722         bcx
1723     }
1724
1725     /// Ties up the llstaticallocas -> llloadenv -> lltop edges,
1726     /// and builds the return block.
1727     pub fn finish(&'blk self, last_bcx: Block<'blk, 'tcx>,
1728                   ret_debug_loc: DebugLoc) {
1729         let _icx = push_ctxt("FunctionContext::finish");
1730
1731         let ret_cx = match self.llreturn.get() {
1732             Some(llreturn) => {
1733                 if !last_bcx.terminated.get() {
1734                     Br(last_bcx, llreturn, DebugLoc::None);
1735                 }
1736                 raw_block(self, llreturn)
1737             }
1738             None => last_bcx,
1739         };
1740
1741         self.build_return_block(ret_cx, ret_debug_loc);
1742
1743         debuginfo::clear_source_location(self);
1744         self.cleanup();
1745     }
1746
1747     // Builds the return block for a function.
1748     pub fn build_return_block(&self, ret_cx: Block<'blk, 'tcx>,
1749                               ret_debug_location: DebugLoc) {
1750         if self.llretslotptr.get().is_none() ||
1751            ret_cx.unreachable.get() ||
1752            (!self.needs_ret_allocas && self.fn_ty.ret.is_indirect()) {
1753             return RetVoid(ret_cx, ret_debug_location);
1754         }
1755
1756         let retslot = if self.needs_ret_allocas {
1757             Load(ret_cx, self.llretslotptr.get().unwrap())
1758         } else {
1759             self.llretslotptr.get().unwrap()
1760         };
1761         let retptr = Value(retslot);
1762         let llty = self.fn_ty.ret.original_ty;
1763         match (retptr.get_dominating_store(ret_cx), self.fn_ty.ret.cast) {
1764             // If there's only a single store to the ret slot, we can directly return
1765             // the value that was stored and omit the store and the alloca.
1766             // However, we only want to do this when there is no cast needed.
1767             (Some(s), None) => {
1768                 let mut retval = s.get_operand(0).unwrap().get();
1769                 s.erase_from_parent();
1770
1771                 if retptr.has_no_uses() {
1772                     retptr.erase_from_parent();
1773                 }
1774
1775                 if self.fn_ty.ret.is_indirect() {
1776                     Store(ret_cx, retval, get_param(self.llfn, 0));
1777                     RetVoid(ret_cx, ret_debug_location)
1778                 } else {
1779                     if llty == Type::i1(self.ccx) {
1780                         retval = Trunc(ret_cx, retval, llty);
1781                     }
1782                     Ret(ret_cx, retval, ret_debug_location)
1783                 }
1784             }
1785             (_, cast_ty) if self.fn_ty.ret.is_indirect() => {
1786                 // Otherwise, copy the return value to the ret slot.
1787                 assert_eq!(cast_ty, None);
1788                 let llsz = llsize_of(self.ccx, self.fn_ty.ret.ty);
1789                 let llalign = llalign_of_min(self.ccx, self.fn_ty.ret.ty);
1790                 call_memcpy(&B(ret_cx), get_param(self.llfn, 0),
1791                             retslot, llsz, llalign as u32);
1792                 RetVoid(ret_cx, ret_debug_location)
1793             }
1794             (_, Some(cast_ty)) => {
1795                 let load = Load(ret_cx, PointerCast(ret_cx, retslot, cast_ty.ptr_to()));
1796                 let llalign = llalign_of_min(self.ccx, self.fn_ty.ret.ty);
1797                 unsafe {
1798                     llvm::LLVMSetAlignment(load, llalign);
1799                 }
1800                 Ret(ret_cx, load, ret_debug_location)
1801             }
1802             (_, None) => {
1803                 let retval = if llty == Type::i1(self.ccx) {
1804                     let val = LoadRangeAssert(ret_cx, retslot, 0, 2, llvm::False);
1805                     Trunc(ret_cx, val, llty)
1806                 } else {
1807                     Load(ret_cx, retslot)
1808                 };
1809                 Ret(ret_cx, retval, ret_debug_location)
1810             }
1811         }
1812     }
1813 }
1814
1815 /// Builds an LLVM function out of a source function.
1816 ///
1817 /// If the function closes over its environment a closure will be returned.
1818 pub fn trans_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
1819                                decl: &hir::FnDecl,
1820                                body: &hir::Block,
1821                                llfndecl: ValueRef,
1822                                param_substs: &'tcx Substs<'tcx>,
1823                                def_id: DefId,
1824                                inlined_id: ast::NodeId,
1825                                fn_ty: FnType,
1826                                abi: Abi,
1827                                closure_env: closure::ClosureEnv) {
1828     ccx.stats().n_closures.set(ccx.stats().n_closures.get() + 1);
1829
1830     if collector::collecting_debug_information(ccx) {
1831         ccx.record_translation_item_as_generated(
1832             TransItem::Fn(Instance::new(def_id, param_substs)));
1833     }
1834
1835     let _icx = push_ctxt("trans_closure");
1836     attributes::emit_uwtable(llfndecl, true);
1837
1838     debug!("trans_closure(..., param_substs={:?})", param_substs);
1839
1840     let (arena, fcx): (TypedArena<_>, FunctionContext);
1841     arena = TypedArena::new();
1842     fcx = FunctionContext::new(ccx, llfndecl, fn_ty, Some(def_id), param_substs, &arena);
1843
1844     if fcx.mir.is_some() {
1845         return mir::trans_mir(&fcx);
1846     }
1847
1848     // cleanup scope for the incoming arguments
1849     let fn_cleanup_debug_loc = debuginfo::get_cleanup_debug_loc_for_ast_node(
1850         ccx, inlined_id, body.span, true);
1851     let arg_scope = fcx.push_custom_cleanup_scope_with_debug_loc(fn_cleanup_debug_loc);
1852
1853     // Set up arguments to the function.
1854     debug!("trans_closure: function: {:?}", Value(fcx.llfn));
1855     let bcx = fcx.bind_args(&decl.inputs, abi, inlined_id, closure_env, arg_scope);
1856
1857     // Up until here, IR instructions for this function have explicitly not been annotated with
1858     // source code location, so we don't step into call setup code. From here on, source location
1859     // emitting should be enabled.
1860     debuginfo::start_emitting_source_locations(&fcx);
1861
1862     let dest = if fcx.fn_ty.ret.is_ignore() {
1863         expr::Ignore
1864     } else {
1865         expr::SaveIn(fcx.get_ret_slot(bcx, "iret_slot"))
1866     };
1867
1868     // This call to trans_block is the place where we bridge between
1869     // translation calls that don't have a return value (trans_crate,
1870     // trans_mod, trans_item, et cetera) and those that do
1871     // (trans_block, trans_expr, et cetera).
1872     let mut bcx = controlflow::trans_block(bcx, body, dest);
1873
1874     match dest {
1875         expr::SaveIn(slot) if fcx.needs_ret_allocas => {
1876             Store(bcx, slot, fcx.llretslotptr.get().unwrap());
1877         }
1878         _ => {}
1879     }
1880
1881     match fcx.llreturn.get() {
1882         Some(_) => {
1883             Br(bcx, fcx.return_exit_block(), DebugLoc::None);
1884             fcx.pop_custom_cleanup_scope(arg_scope);
1885         }
1886         None => {
1887             // Microoptimization writ large: avoid creating a separate
1888             // llreturn basic block
1889             bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_scope);
1890         }
1891     };
1892
1893     // Put return block after all other blocks.
1894     // This somewhat improves single-stepping experience in debugger.
1895     unsafe {
1896         let llreturn = fcx.llreturn.get();
1897         if let Some(llreturn) = llreturn {
1898             llvm::LLVMMoveBasicBlockAfter(llreturn, bcx.llbb);
1899         }
1900     }
1901
1902     let ret_debug_loc = DebugLoc::At(fn_cleanup_debug_loc.id, fn_cleanup_debug_loc.span);
1903
1904     // Insert the mandatory first few basic blocks before lltop.
1905     fcx.finish(bcx, ret_debug_loc);
1906 }
1907
1908 /// Creates an LLVM function corresponding to a source language function.
1909 pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
1910                           decl: &hir::FnDecl,
1911                           body: &hir::Block,
1912                           llfndecl: ValueRef,
1913                           param_substs: &'tcx Substs<'tcx>,
1914                           id: ast::NodeId) {
1915     let _s = StatRecorder::new(ccx, ccx.tcx().map.path_to_string(id).to_string());
1916     debug!("trans_fn(param_substs={:?})", param_substs);
1917     let _icx = push_ctxt("trans_fn");
1918     let fn_ty = ccx.tcx().node_id_to_type(id);
1919     let fn_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &fn_ty);
1920     let sig = ccx.tcx().erase_late_bound_regions(fn_ty.fn_sig());
1921     let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
1922     let abi = fn_ty.fn_abi();
1923     let fn_ty = FnType::new(ccx, abi, &sig, &[]);
1924     let def_id = if let Some(&def_id) = ccx.external_srcs().borrow().get(&id) {
1925         def_id
1926     } else {
1927         ccx.tcx().map.local_def_id(id)
1928     };
1929     trans_closure(ccx,
1930                   decl,
1931                   body,
1932                   llfndecl,
1933                   param_substs,
1934                   def_id,
1935                   id,
1936                   fn_ty,
1937                   abi,
1938                   closure::ClosureEnv::NotClosure);
1939 }
1940
1941 pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
1942                                                  ctor_ty: Ty<'tcx>,
1943                                                  disr: Disr,
1944                                                  args: CallArgs,
1945                                                  dest: expr::Dest,
1946                                                  debug_loc: DebugLoc)
1947                                                  -> Result<'blk, 'tcx> {
1948
1949     let ccx = bcx.fcx.ccx;
1950
1951     let sig = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_sig());
1952     let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
1953     let result_ty = sig.output.unwrap();
1954
1955     // Get location to store the result. If the user does not care about
1956     // the result, just make a stack slot
1957     let llresult = match dest {
1958         expr::SaveIn(d) => d,
1959         expr::Ignore => {
1960             if !type_is_zero_size(ccx, result_ty) {
1961                 let llresult = alloc_ty(bcx, result_ty, "constructor_result");
1962                 call_lifetime_start(bcx, llresult);
1963                 llresult
1964             } else {
1965                 C_undef(type_of::type_of(ccx, result_ty).ptr_to())
1966             }
1967         }
1968     };
1969
1970     if !type_is_zero_size(ccx, result_ty) {
1971         match args {
1972             ArgExprs(exprs) => {
1973                 let fields = exprs.iter().map(|x| &**x).enumerate().collect::<Vec<_>>();
1974                 bcx = expr::trans_adt(bcx,
1975                                       result_ty,
1976                                       disr,
1977                                       &fields[..],
1978                                       None,
1979                                       expr::SaveIn(llresult),
1980                                       debug_loc);
1981             }
1982             _ => ccx.sess().bug("expected expr as arguments for variant/struct tuple constructor"),
1983         }
1984     } else {
1985         // Just eval all the expressions (if any). Since expressions in Rust can have arbitrary
1986         // contents, there could be side-effects we need from them.
1987         match args {
1988             ArgExprs(exprs) => {
1989                 for expr in exprs {
1990                     bcx = expr::trans_into(bcx, expr, expr::Ignore);
1991                 }
1992             }
1993             _ => (),
1994         }
1995     }
1996
1997     // If the caller doesn't care about the result
1998     // drop the temporary we made
1999     let bcx = match dest {
2000         expr::SaveIn(_) => bcx,
2001         expr::Ignore => {
2002             let bcx = glue::drop_ty(bcx, llresult, result_ty, debug_loc);
2003             if !type_is_zero_size(ccx, result_ty) {
2004                 call_lifetime_end(bcx, llresult);
2005             }
2006             bcx
2007         }
2008     };
2009
2010     Result::new(bcx, llresult)
2011 }
2012
2013 pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
2014                                  ctor_id: ast::NodeId,
2015                                  disr: Disr,
2016                                  param_substs: &'tcx Substs<'tcx>,
2017                                  llfndecl: ValueRef) {
2018     let ctor_ty = ccx.tcx().node_id_to_type(ctor_id);
2019     let ctor_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &ctor_ty);
2020
2021     let sig = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_sig());
2022     let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
2023     let fn_ty = FnType::new(ccx, Abi::Rust, &sig, &[]);
2024
2025     let (arena, fcx): (TypedArena<_>, FunctionContext);
2026     arena = TypedArena::new();
2027     fcx = FunctionContext::new(ccx, llfndecl, fn_ty,
2028                                Some(ccx.tcx().map.local_def_id(ctor_id)),
2029                                param_substs, &arena);
2030     let bcx = fcx.init(false, None);
2031
2032     assert!(!fcx.needs_ret_allocas);
2033
2034     if !fcx.fn_ty.ret.is_ignore() {
2035         let dest = fcx.get_ret_slot(bcx, "eret_slot");
2036         let dest_val = adt::MaybeSizedValue::sized(dest); // Can return unsized value
2037         let repr = adt::represent_type(ccx, sig.output.unwrap());
2038         let mut llarg_idx = fcx.fn_ty.ret.is_indirect() as usize;
2039         let mut arg_idx = 0;
2040         for (i, arg_ty) in sig.inputs.into_iter().enumerate() {
2041             let lldestptr = adt::trans_field_ptr(bcx, &repr, dest_val, Disr::from(disr), i);
2042             let arg = &fcx.fn_ty.args[arg_idx];
2043             arg_idx += 1;
2044             let b = &bcx.build();
2045             if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
2046                 let meta = &fcx.fn_ty.args[arg_idx];
2047                 arg_idx += 1;
2048                 arg.store_fn_arg(b, &mut llarg_idx, expr::get_dataptr(bcx, lldestptr));
2049                 meta.store_fn_arg(b, &mut llarg_idx, expr::get_meta(bcx, lldestptr));
2050             } else {
2051                 arg.store_fn_arg(b, &mut llarg_idx, lldestptr);
2052             }
2053         }
2054         adt::trans_set_discr(bcx, &repr, dest, disr);
2055     }
2056
2057     fcx.finish(bcx, DebugLoc::None);
2058 }
2059
2060 fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &hir::EnumDef, sp: Span, id: ast::NodeId) {
2061     let mut sizes = Vec::new(); // does no allocation if no pushes, thankfully
2062
2063     let print_info = ccx.sess().print_enum_sizes();
2064
2065     let levels = ccx.tcx().node_lint_levels.borrow();
2066     let lint_id = lint::LintId::of(lint::builtin::VARIANT_SIZE_DIFFERENCES);
2067     let lvlsrc = levels.get(&(id, lint_id));
2068     let is_allow = lvlsrc.map_or(true, |&(lvl, _)| lvl == lint::Allow);
2069
2070     if is_allow && !print_info {
2071         // we're not interested in anything here
2072         return;
2073     }
2074
2075     let ty = ccx.tcx().node_id_to_type(id);
2076     let avar = adt::represent_type(ccx, ty);
2077     match *avar {
2078         adt::General(_, ref variants, _) => {
2079             for var in variants {
2080                 let mut size = 0;
2081                 for field in var.fields.iter().skip(1) {
2082                     // skip the discriminant
2083                     size += llsize_of_real(ccx, sizing_type_of(ccx, *field));
2084                 }
2085                 sizes.push(size);
2086             }
2087         },
2088         _ => { /* its size is either constant or unimportant */ }
2089     }
2090
2091     let (largest, slargest, largest_index) = sizes.iter().enumerate().fold((0, 0, 0),
2092         |(l, s, li), (idx, &size)|
2093             if size > l {
2094                 (size, l, idx)
2095             } else if size > s {
2096                 (l, size, li)
2097             } else {
2098                 (l, s, li)
2099             }
2100     );
2101
2102     // FIXME(#30505) Should use logging for this.
2103     if print_info {
2104         let llty = type_of::sizing_type_of(ccx, ty);
2105
2106         let sess = &ccx.tcx().sess;
2107         sess.span_note_without_error(sp,
2108                                      &format!("total size: {} bytes", llsize_of_real(ccx, llty)));
2109         match *avar {
2110             adt::General(..) => {
2111                 for (i, var) in enum_def.variants.iter().enumerate() {
2112                     ccx.tcx()
2113                        .sess
2114                        .span_note_without_error(var.span,
2115                                                 &format!("variant data: {} bytes", sizes[i]));
2116                 }
2117             }
2118             _ => {}
2119         }
2120     }
2121
2122     // we only warn if the largest variant is at least thrice as large as
2123     // the second-largest.
2124     if !is_allow && largest > slargest * 3 && slargest > 0 {
2125         // Use lint::raw_emit_lint rather than sess.add_lint because the lint-printing
2126         // pass for the latter already ran.
2127         lint::raw_struct_lint(&ccx.tcx().sess,
2128                               &ccx.tcx().sess.lint_store.borrow(),
2129                               lint::builtin::VARIANT_SIZE_DIFFERENCES,
2130                               *lvlsrc.unwrap(),
2131                               Some(sp),
2132                               &format!("enum variant is more than three times larger ({} bytes) \
2133                                         than the next largest (ignoring padding)",
2134                                        largest))
2135             .span_note(enum_def.variants[largest_index].span,
2136                        "this variant is the largest")
2137             .emit();
2138     }
2139 }
2140
2141 pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
2142     // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
2143     // applicable to variable declarations and may not really make sense for
2144     // Rust code in the first place but whitelist them anyway and trust that
2145     // the user knows what s/he's doing. Who knows, unanticipated use cases
2146     // may pop up in the future.
2147     //
2148     // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
2149     // and don't have to be, LLVM treats them as no-ops.
2150     match name {
2151         "appending" => Some(llvm::AppendingLinkage),
2152         "available_externally" => Some(llvm::AvailableExternallyLinkage),
2153         "common" => Some(llvm::CommonLinkage),
2154         "extern_weak" => Some(llvm::ExternalWeakLinkage),
2155         "external" => Some(llvm::ExternalLinkage),
2156         "internal" => Some(llvm::InternalLinkage),
2157         "linkonce" => Some(llvm::LinkOnceAnyLinkage),
2158         "linkonce_odr" => Some(llvm::LinkOnceODRLinkage),
2159         "private" => Some(llvm::PrivateLinkage),
2160         "weak" => Some(llvm::WeakAnyLinkage),
2161         "weak_odr" => Some(llvm::WeakODRLinkage),
2162         _ => None,
2163     }
2164 }
2165
2166
2167 /// Enum describing the origin of an LLVM `Value`, for linkage purposes.
2168 #[derive(Copy, Clone)]
2169 pub enum ValueOrigin {
2170     /// The LLVM `Value` is in this context because the corresponding item was
2171     /// assigned to the current compilation unit.
2172     OriginalTranslation,
2173     /// The `Value`'s corresponding item was assigned to some other compilation
2174     /// unit, but the `Value` was translated in this context anyway because the
2175     /// item is marked `#[inline]`.
2176     InlinedCopy,
2177 }
2178
2179 /// Set the appropriate linkage for an LLVM `ValueRef` (function or global).
2180 /// If the `llval` is the direct translation of a specific Rust item, `id`
2181 /// should be set to the `NodeId` of that item.  (This mapping should be
2182 /// 1-to-1, so monomorphizations and drop/visit glue should have `id` set to
2183 /// `None`.)  `llval_origin` indicates whether `llval` is the translation of an
2184 /// item assigned to `ccx`'s compilation unit or an inlined copy of an item
2185 /// assigned to a different compilation unit.
2186 pub fn update_linkage(ccx: &CrateContext,
2187                       llval: ValueRef,
2188                       id: Option<ast::NodeId>,
2189                       llval_origin: ValueOrigin) {
2190     match llval_origin {
2191         InlinedCopy => {
2192             // `llval` is a translation of an item defined in a separate
2193             // compilation unit.  This only makes sense if there are at least
2194             // two compilation units.
2195             assert!(ccx.sess().opts.cg.codegen_units > 1);
2196             // `llval` is a copy of something defined elsewhere, so use
2197             // `AvailableExternallyLinkage` to avoid duplicating code in the
2198             // output.
2199             llvm::SetLinkage(llval, llvm::AvailableExternallyLinkage);
2200             return;
2201         },
2202         OriginalTranslation => {},
2203     }
2204
2205     if let Some(id) = id {
2206         let item = ccx.tcx().map.get(id);
2207         if let hir_map::NodeItem(i) = item {
2208             if let Some(name) = attr::first_attr_value_str_by_name(&i.attrs, "linkage") {
2209                 if let Some(linkage) = llvm_linkage_by_name(&name) {
2210                     llvm::SetLinkage(llval, linkage);
2211                 } else {
2212                     ccx.sess().span_fatal(i.span, "invalid linkage specified");
2213                 }
2214                 return;
2215             }
2216         }
2217     }
2218
2219     match id {
2220         Some(id) if ccx.reachable().contains(&id) => {
2221             llvm::SetLinkage(llval, llvm::ExternalLinkage);
2222         },
2223         _ => {
2224             // `id` does not refer to an item in `ccx.reachable`.
2225             if ccx.sess().opts.cg.codegen_units > 1 {
2226                 llvm::SetLinkage(llval, llvm::ExternalLinkage);
2227             } else {
2228                 llvm::SetLinkage(llval, llvm::InternalLinkage);
2229             }
2230         },
2231     }
2232 }
2233
2234 fn set_global_section(ccx: &CrateContext, llval: ValueRef, i: &hir::Item) {
2235     match attr::first_attr_value_str_by_name(&i.attrs, "link_section") {
2236         Some(sect) => {
2237             if contains_null(&sect) {
2238                 ccx.sess().fatal(&format!("Illegal null byte in link_section value: `{}`", &sect));
2239             }
2240             unsafe {
2241                 let buf = CString::new(sect.as_bytes()).unwrap();
2242                 llvm::LLVMSetSection(llval, buf.as_ptr());
2243             }
2244         },
2245         None => ()
2246     }
2247 }
2248
2249 pub fn trans_item(ccx: &CrateContext, item: &hir::Item) {
2250     let _icx = push_ctxt("trans_item");
2251
2252     let tcx = ccx.tcx();
2253     let from_external = ccx.external_srcs().borrow().contains_key(&item.id);
2254
2255     match item.node {
2256         hir::ItemFn(ref decl, _, _, _, ref generics, ref body) => {
2257             if !generics.is_type_parameterized() {
2258                 let trans_everywhere = attr::requests_inline(&item.attrs);
2259                 // Ignore `trans_everywhere` for cross-crate inlined items
2260                 // (`from_external`).  `trans_item` will be called once for each
2261                 // compilation unit that references the item, so it will still get
2262                 // translated everywhere it's needed.
2263                 for (ref ccx, is_origin) in ccx.maybe_iter(!from_external && trans_everywhere) {
2264                     let def_id = tcx.map.local_def_id(item.id);
2265                     let empty_substs = ccx.empty_substs_for_def_id(def_id);
2266                     let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
2267                     trans_fn(ccx, &decl, &body, llfn, empty_substs, item.id);
2268                     set_global_section(ccx, llfn, item);
2269                     update_linkage(ccx,
2270                                    llfn,
2271                                    Some(item.id),
2272                                    if is_origin {
2273                                        OriginalTranslation
2274                                    } else {
2275                                        InlinedCopy
2276                                    });
2277
2278                     if is_entry_fn(ccx.sess(), item.id) {
2279                         create_entry_wrapper(ccx, item.span, llfn);
2280                         // check for the #[rustc_error] annotation, which forces an
2281                         // error in trans. This is used to write compile-fail tests
2282                         // that actually test that compilation succeeds without
2283                         // reporting an error.
2284                         if tcx.has_attr(def_id, "rustc_error") {
2285                             tcx.sess.span_fatal(item.span, "compilation successful");
2286                         }
2287                     }
2288                 }
2289             }
2290         }
2291         hir::ItemImpl(_, _, ref generics, _, _, ref impl_items) => {
2292             // Both here and below with generic methods, be sure to recurse and look for
2293             // items that we need to translate.
2294             if !generics.ty_params.is_empty() {
2295                 return;
2296             }
2297
2298             for impl_item in impl_items {
2299                 if let hir::ImplItemKind::Method(ref sig, ref body) = impl_item.node {
2300                     if sig.generics.ty_params.is_empty() {
2301                         let trans_everywhere = attr::requests_inline(&impl_item.attrs);
2302                         for (ref ccx, is_origin) in ccx.maybe_iter(trans_everywhere) {
2303                             let def_id = tcx.map.local_def_id(impl_item.id);
2304                             let empty_substs = ccx.empty_substs_for_def_id(def_id);
2305                             let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
2306                             trans_fn(ccx, &sig.decl, body, llfn, empty_substs, impl_item.id);
2307                             update_linkage(ccx, llfn, Some(impl_item.id),
2308                                 if is_origin {
2309                                     OriginalTranslation
2310                                 } else {
2311                                     InlinedCopy
2312                                 });
2313                         }
2314                     }
2315                 }
2316             }
2317         }
2318         hir::ItemEnum(ref enum_definition, ref gens) => {
2319             if gens.ty_params.is_empty() {
2320                 // sizes only make sense for non-generic types
2321                 enum_variant_size_lint(ccx, enum_definition, item.span, item.id);
2322             }
2323         }
2324         hir::ItemStatic(_, m, ref expr) => {
2325             let g = match consts::trans_static(ccx, m, expr, item.id, &item.attrs) {
2326                 Ok(g) => g,
2327                 Err(err) => ccx.tcx().sess.span_fatal(expr.span, &err.description()),
2328             };
2329             set_global_section(ccx, g, item);
2330             update_linkage(ccx, g, Some(item.id), OriginalTranslation);
2331         }
2332         hir::ItemForeignMod(ref m) => {
2333             if m.abi == Abi::RustIntrinsic || m.abi == Abi::PlatformIntrinsic {
2334                 return;
2335             }
2336             for fi in &m.items {
2337                 let lname = imported_name(fi.name, &fi.attrs).to_string();
2338                 ccx.item_symbols().borrow_mut().insert(fi.id, lname);
2339             }
2340         }
2341         _ => {}
2342     }
2343 }
2344
2345 pub fn is_entry_fn(sess: &Session, node_id: ast::NodeId) -> bool {
2346     match *sess.entry_fn.borrow() {
2347         Some((entry_id, _)) => node_id == entry_id,
2348         None => false,
2349     }
2350 }
2351
2352 /// Create the `main` function which will initialise the rust runtime and call users’ main
2353 /// function.
2354 pub fn create_entry_wrapper(ccx: &CrateContext, sp: Span, main_llfn: ValueRef) {
2355     let et = ccx.sess().entry_type.get().unwrap();
2356     match et {
2357         config::EntryMain => {
2358             create_entry_fn(ccx, sp, main_llfn, true);
2359         }
2360         config::EntryStart => create_entry_fn(ccx, sp, main_llfn, false),
2361         config::EntryNone => {}    // Do nothing.
2362     }
2363
2364     fn create_entry_fn(ccx: &CrateContext,
2365                        sp: Span,
2366                        rust_main: ValueRef,
2367                        use_start_lang_item: bool) {
2368         let llfty = Type::func(&[ccx.int_type(), Type::i8p(ccx).ptr_to()], &ccx.int_type());
2369
2370         if declare::get_defined_value(ccx, "main").is_some() {
2371             // FIXME: We should be smart and show a better diagnostic here.
2372             ccx.sess().struct_span_err(sp, "entry symbol `main` defined multiple times")
2373                       .help("did you use #[no_mangle] on `fn main`? Use #[start] instead")
2374                       .emit();
2375             ccx.sess().abort_if_errors();
2376             panic!();
2377         }
2378         let llfn = declare::declare_cfn(ccx, "main", llfty);
2379
2380         let llbb = unsafe {
2381             llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llfn, "top\0".as_ptr() as *const _)
2382         };
2383         let bld = ccx.raw_builder();
2384         unsafe {
2385             llvm::LLVMPositionBuilderAtEnd(bld, llbb);
2386
2387             link_guard::insert_reference_to_link_guard(ccx, llbb);
2388             debuginfo::gdb::insert_reference_to_gdb_debug_scripts_section_global(ccx);
2389
2390             let (start_fn, args) = if use_start_lang_item {
2391                 let start_def_id = match ccx.tcx().lang_items.require(StartFnLangItem) {
2392                     Ok(id) => id,
2393                     Err(s) => ccx.sess().fatal(&s)
2394                 };
2395                 let empty_substs = ccx.tcx().mk_substs(Substs::empty());
2396                 let start_fn = Callee::def(ccx, start_def_id, empty_substs).reify(ccx).val;
2397                 let args = {
2398                     let opaque_rust_main =
2399                         llvm::LLVMBuildPointerCast(bld,
2400                                                    rust_main,
2401                                                    Type::i8p(ccx).to_ref(),
2402                                                    "rust_main\0".as_ptr() as *const _);
2403
2404                     vec![opaque_rust_main, get_param(llfn, 0), get_param(llfn, 1)]
2405                 };
2406                 (start_fn, args)
2407             } else {
2408                 debug!("using user-defined start fn");
2409                 let args = vec![get_param(llfn, 0 as c_uint), get_param(llfn, 1 as c_uint)];
2410
2411                 (rust_main, args)
2412             };
2413
2414             let result = llvm::LLVMRustBuildCall(bld,
2415                                                  start_fn,
2416                                                  args.as_ptr(),
2417                                                  args.len() as c_uint,
2418                                                  0 as *mut _,
2419                                                  noname());
2420
2421             llvm::LLVMBuildRet(bld, result);
2422         }
2423     }
2424 }
2425
2426 pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
2427                                instance: Instance<'tcx>,
2428                                attrs: &[ast::Attribute])
2429                                -> String {
2430     let id = ccx.tcx().map.as_local_node_id(instance.def).unwrap();
2431
2432     match ccx.external_srcs().borrow().get(&id) {
2433         Some(&did) => {
2434             let sym = ccx.sess().cstore.item_symbol(did);
2435             debug!("found item {} in other crate...", sym);
2436             return sym;
2437         }
2438         None => {}
2439     }
2440
2441     match attr::find_export_name_attr(ccx.sess().diagnostic(), attrs) {
2442         // Use provided name
2443         Some(name) => name.to_string(),
2444         _ => {
2445             if attr::contains_name(attrs, "no_mangle") {
2446                 // Don't mangle
2447                 let path = ccx.tcx().map.def_path_from_id(id);
2448                 path.data.last().unwrap().data.to_string()
2449             } else {
2450                 match weak_lang_items::link_name(attrs) {
2451                     Some(name) => name.to_string(),
2452                     None => {
2453                         // Usual name mangling
2454                         symbol_names::exported_name(ccx, &instance)
2455                     }
2456                 }
2457             }
2458         }
2459     }
2460 }
2461
2462 pub fn imported_name(name: ast::Name, attrs: &[ast::Attribute]) -> InternedString {
2463     match attr::first_attr_value_str_by_name(attrs, "link_name") {
2464         Some(ln) => ln.clone(),
2465         None => match weak_lang_items::link_name(attrs) {
2466             Some(name) => name,
2467             None => name.as_str(),
2468         }
2469     }
2470 }
2471
2472 fn contains_null(s: &str) -> bool {
2473     s.bytes().any(|b| b == 0)
2474 }
2475
2476 pub fn write_metadata<'a, 'tcx>(cx: &SharedCrateContext<'a, 'tcx>,
2477                                 krate: &hir::Crate,
2478                                 reachable: &NodeSet,
2479                                 mir_map: &MirMap<'tcx>)
2480                                 -> Vec<u8> {
2481     use flate;
2482
2483     let any_library = cx.sess()
2484                         .crate_types
2485                         .borrow()
2486                         .iter()
2487                         .any(|ty| *ty != config::CrateTypeExecutable);
2488     if !any_library {
2489         return Vec::new();
2490     }
2491
2492     let cstore = &cx.tcx().sess.cstore;
2493     let metadata = cstore.encode_metadata(cx.tcx(),
2494                                           cx.export_map(),
2495                                           cx.item_symbols(),
2496                                           cx.link_meta(),
2497                                           reachable,
2498                                           mir_map,
2499                                           krate);
2500     let mut compressed = cstore.metadata_encoding_version().to_vec();
2501     compressed.extend_from_slice(&flate::deflate_bytes(&metadata));
2502
2503     let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed[..]);
2504     let llconst = C_struct_in_context(cx.metadata_llcx(), &[llmeta], false);
2505     let name = format!("rust_metadata_{}_{}",
2506                        cx.link_meta().crate_name,
2507                        cx.link_meta().crate_hash);
2508     let buf = CString::new(name).unwrap();
2509     let llglobal = unsafe {
2510         llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(), buf.as_ptr())
2511     };
2512     unsafe {
2513         llvm::LLVMSetInitializer(llglobal, llconst);
2514         let name =
2515             cx.tcx().sess.cstore.metadata_section_name(&cx.sess().target.target);
2516         let name = CString::new(name).unwrap();
2517         llvm::LLVMSetSection(llglobal, name.as_ptr())
2518     }
2519     return metadata;
2520 }
2521
2522 /// Find any symbols that are defined in one compilation unit, but not declared
2523 /// in any other compilation unit.  Give these symbols internal linkage.
2524 fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<&str>) {
2525     unsafe {
2526         let mut declared = HashSet::new();
2527
2528         // Collect all external declarations in all compilation units.
2529         for ccx in cx.iter() {
2530             for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
2531                 let linkage = llvm::LLVMGetLinkage(val);
2532                 // We only care about external declarations (not definitions)
2533                 // and available_externally definitions.
2534                 if !(linkage == llvm::ExternalLinkage as c_uint &&
2535                      llvm::LLVMIsDeclaration(val) != 0) &&
2536                    !(linkage == llvm::AvailableExternallyLinkage as c_uint) {
2537                     continue;
2538                 }
2539
2540                 let name = CStr::from_ptr(llvm::LLVMGetValueName(val))
2541                                .to_bytes()
2542                                .to_vec();
2543                 declared.insert(name);
2544             }
2545         }
2546
2547         // Examine each external definition.  If the definition is not used in
2548         // any other compilation unit, and is not reachable from other crates,
2549         // then give it internal linkage.
2550         for ccx in cx.iter() {
2551             for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
2552                 // We only care about external definitions.
2553                 if !(llvm::LLVMGetLinkage(val) == llvm::ExternalLinkage as c_uint &&
2554                      llvm::LLVMIsDeclaration(val) == 0) {
2555                     continue;
2556                 }
2557
2558                 let name = CStr::from_ptr(llvm::LLVMGetValueName(val))
2559                                .to_bytes()
2560                                .to_vec();
2561                 if !declared.contains(&name) &&
2562                    !reachable.contains(str::from_utf8(&name).unwrap()) {
2563                     llvm::SetLinkage(val, llvm::InternalLinkage);
2564                     llvm::SetDLLStorageClass(val, llvm::DefaultStorageClass);
2565                 }
2566             }
2567         }
2568     }
2569 }
2570
2571 // Create a `__imp_<symbol> = &symbol` global for every public static `symbol`.
2572 // This is required to satisfy `dllimport` references to static data in .rlibs
2573 // when using MSVC linker.  We do this only for data, as linker can fix up
2574 // code references on its own.
2575 // See #26591, #27438
2576 fn create_imps(cx: &SharedCrateContext) {
2577     // The x86 ABI seems to require that leading underscores are added to symbol
2578     // names, so we need an extra underscore on 32-bit. There's also a leading
2579     // '\x01' here which disables LLVM's symbol mangling (e.g. no extra
2580     // underscores added in front).
2581     let prefix = if cx.sess().target.target.target_pointer_width == "32" {
2582         "\x01__imp__"
2583     } else {
2584         "\x01__imp_"
2585     };
2586     unsafe {
2587         for ccx in cx.iter() {
2588             let exported: Vec<_> = iter_globals(ccx.llmod())
2589                                        .filter(|&val| {
2590                                            llvm::LLVMGetLinkage(val) ==
2591                                            llvm::ExternalLinkage as c_uint &&
2592                                            llvm::LLVMIsDeclaration(val) == 0
2593                                        })
2594                                        .collect();
2595
2596             let i8p_ty = Type::i8p(&ccx);
2597             for val in exported {
2598                 let name = CStr::from_ptr(llvm::LLVMGetValueName(val));
2599                 let mut imp_name = prefix.as_bytes().to_vec();
2600                 imp_name.extend(name.to_bytes());
2601                 let imp_name = CString::new(imp_name).unwrap();
2602                 let imp = llvm::LLVMAddGlobal(ccx.llmod(),
2603                                               i8p_ty.to_ref(),
2604                                               imp_name.as_ptr() as *const _);
2605                 let init = llvm::LLVMConstBitCast(val, i8p_ty.to_ref());
2606                 llvm::LLVMSetInitializer(imp, init);
2607                 llvm::SetLinkage(imp, llvm::ExternalLinkage);
2608             }
2609         }
2610     }
2611 }
2612
2613 struct ValueIter {
2614     cur: ValueRef,
2615     step: unsafe extern "C" fn(ValueRef) -> ValueRef,
2616 }
2617
2618 impl Iterator for ValueIter {
2619     type Item = ValueRef;
2620
2621     fn next(&mut self) -> Option<ValueRef> {
2622         let old = self.cur;
2623         if !old.is_null() {
2624             self.cur = unsafe { (self.step)(old) };
2625             Some(old)
2626         } else {
2627             None
2628         }
2629     }
2630 }
2631
2632 fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter {
2633     unsafe {
2634         ValueIter {
2635             cur: llvm::LLVMGetFirstGlobal(llmod),
2636             step: llvm::LLVMGetNextGlobal,
2637         }
2638     }
2639 }
2640
2641 fn iter_functions(llmod: llvm::ModuleRef) -> ValueIter {
2642     unsafe {
2643         ValueIter {
2644             cur: llvm::LLVMGetFirstFunction(llmod),
2645             step: llvm::LLVMGetNextFunction,
2646         }
2647     }
2648 }
2649
2650 /// The context provided lists a set of reachable ids as calculated by
2651 /// middle::reachable, but this contains far more ids and symbols than we're
2652 /// actually exposing from the object file. This function will filter the set in
2653 /// the context to the set of ids which correspond to symbols that are exposed
2654 /// from the object file being generated.
2655 ///
2656 /// This list is later used by linkers to determine the set of symbols needed to
2657 /// be exposed from a dynamic library and it's also encoded into the metadata.
2658 pub fn filter_reachable_ids(ccx: &SharedCrateContext) -> NodeSet {
2659     ccx.reachable().iter().map(|x| *x).filter(|id| {
2660         // First, only worry about nodes which have a symbol name
2661         ccx.item_symbols().borrow().contains_key(id)
2662     }).filter(|&id| {
2663         // Next, we want to ignore some FFI functions that are not exposed from
2664         // this crate. Reachable FFI functions can be lumped into two
2665         // categories:
2666         //
2667         // 1. Those that are included statically via a static library
2668         // 2. Those included otherwise (e.g. dynamically or via a framework)
2669         //
2670         // Although our LLVM module is not literally emitting code for the
2671         // statically included symbols, it's an export of our library which
2672         // needs to be passed on to the linker and encoded in the metadata.
2673         //
2674         // As a result, if this id is an FFI item (foreign item) then we only
2675         // let it through if it's included statically.
2676         match ccx.tcx().map.get(id) {
2677             hir_map::NodeForeignItem(..) => {
2678                 ccx.sess().cstore.is_statically_included_foreign_item(id)
2679             }
2680             _ => true,
2681         }
2682     }).collect()
2683 }
2684
2685 pub fn trans_crate<'tcx>(tcx: &TyCtxt<'tcx>,
2686                          mir_map: &MirMap<'tcx>,
2687                          analysis: ty::CrateAnalysis)
2688                          -> CrateTranslation {
2689     let _task = tcx.dep_graph.in_task(DepNode::TransCrate);
2690
2691     // Be careful with this krate: obviously it gives access to the
2692     // entire contents of the krate. So if you push any subtasks of
2693     // `TransCrate`, you need to be careful to register "reads" of the
2694     // particular items that will be processed.
2695     let krate = tcx.map.krate();
2696
2697     let ty::CrateAnalysis { export_map, reachable, name, .. } = analysis;
2698
2699     let check_overflow = if let Some(v) = tcx.sess.opts.debugging_opts.force_overflow_checks {
2700         v
2701     } else {
2702         tcx.sess.opts.debug_assertions
2703     };
2704
2705     let check_dropflag = if let Some(v) = tcx.sess.opts.debugging_opts.force_dropflag_checks {
2706         v
2707     } else {
2708         tcx.sess.opts.debug_assertions
2709     };
2710
2711     // Before we touch LLVM, make sure that multithreading is enabled.
2712     unsafe {
2713         use std::sync::Once;
2714         static INIT: Once = Once::new();
2715         static mut POISONED: bool = false;
2716         INIT.call_once(|| {
2717             if llvm::LLVMStartMultithreaded() != 1 {
2718                 // use an extra bool to make sure that all future usage of LLVM
2719                 // cannot proceed despite the Once not running more than once.
2720                 POISONED = true;
2721             }
2722
2723             ::back::write::configure_llvm(&tcx.sess);
2724         });
2725
2726         if POISONED {
2727             tcx.sess.bug("couldn't enable multi-threaded LLVM");
2728         }
2729     }
2730
2731     let link_meta = link::build_link_meta(&tcx.sess, krate, name);
2732
2733     let codegen_units = tcx.sess.opts.cg.codegen_units;
2734     let shared_ccx = SharedCrateContext::new(&link_meta.crate_name,
2735                                              codegen_units,
2736                                              tcx,
2737                                              &mir_map,
2738                                              export_map,
2739                                              Sha256::new(),
2740                                              link_meta.clone(),
2741                                              reachable,
2742                                              check_overflow,
2743                                              check_dropflag);
2744
2745     {
2746         let ccx = shared_ccx.get_ccx(0);
2747
2748         // First, verify intrinsics.
2749         intrinsic::check_intrinsics(&ccx);
2750
2751         collect_translation_items(&ccx);
2752
2753         // Next, translate all items. See `TransModVisitor` for
2754         // details on why we walk in this particular way.
2755         {
2756             let _icx = push_ctxt("text");
2757             intravisit::walk_mod(&mut TransItemsWithinModVisitor { ccx: &ccx }, &krate.module);
2758             krate.visit_all_items(&mut TransModVisitor { ccx: &ccx });
2759         }
2760
2761         collector::print_collection_results(&ccx);
2762
2763         symbol_names_test::report_symbol_names(&ccx);
2764     }
2765
2766     emit_link_guard_if_necessary(&shared_ccx);
2767
2768     for ccx in shared_ccx.iter() {
2769         if ccx.sess().opts.debuginfo != NoDebugInfo {
2770             debuginfo::finalize(&ccx);
2771         }
2772         for &(old_g, new_g) in ccx.statics_to_rauw().borrow().iter() {
2773             unsafe {
2774                 let bitcast = llvm::LLVMConstPointerCast(new_g, llvm::LLVMTypeOf(old_g));
2775                 llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
2776                 llvm::LLVMDeleteGlobal(old_g);
2777             }
2778         }
2779     }
2780
2781     let reachable_symbol_ids = filter_reachable_ids(&shared_ccx);
2782
2783     // Translate the metadata.
2784     let metadata = time(tcx.sess.time_passes(), "write metadata", || {
2785         write_metadata(&shared_ccx, krate, &reachable_symbol_ids, mir_map)
2786     });
2787
2788     if shared_ccx.sess().trans_stats() {
2789         let stats = shared_ccx.stats();
2790         println!("--- trans stats ---");
2791         println!("n_glues_created: {}", stats.n_glues_created.get());
2792         println!("n_null_glues: {}", stats.n_null_glues.get());
2793         println!("n_real_glues: {}", stats.n_real_glues.get());
2794
2795         println!("n_fns: {}", stats.n_fns.get());
2796         println!("n_monos: {}", stats.n_monos.get());
2797         println!("n_inlines: {}", stats.n_inlines.get());
2798         println!("n_closures: {}", stats.n_closures.get());
2799         println!("fn stats:");
2800         stats.fn_stats.borrow_mut().sort_by(|&(_, insns_a), &(_, insns_b)| {
2801             insns_b.cmp(&insns_a)
2802         });
2803         for tuple in stats.fn_stats.borrow().iter() {
2804             match *tuple {
2805                 (ref name, insns) => {
2806                     println!("{} insns, {}", insns, *name);
2807                 }
2808             }
2809         }
2810     }
2811     if shared_ccx.sess().count_llvm_insns() {
2812         for (k, v) in shared_ccx.stats().llvm_insns.borrow().iter() {
2813             println!("{:7} {}", *v, *k);
2814         }
2815     }
2816
2817     let modules = shared_ccx.iter()
2818         .map(|ccx| ModuleTranslation { llcx: ccx.llcx(), llmod: ccx.llmod() })
2819         .collect();
2820
2821     let sess = shared_ccx.sess();
2822     let mut reachable_symbols = reachable_symbol_ids.iter().map(|id| {
2823         shared_ccx.item_symbols().borrow()[id].to_string()
2824     }).collect::<Vec<_>>();
2825     if sess.entry_fn.borrow().is_some() {
2826         reachable_symbols.push("main".to_string());
2827     }
2828     reachable_symbols.push(link_guard::link_guard_name(&link_meta.crate_name,
2829                                                        &link_meta.crate_hash));
2830
2831     // For the purposes of LTO, we add to the reachable set all of the upstream
2832     // reachable extern fns. These functions are all part of the public ABI of
2833     // the final product, so LTO needs to preserve them.
2834     if sess.lto() {
2835         for cnum in sess.cstore.crates() {
2836             let syms = sess.cstore.reachable_ids(cnum);
2837             reachable_symbols.extend(syms.into_iter().filter(|did| {
2838                 sess.cstore.is_extern_item(shared_ccx.tcx(), *did)
2839             }).map(|did| {
2840                 sess.cstore.item_symbol(did)
2841             }));
2842         }
2843     }
2844
2845     if codegen_units > 1 {
2846         internalize_symbols(&shared_ccx,
2847                             &reachable_symbols.iter().map(|x| &x[..]).collect());
2848     }
2849
2850     if sess.target.target.options.is_like_msvc &&
2851        sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib) {
2852         create_imps(&shared_ccx);
2853     }
2854
2855     let metadata_module = ModuleTranslation {
2856         llcx: shared_ccx.metadata_llcx(),
2857         llmod: shared_ccx.metadata_llmod(),
2858     };
2859     let no_builtins = attr::contains_name(&krate.attrs, "no_builtins");
2860
2861     assert_dep_graph::assert_dep_graph(tcx);
2862
2863     CrateTranslation {
2864         modules: modules,
2865         metadata_module: metadata_module,
2866         link: link_meta,
2867         metadata: metadata,
2868         reachable: reachable_symbols,
2869         no_builtins: no_builtins,
2870     }
2871 }
2872
2873 fn emit_link_guard_if_necessary(shared_ccx: &SharedCrateContext) {
2874     let link_meta = shared_ccx.link_meta();
2875     let link_guard_name = link_guard::link_guard_name(&link_meta.crate_name,
2876                                                       &link_meta.crate_hash);
2877     let link_guard_name = CString::new(link_guard_name).unwrap();
2878
2879     // Check if the link-guard has already been emitted in a codegen unit
2880     let link_guard_already_emitted = shared_ccx.iter().any(|ccx| {
2881         let link_guard = unsafe { llvm::LLVMGetNamedValue(ccx.llmod(),
2882                                                           link_guard_name.as_ptr()) };
2883         !link_guard.is_null()
2884     });
2885
2886     if !link_guard_already_emitted {
2887         link_guard::get_or_insert_link_guard(&shared_ccx.get_ccx(0));
2888     }
2889 }
2890
2891 /// We visit all the items in the krate and translate them.  We do
2892 /// this in two walks. The first walk just finds module items. It then
2893 /// walks the full contents of those module items and translates all
2894 /// the items within. Note that this entire process is O(n). The
2895 /// reason for this two phased walk is that each module is
2896 /// (potentially) placed into a distinct codegen-unit. This walk also
2897 /// ensures that the immediate contents of each module is processed
2898 /// entirely before we proceed to find more modules, helping to ensure
2899 /// an equitable distribution amongst codegen-units.
2900 pub struct TransModVisitor<'a, 'tcx: 'a> {
2901     pub ccx: &'a CrateContext<'a, 'tcx>,
2902 }
2903
2904 impl<'a, 'tcx, 'v> Visitor<'v> for TransModVisitor<'a, 'tcx> {
2905     fn visit_item(&mut self, i: &hir::Item) {
2906         match i.node {
2907             hir::ItemMod(_) => {
2908                 let item_ccx = self.ccx.rotate();
2909                 intravisit::walk_item(&mut TransItemsWithinModVisitor { ccx: &item_ccx }, i);
2910             }
2911             _ => { }
2912         }
2913     }
2914 }
2915
2916 /// Translates all the items within a given module. Expects owner to
2917 /// invoke `walk_item` on a module item. Ignores nested modules.
2918 pub struct TransItemsWithinModVisitor<'a, 'tcx: 'a> {
2919     pub ccx: &'a CrateContext<'a, 'tcx>,
2920 }
2921
2922 impl<'a, 'tcx, 'v> Visitor<'v> for TransItemsWithinModVisitor<'a, 'tcx> {
2923     fn visit_nested_item(&mut self, item_id: hir::ItemId) {
2924         self.visit_item(self.ccx.tcx().map.expect_item(item_id.id));
2925     }
2926
2927     fn visit_item(&mut self, i: &hir::Item) {
2928         match i.node {
2929             hir::ItemMod(..) => {
2930                 // skip modules, they will be uncovered by the TransModVisitor
2931             }
2932             _ => {
2933                 let def_id = self.ccx.tcx().map.local_def_id(i.id);
2934                 let tcx = self.ccx.tcx();
2935
2936                 // Create a subtask for trans'ing a particular item. We are
2937                 // giving `trans_item` access to this item, so also record a read.
2938                 tcx.dep_graph.with_task(DepNode::TransCrateItem(def_id), || {
2939                     tcx.dep_graph.read(DepNode::Hir(def_id));
2940
2941                     // We are going to be accessing various tables
2942                     // generated by TypeckItemBody; we also assume
2943                     // that the body passes type check. These tables
2944                     // are not individually tracked, so just register
2945                     // a read here.
2946                     tcx.dep_graph.read(DepNode::TypeckItemBody(def_id));
2947
2948                     trans_item(self.ccx, i);
2949                 });
2950
2951                 intravisit::walk_item(self, i);
2952             }
2953         }
2954     }
2955 }
2956
2957 fn collect_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>) {
2958     let time_passes = ccx.sess().time_passes();
2959
2960     let collection_mode = match ccx.sess().opts.debugging_opts.print_trans_items {
2961         Some(ref s) => {
2962             let mode_string = s.to_lowercase();
2963             let mode_string = mode_string.trim();
2964             if mode_string == "eager" {
2965                 TransItemCollectionMode::Eager
2966             } else {
2967                 if mode_string != "lazy" {
2968                     let message = format!("Unknown codegen-item collection mode '{}'. \
2969                                            Falling back to 'lazy' mode.",
2970                                            mode_string);
2971                     ccx.sess().warn(&message);
2972                 }
2973
2974                 TransItemCollectionMode::Lazy
2975             }
2976         }
2977         None => TransItemCollectionMode::Lazy
2978     };
2979
2980     let items = time(time_passes, "translation item collection", || {
2981         collector::collect_crate_translation_items(&ccx, collection_mode)
2982     });
2983
2984     if ccx.sess().opts.debugging_opts.print_trans_items.is_some() {
2985         let mut item_keys: Vec<_> = items.iter()
2986                                          .map(|i| i.to_string(ccx))
2987                                          .collect();
2988         item_keys.sort();
2989
2990         for item in item_keys {
2991             println!("TRANS_ITEM {}", item);
2992         }
2993
2994         let mut ccx_map = ccx.translation_items().borrow_mut();
2995
2996         for cgi in items {
2997             ccx_map.insert(cgi, TransItemState::PredictedButNotGenerated);
2998         }
2999     }
3000 }