Skip to content

Commit

Permalink
Rollup merge of rust-lang#134514 - bjorn3:more_driver_refactors, r=ji…
Browse files Browse the repository at this point in the history
…eyouxu

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 rust-lang#134302. This refactor is too small to be worth it's own PR.
  • Loading branch information
DianQK authored Dec 20, 2024
2 parents 1652e3a + 0daa921 commit 350e7f8
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 86 deletions.
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) {
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() {
// 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);

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

0 comments on commit 350e7f8

Please sign in to comment.