Rollup merge of #134514 - bjorn3:more_driver_refactors, r=jieyouxu
Improve dependency_format a bit * Make `DependencyList` an `IndexVec` rather than emulating one using a `Vec` (which was off-by-one as LOCAL_CRATE was intentionally skipped) * Update some comments for the fact that we now use `#[global_allocator]` rather than `extern crate alloc_system;`/`extern crate alloc_jemalloc;` for specifying which allocator to use. We still use a similar mechanism for the panic runtime, so refer to the panic runtime in those comments instead. * An unrelated refactor to `create_and_enter_global_ctxt` I forgot to include in https://github.com/rust-lang/rust/pull/134302. This refactor is too small to be worth it's own PR.
This commit is contained in:
commit
350e7f858e
10 changed files with 100 additions and 86 deletions
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
@ -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) {
|
||||
Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue,
|
||||
Some(_) => {}
|
||||
None => return Err(errors::LinkRlibError::MissingFormat),
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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<_>>();
|
||||
|
@ -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)
|
||||
|
|
|
@ -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() {
|
||||
// For each dependency that we are linking to statically ...
|
||||
if *dep_format == Linkage::Static {
|
||||
for &(symbol, info) in tcx.exported_symbols(cnum).iter() {
|
||||
|
|
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -796,7 +795,7 @@ 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);
|
||||
|
@ -804,7 +803,7 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
|
|||
|
||||
let feed = tcx.feed_unit_query();
|
||||
feed.features_query(tcx.arena.alloc(rustc_expand::config::features(
|
||||
sess,
|
||||
tcx.sess,
|
||||
&pre_configured_attrs,
|
||||
crate_name,
|
||||
)));
|
||||
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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 => {}
|
||||
|
@ -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)) {
|
||||
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);
|
||||
|
||||
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,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
}),
|
||||
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()
|
||||
|
@ -232,7 +246,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,8 +254,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
|
|||
// 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)
|
||||
});
|
||||
|
@ -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 => {}
|
||||
|
@ -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) {
|
||||
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,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
}),
|
||||
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)
|
||||
});
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -450,6 +464,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);
|
||||
if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy {
|
||||
sess.dcx().emit_err(IncompatiblePanicInDropStrategy {
|
||||
|
@ -460,4 +476,5 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}),
|
||||
)
|
||||
|
|
|
@ -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 {
|
||||
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),
|
||||
}));
|
||||
},
|
||||
));
|
||||
}
|
||||
LazyArray::default()
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -42,7 +42,7 @@ pub enum CrateDepKind {
|
|||
/// A dependency that is only used for its macros.
|
||||
MacrosOnly,
|
||||
/// A dependency that is always injected into the dependency list and so
|
||||
/// doesn't need to be linked to an rlib, e.g., the injected allocator.
|
||||
/// doesn't need to be linked to an rlib, e.g., the injected panic runtime.
|
||||
Implicit,
|
||||
/// A dependency that is required by an rlib version of this crate.
|
||||
/// Ordinary `extern crate`s result in `Explicit` dependencies.
|
||||
|
|
|
@ -152,12 +152,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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue