Skip to content

Commit 0f5d3ba

Browse files
authored
Rollup merge of #104019 - compiler-errors:print-generator-sizes, r=wesleywiser
Compute generator sizes with `-Zprint_type_sizes` Fixes #103887 r? `@pnkfelix`
2 parents ae8794c + 7d23e29 commit 0f5d3ba

File tree

10 files changed

+286
-104
lines changed

10 files changed

+286
-104
lines changed

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

+1-67
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@ use rustc_codegen_ssa::traits::*;
2727
use rustc_fs_util::path_to_c_string;
2828
use rustc_hir::def::CtorKind;
2929
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
30-
use rustc_index::vec::{Idx, IndexVec};
3130
use rustc_middle::bug;
32-
use rustc_middle::mir::{self, GeneratorLayout};
3331
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
3432
use rustc_middle::ty::subst::GenericArgKind;
3533
use rustc_middle::ty::{
@@ -1026,33 +1024,6 @@ fn build_struct_type_di_node<'ll, 'tcx>(
10261024
// Tuples
10271025
//=-----------------------------------------------------------------------------
10281026

1029-
/// Returns names of captured upvars for closures and generators.
1030-
///
1031-
/// Here are some examples:
1032-
/// - `name__field1__field2` when the upvar is captured by value.
1033-
/// - `_ref__name__field` when the upvar is captured by reference.
1034-
///
1035-
/// For generators this only contains upvars that are shared by all states.
1036-
fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'_>, def_id: DefId) -> SmallVec<String> {
1037-
let body = tcx.optimized_mir(def_id);
1038-
1039-
body.var_debug_info
1040-
.iter()
1041-
.filter_map(|var| {
1042-
let is_ref = match var.value {
1043-
mir::VarDebugInfoContents::Place(place) if place.local == mir::Local::new(1) => {
1044-
// The projection is either `[.., Field, Deref]` or `[.., Field]`. It
1045-
// implies whether the variable is captured by value or by reference.
1046-
matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref)
1047-
}
1048-
_ => return None,
1049-
};
1050-
let prefix = if is_ref { "_ref__" } else { "" };
1051-
Some(prefix.to_owned() + var.name.as_str())
1052-
})
1053-
.collect()
1054-
}
1055-
10561027
/// Builds the DW_TAG_member debuginfo nodes for the upvars of a closure or generator.
10571028
/// For a generator, this will handle upvars shared by all states.
10581029
fn build_upvar_field_di_nodes<'ll, 'tcx>(
@@ -1083,7 +1054,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
10831054
.all(|&t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t))
10841055
);
10851056

1086-
let capture_names = closure_saved_names_of_captured_variables(cx.tcx, def_id);
1057+
let capture_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
10871058
let layout = cx.layout_of(closure_or_generator_ty);
10881059

10891060
up_var_tys
@@ -1229,43 +1200,6 @@ fn build_union_type_di_node<'ll, 'tcx>(
12291200
)
12301201
}
12311202

1232-
// FIXME(eddyb) maybe precompute this? Right now it's computed once
1233-
// per generator monomorphization, but it doesn't depend on substs.
1234-
fn generator_layout_and_saved_local_names<'tcx>(
1235-
tcx: TyCtxt<'tcx>,
1236-
def_id: DefId,
1237-
) -> (&'tcx GeneratorLayout<'tcx>, IndexVec<mir::GeneratorSavedLocal, Option<Symbol>>) {
1238-
let body = tcx.optimized_mir(def_id);
1239-
let generator_layout = body.generator_layout().unwrap();
1240-
let mut generator_saved_local_names = IndexVec::from_elem(None, &generator_layout.field_tys);
1241-
1242-
let state_arg = mir::Local::new(1);
1243-
for var in &body.var_debug_info {
1244-
let mir::VarDebugInfoContents::Place(place) = &var.value else { continue };
1245-
if place.local != state_arg {
1246-
continue;
1247-
}
1248-
match place.projection[..] {
1249-
[
1250-
// Deref of the `Pin<&mut Self>` state argument.
1251-
mir::ProjectionElem::Field(..),
1252-
mir::ProjectionElem::Deref,
1253-
// Field of a variant of the state.
1254-
mir::ProjectionElem::Downcast(_, variant),
1255-
mir::ProjectionElem::Field(field, _),
1256-
] => {
1257-
let name = &mut generator_saved_local_names
1258-
[generator_layout.variant_fields[variant][field]];
1259-
if name.is_none() {
1260-
name.replace(var.name);
1261-
}
1262-
}
1263-
_ => {}
1264-
}
1265-
}
1266-
(generator_layout, generator_saved_local_names)
1267-
}
1268-
12691203
/// Computes the type parameters for a type, if any, for the given metadata.
12701204
fn build_generic_type_param_di_nodes<'ll, 'tcx>(
12711205
cx: &CodegenCx<'ll, 'tcx>,

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ use crate::{
2222
common::CodegenCx,
2323
debuginfo::{
2424
metadata::{
25-
build_field_di_node, closure_saved_names_of_captured_variables,
25+
build_field_di_node,
2626
enums::{tag_base_type, DiscrResult},
27-
file_metadata, generator_layout_and_saved_local_names, size_and_align_of, type_di_node,
27+
file_metadata, size_and_align_of, type_di_node,
2828
type_map::{self, Stub, UniqueTypeId},
2929
unknown_file_metadata, DINodeCreationResult, SmallVec, NO_GENERICS, NO_SCOPE_METADATA,
3030
UNKNOWN_LINE_NUMBER,
@@ -677,9 +677,9 @@ fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>(
677677
};
678678

679679
let (generator_layout, state_specific_upvar_names) =
680-
generator_layout_and_saved_local_names(cx.tcx, generator_def_id);
680+
cx.tcx.generator_layout_and_saved_local_names(generator_def_id);
681681

682-
let common_upvar_names = closure_saved_names_of_captured_variables(cx.tcx, generator_def_id);
682+
let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(generator_def_id);
683683
let variant_range = generator_substs.variant_range(generator_def_id, cx.tcx);
684684
let variant_count = (variant_range.start.as_u32()..variant_range.end.as_u32()).len();
685685

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ use crate::{
44
common::CodegenCx,
55
debuginfo::{
66
metadata::{
7-
closure_saved_names_of_captured_variables,
87
enums::tag_base_type,
9-
file_metadata, generator_layout_and_saved_local_names, size_and_align_of, type_di_node,
8+
file_metadata, size_and_align_of, type_di_node,
109
type_map::{self, Stub, StubInfo, UniqueTypeId},
1110
unknown_file_metadata, DINodeCreationResult, SmallVec, NO_GENERICS,
1211
UNKNOWN_LINE_NUMBER,
@@ -157,7 +156,7 @@ pub(super) fn build_generator_di_node<'ll, 'tcx>(
157156
),
158157
|cx, generator_type_di_node| {
159158
let (generator_layout, state_specific_upvar_names) =
160-
generator_layout_and_saved_local_names(cx.tcx, generator_def_id);
159+
cx.tcx.generator_layout_and_saved_local_names(generator_def_id);
161160

162161
let Variants::Multiple { tag_encoding: TagEncoding::Direct, ref variants, .. } = generator_type_and_layout.variants else {
163162
bug!(
@@ -167,7 +166,7 @@ pub(super) fn build_generator_di_node<'ll, 'tcx>(
167166
};
168167

169168
let common_upvar_names =
170-
closure_saved_names_of_captured_variables(cx.tcx, generator_def_id);
169+
cx.tcx.closure_saved_names_of_captured_variables(generator_def_id);
171170

172171
// Build variant struct types
173172
let variant_struct_type_di_nodes: SmallVec<_> = variants

compiler/rustc_middle/src/ty/util.rs

+76
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
22
33
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
4+
use crate::mir;
45
use crate::ty::layout::IntegerExt;
56
use crate::ty::{
67
self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
@@ -15,6 +16,7 @@ use rustc_hir as hir;
1516
use rustc_hir::def::{CtorOf, DefKind, Res};
1617
use rustc_hir::def_id::DefId;
1718
use rustc_index::bit_set::GrowableBitSet;
19+
use rustc_index::vec::{Idx, IndexVec};
1820
use rustc_macros::HashStable;
1921
use rustc_span::{sym, DUMMY_SP};
2022
use rustc_target::abi::{Integer, IntegerType, Size, TargetDataLayout};
@@ -692,6 +694,80 @@ impl<'tcx> TyCtxt<'tcx> {
692694
pub fn bound_impl_subject(self, def_id: DefId) -> ty::EarlyBinder<ty::ImplSubject<'tcx>> {
693695
ty::EarlyBinder(self.impl_subject(def_id))
694696
}
697+
698+
/// Returns names of captured upvars for closures and generators.
699+
///
700+
/// Here are some examples:
701+
/// - `name__field1__field2` when the upvar is captured by value.
702+
/// - `_ref__name__field` when the upvar is captured by reference.
703+
///
704+
/// For generators this only contains upvars that are shared by all states.
705+
pub fn closure_saved_names_of_captured_variables(
706+
self,
707+
def_id: DefId,
708+
) -> SmallVec<[String; 16]> {
709+
let body = self.optimized_mir(def_id);
710+
711+
body.var_debug_info
712+
.iter()
713+
.filter_map(|var| {
714+
let is_ref = match var.value {
715+
mir::VarDebugInfoContents::Place(place)
716+
if place.local == mir::Local::new(1) =>
717+
{
718+
// The projection is either `[.., Field, Deref]` or `[.., Field]`. It
719+
// implies whether the variable is captured by value or by reference.
720+
matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref)
721+
}
722+
_ => return None,
723+
};
724+
let prefix = if is_ref { "_ref__" } else { "" };
725+
Some(prefix.to_owned() + var.name.as_str())
726+
})
727+
.collect()
728+
}
729+
730+
// FIXME(eddyb) maybe precompute this? Right now it's computed once
731+
// per generator monomorphization, but it doesn't depend on substs.
732+
pub fn generator_layout_and_saved_local_names(
733+
self,
734+
def_id: DefId,
735+
) -> (
736+
&'tcx ty::GeneratorLayout<'tcx>,
737+
IndexVec<mir::GeneratorSavedLocal, Option<rustc_span::Symbol>>,
738+
) {
739+
let tcx = self;
740+
let body = tcx.optimized_mir(def_id);
741+
let generator_layout = body.generator_layout().unwrap();
742+
let mut generator_saved_local_names =
743+
IndexVec::from_elem(None, &generator_layout.field_tys);
744+
745+
let state_arg = mir::Local::new(1);
746+
for var in &body.var_debug_info {
747+
let mir::VarDebugInfoContents::Place(place) = &var.value else { continue };
748+
if place.local != state_arg {
749+
continue;
750+
}
751+
match place.projection[..] {
752+
[
753+
// Deref of the `Pin<&mut Self>` state argument.
754+
mir::ProjectionElem::Field(..),
755+
mir::ProjectionElem::Deref,
756+
// Field of a variant of the state.
757+
mir::ProjectionElem::Downcast(_, variant),
758+
mir::ProjectionElem::Field(field, _),
759+
] => {
760+
let name = &mut generator_saved_local_names
761+
[generator_layout.variant_fields[variant][field]];
762+
if name.is_none() {
763+
name.replace(var.name);
764+
}
765+
}
766+
_ => {}
767+
}
768+
}
769+
(generator_layout, generator_saved_local_names)
770+
}
695771
}
696772

697773
struct OpaqueTypeExpander<'tcx> {

compiler/rustc_session/src/code_stats.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub enum SizeKind {
1919
Min,
2020
}
2121

22-
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
22+
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
2323
pub struct FieldInfo {
2424
pub name: Symbol,
2525
pub offset: u64,
@@ -33,6 +33,7 @@ pub enum DataTypeKind {
3333
Union,
3434
Enum,
3535
Closure,
36+
Generator,
3637
}
3738

3839
#[derive(PartialEq, Eq, Hash, Debug)]
@@ -114,7 +115,7 @@ impl CodeStats {
114115

115116
let struct_like = match kind {
116117
DataTypeKind::Struct | DataTypeKind::Closure => true,
117-
DataTypeKind::Enum | DataTypeKind::Union => false,
118+
DataTypeKind::Enum | DataTypeKind::Union | DataTypeKind::Generator => false,
118119
};
119120
for (i, variant_info) in variants.into_iter().enumerate() {
120121
let VariantInfo { ref name, kind: _, align: _, size, ref fields } = *variant_info;

0 commit comments

Comments
 (0)