Move most of make_query into a generic function, away from the macro

This should both make the code easier to read and also greatly reduce the amount of codegen
the compiler has to do, since it only needs to monomorphize `create_query_frame` for each
new key and not for each query.
This commit is contained in:
Joshua Nelson 2022-08-11 20:36:13 -05:00
parent 1de08b19d1
commit 0bedd354ca
2 changed files with 56 additions and 42 deletions

View File

@ -15,7 +15,6 @@ extern crate rustc_macros;
#[macro_use] #[macro_use]
extern crate rustc_middle; extern crate rustc_middle;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::AtomicU64; use rustc_data_structures::sync::AtomicU64;
use rustc_middle::arena::Arena; use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::{self, DepKindStruct, SerializedDepNodeIndex}; use rustc_middle::dep_graph::{self, DepKindStruct, SerializedDepNodeIndex};

View File

@ -2,13 +2,18 @@
//! generate the actual methods on tcx which find and execute the provider, //! generate the actual methods on tcx which find and execute the provider,
//! manage the caches, and so forth. //! manage the caches, and so forth.
use crate::keys::Key;
use crate::{on_disk_cache, Queries}; use crate::{on_disk_cache, Queries};
use rustc_middle::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; use rustc_middle::dep_graph::{self, DepKind, DepNodeIndex, SerializedDepNodeIndex};
use rustc_middle::ty::tls::{self, ImplicitCtxt}; use rustc_middle::ty::tls::{self, ImplicitCtxt};
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::{self, TyCtxt};
use rustc_query_system::dep_graph::HasDepContext; use rustc_query_system::dep_graph::HasDepContext;
use rustc_query_system::query::{QueryContext, QueryJobId, QueryMap, QuerySideEffects}; use rustc_query_system::ich::StableHashingContext;
use rustc_query_system::query::{
QueryContext, QueryJobId, QueryMap, QuerySideEffects, QueryStackFrame,
};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::Lock; use rustc_data_structures::sync::Lock;
use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::{Diagnostic, Handler}; use rustc_errors::{Diagnostic, Handler};
@ -233,35 +238,24 @@ macro_rules! get_provider {
}; };
} }
macro_rules! define_queries { pub(crate) fn create_query_frame<
( 'tcx,
$($(#[$attr:meta])* K: Copy + Key + for<'a> HashStable<StableHashingContext<'a>>,
[$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => { >(
define_queries_struct! { tcx: QueryCtxt<'tcx>,
input: ($(([$($modifiers)*] [$($attr)*] [$name]))*) do_describe: fn(QueryCtxt<'tcx>, K) -> String,
} key: K,
kind: DepKind,
mod make_query { name: &'static str,
use super::*; ) -> QueryStackFrame {
// Create an eponymous constructor for each query.
$(#[allow(nonstandard_style)] $(#[$attr])*
pub fn $name<'tcx>(tcx: QueryCtxt<'tcx>, key: <queries::$name<'tcx> as QueryConfig>::Key) -> QueryStackFrame {
let kind = dep_graph::DepKind::$name;
let name = stringify!($name);
// Disable visible paths printing for performance reasons. // Disable visible paths printing for performance reasons.
// Showing visible path instead of any path is not that important in production. // Showing visible path instead of any path is not that important in production.
let description = ty::print::with_no_visible_paths!( let description = ty::print::with_no_visible_paths!(
// Force filename-line mode to avoid invoking `type_of` query. // Force filename-line mode to avoid invoking `type_of` query.
ty::print::with_forced_impl_filename_line!( ty::print::with_forced_impl_filename_line!(do_describe(tcx, key))
queries::$name::describe(tcx, key)
)
); );
let description = if tcx.sess.verbose() { let description =
format!("{} [{}]", description, name) if tcx.sess.verbose() { format!("{} [{}]", description, name) } else { description };
} else {
description
};
let span = if kind == dep_graph::DepKind::def_span { let span = if kind == dep_graph::DepKind::def_span {
// The `def_span` query is used to calculate `default_span`, // The `def_span` query is used to calculate `default_span`,
// so exit to avoid infinite recursion. // so exit to avoid infinite recursion.
@ -278,7 +272,7 @@ macro_rules! define_queries {
.and_then(|def_id| tcx.opt_def_kind(def_id)) .and_then(|def_id| tcx.opt_def_kind(def_id))
}; };
let hash = || { let hash = || {
tcx.with_stable_hashing_context(|mut hcx|{ tcx.with_stable_hashing_context(|mut hcx| {
let mut hasher = StableHasher::new(); let mut hasher = StableHasher::new();
std::mem::discriminant(&kind).hash_stable(&mut hcx, &mut hasher); std::mem::discriminant(&kind).hash_stable(&mut hcx, &mut hasher);
key.hash_stable(&mut hcx, &mut hasher); key.hash_stable(&mut hcx, &mut hasher);
@ -287,6 +281,27 @@ macro_rules! define_queries {
}; };
QueryStackFrame::new(name, description, span, def_kind, hash) QueryStackFrame::new(name, description, span, def_kind, hash)
}
// NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
// invoked by `rustc_query_append`.
macro_rules! define_queries {
(
$($(#[$attr:meta])*
[$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
define_queries_struct! {
input: ($(([$($modifiers)*] [$($attr)*] [$name]))*)
}
mod make_query {
use super::*;
// Create an eponymous constructor for each query.
$(#[allow(nonstandard_style)] $(#[$attr])*
pub fn $name<'tcx>(tcx: QueryCtxt<'tcx>, key: <queries::$name<'tcx> as QueryConfig>::Key) -> QueryStackFrame {
let kind = dep_graph::DepKind::$name;
let name = stringify!($name);
$crate::plumbing::create_query_frame(tcx, queries::$name::describe, key, kind, name)
})* })*
} }