Browse Source

Validate code movement performed by IndexRangeTransform.

pull/2069/head
Daniel Grunwald 5 years ago
parent
commit
fe2143b41f
  1. 21
      ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
  2. 15
      ICSharpCode.Decompiler/IL/Transforms/IndexRangeTransform.cs

21
ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

@ -666,24 +666,33 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -666,24 +666,33 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
/// <summary>
/// Gets whether arg can be un-inlined out of stmt.
/// Gets whether 'expressionBeingMoved' can be moved from somewhere before 'stmt' to become the replacement of 'targetLoad'.
/// </summary>
/// <seealso cref="ILInstruction.Extract"/>
internal static bool CanUninline(ILInstruction arg, ILInstruction stmt)
public static bool CanMoveInto(ILInstruction expressionBeingMoved, ILInstruction stmt, ILInstruction targetLoad)
{
Debug.Assert(arg.IsDescendantOf(stmt));
for (ILInstruction inst = arg; inst != stmt; inst = inst.Parent) {
Debug.Assert(targetLoad.IsDescendantOf(stmt));
for (ILInstruction inst = targetLoad; inst != stmt; inst = inst.Parent) {
if (!inst.SlotInfo.CanInlineInto)
return false;
// Check whether re-ordering with predecessors is valid:
int childIndex = inst.ChildIndex;
for (int i = 0; i < childIndex; ++i) {
ILInstruction predecessor = inst.Parent.Children[i];
if (!SemanticHelper.MayReorder(arg, predecessor))
if (!IsSafeForInlineOver(predecessor, expressionBeingMoved))
return false;
}
}
return true;
}
/// <summary>
/// Gets whether arg can be un-inlined out of stmt.
/// </summary>
/// <seealso cref="ILInstruction.Extract"/>
internal static bool CanUninline(ILInstruction arg, ILInstruction stmt)
{
// moving into and moving out-of are equivalent
return CanMoveInto(arg, stmt, arg);
}
}
}

15
ICSharpCode.Decompiler/IL/Transforms/IndexRangeTransform.cs

@ -271,10 +271,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -271,10 +271,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return;
}
if (rangeVar != null) {
if (!MatchIndexFromRange(startIndexKind, startIndexLoad, rangeVar, "get_Start"))
return;
if (!MatchIndexFromRange(endIndexKind, endIndexLoad, rangeVar, "get_End"))
return;
return; // this should only ever happen in the second step (ExtendSlicing)
}
if (!(sliceLengthVar.LoadInstructions.Single().Parent is CallInstruction call))
return;
@ -291,9 +288,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -291,9 +288,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
} else {
if (!call.Arguments[1].MatchLdLoc(startOffsetVar))
return;
if (!ILInlining.CanMoveInto(startOffsetVarInit, block.Instructions[pos], call.Arguments[1]))
return;
}
if (!call.Arguments[2].MatchLdLoc(sliceLengthVar))
return;
if (!ILInlining.CanMoveInto(sliceLengthVarInit, block.Instructions[pos], call.Arguments[2]))
return;
if (!CSharpWillGenerateIndexer(call.Method.DeclaringType, slicing: true))
return;
var specialMethods = new IndexMethods(context.TypeSystem);
@ -385,13 +386,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -385,13 +386,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// holds because we've used containerLengthVar at least once
Debug.Assert(startIndexKind != IndexKind.FromStart || endIndexKind != IndexKind.FromStart);
if (rangeVar != null) {
if (!ILInlining.CanMoveInto(rangeVarInit, block.Instructions[pos], startIndexLoad))
return;
if (!MatchIndexFromRange(startIndexKind, startIndexLoad, rangeVar, "get_Start"))
return;
if (!MatchIndexFromRange(endIndexKind, endIndexLoad, rangeVar, "get_End"))
return;
}
context.Step("Merge containerLengthVar into slicing", slicingCall);
var specialMethods = new IndexMethods(context.TypeSystem);
if (!specialMethods.IsValid)
return;
context.Step("Merge containerLengthVar into slicing", slicingCall);
rangeCtorCall.ReplaceWith(MakeRange(startIndexKind, startIndexLoad, endIndexKind, endIndexLoad, specialMethods));
for (int i = startPos; i < pos; i++) {
slicingCall.AddILRange(block.Instructions[i]);

Loading…
Cancel
Save