]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/trans/base.rs
Re-word explanation on closures in intro
[rust.git] / src / librustc_trans / trans / base.rs
1 // Copyright 2012-2014 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 // trans.rs: 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 // trans_impl, 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::{mangle_exported_name};
34 use back::{link, abi};
35 use lint;
36 use llvm::{AttrHelper, BasicBlockRef, Linkage, ValueRef, Vector, get_param};
37 use llvm;
38 use metadata::{csearch, encoder, loader};
39 use middle::astencode;
40 use middle::cfg;
41 use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
42 use middle::weak_lang_items;
43 use middle::subst::{Subst, Substs};
44 use middle::ty::{self, Ty, ClosureTyper};
45 use session::config::{self, NoDebugInfo};
46 use session::Session;
47 use trans::_match;
48 use trans::adt;
49 use trans::build::*;
50 use trans::builder::{Builder, noname};
51 use trans::callee;
52 use trans::cleanup::CleanupMethods;
53 use trans::cleanup;
54 use trans::closure;
55 use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_integral};
56 use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef};
57 use trans::common::{CrateContext, ExternMap, FunctionContext};
58 use trans::common::{Result, NodeIdAndSpan};
59 use trans::common::{node_id_type, return_type_is_void};
60 use trans::common::{type_is_immediate, type_is_zero_size, val_ty};
61 use trans::common;
62 use trans::consts;
63 use trans::context::SharedCrateContext;
64 use trans::controlflow;
65 use trans::datum;
66 use trans::debuginfo::{self, DebugLoc, ToDebugLoc};
67 use trans::expr;
68 use trans::foreign;
69 use trans::glue;
70 use trans::inline;
71 use trans::intrinsic;
72 use trans::machine;
73 use trans::machine::{llsize_of, llsize_of_real};
74 use trans::meth;
75 use trans::monomorphize;
76 use trans::tvec;
77 use trans::type_::Type;
78 use trans::type_of;
79 use trans::type_of::*;
80 use trans::value::Value;
81 use util::common::indenter;
82 use util::ppaux::{Repr, ty_to_string};
83 use util::sha2::Sha256;
84 use util::nodemap::NodeMap;
85
86 use arena::TypedArena;
87 use libc::{c_uint, uint64_t};
88 use std::ffi::{CStr, CString};
89 use std::cell::{Cell, RefCell};
90 use std::collections::HashSet;
91 use std::mem;
92 use std::str;
93 use std::{i8, i16, i32, i64};
94 use syntax::abi::{Rust, RustCall, RustIntrinsic, Abi};
95 use syntax::ast_util::local_def;
96 use syntax::attr::AttrMetaMethods;
97 use syntax::attr;
98 use syntax::codemap::Span;
99 use syntax::parse::token::InternedString;
100 use syntax::visit::Visitor;
101 use syntax::visit;
102 use syntax::{ast, ast_util, ast_map};
103
104 thread_local! {
105     static TASK_LOCAL_INSN_KEY: RefCell<Option<Vec<&'static str>>> = {
106         RefCell::new(None)
107     }
108 }
109
110 pub fn with_insn_ctxt<F>(blk: F) where
111     F: FnOnce(&[&'static str]),
112 {
113     TASK_LOCAL_INSN_KEY.with(move |slot| {
114         slot.borrow().as_ref().map(move |s| blk(s));
115     })
116 }
117
118 pub fn init_insn_ctxt() {
119     TASK_LOCAL_INSN_KEY.with(|slot| {
120         *slot.borrow_mut() = Some(Vec::new());
121     });
122 }
123
124 pub struct _InsnCtxt {
125     _cannot_construct_outside_of_this_module: ()
126 }
127
128 #[unsafe_destructor]
129 impl Drop for _InsnCtxt {
130     fn drop(&mut self) {
131         TASK_LOCAL_INSN_KEY.with(|slot| {
132             match slot.borrow_mut().as_mut() {
133                 Some(ctx) => { ctx.pop(); }
134                 None => {}
135             }
136         })
137     }
138 }
139
140 pub fn push_ctxt(s: &'static str) -> _InsnCtxt {
141     debug!("new InsnCtxt: {}", s);
142     TASK_LOCAL_INSN_KEY.with(|slot| {
143         match slot.borrow_mut().as_mut() {
144             Some(ctx) => ctx.push(s),
145             None => {}
146         }
147     });
148     _InsnCtxt { _cannot_construct_outside_of_this_module: () }
149 }
150
151 pub struct StatRecorder<'a, 'tcx: 'a> {
152     ccx: &'a CrateContext<'a, 'tcx>,
153     name: Option<String>,
154     istart: uint,
155 }
156
157 impl<'a, 'tcx> StatRecorder<'a, 'tcx> {
158     pub fn new(ccx: &'a CrateContext<'a, 'tcx>, name: String)
159                -> StatRecorder<'a, 'tcx> {
160         let istart = ccx.stats().n_llvm_insns.get();
161         StatRecorder {
162             ccx: ccx,
163             name: Some(name),
164             istart: istart,
165         }
166     }
167 }
168
169 #[unsafe_destructor]
170 impl<'a, 'tcx> Drop for StatRecorder<'a, 'tcx> {
171     fn drop(&mut self) {
172         if self.ccx.sess().trans_stats() {
173             let iend = self.ccx.stats().n_llvm_insns.get();
174             self.ccx.stats().fn_stats.borrow_mut().push((self.name.take().unwrap(),
175                                                        iend - self.istart));
176             self.ccx.stats().n_fns.set(self.ccx.stats().n_fns.get() + 1);
177             // Reset LLVM insn count to avoid compound costs.
178             self.ccx.stats().n_llvm_insns.set(self.istart);
179         }
180     }
181 }
182
183 // only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
184 pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv,
185                ty: Type, output: ty::FnOutput) -> ValueRef {
186
187     let buf = CString::new(name).unwrap();
188     let llfn: ValueRef = unsafe {
189         llvm::LLVMGetOrInsertFunction(ccx.llmod(), buf.as_ptr(), ty.to_ref())
190     };
191
192     // diverging functions may unwind, but can never return normally
193     if output == ty::FnDiverging {
194         llvm::SetFunctionAttribute(llfn, llvm::NoReturnAttribute);
195     }
196
197     if ccx.tcx().sess.opts.cg.no_redzone
198         .unwrap_or(ccx.tcx().sess.target.target.options.disable_redzone) {
199         llvm::SetFunctionAttribute(llfn, llvm::NoRedZoneAttribute)
200     }
201
202     llvm::SetFunctionCallConv(llfn, cc);
203     // Function addresses in Rust are never significant, allowing functions to be merged.
204     llvm::SetUnnamedAddr(llfn, true);
205
206     if ccx.is_split_stack_supported() && !ccx.sess().opts.cg.no_stack_check {
207         set_split_stack(llfn);
208     }
209
210     llfn
211 }
212
213 // only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
214 pub fn decl_cdecl_fn(ccx: &CrateContext,
215                      name: &str,
216                      ty: Type,
217                      output: Ty) -> ValueRef {
218     decl_fn(ccx, name, llvm::CCallConv, ty, ty::FnConverging(output))
219 }
220
221 // only use this for foreign function ABIs and glue, use `get_extern_rust_fn` for Rust functions
222 pub fn get_extern_fn(ccx: &CrateContext,
223                      externs: &mut ExternMap,
224                      name: &str,
225                      cc: llvm::CallConv,
226                      ty: Type,
227                      output: Ty)
228                      -> ValueRef {
229     match externs.get(name) {
230         Some(n) => return *n,
231         None => {}
232     }
233     let f = decl_fn(ccx, name, cc, ty, ty::FnConverging(output));
234     externs.insert(name.to_string(), f);
235     f
236 }
237
238 fn get_extern_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<'tcx>,
239                                 name: &str, did: ast::DefId) -> ValueRef {
240     match ccx.externs().borrow().get(name) {
241         Some(n) => return *n,
242         None => ()
243     }
244
245     let f = decl_rust_fn(ccx, fn_ty, name);
246
247     let attrs = csearch::get_item_attrs(&ccx.sess().cstore, did);
248     set_llvm_fn_attrs(ccx, &attrs[..], f);
249
250     ccx.externs().borrow_mut().insert(name.to_string(), f);
251     f
252 }
253
254 pub fn self_type_for_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
255                                        closure_id: ast::DefId,
256                                        fn_ty: Ty<'tcx>)
257                                        -> Ty<'tcx>
258 {
259     let closure_kind = ccx.tcx().closure_kind(closure_id);
260     match closure_kind {
261         ty::FnClosureKind => {
262             ty::mk_imm_rptr(ccx.tcx(), ccx.tcx().mk_region(ty::ReStatic), fn_ty)
263         }
264         ty::FnMutClosureKind => {
265             ty::mk_mut_rptr(ccx.tcx(), ccx.tcx().mk_region(ty::ReStatic), fn_ty)
266         }
267         ty::FnOnceClosureKind => fn_ty
268     }
269 }
270
271 pub fn kind_for_closure(ccx: &CrateContext, closure_id: ast::DefId) -> ty::ClosureKind {
272     ccx.tcx().closure_kinds.borrow()[closure_id]
273 }
274
275 pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
276                               fn_ty: Ty<'tcx>, name: &str) -> ValueRef {
277     debug!("decl_rust_fn(fn_ty={}, name={:?})",
278            fn_ty.repr(ccx.tcx()),
279            name);
280
281     let fn_ty = monomorphize::normalize_associated_type(ccx.tcx(), &fn_ty);
282
283     debug!("decl_rust_fn: fn_ty={} (after normalized associated types)",
284            fn_ty.repr(ccx.tcx()));
285
286     let function_type; // placeholder so that the memory ownership works out ok
287
288     let (sig, abi, env) = match fn_ty.sty {
289         ty::ty_bare_fn(_, ref f) => {
290             (&f.sig, f.abi, None)
291         }
292         ty::ty_closure(closure_did, substs) => {
293             let typer = common::NormalizingClosureTyper::new(ccx.tcx());
294             function_type = typer.closure_type(closure_did, substs);
295             let self_type = self_type_for_closure(ccx, closure_did, fn_ty);
296             let llenvironment_type = type_of_explicit_arg(ccx, self_type);
297             debug!("decl_rust_fn: function_type={} self_type={}",
298                    function_type.repr(ccx.tcx()),
299                    self_type.repr(ccx.tcx()));
300             (&function_type.sig, RustCall, Some(llenvironment_type))
301         }
302         _ => ccx.sess().bug("expected closure or fn")
303     };
304
305     let sig = ty::erase_late_bound_regions(ccx.tcx(), sig);
306     let sig = ty::Binder(sig);
307
308     debug!("decl_rust_fn: sig={} (after erasing regions)",
309            sig.repr(ccx.tcx()));
310
311     let llfty = type_of_rust_fn(ccx, env, &sig, abi);
312
313     debug!("decl_rust_fn: llfty={}",
314            ccx.tn().type_to_string(llfty));
315
316     let llfn = decl_fn(ccx, name, llvm::CCallConv, llfty, sig.0.output /* (1) */);
317     let attrs = get_fn_llvm_attributes(ccx, fn_ty);
318     attrs.apply_llfn(llfn);
319
320     // (1) it's ok to directly access sig.0.output because we erased all late-bound-regions above
321
322     llfn
323 }
324
325 pub fn decl_internal_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
326                                        fn_ty: Ty<'tcx>, name: &str) -> ValueRef {
327     let llfn = decl_rust_fn(ccx, fn_ty, name);
328     llvm::SetLinkage(llfn, llvm::InternalLinkage);
329     llfn
330 }
331
332 pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId,
333                                   t: Ty<'tcx>) -> ValueRef {
334     let name = csearch::get_symbol(&ccx.sess().cstore, did);
335     let ty = type_of(ccx, t);
336     match ccx.externs().borrow_mut().get(&name) {
337         Some(n) => return *n,
338         None => ()
339     }
340     unsafe {
341         let buf = CString::new(name.clone()).unwrap();
342         let c = llvm::LLVMAddGlobal(ccx.llmod(), ty.to_ref(), buf.as_ptr());
343         // Thread-local statics in some other crate need to *always* be linked
344         // against in a thread-local fashion, so we need to be sure to apply the
345         // thread-local attribute locally if it was present remotely. If we
346         // don't do this then linker errors can be generated where the linker
347         // complains that one object files has a thread local version of the
348         // symbol and another one doesn't.
349         for attr in &*ty::get_attrs(ccx.tcx(), did) {
350             if attr.check_name("thread_local") {
351                 llvm::set_thread_local(c, true);
352             }
353         }
354         ccx.externs().borrow_mut().insert(name.to_string(), c);
355         return c;
356     }
357 }
358
359 fn require_alloc_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
360                                 info_ty: Ty<'tcx>, it: LangItem) -> ast::DefId {
361     match bcx.tcx().lang_items.require(it) {
362         Ok(id) => id,
363         Err(s) => {
364             bcx.sess().fatal(&format!("allocation of `{}` {}",
365                                      bcx.ty_to_string(info_ty),
366                                      s));
367         }
368     }
369 }
370
371 // The following malloc_raw_dyn* functions allocate a box to contain
372 // a given type, but with a potentially dynamic size.
373
374 pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
375                                   llty_ptr: Type,
376                                   info_ty: Ty<'tcx>,
377                                   size: ValueRef,
378                                   align: ValueRef,
379                                   debug_loc: DebugLoc)
380                                   -> Result<'blk, 'tcx> {
381     let _icx = push_ctxt("malloc_raw_exchange");
382
383     // Allocate space:
384     let r = callee::trans_lang_call(bcx,
385         require_alloc_fn(bcx, info_ty, ExchangeMallocFnLangItem),
386         &[size, align],
387         None,
388         debug_loc);
389
390     Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr))
391 }
392
393 #[allow(dead_code)] // useful
394 pub fn set_optimize_for_size(f: ValueRef) {
395     llvm::SetFunctionAttribute(f, llvm::OptimizeForSizeAttribute)
396 }
397
398 pub fn set_no_inline(f: ValueRef) {
399     llvm::SetFunctionAttribute(f, llvm::NoInlineAttribute)
400 }
401
402 #[allow(dead_code)] // useful
403 pub fn set_no_unwind(f: ValueRef) {
404     llvm::SetFunctionAttribute(f, llvm::NoUnwindAttribute)
405 }
406
407 // Tell LLVM to emit the information necessary to unwind the stack for the
408 // function f.
409 pub fn set_uwtable(f: ValueRef) {
410     llvm::SetFunctionAttribute(f, llvm::UWTableAttribute)
411 }
412
413 pub fn set_inline_hint(f: ValueRef) {
414     llvm::SetFunctionAttribute(f, llvm::InlineHintAttribute)
415 }
416
417 pub fn set_llvm_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) {
418     use syntax::attr::{find_inline_attr, InlineAttr};
419     // Set the inline hint if there is one
420     match find_inline_attr(Some(ccx.sess().diagnostic()), attrs) {
421         InlineAttr::Hint   => set_inline_hint(llfn),
422         InlineAttr::Always => set_always_inline(llfn),
423         InlineAttr::Never  => set_no_inline(llfn),
424         InlineAttr::None   => { /* fallthrough */ }
425     }
426
427     for attr in attrs {
428         let mut used = true;
429         match &attr.name()[..] {
430             "no_stack_check" => unset_split_stack(llfn),
431             "no_split_stack" => {
432                 unset_split_stack(llfn);
433                 ccx.sess().span_warn(attr.span,
434                                      "no_split_stack is a deprecated synonym for no_stack_check");
435             }
436             "cold" => unsafe {
437                 llvm::LLVMAddFunctionAttribute(llfn,
438                                                llvm::FunctionIndex as c_uint,
439                                                llvm::ColdAttribute as uint64_t)
440             },
441             "allocator" => {
442                 llvm::NoAliasAttribute.apply_llfn(llvm::ReturnIndex as c_uint, llfn);
443             }
444             _ => used = false,
445         }
446         if used {
447             attr::mark_used(attr);
448         }
449     }
450 }
451
452 pub fn set_always_inline(f: ValueRef) {
453     llvm::SetFunctionAttribute(f, llvm::AlwaysInlineAttribute)
454 }
455
456 pub fn set_split_stack(f: ValueRef) {
457     unsafe {
458         llvm::LLVMAddFunctionAttrString(f, llvm::FunctionIndex as c_uint,
459                                         "split-stack\0".as_ptr() as *const _);
460     }
461 }
462
463 pub fn unset_split_stack(f: ValueRef) {
464     unsafe {
465         llvm::LLVMRemoveFunctionAttrString(f, llvm::FunctionIndex as c_uint,
466                                            "split-stack\0".as_ptr() as *const _);
467     }
468 }
469
470 // Double-check that we never ask LLVM to declare the same symbol twice. It
471 // silently mangles such symbols, breaking our linkage model.
472 pub fn note_unique_llvm_symbol(ccx: &CrateContext, sym: String) {
473     if ccx.all_llvm_symbols().borrow().contains(&sym) {
474         ccx.sess().bug(&format!("duplicate LLVM symbol: {}", sym));
475     }
476     ccx.all_llvm_symbols().borrow_mut().insert(sym);
477 }
478
479
480 pub fn get_res_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
481                               did: ast::DefId,
482                               t: Ty<'tcx>,
483                               parent_id: ast::DefId,
484                               substs: &Substs<'tcx>)
485                               -> ValueRef {
486     let _icx = push_ctxt("trans_res_dtor");
487     let did = inline::maybe_instantiate_inline(ccx, did);
488
489     if !substs.types.is_empty() {
490         assert_eq!(did.krate, ast::LOCAL_CRATE);
491
492         // Since we're in trans we don't care for any region parameters
493         let substs = ccx.tcx().mk_substs(Substs::erased(substs.types.clone()));
494
495         let (val, _, _) = monomorphize::monomorphic_fn(ccx, did, substs, None);
496
497         val
498     } else if did.krate == ast::LOCAL_CRATE {
499         get_item_val(ccx, did.node)
500     } else {
501         let tcx = ccx.tcx();
502         let name = csearch::get_symbol(&ccx.sess().cstore, did);
503         let class_ty = ty::lookup_item_type(tcx, parent_id).ty.subst(tcx, substs);
504         let llty = type_of_dtor(ccx, class_ty);
505         let dtor_ty = ty::mk_ctor_fn(ccx.tcx(),
506                                      did,
507                                      &[glue::get_drop_glue_type(ccx, t)],
508                                      ty::mk_nil(ccx.tcx()));
509         get_extern_fn(ccx,
510                       &mut *ccx.externs().borrow_mut(),
511                       &name[..],
512                       llvm::CCallConv,
513                       llty,
514                       dtor_ty)
515     }
516 }
517
518 pub fn bin_op_to_icmp_predicate(ccx: &CrateContext, op: ast::BinOp_, signed: bool)
519                                 -> llvm::IntPredicate {
520     match op {
521         ast::BiEq => llvm::IntEQ,
522         ast::BiNe => llvm::IntNE,
523         ast::BiLt => if signed { llvm::IntSLT } else { llvm::IntULT },
524         ast::BiLe => if signed { llvm::IntSLE } else { llvm::IntULE },
525         ast::BiGt => if signed { llvm::IntSGT } else { llvm::IntUGT },
526         ast::BiGe => if signed { llvm::IntSGE } else { llvm::IntUGE },
527         op => {
528             ccx.sess().bug(&format!("comparison_op_to_icmp_predicate: expected \
529                                      comparison operator, found {:?}", op));
530         }
531     }
532 }
533
534 pub fn bin_op_to_fcmp_predicate(ccx: &CrateContext, op: ast::BinOp_)
535                                 -> llvm::RealPredicate {
536     match op {
537         ast::BiEq => llvm::RealOEQ,
538         ast::BiNe => llvm::RealUNE,
539         ast::BiLt => llvm::RealOLT,
540         ast::BiLe => llvm::RealOLE,
541         ast::BiGt => llvm::RealOGT,
542         ast::BiGe => llvm::RealOGE,
543         op => {
544             ccx.sess().bug(&format!("comparison_op_to_fcmp_predicate: expected \
545                                      comparison operator, found {:?}", op));
546         }
547     }
548 }
549
550 pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
551                                         lhs: ValueRef,
552                                         rhs: ValueRef,
553                                         t: Ty<'tcx>,
554                                         op: ast::BinOp_,
555                                         debug_loc: DebugLoc)
556                                         -> ValueRef {
557     match t.sty {
558         ty::ty_tup(ref tys) if tys.is_empty() => {
559             // We don't need to do actual comparisons for nil.
560             // () == () holds but () < () does not.
561             match op {
562                 ast::BiEq | ast::BiLe | ast::BiGe => return C_bool(bcx.ccx(), true),
563                 ast::BiNe | ast::BiLt | ast::BiGt => return C_bool(bcx.ccx(), false),
564                 // refinements would be nice
565                 _ => bcx.sess().bug("compare_scalar_types: must be a comparison operator")
566             }
567         }
568         ty::ty_bool | ty::ty_uint(_) | ty::ty_char => {
569             ICmp(bcx, bin_op_to_icmp_predicate(bcx.ccx(), op, false), lhs, rhs, debug_loc)
570         }
571         ty::ty_ptr(mt) if common::type_is_sized(bcx.tcx(), mt.ty) => {
572             ICmp(bcx, bin_op_to_icmp_predicate(bcx.ccx(), op, false), lhs, rhs, debug_loc)
573         }
574         ty::ty_int(_) => {
575             ICmp(bcx, bin_op_to_icmp_predicate(bcx.ccx(), op, true), lhs, rhs, debug_loc)
576         }
577         ty::ty_float(_) => {
578             FCmp(bcx, bin_op_to_fcmp_predicate(bcx.ccx(), op), lhs, rhs, debug_loc)
579         }
580         // Should never get here, because t is scalar.
581         _ => bcx.sess().bug("non-scalar type passed to compare_scalar_types")
582     }
583 }
584
585 pub fn compare_simd_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
586                                       lhs: ValueRef,
587                                       rhs: ValueRef,
588                                       t: Ty<'tcx>,
589                                       op: ast::BinOp_,
590                                       debug_loc: DebugLoc)
591                                       -> ValueRef {
592     let signed = match t.sty {
593         ty::ty_float(_) => {
594             // The comparison operators for floating point vectors are challenging.
595             // LLVM outputs a `< size x i1 >`, but if we perform a sign extension
596             // then bitcast to a floating point vector, the result will be `-NaN`
597             // for each truth value. Because of this they are unsupported.
598             bcx.sess().bug("compare_simd_types: comparison operators \
599                             not supported for floating point SIMD types")
600         },
601         ty::ty_uint(_) => false,
602         ty::ty_int(_) => true,
603         _ => bcx.sess().bug("compare_simd_types: invalid SIMD type"),
604     };
605
606     let cmp = bin_op_to_icmp_predicate(bcx.ccx(), op, signed);
607     // LLVM outputs an `< size x i1 >`, so we need to perform a sign extension
608     // to get the correctly sized type. This will compile to a single instruction
609     // once the IR is converted to assembly if the SIMD instruction is supported
610     // by the target architecture.
611     SExt(bcx, ICmp(bcx, cmp, lhs, rhs, debug_loc), val_ty(lhs))
612 }
613
614 // Iterates through the elements of a structural type.
615 pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
616                                          av: ValueRef,
617                                          t: Ty<'tcx>,
618                                          mut f: F)
619                                          -> Block<'blk, 'tcx> where
620     F: FnMut(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>,
621 {
622     let _icx = push_ctxt("iter_structural_ty");
623
624     fn iter_variant<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
625                                    repr: &adt::Repr<'tcx>,
626                                    av: ValueRef,
627                                    variant: &ty::VariantInfo<'tcx>,
628                                    substs: &Substs<'tcx>,
629                                    f: &mut F)
630                                    -> Block<'blk, 'tcx> where
631         F: FnMut(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>,
632     {
633         let _icx = push_ctxt("iter_variant");
634         let tcx = cx.tcx();
635         let mut cx = cx;
636
637         for (i, &arg) in variant.args.iter().enumerate() {
638             let arg = monomorphize::apply_param_substs(tcx, substs, &arg);
639             cx = f(cx, adt::trans_field_ptr(cx, repr, av, variant.disr_val, i), arg);
640         }
641         return cx;
642     }
643
644     let (data_ptr, info) = if common::type_is_sized(cx.tcx(), t) {
645         (av, None)
646     } else {
647         let data = GEPi(cx, av, &[0, abi::FAT_PTR_ADDR]);
648         let info = GEPi(cx, av, &[0, abi::FAT_PTR_EXTRA]);
649         (Load(cx, data), Some(Load(cx, info)))
650     };
651
652     let mut cx = cx;
653     match t.sty {
654       ty::ty_struct(..) => {
655           let repr = adt::represent_type(cx.ccx(), t);
656           expr::with_field_tys(cx.tcx(), t, None, |discr, field_tys| {
657               for (i, field_ty) in field_tys.iter().enumerate() {
658                   let field_ty = field_ty.mt.ty;
659                   let llfld_a = adt::trans_field_ptr(cx, &*repr, data_ptr, discr, i);
660
661                   let val = if common::type_is_sized(cx.tcx(), field_ty) {
662                       llfld_a
663                   } else {
664                       let scratch = datum::rvalue_scratch_datum(cx, field_ty, "__fat_ptr_iter");
665                       Store(cx, llfld_a, GEPi(cx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
666                       Store(cx, info.unwrap(), GEPi(cx, scratch.val, &[0, abi::FAT_PTR_EXTRA]));
667                       scratch.val
668                   };
669                   cx = f(cx, val, field_ty);
670               }
671           })
672       }
673       ty::ty_closure(def_id, substs) => {
674           let repr = adt::represent_type(cx.ccx(), t);
675           let typer = common::NormalizingClosureTyper::new(cx.tcx());
676           let upvars = typer.closure_upvars(def_id, substs).unwrap();
677           for (i, upvar) in upvars.iter().enumerate() {
678               let llupvar = adt::trans_field_ptr(cx, &*repr, data_ptr, 0, i);
679               cx = f(cx, llupvar, upvar.ty);
680           }
681       }
682       ty::ty_vec(_, Some(n)) => {
683         let (base, len) = tvec::get_fixed_base_and_len(cx, data_ptr, n);
684         let unit_ty = ty::sequence_element_type(cx.tcx(), t);
685         cx = tvec::iter_vec_raw(cx, base, unit_ty, len, f);
686       }
687       ty::ty_vec(_, None) | ty::ty_str => {
688         let unit_ty = ty::sequence_element_type(cx.tcx(), t);
689         cx = tvec::iter_vec_raw(cx, data_ptr, unit_ty, info.unwrap(), f);
690       }
691       ty::ty_tup(ref args) => {
692           let repr = adt::represent_type(cx.ccx(), t);
693           for (i, arg) in args.iter().enumerate() {
694               let llfld_a = adt::trans_field_ptr(cx, &*repr, data_ptr, 0, i);
695               cx = f(cx, llfld_a, *arg);
696           }
697       }
698       ty::ty_enum(tid, substs) => {
699           let fcx = cx.fcx;
700           let ccx = fcx.ccx;
701
702           let repr = adt::represent_type(ccx, t);
703           let variants = ty::enum_variants(ccx.tcx(), tid);
704           let n_variants = (*variants).len();
705
706           // NB: we must hit the discriminant first so that structural
707           // comparison know not to proceed when the discriminants differ.
708
709           match adt::trans_switch(cx, &*repr, av) {
710               (_match::Single, None) => {
711                   cx = iter_variant(cx, &*repr, av, &*(*variants)[0],
712                                     substs, &mut f);
713               }
714               (_match::Switch, Some(lldiscrim_a)) => {
715                   cx = f(cx, lldiscrim_a, cx.tcx().types.int);
716                   let unr_cx = fcx.new_temp_block("enum-iter-unr");
717                   Unreachable(unr_cx);
718                   let llswitch = Switch(cx, lldiscrim_a, unr_cx.llbb,
719                                         n_variants);
720                   let next_cx = fcx.new_temp_block("enum-iter-next");
721
722                   for variant in &(*variants) {
723                       let variant_cx =
724                           fcx.new_temp_block(
725                               &format!("enum-iter-variant-{}",
726                                       &variant.disr_val.to_string())
727                               );
728                       match adt::trans_case(cx, &*repr, variant.disr_val) {
729                           _match::SingleResult(r) => {
730                               AddCase(llswitch, r.val, variant_cx.llbb)
731                           }
732                           _ => ccx.sess().unimpl("value from adt::trans_case \
733                                                   in iter_structural_ty")
734                       }
735                       let variant_cx =
736                           iter_variant(variant_cx,
737                                        &*repr,
738                                        data_ptr,
739                                        &**variant,
740                                        substs,
741                                        &mut f);
742                       Br(variant_cx, next_cx.llbb, DebugLoc::None);
743                   }
744                   cx = next_cx;
745               }
746               _ => ccx.sess().unimpl("value from adt::trans_switch \
747                                       in iter_structural_ty")
748           }
749       }
750       _ => {
751           cx.sess().unimpl(&format!("type in iter_structural_ty: {}",
752                                    ty_to_string(cx.tcx(), t)))
753       }
754     }
755     return cx;
756 }
757
758 pub fn cast_shift_expr_rhs(cx: Block,
759                            op: ast::BinOp,
760                            lhs: ValueRef,
761                            rhs: ValueRef)
762                            -> ValueRef {
763     cast_shift_rhs(op, lhs, rhs,
764                    |a,b| Trunc(cx, a, b),
765                    |a,b| ZExt(cx, a, b))
766 }
767
768 pub fn cast_shift_const_rhs(op: ast::BinOp,
769                             lhs: ValueRef, rhs: ValueRef) -> ValueRef {
770     cast_shift_rhs(op, lhs, rhs,
771                    |a, b| unsafe { llvm::LLVMConstTrunc(a, b.to_ref()) },
772                    |a, b| unsafe { llvm::LLVMConstZExt(a, b.to_ref()) })
773 }
774
775 pub fn cast_shift_rhs<F, G>(op: ast::BinOp,
776                             lhs: ValueRef,
777                             rhs: ValueRef,
778                             trunc: F,
779                             zext: G)
780                             -> ValueRef where
781     F: FnOnce(ValueRef, Type) -> ValueRef,
782     G: FnOnce(ValueRef, Type) -> ValueRef,
783 {
784     // Shifts may have any size int on the rhs
785     if ast_util::is_shift_binop(op.node) {
786         let mut rhs_llty = val_ty(rhs);
787         let mut lhs_llty = val_ty(lhs);
788         if rhs_llty.kind() == Vector { rhs_llty = rhs_llty.element_type() }
789         if lhs_llty.kind() == Vector { lhs_llty = lhs_llty.element_type() }
790         let rhs_sz = rhs_llty.int_width();
791         let lhs_sz = lhs_llty.int_width();
792         if lhs_sz < rhs_sz {
793             trunc(rhs, lhs_llty)
794         } else if lhs_sz > rhs_sz {
795             // FIXME (#1877: If shifting by negative
796             // values becomes not undefined then this is wrong.
797             zext(rhs, lhs_llty)
798         } else {
799             rhs
800         }
801     } else {
802         rhs
803     }
804 }
805
806 pub fn fail_if_zero_or_overflows<'blk, 'tcx>(
807                                 cx: Block<'blk, 'tcx>,
808                                 call_info: NodeIdAndSpan,
809                                 divrem: ast::BinOp,
810                                 lhs: ValueRef,
811                                 rhs: ValueRef,
812                                 rhs_t: Ty<'tcx>)
813                                 -> Block<'blk, 'tcx> {
814     let (zero_text, overflow_text) = if divrem.node == ast::BiDiv {
815         ("attempted to divide by zero",
816          "attempted to divide with overflow")
817     } else {
818         ("attempted remainder with a divisor of zero",
819          "attempted remainder with overflow")
820     };
821     let debug_loc = call_info.debug_loc();
822
823     let (is_zero, is_signed) = match rhs_t.sty {
824         ty::ty_int(t) => {
825             let zero = C_integral(Type::int_from_ty(cx.ccx(), t), 0, false);
826             (ICmp(cx, llvm::IntEQ, rhs, zero, debug_loc), true)
827         }
828         ty::ty_uint(t) => {
829             let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0, false);
830             (ICmp(cx, llvm::IntEQ, rhs, zero, debug_loc), false)
831         }
832         _ => {
833             cx.sess().bug(&format!("fail-if-zero on unexpected type: {}",
834                                   ty_to_string(cx.tcx(), rhs_t)));
835         }
836     };
837     let bcx = with_cond(cx, is_zero, |bcx| {
838         controlflow::trans_fail(bcx, call_info, InternedString::new(zero_text))
839     });
840
841     // To quote LLVM's documentation for the sdiv instruction:
842     //
843     //      Division by zero leads to undefined behavior. Overflow also leads
844     //      to undefined behavior; this is a rare case, but can occur, for
845     //      example, by doing a 32-bit division of -2147483648 by -1.
846     //
847     // In order to avoid undefined behavior, we perform runtime checks for
848     // signed division/remainder which would trigger overflow. For unsigned
849     // integers, no action beyond checking for zero need be taken.
850     if is_signed {
851         let (llty, min) = match rhs_t.sty {
852             ty::ty_int(t) => {
853                 let llty = Type::int_from_ty(cx.ccx(), t);
854                 let min = match t {
855                     ast::TyIs(_) if llty == Type::i32(cx.ccx()) => i32::MIN as u64,
856                     ast::TyIs(_) => i64::MIN as u64,
857                     ast::TyI8 => i8::MIN as u64,
858                     ast::TyI16 => i16::MIN as u64,
859                     ast::TyI32 => i32::MIN as u64,
860                     ast::TyI64 => i64::MIN as u64,
861                 };
862                 (llty, min)
863             }
864             _ => unreachable!(),
865         };
866         let minus_one = ICmp(bcx, llvm::IntEQ, rhs,
867                              C_integral(llty, -1, false), debug_loc);
868         with_cond(bcx, minus_one, |bcx| {
869             let is_min = ICmp(bcx, llvm::IntEQ, lhs,
870                               C_integral(llty, min, true), debug_loc);
871             with_cond(bcx, is_min, |bcx| {
872                 controlflow::trans_fail(bcx,
873                                         call_info,
874                                         InternedString::new(overflow_text))
875             })
876         })
877     } else {
878         bcx
879     }
880 }
881
882 pub fn trans_external_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
883                                      did: ast::DefId, t: Ty<'tcx>) -> ValueRef {
884     let name = csearch::get_symbol(&ccx.sess().cstore, did);
885     match t.sty {
886         ty::ty_bare_fn(_, ref fn_ty) => {
887             match ccx.sess().target.target.adjust_abi(fn_ty.abi) {
888                 Rust | RustCall => {
889                     get_extern_rust_fn(ccx, t, &name[..], did)
890                 }
891                 RustIntrinsic => {
892                     ccx.sess().bug("unexpected intrinsic in trans_external_path")
893                 }
894                 _ => {
895                     let llfn = foreign::register_foreign_item_fn(ccx, fn_ty.abi, t, &name[..]);
896                     let attrs = csearch::get_item_attrs(&ccx.sess().cstore, did);
897                     set_llvm_fn_attrs(ccx, &attrs, llfn);
898                     llfn
899                 }
900             }
901         }
902         _ => {
903             get_extern_const(ccx, did, t)
904         }
905     }
906 }
907
908 pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
909                           llfn: ValueRef,
910                           llargs: &[ValueRef],
911                           fn_ty: Ty<'tcx>,
912                           debug_loc: DebugLoc)
913                           -> (ValueRef, Block<'blk, 'tcx>) {
914     let _icx = push_ctxt("invoke_");
915     if bcx.unreachable.get() {
916         return (C_null(Type::i8(bcx.ccx())), bcx);
917     }
918
919     let attributes = get_fn_llvm_attributes(bcx.ccx(), fn_ty);
920
921     match bcx.opt_node_id {
922         None => {
923             debug!("invoke at ???");
924         }
925         Some(id) => {
926             debug!("invoke at {}", bcx.tcx().map.node_to_string(id));
927         }
928     }
929
930     if need_invoke(bcx) {
931         debug!("invoking {} at {:?}", bcx.val_to_string(llfn), bcx.llbb);
932         for &llarg in llargs {
933             debug!("arg: {}", bcx.val_to_string(llarg));
934         }
935         let normal_bcx = bcx.fcx.new_temp_block("normal-return");
936         let landing_pad = bcx.fcx.get_landing_pad();
937
938         let llresult = Invoke(bcx,
939                               llfn,
940                               &llargs[..],
941                               normal_bcx.llbb,
942                               landing_pad,
943                               Some(attributes),
944                               debug_loc);
945         return (llresult, normal_bcx);
946     } else {
947         debug!("calling {} at {:?}", bcx.val_to_string(llfn), bcx.llbb);
948         for &llarg in llargs {
949             debug!("arg: {}", bcx.val_to_string(llarg));
950         }
951
952         let llresult = Call(bcx,
953                             llfn,
954                             &llargs[..],
955                             Some(attributes),
956                             debug_loc);
957         return (llresult, bcx);
958     }
959 }
960
961 pub fn need_invoke(bcx: Block) -> bool {
962     if bcx.sess().no_landing_pads() {
963         return false;
964     }
965
966     // Avoid using invoke if we are already inside a landing pad.
967     if bcx.is_lpad {
968         return false;
969     }
970
971     bcx.fcx.needs_invoke()
972 }
973
974 pub fn load_if_immediate<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
975                                      v: ValueRef, t: Ty<'tcx>) -> ValueRef {
976     let _icx = push_ctxt("load_if_immediate");
977     if type_is_immediate(cx.ccx(), t) { return load_ty(cx, v, t); }
978     return v;
979 }
980
981 /// Helper for loading values from memory. Does the necessary conversion if the in-memory type
982 /// differs from the type used for SSA values. Also handles various special cases where the type
983 /// gives us better information about what we are loading.
984 pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
985                            ptr: ValueRef, t: Ty<'tcx>) -> ValueRef {
986     if type_is_zero_size(cx.ccx(), t) {
987         C_undef(type_of::type_of(cx.ccx(), t))
988     } else if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() {
989         // We want to pass small aggregates as immediate values, but using an aggregate LLVM type
990         // for this leads to bad optimizations, so its arg type is an appropriately sized integer
991         // and we have to convert it
992         Load(cx, BitCast(cx, ptr, type_of::arg_type_of(cx.ccx(), t).ptr_to()))
993     } else {
994         unsafe {
995             let global = llvm::LLVMIsAGlobalVariable(ptr);
996             if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True {
997                 let val = llvm::LLVMGetInitializer(global);
998                 if !val.is_null() {
999                     // This could go into its own function, for DRY.
1000                     // (something like "pre-store packing/post-load unpacking")
1001                     if ty::type_is_bool(t) {
1002                         return Trunc(cx, val, Type::i1(cx.ccx()));
1003                     } else {
1004                         return val;
1005                     }
1006                 }
1007             }
1008         }
1009         if ty::type_is_bool(t) {
1010             Trunc(cx, LoadRangeAssert(cx, ptr, 0, 2, llvm::False), Type::i1(cx.ccx()))
1011         } else if ty::type_is_char(t) {
1012             // a char is a Unicode codepoint, and so takes values from 0
1013             // to 0x10FFFF inclusive only.
1014             LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, llvm::False)
1015         } else if (ty::type_is_region_ptr(t) || ty::type_is_unique(t))
1016                   && !common::type_is_fat_ptr(cx.tcx(), t) {
1017             LoadNonNull(cx, ptr)
1018         } else {
1019             Load(cx, ptr)
1020         }
1021     }
1022 }
1023
1024 /// Helper for storing values in memory. Does the necessary conversion if the in-memory type
1025 /// differs from the type used for SSA values.
1026 pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t: Ty<'tcx>) {
1027     if ty::type_is_bool(t) {
1028         Store(cx, ZExt(cx, v, Type::i8(cx.ccx())), dst);
1029     } else if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() {
1030         // We want to pass small aggregates as immediate values, but using an aggregate LLVM type
1031         // for this leads to bad optimizations, so its arg type is an appropriately sized integer
1032         // and we have to convert it
1033         Store(cx, v, BitCast(cx, dst, type_of::arg_type_of(cx.ccx(), t).ptr_to()));
1034     } else {
1035         Store(cx, v, dst);
1036     }
1037 }
1038
1039 pub fn init_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, local: &ast::Local)
1040                               -> Block<'blk, 'tcx> {
1041     debug!("init_local(bcx={}, local.id={})", bcx.to_str(), local.id);
1042     let _indenter = indenter();
1043     let _icx = push_ctxt("init_local");
1044     _match::store_local(bcx, local)
1045 }
1046
1047 pub fn raw_block<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>,
1048                              is_lpad: bool,
1049                              llbb: BasicBlockRef)
1050                              -> Block<'blk, 'tcx> {
1051     common::BlockS::new(llbb, is_lpad, None, fcx)
1052 }
1053
1054 pub fn with_cond<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
1055                                 val: ValueRef,
1056                                 f: F)
1057                                 -> Block<'blk, 'tcx> where
1058     F: FnOnce(Block<'blk, 'tcx>) -> Block<'blk, 'tcx>,
1059 {
1060     let _icx = push_ctxt("with_cond");
1061
1062     if bcx.unreachable.get() ||
1063             (common::is_const(val) && common::const_to_uint(val) == 0) {
1064         return bcx;
1065     }
1066
1067     let fcx = bcx.fcx;
1068     let next_cx = fcx.new_temp_block("next");
1069     let cond_cx = fcx.new_temp_block("cond");
1070     CondBr(bcx, val, cond_cx.llbb, next_cx.llbb, DebugLoc::None);
1071     let after_cx = f(cond_cx);
1072     if !after_cx.terminated.get() {
1073         Br(after_cx, next_cx.llbb, DebugLoc::None);
1074     }
1075     next_cx
1076 }
1077
1078 pub fn call_lifetime_start(cx: Block, ptr: ValueRef) {
1079     if cx.sess().opts.optimize == config::No {
1080         return;
1081     }
1082
1083     let _icx = push_ctxt("lifetime_start");
1084     let ccx = cx.ccx();
1085
1086     let llsize = C_u64(ccx, machine::llsize_of_alloc(ccx, val_ty(ptr).element_type()));
1087     let ptr = PointerCast(cx, ptr, Type::i8p(ccx));
1088     let lifetime_start = ccx.get_intrinsic(&"llvm.lifetime.start");
1089     Call(cx, lifetime_start, &[llsize, ptr], None, DebugLoc::None);
1090 }
1091
1092 pub fn call_lifetime_end(cx: Block, ptr: ValueRef) {
1093     if cx.sess().opts.optimize == config::No {
1094         return;
1095     }
1096
1097     let _icx = push_ctxt("lifetime_end");
1098     let ccx = cx.ccx();
1099
1100     let llsize = C_u64(ccx, machine::llsize_of_alloc(ccx, val_ty(ptr).element_type()));
1101     let ptr = PointerCast(cx, ptr, Type::i8p(ccx));
1102     let lifetime_end = ccx.get_intrinsic(&"llvm.lifetime.end");
1103     Call(cx, lifetime_end, &[llsize, ptr], None, DebugLoc::None);
1104 }
1105
1106 pub fn call_memcpy(cx: Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) {
1107     let _icx = push_ctxt("call_memcpy");
1108     let ccx = cx.ccx();
1109     let key = match &ccx.sess().target.target.target_pointer_width[..] {
1110         "32" => "llvm.memcpy.p0i8.p0i8.i32",
1111         "64" => "llvm.memcpy.p0i8.p0i8.i64",
1112         tws => panic!("Unsupported target word size for memcpy: {}", tws),
1113     };
1114     let memcpy = ccx.get_intrinsic(&key);
1115     let src_ptr = PointerCast(cx, src, Type::i8p(ccx));
1116     let dst_ptr = PointerCast(cx, dst, Type::i8p(ccx));
1117     let size = IntCast(cx, n_bytes, ccx.int_type());
1118     let align = C_i32(ccx, align as i32);
1119     let volatile = C_bool(ccx, false);
1120     Call(cx, memcpy, &[dst_ptr, src_ptr, size, align, volatile], None, DebugLoc::None);
1121 }
1122
1123 pub fn memcpy_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1124                              dst: ValueRef, src: ValueRef,
1125                              t: Ty<'tcx>) {
1126     let _icx = push_ctxt("memcpy_ty");
1127     let ccx = bcx.ccx();
1128     if ty::type_is_structural(t) {
1129         let llty = type_of::type_of(ccx, t);
1130         let llsz = llsize_of(ccx, llty);
1131         let llalign = type_of::align_of(ccx, t);
1132         call_memcpy(bcx, dst, src, llsz, llalign as u32);
1133     } else {
1134         store_ty(bcx, load_ty(bcx, src, t), dst, t);
1135     }
1136 }
1137
1138 pub fn zero_mem<'blk, 'tcx>(cx: Block<'blk, 'tcx>, llptr: ValueRef, t: Ty<'tcx>) {
1139     if cx.unreachable.get() { return; }
1140     let _icx = push_ctxt("zero_mem");
1141     let bcx = cx;
1142     memzero(&B(bcx), llptr, t);
1143 }
1144
1145 // Always use this function instead of storing a zero constant to the memory
1146 // in question. If you store a zero constant, LLVM will drown in vreg
1147 // allocation for large data structures, and the generated code will be
1148 // awful. (A telltale sign of this is large quantities of
1149 // `mov [byte ptr foo],0` in the generated code.)
1150 fn memzero<'a, 'tcx>(b: &Builder<'a, 'tcx>, llptr: ValueRef, ty: Ty<'tcx>) {
1151     let _icx = push_ctxt("memzero");
1152     let ccx = b.ccx;
1153
1154     let llty = type_of::type_of(ccx, ty);
1155
1156     let intrinsic_key = match &ccx.sess().target.target.target_pointer_width[..] {
1157         "32" => "llvm.memset.p0i8.i32",
1158         "64" => "llvm.memset.p0i8.i64",
1159         tws => panic!("Unsupported target word size for memset: {}", tws),
1160     };
1161
1162     let llintrinsicfn = ccx.get_intrinsic(&intrinsic_key);
1163     let llptr = b.pointercast(llptr, Type::i8(ccx).ptr_to());
1164     let llzeroval = C_u8(ccx, 0);
1165     let size = machine::llsize_of(ccx, llty);
1166     let align = C_i32(ccx, type_of::align_of(ccx, ty) as i32);
1167     let volatile = C_bool(ccx, false);
1168     b.call(llintrinsicfn, &[llptr, llzeroval, size, align, volatile], None);
1169 }
1170
1171 pub fn alloc_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, name: &str) -> ValueRef {
1172     let _icx = push_ctxt("alloc_ty");
1173     let ccx = bcx.ccx();
1174     let ty = type_of::type_of(ccx, t);
1175     assert!(!ty::type_has_params(t));
1176     let val = alloca(bcx, ty, name);
1177     return val;
1178 }
1179
1180 pub fn alloca(cx: Block, ty: Type, name: &str) -> ValueRef {
1181     let p = alloca_no_lifetime(cx, ty, name);
1182     call_lifetime_start(cx, p);
1183     p
1184 }
1185
1186 pub fn alloca_no_lifetime(cx: Block, ty: Type, name: &str) -> ValueRef {
1187     let _icx = push_ctxt("alloca");
1188     if cx.unreachable.get() {
1189         unsafe {
1190             return llvm::LLVMGetUndef(ty.ptr_to().to_ref());
1191         }
1192     }
1193     debuginfo::clear_source_location(cx.fcx);
1194     Alloca(cx, ty, name)
1195 }
1196
1197 // Creates the alloca slot which holds the pointer to the slot for the final return value
1198 pub fn make_return_slot_pointer<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
1199                                           output_type: Ty<'tcx>) -> ValueRef {
1200     let lloutputtype = type_of::type_of(fcx.ccx, output_type);
1201
1202     // We create an alloca to hold a pointer of type `output_type`
1203     // which will hold the pointer to the right alloca which has the
1204     // final ret value
1205     if fcx.needs_ret_allocas {
1206         // Let's create the stack slot
1207         let slot = AllocaFcx(fcx, lloutputtype.ptr_to(), "llretslotptr");
1208
1209         // and if we're using an out pointer, then store that in our newly made slot
1210         if type_of::return_uses_outptr(fcx.ccx, output_type) {
1211             let outptr = get_param(fcx.llfn, 0);
1212
1213             let b = fcx.ccx.builder();
1214             b.position_before(fcx.alloca_insert_pt.get().unwrap());
1215             b.store(outptr, slot);
1216         }
1217
1218         slot
1219
1220     // But if there are no nested returns, we skip the indirection and have a single
1221     // retslot
1222     } else {
1223         if type_of::return_uses_outptr(fcx.ccx, output_type) {
1224             get_param(fcx.llfn, 0)
1225         } else {
1226             AllocaFcx(fcx, lloutputtype, "sret_slot")
1227         }
1228     }
1229 }
1230
1231 struct FindNestedReturn {
1232     found: bool,
1233 }
1234
1235 impl FindNestedReturn {
1236     fn new() -> FindNestedReturn {
1237         FindNestedReturn { found: false }
1238     }
1239 }
1240
1241 impl<'v> Visitor<'v> for FindNestedReturn {
1242     fn visit_expr(&mut self, e: &ast::Expr) {
1243         match e.node {
1244             ast::ExprRet(..) => {
1245                 self.found = true;
1246             }
1247             _ => visit::walk_expr(self, e)
1248         }
1249     }
1250 }
1251
1252 fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>) {
1253     let blk = match tcx.map.find(id) {
1254         Some(ast_map::NodeItem(i)) => {
1255             match i.node {
1256                 ast::ItemFn(_, _, _, _, ref blk) => {
1257                     blk
1258                 }
1259                 _ => tcx.sess.bug("unexpected item variant in has_nested_returns")
1260             }
1261         }
1262         Some(ast_map::NodeTraitItem(trait_item)) => {
1263             match trait_item.node {
1264                 ast::MethodTraitItem(_, Some(ref body)) => body,
1265                 ast::MethodTraitItem(_, None) => {
1266                     tcx.sess.bug("unexpected variant: required trait method \
1267                                   in has_nested_returns")
1268                 }
1269                 ast::TypeTraitItem(..) => {
1270                     tcx.sess.bug("unexpected variant: associated type trait item in \
1271                                   has_nested_returns")
1272                 }
1273             }
1274         }
1275         Some(ast_map::NodeImplItem(impl_item)) => {
1276             match impl_item.node {
1277                 ast::MethodImplItem(_, ref body) => body,
1278                 ast::TypeImplItem(_) => {
1279                     tcx.sess.bug("unexpected variant: associated type impl item in \
1280                                   has_nested_returns")
1281                 }
1282                 ast::MacImplItem(_) => {
1283                     tcx.sess.bug("unexpected variant: unexpanded macro impl item in \
1284                                   has_nested_returns")
1285                 }
1286             }
1287         }
1288         Some(ast_map::NodeExpr(e)) => {
1289             match e.node {
1290                 ast::ExprClosure(_, _, ref blk) => blk,
1291                 _ => tcx.sess.bug("unexpected expr variant in has_nested_returns")
1292             }
1293         }
1294         Some(ast_map::NodeVariant(..)) |
1295         Some(ast_map::NodeStructCtor(..)) => return (ast::DUMMY_NODE_ID, None),
1296
1297         // glue, shims, etc
1298         None if id == ast::DUMMY_NODE_ID => return (ast::DUMMY_NODE_ID, None),
1299
1300         _ => tcx.sess.bug(&format!("unexpected variant in has_nested_returns: {}",
1301                                    tcx.map.path_to_string(id)))
1302     };
1303
1304     (blk.id, Some(cfg::CFG::new(tcx, blk)))
1305 }
1306
1307 // Checks for the presence of "nested returns" in a function.
1308 // Nested returns are when the inner expression of a return expression
1309 // (the 'expr' in 'return expr') contains a return expression. Only cases
1310 // where the outer return is actually reachable are considered. Implicit
1311 // returns from the end of blocks are considered as well.
1312 //
1313 // This check is needed to handle the case where the inner expression is
1314 // part of a larger expression that may have already partially-filled the
1315 // return slot alloca. This can cause errors related to clean-up due to
1316 // the clobbering of the existing value in the return slot.
1317 fn has_nested_returns(tcx: &ty::ctxt, cfg: &cfg::CFG, blk_id: ast::NodeId) -> bool {
1318     for n in cfg.graph.depth_traverse(cfg.entry) {
1319         match tcx.map.find(n.id()) {
1320             Some(ast_map::NodeExpr(ex)) => {
1321                 if let ast::ExprRet(Some(ref ret_expr)) = ex.node {
1322                     let mut visitor = FindNestedReturn::new();
1323                     visit::walk_expr(&mut visitor, &**ret_expr);
1324                     if visitor.found {
1325                         return true;
1326                     }
1327                 }
1328             }
1329             Some(ast_map::NodeBlock(blk)) if blk.id == blk_id => {
1330                 let mut visitor = FindNestedReturn::new();
1331                 visit::walk_expr_opt(&mut visitor, &blk.expr);
1332                 if visitor.found {
1333                     return true;
1334                 }
1335             }
1336             _ => {}
1337         }
1338     }
1339
1340     return false;
1341 }
1342
1343 // NB: must keep 4 fns in sync:
1344 //
1345 //  - type_of_fn
1346 //  - create_datums_for_fn_args.
1347 //  - new_fn_ctxt
1348 //  - trans_args
1349 //
1350 // Be warned! You must call `init_function` before doing anything with the
1351 // returned function context.
1352 pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
1353                              llfndecl: ValueRef,
1354                              id: ast::NodeId,
1355                              has_env: bool,
1356                              output_type: ty::FnOutput<'tcx>,
1357                              param_substs: &'tcx Substs<'tcx>,
1358                              sp: Option<Span>,
1359                              block_arena: &'a TypedArena<common::BlockS<'a, 'tcx>>)
1360                              -> FunctionContext<'a, 'tcx> {
1361     common::validate_substs(param_substs);
1362
1363     debug!("new_fn_ctxt(path={}, id={}, param_substs={})",
1364            if id == -1 {
1365                "".to_string()
1366            } else {
1367                ccx.tcx().map.path_to_string(id).to_string()
1368            },
1369            id, param_substs.repr(ccx.tcx()));
1370
1371     let uses_outptr = match output_type {
1372         ty::FnConverging(output_type) => {
1373             let substd_output_type =
1374                 monomorphize::apply_param_substs(ccx.tcx(), param_substs, &output_type);
1375             type_of::return_uses_outptr(ccx, substd_output_type)
1376         }
1377         ty::FnDiverging => false
1378     };
1379     let debug_context = debuginfo::create_function_debug_context(ccx, id, param_substs, llfndecl);
1380     let (blk_id, cfg) = build_cfg(ccx.tcx(), id);
1381     let nested_returns = if let Some(ref cfg) = cfg {
1382         has_nested_returns(ccx.tcx(), cfg, blk_id)
1383     } else {
1384         false
1385     };
1386
1387     let mut fcx = FunctionContext {
1388           llfn: llfndecl,
1389           llenv: None,
1390           llretslotptr: Cell::new(None),
1391           param_env: ty::empty_parameter_environment(ccx.tcx()),
1392           alloca_insert_pt: Cell::new(None),
1393           llreturn: Cell::new(None),
1394           needs_ret_allocas: nested_returns,
1395           personality: Cell::new(None),
1396           caller_expects_out_pointer: uses_outptr,
1397           lllocals: RefCell::new(NodeMap()),
1398           llupvars: RefCell::new(NodeMap()),
1399           id: id,
1400           param_substs: param_substs,
1401           span: sp,
1402           block_arena: block_arena,
1403           ccx: ccx,
1404           debug_context: debug_context,
1405           scopes: RefCell::new(Vec::new()),
1406           cfg: cfg
1407     };
1408
1409     if has_env {
1410         fcx.llenv = Some(get_param(fcx.llfn, fcx.env_arg_pos() as c_uint))
1411     }
1412
1413     fcx
1414 }
1415
1416 /// Performs setup on a newly created function, creating the entry scope block
1417 /// and allocating space for the return pointer.
1418 pub fn init_function<'a, 'tcx>(fcx: &'a FunctionContext<'a, 'tcx>,
1419                                skip_retptr: bool,
1420                                output: ty::FnOutput<'tcx>)
1421                                -> Block<'a, 'tcx> {
1422     let entry_bcx = fcx.new_temp_block("entry-block");
1423
1424     // Use a dummy instruction as the insertion point for all allocas.
1425     // This is later removed in FunctionContext::cleanup.
1426     fcx.alloca_insert_pt.set(Some(unsafe {
1427         Load(entry_bcx, C_null(Type::i8p(fcx.ccx)));
1428         llvm::LLVMGetFirstInstruction(entry_bcx.llbb)
1429     }));
1430
1431     if let ty::FnConverging(output_type) = output {
1432         // This shouldn't need to recompute the return type,
1433         // as new_fn_ctxt did it already.
1434         let substd_output_type = fcx.monomorphize(&output_type);
1435         if !return_type_is_void(fcx.ccx, substd_output_type) {
1436             // If the function returns nil/bot, there is no real return
1437             // value, so do not set `llretslotptr`.
1438             if !skip_retptr || fcx.caller_expects_out_pointer {
1439                 // Otherwise, we normally allocate the llretslotptr, unless we
1440                 // have been instructed to skip it for immediate return
1441                 // values.
1442                 fcx.llretslotptr.set(Some(make_return_slot_pointer(fcx, substd_output_type)));
1443             }
1444         }
1445     }
1446
1447     entry_bcx
1448 }
1449
1450 // NB: must keep 4 fns in sync:
1451 //
1452 //  - type_of_fn
1453 //  - create_datums_for_fn_args.
1454 //  - new_fn_ctxt
1455 //  - trans_args
1456
1457 pub fn arg_kind<'a, 'tcx>(cx: &FunctionContext<'a, 'tcx>, t: Ty<'tcx>)
1458                           -> datum::Rvalue {
1459     use trans::datum::{ByRef, ByValue};
1460
1461     datum::Rvalue {
1462         mode: if arg_is_indirect(cx.ccx, t) { ByRef } else { ByValue }
1463     }
1464 }
1465
1466 // work around bizarre resolve errors
1467 pub type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
1468
1469 // create_datums_for_fn_args: creates rvalue datums for each of the
1470 // incoming function arguments. These will later be stored into
1471 // appropriate lvalue datums.
1472 pub fn create_datums_for_fn_args<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
1473                                            arg_tys: &[Ty<'tcx>])
1474                                            -> Vec<RvalueDatum<'tcx>> {
1475     let _icx = push_ctxt("create_datums_for_fn_args");
1476
1477     // Return an array wrapping the ValueRefs that we get from `get_param` for
1478     // each argument into datums.
1479     arg_tys.iter().enumerate().map(|(i, &arg_ty)| {
1480         let llarg = get_param(fcx.llfn, fcx.arg_pos(i) as c_uint);
1481         datum::Datum::new(llarg, arg_ty, arg_kind(fcx, arg_ty))
1482     }).collect()
1483 }
1484
1485 /// Creates rvalue datums for each of the incoming function arguments and
1486 /// tuples the arguments. These will later be stored into appropriate lvalue
1487 /// datums.
1488 ///
1489 /// FIXME(pcwalton): Reduce the amount of code bloat this is responsible for.
1490 fn create_datums_for_fn_args_under_call_abi<'blk, 'tcx>(
1491         mut bcx: Block<'blk, 'tcx>,
1492         arg_scope: cleanup::CustomScopeIndex,
1493         arg_tys: &[Ty<'tcx>])
1494         -> Vec<RvalueDatum<'tcx>> {
1495     let mut result = Vec::new();
1496     for (i, &arg_ty) in arg_tys.iter().enumerate() {
1497         if i < arg_tys.len() - 1 {
1498             // Regular argument.
1499             let llarg = get_param(bcx.fcx.llfn, bcx.fcx.arg_pos(i) as c_uint);
1500             result.push(datum::Datum::new(llarg, arg_ty, arg_kind(bcx.fcx,
1501                                                                   arg_ty)));
1502             continue
1503         }
1504
1505         // This is the last argument. Tuple it.
1506         match arg_ty.sty {
1507             ty::ty_tup(ref tupled_arg_tys) => {
1508                 let tuple_args_scope_id = cleanup::CustomScope(arg_scope);
1509                 let tuple =
1510                     unpack_datum!(bcx,
1511                                   datum::lvalue_scratch_datum(bcx,
1512                                                               arg_ty,
1513                                                               "tupled_args",
1514                                                               tuple_args_scope_id,
1515                                                               (),
1516                                                               |(),
1517                                                                mut bcx,
1518                                                                llval| {
1519                         for (j, &tupled_arg_ty) in
1520                                     tupled_arg_tys.iter().enumerate() {
1521                             let llarg =
1522                                 get_param(bcx.fcx.llfn,
1523                                           bcx.fcx.arg_pos(i + j) as c_uint);
1524                             let lldest = GEPi(bcx, llval, &[0, j]);
1525                             let datum = datum::Datum::new(
1526                                 llarg,
1527                                 tupled_arg_ty,
1528                                 arg_kind(bcx.fcx, tupled_arg_ty));
1529                             bcx = datum.store_to(bcx, lldest);
1530                         }
1531                         bcx
1532                     }));
1533                 let tuple = unpack_datum!(bcx,
1534                                           tuple.to_expr_datum()
1535                                                .to_rvalue_datum(bcx,
1536                                                                 "argtuple"));
1537                 result.push(tuple);
1538             }
1539             _ => {
1540                 bcx.tcx().sess.bug("last argument of a function with \
1541                                     `rust-call` ABI isn't a tuple?!")
1542             }
1543         };
1544
1545     }
1546
1547     result
1548 }
1549
1550 fn copy_args_to_allocas<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1551                                     arg_scope: cleanup::CustomScopeIndex,
1552                                     args: &[ast::Arg],
1553                                     arg_datums: Vec<RvalueDatum<'tcx>>)
1554                                     -> Block<'blk, 'tcx> {
1555     debug!("copy_args_to_allocas");
1556
1557     let _icx = push_ctxt("copy_args_to_allocas");
1558     let mut bcx = bcx;
1559
1560     let arg_scope_id = cleanup::CustomScope(arg_scope);
1561
1562     for (i, arg_datum) in arg_datums.into_iter().enumerate() {
1563         // For certain mode/type combinations, the raw llarg values are passed
1564         // by value.  However, within the fn body itself, we want to always
1565         // have all locals and arguments be by-ref so that we can cancel the
1566         // cleanup and for better interaction with LLVM's debug info.  So, if
1567         // the argument would be passed by value, we store it into an alloca.
1568         // This alloca should be optimized away by LLVM's mem-to-reg pass in
1569         // the event it's not truly needed.
1570
1571         bcx = _match::store_arg(bcx, &*args[i].pat, arg_datum, arg_scope_id);
1572         debuginfo::create_argument_metadata(bcx, &args[i]);
1573     }
1574
1575     bcx
1576 }
1577
1578 fn copy_closure_args_to_allocas<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
1579                                             arg_scope: cleanup::CustomScopeIndex,
1580                                             args: &[ast::Arg],
1581                                             arg_datums: Vec<RvalueDatum<'tcx>>,
1582                                             monomorphized_arg_types: &[Ty<'tcx>])
1583                                             -> Block<'blk, 'tcx> {
1584     let _icx = push_ctxt("copy_closure_args_to_allocas");
1585     let arg_scope_id = cleanup::CustomScope(arg_scope);
1586
1587     assert_eq!(arg_datums.len(), 1);
1588
1589     let arg_datum = arg_datums.into_iter().next().unwrap();
1590
1591     // Untuple the rest of the arguments.
1592     let tuple_datum =
1593         unpack_datum!(bcx,
1594                       arg_datum.to_lvalue_datum_in_scope(bcx,
1595                                                          "argtuple",
1596                                                          arg_scope_id));
1597     let untupled_arg_types = match monomorphized_arg_types[0].sty {
1598         ty::ty_tup(ref types) => &types[..],
1599         _ => {
1600             bcx.tcx().sess.span_bug(args[0].pat.span,
1601                                     "first arg to `rust-call` ABI function \
1602                                      wasn't a tuple?!")
1603         }
1604     };
1605     for j in 0..args.len() {
1606         let tuple_element_type = untupled_arg_types[j];
1607         let tuple_element_datum =
1608             tuple_datum.get_element(bcx,
1609                                     tuple_element_type,
1610                                     |llval| GEPi(bcx, llval, &[0, j]));
1611         let tuple_element_datum = tuple_element_datum.to_expr_datum();
1612         let tuple_element_datum =
1613             unpack_datum!(bcx,
1614                           tuple_element_datum.to_rvalue_datum(bcx,
1615                                                               "arg"));
1616         bcx = _match::store_arg(bcx,
1617                                 &*args[j].pat,
1618                                 tuple_element_datum,
1619                                 arg_scope_id);
1620
1621         debuginfo::create_argument_metadata(bcx, &args[j]);
1622     }
1623
1624     bcx
1625 }
1626
1627 // Ties up the llstaticallocas -> llloadenv -> lltop edges,
1628 // and builds the return block.
1629 pub fn finish_fn<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>,
1630                              last_bcx: Block<'blk, 'tcx>,
1631                              retty: ty::FnOutput<'tcx>,
1632                              ret_debug_loc: DebugLoc) {
1633     let _icx = push_ctxt("finish_fn");
1634
1635     let ret_cx = match fcx.llreturn.get() {
1636         Some(llreturn) => {
1637             if !last_bcx.terminated.get() {
1638                 Br(last_bcx, llreturn, DebugLoc::None);
1639             }
1640             raw_block(fcx, false, llreturn)
1641         }
1642         None => last_bcx
1643     };
1644
1645     // This shouldn't need to recompute the return type,
1646     // as new_fn_ctxt did it already.
1647     let substd_retty = fcx.monomorphize(&retty);
1648     build_return_block(fcx, ret_cx, substd_retty, ret_debug_loc);
1649
1650     debuginfo::clear_source_location(fcx);
1651     fcx.cleanup();
1652 }
1653
1654 // Builds the return block for a function.
1655 pub fn build_return_block<'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>,
1656                                       ret_cx: Block<'blk, 'tcx>,
1657                                       retty: ty::FnOutput<'tcx>,
1658                                       ret_debug_location: DebugLoc) {
1659     if fcx.llretslotptr.get().is_none() ||
1660        (!fcx.needs_ret_allocas && fcx.caller_expects_out_pointer) {
1661         return RetVoid(ret_cx, ret_debug_location);
1662     }
1663
1664     let retslot = if fcx.needs_ret_allocas {
1665         Load(ret_cx, fcx.llretslotptr.get().unwrap())
1666     } else {
1667         fcx.llretslotptr.get().unwrap()
1668     };
1669     let retptr = Value(retslot);
1670     match retptr.get_dominating_store(ret_cx) {
1671         // If there's only a single store to the ret slot, we can directly return
1672         // the value that was stored and omit the store and the alloca
1673         Some(s) => {
1674             let retval = s.get_operand(0).unwrap().get();
1675             s.erase_from_parent();
1676
1677             if retptr.has_no_uses() {
1678                 retptr.erase_from_parent();
1679             }
1680
1681             let retval = if retty == ty::FnConverging(fcx.ccx.tcx().types.bool) {
1682                 Trunc(ret_cx, retval, Type::i1(fcx.ccx))
1683             } else {
1684                 retval
1685             };
1686
1687             if fcx.caller_expects_out_pointer {
1688                 if let ty::FnConverging(retty) = retty {
1689                     store_ty(ret_cx, retval, get_param(fcx.llfn, 0), retty);
1690                 }
1691                 RetVoid(ret_cx, ret_debug_location)
1692             } else {
1693                 Ret(ret_cx, retval, ret_debug_location)
1694             }
1695         }
1696         // Otherwise, copy the return value to the ret slot
1697         None => match retty {
1698             ty::FnConverging(retty) => {
1699                 if fcx.caller_expects_out_pointer {
1700                     memcpy_ty(ret_cx, get_param(fcx.llfn, 0), retslot, retty);
1701                     RetVoid(ret_cx, ret_debug_location)
1702                 } else {
1703                     Ret(ret_cx, load_ty(ret_cx, retslot, retty), ret_debug_location)
1704                 }
1705             }
1706             ty::FnDiverging => {
1707                 if fcx.caller_expects_out_pointer {
1708                     RetVoid(ret_cx, ret_debug_location)
1709                 } else {
1710                     Ret(ret_cx, C_undef(Type::nil(fcx.ccx)), ret_debug_location)
1711                 }
1712             }
1713         }
1714     }
1715 }
1716
1717 // trans_closure: Builds an LLVM function out of a source function.
1718 // If the function closes over its environment a closure will be
1719 // returned.
1720 pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
1721                                    decl: &ast::FnDecl,
1722                                    body: &ast::Block,
1723                                    llfndecl: ValueRef,
1724                                    param_substs: &'tcx Substs<'tcx>,
1725                                    fn_ast_id: ast::NodeId,
1726                                    _attributes: &[ast::Attribute],
1727                                    output_type: ty::FnOutput<'tcx>,
1728                                    abi: Abi,
1729                                    closure_env: closure::ClosureEnv<'b>) {
1730     ccx.stats().n_closures.set(ccx.stats().n_closures.get() + 1);
1731
1732     let _icx = push_ctxt("trans_closure");
1733     set_uwtable(llfndecl);
1734
1735     debug!("trans_closure(..., param_substs={})",
1736            param_substs.repr(ccx.tcx()));
1737
1738     let has_env = match closure_env {
1739         closure::ClosureEnv::Closure(_) => true,
1740         closure::ClosureEnv::NotClosure => false,
1741     };
1742
1743     let (arena, fcx): (TypedArena<_>, FunctionContext);
1744     arena = TypedArena::new();
1745     fcx = new_fn_ctxt(ccx,
1746                       llfndecl,
1747                       fn_ast_id,
1748                       has_env,
1749                       output_type,
1750                       param_substs,
1751                       Some(body.span),
1752                       &arena);
1753     let mut bcx = init_function(&fcx, false, output_type);
1754
1755     // cleanup scope for the incoming arguments
1756     let fn_cleanup_debug_loc =
1757         debuginfo::get_cleanup_debug_loc_for_ast_node(ccx, fn_ast_id, body.span, true);
1758     let arg_scope = fcx.push_custom_cleanup_scope_with_debug_loc(fn_cleanup_debug_loc);
1759
1760     let block_ty = node_id_type(bcx, body.id);
1761
1762     // Set up arguments to the function.
1763     let monomorphized_arg_types =
1764         decl.inputs.iter()
1765                    .map(|arg| node_id_type(bcx, arg.id))
1766                    .collect::<Vec<_>>();
1767     let monomorphized_arg_types = match closure_env {
1768         closure::ClosureEnv::NotClosure => {
1769             monomorphized_arg_types
1770         }
1771
1772         // Tuple up closure argument types for the "rust-call" ABI.
1773         closure::ClosureEnv::Closure(_) => {
1774             vec![ty::mk_tup(ccx.tcx(), monomorphized_arg_types)]
1775         }
1776     };
1777     for monomorphized_arg_type in &monomorphized_arg_types {
1778         debug!("trans_closure: monomorphized_arg_type: {}",
1779                ty_to_string(ccx.tcx(), *monomorphized_arg_type));
1780     }
1781     debug!("trans_closure: function lltype: {}",
1782            bcx.fcx.ccx.tn().val_to_string(bcx.fcx.llfn));
1783
1784     let arg_datums = if abi != RustCall {
1785         create_datums_for_fn_args(&fcx,
1786                                   &monomorphized_arg_types[..])
1787     } else {
1788         create_datums_for_fn_args_under_call_abi(
1789             bcx,
1790             arg_scope,
1791             &monomorphized_arg_types[..])
1792     };
1793
1794     bcx = match closure_env {
1795         closure::ClosureEnv::NotClosure => {
1796             copy_args_to_allocas(bcx,
1797                                  arg_scope,
1798                                  &decl.inputs,
1799                                  arg_datums)
1800         }
1801         closure::ClosureEnv::Closure(_) => {
1802             copy_closure_args_to_allocas(
1803                 bcx,
1804                 arg_scope,
1805                 &decl.inputs,
1806                 arg_datums,
1807                 &monomorphized_arg_types[..])
1808         }
1809     };
1810
1811     bcx = closure_env.load(bcx, cleanup::CustomScope(arg_scope));
1812
1813     // Up until here, IR instructions for this function have explicitly not been annotated with
1814     // source code location, so we don't step into call setup code. From here on, source location
1815     // emitting should be enabled.
1816     debuginfo::start_emitting_source_locations(&fcx);
1817
1818     let dest = match fcx.llretslotptr.get() {
1819         Some(_) => expr::SaveIn(fcx.get_ret_slot(bcx, ty::FnConverging(block_ty), "iret_slot")),
1820         None => {
1821             assert!(type_is_zero_size(bcx.ccx(), block_ty));
1822             expr::Ignore
1823         }
1824     };
1825
1826     // This call to trans_block is the place where we bridge between
1827     // translation calls that don't have a return value (trans_crate,
1828     // trans_mod, trans_item, et cetera) and those that do
1829     // (trans_block, trans_expr, et cetera).
1830     bcx = controlflow::trans_block(bcx, body, dest);
1831
1832     match dest {
1833         expr::SaveIn(slot) if fcx.needs_ret_allocas => {
1834             Store(bcx, slot, fcx.llretslotptr.get().unwrap());
1835         }
1836         _ => {}
1837     }
1838
1839     match fcx.llreturn.get() {
1840         Some(_) => {
1841             Br(bcx, fcx.return_exit_block(), DebugLoc::None);
1842             fcx.pop_custom_cleanup_scope(arg_scope);
1843         }
1844         None => {
1845             // Microoptimization writ large: avoid creating a separate
1846             // llreturn basic block
1847             bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_scope);
1848         }
1849     };
1850
1851     // Put return block after all other blocks.
1852     // This somewhat improves single-stepping experience in debugger.
1853     unsafe {
1854         let llreturn = fcx.llreturn.get();
1855         if let Some(llreturn) = llreturn {
1856             llvm::LLVMMoveBasicBlockAfter(llreturn, bcx.llbb);
1857         }
1858     }
1859
1860     let ret_debug_loc = DebugLoc::At(fn_cleanup_debug_loc.id,
1861                                      fn_cleanup_debug_loc.span);
1862
1863     // Insert the mandatory first few basic blocks before lltop.
1864     finish_fn(&fcx, bcx, output_type, ret_debug_loc);
1865 }
1866
1867 // trans_fn: creates an LLVM function corresponding to a source language
1868 // function.
1869 pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
1870                           decl: &ast::FnDecl,
1871                           body: &ast::Block,
1872                           llfndecl: ValueRef,
1873                           param_substs: &'tcx Substs<'tcx>,
1874                           id: ast::NodeId,
1875                           attrs: &[ast::Attribute]) {
1876     let _s = StatRecorder::new(ccx, ccx.tcx().map.path_to_string(id).to_string());
1877     debug!("trans_fn(param_substs={})", param_substs.repr(ccx.tcx()));
1878     let _icx = push_ctxt("trans_fn");
1879     let fn_ty = ty::node_id_to_type(ccx.tcx(), id);
1880     let output_type = ty::erase_late_bound_regions(ccx.tcx(), &ty::ty_fn_ret(fn_ty));
1881     let abi = ty::ty_fn_abi(fn_ty);
1882     trans_closure(ccx,
1883                   decl,
1884                   body,
1885                   llfndecl,
1886                   param_substs,
1887                   id,
1888                   attrs,
1889                   output_type,
1890                   abi,
1891                   closure::ClosureEnv::NotClosure);
1892 }
1893
1894 pub fn trans_enum_variant<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
1895                                     _enum_id: ast::NodeId,
1896                                     variant: &ast::Variant,
1897                                     _args: &[ast::VariantArg],
1898                                     disr: ty::Disr,
1899                                     param_substs: &'tcx Substs<'tcx>,
1900                                     llfndecl: ValueRef) {
1901     let _icx = push_ctxt("trans_enum_variant");
1902
1903     trans_enum_variant_or_tuple_like_struct(
1904         ccx,
1905         variant.node.id,
1906         disr,
1907         param_substs,
1908         llfndecl);
1909 }
1910
1911 pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
1912                                                  ctor_ty: Ty<'tcx>,
1913                                                  disr: ty::Disr,
1914                                                  args: callee::CallArgs,
1915                                                  dest: expr::Dest,
1916                                                  debug_loc: DebugLoc)
1917                                                  -> Result<'blk, 'tcx> {
1918
1919     let ccx = bcx.fcx.ccx;
1920     let tcx = ccx.tcx();
1921
1922     let result_ty = match ctor_ty.sty {
1923         ty::ty_bare_fn(_, ref bft) => {
1924             ty::erase_late_bound_regions(bcx.tcx(), &bft.sig.output()).unwrap()
1925         }
1926         _ => ccx.sess().bug(
1927             &format!("trans_enum_variant_constructor: \
1928                      unexpected ctor return type {}",
1929                      ctor_ty.repr(tcx)))
1930     };
1931
1932     // Get location to store the result. If the user does not care about
1933     // the result, just make a stack slot
1934     let llresult = match dest {
1935         expr::SaveIn(d) => d,
1936         expr::Ignore => {
1937             if !type_is_zero_size(ccx, result_ty) {
1938                 alloc_ty(bcx, result_ty, "constructor_result")
1939             } else {
1940                 C_undef(type_of::type_of(ccx, result_ty))
1941             }
1942         }
1943     };
1944
1945     if !type_is_zero_size(ccx, result_ty) {
1946         match args {
1947             callee::ArgExprs(exprs) => {
1948                 let fields = exprs.iter().map(|x| &**x).enumerate().collect::<Vec<_>>();
1949                 bcx = expr::trans_adt(bcx,
1950                                       result_ty,
1951                                       disr,
1952                                       &fields[..],
1953                                       None,
1954                                       expr::SaveIn(llresult),
1955                                       debug_loc);
1956             }
1957             _ => ccx.sess().bug("expected expr as arguments for variant/struct tuple constructor")
1958         }
1959     }
1960
1961     // If the caller doesn't care about the result
1962     // drop the temporary we made
1963     let bcx = match dest {
1964         expr::SaveIn(_) => bcx,
1965         expr::Ignore => {
1966             let bcx = glue::drop_ty(bcx, llresult, result_ty, debug_loc);
1967             if !type_is_zero_size(ccx, result_ty) {
1968                 call_lifetime_end(bcx, llresult);
1969             }
1970             bcx
1971         }
1972     };
1973
1974     Result::new(bcx, llresult)
1975 }
1976
1977 pub fn trans_tuple_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
1978                                     _fields: &[ast::StructField],
1979                                     ctor_id: ast::NodeId,
1980                                     param_substs: &'tcx Substs<'tcx>,
1981                                     llfndecl: ValueRef) {
1982     let _icx = push_ctxt("trans_tuple_struct");
1983
1984     trans_enum_variant_or_tuple_like_struct(
1985         ccx,
1986         ctor_id,
1987         0,
1988         param_substs,
1989         llfndecl);
1990 }
1991
1992 fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
1993                                                      ctor_id: ast::NodeId,
1994                                                      disr: ty::Disr,
1995                                                      param_substs: &'tcx Substs<'tcx>,
1996                                                      llfndecl: ValueRef) {
1997     let ctor_ty = ty::node_id_to_type(ccx.tcx(), ctor_id);
1998     let ctor_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &ctor_ty);
1999
2000     let result_ty = match ctor_ty.sty {
2001         ty::ty_bare_fn(_, ref bft) => {
2002             ty::erase_late_bound_regions(ccx.tcx(), &bft.sig.output())
2003         }
2004         _ => ccx.sess().bug(
2005             &format!("trans_enum_variant_or_tuple_like_struct: \
2006                      unexpected ctor return type {}",
2007                     ty_to_string(ccx.tcx(), ctor_ty)))
2008     };
2009
2010     let (arena, fcx): (TypedArena<_>, FunctionContext);
2011     arena = TypedArena::new();
2012     fcx = new_fn_ctxt(ccx, llfndecl, ctor_id, false, result_ty,
2013                       param_substs, None, &arena);
2014     let bcx = init_function(&fcx, false, result_ty);
2015
2016     assert!(!fcx.needs_ret_allocas);
2017
2018     let arg_tys =
2019         ty::erase_late_bound_regions(
2020             ccx.tcx(), &ty::ty_fn_args(ctor_ty));
2021
2022     let arg_datums = create_datums_for_fn_args(&fcx, &arg_tys[..]);
2023
2024     if !type_is_zero_size(fcx.ccx, result_ty.unwrap()) {
2025         let dest = fcx.get_ret_slot(bcx, result_ty, "eret_slot");
2026         let repr = adt::represent_type(ccx, result_ty.unwrap());
2027         for (i, arg_datum) in arg_datums.into_iter().enumerate() {
2028             let lldestptr = adt::trans_field_ptr(bcx,
2029                                                  &*repr,
2030                                                  dest,
2031                                                  disr,
2032                                                  i);
2033             arg_datum.store_to(bcx, lldestptr);
2034         }
2035         adt::trans_set_discr(bcx, &*repr, dest, disr);
2036     }
2037
2038     finish_fn(&fcx, bcx, result_ty, DebugLoc::None);
2039 }
2040
2041 fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &ast::EnumDef, sp: Span, id: ast::NodeId) {
2042     let mut sizes = Vec::new(); // does no allocation if no pushes, thankfully
2043
2044     let print_info = ccx.sess().print_enum_sizes();
2045
2046     let levels = ccx.tcx().node_lint_levels.borrow();
2047     let lint_id = lint::LintId::of(lint::builtin::VARIANT_SIZE_DIFFERENCES);
2048     let lvlsrc = levels.get(&(id, lint_id));
2049     let is_allow = lvlsrc.map_or(true, |&(lvl, _)| lvl == lint::Allow);
2050
2051     if is_allow && !print_info {
2052         // we're not interested in anything here
2053         return
2054     }
2055
2056     let ty = ty::node_id_to_type(ccx.tcx(), id);
2057     let avar = adt::represent_type(ccx, ty);
2058     match *avar {
2059         adt::General(_, ref variants, _) => {
2060             for var in variants {
2061                 let mut size = 0;
2062                 for field in var.fields.iter().skip(1) {
2063                     // skip the discriminant
2064                     size += llsize_of_real(ccx, sizing_type_of(ccx, *field));
2065                 }
2066                 sizes.push(size);
2067             }
2068         },
2069         _ => { /* its size is either constant or unimportant */ }
2070     }
2071
2072     let (largest, slargest, largest_index) = sizes.iter().enumerate().fold((0, 0, 0),
2073         |(l, s, li), (idx, &size)|
2074             if size > l {
2075                 (size, l, idx)
2076             } else if size > s {
2077                 (l, size, li)
2078             } else {
2079                 (l, s, li)
2080             }
2081     );
2082
2083     if print_info {
2084         let llty = type_of::sizing_type_of(ccx, ty);
2085
2086         let sess = &ccx.tcx().sess;
2087         sess.span_note(sp, &*format!("total size: {} bytes", llsize_of_real(ccx, llty)));
2088         match *avar {
2089             adt::General(..) => {
2090                 for (i, var) in enum_def.variants.iter().enumerate() {
2091                     ccx.tcx().sess.span_note(var.span,
2092                                              &*format!("variant data: {} bytes", sizes[i]));
2093                 }
2094             }
2095             _ => {}
2096         }
2097     }
2098
2099     // we only warn if the largest variant is at least thrice as large as
2100     // the second-largest.
2101     if !is_allow && largest > slargest * 3 && slargest > 0 {
2102         // Use lint::raw_emit_lint rather than sess.add_lint because the lint-printing
2103         // pass for the latter already ran.
2104         lint::raw_emit_lint(&ccx.tcx().sess, lint::builtin::VARIANT_SIZE_DIFFERENCES,
2105                             *lvlsrc.unwrap(), Some(sp),
2106                             &format!("enum variant is more than three times larger \
2107                                      ({} bytes) than the next largest (ignoring padding)",
2108                                     largest));
2109
2110         ccx.sess().span_note(enum_def.variants[largest_index].span,
2111                              "this variant is the largest");
2112     }
2113 }
2114
2115 pub struct TransItemVisitor<'a, 'tcx: 'a> {
2116     pub ccx: &'a CrateContext<'a, 'tcx>,
2117 }
2118
2119 impl<'a, 'tcx, 'v> Visitor<'v> for TransItemVisitor<'a, 'tcx> {
2120     fn visit_item(&mut self, i: &ast::Item) {
2121         trans_item(self.ccx, i);
2122     }
2123 }
2124
2125 pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
2126     // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
2127     // applicable to variable declarations and may not really make sense for
2128     // Rust code in the first place but whitelist them anyway and trust that
2129     // the user knows what s/he's doing. Who knows, unanticipated use cases
2130     // may pop up in the future.
2131     //
2132     // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
2133     // and don't have to be, LLVM treats them as no-ops.
2134     match name {
2135         "appending" => Some(llvm::AppendingLinkage),
2136         "available_externally" => Some(llvm::AvailableExternallyLinkage),
2137         "common" => Some(llvm::CommonLinkage),
2138         "extern_weak" => Some(llvm::ExternalWeakLinkage),
2139         "external" => Some(llvm::ExternalLinkage),
2140         "internal" => Some(llvm::InternalLinkage),
2141         "linkonce" => Some(llvm::LinkOnceAnyLinkage),
2142         "linkonce_odr" => Some(llvm::LinkOnceODRLinkage),
2143         "private" => Some(llvm::PrivateLinkage),
2144         "weak" => Some(llvm::WeakAnyLinkage),
2145         "weak_odr" => Some(llvm::WeakODRLinkage),
2146         _ => None,
2147     }
2148 }
2149
2150
2151 /// Enum describing the origin of an LLVM `Value`, for linkage purposes.
2152 #[derive(Copy)]
2153 pub enum ValueOrigin {
2154     /// The LLVM `Value` is in this context because the corresponding item was
2155     /// assigned to the current compilation unit.
2156     OriginalTranslation,
2157     /// The `Value`'s corresponding item was assigned to some other compilation
2158     /// unit, but the `Value` was translated in this context anyway because the
2159     /// item is marked `#[inline]`.
2160     InlinedCopy,
2161 }
2162
2163 /// Set the appropriate linkage for an LLVM `ValueRef` (function or global).
2164 /// If the `llval` is the direct translation of a specific Rust item, `id`
2165 /// should be set to the `NodeId` of that item.  (This mapping should be
2166 /// 1-to-1, so monomorphizations and drop/visit glue should have `id` set to
2167 /// `None`.)  `llval_origin` indicates whether `llval` is the translation of an
2168 /// item assigned to `ccx`'s compilation unit or an inlined copy of an item
2169 /// assigned to a different compilation unit.
2170 pub fn update_linkage(ccx: &CrateContext,
2171                       llval: ValueRef,
2172                       id: Option<ast::NodeId>,
2173                       llval_origin: ValueOrigin) {
2174     match llval_origin {
2175         InlinedCopy => {
2176             // `llval` is a translation of an item defined in a separate
2177             // compilation unit.  This only makes sense if there are at least
2178             // two compilation units.
2179             assert!(ccx.sess().opts.cg.codegen_units > 1);
2180             // `llval` is a copy of something defined elsewhere, so use
2181             // `AvailableExternallyLinkage` to avoid duplicating code in the
2182             // output.
2183             llvm::SetLinkage(llval, llvm::AvailableExternallyLinkage);
2184             return;
2185         },
2186         OriginalTranslation => {},
2187     }
2188
2189     if let Some(id) = id {
2190         let item = ccx.tcx().map.get(id);
2191         if let ast_map::NodeItem(i) = item {
2192             if let Some(name) = attr::first_attr_value_str_by_name(&i.attrs, "linkage") {
2193                 if let Some(linkage) = llvm_linkage_by_name(&name) {
2194                     llvm::SetLinkage(llval, linkage);
2195                 } else {
2196                     ccx.sess().span_fatal(i.span, "invalid linkage specified");
2197                 }
2198                 return;
2199             }
2200         }
2201     }
2202
2203     match id {
2204         Some(id) if ccx.reachable().contains(&id) => {
2205             llvm::SetLinkage(llval, llvm::ExternalLinkage);
2206         },
2207         _ => {
2208             // `id` does not refer to an item in `ccx.reachable`.
2209             if ccx.sess().opts.cg.codegen_units > 1 {
2210                 llvm::SetLinkage(llval, llvm::ExternalLinkage);
2211             } else {
2212                 llvm::SetLinkage(llval, llvm::InternalLinkage);
2213             }
2214         },
2215     }
2216 }
2217
2218 pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
2219     let _icx = push_ctxt("trans_item");
2220
2221     let from_external = ccx.external_srcs().borrow().contains_key(&item.id);
2222
2223     match item.node {
2224       ast::ItemFn(ref decl, _fn_style, abi, ref generics, ref body) => {
2225         if !generics.is_type_parameterized() {
2226             let trans_everywhere = attr::requests_inline(&item.attrs);
2227             // Ignore `trans_everywhere` for cross-crate inlined items
2228             // (`from_external`).  `trans_item` will be called once for each
2229             // compilation unit that references the item, so it will still get
2230             // translated everywhere it's needed.
2231             for (ref ccx, is_origin) in ccx.maybe_iter(!from_external && trans_everywhere) {
2232                 let llfn = get_item_val(ccx, item.id);
2233                 let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
2234                 if abi != Rust {
2235                     foreign::trans_rust_fn_with_foreign_abi(ccx,
2236                                                             &**decl,
2237                                                             &**body,
2238                                                             &item.attrs,
2239                                                             llfn,
2240                                                             empty_substs,
2241                                                             item.id,
2242                                                             None);
2243                 } else {
2244                     trans_fn(ccx,
2245                              &**decl,
2246                              &**body,
2247                              llfn,
2248                              empty_substs,
2249                              item.id,
2250                              &item.attrs);
2251                 }
2252                 update_linkage(ccx,
2253                                llfn,
2254                                Some(item.id),
2255                                if is_origin { OriginalTranslation } else { InlinedCopy });
2256             }
2257         }
2258
2259         // Be sure to travel more than just one layer deep to catch nested
2260         // items in blocks and such.
2261         let mut v = TransItemVisitor{ ccx: ccx };
2262         v.visit_block(&**body);
2263       }
2264       ast::ItemImpl(_, _, ref generics, _, _, ref impl_items) => {
2265         meth::trans_impl(ccx,
2266                          item.ident,
2267                          &impl_items[..],
2268                          generics,
2269                          item.id);
2270       }
2271       ast::ItemMod(ref m) => {
2272         trans_mod(&ccx.rotate(), m);
2273       }
2274       ast::ItemEnum(ref enum_definition, ref gens) => {
2275         if gens.ty_params.is_empty() {
2276             // sizes only make sense for non-generic types
2277
2278             enum_variant_size_lint(ccx, enum_definition, item.span, item.id);
2279         }
2280       }
2281       ast::ItemConst(_, ref expr) => {
2282           // Recurse on the expression to catch items in blocks
2283           let mut v = TransItemVisitor{ ccx: ccx };
2284           v.visit_expr(&**expr);
2285       }
2286       ast::ItemStatic(_, m, ref expr) => {
2287           // Recurse on the expression to catch items in blocks
2288           let mut v = TransItemVisitor{ ccx: ccx };
2289           v.visit_expr(&**expr);
2290
2291           consts::trans_static(ccx, m, item.id);
2292           let g = get_item_val(ccx, item.id);
2293           update_linkage(ccx, g, Some(item.id), OriginalTranslation);
2294
2295           // Do static_assert checking. It can't really be done much earlier
2296           // because we need to get the value of the bool out of LLVM
2297           if attr::contains_name(&item.attrs, "static_assert") {
2298               if !ty::type_is_bool(ty::expr_ty(ccx.tcx(), expr)) {
2299                   ccx.sess().span_fatal(expr.span,
2300                                         "can only have static_assert on a static \
2301                                          with type `bool`");
2302               }
2303               if m == ast::MutMutable {
2304                   ccx.sess().span_fatal(expr.span,
2305                                         "cannot have static_assert on a mutable \
2306                                          static");
2307               }
2308
2309               let v = ccx.static_values().borrow()[item.id].clone();
2310               unsafe {
2311                   if !(llvm::LLVMConstIntGetZExtValue(v) != 0) {
2312                       ccx.sess().span_fatal(expr.span, "static assertion failed");
2313                   }
2314               }
2315           }
2316       },
2317       ast::ItemForeignMod(ref foreign_mod) => {
2318         foreign::trans_foreign_mod(ccx, foreign_mod);
2319       }
2320       ast::ItemTrait(..) => {
2321         // Inside of this trait definition, we won't be actually translating any
2322         // functions, but the trait still needs to be walked. Otherwise default
2323         // methods with items will not get translated and will cause ICE's when
2324         // metadata time comes around.
2325         let mut v = TransItemVisitor{ ccx: ccx };
2326         visit::walk_item(&mut v, item);
2327       }
2328       _ => {/* fall through */ }
2329     }
2330 }
2331
2332 // Translate a module. Doing this amounts to translating the items in the
2333 // module; there ends up being no artifact (aside from linkage names) of
2334 // separate modules in the compiled program.  That's because modules exist
2335 // only as a convenience for humans working with the code, to organize names
2336 // and control visibility.
2337 pub fn trans_mod(ccx: &CrateContext, m: &ast::Mod) {
2338     let _icx = push_ctxt("trans_mod");
2339     for item in &m.items {
2340         trans_item(ccx, &**item);
2341     }
2342 }
2343
2344 fn finish_register_fn(ccx: &CrateContext, sp: Span, sym: String, node_id: ast::NodeId,
2345                       llfn: ValueRef) {
2346     ccx.item_symbols().borrow_mut().insert(node_id, sym);
2347
2348     // The stack exhaustion lang item shouldn't have a split stack because
2349     // otherwise it would continue to be exhausted (bad), and both it and the
2350     // eh_personality functions need to be externally linkable.
2351     let def = ast_util::local_def(node_id);
2352     if ccx.tcx().lang_items.stack_exhausted() == Some(def) {
2353         unset_split_stack(llfn);
2354         llvm::SetLinkage(llfn, llvm::ExternalLinkage);
2355     }
2356     if ccx.tcx().lang_items.eh_personality() == Some(def) {
2357         llvm::SetLinkage(llfn, llvm::ExternalLinkage);
2358     }
2359
2360
2361     if is_entry_fn(ccx.sess(), node_id) {
2362         // check for the #[rustc_error] annotation, which forces an
2363         // error in trans. This is used to write compile-fail tests
2364         // that actually test that compilation succeeds without
2365         // reporting an error.
2366         if ty::has_attr(ccx.tcx(), local_def(node_id), "rustc_error") {
2367             ccx.tcx().sess.span_fatal(sp, "compilation successful");
2368         }
2369
2370         create_entry_wrapper(ccx, sp, llfn);
2371     }
2372 }
2373
2374 fn register_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
2375                          sp: Span,
2376                          sym: String,
2377                          node_id: ast::NodeId,
2378                          node_type: Ty<'tcx>)
2379                          -> ValueRef {
2380     if let ty::ty_bare_fn(_, ref f) = node_type.sty {
2381         if f.abi != Rust && f.abi != RustCall {
2382             ccx.sess().span_bug(sp, &format!("only the `{}` or `{}` calling conventions are valid \
2383                                               for this function; `{}` was specified",
2384                                               Rust.name(), RustCall.name(), f.abi.name()));
2385         }
2386     } else {
2387         ccx.sess().span_bug(sp, "expected bare rust function")
2388     }
2389
2390     let llfn = decl_rust_fn(ccx, node_type, &sym[..]);
2391     finish_register_fn(ccx, sp, sym, node_id, llfn);
2392     llfn
2393 }
2394
2395 pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<'tcx>)
2396                                         -> llvm::AttrBuilder
2397 {
2398     use middle::ty::{BrAnon, ReLateBound};
2399
2400     let function_type;
2401     let (fn_sig, abi, env_ty) = match fn_ty.sty {
2402         ty::ty_bare_fn(_, ref f) => (&f.sig, f.abi, None),
2403         ty::ty_closure(closure_did, substs) => {
2404             let typer = common::NormalizingClosureTyper::new(ccx.tcx());
2405             function_type = typer.closure_type(closure_did, substs);
2406             let self_type = self_type_for_closure(ccx, closure_did, fn_ty);
2407             (&function_type.sig, RustCall, Some(self_type))
2408         }
2409         _ => ccx.sess().bug("expected closure or function.")
2410     };
2411
2412     let fn_sig = ty::erase_late_bound_regions(ccx.tcx(), fn_sig);
2413
2414     let mut attrs = llvm::AttrBuilder::new();
2415     let ret_ty = fn_sig.output;
2416
2417     // These have an odd calling convention, so we need to manually
2418     // unpack the input ty's
2419     let input_tys = match fn_ty.sty {
2420         ty::ty_closure(..) => {
2421             assert!(abi == RustCall);
2422
2423             match fn_sig.inputs[0].sty {
2424                 ty::ty_tup(ref inputs) => {
2425                     let mut full_inputs = vec![env_ty.expect("Missing closure environment")];
2426                     full_inputs.push_all(inputs);
2427                     full_inputs
2428                 }
2429                 _ => ccx.sess().bug("expected tuple'd inputs")
2430             }
2431         },
2432         ty::ty_bare_fn(..) if abi == RustCall => {
2433             let mut inputs = vec![fn_sig.inputs[0]];
2434
2435             match fn_sig.inputs[1].sty {
2436                 ty::ty_tup(ref t_in) => {
2437                     inputs.push_all(&t_in[..]);
2438                     inputs
2439                 }
2440                 _ => ccx.sess().bug("expected tuple'd inputs")
2441             }
2442         }
2443         _ => fn_sig.inputs.clone()
2444     };
2445
2446     // Index 0 is the return value of the llvm func, so we start at 1
2447     let mut first_arg_offset = 1;
2448     if let ty::FnConverging(ret_ty) = ret_ty {
2449         // A function pointer is called without the declaration
2450         // available, so we have to apply any attributes with ABI
2451         // implications directly to the call instruction. Right now,
2452         // the only attribute we need to worry about is `sret`.
2453         if type_of::return_uses_outptr(ccx, ret_ty) {
2454             let llret_sz = llsize_of_real(ccx, type_of::type_of(ccx, ret_ty));
2455
2456             // The outptr can be noalias and nocapture because it's entirely
2457             // invisible to the program. We also know it's nonnull as well
2458             // as how many bytes we can dereference
2459             attrs.arg(1, llvm::StructRetAttribute)
2460                  .arg(1, llvm::NoAliasAttribute)
2461                  .arg(1, llvm::NoCaptureAttribute)
2462                  .arg(1, llvm::DereferenceableAttribute(llret_sz));
2463
2464             // Add one more since there's an outptr
2465             first_arg_offset += 1;
2466         } else {
2467             // The `noalias` attribute on the return value is useful to a
2468             // function ptr caller.
2469             match ret_ty.sty {
2470                 // `~` pointer return values never alias because ownership
2471                 // is transferred
2472                 ty::ty_uniq(it) if !common::type_is_sized(ccx.tcx(), it) => {}
2473                 ty::ty_uniq(_) => {
2474                     attrs.ret(llvm::NoAliasAttribute);
2475                 }
2476                 _ => {}
2477             }
2478
2479             // We can also mark the return value as `dereferenceable` in certain cases
2480             match ret_ty.sty {
2481                 // These are not really pointers but pairs, (pointer, len)
2482                 ty::ty_uniq(it) |
2483                 ty::ty_rptr(_, ty::mt { ty: it, .. }) if !common::type_is_sized(ccx.tcx(), it) => {}
2484                 ty::ty_uniq(inner) | ty::ty_rptr(_, ty::mt { ty: inner, .. }) => {
2485                     let llret_sz = llsize_of_real(ccx, type_of::type_of(ccx, inner));
2486                     attrs.ret(llvm::DereferenceableAttribute(llret_sz));
2487                 }
2488                 _ => {}
2489             }
2490
2491             if let ty::ty_bool = ret_ty.sty {
2492                 attrs.ret(llvm::ZExtAttribute);
2493             }
2494         }
2495     }
2496
2497     for (idx, &t) in input_tys.iter().enumerate().map(|(i, v)| (i + first_arg_offset, v)) {
2498         match t.sty {
2499             // this needs to be first to prevent fat pointers from falling through
2500             _ if !type_is_immediate(ccx, t) => {
2501                 let llarg_sz = llsize_of_real(ccx, type_of::type_of(ccx, t));
2502
2503                 // For non-immediate arguments the callee gets its own copy of
2504                 // the value on the stack, so there are no aliases. It's also
2505                 // program-invisible so can't possibly capture
2506                 attrs.arg(idx, llvm::NoAliasAttribute)
2507                      .arg(idx, llvm::NoCaptureAttribute)
2508                      .arg(idx, llvm::DereferenceableAttribute(llarg_sz));
2509             }
2510
2511             ty::ty_bool => {
2512                 attrs.arg(idx, llvm::ZExtAttribute);
2513             }
2514
2515             // `~` pointer parameters never alias because ownership is transferred
2516             ty::ty_uniq(inner) => {
2517                 let llsz = llsize_of_real(ccx, type_of::type_of(ccx, inner));
2518
2519                 attrs.arg(idx, llvm::NoAliasAttribute)
2520                      .arg(idx, llvm::DereferenceableAttribute(llsz));
2521             }
2522
2523             // `&mut` pointer parameters never alias other parameters, or mutable global data
2524             //
2525             // `&T` where `T` contains no `UnsafeCell<U>` is immutable, and can be marked as both
2526             // `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely on
2527             // memory dependencies rather than pointer equality
2528             ty::ty_rptr(b, mt) if mt.mutbl == ast::MutMutable ||
2529                                   !ty::type_contents(ccx.tcx(), mt.ty).interior_unsafe() => {
2530
2531                 let llsz = llsize_of_real(ccx, type_of::type_of(ccx, mt.ty));
2532                 attrs.arg(idx, llvm::NoAliasAttribute)
2533                      .arg(idx, llvm::DereferenceableAttribute(llsz));
2534
2535                 if mt.mutbl == ast::MutImmutable {
2536                     attrs.arg(idx, llvm::ReadOnlyAttribute);
2537                 }
2538
2539                 if let ReLateBound(_, BrAnon(_)) = *b {
2540                     attrs.arg(idx, llvm::NoCaptureAttribute);
2541                 }
2542             }
2543
2544             // When a reference in an argument has no named lifetime, it's impossible for that
2545             // reference to escape this function (returned or stored beyond the call by a closure).
2546             ty::ty_rptr(&ReLateBound(_, BrAnon(_)), mt) => {
2547                 let llsz = llsize_of_real(ccx, type_of::type_of(ccx, mt.ty));
2548                 attrs.arg(idx, llvm::NoCaptureAttribute)
2549                      .arg(idx, llvm::DereferenceableAttribute(llsz));
2550             }
2551
2552             // & pointer parameters are also never null and we know exactly how
2553             // many bytes we can dereference
2554             ty::ty_rptr(_, mt) => {
2555                 let llsz = llsize_of_real(ccx, type_of::type_of(ccx, mt.ty));
2556                 attrs.arg(idx, llvm::DereferenceableAttribute(llsz));
2557             }
2558             _ => ()
2559         }
2560     }
2561
2562     attrs
2563 }
2564
2565 // only use this for foreign function ABIs and glue, use `register_fn` for Rust functions
2566 pub fn register_fn_llvmty(ccx: &CrateContext,
2567                           sp: Span,
2568                           sym: String,
2569                           node_id: ast::NodeId,
2570                           cc: llvm::CallConv,
2571                           llfty: Type) -> ValueRef {
2572     debug!("register_fn_llvmty id={} sym={}", node_id, sym);
2573
2574     let llfn = decl_fn(ccx,
2575                        &sym[..],
2576                        cc,
2577                        llfty,
2578                        ty::FnConverging(ty::mk_nil(ccx.tcx())));
2579     finish_register_fn(ccx, sp, sym, node_id, llfn);
2580     llfn
2581 }
2582
2583 pub fn is_entry_fn(sess: &Session, node_id: ast::NodeId) -> bool {
2584     match *sess.entry_fn.borrow() {
2585         Some((entry_id, _)) => node_id == entry_id,
2586         None => false
2587     }
2588 }
2589
2590 // Create a _rust_main(args: ~[str]) function which will be called from the
2591 // runtime rust_start function
2592 pub fn create_entry_wrapper(ccx: &CrateContext,
2593                            _sp: Span,
2594                            main_llfn: ValueRef) {
2595     let et = ccx.sess().entry_type.get().unwrap();
2596     match et {
2597         config::EntryMain => {
2598             create_entry_fn(ccx, main_llfn, true);
2599         }
2600         config::EntryStart => create_entry_fn(ccx, main_llfn, false),
2601         config::EntryNone => {}    // Do nothing.
2602     }
2603
2604     fn create_entry_fn(ccx: &CrateContext,
2605                        rust_main: ValueRef,
2606                        use_start_lang_item: bool) {
2607         let llfty = Type::func(&[ccx.int_type(), Type::i8p(ccx).ptr_to()],
2608                                &ccx.int_type());
2609
2610         let llfn = decl_cdecl_fn(ccx, "main", llfty, ty::mk_nil(ccx.tcx()));
2611
2612         // FIXME: #16581: Marking a symbol in the executable with `dllexport`
2613         // linkage forces MinGW's linker to output a `.reloc` section for ASLR
2614         if ccx.sess().target.target.options.is_like_windows {
2615             unsafe { llvm::LLVMRustSetDLLExportStorageClass(llfn) }
2616         }
2617
2618         let llbb = unsafe {
2619             llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llfn,
2620                                                 "top\0".as_ptr() as *const _)
2621         };
2622         let bld = ccx.raw_builder();
2623         unsafe {
2624             llvm::LLVMPositionBuilderAtEnd(bld, llbb);
2625
2626             debuginfo::insert_reference_to_gdb_debug_scripts_section_global(ccx);
2627
2628             let (start_fn, args) = if use_start_lang_item {
2629                 let start_def_id = match ccx.tcx().lang_items.require(StartFnLangItem) {
2630                     Ok(id) => id,
2631                     Err(s) => { ccx.sess().fatal(&s[..]); }
2632                 };
2633                 let start_fn = if start_def_id.krate == ast::LOCAL_CRATE {
2634                     get_item_val(ccx, start_def_id.node)
2635                 } else {
2636                     let start_fn_type = csearch::get_type(ccx.tcx(),
2637                                                           start_def_id).ty;
2638                     trans_external_path(ccx, start_def_id, start_fn_type)
2639                 };
2640
2641                 let args = {
2642                     let opaque_rust_main = llvm::LLVMBuildPointerCast(bld,
2643                         rust_main, Type::i8p(ccx).to_ref(),
2644                         "rust_main\0".as_ptr() as *const _);
2645
2646                     vec!(
2647                         opaque_rust_main,
2648                         get_param(llfn, 0),
2649                         get_param(llfn, 1)
2650                      )
2651                 };
2652                 (start_fn, args)
2653             } else {
2654                 debug!("using user-defined start fn");
2655                 let args = vec!(
2656                     get_param(llfn, 0 as c_uint),
2657                     get_param(llfn, 1 as c_uint)
2658                 );
2659
2660                 (rust_main, args)
2661             };
2662
2663             let result = llvm::LLVMBuildCall(bld,
2664                                              start_fn,
2665                                              args.as_ptr(),
2666                                              args.len() as c_uint,
2667                                              noname());
2668
2669             llvm::LLVMBuildRet(bld, result);
2670         }
2671     }
2672 }
2673
2674 fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, id: ast::NodeId,
2675                            ty: Ty<'tcx>, attrs: &[ast::Attribute]) -> String {
2676     match ccx.external_srcs().borrow().get(&id) {
2677         Some(&did) => {
2678             let sym = csearch::get_symbol(&ccx.sess().cstore, did);
2679             debug!("found item {} in other crate...", sym);
2680             return sym;
2681         }
2682         None => {}
2683     }
2684
2685     match attr::first_attr_value_str_by_name(attrs, "export_name") {
2686         // Use provided name
2687         Some(name) => name.to_string(),
2688
2689         _ => ccx.tcx().map.with_path(id, |path| {
2690             if attr::contains_name(attrs, "no_mangle") {
2691                 // Don't mangle
2692                 path.last().unwrap().to_string()
2693             } else {
2694                 match weak_lang_items::link_name(attrs) {
2695                     Some(name) => name.to_string(),
2696                     None => {
2697                         // Usual name mangling
2698                         mangle_exported_name(ccx, path, ty, id)
2699                     }
2700                 }
2701             }
2702         })
2703     }
2704 }
2705
2706 fn contains_null(s: &str) -> bool {
2707     s.bytes().any(|b| b == 0)
2708 }
2709
2710 pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
2711     debug!("get_item_val(id=`{}`)", id);
2712
2713     match ccx.item_vals().borrow().get(&id).cloned() {
2714         Some(v) => return v,
2715         None => {}
2716     }
2717
2718     let item = ccx.tcx().map.get(id);
2719     debug!("get_item_val: id={} item={:?}", id, item);
2720     let val = match item {
2721         ast_map::NodeItem(i) => {
2722             let ty = ty::node_id_to_type(ccx.tcx(), i.id);
2723             let sym = || exported_name(ccx, id, ty, &i.attrs);
2724
2725             let v = match i.node {
2726                 ast::ItemStatic(_, _, ref expr) => {
2727                     // If this static came from an external crate, then
2728                     // we need to get the symbol from csearch instead of
2729                     // using the current crate's name/version
2730                     // information in the hash of the symbol
2731                     let sym = sym();
2732                     debug!("making {}", sym);
2733
2734                     // We need the translated value here, because for enums the
2735                     // LLVM type is not fully determined by the Rust type.
2736                     let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
2737                     let (v, ty) = consts::const_expr(ccx, &**expr, empty_substs);
2738                     ccx.static_values().borrow_mut().insert(id, v);
2739                     unsafe {
2740                         // boolean SSA values are i1, but they have to be stored in i8 slots,
2741                         // otherwise some LLVM optimization passes don't work as expected
2742                         let llty = if ty::type_is_bool(ty) {
2743                             llvm::LLVMInt8TypeInContext(ccx.llcx())
2744                         } else {
2745                             llvm::LLVMTypeOf(v)
2746                         };
2747                         if contains_null(&sym[..]) {
2748                             ccx.sess().fatal(
2749                                 &format!("Illegal null byte in export_name \
2750                                          value: `{}`", sym));
2751                         }
2752                         let buf = CString::new(sym.clone()).unwrap();
2753                         let g = llvm::LLVMAddGlobal(ccx.llmod(), llty,
2754                                                     buf.as_ptr());
2755
2756                         if attr::contains_name(&i.attrs,
2757                                                "thread_local") {
2758                             llvm::set_thread_local(g, true);
2759                         }
2760                         ccx.item_symbols().borrow_mut().insert(i.id, sym);
2761                         g
2762                     }
2763                 }
2764
2765                 ast::ItemFn(_, _, abi, _, _) => {
2766                     let sym = sym();
2767                     let llfn = if abi == Rust {
2768                         register_fn(ccx, i.span, sym, i.id, ty)
2769                     } else {
2770                         foreign::register_rust_fn_with_foreign_abi(ccx,
2771                                                                    i.span,
2772                                                                    sym,
2773                                                                    i.id)
2774                     };
2775                     set_llvm_fn_attrs(ccx, &i.attrs, llfn);
2776                     llfn
2777                 }
2778
2779                 _ => ccx.sess().bug("get_item_val: weird result in table")
2780             };
2781
2782             match attr::first_attr_value_str_by_name(&i.attrs,
2783                                                      "link_section") {
2784                 Some(sect) => {
2785                     if contains_null(&sect) {
2786                         ccx.sess().fatal(&format!("Illegal null byte in link_section value: `{}`",
2787                                                  &sect));
2788                     }
2789                     unsafe {
2790                         let buf = CString::new(sect.as_bytes()).unwrap();
2791                         llvm::LLVMSetSection(v, buf.as_ptr());
2792                     }
2793                 },
2794                 None => ()
2795             }
2796
2797             v
2798         }
2799
2800         ast_map::NodeTraitItem(trait_item) => {
2801             debug!("get_item_val(): processing a NodeTraitItem");
2802             match trait_item.node {
2803                 ast::MethodTraitItem(_, None) | ast::TypeTraitItem(..) => {
2804                     ccx.sess().span_bug(trait_item.span,
2805                         "unexpected variant: required trait method in get_item_val()");
2806                 }
2807                 ast::MethodTraitItem(_, Some(_)) => {
2808                     register_method(ccx, id, &trait_item.attrs, trait_item.span)
2809                 }
2810             }
2811         }
2812
2813         ast_map::NodeImplItem(impl_item) => {
2814             match impl_item.node {
2815                 ast::MethodImplItem(..) => {
2816                     register_method(ccx, id, &impl_item.attrs, impl_item.span)
2817                 }
2818                 ast::TypeImplItem(_) => {
2819                     ccx.sess().span_bug(impl_item.span,
2820                         "unexpected variant: associated type in get_item_val()")
2821                 }
2822                 ast::MacImplItem(_) => {
2823                     ccx.sess().span_bug(impl_item.span,
2824                         "unexpected variant: unexpanded macro in get_item_val()")
2825                 }
2826             }
2827         }
2828
2829         ast_map::NodeForeignItem(ni) => {
2830             match ni.node {
2831                 ast::ForeignItemFn(..) => {
2832                     let abi = ccx.tcx().map.get_foreign_abi(id);
2833                     let ty = ty::node_id_to_type(ccx.tcx(), ni.id);
2834                     let name = foreign::link_name(&*ni);
2835                     let llfn = foreign::register_foreign_item_fn(ccx, abi, ty, &name);
2836                     set_llvm_fn_attrs(ccx, &ni.attrs, llfn);
2837                     llfn
2838                 }
2839                 ast::ForeignItemStatic(..) => {
2840                     foreign::register_static(ccx, &*ni)
2841                 }
2842             }
2843         }
2844
2845         ast_map::NodeVariant(ref v) => {
2846             let llfn;
2847             let args = match v.node.kind {
2848                 ast::TupleVariantKind(ref args) => args,
2849                 ast::StructVariantKind(_) => {
2850                     ccx.sess().bug("struct variant kind unexpected in get_item_val")
2851                 }
2852             };
2853             assert!(args.len() != 0);
2854             let ty = ty::node_id_to_type(ccx.tcx(), id);
2855             let parent = ccx.tcx().map.get_parent(id);
2856             let enm = ccx.tcx().map.expect_item(parent);
2857             let sym = exported_name(ccx,
2858                                     id,
2859                                     ty,
2860                                     &enm.attrs);
2861
2862             llfn = match enm.node {
2863                 ast::ItemEnum(_, _) => {
2864                     register_fn(ccx, (*v).span, sym, id, ty)
2865                 }
2866                 _ => ccx.sess().bug("NodeVariant, shouldn't happen")
2867             };
2868             set_inline_hint(llfn);
2869             llfn
2870         }
2871
2872         ast_map::NodeStructCtor(struct_def) => {
2873             // Only register the constructor if this is a tuple-like struct.
2874             let ctor_id = match struct_def.ctor_id {
2875                 None => {
2876                     ccx.sess().bug("attempt to register a constructor of \
2877                                     a non-tuple-like struct")
2878                 }
2879                 Some(ctor_id) => ctor_id,
2880             };
2881             let parent = ccx.tcx().map.get_parent(id);
2882             let struct_item = ccx.tcx().map.expect_item(parent);
2883             let ty = ty::node_id_to_type(ccx.tcx(), ctor_id);
2884             let sym = exported_name(ccx,
2885                                     id,
2886                                     ty,
2887                                     &struct_item.attrs);
2888             let llfn = register_fn(ccx, struct_item.span,
2889                                    sym, ctor_id, ty);
2890             set_inline_hint(llfn);
2891             llfn
2892         }
2893
2894         ref variant => {
2895             ccx.sess().bug(&format!("get_item_val(): unexpected variant: {:?}",
2896                                    variant))
2897         }
2898     };
2899
2900     // All LLVM globals and functions are initially created as external-linkage
2901     // declarations.  If `trans_item`/`trans_fn` later turns the declaration
2902     // into a definition, it adjusts the linkage then (using `update_linkage`).
2903     //
2904     // The exception is foreign items, which have their linkage set inside the
2905     // call to `foreign::register_*` above.  We don't touch the linkage after
2906     // that (`foreign::trans_foreign_mod` doesn't adjust the linkage like the
2907     // other item translation functions do).
2908
2909     ccx.item_vals().borrow_mut().insert(id, val);
2910     val
2911 }
2912
2913 fn register_method(ccx: &CrateContext, id: ast::NodeId,
2914                    attrs: &[ast::Attribute], span: Span) -> ValueRef {
2915     let mty = ty::node_id_to_type(ccx.tcx(), id);
2916
2917     let sym = exported_name(ccx, id, mty, &attrs);
2918
2919     if let ty::ty_bare_fn(_, ref f) = mty.sty {
2920         let llfn = if f.abi == Rust || f.abi == RustCall {
2921             register_fn(ccx, span, sym, id, mty)
2922         } else {
2923             foreign::register_rust_fn_with_foreign_abi(ccx, span, sym, id)
2924         };
2925         set_llvm_fn_attrs(ccx, &attrs, llfn);
2926         return llfn;
2927     } else {
2928         ccx.sess().span_bug(span, "expected bare rust function");
2929     }
2930 }
2931
2932 pub fn crate_ctxt_to_encode_parms<'a, 'tcx>(cx: &'a SharedCrateContext<'tcx>,
2933                                             ie: encoder::EncodeInlinedItem<'a>)
2934                                             -> encoder::EncodeParams<'a, 'tcx> {
2935     encoder::EncodeParams {
2936         diag: cx.sess().diagnostic(),
2937         tcx: cx.tcx(),
2938         reexports: cx.export_map(),
2939         item_symbols: cx.item_symbols(),
2940         link_meta: cx.link_meta(),
2941         cstore: &cx.sess().cstore,
2942         encode_inlined_item: ie,
2943         reachable: cx.reachable(),
2944     }
2945 }
2946
2947 pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec<u8> {
2948     use flate;
2949
2950     let any_library = cx.sess().crate_types.borrow().iter().any(|ty| {
2951         *ty != config::CrateTypeExecutable
2952     });
2953     if !any_library {
2954         return Vec::new()
2955     }
2956
2957     let encode_inlined_item: encoder::EncodeInlinedItem =
2958         Box::new(|ecx, rbml_w, ii| astencode::encode_inlined_item(ecx, rbml_w, ii));
2959
2960     let encode_parms = crate_ctxt_to_encode_parms(cx, encode_inlined_item);
2961     let metadata = encoder::encode_metadata(encode_parms, krate);
2962     let mut compressed = encoder::metadata_encoding_version.to_vec();
2963     compressed.push_all(&flate::deflate_bytes(&metadata));
2964     let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed[..]);
2965     let llconst = C_struct_in_context(cx.metadata_llcx(), &[llmeta], false);
2966     let name = format!("rust_metadata_{}_{}",
2967                        cx.link_meta().crate_name,
2968                        cx.link_meta().crate_hash);
2969     let buf = CString::new(name).unwrap();
2970     let llglobal = unsafe {
2971         llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(),
2972                             buf.as_ptr())
2973     };
2974     unsafe {
2975         llvm::LLVMSetInitializer(llglobal, llconst);
2976         let name = loader::meta_section_name(cx.sess().target.target.options.is_like_osx);
2977         let name = CString::new(name).unwrap();
2978         llvm::LLVMSetSection(llglobal, name.as_ptr())
2979     }
2980     return metadata;
2981 }
2982
2983 /// Find any symbols that are defined in one compilation unit, but not declared
2984 /// in any other compilation unit.  Give these symbols internal linkage.
2985 fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
2986     unsafe {
2987         let mut declared = HashSet::new();
2988
2989         let iter_globals = |llmod| {
2990             ValueIter {
2991                 cur: llvm::LLVMGetFirstGlobal(llmod),
2992                 step: llvm::LLVMGetNextGlobal,
2993             }
2994         };
2995
2996         let iter_functions = |llmod| {
2997             ValueIter {
2998                 cur: llvm::LLVMGetFirstFunction(llmod),
2999                 step: llvm::LLVMGetNextFunction,
3000             }
3001         };
3002
3003         // Collect all external declarations in all compilation units.
3004         for ccx in cx.iter() {
3005             for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
3006                 let linkage = llvm::LLVMGetLinkage(val);
3007                 // We only care about external declarations (not definitions)
3008                 // and available_externally definitions.
3009                 if !(linkage == llvm::ExternalLinkage as c_uint &&
3010                      llvm::LLVMIsDeclaration(val) != 0) &&
3011                    !(linkage == llvm::AvailableExternallyLinkage as c_uint) {
3012                     continue
3013                 }
3014
3015                 let name = CStr::from_ptr(llvm::LLVMGetValueName(val))
3016                                 .to_bytes().to_vec();
3017                 declared.insert(name);
3018             }
3019         }
3020
3021         // Examine each external definition.  If the definition is not used in
3022         // any other compilation unit, and is not reachable from other crates,
3023         // then give it internal linkage.
3024         for ccx in cx.iter() {
3025             for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
3026                 // We only care about external definitions.
3027                 if !(llvm::LLVMGetLinkage(val) == llvm::ExternalLinkage as c_uint &&
3028                      llvm::LLVMIsDeclaration(val) == 0) {
3029                     continue
3030                 }
3031
3032                 let name = CStr::from_ptr(llvm::LLVMGetValueName(val))
3033                                 .to_bytes().to_vec();
3034                 if !declared.contains(&name) &&
3035                    !reachable.contains(str::from_utf8(&name).unwrap()) {
3036                     llvm::SetLinkage(val, llvm::InternalLinkage);
3037                 }
3038             }
3039         }
3040     }
3041
3042
3043     struct ValueIter {
3044         cur: ValueRef,
3045         step: unsafe extern "C" fn(ValueRef) -> ValueRef,
3046     }
3047
3048     impl Iterator for ValueIter {
3049         type Item = ValueRef;
3050
3051         fn next(&mut self) -> Option<ValueRef> {
3052             let old = self.cur;
3053             if !old.is_null() {
3054                 self.cur = unsafe {
3055                     let step: unsafe extern "C" fn(ValueRef) -> ValueRef =
3056                         mem::transmute_copy(&self.step);
3057                     step(old)
3058                 };
3059                 Some(old)
3060             } else {
3061                 None
3062             }
3063         }
3064     }
3065 }
3066
3067 pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
3068                          -> (ty::ctxt<'tcx>, CrateTranslation) {
3069     let ty::CrateAnalysis { ty_cx: tcx, export_map, reachable, name, .. } = analysis;
3070     let krate = tcx.map.krate();
3071
3072     let check_overflow = if let Some(v) = tcx.sess.opts.debugging_opts.force_overflow_checks {
3073         v
3074     } else {
3075         tcx.sess.opts.debug_assertions
3076     };
3077
3078     // Before we touch LLVM, make sure that multithreading is enabled.
3079     unsafe {
3080         use std::sync::{Once, ONCE_INIT};
3081         static INIT: Once = ONCE_INIT;
3082         static mut POISONED: bool = false;
3083         INIT.call_once(|| {
3084             if llvm::LLVMStartMultithreaded() != 1 {
3085                 // use an extra bool to make sure that all future usage of LLVM
3086                 // cannot proceed despite the Once not running more than once.
3087                 POISONED = true;
3088             }
3089         });
3090
3091         if POISONED {
3092             tcx.sess.bug("couldn't enable multi-threaded LLVM");
3093         }
3094     }
3095
3096     let link_meta = link::build_link_meta(&tcx.sess, krate, name);
3097
3098     let codegen_units = tcx.sess.opts.cg.codegen_units;
3099     let shared_ccx = SharedCrateContext::new(&link_meta.crate_name,
3100                                              codegen_units,
3101                                              tcx,
3102                                              export_map,
3103                                              Sha256::new(),
3104                                              link_meta.clone(),
3105                                              reachable,
3106                                              check_overflow);
3107
3108     {
3109         let ccx = shared_ccx.get_ccx(0);
3110
3111         // First, verify intrinsics.
3112         intrinsic::check_intrinsics(&ccx);
3113
3114         // Next, translate the module.
3115         {
3116             let _icx = push_ctxt("text");
3117             trans_mod(&ccx, &krate.module);
3118         }
3119     }
3120
3121     for ccx in shared_ccx.iter() {
3122         if ccx.sess().opts.debuginfo != NoDebugInfo {
3123             debuginfo::finalize(&ccx);
3124         }
3125     }
3126
3127     // Translate the metadata.
3128     let metadata = write_metadata(&shared_ccx, krate);
3129
3130     if shared_ccx.sess().trans_stats() {
3131         let stats = shared_ccx.stats();
3132         println!("--- trans stats ---");
3133         println!("n_glues_created: {}", stats.n_glues_created.get());
3134         println!("n_null_glues: {}", stats.n_null_glues.get());
3135         println!("n_real_glues: {}", stats.n_real_glues.get());
3136
3137         println!("n_fns: {}", stats.n_fns.get());
3138         println!("n_monos: {}", stats.n_monos.get());
3139         println!("n_inlines: {}", stats.n_inlines.get());
3140         println!("n_closures: {}", stats.n_closures.get());
3141         println!("fn stats:");
3142         stats.fn_stats.borrow_mut().sort_by(|&(_, insns_a), &(_, insns_b)| {
3143             insns_b.cmp(&insns_a)
3144         });
3145         for tuple in &*stats.fn_stats.borrow() {
3146             match *tuple {
3147                 (ref name, insns) => {
3148                     println!("{} insns, {}", insns, *name);
3149                 }
3150             }
3151         }
3152     }
3153     if shared_ccx.sess().count_llvm_insns() {
3154         for (k, v) in &*shared_ccx.stats().llvm_insns.borrow() {
3155             println!("{:7} {}", *v, *k);
3156         }
3157     }
3158
3159     let modules = shared_ccx.iter()
3160         .map(|ccx| ModuleTranslation { llcx: ccx.llcx(), llmod: ccx.llmod() })
3161         .collect();
3162
3163     let mut reachable: Vec<String> = shared_ccx.reachable().iter().filter_map(|id| {
3164         shared_ccx.item_symbols().borrow().get(id).map(|s| s.to_string())
3165     }).collect();
3166
3167     // For the purposes of LTO, we add to the reachable set all of the upstream
3168     // reachable extern fns. These functions are all part of the public ABI of
3169     // the final product, so LTO needs to preserve them.
3170     shared_ccx.sess().cstore.iter_crate_data(|cnum, _| {
3171         let syms = csearch::get_reachable_extern_fns(&shared_ccx.sess().cstore, cnum);
3172         reachable.extend(syms.into_iter().map(|did| {
3173             csearch::get_symbol(&shared_ccx.sess().cstore, did)
3174         }));
3175     });
3176
3177     // Make sure that some other crucial symbols are not eliminated from the
3178     // module. This includes the main function, the crate map (used for debug
3179     // log settings and I/O), and finally the curious rust_stack_exhausted
3180     // symbol. This symbol is required for use by the libmorestack library that
3181     // we link in, so we must ensure that this symbol is not internalized (if
3182     // defined in the crate).
3183     reachable.push("main".to_string());
3184     reachable.push("rust_stack_exhausted".to_string());
3185
3186     // referenced from .eh_frame section on some platforms
3187     reachable.push("rust_eh_personality".to_string());
3188     // referenced from rt/rust_try.ll
3189     reachable.push("rust_eh_personality_catch".to_string());
3190
3191     if codegen_units > 1 {
3192         internalize_symbols(&shared_ccx, &reachable.iter().cloned().collect());
3193     }
3194
3195     let metadata_module = ModuleTranslation {
3196         llcx: shared_ccx.metadata_llcx(),
3197         llmod: shared_ccx.metadata_llmod(),
3198     };
3199     let formats = shared_ccx.tcx().dependency_formats.borrow().clone();
3200     let no_builtins = attr::contains_name(&krate.attrs, "no_builtins");
3201
3202     let translation = CrateTranslation {
3203         modules: modules,
3204         metadata_module: metadata_module,
3205         link: link_meta,
3206         metadata: metadata,
3207         reachable: reachable,
3208         crate_formats: formats,
3209         no_builtins: no_builtins,
3210     };
3211
3212     (shared_ccx.take_tcx(), translation)
3213 }