Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

-Zprint-type-sizes: print the types of awaitees and unnamed coroutine locals. #122922

Merged
merged 1 commit into from
Mar 23, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions compiler/rustc_session/src/code_stats.rs
Original file line number Diff line number Diff line change
@@ -44,6 +44,10 @@ pub struct FieldInfo {
pub offset: u64,
pub size: u64,
pub align: u64,
/// Name of the type of this field.
/// Present only if the creator thought that this would be important for identifying the field,
/// typically because the field name is uninformative.
pub type_name: Option<Symbol>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub type_name: Option<Symbol>,
pub type_name: Option<Ty<'tcx>>,

Copy link
Contributor Author

@kpreid kpreid Mar 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Ty we have when constructing FieldInfo is a rustc_middle::ty::Ty. rustc_session, the crate containing FieldInfo, is a dependency of rustc_middle, so that would create a dependency cycle. What do you propose we do about that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh lol

We could use a hook (compiler/rustc_middle/src/hooks/mod.rs) and pull the print_type_sizes + FieldInfo out of rustc_session and down into rustc_ty_utils?

That would have the added benefit of making the layout and the size printing code live together.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well hm. CodeStats still lives in Session. I wonder if there's anywhere global this can live while also being mutable. Oh well, probably too much work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

global mutable state... 🙀

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's already global mutable state for the record lol

Fixing this would probably just be uplifting it from Session to GlobalCtxt

}

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
@@ -192,7 +196,7 @@ impl CodeStats {
fields.sort_by_key(|f| (f.offset, f.size));

for field in fields {
let FieldInfo { kind, ref name, offset, size, align } = field;
let FieldInfo { kind, ref name, offset, size, align, type_name } = field;

if offset > min_offset {
let pad = offset - min_offset;
@@ -201,21 +205,27 @@ impl CodeStats {

if offset < min_offset {
// If this happens it's probably a union.
println!(
print!(
"print-type-size {indent}{kind} `.{name}`: {size} bytes, \
offset: {offset} bytes, \
alignment: {align} bytes"
);
} else if info.packed || offset == min_offset {
println!("print-type-size {indent}{kind} `.{name}`: {size} bytes");
print!("print-type-size {indent}{kind} `.{name}`: {size} bytes");
} else {
// Include field alignment in output only if it caused padding injection
println!(
print!(
"print-type-size {indent}{kind} `.{name}`: {size} bytes, \
alignment: {align} bytes"
);
}

if let Some(type_name) = type_name {
println!(", type: {type_name}");
} else {
println!();
}

min_offset = offset + size;
}
}
10 changes: 9 additions & 1 deletion compiler/rustc_ty_utils/src/layout.rs
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ use rustc_middle::ty::layout::{
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, AdtDef, EarlyBinder, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
use rustc_span::sym;
use rustc_span::symbol::Symbol;
use rustc_target::abi::*;

@@ -1007,6 +1008,7 @@ fn variant_info_for_adt<'tcx>(
offset: offset.bytes(),
size: field_layout.size.bytes(),
align: field_layout.align.abi.bytes(),
type_name: None,
}
})
.collect();
@@ -1090,6 +1092,7 @@ fn variant_info_for_coroutine<'tcx>(
offset: offset.bytes(),
size: field_layout.size.bytes(),
align: field_layout.align.abi.bytes(),
type_name: None,
}
})
.collect();
@@ -1104,19 +1107,24 @@ fn variant_info_for_coroutine<'tcx>(
.iter()
.enumerate()
.map(|(field_idx, local)| {
let field_name = coroutine.field_names[*local];
let field_layout = variant_layout.field(cx, field_idx);
let offset = variant_layout.fields.offset(field_idx);
// The struct is as large as the last field's end
variant_size = variant_size.max(offset + field_layout.size);
FieldInfo {
kind: FieldKind::CoroutineLocal,
name: coroutine.field_names[*local].unwrap_or(Symbol::intern(&format!(
name: field_name.unwrap_or(Symbol::intern(&format!(
".coroutine_field{}",
local.as_usize()
))),
offset: offset.bytes(),
size: field_layout.size.bytes(),
align: field_layout.align.abi.bytes(),
// Include the type name if there is no field name, or if the name is the
// __awaitee placeholder symbol which means a child future being `.await`ed.
type_name: (field_name.is_none() || field_name == Some(sym::__awaitee))
.then(|| Symbol::intern(&field_layout.ty.to_string())),
}
})
.chain(upvar_fields.iter().copied())
14 changes: 7 additions & 7 deletions tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:21:21: 24:2}`:
print-type-size discriminant: 1 bytes
print-type-size variant `Unresumed`: 0 bytes
print-type-size variant `Suspend0`: 3077 bytes
print-type-size local `.__awaitee`: 3077 bytes
print-type-size local `.__awaitee`: 3077 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}
print-type-size variant `Returned`: 0 bytes
print-type-size variant `Panicked`: 0 bytes
print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}>`: 3077 bytes, alignment: 1 bytes
@@ -19,19 +19,19 @@ print-type-size variant `Suspend0`: 2052 bytes
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size padding: 1 bytes
print-type-size local `.fut`: 1025 bytes, alignment: 1 bytes
print-type-size local `..coroutine_field4`: 1 bytes
print-type-size local `.__awaitee`: 1 bytes
print-type-size local `..coroutine_field4`: 1 bytes, type: bool
print-type-size local `.__awaitee`: 1 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}
print-type-size variant `Suspend1`: 3076 bytes
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size padding: 1026 bytes
print-type-size local `..coroutine_field4`: 1 bytes, alignment: 1 bytes
print-type-size local `.__awaitee`: 1025 bytes
print-type-size local `..coroutine_field4`: 1 bytes, alignment: 1 bytes, type: bool
print-type-size local `.__awaitee`: 1025 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37}
print-type-size variant `Suspend2`: 2052 bytes
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size padding: 1 bytes
print-type-size local `.fut`: 1025 bytes, alignment: 1 bytes
print-type-size local `..coroutine_field4`: 1 bytes
print-type-size local `.__awaitee`: 1 bytes
print-type-size local `..coroutine_field4`: 1 bytes, type: bool
print-type-size local `.__awaitee`: 1 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}
print-type-size variant `Returned`: 1025 bytes
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size variant `Panicked`: 1025 bytes
6 changes: 3 additions & 3 deletions tests/ui/async-await/future-sizes/large-arg.stdout
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ print-type-size type: `{async fn body@$DIR/large-arg.rs:6:21: 8:2}`: 3076 bytes,
print-type-size discriminant: 1 bytes
print-type-size variant `Unresumed`: 0 bytes
print-type-size variant `Suspend0`: 3075 bytes
print-type-size local `.__awaitee`: 3075 bytes
print-type-size local `.__awaitee`: 3075 bytes, type: {async fn body@$DIR/large-arg.rs:10:30: 12:2}
print-type-size variant `Returned`: 0 bytes
print-type-size variant `Panicked`: 0 bytes
print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/large-arg.rs:10:30: 12:2}>`: 3075 bytes, alignment: 1 bytes
@@ -17,7 +17,7 @@ print-type-size variant `Unresumed`: 1024 bytes
print-type-size upvar `.t`: 1024 bytes
print-type-size variant `Suspend0`: 3074 bytes
print-type-size upvar `.t`: 1024 bytes
print-type-size local `.__awaitee`: 2050 bytes
print-type-size local `.__awaitee`: 2050 bytes, type: {async fn body@$DIR/large-arg.rs:13:26: 15:2}
print-type-size variant `Returned`: 1024 bytes
print-type-size upvar `.t`: 1024 bytes
print-type-size variant `Panicked`: 1024 bytes
@@ -34,7 +34,7 @@ print-type-size variant `Unresumed`: 1024 bytes
print-type-size upvar `.t`: 1024 bytes
print-type-size variant `Suspend0`: 2049 bytes
print-type-size upvar `.t`: 1024 bytes
print-type-size local `.__awaitee`: 1025 bytes
print-type-size local `.__awaitee`: 1025 bytes, type: {async fn body@$DIR/large-arg.rs:16:26: 18:2}
print-type-size variant `Returned`: 1024 bytes
print-type-size upvar `.t`: 1024 bytes
print-type-size variant `Panicked`: 1024 bytes
2 changes: 1 addition & 1 deletion tests/ui/print_type_sizes/async.stdout
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ print-type-size upvar `.arg`: 8192 bytes
print-type-size variant `Suspend0`: 16385 bytes
print-type-size upvar `.arg`: 8192 bytes
print-type-size local `.arg`: 8192 bytes
print-type-size local `.__awaitee`: 1 bytes
print-type-size local `.__awaitee`: 1 bytes, type: {async fn body@$DIR/async.rs:8:17: 8:19}
print-type-size variant `Returned`: 8192 bytes
print-type-size upvar `.arg`: 8192 bytes
print-type-size variant `Panicked`: 8192 bytes