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 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
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
10 changes: 5 additions & 5 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ pub fn each_linked_rlib(
};

for &cnum in crates {
jieyouxu marked this conversation as resolved.
Show resolved Hide resolved
match fmts.get(cnum.as_usize() - 1) {
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 +624,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 +2361,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 +2754,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
89 changes: 50 additions & 39 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,13 +211,19 @@ 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();
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.
Expand All @@ -232,7 +239,7 @@ 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;
}
}

Expand All @@ -252,8 +259,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,14 +343,17 @@ 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
Expand All @@ -367,8 +379,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 +388,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]) {
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 +440,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 +458,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
14 changes: 8 additions & 6 deletions src/tools/miri/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,14 @@ pub fn iter_exported_symbols<'tcx>(
let dependency_format = dependency_formats
.get(&CrateType::Executable)
.expect("interpreting a non-executable crate");
for cnum in dependency_format.iter().enumerate().filter_map(|(num, &linkage)| {
// We add 1 to the number because that's what rustc also does everywhere it
// calls `CrateNum::new`...
#[expect(clippy::arithmetic_side_effects)]
(linkage != Linkage::NotLinked).then_some(CrateNum::new(num + 1))
}) {
for cnum in dependency_format
.iter_enumerated()
.filter_map(|(num, &linkage)| (linkage != Linkage::NotLinked).then_some(num))
{
if cnum == LOCAL_CRATE {
continue; // Already handled above
}

// We can ignore `_export_info` here: we are a Rust crate, and everything is exported
// from a Rust crate.
for &(symbol, _export_info) in tcx.exported_symbols(cnum) {
Expand Down