@@ -34,6 +34,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
3434 public class SwitchOnStringTransform : IILTransform
3535 {
3636 ILTransformContext context ;
37+ private readonly SwitchAnalysis analysis = new SwitchAnalysis ( ) ;
3738
3839 public void Run ( ILFunction function , ILTransformContext context )
3940 {
@@ -1191,8 +1192,7 @@ private bool MatchRoslynSwitchOnStringUsingLengthAndChar(InstructionCollection<I
11911192 else
11921193 {
11931194 int length = ( int ) block . Length . Intervals [ 0 ] . Start ;
1194- if ( MatchSwitchOnCharBlock ( block . TargetBlock , length , switchValueVar , out var mapping )
1195- || MatchIfElseOnCharBlock ( block . TargetBlock , length , switchValueVar , out mapping ) )
1195+ if ( MatchSwitchOnCharBlock ( block . TargetBlock , length , switchValueVar , out var mapping ) )
11961196 {
11971197 foreach ( var item in mapping )
11981198 {
@@ -1277,6 +1277,7 @@ bool MatchSwitchOnCharBlock(Block block, int length, ILVariable switchValueVar,
12771277 if ( block . IncomingEdgeCount != 1 )
12781278 return false ;
12791279 SwitchInstruction @switch ;
1280+ List < KeyValuePair < LongSet , ILInstruction > > sections ;
12801281 int index ;
12811282 switch ( block . Instructions . Count )
12821283 {
@@ -1286,6 +1287,7 @@ bool MatchSwitchOnCharBlock(Block block, int length, ILVariable switchValueVar,
12861287 return false ;
12871288 if ( ! MatchGetChars ( @switch . Value , switchValueVar , out index ) )
12881289 return false ;
1290+ sections = @switch . Sections . SelectList ( s => new KeyValuePair < LongSet , ILInstruction > ( s . Labels , s . Body ) ) ;
12891291 break ;
12901292 case 2 :
12911293 if ( ! block . Instructions [ 0 ] . MatchStLoc ( out var charTempVar , out var getCharsCall ) )
@@ -1299,19 +1301,33 @@ bool MatchSwitchOnCharBlock(Block block, int length, ILVariable switchValueVar,
12991301 return false ;
13001302 if ( ! @switch . Value . MatchLdLoc ( charTempVar ) )
13011303 return false ;
1304+ sections = @switch . Sections . SelectList ( s => new KeyValuePair < LongSet , ILInstruction > ( s . Labels , s . Body ) ) ;
13021305 break ;
13031306 default :
1304- return false ;
1307+ if ( ! analysis . AnalyzeBlock ( block ) )
1308+ {
1309+ return false ;
1310+ }
1311+ if ( ! block . Instructions [ 0 ] . MatchStLoc ( out charTempVar , out getCharsCall ) )
1312+ return false ;
1313+ if ( ! MatchGetChars ( getCharsCall , switchValueVar , out index ) )
1314+ return false ;
1315+ if ( index < 0 )
1316+ return false ;
1317+ if ( analysis . SwitchVariable != charTempVar )
1318+ return false ;
1319+ sections = analysis . Sections ;
1320+ break ;
13051321 }
13061322 if ( index >= length )
13071323 return false ;
1308- SwitchSection defaultSection = null ;
1309- foreach ( var section in @switch . Sections )
1324+ bool hasDefaultSection = false ;
1325+ foreach ( var ( labels , body ) in sections )
13101326 {
1311- if ( section . Labels . Count ( ) == 1 )
1327+ if ( labels . Count ( ) == 1 )
13121328 {
1313- char ch = unchecked ( ( char ) section . Labels . Values . Single ( ) ) ;
1314- if ( ! section . Body . MatchBranch ( out var targetBlock ) )
1329+ char ch = unchecked ( ( char ) labels . Values . Single ( ) ) ;
1330+ if ( ! body . MatchBranch ( out var targetBlock ) )
13151331 return false ;
13161332 if ( length == 1 )
13171333 {
@@ -1332,9 +1348,9 @@ bool MatchSwitchOnCharBlock(Block block, int length, ILVariable switchValueVar,
13321348 }
13331349 }
13341350 }
1335- else if ( defaultSection == null )
1351+ else if ( ! hasDefaultSection )
13361352 {
1337- defaultSection = section ;
1353+ hasDefaultSection = true ;
13381354 }
13391355 else
13401356 {
@@ -1344,47 +1360,6 @@ bool MatchSwitchOnCharBlock(Block block, int length, ILVariable switchValueVar,
13441360 return results ? . Count > 0 ;
13451361 }
13461362
1347- bool MatchIfElseOnCharBlock ( Block startOfChainBlock , int length , ILVariable switchValueVar , out List < ( string StringValue , ILInstruction BodyOrLeave ) > results )
1348- {
1349- results = null ;
1350- if ( startOfChainBlock . IncomingEdgeCount != 1 )
1351- return false ;
1352- if ( startOfChainBlock . Instructions . Count != 3 )
1353- return false ;
1354- if ( ! startOfChainBlock . Instructions [ 0 ] . MatchStLoc ( out var charTempVar , out var getCharsCall ) )
1355- return false ;
1356- if ( ! MatchGetChars ( getCharsCall , switchValueVar , out int index ) )
1357- return false ;
1358- if ( index < 0 )
1359- return false ;
1360- if ( index >= length )
1361- return false ;
1362- var currentBlock = startOfChainBlock ;
1363- int offset = 1 ;
1364- while ( true )
1365- {
1366- if ( ! currentBlock . Instructions [ offset ] . MatchIfInstruction ( out var condition , out var gotoHead ) )
1367- break ;
1368- if ( ! condition . MatchCompEquals ( out var left , out var right ) )
1369- break ;
1370- if ( ! left . MatchLdLoc ( charTempVar ) || ! right . MatchLdcI4 ( out int i ) )
1371- break ;
1372- if ( ! currentBlock . Instructions [ offset + 1 ] . MatchBranch ( out var nextBlock ) )
1373- break ;
1374- if ( ! gotoHead . MatchBranch ( out var headBlock ) )
1375- break ;
1376- if ( ! MatchRoslynCaseBlockHead ( headBlock , switchValueVar , out var bodyOrLeave , out var exit , out var stringValue , out _ ) )
1377- break ;
1378- if ( exit != nullCase )
1379- return false ;
1380- results ??= new ( ) ;
1381- results . Add ( ( stringValue , bodyOrLeave ) ) ;
1382- offset = 0 ;
1383- currentBlock = nextBlock ;
1384- }
1385- return true ;
1386- }
1387-
13881363 bool MatchSwitchOnLengthBlock ( ILVariable switchValueVar , Block switchOnLengthBlock , out List < ( LongSet Length , Block TargetBlock ) > blocks )
13891364 {
13901365 blocks = null ;
0 commit comments