diff --git a/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs b/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs
index 0510b8c87..3382d6926 100644
--- a/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs
@@ -27,6 +27,11 @@ namespace ICSharpCode.Decompiler.IL
return OpCode == OpCode.LdcI4 && ((LdcI4)this).Value == val;
}
+ public bool MatchLdcF(double value)
+ {
+ return MatchLdcF(out var v) && v == value;
+ }
+
///
/// Matches either LdcI4 or LdcI8.
///
diff --git a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs
index 1f7d0f232..670e870c8 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs
@@ -207,7 +207,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!exitBlockJump.MatchBranch(out var nullValueCaseBlock))
return false;
- if (!(condition.MatchCompEquals(out var left, out var right) && right.MatchLdNull() && (left.Match(switchValue).Success || left.MatchLdLoc(switchValueVar))))
+ 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;
if (nextBlockJump == null || nextBlockJump.TargetBlock.IncomingEdgeCount != 1)
@@ -311,15 +312,31 @@ namespace ICSharpCode.Decompiler.IL.Transforms
bool ExtractStringValuesFromInitBlock(Block block, out List values, Block targetBlock, IType dictionaryType, IField dictionaryField)
{
values = null;
- if (!(block.Instructions[0].MatchStLoc(out var dictVar, out var newObjDict) &&
- newObjDict is NewObj newObj && newObj.Arguments.Count >= 1 && newObj.Arguments[0].MatchLdcI4(out var valuesLength)))
+ // stloc dictVar(newobj Dictionary..ctor(ldc.i4 valuesLength))
+ // -or-
+ // stloc dictVar(newobj Hashtable..ctor(ldc.i4 capacity, ldc.f loadFactor))
+ if (!(block.Instructions[0].MatchStLoc(out var dictVar, out var newObjDict) && newObjDict is NewObj newObj))
+ return false;
+ if (!newObj.Method.DeclaringType.Equals(dictionaryType))
return false;
+ int valuesLength = 0;
+ if (newObj.Arguments.Count == 2) {
+ if (!newObj.Arguments[0].MatchLdcI4(out valuesLength))
+ return false;
+ if (!newObj.Arguments[1].MatchLdcF(0.5))
+ return false;
+ } else if (newObj.Arguments.Count == 1) {
+ if (!newObj.Arguments[0].MatchLdcI4(out valuesLength))
+ return false;
+ }
values = new List(valuesLength);
int i = 0;
- while (i + 1 < block.Instructions.Count - 2 && MatchAddCall(block.Instructions[i + 1], dictVar, i, out var value)) {
+ while (MatchAddCall(dictionaryType, block.Instructions[i + 1], dictVar, i, out var value)) {
values.Add(value);
i++;
}
+ // final store to compiler-generated variable:
+ // volatile.stobj dictionaryType(ldsflda dictionaryField, ldloc dictVar)
if (!(block.Instructions[i + 1].MatchStObj(out var loadField, out var dictVarLoad, out var dictType) &&
dictType.Equals(dictionaryType) && loadField.MatchLdsFlda(out var dictField) && dictField.Equals(dictionaryField)) &&
dictVarLoad.MatchLdLoc(dictVar))
@@ -332,12 +349,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// -or-
/// call Add(ldloc dictVar, ldstr value, box System.Int32(ldc.i4 index))
///
- bool MatchAddCall(ILInstruction inst, ILVariable dictVar, int index, out string value)
+ bool MatchAddCall(IType dictionaryType, ILInstruction inst, ILVariable dictVar, int index, out string value)
{
value = null;
- return inst is Call c && c.Method.Name == "Add" && c.Arguments.Count == 3 &&
- c.Arguments[0].MatchLdLoc(dictVar) && c.Arguments[1].MatchLdStr(out value) &&
- (c.Arguments[2].MatchLdcI4(index) || (c.Arguments[2].MatchBox(out var arg, out _) && arg.MatchLdcI4(index)));
+ if (!(inst is Call c && c.Method.Name == "Add" && c.Arguments.Count == 3))
+ return false;
+ if (!(c.Arguments[0].MatchLdLoc(dictVar) && c.Arguments[1].MatchLdStr(out value)))
+ return false;
+ if (!(c.Method.DeclaringType.Equals(dictionaryType) && c.Method.IsStatic))
+ return false;
+ return (c.Arguments[2].MatchLdcI4(index) || (c.Arguments[2].MatchBox(out var arg, out _) && arg.MatchLdcI4(index)));
}
bool IsStringToIntDictionary(IType dictionaryType)