diff options
Diffstat (limited to 'src/librustc_trans/trans/collector.rs')
-rw-r--r-- | src/librustc_trans/trans/collector.rs | 227 |
1 files changed, 72 insertions, 155 deletions
diff --git a/src/librustc_trans/trans/collector.rs b/src/librustc_trans/trans/collector.rs index cea97c1a1e7..2c996c032ca 100644 --- a/src/librustc_trans/trans/collector.rs +++ b/src/librustc_trans/trans/collector.rs @@ -194,10 +194,10 @@ use rustc_front::intravisit as hir_visit; use rustc::front::map as hir_map; use rustc::middle::def_id::DefId; use rustc::middle::lang_items::{ExchangeFreeFnLangItem, ExchangeMallocFnLangItem}; -use rustc::middle::{ty, traits}; +use rustc::middle::traits; use rustc::middle::subst::{self, Substs, Subst}; +use rustc::middle::ty::{self, Ty, TypeFoldable}; use rustc::middle::ty::adjustment::CustomCoerceUnsized; -use rustc::middle::ty::fold::TypeFoldable; use rustc::mir::repr as mir; use rustc::mir::visit as mir_visit; use rustc::mir::visit::Visitor as MirVisitor; @@ -213,11 +213,10 @@ use trans::common::{fulfill_obligation, normalize_and_test_predicates, type_is_sized}; use trans::glue; use trans::meth; -use trans::monomorphize; +use trans::monomorphize::{self, Instance}; use util::nodemap::{FnvHashSet, FnvHashMap, DefIdMap}; use std::hash::{Hash, Hasher}; -use std::rc::Rc; #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)] pub enum TransItemCollectionMode { @@ -225,13 +224,10 @@ pub enum TransItemCollectionMode { Lazy } -#[derive(Eq, Clone, Copy, Debug)] +#[derive(PartialEq, Eq, Clone, Copy, Debug)] pub enum TransItem<'tcx> { - DropGlue(ty::Ty<'tcx>), - Fn { - def_id: DefId, - substs: &'tcx Substs<'tcx> - }, + DropGlue(Ty<'tcx>), + Fn(Instance<'tcx>), Static(NodeId) } @@ -242,35 +238,19 @@ impl<'tcx> Hash for TransItem<'tcx> { 0u8.hash(s); t.hash(s); }, - TransItem::Fn { def_id, substs } => { + TransItem::Fn(instance) => { 1u8.hash(s); - def_id.hash(s); - (substs as *const Substs<'tcx> as usize).hash(s); + instance.def.hash(s); + (instance.params as *const _ as usize).hash(s); } TransItem::Static(node_id) => { - 3u8.hash(s); + 2u8.hash(s); node_id.hash(s); } }; } } -impl<'tcx> PartialEq for TransItem<'tcx> { - fn eq(&self, other: &Self) -> bool { - match (*self, *other) { - (TransItem::DropGlue(t1), TransItem::DropGlue(t2)) => t1 == t2, - (TransItem::Fn { def_id: def_id1, substs: substs1 }, - TransItem::Fn { def_id: def_id2, substs: substs2 }) => { - def_id1 == def_id2 && substs1 == substs2 - }, - (TransItem::Static(node_id1), TransItem::Static(node_id2)) => { - node_id1 == node_id2 - }, - _ => false - } - } -} - pub fn collect_crate_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, mode: TransItemCollectionMode) -> FnvHashSet<TransItem<'tcx>> { @@ -282,14 +262,9 @@ pub fn collect_crate_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, debug!("Building translation item graph, beginning at roots"); let mut visited = FnvHashSet(); let mut recursion_depths = DefIdMap(); - let mut mir_cache = DefIdMap(); for root in roots { - collect_items_rec(ccx, - root, - &mut visited, - &mut recursion_depths, - &mut mir_cache); + collect_items_rec(ccx, root, &mut visited, &mut recursion_depths); } visited @@ -319,27 +294,11 @@ fn collect_roots<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, roots } -#[derive(Clone)] -enum CachedMir<'mir, 'tcx: 'mir> { - Ref(&'mir mir::Mir<'tcx>), - Owned(Rc<mir::Mir<'tcx>>) -} - -impl<'mir, 'tcx: 'mir> CachedMir<'mir, 'tcx> { - fn get_ref<'a>(&'a self) -> &'a mir::Mir<'tcx> { - match *self { - CachedMir::Ref(r) => r, - CachedMir::Owned(ref rc) => &rc, - } - } -} - // Collect all monomorphized translation items reachable from `starting_point` fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>, starting_point: TransItem<'tcx>, visited: &mut FnvHashSet<TransItem<'tcx>>, - recursion_depths: &mut DefIdMap<usize>, - mir_cache: &mut DefIdMap<CachedMir<'a, 'tcx>>) { + recursion_depths: &mut DefIdMap<usize>) { if !visited.insert(starting_point.clone()) { // We've been here already, no need to search again. return; @@ -357,29 +316,33 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>, TransItem::Static(_) => { recursion_depth_reset = None; } - TransItem::Fn { def_id, substs: ref param_substs } => { + TransItem::Fn(instance) => { // Keep track of the monomorphization recursion depth recursion_depth_reset = Some(check_recursion_limit(ccx, - def_id, + instance, recursion_depths)); // Scan the MIR in order to find function calls, closures, and // drop-glue - let mir = load_mir(ccx, def_id, mir_cache); + let mir = errors::expect(ccx.sess().diagnostic(), ccx.get_mir(instance.def), + || format!("Could not find MIR for function: {}", instance)); let mut visitor = MirNeighborCollector { ccx: ccx, - mir: mir.get_ref(), + mir: &mir, output: &mut neighbors, - param_substs: param_substs + param_substs: ccx.tcx().mk_substs(Substs { + types: instance.params.clone(), + regions: subst::ErasedRegions + }) }; - visitor.visit_mir(mir.get_ref()); + visitor.visit_mir(&mir); } } for neighbour in neighbors { - collect_items_rec(ccx, neighbour, visited, recursion_depths, mir_cache); + collect_items_rec(ccx, neighbour, visited, recursion_depths); } if let Some((def_id, depth)) = recursion_depth_reset { @@ -389,42 +352,11 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>, debug!("END collect_items_rec({})", starting_point.to_string(ccx)); } -fn load_mir<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>, - def_id: DefId, - mir_cache: &mut DefIdMap<CachedMir<'a, 'tcx>>) - -> CachedMir<'a, 'tcx> { - let mir_not_found_error_message = || { - format!("Could not find MIR for function: {}", - ccx.tcx().item_path_str(def_id)) - }; - - if def_id.is_local() { - let node_id = ccx.tcx().map.as_local_node_id(def_id).unwrap(); - let mir_opt = ccx.mir_map().map.get(&node_id); - let mir = errors::expect(ccx.sess().diagnostic(), - mir_opt, - mir_not_found_error_message); - CachedMir::Ref(mir) - } else { - if let Some(mir) = mir_cache.get(&def_id) { - return mir.clone(); - } - - let mir_opt = ccx.sess().cstore.maybe_get_item_mir(ccx.tcx(), def_id); - let mir = errors::expect(ccx.sess().diagnostic(), - mir_opt, - mir_not_found_error_message); - let cached = CachedMir::Owned(Rc::new(mir)); - mir_cache.insert(def_id, cached.clone()); - cached - } -} - fn check_recursion_limit<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>, - def_id: DefId, + instance: Instance<'tcx>, recursion_depths: &mut DefIdMap<usize>) -> (DefId, usize) { - let recursion_depth = recursion_depths.get(&def_id) + let recursion_depth = recursion_depths.get(&instance.def) .map(|x| *x) .unwrap_or(0); debug!(" => recursion depth={}", recursion_depth); @@ -433,20 +365,18 @@ fn check_recursion_limit<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>, // more than the recursion limit is assumed to be causing an // infinite expansion. if recursion_depth > ccx.sess().recursion_limit.get() { - if let Some(node_id) = ccx.tcx().map.as_local_node_id(def_id) { - ccx.sess().span_fatal(ccx.tcx().map.span(node_id), - "reached the recursion limit during monomorphization"); + let error = format!("reached the recursion limit while instantiating `{}`", + instance); + if let Some(node_id) = ccx.tcx().map.as_local_node_id(instance.def) { + ccx.sess().span_fatal(ccx.tcx().map.span(node_id), &error); } else { - let error = format!("reached the recursion limit during \ - monomorphization of '{}'", - ccx.tcx().item_path_str(def_id)); - ccx.sess().fatal(&error[..]); + ccx.sess().fatal(&error); } } - recursion_depths.insert(def_id, recursion_depth + 1); + recursion_depths.insert(instance.def, recursion_depth + 1); - (def_id, recursion_depth) + (instance.def, recursion_depth) } struct MirNeighborCollector<'a, 'tcx: 'a> { @@ -750,7 +680,7 @@ fn do_static_dispatch<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, param_substs: &'tcx Substs<'tcx>) -> Option<(DefId, &'tcx Substs<'tcx>)> { debug!("do_static_dispatch(fn_def_id={}, fn_substs={:?}, param_substs={:?})", - def_id_to_string(ccx, fn_def_id, None), + def_id_to_string(ccx, fn_def_id), fn_substs, param_substs); @@ -798,8 +728,8 @@ fn do_static_trait_method_dispatch<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, trait_id={}, \ callee_substs={:?}, \ param_substs={:?}", - def_id_to_string(ccx, trait_method.def_id, None), - def_id_to_string(ccx, trait_id, None), + def_id_to_string(ccx, trait_method.def_id), + def_id_to_string(ccx, trait_id), callee_substs, param_substs); @@ -933,7 +863,7 @@ fn create_fn_trans_item<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, -> TransItem<'tcx> { debug!("create_fn_trans_item(def_id={}, fn_substs={:?}, param_substs={:?})", - def_id_to_string(ccx, def_id, None), + def_id_to_string(ccx, def_id), fn_substs, param_substs); @@ -945,10 +875,10 @@ fn create_fn_trans_item<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_substs); let concrete_substs = ccx.tcx().erase_regions(&concrete_substs); - let trans_item = TransItem::Fn { - def_id: def_id, - substs: ccx.tcx().mk_substs(concrete_substs), - }; + let trans_item = TransItem::Fn(Instance { + def: def_id, + params: &ccx.tcx().mk_substs(concrete_substs).types, + }); return trans_item; } @@ -1048,8 +978,7 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> { if self.mode == TransItemCollectionMode::Eager { debug!("RootCollector: ADT drop-glue for {}", def_id_to_string(self.ccx, - self.ccx.tcx().map.local_def_id(item.id), - None)); + self.ccx.tcx().map.local_def_id(item.id))); let ty = glue::get_drop_glue_type(self.ccx, ty); self.output.push(TransItem::DropGlue(ty)); @@ -1059,8 +988,7 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> { hir::ItemStatic(..) => { debug!("RootCollector: ItemStatic({})", def_id_to_string(self.ccx, - self.ccx.tcx().map.local_def_id(item.id), - None)); + self.ccx.tcx().map.local_def_id(item.id))); self.output.push(TransItem::Static(item.id)); } hir::ItemFn(_, _, constness, _, ref generics, _) => { @@ -1069,12 +997,10 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> { let def_id = self.ccx.tcx().map.local_def_id(item.id); debug!("RootCollector: ItemFn({})", - def_id_to_string(self.ccx, def_id, None)); + def_id_to_string(self.ccx, def_id)); - self.output.push(TransItem::Fn { - def_id: def_id, - substs: self.trans_empty_substs - }); + let instance = Instance::mono(self.ccx.tcx(), def_id); + self.output.push(TransItem::Fn(instance)); } } } @@ -1108,12 +1034,10 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> { let def_id = self.ccx.tcx().map.local_def_id(ii.id); debug!("RootCollector: MethodImplItem({})", - def_id_to_string(self.ccx, def_id, None)); + def_id_to_string(self.ccx, def_id)); - self.output.push(TransItem::Fn { - def_id: def_id, - substs: self.trans_empty_substs - }); + let instance = Instance::mono(self.ccx.tcx(), def_id); + self.output.push(TransItem::Fn(instance)); } } _ => { /* Nothing to do here */ } @@ -1142,7 +1066,7 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let impl_def_id = tcx.map.local_def_id(item.id); debug!("create_trans_items_for_default_impls(item={})", - def_id_to_string(ccx, impl_def_id, None)); + def_id_to_string(ccx, impl_def_id)); if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) { let default_impls = tcx.provided_trait_methods(trait_ref.def_id); @@ -1225,7 +1149,7 @@ pub fn push_unique_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty::TyStruct(adt_def, substs) | ty::TyEnum(adt_def, substs) => { push_item_name(cx, adt_def.did, output); - push_type_params(cx, substs, &[], output); + push_type_params(cx, &substs.types, &[], output); }, ty::TyTuple(ref component_types) => { output.push('('); @@ -1275,7 +1199,7 @@ pub fn push_unique_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty::TyTrait(ref trait_data) => { push_item_name(cx, trait_data.principal.skip_binder().def_id, output); push_type_params(cx, - &trait_data.principal.skip_binder().substs, + &trait_data.principal.skip_binder().substs.types, &trait_data.bounds.projection_bounds, output); }, @@ -1285,7 +1209,7 @@ pub fn push_unique_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, output.push_str("unsafe "); } - if abi != ::syntax::abi::Abi::Rust { + if abi != ::trans::abi::Abi::Rust { output.push_str("extern \""); output.push_str(abi.name()); output.push_str("\" "); @@ -1329,7 +1253,7 @@ pub fn push_unique_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, output.push_str("{"); output.push_str(&format!("{}:{}", def_id.krate, def_id.index.as_usize())); output.push_str("}"); - push_type_params(cx, closure_substs.func_substs, &[], output); + push_type_params(cx, &closure_substs.func_substs.types, &[], output); } ty::TyError | ty::TyInfer(_) | @@ -1371,16 +1295,16 @@ fn push_item_name(ccx: &CrateContext, } fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, - substs: &Substs<'tcx>, + types: &'tcx subst::VecPerParamSpace<Ty<'tcx>>, projections: &[ty::PolyProjectionPredicate<'tcx>], output: &mut String) { - if substs.types.is_empty() && projections.is_empty() { + if types.is_empty() && projections.is_empty() { return; } output.push('<'); - for &type_parameter in &substs.types { + for &type_parameter in types { push_unique_type_name(cx, type_parameter, output); output.push_str(", "); } @@ -1400,23 +1324,16 @@ fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, output.push('>'); } -fn push_def_id_as_string<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - def_id: DefId, - substs: Option<&Substs<'tcx>>, - output: &mut String) { - push_item_name(ccx, def_id, output); - - if let Some(substs) = substs { - push_type_params(ccx, substs, &[], output); - } +fn push_instance_as_string<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, + instance: Instance<'tcx>, + output: &mut String) { + push_item_name(ccx, instance.def, output); + push_type_params(ccx, instance.params, &[], output); } -fn def_id_to_string<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - def_id: DefId, - substs: Option<&Substs<'tcx>>) - -> String { +fn def_id_to_string(ccx: &CrateContext, def_id: DefId) -> String { let mut output = String::new(); - push_def_id_as_string(ccx, def_id, substs, &mut output); + push_item_name(ccx, def_id, &mut output); output } @@ -1440,23 +1357,23 @@ impl<'tcx> TransItem<'tcx> { push_unique_type_name(ccx, t, &mut s); s } - TransItem::Fn { def_id, ref substs } => { - to_string_internal(ccx, "fn ", def_id, Some(substs)) + TransItem::Fn(instance) => { + to_string_internal(ccx, "fn ", instance) }, TransItem::Static(node_id) => { let def_id = hir_map.local_def_id(node_id); - to_string_internal(ccx, "static ", def_id, None) + let instance = Instance::mono(ccx.tcx(), def_id); + to_string_internal(ccx, "static ", instance) }, }; fn to_string_internal<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, prefix: &str, - def_id: DefId, - substs: Option<&Substs<'tcx>>) + instance: Instance<'tcx>) -> String { let mut result = String::with_capacity(32); result.push_str(prefix); - push_def_id_as_string(ccx, def_id, substs, &mut result); + push_instance_as_string(ccx, instance, &mut result); result } } @@ -1466,10 +1383,10 @@ impl<'tcx> TransItem<'tcx> { TransItem::DropGlue(t) => { format!("DropGlue({})", t as *const _ as usize) } - TransItem::Fn { def_id, substs } => { + TransItem::Fn(instance) => { format!("Fn({:?}, {})", - def_id, - substs as *const _ as usize) + instance.def, + instance.params as *const _ as usize) } TransItem::Static(id) => { format!("Static({:?})", id) |