diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 071d9d68dbb..bcca008c5e9 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -2684,6 +2684,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, println!("n_null_glues: {}", stats.n_null_glues.get()); println!("n_real_glues: {}", stats.n_real_glues.get()); + println!("n_fallback_instantiations: {}", stats.n_fallback_instantiations.get()); + println!("n_fns: {}", stats.n_fns.get()); println!("n_monos: {}", stats.n_monos.get()); println!("n_inlines: {}", stats.n_inlines.get()); @@ -2875,6 +2877,14 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a assert!(scx.tcx().sess.opts.cg.codegen_units == codegen_units.len() || scx.tcx().sess.opts.debugging_opts.incremental.is_some()); + { + let mut ccx_map = scx.translation_items().borrow_mut(); + + for trans_item in items.iter().cloned() { + ccx_map.insert(trans_item, TransItemState::PredictedButNotGenerated); + } + } + if scx.sess().opts.debugging_opts.print_trans_items.is_some() { let mut item_to_cgus = HashMap::new(); @@ -2926,12 +2936,6 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a for item in item_keys { println!("TRANS_ITEM {}", item); } - - let mut ccx_map = scx.translation_items().borrow_mut(); - - for cgi in items { - ccx_map.insert(cgi, TransItemState::PredictedButNotGenerated); - } } (codegen_units, symbol_map) diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 64e0351610f..8f700e2fe38 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -53,6 +53,7 @@ pub struct Stats { pub n_glues_created: Cell, pub n_null_glues: Cell, pub n_real_glues: Cell, + pub n_fallback_instantiations: Cell, pub n_fns: Cell, pub n_monos: Cell, pub n_inlines: Cell, @@ -406,6 +407,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { n_glues_created: Cell::new(0), n_null_glues: Cell::new(0), n_real_glues: Cell::new(0), + n_fallback_instantiations: Cell::new(0), n_fns: Cell::new(0), n_monos: Cell::new(0), n_inlines: Cell::new(0), diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 3b4a9499a11..468192d7f11 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -234,13 +234,34 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKind<'tcx>) -> ValueRef { let g = g.map_ty(|t| get_drop_glue_type(ccx.tcx(), t)); match ccx.drop_glues().borrow().get(&g) { - Some(&(glue, _)) => glue, - None => { bug!("Could not find drop glue for {:?} -- {} -- {}. \ - It should have be instantiated during the pre-definition phase", - g, - TransItem::DropGlue(g).to_raw_string(), - ccx.codegen_unit().name) } + Some(&(glue, _)) => return glue, + None => { + debug!("Could not find drop glue for {:?} -- {} -- {}. \ + Falling back to on-demand instantiation.", + g, + TransItem::DropGlue(g).to_raw_string(), + ccx.codegen_unit().name); + + ccx.stats().n_fallback_instantiations.set(ccx.stats() + .n_fallback_instantiations + .get() + 1); + } } + + // FIXME: #34151 + // Normally, getting here would indicate a bug in trans::collector, + // since it seems to have missed a translation item. When we are + // translating with non-MIR-based trans, however, the results of the + // collector are not entirely reliable since it bases its analysis + // on MIR. Thus, we'll instantiate the missing function on demand in + // this codegen unit, so that things keep working. + + TransItem::DropGlue(g).predefine(ccx, llvm::LinkOnceODRLinkage); + TransItem::DropGlue(g).define(ccx); + + // Now that we made sure that the glue function is in ccx.drop_glues, + // give it another try + get_drop_glue_core(ccx, g) } pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index f12eb1cd8e1..71aacfdfe58 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -121,8 +121,25 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ref attrs, node: hir::MethodTraitItem( hir::MethodSig { .. }, Some(_)), .. }) => { - attributes::from_fn_attrs(ccx, attrs, lldecl); - llvm::SetLinkage(lldecl, llvm::ExternalLinkage); + let trans_item = TransItem::Fn(instance); + + if ccx.shared().translation_items().borrow().contains_key(&trans_item) { + attributes::from_fn_attrs(ccx, attrs, lldecl); + llvm::SetLinkage(lldecl, llvm::ExternalLinkage); + } else { + // FIXME: #34151 + // Normally, getting here would indicate a bug in trans::collector, + // since it seems to have missed a translation item. When we are + // translating with non-MIR based trans, however, the results of + // the collector are not entirely reliable since it bases its + // analysis on MIR. Thus, we'll instantiate the missing function + // privately in this codegen unit, so that things keep working. + ccx.stats().n_fallback_instantiations.set(ccx.stats() + .n_fallback_instantiations + .get() + 1); + trans_item.predefine(ccx, llvm::PrivateLinkage); + trans_item.define(ccx); + } } hir_map::NodeVariant(_) | hir_map::NodeStructCtor(_) => { diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 785c193c855..edf5db81b18 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -517,11 +517,11 @@ fn single_codegen_unit<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if reachable.contains(&node_id) { llvm::ExternalLinkage } else { - llvm::InternalLinkage + llvm::PrivateLinkage } } TransItem::DropGlue(_) => { - llvm::InternalLinkage + llvm::PrivateLinkage } TransItem::Fn(instance) => { if trans_item.is_generic_fn() || diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index b4f8a116662..2fc90b821fe 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -108,19 +108,19 @@ impl<'a, 'tcx> TransItem<'tcx> { ccx.codegen_unit().name); let symbol_name = ccx.symbol_map() - .get(*self) - .expect("Name not present in SymbolMap?"); - debug!("symbol {}", symbol_name); + .get_or_compute(ccx.shared(), *self); + + debug!("symbol {}", &symbol_name); match *self { TransItem::Static(node_id) => { - TransItem::predefine_static(ccx, node_id, linkage, symbol_name); + TransItem::predefine_static(ccx, node_id, linkage, &symbol_name); } TransItem::Fn(instance) => { - TransItem::predefine_fn(ccx, instance, linkage, symbol_name); + TransItem::predefine_fn(ccx, instance, linkage, &symbol_name); } TransItem::DropGlue(dg) => { - TransItem::predefine_drop_glue(ccx, dg, linkage, symbol_name); + TransItem::predefine_drop_glue(ccx, dg, linkage, &symbol_name); } }