summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_interface/src/queries.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_interface/src/queries.rs')
-rw-r--r--compiler/rustc_interface/src/queries.rs168
1 files changed, 77 insertions, 91 deletions
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 3a5f788e8..8a553b95e 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -1,13 +1,14 @@
use crate::errors::{FailedWritingFile, RustcErrorFatal, RustcErrorUnexpectedAnnotation};
use crate::interface::{Compiler, Result};
-use crate::{passes, util};
+use crate::{errors, passes, util};
use rustc_ast as ast;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::CodegenResults;
use rustc_data_structures::steal::Steal;
use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, Lrc, OnceLock, WorkerLocal};
+use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, OnceLock, WorkerLocal};
+use rustc_hir::def::DefKind;
use rustc_hir::def_id::{StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::definitions::Definitions;
use rustc_incremental::setup_dep_graph;
@@ -15,9 +16,11 @@ use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::DepGraph;
use rustc_middle::ty::{GlobalCtxt, TyCtxt};
+use rustc_serialize::opaque::FileEncodeResult;
use rustc_session::config::{self, CrateType, OutputFilenames, OutputType};
use rustc_session::cstore::Untracked;
-use rustc_session::{output::find_crate_name, Session};
+use rustc_session::output::find_crate_name;
+use rustc_session::Session;
use rustc_span::symbol::sym;
use std::any::Any;
use std::cell::{RefCell, RefMut};
@@ -83,7 +86,6 @@ pub struct Queries<'tcx> {
hir_arena: WorkerLocal<rustc_hir::Arena<'tcx>>,
parse: Query<ast::Crate>,
- pre_configure: Query<(ast::Crate, ast::AttrVec)>,
// This just points to what's in `gcx_cell`.
gcx: Query<&'tcx GlobalCtxt<'tcx>>,
}
@@ -96,29 +98,26 @@ impl<'tcx> Queries<'tcx> {
arena: WorkerLocal::new(|_| Arena::default()),
hir_arena: WorkerLocal::new(|_| rustc_hir::Arena::default()),
parse: Default::default(),
- pre_configure: Default::default(),
gcx: Default::default(),
}
}
- fn session(&self) -> &Lrc<Session> {
- &self.compiler.sess
- }
- fn codegen_backend(&self) -> &Lrc<dyn CodegenBackend> {
- self.compiler.codegen_backend()
+ pub fn finish(&self) -> FileEncodeResult {
+ if let Some(gcx) = self.gcx_cell.get() { gcx.finish() } else { Ok(0) }
}
pub fn parse(&self) -> Result<QueryResult<'_, ast::Crate>> {
- self.parse
- .compute(|| passes::parse(self.session()).map_err(|mut parse_error| parse_error.emit()))
+ self.parse.compute(|| {
+ passes::parse(&self.compiler.sess).map_err(|mut parse_error| parse_error.emit())
+ })
}
- #[deprecated = "pre_configure may be made private in the future. If you need it please open an issue with your use case."]
- pub fn pre_configure(&self) -> Result<QueryResult<'_, (ast::Crate, ast::AttrVec)>> {
- self.pre_configure.compute(|| {
+ pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> {
+ self.gcx.compute(|| {
+ let sess = &self.compiler.sess;
+
let mut krate = self.parse()?.steal();
- let sess = self.session();
rustc_builtin_macros::cmdline_attrs::inject(
&mut krate,
&sess.parse_sess,
@@ -127,15 +126,6 @@ impl<'tcx> Queries<'tcx> {
let pre_configured_attrs =
rustc_expand::config::pre_configure_attrs(sess, &krate.attrs);
- Ok((krate, pre_configured_attrs))
- })
- }
-
- pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> {
- self.gcx.compute(|| {
- let sess = self.session();
- #[allow(deprecated)]
- let (krate, pre_configured_attrs) = self.pre_configure()?.steal();
// parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
let crate_name = find_crate_name(sess, &pre_configured_attrs);
@@ -146,12 +136,11 @@ impl<'tcx> Queries<'tcx> {
sess.opts.cg.metadata.clone(),
sess.cfg_version,
);
+ let outputs = util::build_output_filenames(&pre_configured_attrs, sess);
let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id)?;
- let lint_store =
- Lrc::new(passes::create_lint_store(sess, self.compiler.register_lints.as_deref()));
let cstore = FreezeLock::new(Box::new(CStore::new(
- self.codegen_backend().metadata_loader(),
+ self.compiler.codegen_backend.metadata_loader(),
stable_crate_id,
)) as _);
let definitions = FreezeLock::new(Definitions::new(stable_crate_id));
@@ -164,7 +153,6 @@ impl<'tcx> Queries<'tcx> {
self.compiler,
crate_types,
stable_crate_id,
- lint_store,
dep_graph,
untracked,
&self.gcx_cell,
@@ -183,25 +171,20 @@ impl<'tcx> Queries<'tcx> {
crate_name,
)));
feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs))));
+ feed.output_filenames(Arc::new(outputs));
+
+ let feed = tcx.feed_local_def_id(CRATE_DEF_ID);
+ feed.def_kind(DefKind::Mod);
});
Ok(qcx)
})
}
- pub fn ongoing_codegen(&'tcx self) -> Result<Box<dyn Any>> {
+ pub fn write_dep_info(&'tcx self) -> Result<()> {
self.global_ctxt()?.enter(|tcx| {
- // Don't do code generation if there were any errors
- self.session().compile_status()?;
-
- // If we have any delayed bugs, for example because we created TyKind::Error earlier,
- // it's likely that codegen will only cause more ICEs, obscuring the original problem
- self.session().diagnostic().flush_delayed();
-
- // Hook for UI tests.
- Self::check_for_rustc_errors_attr(tcx);
-
- Ok(passes::start_codegen(&**self.codegen_backend(), tcx))
- })
+ passes::write_dep_info(tcx);
+ });
+ Ok(())
}
/// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used
@@ -211,16 +194,16 @@ impl<'tcx> Queries<'tcx> {
let Some((def_id, _)) = tcx.entry_fn(()) else { return };
for attr in tcx.get_attrs(def_id, sym::rustc_error) {
match attr.meta_item_list() {
- // Check if there is a `#[rustc_error(delay_span_bug_from_inside_query)]`.
+ // Check if there is a `#[rustc_error(span_delayed_bug_from_inside_query)]`.
Some(list)
if list.iter().any(|list_item| {
matches!(
list_item.ident().map(|i| i.name),
- Some(sym::delay_span_bug_from_inside_query)
+ Some(sym::span_delayed_bug_from_inside_query)
)
}) =>
{
- tcx.ensure().trigger_delay_span_bug(def_id);
+ tcx.ensure().trigger_span_delayed_bug(def_id);
}
// Bare `#[rustc_error]`.
@@ -238,68 +221,61 @@ impl<'tcx> Queries<'tcx> {
}
}
- pub fn linker(&'tcx self, ongoing_codegen: Box<dyn Any>) -> Result<Linker> {
- let sess = self.session().clone();
- let codegen_backend = self.codegen_backend().clone();
+ pub fn codegen_and_build_linker(&'tcx self) -> Result<Linker> {
+ self.global_ctxt()?.enter(|tcx| {
+ // Don't do code generation if there were any errors
+ self.compiler.sess.compile_status()?;
- let (crate_hash, prepare_outputs, dep_graph) = self.global_ctxt()?.enter(|tcx| {
- (
- if tcx.needs_crate_hash() { Some(tcx.crate_hash(LOCAL_CRATE)) } else { None },
- tcx.output_filenames(()).clone(),
- tcx.dep_graph.clone(),
- )
- });
+ // If we have any delayed bugs, for example because we created TyKind::Error earlier,
+ // it's likely that codegen will only cause more ICEs, obscuring the original problem
+ self.compiler.sess.dcx().flush_delayed();
- Ok(Linker {
- sess,
- codegen_backend,
+ // Hook for UI tests.
+ Self::check_for_rustc_errors_attr(tcx);
- dep_graph,
- prepare_outputs,
- crate_hash,
- ongoing_codegen,
+ let ongoing_codegen = passes::start_codegen(&*self.compiler.codegen_backend, tcx);
+
+ Ok(Linker {
+ dep_graph: tcx.dep_graph.clone(),
+ output_filenames: tcx.output_filenames(()).clone(),
+ crate_hash: if tcx.needs_crate_hash() {
+ Some(tcx.crate_hash(LOCAL_CRATE))
+ } else {
+ None
+ },
+ ongoing_codegen,
+ })
})
}
}
pub struct Linker {
- // compilation inputs
- sess: Lrc<Session>,
- codegen_backend: Lrc<dyn CodegenBackend>,
-
- // compilation outputs
dep_graph: DepGraph,
- prepare_outputs: Arc<OutputFilenames>,
+ output_filenames: Arc<OutputFilenames>,
// Only present when incr. comp. is enabled.
crate_hash: Option<Svh>,
ongoing_codegen: Box<dyn Any>,
}
impl Linker {
- pub fn link(self) -> Result<()> {
- let (codegen_results, work_products) = self.codegen_backend.join_codegen(
- self.ongoing_codegen,
- &self.sess,
- &self.prepare_outputs,
- )?;
+ pub fn link(self, sess: &Session, codegen_backend: &dyn CodegenBackend) -> Result<()> {
+ let (codegen_results, work_products) =
+ codegen_backend.join_codegen(self.ongoing_codegen, sess, &self.output_filenames)?;
- self.sess.compile_status()?;
+ sess.compile_status()?;
- let sess = &self.sess;
- let dep_graph = self.dep_graph;
sess.time("serialize_work_products", || {
- rustc_incremental::save_work_product_index(sess, &dep_graph, work_products)
+ rustc_incremental::save_work_product_index(sess, &self.dep_graph, work_products)
});
- let prof = self.sess.prof.clone();
- prof.generic_activity("drop_dep_graph").run(move || drop(dep_graph));
+ let prof = sess.prof.clone();
+ prof.generic_activity("drop_dep_graph").run(move || drop(self.dep_graph));
// Now that we won't touch anything in the incremental compilation directory
// any more, we can finalize it (which involves renaming it)
- rustc_incremental::finalize_session_directory(&self.sess, self.crate_hash);
+ rustc_incremental::finalize_session_directory(sess, self.crate_hash);
- if !self
- .sess
+ if !sess
.opts
.output_types
.keys()
@@ -309,14 +285,19 @@ impl Linker {
}
if sess.opts.unstable_opts.no_link {
- let rlink_file = self.prepare_outputs.with_extension(config::RLINK_EXT);
- CodegenResults::serialize_rlink(sess, &rlink_file, &codegen_results)
- .map_err(|error| sess.emit_fatal(FailedWritingFile { path: &rlink_file, error }))?;
+ let rlink_file = self.output_filenames.with_extension(config::RLINK_EXT);
+ CodegenResults::serialize_rlink(
+ sess,
+ &rlink_file,
+ &codegen_results,
+ &*self.output_filenames,
+ )
+ .map_err(|error| sess.emit_fatal(FailedWritingFile { path: &rlink_file, error }))?;
return Ok(());
}
let _timer = sess.prof.verbose_generic_activity("link_crate");
- self.codegen_backend.link(&self.sess, codegen_results, &self.prepare_outputs)
+ codegen_backend.link(sess, codegen_results, &self.output_filenames)
}
}
@@ -325,6 +306,7 @@ impl Compiler {
where
F: for<'tcx> FnOnce(&'tcx Queries<'tcx>) -> T,
{
+ // Must declare `_timer` first so that it is dropped after `queries`.
let mut _timer = None;
let queries = Queries::new(self);
let ret = f(&queries);
@@ -337,15 +319,19 @@ impl Compiler {
// after this point, they'll show up as "<unknown>" in self-profiling data.
{
let _prof_timer =
- queries.session().prof.generic_activity("self_profile_alloc_query_strings");
+ queries.compiler.sess.prof.generic_activity("self_profile_alloc_query_strings");
gcx.enter(rustc_query_impl::alloc_self_profile_query_strings);
}
- self.session()
- .time("serialize_dep_graph", || gcx.enter(rustc_incremental::save_dep_graph));
+ self.sess.time("serialize_dep_graph", || gcx.enter(rustc_incremental::save_dep_graph));
}
- _timer = Some(self.session().timer("free_global_ctxt"));
+ // The timer's lifetime spans the dropping of `queries`, which contains
+ // the global context.
+ _timer = Some(self.sess.timer("free_global_ctxt"));
+ if let Err((path, error)) = queries.finish() {
+ self.sess.emit_err(errors::FailedWritingFile { path: &path, error });
+ }
ret
}