Skip to content

Commit 23d415a

Browse files
committed
Refactor MIR metadata emission.
1 parent f071b50 commit 23d415a

File tree

1 file changed

+43
-215
lines changed

1 file changed

+43
-215
lines changed

compiler/rustc_metadata/src/rmeta/encoder.rs

+43-215
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ use crate::rmeta::table::{FixedSizeEncoding, TableBuilder};
22
use crate::rmeta::*;
33

44
use rustc_data_structures::fingerprint::{Fingerprint, FingerprintEncoder};
5-
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
5+
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
66
use rustc_data_structures::stable_hasher::StableHasher;
7-
use rustc_data_structures::sync::{join, Lrc};
7+
use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator};
88
use rustc_hir as hir;
99
use rustc_hir::def::{CtorOf, DefKind};
1010
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
1111
use rustc_hir::definitions::DefPathData;
1212
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
13-
use rustc_hir::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor};
13+
use rustc_hir::itemlikevisit::ItemLikeVisitor;
1414
use rustc_hir::lang_items;
1515
use rustc_hir::{AnonConst, GenericParamKind};
1616
use rustc_index::bit_set::GrowableBitSet;
@@ -65,11 +65,6 @@ pub(super) struct EncodeContext<'a, 'tcx> {
6565
required_source_files: Option<GrowableBitSet<usize>>,
6666
is_proc_macro: bool,
6767
hygiene_ctxt: &'a HygieneEncodeContext,
68-
69-
// Determines if MIR used for code generation will be included in the crate
70-
// metadata. When emitting only metadata (e.g., cargo check), we can avoid
71-
// generating optimized MIR altogether.
72-
emit_codegen_mir: bool,
7368
}
7469

7570
/// If the current crate is a proc-macro, returns early with `Lazy:empty()`.
@@ -580,6 +575,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
580575
// Encode the items.
581576
i = self.position();
582577
self.encode_def_ids();
578+
self.encode_mir();
583579
self.encode_info_for_items();
584580
let item_bytes = self.position() - i;
585581

@@ -919,11 +915,6 @@ impl EncodeContext<'a, 'tcx> {
919915
self.encode_generics(def_id);
920916
self.encode_explicit_predicates(def_id);
921917
self.encode_inferred_outlives(def_id);
922-
let opt_mir = tcx.sess.opts.debugging_opts.always_encode_mir || self.emit_codegen_mir;
923-
if opt_mir {
924-
self.encode_optimized_mir(def_id.expect_local());
925-
}
926-
self.encode_mir_for_ctfe(def_id.expect_local());
927918
}
928919

929920
fn encode_info_for_mod(&mut self, id: hir::HirId, md: &hir::Mod<'_>) {
@@ -1009,11 +1000,6 @@ impl EncodeContext<'a, 'tcx> {
10091000
self.encode_generics(def_id);
10101001
self.encode_explicit_predicates(def_id);
10111002
self.encode_inferred_outlives(def_id);
1012-
let opt_mir = tcx.sess.opts.debugging_opts.always_encode_mir || self.emit_codegen_mir;
1013-
if opt_mir {
1014-
self.encode_optimized_mir(def_id.expect_local());
1015-
}
1016-
self.encode_mir_for_ctfe(def_id.expect_local());
10171003
}
10181004

10191005
fn encode_generics(&mut self, def_id: DefId) {
@@ -1119,34 +1105,6 @@ impl EncodeContext<'a, 'tcx> {
11191105
self.encode_generics(def_id);
11201106
self.encode_explicit_predicates(def_id);
11211107
self.encode_inferred_outlives(def_id);
1122-
1123-
// This should be kept in sync with `PrefetchVisitor.visit_trait_item`.
1124-
match trait_item.kind {
1125-
ty::AssocKind::Type => {}
1126-
ty::AssocKind::Const => {
1127-
if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id.expect_local()) {
1128-
self.encode_mir_for_ctfe(def_id.expect_local());
1129-
self.encode_promoted_mir(def_id.expect_local());
1130-
}
1131-
}
1132-
ty::AssocKind::Fn => {
1133-
let opt_mir =
1134-
tcx.sess.opts.debugging_opts.always_encode_mir || self.emit_codegen_mir;
1135-
if opt_mir {
1136-
if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id.expect_local()) {
1137-
self.encode_optimized_mir(def_id.expect_local());
1138-
self.encode_promoted_mir(def_id.expect_local());
1139-
}
1140-
}
1141-
}
1142-
}
1143-
}
1144-
1145-
fn should_encode_fn_opt_mir(&self, def_id: DefId) -> bool {
1146-
self.tcx.sess.opts.debugging_opts.always_encode_mir
1147-
|| (self.emit_codegen_mir
1148-
&& (self.tcx.generics_of(def_id).requires_monomorphization(self.tcx)
1149-
|| self.tcx.codegen_fn_attrs(def_id).requests_inline()))
11501108
}
11511109

11521110
fn encode_info_for_impl_item(&mut self, def_id: DefId) {
@@ -1208,27 +1166,6 @@ impl EncodeContext<'a, 'tcx> {
12081166
self.encode_generics(def_id);
12091167
self.encode_explicit_predicates(def_id);
12101168
self.encode_inferred_outlives(def_id);
1211-
1212-
// The following part should be kept in sync with `PrefetchVisitor.visit_impl_item`.
1213-
1214-
let (mir, mir_const) = match ast_item.kind {
1215-
hir::ImplItemKind::Const(..) => (false, true),
1216-
hir::ImplItemKind::Fn(ref sig, _) => {
1217-
let opt_mir = self.should_encode_fn_opt_mir(def_id);
1218-
let is_const_fn = sig.header.constness == hir::Constness::Const;
1219-
(opt_mir, is_const_fn)
1220-
}
1221-
hir::ImplItemKind::TyAlias(..) => (false, false),
1222-
};
1223-
if mir {
1224-
self.encode_optimized_mir(def_id.expect_local());
1225-
}
1226-
if mir || mir_const {
1227-
self.encode_promoted_mir(def_id.expect_local());
1228-
}
1229-
if mir_const {
1230-
self.encode_mir_for_ctfe(def_id.expect_local());
1231-
}
12321169
}
12331170

12341171
fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) -> Lazy<[Ident]> {
@@ -1239,36 +1176,37 @@ impl EncodeContext<'a, 'tcx> {
12391176
self.lazy(param_names.iter())
12401177
}
12411178

1242-
fn encode_mir_for_ctfe(&mut self, def_id: LocalDefId) {
1243-
debug!("EntryBuilder::encode_mir_for_ctfe({:?})", def_id);
1244-
record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- self.tcx.mir_for_ctfe(def_id));
1245-
1246-
let unused = self.tcx.unused_generic_params(def_id);
1247-
if !unused.is_empty() {
1248-
record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
1179+
fn encode_mir(&mut self) {
1180+
if self.is_proc_macro {
1181+
return;
12491182
}
1183+
for &def_id in self.tcx.mir_keys(LOCAL_CRATE).iter() {
1184+
let (encode_const, encode_opt) = should_encode_mir(self.tcx, def_id);
1185+
if !encode_const && !encode_opt {
1186+
continue;
1187+
}
12501188

1251-
let abstract_const = self.tcx.mir_abstract_const(def_id);
1252-
if let Ok(Some(abstract_const)) = abstract_const {
1253-
record!(self.tables.mir_abstract_consts[def_id.to_def_id()] <- abstract_const);
1254-
}
1255-
}
1189+
debug!("EntryBuilder::encode_mir({:?})", def_id);
1190+
if encode_opt {
1191+
record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id));
1192+
}
1193+
if encode_const {
1194+
record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- self.tcx.mir_for_ctfe(def_id));
1195+
}
1196+
record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id));
12561197

1257-
fn encode_optimized_mir(&mut self, def_id: LocalDefId) {
1258-
debug!("EntryBuilder::encode_optimized_mir({:?})", def_id);
1259-
record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id));
1198+
let unused = self.tcx.unused_generic_params(def_id);
1199+
if !unused.is_empty() {
1200+
record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
1201+
}
12601202

1261-
let unused = self.tcx.unused_generic_params(def_id);
1262-
if !unused.is_empty() {
1263-
record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
1203+
let abstract_const = self.tcx.mir_abstract_const(def_id);
1204+
if let Ok(Some(abstract_const)) = abstract_const {
1205+
record!(self.tables.mir_abstract_consts[def_id.to_def_id()] <- abstract_const);
1206+
}
12641207
}
12651208
}
12661209

1267-
fn encode_promoted_mir(&mut self, def_id: LocalDefId) {
1268-
debug!("EncodeContext::encode_promoted_mir({:?})", def_id);
1269-
record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id));
1270-
}
1271-
12721210
// Encodes the inherent implementations of a structure, enumeration, or trait.
12731211
fn encode_inherent_implementations(&mut self, def_id: DefId) {
12741212
debug!("EncodeContext::encode_inherent_implementations({:?})", def_id);
@@ -1524,28 +1462,6 @@ impl EncodeContext<'a, 'tcx> {
15241462
}
15251463
_ => {}
15261464
}
1527-
1528-
// The following part should be kept in sync with `PrefetchVisitor.visit_item`.
1529-
1530-
let (mir, const_mir) = match item.kind {
1531-
hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => (false, true),
1532-
hir::ItemKind::Fn(ref sig, ..) => {
1533-
let opt_mir = self.should_encode_fn_opt_mir(def_id);
1534-
let is_const_fn = sig.header.constness == hir::Constness::Const;
1535-
// We don't need the optimized MIR for const fns.
1536-
(opt_mir, is_const_fn)
1537-
}
1538-
_ => (false, false),
1539-
};
1540-
if mir {
1541-
self.encode_optimized_mir(def_id.expect_local());
1542-
}
1543-
if mir || const_mir {
1544-
self.encode_promoted_mir(def_id.expect_local());
1545-
}
1546-
if const_mir {
1547-
self.encode_mir_for_ctfe(def_id.expect_local());
1548-
}
15491465
}
15501466

15511467
/// Serialize the text of exported macros
@@ -1587,14 +1503,6 @@ impl EncodeContext<'a, 'tcx> {
15871503
record!(self.tables.fn_sig[def_id] <- substs.as_closure().sig());
15881504
}
15891505
self.encode_generics(def_id.to_def_id());
1590-
let opt_mir = // FIXME: Optimized MIR is necessary to determine the layout of generators.
1591-
matches!(ty.kind(), ty::Generator(..))
1592-
|| self.tcx.sess.opts.debugging_opts.always_encode_mir
1593-
|| self.emit_codegen_mir;
1594-
if opt_mir {
1595-
self.encode_optimized_mir(def_id);
1596-
self.encode_promoted_mir(def_id);
1597-
}
15981506
}
15991507

16001508
fn encode_info_for_anon_const(&mut self, def_id: LocalDefId) {
@@ -1609,8 +1517,6 @@ impl EncodeContext<'a, 'tcx> {
16091517
self.encode_generics(def_id.to_def_id());
16101518
self.encode_explicit_predicates(def_id.to_def_id());
16111519
self.encode_inferred_outlives(def_id.to_def_id());
1612-
self.encode_mir_for_ctfe(def_id);
1613-
self.encode_promoted_mir(def_id);
16141520
}
16151521

16161522
fn encode_native_libraries(&mut self) -> Lazy<[NativeLib]> {
@@ -2075,90 +1981,25 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
20751981

20761982
/// Used to prefetch queries which will be needed later by metadata encoding.
20771983
/// Only a subset of the queries are actually prefetched to keep this code smaller.
2078-
struct PrefetchVisitor<'tcx> {
2079-
tcx: TyCtxt<'tcx>,
2080-
mir_keys: &'tcx FxHashSet<LocalDefId>,
2081-
}
2082-
2083-
impl<'tcx> PrefetchVisitor<'tcx> {
2084-
fn prefetch_ctfe_mir(&self, def_id: LocalDefId) {
2085-
if self.mir_keys.contains(&def_id) {
2086-
self.tcx.ensure().mir_for_ctfe(def_id);
2087-
self.tcx.ensure().promoted_mir(def_id);
2088-
}
1984+
fn prefetch_mir(tcx: TyCtxt<'_>) {
1985+
if !tcx.sess.opts.output_types.should_codegen() {
1986+
// We won't emit MIR, so don't prefetch it.
1987+
return;
20891988
}
2090-
fn prefetch_mir(&self, def_id: LocalDefId) {
2091-
if self.mir_keys.contains(&def_id) {
2092-
self.tcx.ensure().optimized_mir(def_id);
2093-
self.tcx.ensure().promoted_mir(def_id);
2094-
}
2095-
}
2096-
}
20971989

2098-
impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> {
2099-
fn visit_item(&self, item: &hir::Item<'_>) {
2100-
// This should be kept in sync with `encode_info_for_item`.
2101-
let tcx = self.tcx;
2102-
match item.kind {
2103-
hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => {
2104-
self.prefetch_ctfe_mir(tcx.hir().local_def_id(item.hir_id))
2105-
}
2106-
hir::ItemKind::Fn(ref sig, ..) => {
2107-
let def_id = tcx.hir().local_def_id(item.hir_id);
2108-
let opt_mir = tcx.generics_of(def_id.to_def_id()).requires_monomorphization(tcx)
2109-
|| tcx.codegen_fn_attrs(def_id.to_def_id()).requests_inline();
2110-
if opt_mir {
2111-
self.prefetch_mir(def_id)
2112-
}
2113-
if sig.header.constness == hir::Constness::Const {
2114-
self.prefetch_ctfe_mir(def_id);
2115-
}
2116-
}
2117-
_ => (),
2118-
}
2119-
}
1990+
par_iter(tcx.mir_keys(LOCAL_CRATE)).for_each(|&def_id| {
1991+
let (encode_const, encode_opt) = should_encode_mir(tcx, def_id);
21201992

2121-
fn visit_trait_item(&self, trait_item: &'v hir::TraitItem<'v>) {
2122-
// This should be kept in sync with `encode_info_for_trait_item`.
2123-
let def_id = self.tcx.hir().local_def_id(trait_item.hir_id);
2124-
match trait_item.kind {
2125-
hir::TraitItemKind::Type(..) => {}
2126-
hir::TraitItemKind::Const(..) => {
2127-
self.prefetch_ctfe_mir(def_id);
2128-
}
2129-
hir::TraitItemKind::Fn(..) => {
2130-
self.prefetch_mir(def_id);
2131-
}
1993+
if encode_const {
1994+
tcx.ensure().mir_for_ctfe(def_id);
21321995
}
2133-
}
2134-
2135-
fn visit_impl_item(&self, impl_item: &'v hir::ImplItem<'v>) {
2136-
// This should be kept in sync with `encode_info_for_impl_item`.
2137-
let tcx = self.tcx;
2138-
match impl_item.kind {
2139-
hir::ImplItemKind::Const(..) => {
2140-
self.prefetch_ctfe_mir(tcx.hir().local_def_id(impl_item.hir_id))
2141-
}
2142-
hir::ImplItemKind::Fn(ref sig, _) => {
2143-
let def_id = tcx.hir().local_def_id(impl_item.hir_id);
2144-
let opt_mir = tcx.generics_of(def_id.to_def_id()).requires_monomorphization(tcx)
2145-
|| tcx.codegen_fn_attrs(def_id.to_def_id()).requests_inline();
2146-
let is_const_fn = sig.header.constness == hir::Constness::Const;
2147-
if opt_mir {
2148-
self.prefetch_mir(def_id)
2149-
}
2150-
if is_const_fn {
2151-
self.prefetch_ctfe_mir(def_id);
2152-
}
2153-
}
2154-
hir::ImplItemKind::TyAlias(..) => (),
1996+
if encode_opt {
1997+
tcx.ensure().optimized_mir(def_id);
21551998
}
2156-
}
2157-
2158-
fn visit_foreign_item(&self, _foreign_item: &'v hir::ForeignItem<'v>) {
2159-
// This should be kept in sync with `encode_info_for_foreign_item`.
2160-
// Foreign items contain no MIR.
2161-
}
1999+
if encode_opt || encode_const {
2000+
tcx.ensure().promoted_mir(def_id);
2001+
}
2002+
})
21622003
}
21632004

21642005
// NOTE(eddyb) The following comment was preserved for posterity, even
@@ -2198,19 +2039,7 @@ pub(super) fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata {
21982039
// Prefetch some queries used by metadata encoding.
21992040
// This is not necessary for correctness, but is only done for performance reasons.
22002041
// It can be removed if it turns out to cause trouble or be detrimental to performance.
2201-
join(
2202-
|| {
2203-
if !tcx.sess.opts.output_types.should_codegen() {
2204-
// We won't emit MIR, so don't prefetch it.
2205-
return;
2206-
}
2207-
tcx.hir().krate().par_visit_all_item_likes(&PrefetchVisitor {
2208-
tcx,
2209-
mir_keys: tcx.mir_keys(LOCAL_CRATE),
2210-
});
2211-
},
2212-
|| tcx.exported_symbols(LOCAL_CRATE),
2213-
);
2042+
join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE));
22142043
},
22152044
)
22162045
.0
@@ -2243,7 +2072,6 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
22432072
required_source_files,
22442073
is_proc_macro: tcx.sess.crate_types().contains(&CrateType::ProcMacro),
22452074
hygiene_ctxt: &hygiene_ctxt,
2246-
emit_codegen_mir: tcx.sess.opts.output_types.should_codegen(),
22472075
};
22482076

22492077
// Encode the rustc version string in a predictable location.

0 commit comments

Comments
 (0)