Skip to content

Commit 405bb92

Browse files
Allow for internalizing monomorphizations that cannot be shared.
1 parent fb03fe4 commit 405bb92

File tree

7 files changed

+136
-28
lines changed

7 files changed

+136
-28
lines changed

src/librustc/dep_graph/dep_node.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,7 @@ define_dep_nodes!( <'tcx>
561561
[] ImplParent(DefId),
562562
[] TraitOfItem(DefId),
563563
[] IsReachableNonGeneric(DefId),
564+
[] IsUnreachableLocalDefinition(DefId),
564565
[] IsMirAvailable(DefId),
565566
[] ItemAttrs(DefId),
566567
[] TransFnAttrs(DefId),

src/librustc/ty/context.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use dep_graph::{DepNode, DepConstructor};
1515
use errors::DiagnosticBuilder;
1616
use session::Session;
1717
use session::config::{BorrowckMode, OutputFilenames, OptLevel};
18+
use session::config::CrateType::*;
1819
use middle;
1920
use hir::{TraitCandidate, HirId, ItemLocalId};
2021
use hir::def::{Def, Export};
@@ -1515,6 +1516,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
15151516
}
15161517
}
15171518
}
1519+
1520+
#[inline]
1521+
pub fn local_crate_exports_generics(self) -> bool {
1522+
self.sess.crate_types.borrow().iter().any(|crate_type| {
1523+
match crate_type {
1524+
CrateTypeExecutable |
1525+
CrateTypeStaticlib |
1526+
CrateTypeProcMacro |
1527+
CrateTypeCdylib => false,
1528+
CrateTypeRlib |
1529+
CrateTypeDylib => true,
1530+
}
1531+
})
1532+
}
15181533
}
15191534

15201535
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {

src/librustc/ty/maps/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ define_maps! { <'tcx>
318318
[] fn reachable_non_generics: ReachableNonGenerics(CrateNum)
319319
-> Lrc<DefIdMap<SymbolExportLevel>>,
320320
[] fn is_reachable_non_generic: IsReachableNonGeneric(DefId) -> bool,
321+
[] fn is_unreachable_local_definition: IsUnreachableLocalDefinition(DefId) -> bool,
321322

322323
[] fn upstream_monomorphizations: UpstreamMonomorphizations(CrateNum)
323324
-> Lrc<DefIdMap<Lrc<FxHashMap<&'tcx Substs<'tcx>, CrateNum>>>>,

src/librustc/ty/maps/plumbing.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,9 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
854854
DepKind::ImplParent => { force!(impl_parent, def_id!()); }
855855
DepKind::TraitOfItem => { force!(trait_of_item, def_id!()); }
856856
DepKind::IsReachableNonGeneric => { force!(is_reachable_non_generic, def_id!()); }
857+
DepKind::IsUnreachableLocalDefinition => {
858+
force!(is_unreachable_local_definition, def_id!());
859+
}
857860
DepKind::IsMirAvailable => { force!(is_mir_available, def_id!()); }
858861
DepKind::ItemAttrs => { force!(item_attrs, def_id!()); }
859862
DepKind::TransFnAttrs => { force!(trans_fn_attrs, def_id!()); }

src/librustc_mir/monomorphize/partitioning.rs

Lines changed: 64 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,8 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
301301
let mut codegen_units = FxHashMap();
302302
let is_incremental_build = tcx.sess.opts.incremental.is_some();
303303
let mut internalization_candidates = FxHashSet();
304-
let share_generics = tcx.share_generics();
304+
let export_generics = tcx.share_generics() &&
305+
tcx.local_crate_exports_generics();
305306

306307
for trans_item in trans_items {
307308
match trans_item.instantiation_mode(tcx) {
@@ -326,14 +327,27 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
326327
.or_insert_with(make_codegen_unit);
327328

328329
let mut can_be_internalized = true;
329-
let default_visibility = |id: DefId| {
330-
if tcx.sess.target.target.options.default_hidden_visibility &&
331-
tcx.reachable_non_generics(id.krate).get(&id).cloned() !=
332-
Some(SymbolExportLevel::C)
333-
{
334-
Visibility::Hidden
335-
} else {
330+
let default_visibility = |id: DefId, is_generic: bool| {
331+
if !tcx.sess.target.target.options.default_hidden_visibility {
332+
return Visibility::Default
333+
}
334+
335+
// Generic functions never have export level C
336+
if is_generic {
337+
return Visibility::Hidden
338+
}
339+
340+
// Things with export level C don't get instantiated in downstream
341+
// crates
342+
if !id.is_local() {
343+
return Visibility::Hidden
344+
}
345+
346+
if let Some(&SymbolExportLevel::C) = tcx.reachable_non_generics(id.krate)
347+
.get(&id) {
336348
Visibility::Default
349+
} else {
350+
Visibility::Hidden
337351
}
338352
};
339353
let (linkage, mut visibility) = match trans_item.explicit_linkage(tcx) {
@@ -343,6 +357,11 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
343357
MonoItem::Fn(ref instance) => {
344358
let visibility = match instance.def {
345359
InstanceDef::Item(def_id) => {
360+
let is_generic = instance.substs
361+
.types()
362+
.next()
363+
.is_some();
364+
346365
// The `start_fn` lang item is actually a
347366
// monomorphized instance of a function in the
348367
// standard library, used for the `main`
@@ -364,22 +383,46 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
364383
if tcx.lang_items().start_fn() == Some(def_id) {
365384
can_be_internalized = false;
366385
Visibility::Hidden
367-
} else if instance.substs.types().next().is_some() {
368-
if share_generics {
369-
can_be_internalized = false;
370-
Visibility::Default
386+
} else if def_id.is_local() {
387+
if is_generic {
388+
if export_generics {
389+
if tcx.is_unreachable_local_definition(def_id) {
390+
// This instance cannot be used
391+
// from another crate.
392+
Visibility::Hidden
393+
} else {
394+
// This instance might be useful in
395+
// a downstream crate.
396+
can_be_internalized = false;
397+
default_visibility(def_id, true)
398+
}
399+
} else {
400+
// We are not exporting generics or
401+
// the definition is not reachable
402+
// for downstream crates, we can
403+
// internalize its instantiations.
404+
Visibility::Hidden
405+
}
371406
} else {
372-
Visibility::Hidden
407+
// This isn't a generic function.
408+
if tcx.is_reachable_non_generic(def_id) {
409+
can_be_internalized = false;
410+
debug_assert!(!is_generic);
411+
default_visibility(def_id, false)
412+
} else {
413+
Visibility::Hidden
414+
}
373415
}
374-
} else if def_id.is_local() {
375-
if tcx.is_reachable_non_generic(def_id) {
376-
can_be_internalized = false;
377-
default_visibility(def_id)
416+
} else {
417+
// This is an upstream DefId.
418+
if export_generics && is_generic {
419+
// If it is a upstream monomorphization
420+
// and we export generics, we must make
421+
// it available to downstream crates.
422+
default_visibility(def_id, true)
378423
} else {
379424
Visibility::Hidden
380425
}
381-
} else {
382-
Visibility::Hidden
383426
}
384427
}
385428
InstanceDef::FnPtrShim(..) |
@@ -396,7 +439,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
396439
MonoItem::Static(def_id) => {
397440
let visibility = if tcx.is_reachable_non_generic(def_id) {
398441
can_be_internalized = false;
399-
default_visibility(def_id)
442+
default_visibility(def_id, false)
400443
} else {
401444
Visibility::Hidden
402445
};
@@ -406,7 +449,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
406449
let def_id = tcx.hir.local_def_id(node_id);
407450
let visibility = if tcx.is_reachable_non_generic(def_id) {
408451
can_be_internalized = false;
409-
default_visibility(def_id)
452+
default_visibility(def_id, false)
410453
} else {
411454
Visibility::Hidden
412455
};

src/librustc_trans/back/symbol_export.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,22 +241,20 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
241241
symbols.push((exported_symbol, SymbolExportLevel::Rust));
242242
}
243243

244-
if tcx.share_generics() {
244+
if tcx.share_generics() && tcx.local_crate_exports_generics() {
245245
use rustc::mir::mono::{Linkage, Visibility, MonoItem};
246246
use rustc::ty::InstanceDef;
247247

248248
let (_, cgus) = tcx.collect_and_partition_translation_items(LOCAL_CRATE);
249249

250250
for (mono_item, &(linkage, visibility)) in cgus.iter()
251251
.flat_map(|cgu| cgu.items().iter()) {
252-
if linkage == Linkage::External {
252+
if linkage == Linkage::External && visibility == Visibility::Default {
253253
if let &MonoItem::Fn(Instance {
254254
def: InstanceDef::Item(def_id),
255255
substs,
256256
}) = mono_item {
257257
if substs.types().next().is_some() {
258-
assert!(tcx.lang_items().start_fn() == Some(def_id) ||
259-
visibility == Visibility::Default);
260258
symbols.push((ExportedSymbol::Generic(def_id, substs),
261259
SymbolExportLevel::Rust));
262260
}
@@ -310,11 +308,21 @@ fn upstream_monomorphizations_for_provider<'a, 'tcx>(
310308
.cloned()
311309
}
312310

311+
fn is_unreachable_local_definition_provider(tcx: TyCtxt, def_id: DefId) -> bool {
312+
if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
313+
!tcx.reachable_set(LOCAL_CRATE).0.contains(&node_id)
314+
} else {
315+
bug!("is_unreachable_local_definition called with non-local DefId: {:?}",
316+
def_id)
317+
}
318+
}
319+
313320
pub fn provide(providers: &mut Providers) {
314321
providers.reachable_non_generics = reachable_non_generics_provider;
315322
providers.is_reachable_non_generic = is_reachable_non_generic_provider_local;
316323
providers.exported_symbols = exported_symbols_provider_local;
317324
providers.upstream_monomorphizations = upstream_monomorphizations_provider;
325+
providers.is_unreachable_local_definition = is_unreachable_local_definition_provider;
318326
}
319327

320328
pub fn provide_extern(providers: &mut Providers) {

src/librustc_trans/callee.rs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,16 +148,53 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
148148
unsafe {
149149
llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
150150

151-
if cx.tcx.share_generics() && instance.substs.types().next().is_some() {
152-
// If this is a generic function and we are sharing generics
153-
// it will always have Visibility::Default
151+
let is_generic = instance.substs.types().next().is_some();
152+
153+
if is_generic {
154+
if cx.tcx.share_generics() {
155+
// We are in share_generics mode.
156+
157+
if instance_def_id.is_local() {
158+
// This is a definition from the current crate. If the
159+
// definition is unreachable for downstream crates or
160+
// the current crate does not re-export generics, the
161+
// instance has been hidden
162+
if cx.tcx.is_unreachable_local_definition(instance_def_id) ||
163+
!cx.tcx.local_crate_exports_generics() {
164+
llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
165+
}
166+
} else {
167+
if cx.tcx.upstream_monomorphizations_for(instance_def_id)
168+
.map(|set| set.contains_key(instance.substs))
169+
.unwrap_or(false) {
170+
// This is instantiated in another crate. It cannot be hidden
171+
} else {
172+
// This is a local instantiation of an upstream definition.
173+
// If the current crate does not re-export it, it is hidden.
174+
if !cx.tcx.local_crate_exports_generics() {
175+
llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
176+
}
177+
}
178+
}
179+
} else {
180+
// When not sharing generics, all instances are in the same
181+
// crate and have hidden visibility
182+
llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
183+
}
154184
} else {
185+
// This is a non-generic function
155186
if cx.tcx.is_translated_item(instance_def_id) {
187+
// This is a function that is instantiated in the local crate
188+
156189
if instance_def_id.is_local() {
190+
// This is function that is defined in the local crate.
191+
// If it is not reachable, it is hidden.
157192
if !cx.tcx.is_reachable_non_generic(instance_def_id) {
158193
llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
159194
}
160195
} else {
196+
// This is a function from an upstream crate that has
197+
// been instantiated here. These are always hidden.
161198
llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
162199
}
163200
}

0 commit comments

Comments
 (0)