Browse Source

Use PopStObjTarget in ILReader, if a call instruction has the same semantics as initobj.

pull/2766/head
Siegfried Pammer 3 years ago
parent
commit
81f575e9ce
  1. 37
      ICSharpCode.Decompiler/IL/ILReader.cs

37
ICSharpCode.Decompiler/IL/ILReader.cs

@ -1391,7 +1391,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1391,7 +1391,7 @@ namespace ICSharpCode.Decompiler.IL
ILInstruction PopStObjTarget()
{
// stobj has a special invariant (StObj.CheckTargetSlot)
// that prohibts inlining LdElema/LdFlda.
// that prohibits inlining LdElema/LdFlda.
if (expressionStack.LastOrDefault() is LdElema or LdFlda)
{
FlushExpressionStack();
@ -1616,22 +1616,12 @@ namespace ICSharpCode.Decompiler.IL @@ -1616,22 +1616,12 @@ namespace ICSharpCode.Decompiler.IL
DecodedInstruction DecodeCall(OpCode opCode)
{
var method = ReadAndDecodeMethodReference();
int firstArgument = (opCode != OpCode.NewObj && !method.IsStatic) ? 1 : 0;
var arguments = new ILInstruction[firstArgument + method.Parameters.Count];
for (int i = method.Parameters.Count - 1; i >= 0; i--)
{
arguments[firstArgument + i] = Pop(method.Parameters[i].Type.GetStackType());
}
if (firstArgument == 1)
{
arguments[0] = Pop(CallInstruction.ExpectedTypeForThisPointer(constrainedPrefix ?? method.DeclaringType));
}
// arguments is in reverse order of the Pop calls, thus
// arguments is now in the correct evaluation order.
ILInstruction[] arguments;
switch (method.DeclaringType.Kind)
{
case TypeKind.Array:
{
arguments = PrepareArguments(firstArgumentIsStObjTarget: false);
var elementType = ((ArrayType)method.DeclaringType).ElementType;
if (opCode == OpCode.NewObj)
return Push(new NewArr(elementType, arguments));
@ -1668,6 +1658,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1668,6 +1658,7 @@ namespace ICSharpCode.Decompiler.IL
// So we represent this call as "stobj Struct(target, newobj Struct.ctor(...))".
// This needs to happen early (not as a transform) because the StObj.TargetSlot has
// restricted inlining (doesn't accept ldflda when exceptions aren't delayed).
arguments = PrepareArguments(firstArgumentIsStObjTarget: true);
var newobj = new NewObj(method);
newobj.ILStackWasEmpty = CurrentStackIsEmpty();
newobj.ConstrainedTo = constrainedPrefix;
@ -1675,6 +1666,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1675,6 +1666,7 @@ namespace ICSharpCode.Decompiler.IL
return new StObj(arguments[0], newobj, method.DeclaringType);
}
default:
arguments = PrepareArguments(firstArgumentIsStObjTarget: false);
var call = CallInstruction.Create(opCode, method);
call.ILStackWasEmpty = CurrentStackIsEmpty();
call.ConstrainedTo = constrainedPrefix;
@ -1683,6 +1675,25 @@ namespace ICSharpCode.Decompiler.IL @@ -1683,6 +1675,25 @@ namespace ICSharpCode.Decompiler.IL
return Push(call);
return call;
}
ILInstruction[] PrepareArguments(bool firstArgumentIsStObjTarget)
{
int firstArgument = (opCode != OpCode.NewObj && !method.IsStatic) ? 1 : 0;
var arguments = new ILInstruction[firstArgument + method.Parameters.Count];
for (int i = method.Parameters.Count - 1; i >= 0; i--)
{
arguments[firstArgument + i] = Pop(method.Parameters[i].Type.GetStackType());
}
if (firstArgument == 1)
{
arguments[0] = firstArgumentIsStObjTarget
? PopStObjTarget()
: Pop(CallInstruction.ExpectedTypeForThisPointer(constrainedPrefix ?? method.DeclaringType));
}
// arguments is in reverse order of the Pop calls, thus
// arguments is now in the correct evaluation order.
return arguments;
}
}
DecodedInstruction DecodeCallIndirect()

Loading…
Cancel
Save