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

Improve dependency_format a bit #134514

Merged
merged 4 commits into from
Dec 20, 2024
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
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/driver/jit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ fn dep_symbol_lookup_fn(
// search path.
for &cnum in crate_info.used_crates.iter().rev() {
let src = &crate_info.used_crate_source[&cnum];
match data[cnum.as_usize() - 1] {
match data[cnum] {
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
Linkage::Static => {
let name = crate_info.crate_name[&cnum];
Expand Down
15 changes: 7 additions & 8 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,6 @@ pub fn each_linked_rlib(
crate_type: Option<CrateType>,
f: &mut dyn FnMut(CrateNum, &Path),
) -> Result<(), errors::LinkRlibError> {
let crates = info.used_crates.iter();

let fmts = if let Some(crate_type) = crate_type {
let Some(fmts) = info.dependency_formats.get(&crate_type) else {
return Err(errors::LinkRlibError::MissingFormat);
Expand All @@ -261,8 +259,9 @@ pub fn each_linked_rlib(
info.dependency_formats.first().unwrap().1
};

for &cnum in crates {
match fmts.get(cnum.as_usize() - 1) {
let used_dep_crates = info.used_crates.iter();
for &cnum in used_dep_crates {
match fmts.get(cnum) {
jieyouxu marked this conversation as resolved.
Show resolved Hide resolved
Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue,
Some(_) => {}
None => return Err(errors::LinkRlibError::MissingFormat),
Expand Down Expand Up @@ -624,7 +623,7 @@ fn link_staticlib(

let mut all_rust_dylibs = vec![];
for &cnum in crates {
match fmts.get(cnum.as_usize() - 1) {
match fmts.get(cnum) {
Some(&Linkage::Dynamic) => {}
_ => continue,
}
Expand Down Expand Up @@ -2361,8 +2360,8 @@ fn linker_with_args(
.crate_info
.native_libraries
.iter()
.filter_map(|(cnum, libraries)| {
(dependency_linkage[cnum.as_usize() - 1] != Linkage::Static).then_some(libraries)
.filter_map(|(&cnum, libraries)| {
(dependency_linkage[cnum] != Linkage::Static).then_some(libraries)
})
.flatten()
.collect::<Vec<_>>();
Expand Down Expand Up @@ -2754,7 +2753,7 @@ fn add_upstream_rust_crates(
// (e.g. `libstd` when `-C prefer-dynamic` is used).
// FIXME: `dependency_formats` can report `profiler_builtins` as `NotLinked` for some
// reason, it shouldn't do that because `profiler_builtins` should indeed be linked.
let linkage = data[cnum.as_usize() - 1];
let linkage = data[cnum];
let link_static_crate = linkage == Linkage::Static
|| (linkage == Linkage::IncludedFromDylib || linkage == Linkage::NotLinked)
&& (codegen_results.crate_info.compiler_builtins == Some(cnum)
Expand Down
7 changes: 1 addition & 6 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1744,15 +1744,10 @@ fn for_each_exported_symbols_include_dep<'tcx>(
crate_type: CrateType,
mut callback: impl FnMut(ExportedSymbol<'tcx>, SymbolExportInfo, CrateNum),
) {
for &(symbol, info) in tcx.exported_symbols(LOCAL_CRATE).iter() {
callback(symbol, info, LOCAL_CRATE);
}

let formats = tcx.dependency_formats(());
let deps = &formats[&crate_type];

for (index, dep_format) in deps.iter().enumerate() {
let cnum = CrateNum::new(index + 1);
for (cnum, dep_format) in deps.iter_enumerated() {
jieyouxu marked this conversation as resolved.
Show resolved Hide resolved
// For each dependency that we are linking to statically ...
if *dep_format == Linkage::Static {
for &(symbol, info) in tcx.exported_symbols(cnum).iter() {
Expand Down
15 changes: 7 additions & 8 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use rustc_incremental::setup_dep_graph;
use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore, unerased_lint_store};
use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena;
use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt};
use rustc_middle::ty::{self, CurrentGcx, GlobalCtxt, RegisteredTools, TyCtxt};
use rustc_middle::util::Providers;
use rustc_parse::{
new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal, validate_attr,
Expand Down Expand Up @@ -770,15 +770,14 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
// subtyping for GlobalCtxt::enter to be allowed.
let inner: Box<
dyn for<'tcx> FnOnce(
&'tcx Compiler,
&'tcx Session,
CurrentGcx,
&'tcx OnceLock<GlobalCtxt<'tcx>>,
&'tcx WorkerLocal<Arena<'tcx>>,
&'tcx WorkerLocal<rustc_hir::Arena<'tcx>>,
F,
) -> T,
> = Box::new(move |compiler, gcx_cell, arena, hir_arena, f| {
let sess = &compiler.sess;

> = Box::new(move |sess, current_gcx, gcx_cell, arena, hir_arena, f| {
TyCtxt::create_global_ctxt(
gcx_cell,
sess,
Expand All @@ -796,15 +795,15 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
incremental,
),
providers.hooks,
compiler.current_gcx.clone(),
current_gcx,
|tcx| {
let feed = tcx.create_crate_num(stable_crate_id).unwrap();
assert_eq!(feed.key(), LOCAL_CRATE);
feed.crate_name(crate_name);

let feed = tcx.feed_unit_query();
feed.features_query(tcx.arena.alloc(rustc_expand::config::features(
sess,
tcx.sess,
&pre_configured_attrs,
crate_name,
)));
Expand All @@ -819,7 +818,7 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
)
});

inner(compiler, &gcx_cell, &arena, &hir_arena, f)
inner(&compiler.sess, compiler.current_gcx.clone(), &gcx_cell, &arena, &hir_arena, f)
}

/// Runs all analyses that we guarantee to run, even if errors were reported in earlier analyses.
Expand Down
111 changes: 64 additions & 47 deletions compiler/rustc_metadata/src/dependency_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@
//! than finding a number of solutions (there are normally quite a few).

use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::CrateNum;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_index::IndexVec;
use rustc_middle::bug;
use rustc_middle::middle::dependency_format::{Dependencies, DependencyList, Linkage};
use rustc_middle::ty::TyCtxt;
Expand Down Expand Up @@ -84,7 +85,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
let sess = &tcx.sess;

if !sess.opts.output_types.should_codegen() {
return Vec::new();
return IndexVec::new();
}

let preferred_linkage = match ty {
Expand Down Expand Up @@ -131,7 +132,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {

match preferred_linkage {
// If the crate is not linked, there are no link-time dependencies.
Linkage::NotLinked => return Vec::new(),
Linkage::NotLinked => return IndexVec::new(),
Linkage::Static => {
// Attempt static linkage first. For dylibs and executables, we may be
// able to retry below with dynamic linkage.
Expand All @@ -156,7 +157,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
}
sess.dcx().emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) });
}
return Vec::new();
return IndexVec::new();
}
}
Linkage::Dynamic | Linkage::IncludedFromDylib => {}
Expand Down Expand Up @@ -210,19 +211,32 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {

// Collect what we've got so far in the return vector.
let last_crate = tcx.crates(()).len();
let mut ret = (1..last_crate + 1)
.map(|cnum| match formats.get(&CrateNum::new(cnum)) {
Some(&RequireDynamic) => Linkage::Dynamic,
Some(&RequireStatic) => Linkage::IncludedFromDylib,
None => Linkage::NotLinked,
})
.collect::<Vec<_>>();
let mut ret = IndexVec::new();

// We need to fill in something for LOCAL_CRATE as IndexVec is a dense map.
// Linkage::Static semantically the most correct thing to use as the local
// crate is always statically linked into the linker output, even when
// linking a dylib. Using Linkage::Static also allow avoiding special cases
// for LOCAL_CRATE in some places.
assert_eq!(ret.push(Linkage::Static), LOCAL_CRATE);
jieyouxu marked this conversation as resolved.
Show resolved Hide resolved

for cnum in 1..last_crate + 1 {
let cnum = CrateNum::new(cnum);
assert_eq!(
ret.push(match formats.get(&cnum) {
Some(&RequireDynamic) => Linkage::Dynamic,
Some(&RequireStatic) => Linkage::IncludedFromDylib,
None => Linkage::NotLinked,
}),
cnum
);
}

// Run through the dependency list again, and add any missing libraries as
// static libraries.
//
// If the crate hasn't been included yet and it's not actually required
// (e.g., it's an allocator) then we skip it here as well.
// (e.g., it's a panic runtime) then we skip it here as well.
for &cnum in tcx.crates(()).iter() {
let src = tcx.used_crate_source(cnum);
if src.dylib.is_none()
Expand All @@ -232,16 +246,15 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
assert!(src.rlib.is_some() || src.rmeta.is_some());
info!("adding staticlib: {}", tcx.crate_name(cnum));
add_library(tcx, cnum, RequireStatic, &mut formats, &mut unavailable_as_static);
ret[cnum.as_usize() - 1] = Linkage::Static;
ret[cnum] = Linkage::Static;
}
}

// We've gotten this far because we're emitting some form of a final
// artifact which means that we may need to inject dependencies of some
// form.
//
// Things like allocators and panic runtimes may not have been activated
// quite yet, so do so here.
// Things like panic runtimes may not have been activated quite yet, so do so here.
activate_injected_dep(CStore::from_tcx(tcx).injected_panic_runtime(), &mut ret, &|cnum| {
tcx.is_panic_runtime(cnum)
});
Expand All @@ -252,8 +265,10 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
//
// For situations like this, we perform one last pass over the dependencies,
// making sure that everything is available in the requested format.
for (cnum, kind) in ret.iter().enumerate() {
let cnum = CrateNum::new(cnum + 1);
for (cnum, kind) in ret.iter_enumerated() {
if cnum == LOCAL_CRATE {
continue;
}
let src = tcx.used_crate_source(cnum);
match *kind {
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
Expand Down Expand Up @@ -334,18 +349,21 @@ fn attempt_static(tcx: TyCtxt<'_>, unavailable: &mut Vec<CrateNum>) -> Option<De

// All crates are available in an rlib format, so we're just going to link
// everything in explicitly so long as it's actually required.
let mut ret = tcx
.crates(())
.iter()
.map(|&cnum| match tcx.dep_kind(cnum) {
CrateDepKind::Explicit => Linkage::Static,
CrateDepKind::MacrosOnly | CrateDepKind::Implicit => Linkage::NotLinked,
})
.collect::<Vec<_>>();
let mut ret = IndexVec::new();
assert_eq!(ret.push(Linkage::Static), LOCAL_CRATE);
for &cnum in tcx.crates(()) {
assert_eq!(
ret.push(match tcx.dep_kind(cnum) {
CrateDepKind::Explicit => Linkage::Static,
CrateDepKind::MacrosOnly | CrateDepKind::Implicit => Linkage::NotLinked,
}),
cnum
);
}

// Our allocator/panic runtime may not have been linked above if it wasn't
// explicitly linked, which is the case for any injected dependency. Handle
// that here and activate them.
// Our panic runtime may not have been linked above if it wasn't explicitly
// linked, which is the case for any injected dependency. Handle that here
// and activate it.
activate_injected_dep(CStore::from_tcx(tcx).injected_panic_runtime(), &mut ret, &|cnum| {
tcx.is_panic_runtime(cnum)
});
Expand All @@ -367,8 +385,7 @@ fn activate_injected_dep(
list: &mut DependencyList,
replaces_injected: &dyn Fn(CrateNum) -> bool,
) {
for (i, slot) in list.iter().enumerate() {
let cnum = CrateNum::new(i + 1);
for (cnum, slot) in list.iter_enumerated() {
if !replaces_injected(cnum) {
continue;
}
Expand All @@ -377,25 +394,23 @@ fn activate_injected_dep(
}
}
if let Some(injected) = injected {
let idx = injected.as_usize() - 1;
assert_eq!(list[idx], Linkage::NotLinked);
list[idx] = Linkage::Static;
assert_eq!(list[injected], Linkage::NotLinked);
list[injected] = Linkage::Static;
}
}

// After the linkage for a crate has been determined we need to verify that
// there's only going to be one allocator in the output.
fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
/// After the linkage for a crate has been determined we need to verify that
/// there's only going to be one panic runtime in the output.
fn verify_ok(tcx: TyCtxt<'_>, list: &DependencyList) {
let sess = &tcx.sess;
if list.is_empty() {
return;
}
let mut panic_runtime = None;
for (i, linkage) in list.iter().enumerate() {
for (cnum, linkage) in list.iter_enumerated() {
if let Linkage::NotLinked = *linkage {
continue;
}
let cnum = CrateNum::new(i + 1);

if tcx.is_panic_runtime(cnum) {
if let Some((prev, _)) = panic_runtime {
Expand Down Expand Up @@ -431,11 +446,10 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
// strategy. If the dep isn't linked, we ignore it, and if our strategy
// is abort then it's compatible with everything. Otherwise all crates'
// panic strategy must match our own.
for (i, linkage) in list.iter().enumerate() {
for (cnum, linkage) in list.iter_enumerated() {
if let Linkage::NotLinked = *linkage {
continue;
}
let cnum = CrateNum::new(i + 1);
if cnum == runtime_cnum || tcx.is_compiler_builtins(cnum) {
continue;
}
Expand All @@ -450,13 +464,16 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
});
}

let found_drop_strategy = tcx.panic_in_drop_strategy(cnum);
if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy {
sess.dcx().emit_err(IncompatiblePanicInDropStrategy {
crate_name: tcx.crate_name(cnum),
found_strategy: found_drop_strategy,
desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
});
// panic_in_drop_strategy isn't allowed for LOCAL_CRATE
if cnum != LOCAL_CRATE {
let found_drop_strategy = tcx.panic_in_drop_strategy(cnum);
if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy {
sess.dcx().emit_err(IncompatiblePanicInDropStrategy {
crate_name: tcx.crate_name(cnum),
found_strategy: found_drop_strategy,
desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
});
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1474,7 +1474,7 @@ impl<'a> CrateMetadataRef<'a> {
) -> &'tcx [(CrateNum, LinkagePreference)] {
tcx.arena.alloc_from_iter(
self.root.dylib_dependency_formats.decode(self).enumerate().flat_map(|(i, link)| {
let cnum = CrateNum::new(i + 1);
let cnum = CrateNum::new(i + 1); // We skipped LOCAL_CRATE when encoding
link.map(|link| (self.cnum_map[cnum], link))
}),
)
Expand Down
12 changes: 7 additions & 5 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2165,12 +2165,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
empty_proc_macro!(self);
let formats = self.tcx.dependency_formats(());
if let Some(arr) = formats.get(&CrateType::Dylib) {
return self.lazy_array(arr.iter().map(|slot| match *slot {
Linkage::NotLinked | Linkage::IncludedFromDylib => None,
return self.lazy_array(arr.iter().skip(1 /* skip LOCAL_CRATE */).map(
|slot| match *slot {
Linkage::NotLinked | Linkage::IncludedFromDylib => None,

Linkage::Dynamic => Some(LinkagePreference::RequireDynamic),
Linkage::Static => Some(LinkagePreference::RequireStatic),
}));
Linkage::Dynamic => Some(LinkagePreference::RequireDynamic),
Linkage::Static => Some(LinkagePreference::RequireStatic),
},
));
}
LazyArray::default()
}
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_middle/src/middle/dependency_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
// this will introduce circular dependency between rustc_metadata and rustc_middle

use rustc_data_structures::fx::FxIndexMap;
use rustc_hir::def_id::CrateNum;
use rustc_index::IndexVec;
use rustc_macros::{Decodable, Encodable, HashStable};
use rustc_session::config::CrateType;

/// A list of dependencies for a certain crate type.
///
/// The length of this vector is the same as the number of external crates used.
pub type DependencyList = Vec<Linkage>;
pub type DependencyList = IndexVec<CrateNum, Linkage>;

/// A mapping of all required dependencies for a particular flavor of output.
///
Expand Down
Loading
Loading