Browse Source

Do not detect array initializer if element type and store type do not match.

pull/1012/head
Siegfried Pammer 8 years ago
parent
commit
7ad556e0bf
  1. 28
      ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs

28
ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs

@ -67,7 +67,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
} }
if (arrayLength.Length == 1) { if (arrayLength.Length == 1) {
int instructionsToRemove; int instructionsToRemove;
if (HandleSimpleArrayInitializer(body, pos + 1, v, arrayLength[0], out values, out instructionsToRemove)) { if (HandleSimpleArrayInitializer(body, pos + 1, v, elementType, arrayLength[0], out values, out instructionsToRemove)) {
context.Step("HandleSimpleArrayInitializer", inst); context.Step("HandleSimpleArrayInitializer", inst);
var block = new Block(BlockKind.ArrayInitializer); var block = new Block(BlockKind.ArrayInitializer);
var tempStore = context.Function.RegisterVariable(VariableKind.InitializerTarget, v.Type); var tempStore = context.Function.RegisterVariable(VariableKind.InitializerTarget, v.Type);
@ -85,7 +85,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
ILInlining.InlineIfPossible(body, pos, context); ILInlining.InlineIfPossible(body, pos, context);
return true; return true;
} }
if (HandleJaggedArrayInitializer(body, pos + 1, v, arrayLength[0], out ILVariable finalStore, out values, out instructionsToRemove)) { if (HandleJaggedArrayInitializer(body, pos + 1, v, elementType, arrayLength[0], out ILVariable finalStore, out values, out instructionsToRemove)) {
context.Step("HandleJaggedArrayInitializer", inst); context.Step("HandleJaggedArrayInitializer", inst);
var block = new Block(BlockKind.ArrayInitializer); var block = new Block(BlockKind.ArrayInitializer);
var tempStore = context.Function.RegisterVariable(VariableKind.InitializerTarget, v.Type); var tempStore = context.Function.RegisterVariable(VariableKind.InitializerTarget, v.Type);
@ -163,7 +163,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// <summary> /// <summary>
/// Handle simple case where RuntimeHelpers.InitializeArray is not used. /// Handle simple case where RuntimeHelpers.InitializeArray is not used.
/// </summary> /// </summary>
bool HandleSimpleArrayInitializer(Block block, int pos, ILVariable store, int length, out ILInstruction[] values, out int instructionsToRemove) bool HandleSimpleArrayInitializer(Block block, int pos, ILVariable store, IType elementType, int length, out ILInstruction[] values, out int instructionsToRemove)
{ {
instructionsToRemove = 0; instructionsToRemove = 0;
values = null; values = null;
@ -171,12 +171,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
int index = 0; int index = 0;
int elementCount = 0; int elementCount = 0;
for (int i = pos; i < block.Instructions.Count; i++) { for (int i = pos; i < block.Instructions.Count; i++) {
ILInstruction target, value;
IType type;
if (index >= length) if (index >= length)
break; break;
if (!block.Instructions[i].MatchStObj(out target, out value, out type) || value.Descendants.OfType<IInstructionWithVariableOperand>().Any(inst => inst.Variable == store)) if (!block.Instructions[i].MatchStObj(out ILInstruction target, out ILInstruction value, out IType type) || value.Descendants.OfType<IInstructionWithVariableOperand>().Any(inst => inst.Variable == store))
break; break;
if (!type.Equals(elementType))
return false;
var ldelem = target as LdElema; var ldelem = target as LdElema;
if (ldelem == null || !ldelem.Array.MatchLdLoc(store) || ldelem.Indices.Count != 1 || !ldelem.Indices[0].MatchLdcI4(out index)) if (ldelem == null || !ldelem.Array.MatchLdLoc(store) || ldelem.Indices.Count != 1 || !ldelem.Indices[0].MatchLdcI4(out index))
break; break;
@ -190,22 +190,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return elementCount > 0; return elementCount > 0;
} }
bool HandleJaggedArrayInitializer(Block block, int pos, ILVariable store, int length, out ILVariable finalStore, out ILInstruction[] values, out int instructionsToRemove) bool HandleJaggedArrayInitializer(Block block, int pos, ILVariable store, IType elementType, int length, out ILVariable finalStore, out ILInstruction[] values, out int instructionsToRemove)
{ {
instructionsToRemove = 0; instructionsToRemove = 0;
finalStore = null; finalStore = null;
values = new ILInstruction[length]; values = new ILInstruction[length];
ILInstruction initializer; ILInstruction initializer;
IType type;
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
ILVariable temp;
ILInstruction storeLoad;
// 1. Instruction: (optional) temporary copy of store // 1. Instruction: (optional) temporary copy of store
bool hasTemporaryCopy = block.Instructions[pos].MatchStLoc(out temp, out storeLoad) && storeLoad.MatchLdLoc(store); bool hasTemporaryCopy = block.Instructions[pos].MatchStLoc(out ILVariable temp, out ILInstruction storeLoad) && storeLoad.MatchLdLoc(store);
if (hasTemporaryCopy) { if (hasTemporaryCopy) {
if (!MatchJaggedArrayStore(block, pos + 1, temp, i, out initializer)) if (!MatchJaggedArrayStore(block, pos + 1, temp, i, out initializer, out type) || !elementType.Equals(type))
return false; return false;
} else { } else {
if (!MatchJaggedArrayStore(block, pos, store, i, out initializer)) if (!MatchJaggedArrayStore(block, pos, store, i, out initializer, out type) || !elementType.Equals(type))
return false; return false;
} }
values[i] = initializer; values[i] = initializer;
@ -224,13 +224,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true; return true;
} }
bool MatchJaggedArrayStore(Block block, int pos, ILVariable store, int index, out ILInstruction initializer) bool MatchJaggedArrayStore(Block block, int pos, ILVariable store, int index, out ILInstruction initializer, out IType type)
{ {
initializer = null; initializer = null;
type = null;
// 3. Instruction: stobj(ldelema(ldloc temp, ldc.i4 0), ldloc tempArrayLoad) // 3. Instruction: stobj(ldelema(ldloc temp, ldc.i4 0), ldloc tempArrayLoad)
var finalInstruction = block.Instructions.ElementAtOrDefault(pos + 1); var finalInstruction = block.Instructions.ElementAtOrDefault(pos + 1);
ILInstruction tempAccess, tempArrayLoad; ILInstruction tempAccess, tempArrayLoad;
IType type;
ILVariable initializerStore; ILVariable initializerStore;
if (finalInstruction == null || !finalInstruction.MatchStObj(out tempAccess, out tempArrayLoad, out type) || !tempArrayLoad.MatchLdLoc(out initializerStore)) if (finalInstruction == null || !finalInstruction.MatchStObj(out tempAccess, out tempArrayLoad, out type) || !tempArrayLoad.MatchLdLoc(out initializerStore))
return false; return false;

Loading…
Cancel
Save