Skip to content

Commit d332a12

Browse files
committed
Change how coroutine layout is dumped in MIR.
1 parent 5878c57 commit d332a12

6 files changed

Lines changed: 131 additions & 126 deletions

compiler/rustc_middle/src/mir/pretty.rs

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::mir::interpret::{
1515
};
1616
use crate::mir::visit::Visitor;
1717
use crate::mir::*;
18+
use crate::ty::CoroutineArgsExt;
1819

1920
const INDENT: &str = " ";
2021
/// Alignment for lining up comments following MIR statements
@@ -185,9 +186,6 @@ impl<'a, 'tcx> MirDumper<'a, 'tcx> {
185186
Some(promoted) => write!(w, "::{promoted:?}`")?,
186187
}
187188
writeln!(w, " {} {}", self.disambiguator, self.pass_name)?;
188-
if let Some(ref layout) = body.coroutine_layout_raw() {
189-
writeln!(w, "/* coroutine_layout = {layout:#?} */")?;
190-
}
191189
writeln!(w)?;
192190
(self.writer.extra_data)(PassWhere::BeforeCFG, w)?;
193191
write_user_type_annotations(self.tcx(), body, w)?;
@@ -429,6 +427,31 @@ fn write_scope_tree(
429427
}
430428
}
431429

430+
// Coroutine debuginfo.
431+
if let Some(layout) = body.coroutine_layout_raw() {
432+
for (field, name) in layout.field_names.iter_enumerated() {
433+
if let Some(name) = name
434+
&& let source_info = layout.field_tys[field].source_info
435+
&& source_info.scope == parent
436+
{
437+
let indented_debug_info =
438+
format!("{0:1$}coroutine debug {2} => {3:?};", INDENT, indent, name, field);
439+
440+
if options.include_extra_comments {
441+
writeln!(
442+
w,
443+
"{0:1$} // in {2}",
444+
indented_debug_info,
445+
ALIGN,
446+
comment(tcx, source_info),
447+
)?;
448+
} else {
449+
writeln!(w, "{indented_debug_info}")?;
450+
}
451+
}
452+
}
453+
}
454+
432455
// Local variable types.
433456
for (local, local_decl) in body.local_decls.iter_enumerated() {
434457
if (1..body.arg_count + 1).contains(&local.index()) {
@@ -530,6 +553,50 @@ impl Debug for VarDebugInfo<'_> {
530553
}
531554
}
532555

556+
fn write_coroutine_layout<'tcx>(
557+
tcx: TyCtxt<'tcx>,
558+
layout: &CoroutineLayout<'_>,
559+
w: &mut dyn io::Write,
560+
options: PrettyPrintMirOptions,
561+
) -> io::Result<()> {
562+
let CoroutineLayout {
563+
field_tys,
564+
field_names: _, // Dumped in scope tree with debug info.
565+
variant_fields,
566+
variant_source_info,
567+
storage_conflicts,
568+
} = layout;
569+
570+
writeln!(w, "{INDENT}coroutine layout {{")?;
571+
572+
for (field, CoroutineSavedTy { ty, source_info, ignore_for_traits }) in
573+
field_tys.iter_enumerated()
574+
{
575+
let ignore_for_traits = if *ignore_for_traits { " (ignored for traits)" } else { "" };
576+
let indented_body = format!("{INDENT}{INDENT}field {field:?}: {ty}{ignore_for_traits};",);
577+
if options.include_extra_comments {
578+
writeln!(w, "{0:ALIGN$} // in {1}", indented_body, comment(tcx, *source_info))?;
579+
} else {
580+
writeln!(w, "{}", indented_body)?;
581+
}
582+
}
583+
584+
writeln!(w, "{INDENT}{INDENT}variant_fields = {{")?;
585+
for (variant, fields) in variant_fields.iter_enumerated() {
586+
let variant_name = ty::CoroutineArgs::variant_name(variant);
587+
let header = format!("{INDENT}{INDENT}{INDENT}{variant_name:9}({variant:?}): {fields:?},");
588+
if options.include_extra_comments {
589+
let source_info = variant_source_info[variant];
590+
writeln!(w, "{0:ALIGN$} // in {1}", header, comment(tcx, source_info))?;
591+
} else {
592+
writeln!(w, "{}", header)?;
593+
}
594+
}
595+
writeln!(w, "{INDENT}{INDENT}}}")?;
596+
writeln!(w, "{INDENT}{INDENT}storage_conflicts = {storage_conflicts:?}")?;
597+
writeln!(w, "{INDENT}}}")
598+
}
599+
533600
/// Write out a human-readable textual representation of the MIR's `fn` type and the types of its
534601
/// local variables (both user-defined bindings and compiler temporaries).
535602
fn write_mir_intro<'tcx>(
@@ -541,6 +608,10 @@ fn write_mir_intro<'tcx>(
541608
write_mir_sig(tcx, body, w)?;
542609
writeln!(w, "{{")?;
543610

611+
if let Some(ref layout) = body.coroutine_layout_raw() {
612+
write_coroutine_layout(tcx, layout, w, options)?;
613+
}
614+
544615
// construct a scope tree and write it out
545616
let mut scope_tree: FxHashMap<SourceScope, Vec<SourceScope>> = Default::default();
546617
for (index, scope_data) in body.source_scopes.iter_enumerated() {

tests/mir-opt/coroutine/async_await.a-{closure#0}.coroutine_resume.0.mir

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
// MIR for `a::{closure#0}` 0 coroutine_resume
2-
/* coroutine_layout = CoroutineLayout {
3-
field_tys: {},
4-
variant_fields: {
5-
Unresumed(0): [],
6-
Returned (1): [],
7-
Panicked (2): [],
8-
},
9-
storage_conflicts: BitMatrix(0x0) {},
10-
} */
112

123
fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> {
4+
coroutine layout {
5+
variant_fields = {
6+
Unresumed(0): [],
7+
Returned (1): [],
8+
Panicked (2): [],
9+
}
10+
storage_conflicts = BitMatrix(0x0) {}
11+
}
1312
debug _task_context => _2;
1413
let mut _0: std::task::Poll<()>;
1514
let mut _3: ();

tests/mir-opt/coroutine/async_await.b-{closure#0}.coroutine_resume.0.mir

Lines changed: 14 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,21 @@
11
// MIR for `b::{closure#0}` 0 coroutine_resume
2-
/* coroutine_layout = CoroutineLayout {
3-
field_tys: {
4-
_s0: CoroutineSavedTy {
5-
ty: Coroutine(
6-
DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
7-
[
8-
(),
9-
std::future::ResumeTy,
10-
(),
11-
(),
12-
(),
13-
],
14-
),
15-
source_info: SourceInfo {
16-
span: $DIR/async_await.rs:27:5: 27:14 (#9),
17-
scope: scope[0],
18-
},
19-
ignore_for_traits: false,
20-
},
21-
_s1: CoroutineSavedTy {
22-
ty: Coroutine(
23-
DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
24-
[
25-
(),
26-
std::future::ResumeTy,
27-
(),
28-
(),
29-
(),
30-
],
31-
),
32-
source_info: SourceInfo {
33-
span: $DIR/async_await.rs:28:5: 28:14 (#11),
34-
scope: scope[0],
35-
},
36-
ignore_for_traits: false,
37-
},
38-
},
39-
variant_fields: {
40-
Unresumed(0): [],
41-
Returned (1): [],
42-
Panicked (2): [],
43-
Suspend0 (3): [_s0],
44-
Suspend1 (4): [_s1],
45-
},
46-
storage_conflicts: BitMatrix(2x2) {
47-
(_s0, _s0),
48-
(_s1, _s1),
49-
},
50-
} */
512

523
fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> Poll<()> {
4+
coroutine layout {
5+
field _s0: {async fn body of a()};
6+
field _s1: {async fn body of a()};
7+
variant_fields = {
8+
Unresumed(0): [],
9+
Returned (1): [],
10+
Panicked (2): [],
11+
Suspend0 (3): [_s0],
12+
Suspend1 (4): [_s1],
13+
}
14+
storage_conflicts = BitMatrix(2x2) {(_s0, _s0), (_s1, _s1)}
15+
}
5316
debug _task_context => _2;
17+
coroutine debug __awaitee => _s0;
18+
coroutine debug __awaitee => _s1;
5419
let mut _0: std::task::Poll<()>;
5520
let _3: ();
5621
let mut _4: {async fn body of a()};

tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.after.mir

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,19 @@
11
// MIR for `main::{closure#0}` after StateTransform
2-
/* coroutine_layout = CoroutineLayout {
3-
field_tys: {
4-
_s0: CoroutineSavedTy {
5-
ty: std::string::String,
6-
source_info: SourceInfo {
7-
span: $DIR/coroutine.rs:19:6: 19:9 (#0),
8-
scope: scope[0],
9-
},
10-
ignore_for_traits: false,
11-
},
12-
},
13-
variant_fields: {
14-
Unresumed(0): [],
15-
Returned (1): [],
16-
Panicked (2): [],
17-
Suspend0 (3): [_s0],
18-
Suspend1 (4): [_s0],
19-
},
20-
storage_conflicts: BitMatrix(1x1) {
21-
(_s0, _s0),
22-
},
23-
} */
242

253
fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:19:5: 19:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> {
4+
coroutine layout {
5+
field _s0: String;
6+
variant_fields = {
7+
Unresumed(0): [],
8+
Returned (1): [],
9+
Panicked (2): [],
10+
Suspend0 (3): [_s0],
11+
Suspend1 (4): [_s0],
12+
}
13+
storage_conflicts = BitMatrix(1x1) {(_s0, _s0)}
14+
}
2615
debug arg => (((*_18) as variant#4).0: std::string::String);
16+
coroutine debug arg => _s0;
2717
let mut _0: std::ops::CoroutineState<(&str, std::string::String, &std::panic::Location<'_>), ()>;
2818
let _3: std::string::String;
2919
let mut _4: (&str, std::string::String, &std::panic::Location<'_>);

tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.after.mir

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,19 @@
11
// MIR for `main::{closure#1}` after StateTransform
2-
/* coroutine_layout = CoroutineLayout {
3-
field_tys: {
4-
_s0: CoroutineSavedTy {
5-
ty: std::string::String,
6-
source_info: SourceInfo {
7-
span: $DIR/coroutine.rs:26:6: 26:9 (#0),
8-
scope: scope[0],
9-
},
10-
ignore_for_traits: false,
11-
},
12-
},
13-
variant_fields: {
14-
Unresumed(0): [],
15-
Returned (1): [],
16-
Panicked (2): [],
17-
Suspend0 (3): [_s0],
18-
Suspend1 (4): [_s0],
19-
},
20-
storage_conflicts: BitMatrix(1x1) {
21-
(_s0, _s0),
22-
},
23-
} */
242

253
fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:26:5: 26:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> {
4+
coroutine layout {
5+
field _s0: String;
6+
variant_fields = {
7+
Unresumed(0): [],
8+
Returned (1): [],
9+
Panicked (2): [],
10+
Suspend0 (3): [_s0],
11+
Suspend1 (4): [_s0],
12+
}
13+
storage_conflicts = BitMatrix(1x1) {(_s0, _s0)}
14+
}
2615
debug arg => (((*_18) as variant#4).0: std::string::String);
16+
coroutine debug arg => _s0;
2717
let mut _0: std::ops::CoroutineState<(&str, std::string::String, &std::panic::Location<'_>), ()>;
2818
let _3: std::string::String;
2919
let mut _4: (&str, std::string::String, &std::panic::Location<'_>);

tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,18 @@
11
// MIR for `main::{closure#0}` 0 coroutine_resume
2-
/* coroutine_layout = CoroutineLayout {
3-
field_tys: {
4-
_s0: CoroutineSavedTy {
5-
ty: HasDrop,
6-
source_info: SourceInfo {
7-
span: $DIR/coroutine_tiny.rs:22:13: 22:15 (#0),
8-
scope: scope[0],
9-
},
10-
ignore_for_traits: false,
11-
},
12-
},
13-
variant_fields: {
14-
Unresumed(0): [],
15-
Returned (1): [],
16-
Panicked (2): [],
17-
Suspend0 (3): [_s0],
18-
},
19-
storage_conflicts: BitMatrix(1x1) {
20-
(_s0, _s0),
21-
},
22-
} */
232

243
fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}>, _2: u8) -> CoroutineState<(), ()> {
4+
coroutine layout {
5+
field _s0: HasDrop;
6+
variant_fields = {
7+
Unresumed(0): [],
8+
Returned (1): [],
9+
Panicked (2): [],
10+
Suspend0 (3): [_s0],
11+
}
12+
storage_conflicts = BitMatrix(1x1) {(_s0, _s0)}
13+
}
2514
debug _x => _2;
15+
coroutine debug _d => _s0;
2616
let mut _0: std::ops::CoroutineState<(), ()>;
2717
let _3: HasDrop;
2818
let mut _4: !;

0 commit comments

Comments
 (0)