Make DependencyList an IndexVec
This commit is contained in:
parent
38bc902b15
commit
7e6be13647
8 changed files with 76 additions and 66 deletions
|
@ -294,7 +294,7 @@ fn dep_symbol_lookup_fn(
|
||||||
// search path.
|
// search path.
|
||||||
for &cnum in crate_info.used_crates.iter().rev() {
|
for &cnum in crate_info.used_crates.iter().rev() {
|
||||||
let src = &crate_info.used_crate_source[&cnum];
|
let src = &crate_info.used_crate_source[&cnum];
|
||||||
match data[cnum.as_usize() - 1] {
|
match data[cnum] {
|
||||||
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
|
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
|
||||||
Linkage::Static => {
|
Linkage::Static => {
|
||||||
let name = crate_info.crate_name[&cnum];
|
let name = crate_info.crate_name[&cnum];
|
||||||
|
|
|
@ -262,7 +262,7 @@ pub fn each_linked_rlib(
|
||||||
};
|
};
|
||||||
|
|
||||||
for &cnum in crates {
|
for &cnum in crates {
|
||||||
match fmts.get(cnum.as_usize() - 1) {
|
match fmts.get(cnum) {
|
||||||
Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue,
|
Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue,
|
||||||
Some(_) => {}
|
Some(_) => {}
|
||||||
None => return Err(errors::LinkRlibError::MissingFormat),
|
None => return Err(errors::LinkRlibError::MissingFormat),
|
||||||
|
@ -624,7 +624,7 @@ fn link_staticlib(
|
||||||
|
|
||||||
let mut all_rust_dylibs = vec![];
|
let mut all_rust_dylibs = vec![];
|
||||||
for &cnum in crates {
|
for &cnum in crates {
|
||||||
match fmts.get(cnum.as_usize() - 1) {
|
match fmts.get(cnum) {
|
||||||
Some(&Linkage::Dynamic) => {}
|
Some(&Linkage::Dynamic) => {}
|
||||||
_ => continue,
|
_ => continue,
|
||||||
}
|
}
|
||||||
|
@ -2361,8 +2361,8 @@ fn linker_with_args(
|
||||||
.crate_info
|
.crate_info
|
||||||
.native_libraries
|
.native_libraries
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(cnum, libraries)| {
|
.filter_map(|(&cnum, libraries)| {
|
||||||
(dependency_linkage[cnum.as_usize() - 1] != Linkage::Static).then_some(libraries)
|
(dependency_linkage[cnum] != Linkage::Static).then_some(libraries)
|
||||||
})
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -2754,7 +2754,7 @@ fn add_upstream_rust_crates(
|
||||||
// (e.g. `libstd` when `-C prefer-dynamic` is used).
|
// (e.g. `libstd` when `-C prefer-dynamic` is used).
|
||||||
// FIXME: `dependency_formats` can report `profiler_builtins` as `NotLinked` for some
|
// FIXME: `dependency_formats` can report `profiler_builtins` as `NotLinked` for some
|
||||||
// reason, it shouldn't do that because `profiler_builtins` should indeed be linked.
|
// 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
|
let link_static_crate = linkage == Linkage::Static
|
||||||
|| (linkage == Linkage::IncludedFromDylib || linkage == Linkage::NotLinked)
|
|| (linkage == Linkage::IncludedFromDylib || linkage == Linkage::NotLinked)
|
||||||
&& (codegen_results.crate_info.compiler_builtins == Some(cnum)
|
&& (codegen_results.crate_info.compiler_builtins == Some(cnum)
|
||||||
|
|
|
@ -1744,15 +1744,10 @@ fn for_each_exported_symbols_include_dep<'tcx>(
|
||||||
crate_type: CrateType,
|
crate_type: CrateType,
|
||||||
mut callback: impl FnMut(ExportedSymbol<'tcx>, SymbolExportInfo, CrateNum),
|
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 formats = tcx.dependency_formats(());
|
||||||
let deps = &formats[&crate_type];
|
let deps = &formats[&crate_type];
|
||||||
|
|
||||||
for (index, dep_format) in deps.iter().enumerate() {
|
for (cnum, dep_format) in deps.iter_enumerated() {
|
||||||
let cnum = CrateNum::new(index + 1);
|
|
||||||
// For each dependency that we are linking to statically ...
|
// For each dependency that we are linking to statically ...
|
||||||
if *dep_format == Linkage::Static {
|
if *dep_format == Linkage::Static {
|
||||||
for &(symbol, info) in tcx.exported_symbols(cnum).iter() {
|
for &(symbol, info) in tcx.exported_symbols(cnum).iter() {
|
||||||
|
|
|
@ -52,7 +52,8 @@
|
||||||
//! than finding a number of solutions (there are normally quite a few).
|
//! than finding a number of solutions (there are normally quite a few).
|
||||||
|
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
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::bug;
|
||||||
use rustc_middle::middle::dependency_format::{Dependencies, DependencyList, Linkage};
|
use rustc_middle::middle::dependency_format::{Dependencies, DependencyList, Linkage};
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
@ -84,7 +85,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
|
||||||
let sess = &tcx.sess;
|
let sess = &tcx.sess;
|
||||||
|
|
||||||
if !sess.opts.output_types.should_codegen() {
|
if !sess.opts.output_types.should_codegen() {
|
||||||
return Vec::new();
|
return IndexVec::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
let preferred_linkage = match ty {
|
let preferred_linkage = match ty {
|
||||||
|
@ -131,7 +132,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
|
||||||
|
|
||||||
match preferred_linkage {
|
match preferred_linkage {
|
||||||
// If the crate is not linked, there are no link-time dependencies.
|
// If the crate is not linked, there are no link-time dependencies.
|
||||||
Linkage::NotLinked => return Vec::new(),
|
Linkage::NotLinked => return IndexVec::new(),
|
||||||
Linkage::Static => {
|
Linkage::Static => {
|
||||||
// Attempt static linkage first. For dylibs and executables, we may be
|
// Attempt static linkage first. For dylibs and executables, we may be
|
||||||
// able to retry below with dynamic linkage.
|
// able to retry below with dynamic linkage.
|
||||||
|
@ -156,7 +157,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
|
||||||
}
|
}
|
||||||
sess.dcx().emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) });
|
sess.dcx().emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) });
|
||||||
}
|
}
|
||||||
return Vec::new();
|
return IndexVec::new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Linkage::Dynamic | Linkage::IncludedFromDylib => {}
|
Linkage::Dynamic | Linkage::IncludedFromDylib => {}
|
||||||
|
@ -210,13 +211,19 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
|
||||||
|
|
||||||
// Collect what we've got so far in the return vector.
|
// Collect what we've got so far in the return vector.
|
||||||
let last_crate = tcx.crates(()).len();
|
let last_crate = tcx.crates(()).len();
|
||||||
let mut ret = (1..last_crate + 1)
|
let mut ret = IndexVec::new();
|
||||||
.map(|cnum| match formats.get(&CrateNum::new(cnum)) {
|
assert_eq!(ret.push(Linkage::Static), LOCAL_CRATE);
|
||||||
|
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(&RequireDynamic) => Linkage::Dynamic,
|
||||||
Some(&RequireStatic) => Linkage::IncludedFromDylib,
|
Some(&RequireStatic) => Linkage::IncludedFromDylib,
|
||||||
None => Linkage::NotLinked,
|
None => Linkage::NotLinked,
|
||||||
})
|
}),
|
||||||
.collect::<Vec<_>>();
|
cnum
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Run through the dependency list again, and add any missing libraries as
|
// Run through the dependency list again, and add any missing libraries as
|
||||||
// static libraries.
|
// static libraries.
|
||||||
|
@ -232,7 +239,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
|
||||||
assert!(src.rlib.is_some() || src.rmeta.is_some());
|
assert!(src.rlib.is_some() || src.rmeta.is_some());
|
||||||
info!("adding staticlib: {}", tcx.crate_name(cnum));
|
info!("adding staticlib: {}", tcx.crate_name(cnum));
|
||||||
add_library(tcx, cnum, RequireStatic, &mut formats, &mut unavailable_as_static);
|
add_library(tcx, cnum, RequireStatic, &mut formats, &mut unavailable_as_static);
|
||||||
ret[cnum.as_usize() - 1] = Linkage::Static;
|
ret[cnum] = Linkage::Static;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,8 +259,10 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
|
||||||
//
|
//
|
||||||
// For situations like this, we perform one last pass over the dependencies,
|
// For situations like this, we perform one last pass over the dependencies,
|
||||||
// making sure that everything is available in the requested format.
|
// making sure that everything is available in the requested format.
|
||||||
for (cnum, kind) in ret.iter().enumerate() {
|
for (cnum, kind) in ret.iter_enumerated() {
|
||||||
let cnum = CrateNum::new(cnum + 1);
|
if cnum == LOCAL_CRATE {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let src = tcx.used_crate_source(cnum);
|
let src = tcx.used_crate_source(cnum);
|
||||||
match *kind {
|
match *kind {
|
||||||
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
|
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
|
||||||
|
@ -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
|
// 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.
|
// everything in explicitly so long as it's actually required.
|
||||||
let mut ret = tcx
|
let mut ret = IndexVec::new();
|
||||||
.crates(())
|
assert_eq!(ret.push(Linkage::Static), LOCAL_CRATE);
|
||||||
.iter()
|
for &cnum in tcx.crates(()) {
|
||||||
.map(|&cnum| match tcx.dep_kind(cnum) {
|
assert_eq!(
|
||||||
|
ret.push(match tcx.dep_kind(cnum) {
|
||||||
CrateDepKind::Explicit => Linkage::Static,
|
CrateDepKind::Explicit => Linkage::Static,
|
||||||
CrateDepKind::MacrosOnly | CrateDepKind::Implicit => Linkage::NotLinked,
|
CrateDepKind::MacrosOnly | CrateDepKind::Implicit => Linkage::NotLinked,
|
||||||
})
|
}),
|
||||||
.collect::<Vec<_>>();
|
cnum
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Our allocator/panic runtime may not have been linked above if it wasn't
|
// 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
|
// explicitly linked, which is the case for any injected dependency. Handle
|
||||||
|
@ -367,8 +379,7 @@ fn activate_injected_dep(
|
||||||
list: &mut DependencyList,
|
list: &mut DependencyList,
|
||||||
replaces_injected: &dyn Fn(CrateNum) -> bool,
|
replaces_injected: &dyn Fn(CrateNum) -> bool,
|
||||||
) {
|
) {
|
||||||
for (i, slot) in list.iter().enumerate() {
|
for (cnum, slot) in list.iter_enumerated() {
|
||||||
let cnum = CrateNum::new(i + 1);
|
|
||||||
if !replaces_injected(cnum) {
|
if !replaces_injected(cnum) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -377,25 +388,23 @@ fn activate_injected_dep(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(injected) = injected {
|
if let Some(injected) = injected {
|
||||||
let idx = injected.as_usize() - 1;
|
assert_eq!(list[injected], Linkage::NotLinked);
|
||||||
assert_eq!(list[idx], Linkage::NotLinked);
|
list[injected] = Linkage::Static;
|
||||||
list[idx] = Linkage::Static;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// After the linkage for a crate has been determined we need to verify that
|
// 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.
|
// 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;
|
let sess = &tcx.sess;
|
||||||
if list.is_empty() {
|
if list.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mut panic_runtime = None;
|
let mut panic_runtime = None;
|
||||||
for (i, linkage) in list.iter().enumerate() {
|
for (cnum, linkage) in list.iter_enumerated() {
|
||||||
if let Linkage::NotLinked = *linkage {
|
if let Linkage::NotLinked = *linkage {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let cnum = CrateNum::new(i + 1);
|
|
||||||
|
|
||||||
if tcx.is_panic_runtime(cnum) {
|
if tcx.is_panic_runtime(cnum) {
|
||||||
if let Some((prev, _)) = panic_runtime {
|
if let Some((prev, _)) = panic_runtime {
|
||||||
|
@ -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
|
// 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'
|
// is abort then it's compatible with everything. Otherwise all crates'
|
||||||
// panic strategy must match our own.
|
// 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 {
|
if let Linkage::NotLinked = *linkage {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let cnum = CrateNum::new(i + 1);
|
|
||||||
if cnum == runtime_cnum || tcx.is_compiler_builtins(cnum) {
|
if cnum == runtime_cnum || tcx.is_compiler_builtins(cnum) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -450,6 +458,8 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// panic_in_drop_strategy isn't allowed for LOCAL_CRATE
|
||||||
|
if cnum != LOCAL_CRATE {
|
||||||
let found_drop_strategy = tcx.panic_in_drop_strategy(cnum);
|
let found_drop_strategy = tcx.panic_in_drop_strategy(cnum);
|
||||||
if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy {
|
if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy {
|
||||||
sess.dcx().emit_err(IncompatiblePanicInDropStrategy {
|
sess.dcx().emit_err(IncompatiblePanicInDropStrategy {
|
||||||
|
@ -460,4 +470,5 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1474,7 +1474,7 @@ impl<'a> CrateMetadataRef<'a> {
|
||||||
) -> &'tcx [(CrateNum, LinkagePreference)] {
|
) -> &'tcx [(CrateNum, LinkagePreference)] {
|
||||||
tcx.arena.alloc_from_iter(
|
tcx.arena.alloc_from_iter(
|
||||||
self.root.dylib_dependency_formats.decode(self).enumerate().flat_map(|(i, link)| {
|
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))
|
link.map(|link| (self.cnum_map[cnum], link))
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
|
@ -2165,12 +2165,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
empty_proc_macro!(self);
|
empty_proc_macro!(self);
|
||||||
let formats = self.tcx.dependency_formats(());
|
let formats = self.tcx.dependency_formats(());
|
||||||
if let Some(arr) = formats.get(&CrateType::Dylib) {
|
if let Some(arr) = formats.get(&CrateType::Dylib) {
|
||||||
return self.lazy_array(arr.iter().map(|slot| match *slot {
|
return self.lazy_array(arr.iter().skip(1 /* skip LOCAL_CRATE */).map(
|
||||||
|
|slot| match *slot {
|
||||||
Linkage::NotLinked | Linkage::IncludedFromDylib => None,
|
Linkage::NotLinked | Linkage::IncludedFromDylib => None,
|
||||||
|
|
||||||
Linkage::Dynamic => Some(LinkagePreference::RequireDynamic),
|
Linkage::Dynamic => Some(LinkagePreference::RequireDynamic),
|
||||||
Linkage::Static => Some(LinkagePreference::RequireStatic),
|
Linkage::Static => Some(LinkagePreference::RequireStatic),
|
||||||
}));
|
},
|
||||||
|
));
|
||||||
}
|
}
|
||||||
LazyArray::default()
|
LazyArray::default()
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,13 +8,13 @@
|
||||||
// this will introduce circular dependency between rustc_metadata and rustc_middle
|
// this will introduce circular dependency between rustc_metadata and rustc_middle
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
|
use rustc_hir::def_id::CrateNum;
|
||||||
|
use rustc_index::IndexVec;
|
||||||
use rustc_macros::{Decodable, Encodable, HashStable};
|
use rustc_macros::{Decodable, Encodable, HashStable};
|
||||||
use rustc_session::config::CrateType;
|
use rustc_session::config::CrateType;
|
||||||
|
|
||||||
/// A list of dependencies for a certain crate type.
|
/// A list of dependencies for a certain crate type.
|
||||||
///
|
pub type DependencyList = IndexVec<CrateNum, Linkage>;
|
||||||
/// The length of this vector is the same as the number of external crates used.
|
|
||||||
pub type DependencyList = Vec<Linkage>;
|
|
||||||
|
|
||||||
/// A mapping of all required dependencies for a particular flavor of output.
|
/// A mapping of all required dependencies for a particular flavor of output.
|
||||||
///
|
///
|
||||||
|
|
|
@ -151,12 +151,14 @@ pub fn iter_exported_symbols<'tcx>(
|
||||||
let dependency_format = dependency_formats
|
let dependency_format = dependency_formats
|
||||||
.get(&CrateType::Executable)
|
.get(&CrateType::Executable)
|
||||||
.expect("interpreting a non-executable crate");
|
.expect("interpreting a non-executable crate");
|
||||||
for cnum in dependency_format.iter().enumerate().filter_map(|(num, &linkage)| {
|
for cnum in dependency_format
|
||||||
// We add 1 to the number because that's what rustc also does everywhere it
|
.iter_enumerated()
|
||||||
// calls `CrateNum::new`...
|
.filter_map(|(num, &linkage)| (linkage != Linkage::NotLinked).then_some(num))
|
||||||
#[expect(clippy::arithmetic_side_effects)]
|
{
|
||||||
(linkage != Linkage::NotLinked).then_some(CrateNum::new(num + 1))
|
if cnum == LOCAL_CRATE {
|
||||||
}) {
|
continue; // Already handled above
|
||||||
|
}
|
||||||
|
|
||||||
// We can ignore `_export_info` here: we are a Rust crate, and everything is exported
|
// We can ignore `_export_info` here: we are a Rust crate, and everything is exported
|
||||||
// from a Rust crate.
|
// from a Rust crate.
|
||||||
for &(symbol, _export_info) in tcx.exported_symbols(cnum) {
|
for &(symbol, _export_info) in tcx.exported_symbols(cnum) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue