@@ -19,28 +19,33 @@ public class NetworkLogicPruner(ModuleDefinition module)
1919 // TODO: support more cases
2020 // readonly FieldDefinition netMode = module.GetType("Terraria.Main").Field("netMode");
2121
22- public void Prune ( ) {
23-
22+ public void Prune ( params string [ ] skippedTypeFullNames ) {
23+ var skipTypes = skippedTypeFullNames . ToHashSet ( ) ;
2424 foreach ( var type in module . GetAllTypes ( ) ) {
25- foreach ( var method in type . Methods ) {
25+
26+ if ( skipTypes . Contains ( type . FullName ) ) {
27+ continue ;
28+ }
29+
30+ foreach ( var method in type . Methods . ToArray ( ) ) {
2631 if ( ! method . HasBody ) {
2732 continue ;
2833 }
2934
3035 Dictionary < Instruction , Instruction > switchBlockEnd = [ ] ;
3136
32- bool goingOn = false ;
37+ bool anyTargetField = false ;
3338 foreach ( var inst in method . Body . Instructions ) {
3439 if ( inst . Operand is not FieldReference fieldReference ) {
3540 continue ;
3641 }
3742 if ( fieldReference . FullName == dedServ . FullName || fieldReference . FullName == skipMenu . FullName ) {
38- goingOn = true ;
43+ anyTargetField = true ;
3944 break ;
4045 }
4146 }
4247
43- if ( ! goingOn ) {
48+ if ( ! anyTargetField ) {
4449 continue ;
4550 }
4651
@@ -118,12 +123,31 @@ public void Prune() {
118123 indexMap [ method . Body . Instructions [ i ] ] = i ;
119124 }
120125
121- var data = ( - 1 , - 1 ) ;
126+ HashSet < int > visited = [ ] ;
127+ Stack < ( int current , int end1 , int end2 ) > paths = [ ] ;
128+ paths . Push ( ( 0 , - 1 , - 1 ) ) ;
129+
130+ while ( paths . TryPop ( out var pathDetail ) ) {
131+
132+ while ( pathDetail . current < method . Body . Instructions . Count ) {
133+ if ( ! visited . Add ( pathDetail . current ) ) {
134+ break ;
135+ }
136+
137+ var reachableInst = method . Body . Instructions [ pathDetail . current ] ;
138+ CanReachCurrentInstruction ( method . Body , jumpSites , switchBlockEnd , reachableInst , removes , indexMap , ref pathDetail ) ;
139+
140+ if ( pathDetail . end1 == - 1 && pathDetail . end2 == - 1
141+ && reachableInst . Operand is Instruction jumpTo
142+ && pathDetail . current < method . Body . Instructions . Count
143+ && method . Body . Instructions [ pathDetail . current ] != jumpTo
144+ && ! visited . Contains ( indexMap [ jumpTo ] ) ) {
122145
123- for ( int i = 0 ; i < method . Body . Instructions . Count ; ) {
124- var reachableInst = method . Body . Instructions [ i ] ;
125- CanReachCurrentInstruction ( method . Body , jumpSites , switchBlockEnd , reachableInst , removes , indexMap , ref i , ref data ) ;
126- reachableInstructions . Add ( reachableInst ) ;
146+ paths . Push ( ( indexMap [ jumpTo ] , pathDetail . end1 , pathDetail . end2 ) ) ;
147+ }
148+
149+ reachableInstructions . Add ( reachableInst ) ;
150+ }
127151 }
128152
129153 foreach ( var rm in removes ) {
@@ -136,23 +160,25 @@ public void Prune() {
136160 }
137161 }
138162
163+
164+
139165 void CanReachCurrentInstruction (
140166
141167 MethodBody body ,
142168 Dictionary < Instruction , List < Instruction > > jumpSites ,
143169 Dictionary < Instruction , Instruction > switchBlockToEnd ,
144170 Instruction instruction ,
145171 List < Instruction > rm ,
146- Dictionary < Instruction , int > indexMap ,
172+ Dictionary < Instruction , int > inst2Index ,
147173
148- ref int index , ref ( int end_dedServIsTrueBlock , int end_skipMenuIsFalseBlock ) data ) {
174+ ref ( int index , int end_dedServIsTrueBlock , int end_skipMenuIsFalseBlock ) data ) {
149175
150176
151- if ( index > data . end_dedServIsTrueBlock ) {
177+ if ( data . index > data . end_dedServIsTrueBlock ) {
152178 data . end_dedServIsTrueBlock = - 1 ;
153179 }
154180
155- if ( index > data . end_skipMenuIsFalseBlock ) {
181+ if ( data . index > data . end_skipMenuIsFalseBlock ) {
156182 data . end_skipMenuIsFalseBlock = - 1 ;
157183 }
158184
@@ -162,30 +188,30 @@ void CanReachCurrentInstruction(
162188 var nextInst = instruction . Next ;
163189
164190 if ( nextInst . OpCode == OpCodes . Brtrue || nextInst . OpCode == OpCodes . Brtrue_S ) {
165- var jumpTarget = ( Instruction ) nextInst . Operand ;
191+ var jumpTo = ( Instruction ) nextInst . Operand ;
166192
167- var jumpIndex = indexMap [ jumpTarget ] ;
168- index = jumpIndex ;
193+ var jumpToIndex = inst2Index [ jumpTo ] ;
194+ data . index = jumpToIndex ;
169195
170196 if ( switchBlockToEnd . TryGetValue ( instruction , out var blockEnd ) ) {
171197 if ( blockEnd . OpCode != OpCodes . Ret
172198 && blockEnd . OpCode != OpCodes . Br
173199 && blockEnd . OpCode != OpCodes . Br_S ) {
174200 blockEnd = blockEnd . Next ;
175201 }
176- var switchEndIndex = indexMap [ blockEnd ] ;
177- if ( switchEndIndex < jumpIndex ) {
178- index = switchEndIndex ;
202+ var switchEndIndex = inst2Index [ blockEnd ] ;
203+ if ( switchEndIndex < jumpToIndex ) {
204+ data . index = switchEndIndex ;
179205 }
180206 rm . Add ( instruction ) ;
181207 return ;
182208 }
183209
184210 // else block
185211 if ( instruction . Previous is not null && ( instruction . Previous . OpCode == OpCodes . Br || instruction . Previous . OpCode == OpCodes . Br_S ) ) {
186- jumpTarget = ( Instruction ) instruction . Previous . Operand ;
187- jumpIndex = indexMap [ jumpTarget ] ;
188- data . end_dedServIsTrueBlock = jumpIndex ;
212+ jumpTo = ( Instruction ) instruction . Previous . Operand ;
213+ jumpToIndex = inst2Index [ jumpTo ] ;
214+ data . end_dedServIsTrueBlock = jumpToIndex ;
189215 }
190216
191217 rm . Add ( instruction ) ;
@@ -195,7 +221,7 @@ void CanReachCurrentInstruction(
195221 if ( nextInst . OpCode == OpCodes . Brfalse || nextInst . OpCode == OpCodes . Brfalse_S ) {
196222 var jumpTarget = ( Instruction ) nextInst . Operand ;
197223 if ( jumpSites [ jumpTarget ] . Count == 1 ) {
198- data . end_dedServIsTrueBlock = indexMap [ jumpTarget ] ;
224+ data . end_dedServIsTrueBlock = inst2Index [ jumpTarget ] ;
199225 rm . Add ( instruction ) ;
200226 rm . Add ( nextInst ) ;
201227 }
@@ -207,18 +233,18 @@ void CanReachCurrentInstruction(
207233 if ( nextInst . OpCode == OpCodes . Brfalse || nextInst . OpCode == OpCodes . Brfalse_S ) {
208234 var jumpTarget = ( Instruction ) nextInst . Operand ;
209235
210- var jumpIndex = indexMap [ jumpTarget ] ;
211- index = jumpIndex ;
236+ var jumpIndex = inst2Index [ jumpTarget ] ;
237+ data . index = jumpIndex ;
212238
213239 if ( switchBlockToEnd . TryGetValue ( instruction , out var blockEnd ) ) {
214240 if ( blockEnd . OpCode != OpCodes . Ret
215241 && blockEnd . OpCode != OpCodes . Br
216242 && blockEnd . OpCode != OpCodes . Br_S ) {
217243 blockEnd = blockEnd . Next ;
218244 }
219- var switchEndIndex = indexMap [ blockEnd ] ;
245+ var switchEndIndex = inst2Index [ blockEnd ] ;
220246 if ( switchEndIndex < jumpIndex ) {
221- index = switchEndIndex ;
247+ data . index = switchEndIndex ;
222248 }
223249 rm . Add ( instruction ) ;
224250 return ;
@@ -227,7 +253,7 @@ void CanReachCurrentInstruction(
227253 // else block
228254 if ( instruction . Previous is not null && ( instruction . Previous . OpCode == OpCodes . Br || instruction . Previous . OpCode == OpCodes . Br_S ) ) {
229255 jumpTarget = ( Instruction ) instruction . Previous . Operand ;
230- jumpIndex = indexMap [ jumpTarget ] ;
256+ jumpIndex = inst2Index [ jumpTarget ] ;
231257 data . end_skipMenuIsFalseBlock = jumpIndex ;
232258 }
233259
@@ -238,23 +264,23 @@ void CanReachCurrentInstruction(
238264 if ( nextInst . OpCode == OpCodes . Brtrue || nextInst . OpCode == OpCodes . Brtrue_S ) {
239265 var jumpTarget = ( Instruction ) nextInst . Operand ;
240266 if ( jumpSites [ jumpTarget ] . Count == 1 ) {
241- data . end_skipMenuIsFalseBlock = indexMap [ jumpTarget ] ;
267+ data . end_skipMenuIsFalseBlock = inst2Index [ jumpTarget ] ;
242268 rm . Add ( instruction ) ;
243269 rm . Add ( nextInst ) ;
244270 }
245271 }
246272 }
247273 }
248274
249- if ( CheckIsJumpOutOfBlock ( body , instruction , switchBlockToEnd , rm , indexMap , ref index , data . end_dedServIsTrueBlock ) ) {
275+ if ( CheckIsJumpOutOfBlock ( body , instruction , switchBlockToEnd , rm , inst2Index , ref data . index , data . end_dedServIsTrueBlock ) ) {
250276 return ;
251277 }
252278
253- if ( CheckIsJumpOutOfBlock ( body , instruction , switchBlockToEnd , rm , indexMap , ref index , data . end_skipMenuIsFalseBlock ) ) {
279+ if ( CheckIsJumpOutOfBlock ( body , instruction , switchBlockToEnd , rm , inst2Index , ref data . index , data . end_skipMenuIsFalseBlock ) ) {
254280 return ;
255281 }
256282
257- index += 1 ;
283+ data . index += 1 ;
258284
259285 return ;
260286
0 commit comments