|
|
@ -373,22 +373,30 @@ namespace ICSharpCode.Decompiler.IL.Transforms |
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
bool MatchLegacySwitchOnStringWithDict(InstructionCollection<ILInstruction> instructions, ref int i) |
|
|
|
bool MatchLegacySwitchOnStringWithDict(InstructionCollection<ILInstruction> instructions, ref int i) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (i < 1) return false; |
|
|
|
// match first block: checking switch-value for null:
|
|
|
|
// match first block: checking switch-value for null
|
|
|
|
// (In some cases, i.e., if switchValueVar is a parameter, the initial store is optional.)
|
|
|
|
// stloc switchValueVar(switchValue)
|
|
|
|
// stloc switchValueVar(switchValue)
|
|
|
|
// if (comp(ldloc switchValueVar == ldnull)) br nullCase
|
|
|
|
// if (comp(ldloc switchValueVar == ldnull)) br nullCase
|
|
|
|
// br nextBlock
|
|
|
|
// br nextBlock
|
|
|
|
if (!(instructions[i].MatchIfInstruction(out var condition, out var exitBlockJump) && |
|
|
|
if (!instructions[i].MatchIfInstruction(out var condition, out var exitBlockJump)) |
|
|
|
instructions[i - 1].MatchStLoc(out var switchValueVar, out var switchValue) && switchValueVar.Type.IsKnownType(KnownTypeCode.String))) |
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (!switchValueVar.IsSingleDefinition) |
|
|
|
if (!(condition.MatchCompEquals(out var left, out var right) && right.MatchLdNull())) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
// The initial store can be omitted in some cases. If there is no initial store or the switch value variable is reused later,
|
|
|
|
|
|
|
|
// we do not inline the "switch value", but create an extra load later on.
|
|
|
|
|
|
|
|
if (i > 0 && instructions[i - 1].MatchStLoc(out var switchValueVar, out var switchValue)) { |
|
|
|
|
|
|
|
if (!(switchValueVar.IsSingleDefinition && ((SemanticHelper.IsPure(switchValue.Flags) && left.Match(switchValue).Success) || left.MatchLdLoc(switchValueVar)))) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (!left.MatchLdLoc(out switchValueVar)) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
switchValue = null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!switchValueVar.Type.IsKnownType(KnownTypeCode.String)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
// either br nullCase or leave container
|
|
|
|
// either br nullCase or leave container
|
|
|
|
if (!exitBlockJump.MatchBranch(out var nullValueCaseBlock) && !exitBlockJump.MatchLeave((BlockContainer)instructions[i].Parent.Parent)) |
|
|
|
if (!exitBlockJump.MatchBranch(out var nullValueCaseBlock) && !exitBlockJump.MatchLeave((BlockContainer)instructions[i].Parent.Parent)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (!(condition.MatchCompEquals(out var left, out var right) && right.MatchLdNull() |
|
|
|
|
|
|
|
&& ((SemanticHelper.IsPure(switchValue.Flags) && left.Match(switchValue).Success) || left.MatchLdLoc(switchValueVar)))) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
var nextBlockJump = instructions.ElementAtOrDefault(i + 1) as Branch; |
|
|
|
var nextBlockJump = instructions.ElementAtOrDefault(i + 1) as Branch; |
|
|
|
if (nextBlockJump == null || nextBlockJump.TargetBlock.IncomingEdgeCount != 1) |
|
|
|
if (nextBlockJump == null || nextBlockJump.TargetBlock.IncomingEdgeCount != 1) |
|
|
|
return false; |
|
|
|
return false; |
|
|
@ -475,7 +483,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
bool keepAssignmentBefore = false; |
|
|
|
bool keepAssignmentBefore = false; |
|
|
|
if (switchValueVar.LoadCount > 2) { |
|
|
|
if (switchValueVar.LoadCount > 2 || switchValue == null) { |
|
|
|
switchValue = new LdLoc(switchValueVar); |
|
|
|
switchValue = new LdLoc(switchValueVar); |
|
|
|
keepAssignmentBefore = true; |
|
|
|
keepAssignmentBefore = true; |
|
|
|
} |
|
|
|
} |
|
|
|