@@ -11,7 +11,8 @@ pub struct MirPatch<'tcx> {
11
11
new_blocks : Vec < BasicBlockData < ' tcx > > ,
12
12
new_statements : Vec < ( Location , StatementKind < ' tcx > ) > ,
13
13
new_locals : Vec < LocalDecl < ' tcx > > ,
14
- resume_block : BasicBlock ,
14
+ resume_block : Option < BasicBlock > ,
15
+ body_span : Span ,
15
16
next_local : usize ,
16
17
}
17
18
@@ -23,47 +24,36 @@ impl<'tcx> MirPatch<'tcx> {
23
24
new_statements : vec ! [ ] ,
24
25
new_locals : vec ! [ ] ,
25
26
next_local : body. local_decls . len ( ) ,
26
- resume_block : START_BLOCK ,
27
+ resume_block : None ,
28
+ body_span : body. span ,
27
29
} ;
28
30
29
- // make sure the MIR we create has a resume block. It is
30
- // completely legal to convert jumps to the resume block
31
- // to jumps to None, but we occasionally have to add
32
- // instructions just before that.
33
-
34
- let mut resume_block = None ;
35
- let mut resume_stmt_block = None ;
31
+ // Check if we already have a resume block
36
32
for ( bb, block) in body. basic_blocks ( ) . iter_enumerated ( ) {
37
- if let TerminatorKind :: Resume = block. terminator ( ) . kind {
38
- if !block. statements . is_empty ( ) {
39
- assert ! ( resume_stmt_block. is_none( ) ) ;
40
- resume_stmt_block = Some ( bb) ;
41
- } else {
42
- resume_block = Some ( bb) ;
43
- }
33
+ if let TerminatorKind :: Resume = block. terminator ( ) . kind && block. statements . is_empty ( ) {
34
+ result. resume_block = Some ( bb) ;
44
35
break ;
45
36
}
46
37
}
47
- let resume_block = resume_block. unwrap_or_else ( || {
48
- result. new_block ( BasicBlockData {
49
- statements : vec ! [ ] ,
50
- terminator : Some ( Terminator {
51
- source_info : SourceInfo :: outermost ( body. span ) ,
52
- kind : TerminatorKind :: Resume ,
53
- } ) ,
54
- is_cleanup : true ,
55
- } )
56
- } ) ;
57
- result. resume_block = resume_block;
58
- if let Some ( resume_stmt_block) = resume_stmt_block {
59
- result
60
- . patch_terminator ( resume_stmt_block, TerminatorKind :: Goto { target : resume_block } ) ;
61
- }
38
+
62
39
result
63
40
}
64
41
65
- pub fn resume_block ( & self ) -> BasicBlock {
66
- self . resume_block
42
+ pub fn resume_block ( & mut self ) -> BasicBlock {
43
+ if let Some ( bb) = self . resume_block {
44
+ return bb;
45
+ }
46
+
47
+ let bb = self . new_block ( BasicBlockData {
48
+ statements : vec ! [ ] ,
49
+ terminator : Some ( Terminator {
50
+ source_info : SourceInfo :: outermost ( self . body_span ) ,
51
+ kind : TerminatorKind :: Resume ,
52
+ } ) ,
53
+ is_cleanup : true ,
54
+ } ) ;
55
+ self . resume_block = Some ( bb) ;
56
+ bb
67
57
}
68
58
69
59
pub fn is_patched ( & self , bb : BasicBlock ) -> bool {
@@ -138,12 +128,17 @@ impl<'tcx> MirPatch<'tcx> {
138
128
self . new_blocks. len( ) ,
139
129
body. basic_blocks( ) . len( )
140
130
) ;
141
- body. basic_blocks_mut ( ) . extend ( self . new_blocks ) ;
131
+ let bbs = if self . patch_map . is_empty ( ) && self . new_blocks . is_empty ( ) {
132
+ body. basic_blocks . as_mut_preserves_cfg ( )
133
+ } else {
134
+ body. basic_blocks . as_mut ( )
135
+ } ;
136
+ bbs. extend ( self . new_blocks ) ;
142
137
body. local_decls . extend ( self . new_locals ) ;
143
138
for ( src, patch) in self . patch_map . into_iter_enumerated ( ) {
144
139
if let Some ( patch) = patch {
145
140
debug ! ( "MirPatch: patching block {:?}" , src) ;
146
- body [ src] . terminator_mut ( ) . kind = patch;
141
+ bbs [ src] . terminator_mut ( ) . kind = patch;
147
142
}
148
143
}
149
144
0 commit comments