diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 40ae5025180..05ae347b534 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -75,6 +75,7 @@ use debuginfo::{self, DebugLoc, ToDebugLoc}; use declare; use expr; use glue; +use inline; use machine; use machine::{llalign_of_min, llsize_of, llsize_of_real}; use meth; @@ -1948,6 +1949,49 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, closure::ClosureEnv::NotClosure); } +pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance<'tcx>) { + let instance = inline::maybe_inline_instance(ccx, instance); + + let fn_node_id = ccx.tcx().map.as_local_node_id(instance.def).unwrap(); + + let _s = StatRecorder::new(ccx, ccx.tcx().node_path_str(fn_node_id)); + debug!("trans_instance(instance={:?})", instance); + let _icx = push_ctxt("trans_instance"); + + let item = ccx.tcx().map.find(fn_node_id).unwrap(); + + let fn_ty = ccx.tcx().lookup_item_type(instance.def).ty; + let fn_ty = ccx.tcx().erase_regions(&fn_ty); + let fn_ty = monomorphize::apply_param_substs(ccx.tcx(), instance.substs, &fn_ty); + + let sig = ccx.tcx().erase_late_bound_regions(fn_ty.fn_sig()); + let sig = ccx.tcx().normalize_associated_type(&sig); + let abi = fn_ty.fn_abi(); + + let lldecl = match ccx.instances().borrow().get(&instance) { + Some(&val) => val, + None => bug!("Instance `{:?}` not already declared", instance) + }; + + match item { + hir_map::NodeItem(&hir::Item { + node: hir::ItemFn(ref decl, _, _, _, _, ref body), .. + }) | + hir_map::NodeTraitItem(&hir::TraitItem { + node: hir::MethodTraitItem( + hir::MethodSig { ref decl, .. }, Some(ref body)), .. + }) | + hir_map::NodeImplItem(&hir::ImplItem { + node: hir::ImplItemKind::Method( + hir::MethodSig { ref decl, .. }, ref body), .. + }) => { + trans_closure(ccx, decl, body, lldecl, instance, + fn_node_id, &sig, abi, closure::ClosureEnv::NotClosure); + } + _ => bug!("Instance is a {:?}?", item) + } +} + pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, ctor_ty: Ty<'tcx>, disr: Disr, @@ -2267,70 +2311,23 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) { let _icx = push_ctxt("trans_item"); let tcx = ccx.tcx(); - let from_external = ccx.external_srcs().borrow().contains_key(&item.id); - match item.node { - hir::ItemFn(ref decl, _, _, _, ref generics, ref body) => { - if !generics.is_type_parameterized() { - let trans_everywhere = attr::requests_inline(&item.attrs); - // Ignore `trans_everywhere` for cross-crate inlined items - // (`from_external`). `trans_item` will be called once for each - // compilation unit that references the item, so it will still get - // translated everywhere it's needed. - for (ref ccx, is_origin) in ccx.maybe_iter(!from_external && trans_everywhere) { - let def_id = tcx.map.local_def_id(item.id); - let empty_substs = ccx.empty_substs_for_def_id(def_id); - let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val; - trans_fn(ccx, &decl, &body, llfn, empty_substs, item.id); - set_link_section(ccx, llfn, &item.attrs); - update_linkage(ccx, - llfn, - Some(item.id), - if is_origin { - OriginalTranslation - } else { - InlinedCopy - }); - - if is_entry_fn(ccx.sess(), item.id) { - create_entry_wrapper(ccx, item.span, llfn); - // check for the #[rustc_error] annotation, which forces an - // error in trans. This is used to write compile-fail tests - // that actually test that compilation succeeds without - // reporting an error. - if tcx.has_attr(def_id, "rustc_error") { - tcx.sess.span_fatal(item.span, "compilation successful"); - } - } + hir::ItemFn(_, _, _, _, _, _) => { + let def_id = tcx.map.local_def_id(item.id); + // check for the #[rustc_error] annotation, which forces an + // error in trans. This is used to write compile-fail tests + // that actually test that compilation succeeds without + // reporting an error. + if is_entry_fn(ccx.sess(), item.id) { + let empty_substs = ccx.empty_substs_for_def_id(def_id); + let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val; + create_entry_wrapper(ccx, item.span, llfn); + if tcx.has_attr(def_id, "rustc_error") { + tcx.sess.span_fatal(item.span, "compilation successful"); } } - } - hir::ItemImpl(_, _, ref generics, _, _, ref impl_items) => { - // Both here and below with generic methods, be sure to recurse and look for - // items that we need to translate. - if !generics.ty_params.is_empty() { - return; - } - for impl_item in impl_items { - if let hir::ImplItemKind::Method(ref sig, ref body) = impl_item.node { - if sig.generics.ty_params.is_empty() { - let trans_everywhere = attr::requests_inline(&impl_item.attrs); - for (ref ccx, is_origin) in ccx.maybe_iter(trans_everywhere) { - let def_id = tcx.map.local_def_id(impl_item.id); - let empty_substs = ccx.empty_substs_for_def_id(def_id); - let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val; - trans_fn(ccx, &sig.decl, body, llfn, empty_substs, impl_item.id); - update_linkage(ccx, llfn, Some(impl_item.id), - if is_origin { - OriginalTranslation - } else { - InlinedCopy - }); - } - } - } - } + // Function is actually translated in trans_instance } hir::ItemEnum(ref enum_definition, ref gens) => { if gens.ty_params.is_empty() { @@ -2338,8 +2335,9 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) { enum_variant_size_lint(ccx, enum_definition, item.span, item.id); } } + hir::ItemImpl(..) | hir::ItemStatic(..) => { - // Don't do anything here. Translation of statics has been moved to + // Don't do anything here. Translation has been moved to // being "collector-driven". } _ => {} @@ -2482,16 +2480,16 @@ fn internalize_symbols(cx: &CrateContextList, reachable: &HashSet<&str>) { let linkage = llvm::LLVMGetLinkage(val); // We only care about external declarations (not definitions) // and available_externally definitions. - if !(linkage == llvm::ExternalLinkage as c_uint && - llvm::LLVMIsDeclaration(val) != 0) && - !(linkage == llvm::AvailableExternallyLinkage as c_uint) { - continue; + let is_available_externally = linkage == llvm::AvailableExternallyLinkage as c_uint; + let is_decl = llvm::LLVMIsDeclaration(val) != 0; + + if is_decl || is_available_externally { + let name = CStr::from_ptr(llvm::LLVMGetValueName(val)) + .to_bytes() + .to_vec(); + declared.insert(name); } - let name = CStr::from_ptr(llvm::LLVMGetValueName(val)) - .to_bytes() - .to_vec(); - declared.insert(name); } } @@ -2501,21 +2499,27 @@ fn internalize_symbols(cx: &CrateContextList, reachable: &HashSet<&str>) { for ccx in cx.iter() { for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) { let linkage = llvm::LLVMGetLinkage(val); - // We only care about external definitions. - if !((linkage == llvm::ExternalLinkage as c_uint || - linkage == llvm::WeakODRLinkage as c_uint) && - llvm::LLVMIsDeclaration(val) == 0) { - continue; - } - let name = CStr::from_ptr(llvm::LLVMGetValueName(val)) - .to_bytes() - .to_vec(); - if !declared.contains(&name) && - !reachable.contains(str::from_utf8(&name).unwrap()) { - llvm::SetLinkage(val, llvm::InternalLinkage); - llvm::SetDLLStorageClass(val, llvm::DefaultStorageClass); - llvm::UnsetComdat(val); + let is_external = linkage == llvm::ExternalLinkage as c_uint; + let is_weak_odr = linkage == llvm::WeakODRLinkage as c_uint; + let is_decl = llvm::LLVMIsDeclaration(val) != 0; + + // We only care about external definitions. + if (is_external || is_weak_odr) && !is_decl { + + let name = CStr::from_ptr(llvm::LLVMGetValueName(val)) + .to_bytes() + .to_vec(); + + let is_declared = declared.contains(&name); + let reachable = reachable.contains(str::from_utf8(&name).unwrap()); + + if !is_declared && !reachable { + llvm::SetLinkage(val, llvm::InternalLinkage); + llvm::SetDLLStorageClass(val, llvm::DefaultStorageClass); + llvm::UnsetComdat(val); + } + } } } @@ -2744,6 +2748,9 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span_bug!(item.span, "Mismatch between hir::Item type and TransItem type") } } + TransItem::Fn(instance) => { + trans_instance(&ccx, instance); + } _ => { } } } @@ -2980,7 +2987,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a let mut item_keys: Vec<_> = items .iter() .map(|i| { - let mut output = i.to_string(scx.tcx()); + let mut output = i.to_string(scx); output.push_str(" @@"); let mut empty = Vec::new(); let mut cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty); diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs index 9196cfce16f..bf9cde9a441 100644 --- a/src/librustc_trans/closure.rs +++ b/src/librustc_trans/closure.rs @@ -10,7 +10,7 @@ use arena::TypedArena; use back::symbol_names; -use llvm::{ValueRef, get_param, get_params}; +use llvm::{self, ValueRef, get_param, get_params}; use rustc::hir::def_id::DefId; use abi::{Abi, FnType}; use adt; @@ -167,7 +167,7 @@ fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, variadic: false }) })); - let llfn = declare::define_internal_fn(ccx, &symbol, function_type); + let llfn = declare::declare_fn(ccx, &symbol, function_type); // set an inline hint for all closures attributes::inline(llfn, attributes::InlineAttr::Hint); @@ -211,6 +211,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>, id, closure_def_id, closure_substs); let llfn = get_or_create_closure_declaration(ccx, closure_def_id, closure_substs); + llvm::SetLinkage(llfn, llvm::WeakODRLinkage); // Get the type of this closure. Use the current `param_substs` as // the closure substitutions. This makes sense because the closure @@ -377,7 +378,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( // Create the by-value helper. let function_name = symbol_names::internal_name_from_type_and_suffix(ccx, llonce_fn_ty, "once_shim"); - let lloncefn = declare::define_internal_fn(ccx, &function_name, llonce_fn_ty); + let lloncefn = declare::declare_fn(ccx, &function_name, llonce_fn_ty); attributes::set_frame_pointer_elimination(ccx, lloncefn); let (block_arena, fcx): (TypedArena<_>, FunctionContext); diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index eea6aec3726..8cb9fd23e49 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -325,7 +325,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>, // We've been here already, no need to search again. return; } - debug!("BEGIN collect_items_rec({})", starting_point.to_string(scx.tcx())); + debug!("BEGIN collect_items_rec({})", starting_point.to_string(scx)); let mut neighbors = Vec::new(); let recursion_depth_reset; @@ -396,7 +396,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>, recursion_depths.insert(def_id, depth); } - debug!("END collect_items_rec({})", starting_point.to_string(scx.tcx())); + debug!("END collect_items_rec({})", starting_point.to_string(scx)); } fn record_inlining_canditates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -456,12 +456,25 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { match *rvalue { mir::Rvalue::Aggregate(mir::AggregateKind::Closure(def_id, ref substs), _) => { - assert!(can_have_local_instance(self.scx.tcx(), def_id)); - let trans_item = create_fn_trans_item(self.scx.tcx(), - def_id, - substs.func_substs, - self.param_substs); - self.output.push(trans_item); + let mir = errors::expect(self.scx.sess().diagnostic(), self.scx.get_mir(def_id), + || format!("Could not find MIR for closure: {:?}", def_id)); + + let concrete_substs = monomorphize::apply_param_substs(self.scx.tcx(), + self.param_substs, + &substs.func_substs); + let concrete_substs = self.scx.tcx().erase_regions(&concrete_substs); + + let mut visitor = MirNeighborCollector { + scx: self.scx, + mir: &mir, + output: self.output, + param_substs: concrete_substs + }; + + visitor.visit_mir(&mir); + for promoted in &mir.promoted { + visitor.visit_mir(promoted); + } } // When doing an cast from a regular pointer to a fat pointer, we // have to instantiate all methods of the trait being cast to, so we @@ -1107,9 +1120,8 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> { self.scx.tcx().map.local_def_id(item.id))); self.output.push(TransItem::Static(item.id)); } - hir::ItemFn(_, _, constness, _, ref generics, _) => { - if !generics.is_type_parameterized() && - constness == hir::Constness::NotConst { + hir::ItemFn(_, _, _, _, ref generics, _) => { + if !generics.is_type_parameterized() { let def_id = self.scx.tcx().map.local_def_id(item.id); debug!("RootCollector: ItemFn({})", @@ -1129,9 +1141,8 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> { match ii.node { hir::ImplItemKind::Method(hir::MethodSig { ref generics, - constness, .. - }, _) if constness == hir::Constness::NotConst => { + }, _) => { let hir_map = &self.scx.tcx().map; let parent_node_id = hir_map.get_parent_node(ii.id); let is_impl_generic = match hir_map.expect_item(parent_node_id) { @@ -1260,7 +1271,7 @@ pub fn print_collection_results<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>) { let mut item_keys = FnvHashMap(); for (item, item_state) in trans_items.iter() { - let k = item.to_string(scx.tcx()); + let k = item.to_string(scx); if item_keys.contains_key(&k) { let prev: (TransItem, TransItemState) = item_keys[&k]; @@ -1288,7 +1299,7 @@ pub fn print_collection_results<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>) { let mut generated = FnvHashSet(); for (item, item_state) in trans_items.iter() { - let item_key = item.to_string(scx.tcx()); + let item_key = item.to_string(scx); match *item_state { TransItemState::PredictedAndGenerated => { diff --git a/src/librustc_trans/inline.rs b/src/librustc_trans/inline.rs index af175fbf882..4077b894d62 100644 --- a/src/librustc_trans/inline.rs +++ b/src/librustc_trans/inline.rs @@ -8,13 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::{AvailableExternallyLinkage, InternalLinkage, SetLinkage}; use middle::cstore::{FoundAst, InlinedItem}; use rustc::hir::def_id::DefId; -use rustc::ty::subst::Substs; -use base::{push_ctxt, trans_item, trans_fn}; -use callee::Callee; +use base::push_ctxt; use common::*; +use monomorphize::Instance; use rustc::dep_graph::DepNode; use rustc::hir; @@ -52,30 +50,6 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option { ccx.external_srcs().borrow_mut().insert(item.id, fn_id); ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1); - trans_item(ccx, item); - - if let hir::ItemFn(_, _, _, _, ref generics, _) = item.node { - // Generics have no symbol, so they can't be given any linkage. - if !generics.is_type_parameterized() { - let linkage = if ccx.sess().opts.cg.codegen_units == 1 { - // We could use AvailableExternallyLinkage here, - // but InternalLinkage allows LLVM to optimize more - // aggressively (at the cost of sometimes - // duplicating code). - InternalLinkage - } else { - // With multiple compilation units, duplicated code - // is more of a problem. Also, `codegen_units > 1` - // means the user is okay with losing some - // performance. - AvailableExternallyLinkage - }; - let empty_substs = tcx.mk_substs(Substs::empty()); - let def_id = tcx.map.local_def_id(item.id); - let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val; - SetLinkage(llfn, linkage); - } - } item.id } @@ -135,35 +109,12 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option { // don't. trait_item.id } - FoundAst::Found(&InlinedItem::ImplItem(impl_did, ref impl_item)) => { + FoundAst::Found(&InlinedItem::ImplItem(_, ref impl_item)) => { ccx.external().borrow_mut().insert(fn_id, Some(impl_item.id)); ccx.external_srcs().borrow_mut().insert(impl_item.id, fn_id); ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1); - // Translate monomorphic impl methods immediately. - if let hir::ImplItemKind::Method(ref sig, ref body) = impl_item.node { - let impl_tpt = tcx.lookup_item_type(impl_did); - if impl_tpt.generics.types.is_empty() && - sig.generics.ty_params.is_empty() { - let def_id = tcx.map.local_def_id(impl_item.id); - let empty_substs = ccx.empty_substs_for_def_id(def_id); - let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val; - trans_fn(ccx, - &sig.decl, - body, - llfn, - empty_substs, - impl_item.id); - // See linkage comments on items. - if ccx.sess().opts.cg.codegen_units == 1 { - SetLinkage(llfn, InternalLinkage); - } else { - SetLinkage(llfn, AvailableExternallyLinkage); - } - } - } - impl_item.id } }; @@ -184,3 +135,12 @@ pub fn get_local_instance(ccx: &CrateContext, fn_id: DefId) pub fn maybe_instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> DefId { get_local_instance(ccx, fn_id).unwrap_or(fn_id) } + +pub fn maybe_inline_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, + instance: Instance<'tcx>) -> Instance<'tcx> { + let def_id = maybe_instantiate_inline(ccx, instance.def); + Instance { + def: def_id, + substs: instance.substs + } +} diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index ab859b88a85..13d6d432422 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -109,15 +109,16 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, }); match map_node { hir_map::NodeItem(&hir::Item { - ref attrs, node: hir::ItemFn(ref decl, _, _, _, _, ref body), .. - }) | - hir_map::NodeTraitItem(&hir::TraitItem { - ref attrs, node: hir::MethodTraitItem( - hir::MethodSig { ref decl, .. }, Some(ref body)), .. + ref attrs, + node: hir::ItemFn(ref decl, _, _, _, _, ref body), .. }) | hir_map::NodeImplItem(&hir::ImplItem { ref attrs, node: hir::ImplItemKind::Method( hir::MethodSig { ref decl, .. }, ref body), .. + }) | + hir_map::NodeTraitItem(&hir::TraitItem { + ref attrs, node: hir::MethodTraitItem( + hir::MethodSig { ref decl, .. }, Some(ref body)), .. }) => { attributes::from_fn_attrs(ccx, attrs, lldecl); diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 92fddd7d77d..f3c0ddfaf73 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -14,19 +14,22 @@ //! item-path. This is used for unit testing the code that generates //! paths etc in all kinds of annoying scenarios. +use attributes; use base; -use context::CrateContext; +use context::{SharedCrateContext, CrateContext}; use declare; use glue::DropGlueKind; use llvm; -use monomorphize::Instance; +use monomorphize::{self, Instance}; +use inline; use rustc::hir; +use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::subst; use std::hash::{Hash, Hasher}; use syntax::ast::{self, NodeId}; -use syntax::attr; +use syntax::{attr,errors}; use syntax::parse::token; use type_of; @@ -59,24 +62,27 @@ impl<'tcx> Hash for TransItem<'tcx> { } -impl<'tcx> TransItem<'tcx> { +impl<'a, 'tcx> TransItem<'tcx> { - pub fn predefine<'ccx>(&self, - ccx: &CrateContext<'ccx, 'tcx>, - linkage: llvm::Linkage) { + pub fn predefine(&self, + ccx: &CrateContext<'a, 'tcx>, + linkage: llvm::Linkage) { match *self { TransItem::Static(node_id) => { TransItem::predefine_static(ccx, node_id, linkage); } + TransItem::Fn(instance) => { + TransItem::predefine_fn(ccx, instance, linkage); + } _ => { // Not yet implemented } } } - fn predefine_static<'a>(ccx: &CrateContext<'a, 'tcx>, - node_id: ast::NodeId, - linkage: llvm::Linkage) { + fn predefine_static(ccx: &CrateContext<'a, 'tcx>, + node_id: ast::NodeId, + linkage: llvm::Linkage) { let def_id = ccx.tcx().map.local_def_id(node_id); let ty = ccx.tcx().lookup_item_type(def_id).ty; let llty = type_of::type_of(ccx, ty); @@ -101,7 +107,57 @@ impl<'tcx> TransItem<'tcx> { } } - pub fn requests_inline<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool { + fn predefine_fn(ccx: &CrateContext<'a, 'tcx>, + instance: Instance<'tcx>, + linkage: llvm::Linkage) { + let unit = ccx.codegen_unit(); + debug!("predefine_fn[cg={}](instance={:?})", &unit.name[..], instance); + assert!(!instance.substs.types.needs_infer() && + !instance.substs.types.has_param_types()); + + let instance = inline::maybe_inline_instance(ccx, instance); + + let item_ty = ccx.tcx().lookup_item_type(instance.def).ty; + let item_ty = ccx.tcx().erase_regions(&item_ty); + let mono_ty = monomorphize::apply_param_substs(ccx.tcx(), instance.substs, &item_ty); + + let fn_node_id = ccx.tcx().map.as_local_node_id(instance.def).unwrap(); + let map_node = errors::expect( + ccx.sess().diagnostic(), + ccx.tcx().map.find(fn_node_id), + || { + format!("while instantiating `{}`, couldn't find it in \ + the item map (may have attempted to monomorphize \ + an item defined in a different crate?)", + instance) + }); + + match map_node { + hir_map::NodeItem(&hir::Item { + ref attrs, node: hir::ItemFn(..), .. + }) | + hir_map::NodeTraitItem(&hir::TraitItem { + ref attrs, node: hir::MethodTraitItem(..), .. + }) | + hir_map::NodeImplItem(&hir::ImplItem { + ref attrs, node: hir::ImplItemKind::Method(..), .. + }) => { + let symbol = instance.symbol_name(ccx.shared()); + let lldecl = declare::declare_fn(ccx, &symbol, mono_ty); + + attributes::from_fn_attrs(ccx, attrs, lldecl); + llvm::SetLinkage(lldecl, linkage); + base::set_link_section(ccx, lldecl, attrs); + + ccx.instances().borrow_mut().insert(instance, lldecl); + } + _ => bug!("Invalid item for TransItem::Fn: `{:?}`", map_node) + }; + + } + + + pub fn requests_inline(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool { match *self { TransItem::Fn(ref instance) => { let attributes = tcx.get_attrs(instance.def); @@ -128,7 +184,7 @@ impl<'tcx> TransItem<'tcx> { } } - pub fn explicit_linkage<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option { + pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option { let def_id = match *self { TransItem::Fn(ref instance) => instance.def, TransItem::Static(node_id) => tcx.map.local_def_id(node_id), @@ -152,7 +208,8 @@ impl<'tcx> TransItem<'tcx> { } } - pub fn to_string<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String { + pub fn to_string(&self, scx: &SharedCrateContext<'a, 'tcx>) -> String { + let tcx = scx.tcx(); let hir_map = &tcx.map; return match *self { @@ -170,13 +227,12 @@ impl<'tcx> TransItem<'tcx> { }, TransItem::Static(node_id) => { let def_id = hir_map.local_def_id(node_id); - let instance = Instance::new(def_id, - tcx.mk_substs(subst::Substs::empty())); + let instance = Instance::mono(scx, def_id); to_string_internal(tcx, "static ", instance) }, }; - fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx,'tcx>, + fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, prefix: &str, instance: Instance<'tcx>) -> String {