Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

trans: Treat generics like regular functions, not like #[inline] function, during CGU partitioning #38944

Merged
merged 5 commits into from
Jan 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ pub trait CrateStore<'tcx> {
fn is_foreign_item(&self, did: DefId) -> bool;
fn is_dllimport_foreign_item(&self, def: DefId) -> bool;
fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool;
fn is_exported_symbol(&self, def_id: DefId) -> bool;

// crate metadata
fn dylib_dependency_formats(&self, cnum: CrateNum)
Expand Down Expand Up @@ -258,11 +259,6 @@ pub trait CrateStore<'tcx> {
fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Mir<'tcx>;
fn is_item_mir_available(&self, def: DefId) -> bool;

/// Take a look if we need to inline or monomorphize this. If so, we
/// will emit code for this item in the local crate, and thus
/// create a translation item for it.
fn can_have_local_instance<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> bool;

// This is basically a 1-based range of ints, which is a little
// silly - I may fix that.
fn crates(&self) -> Vec<CrateNum>;
Expand Down Expand Up @@ -368,6 +364,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
fn is_foreign_item(&self, did: DefId) -> bool { bug!("is_foreign_item") }
fn is_dllimport_foreign_item(&self, id: DefId) -> bool { false }
fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool { false }
fn is_exported_symbol(&self, def_id: DefId) -> bool { false }

// crate metadata
fn dylib_dependency_formats(&self, cnum: CrateNum)
Expand Down Expand Up @@ -436,9 +433,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
fn is_item_mir_available(&self, def: DefId) -> bool {
bug!("is_item_mir_available")
}
fn can_have_local_instance<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> bool {
bug!("can_have_local_instance")
}

// This is basically a 1-based range of ints, which is a little
// silly - I may fix that.
Expand Down
3 changes: 3 additions & 0 deletions src/librustc_metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,10 +302,13 @@ impl<'a> CrateLoader<'a> {
crate_root.def_path_table.decode(&metadata)
});

let exported_symbols = crate_root.exported_symbols.decode(&metadata).collect();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, I thought I had removed this... At least it's by DefIndex not by symbol name.


let mut cmeta = cstore::CrateMetadata {
name: name,
extern_crate: Cell::new(None),
def_path_table: def_path_table,
exported_symbols: exported_symbols,
proc_macros: crate_root.macro_derive_registrar.map(|_| {
self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
}),
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_metadata/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ pub struct CrateMetadata {
/// compilation support.
pub def_path_table: DefPathTable,

pub exported_symbols: FxHashSet<DefIndex>,

pub dep_kind: Cell<DepKind>,
pub source: CrateSource,

Expand Down
9 changes: 4 additions & 5 deletions src/librustc_metadata/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
self.do_is_statically_included_foreign_item(def_id)
}

fn is_exported_symbol(&self, def_id: DefId) -> bool {
self.get_crate_data(def_id.krate).exported_symbols.contains(&def_id.index)
}

fn is_dllimport_foreign_item(&self, def_id: DefId) -> bool {
if def_id.krate == LOCAL_CRATE {
self.dllimport_foreign_items.borrow().contains(&def_id.index)
Expand Down Expand Up @@ -466,11 +470,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
self.get_crate_data(def.krate).is_item_mir_available(def.index)
}

fn can_have_local_instance<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> bool {
self.dep_graph.read(DepNode::MetaData(def));
def.is_local() || self.get_crate_data(def.krate).can_have_local_instance(tcx, def.index)
}

fn crates(&self) -> Vec<CrateNum>
{
let mut result = vec![];
Expand Down
40 changes: 7 additions & 33 deletions src/librustc_metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,14 +445,6 @@ impl<'tcx> EntryKind<'tcx> {
EntryKind::Closure(_) => return None,
})
}
fn is_const_fn(&self, meta: &CrateMetadata) -> bool {
let constness = match *self {
EntryKind::Method(data) => data.decode(meta).fn_data.constness,
EntryKind::Fn(data) => data.decode(meta).constness,
_ => hir::Constness::NotConst,
};
constness == hir::Constness::Const
}
}

impl<'a, 'tcx> CrateMetadata {
Expand Down Expand Up @@ -804,29 +796,6 @@ impl<'a, 'tcx> CrateMetadata {
self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some()
}

pub fn can_have_local_instance(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
id: DefIndex) -> bool {
self.maybe_entry(id).map_or(false, |item| {
let item = item.decode(self);
// if we don't have a MIR, then this item was never meant to be locally instantiated
// or we have a bug in the metadata serialization
item.mir.is_some() && (
// items with generics always can have local instances if monomorphized
item.generics.map_or(false, |generics| {
let generics = generics.decode((self, tcx));
generics.parent_types != 0 || !generics.types.is_empty()
}) ||
match item.kind {
EntryKind::Closure(_) => true,
_ => false,
} ||
item.kind.is_const_fn(self) ||
attr::requests_inline(&self.get_attributes(&item))
)
})
}

pub fn maybe_get_item_mir(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
id: DefIndex)
Expand Down Expand Up @@ -1031,7 +1000,7 @@ impl<'a, 'tcx> CrateMetadata {
}

pub fn get_exported_symbols(&self) -> Vec<DefId> {
self.root.exported_symbols.decode(self).map(|index| self.local_def_id(index)).collect()
self.exported_symbols.iter().map(|&index| self.local_def_id(index)).collect()
}

pub fn get_macro(&self, id: DefIndex) -> (ast::Name, MacroDef) {
Expand All @@ -1043,7 +1012,12 @@ impl<'a, 'tcx> CrateMetadata {
}

pub fn is_const_fn(&self, id: DefIndex) -> bool {
self.entry(id).kind.is_const_fn(self)
let constness = match self.entry(id).kind {
EntryKind::Method(data) => data.decode(self).fn_data.constness,
EntryKind::Fn(data) => data.decode(self).constness,
_ => hir::Constness::NotConst,
};
constness == hir::Constness::Const
}

pub fn is_foreign_item(&self, id: DefIndex) -> bool {
Expand Down
9 changes: 9 additions & 0 deletions src/librustc_trans/back/symbol_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,15 @@ fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
assert!(!substs.has_erasable_regions());
assert!(!substs.needs_subst());
substs.visit_with(&mut hasher);

// If this is an instance of a generic function, we also hash in
// the ID of the instantiating crate. This avoids symbol conflicts
// in case the same instances is emitted in two crates of the same
// project.
if substs.types().next().is_some() {
hasher.hash(scx.tcx().crate_name.as_str());
hasher.hash(scx.sess().local_crate_disambiguator().as_str());
}
}
});

Expand Down
80 changes: 53 additions & 27 deletions src/librustc_trans/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ use glue::{self, DropGlueKind};
use monomorphize::{self, Instance};
use util::nodemap::{FxHashSet, FxHashMap, DefIdMap};

use trans_item::{TransItem, DefPathBasedNames};
use trans_item::{TransItem, DefPathBasedNames, InstantiationMode};

use std::iter;

Expand Down Expand Up @@ -337,6 +337,10 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
}
TransItem::Static(node_id) => {
let def_id = scx.tcx().map.local_def_id(node_id);

// Sanity check whether this ended up being collected accidentally
debug_assert!(should_trans_locally(scx.tcx(), def_id));

let ty = scx.tcx().item_type(def_id);
let ty = glue::get_drop_glue_type(scx, ty);
neighbors.push(TransItem::DropGlue(DropGlueKind::Ty(ty)));
Expand All @@ -346,6 +350,9 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
collect_neighbours(scx, Instance::mono(scx, def_id), &mut neighbors);
}
TransItem::Fn(instance) => {
// Sanity check whether this ended up being collected accidentally
debug_assert!(should_trans_locally(scx.tcx(), instance.def));

// Keep track of the monomorphization recursion depth
recursion_depth_reset = Some(check_recursion_limit(scx.tcx(),
instance,
Expand Down Expand Up @@ -374,7 +381,7 @@ fn record_inlining_canditates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
callees: &[TransItem<'tcx>],
inlining_map: &mut InliningMap<'tcx>) {
let is_inlining_candidate = |trans_item: &TransItem<'tcx>| {
trans_item.needs_local_copy(tcx)
trans_item.instantiation_mode(tcx) == InstantiationMode::LocalCopy
};

let inlining_candidates = callees.into_iter()
Expand Down Expand Up @@ -490,15 +497,16 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
.require(ExchangeMallocFnLangItem)
.unwrap_or_else(|e| self.scx.sess().fatal(&e));

assert!(can_have_local_instance(self.scx.tcx(), exchange_malloc_fn_def_id));
let empty_substs = self.scx.empty_substs_for_def_id(exchange_malloc_fn_def_id);
let exchange_malloc_fn_trans_item =
create_fn_trans_item(self.scx,
exchange_malloc_fn_def_id,
empty_substs,
self.param_substs);
if should_trans_locally(self.scx.tcx(), exchange_malloc_fn_def_id) {
let empty_substs = self.scx.empty_substs_for_def_id(exchange_malloc_fn_def_id);
let exchange_malloc_fn_trans_item =
create_fn_trans_item(self.scx,
exchange_malloc_fn_def_id,
empty_substs,
self.param_substs);

self.output.push(exchange_malloc_fn_trans_item);
self.output.push(exchange_malloc_fn_trans_item);
}
}
_ => { /* not interesting */ }
}
Expand Down Expand Up @@ -609,7 +617,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
match tcx.item_type(def_id).sty {
ty::TyFnDef(def_id, _, f) => {
// Some constructors also have type TyFnDef but they are
// always instantiated inline and don't result in
// always instantiated inline and don't result in a
// translation item. Same for FFI functions.
if let Some(hir_map::NodeForeignItem(_)) = tcx.map.get_if_local(def_id) {
return false;
Expand All @@ -625,7 +633,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
_ => return false
}

can_have_local_instance(tcx, def_id)
should_trans_locally(tcx, def_id)
}
}

Expand Down Expand Up @@ -675,10 +683,27 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
}
}

fn can_have_local_instance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> bool {
tcx.sess.cstore.can_have_local_instance(tcx, def_id)
// Returns true if we should translate an instance in the local crate.
// Returns false if we can just link to the upstream crate and therefore don't
// need a translation item.
fn should_trans_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> bool {
if def_id.is_local() {
true
} else {
if tcx.sess.cstore.is_exported_symbol(def_id) ||
tcx.sess.cstore.is_foreign_item(def_id) {
// We can link to the item in question, no instance needed in this
// crate
false
} else {
if !tcx.sess.cstore.is_item_mir_available(def_id) {
bug!("Cannot create local trans-item for {:?}", def_id)
}
true
}
}
}

fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
Expand All @@ -698,14 +723,15 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
// Make sure the BoxFreeFn lang-item gets translated if there is a boxed value.
if let ty::TyBox(content_type) = ty.sty {
let def_id = scx.tcx().require_lang_item(BoxFreeFnLangItem);
assert!(can_have_local_instance(scx.tcx(), def_id));
let box_free_fn_trans_item =
create_fn_trans_item(scx,
def_id,
scx.tcx().mk_substs(iter::once(Kind::from(content_type))),
scx.tcx().intern_substs(&[]));

output.push(box_free_fn_trans_item);

if should_trans_locally(scx.tcx(), def_id) {
let box_free_fn_trans_item =
create_fn_trans_item(scx,
def_id,
scx.tcx().mk_substs(iter::once(Kind::from(content_type))),
scx.tcx().intern_substs(&[]));
output.push(box_free_fn_trans_item);
}
}

// If the type implements Drop, also add a translation item for the
Expand Down Expand Up @@ -735,7 +761,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
_ => bug!()
};

if can_have_local_instance(scx.tcx(), destructor_did) {
if should_trans_locally(scx.tcx(), destructor_did) {
let trans_item = create_fn_trans_item(scx,
destructor_did,
substs,
Expand Down Expand Up @@ -1080,7 +1106,7 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a,
None
}
})
.filter(|&(def_id, _)| can_have_local_instance(scx.tcx(), def_id))
.filter(|&(def_id, _)| should_trans_locally(scx.tcx(), def_id))
.map(|(def_id, substs)| create_fn_trans_item(scx, def_id, substs, param_substs));
output.extend(methods);
}
Expand Down Expand Up @@ -1255,7 +1281,7 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, '
continue;
}

if can_have_local_instance(tcx, method.def_id) {
if should_trans_locally(tcx, method.def_id) {
let item = create_fn_trans_item(scx,
method.def_id,
callee_substs,
Expand Down
Loading