Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 5 additions & 1 deletion src/librustc_trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1591,7 +1591,11 @@ pub fn filter_reachable_ids(tcx: TyCtxt, reachable: NodeSet) -> NodeSet {
node: hir::ImplItemKind::Method(..), .. }) => {
let def_id = tcx.map.local_def_id(id);
let generics = tcx.lookup_generics(def_id);
generics.parent_types == 0 && generics.types.is_empty()
let attributes = tcx.get_attrs(def_id);
(generics.parent_types == 0 && generics.types.is_empty()) &&
// Functions marked with #[inline] are only ever translated
// with "internal" linkage and are never exported.
!attr::requests_inline(&attributes[..])
}

_ => false
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,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.is_from_extern_crate() || trans_item.requests_inline(tcx)
trans_item.needs_local_copy(tcx)
};

let inlining_candidates = callees.into_iter()
Expand Down
71 changes: 1 addition & 70 deletions src/librustc_trans/partitioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,12 +261,6 @@ pub fn partition<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
{
let tcx = scx.tcx();

if let PartitioningStrategy::FixedUnitCount(1) = strategy {
// If there is only a single codegen-unit, we can use a very simple
// scheme and don't have to bother with doing much analysis.
return vec![single_codegen_unit(tcx, trans_items, reachable)];
}

// In the first step, we place all regular translation items into their
// respective 'home' codegen unit. Regular translation items are all
// functions and statics defined in the local crate.
Expand Down Expand Up @@ -320,7 +314,7 @@ fn place_root_translation_items<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
let mut codegen_units = FnvHashMap();

for trans_item in trans_items {
let is_root = !trans_item.is_instantiated_only_on_demand();
let is_root = !trans_item.is_instantiated_only_on_demand(tcx);

if is_root {
let characteristic_def_id = characteristic_def_id_of_trans_item(scx, trans_item);
Expand Down Expand Up @@ -454,7 +448,6 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit
// reliably in that case.
new_codegen_unit.items.insert(trans_item, llvm::InternalLinkage);
} else {
assert!(trans_item.is_instantiated_only_on_demand());
// We can't be sure if this will also be instantiated
// somewhere else, so we add an instance here with
// InternalLinkage so we don't get any conflicts.
Expand Down Expand Up @@ -550,68 +543,6 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
return token::intern_and_get_ident(&mod_path[..]);
}

fn single_codegen_unit<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
trans_items: I,
reachable: &NodeSet)
-> CodegenUnit<'tcx>
where I: Iterator<Item = TransItem<'tcx>>
{
let mut items = FnvHashMap();

for trans_item in trans_items {
let linkage = trans_item.explicit_linkage(tcx).unwrap_or_else(|| {
match trans_item {
TransItem::Static(node_id) => {
if reachable.contains(&node_id) {
llvm::ExternalLinkage
} else {
llvm::PrivateLinkage
}
}
TransItem::DropGlue(_) => {
llvm::InternalLinkage
}
TransItem::Fn(instance) => {
if trans_item.is_generic_fn() {
// FIXME(mw): Assigning internal linkage to all
// monomorphizations is potentially a waste of space
// since monomorphizations could be shared between
// crates. The main reason for making them internal is
// a limitation in MingW's binutils that cannot deal
// with COFF object that have more than 2^15 sections,
// which is something that can happen for large programs
// when every function gets put into its own COMDAT
// section.
llvm::InternalLinkage
} else if trans_item.is_from_extern_crate() {
// FIXME(mw): It would be nice if we could mark these as
// `AvailableExternallyLinkage`, since they should have
// been instantiated in the extern crate. But this
// sometimes leads to crashes on Windows because LLVM
// does not handle exception handling table instantiation
// reliably in that case.
llvm::InternalLinkage
} else if reachable.contains(&tcx.map
.as_local_node_id(instance.def)
.unwrap()) {
llvm::ExternalLinkage
} else {
// Functions that are not visible outside this crate can
// be marked as internal.
llvm::InternalLinkage
}
}
}
});

items.insert(trans_item, linkage);
}

CodegenUnit::new(
numbered_codegen_unit_name(&tcx.crate_name[..], 0),
items)
}

fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
token::intern_and_get_ident(&format!("{}{}{}",
crate_name,
Expand Down
33 changes: 18 additions & 15 deletions src/librustc_trans/trans_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,19 +241,6 @@ impl<'a, 'tcx> TransItem<'tcx> {
}
}

pub fn requests_inline(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
match *self {
TransItem::Fn(ref instance) => {
instance.substs.types().next().is_some() || {
let attributes = tcx.get_attrs(instance.def);
attr::requests_inline(&attributes[..])
}
}
TransItem::DropGlue(..) => true,
TransItem::Static(..) => false,
}
}

pub fn is_from_extern_crate(&self) -> bool {
match *self {
TransItem::Fn(ref instance) => !instance.def.is_local(),
Expand All @@ -262,10 +249,14 @@ impl<'a, 'tcx> TransItem<'tcx> {
}
}

pub fn is_instantiated_only_on_demand(&self) -> bool {
/// True if the translation item should only be translated to LLVM IR if
/// it is referenced somewhere (like inline functions, for example).
pub fn is_instantiated_only_on_demand(&self, tcx: TyCtxt) -> bool {
match *self {
TransItem::Fn(ref instance) => {
!instance.def.is_local() || instance.substs.types().next().is_some()
!instance.def.is_local() ||
instance.substs.types().next().is_some() ||
attr::requests_inline(&tcx.get_attrs(instance.def)[..])
}
TransItem::DropGlue(..) => true,
TransItem::Static(..) => false,
Expand All @@ -282,6 +273,18 @@ impl<'a, 'tcx> TransItem<'tcx> {
}
}

/// Returns true if there has to be a local copy of this TransItem in every
/// codegen unit that references it (as with inlined functions, for example)
pub fn needs_local_copy(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
// Currently everything that is instantiated only on demand is done so
// with "internal" linkage, so we need a copy to be present in every
// codegen unit.
// This is coincidental: We could also instantiate something only if it
// is referenced (e.g. a regular, private function) but place it in its
// own codegen unit with "external" linkage.
self.is_instantiated_only_on_demand(tcx)
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: it might be nice to put a few notes here as to why things need_local_copy

}

pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Linkage> {
let def_id = match *self {
TransItem::Fn(ref instance) => instance.def,
Expand Down