Browse Source

Prepare for a split of StackType.O into StackType.Obj and StackType.VT: the easy cases

pull/4091/head
Daniel Grunwald 2 weeks ago
parent
commit
c4e181505c
  1. 6
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 36
      ICSharpCode.Decompiler/IL/ILReader.cs
  3. 3
      ICSharpCode.Decompiler/IL/ILTypeExtensions.cs
  4. 20
      ICSharpCode.Decompiler/IL/Instructions.cs
  5. 2
      ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs
  6. 4
      ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs
  7. 8
      ICSharpCode.Decompiler/IL/Instructions/Comp.cs
  8. 2
      ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs
  9. 10
      ICSharpCode.Decompiler/IL/Instructions/Conv.cs
  10. 18
      ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs
  11. 5
      ICSharpCode.Decompiler/IL/Instructions/LdFlda.cs
  12. 8
      ICSharpCode.Decompiler/IL/Instructions/LogicInstructions.cs
  13. 2
      ICSharpCode.Decompiler/IL/Instructions/NullableInstructions.cs
  14. 2
      ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs
  15. 2
      ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs
  16. 4
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
  17. 4
      ICSharpCode.Decompiler/IL/Transforms/PatternMatchingTransform.cs
  18. 2
      ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs
  19. 39
      ICSharpCode.Decompiler/TypeSystem/TypeUtils.cs

6
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1089,7 +1089,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1089,7 +1089,7 @@ namespace ICSharpCode.Decompiler.CSharp
|| !rr.Type.IsKnownType(KnownTypeCode.Boolean))
{
IType targetType;
if (inst.InputType == StackType.O)
if (inst.InputType == StackType.Obj)
{
targetType = compilation.FindType(KnownTypeCode.Object);
}
@ -1227,7 +1227,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1227,7 +1227,7 @@ namespace ICSharpCode.Decompiler.CSharp
left = left.ConvertTo(inputType, this);
right = right.ConvertTo(inputType, this);
}
else if (inst.InputType == StackType.O)
else if (inst.InputType == StackType.Obj)
{
// Unsafe.As<object, UIntPtr>(ref left) op Unsafe.As<object, UIntPtr>(ref right)
// TTo Unsafe.As<TFrom, TTo>(ref TFrom source)
@ -4313,7 +4313,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -4313,7 +4313,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
else
{
Debug.Assert(inst.Value.ResultType == StackType.O);
Debug.Assert(inst.Value.ResultType == StackType.VT);
Debug.Assert(inst.IsLifted);
Debug.Assert(inst.Type == governingType);
}

36
ICSharpCode.Decompiler/IL/ILReader.cs

@ -1122,7 +1122,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1122,7 +1122,7 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Stind_i:
return new StObj(value: Pop(StackType.I), target: PopStObjTarget(), type: compilation.FindType(KnownTypeCode.IntPtr));
case ILOpCode.Stind_ref:
return new StObj(value: Pop(StackType.O), target: PopStObjTarget(), type: compilation.FindType(KnownTypeCode.Object));
return new StObj(value: Pop(StackType.Obj), target: PopStObjTarget(), type: compilation.FindType(KnownTypeCode.Object));
case ILOpCode.Stloc:
case ILOpCode.Stloc_s:
return Stloc(ILParser.DecodeIndex(ref reader, opCode));
@ -1150,7 +1150,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1150,7 +1150,7 @@ namespace ICSharpCode.Decompiler.IL
return Push(new Box(Pop(type.GetStackType()), type));
}
case ILOpCode.Castclass:
return Push(new CastClass(Pop(StackType.O), ReadAndDecodeTypeReference()));
return Push(new CastClass(Pop(StackType.Obj), ReadAndDecodeTypeReference()));
case ILOpCode.Cpobj:
{
var type = ReadAndDecodeTypeReference();
@ -1167,7 +1167,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1167,7 +1167,7 @@ namespace ICSharpCode.Decompiler.IL
{
FlushExpressionStack(); // value-type isinst has inlining restrictions
}
return Push(new IsInst(Pop(StackType.O), type));
return Push(new IsInst(Pop(StackType.Obj), type));
}
case ILOpCode.Ldelem:
return LdElem(ReadAndDecodeTypeReference());
@ -1212,7 +1212,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1212,7 +1212,7 @@ namespace ICSharpCode.Decompiler.IL
return new StObj(value: Pop(field.Type.GetStackType()), target: new LdFlda(PopFieldTarget(field), field) { DelayExceptions = true }, type: field.Type);
}
case ILOpCode.Ldlen:
return Push(new LdLen(StackType.I, Pop(StackType.O)));
return Push(new LdLen(StackType.I, Pop(StackType.Obj)));
case ILOpCode.Ldobj:
return Push(new LdObj(PopPointer(), ReadAndDecodeTypeReference()));
case ILOpCode.Ldsfld:
@ -1330,9 +1330,13 @@ namespace ICSharpCode.Decompiler.IL @@ -1330,9 +1330,13 @@ namespace ICSharpCode.Decompiler.IL
{
v2.Name = $"S_{variables.Count - 1}";
}
if (v1 != v2 && !v1.Type.Equals(v2.Type) && !v2.Type.CannotBeReconstructedFromStackType())
Debug.Assert(v1.StackType == v2.StackType);
// When branches with unequal types are merged, go back to the raw stack type,
// to ensure that the variable can accept all possible values across all branches.
// Exception: don't do this for value types, as FindType(stackType) wouldn't work for them.
if (v1 != v2 && !v1.Type.Equals(v2.Type) && !(v2.StackType == StackType.O && v2.Type.IsReferenceType != true))
{
v2.Type = compilation.FindType(v1.StackType);
v2.Type = compilation.FindType(v2.StackType);
}
return v2;
}
@ -1464,7 +1468,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1464,7 +1468,7 @@ namespace ICSharpCode.Decompiler.IL
else if (expectedType == StackType.Ref)
{
// implicitly start GC tracking / object to interior
if (!inst.ResultType.IsIntegerType() && inst.ResultType != StackType.O)
if (!inst.ResultType.IsIntegerType() && inst.ResultType != StackType.Obj)
{
// We also handle the invalid to-ref cases here because the else case
// below uses expectedType.ToKnownTypeCode(), which doesn't work for Ref.
@ -1533,13 +1537,13 @@ namespace ICSharpCode.Decompiler.IL @@ -1533,13 +1537,13 @@ namespace ICSharpCode.Decompiler.IL
switch (field.DeclaringType.IsReferenceType)
{
case true:
return Pop(StackType.O);
return Pop(StackType.Obj);
case false:
return PopPointer();
default:
// field in unresolved type
var stackType = PeekStackType();
if (stackType == StackType.O || stackType == StackType.Unknown)
if (stackType is StackType.Obj or StackType.VT or StackType.Unknown)
return Pop();
else
return PopPointer();
@ -1554,16 +1558,16 @@ namespace ICSharpCode.Decompiler.IL @@ -1554,16 +1558,16 @@ namespace ICSharpCode.Decompiler.IL
switch (field.DeclaringType.IsReferenceType)
{
case true:
return Pop(StackType.O);
return Pop(StackType.Obj);
case false:
// field of value type: ldfld can handle temporaries
if (PeekStackType() == StackType.O || PeekStackType() == StackType.Unknown)
if (PeekStackType() is StackType.VT or StackType.Unknown)
return new AddressOf(Pop(), field.DeclaringType);
else
return PopPointer();
default:
// field in unresolved type
if (PeekStackType() == StackType.O || PeekStackType() == StackType.Unknown)
if (PeekStackType() is StackType.Obj or StackType.VT or StackType.Unknown)
return Pop();
else
return PopPointer();
@ -1916,7 +1920,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1916,7 +1920,7 @@ namespace ICSharpCode.Decompiler.IL
ILInstruction Comparison(ComparisonKind kind, bool un = false)
{
if (!kind.IsEqualityOrInequality() && PeekStackType() == StackType.O)
if (!kind.IsEqualityOrInequality() && PeekStackType() == StackType.Obj)
{
FlushExpressionStack();
}
@ -1925,7 +1929,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1925,7 +1929,7 @@ namespace ICSharpCode.Decompiler.IL
var left = Pop();
// left will run before right, thus preserving the evaluation order
if ((left.ResultType == StackType.O || left.ResultType == StackType.Ref) && right.ResultType.IsIntegerType())
if ((left.ResultType == StackType.Obj || left.ResultType == StackType.Ref) && right.ResultType.IsIntegerType())
{
// C++/CLI sometimes compares object references with integers.
// Also happens with Ref==I in Unsafe.IsNullRef().
@ -1936,7 +1940,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1936,7 +1940,7 @@ namespace ICSharpCode.Decompiler.IL
}
left = new Conv(left, right.ResultType.ToPrimitiveType(), false, Sign.None);
}
else if ((right.ResultType == StackType.O || right.ResultType == StackType.Ref) && left.ResultType.IsIntegerType())
else if ((right.ResultType == StackType.Obj || right.ResultType == StackType.Ref) && left.ResultType.IsIntegerType())
{
if (left.ResultType == StackType.I4)
{
@ -2031,7 +2035,7 @@ namespace ICSharpCode.Decompiler.IL @@ -2031,7 +2035,7 @@ namespace ICSharpCode.Decompiler.IL
ILInstruction condition = Pop();
switch (condition.ResultType)
{
case StackType.O:
case StackType.Obj:
// introduce explicit comparison with null
condition = new Comp(
negate ? ComparisonKind.Equality : ComparisonKind.Inequality,

3
ICSharpCode.Decompiler/IL/ILTypeExtensions.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Diagnostics;
using System.Linq;
@ -53,7 +54,7 @@ namespace ICSharpCode.Decompiler.IL @@ -53,7 +54,7 @@ namespace ICSharpCode.Decompiler.IL
case PrimitiveType.Unknown:
return StackType.Unknown;
default:
return StackType.O;
return StackType.Obj;
}
}

20
ICSharpCode.Decompiler/IL/Instructions.cs

@ -1147,7 +1147,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1147,7 +1147,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Common instruction for dynamic compound assignments.</summary>
public sealed partial class DynamicCompoundAssign : CompoundAssignmentInstruction
{
public override StackType ResultType => StackType.O;
public override StackType ResultType => StackType.Obj;
public override IType InferType(ICompilation compilation) => SpecialType.Dynamic;
protected override InstructionFlags ComputeFlags()
{
@ -1956,7 +1956,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1956,7 +1956,7 @@ namespace ICSharpCode.Decompiler.IL
internal override void CheckInvariant(ILPhase phase, ICompilation compilation)
{
base.CheckInvariant(phase, compilation);
DebugAssert(onExpression.ResultType == StackType.O);
DebugAssert(onExpression.ResultType == StackType.Obj);
}
}
}
@ -3081,7 +3081,7 @@ namespace ICSharpCode.Decompiler.IL @@ -3081,7 +3081,7 @@ namespace ICSharpCode.Decompiler.IL
this.Value = value;
}
public readonly decimal Value;
public override StackType ResultType => StackType.O;
public override StackType ResultType => StackType.VT;
public override IType InferType(ICompilation compilation) => compilation.FindType(KnownTypeCode.Decimal);
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
@ -4928,7 +4928,7 @@ namespace ICSharpCode.Decompiler.IL @@ -4928,7 +4928,7 @@ namespace ICSharpCode.Decompiler.IL
internal override void CheckInvariant(ILPhase phase, ICompilation compilation)
{
base.CheckInvariant(phase, compilation);
DebugAssert(array.ResultType == StackType.O);
DebugAssert(array.ResultType == StackType.Obj);
}
}
}
@ -5302,7 +5302,7 @@ namespace ICSharpCode.Decompiler.IL @@ -5302,7 +5302,7 @@ namespace ICSharpCode.Decompiler.IL
internal override void CheckInvariant(ILPhase phase, ICompilation compilation)
{
base.CheckInvariant(phase, compilation);
DebugAssert(argument.ResultType == StackType.O);
DebugAssert(argument.ResultType == StackType.Obj);
}
}
}
@ -5392,7 +5392,7 @@ namespace ICSharpCode.Decompiler.IL @@ -5392,7 +5392,7 @@ namespace ICSharpCode.Decompiler.IL
internal override void CheckInvariant(ILPhase phase, ICompilation compilation)
{
base.CheckInvariant(phase, compilation);
DebugAssert(argument.ResultType == StackType.O);
DebugAssert(argument.ResultType == StackType.Obj);
}
}
}
@ -5918,7 +5918,7 @@ namespace ICSharpCode.Decompiler.IL @@ -5918,7 +5918,7 @@ namespace ICSharpCode.Decompiler.IL
internal override void CheckInvariant(ILPhase phase, ICompilation compilation)
{
base.CheckInvariant(phase, compilation);
DebugAssert(argument.ResultType == StackType.O);
DebugAssert(argument.ResultType == StackType.Obj);
}
}
}
@ -6006,7 +6006,7 @@ namespace ICSharpCode.Decompiler.IL @@ -6006,7 +6006,7 @@ namespace ICSharpCode.Decompiler.IL
internal override void CheckInvariant(ILPhase phase, ICompilation compilation)
{
base.CheckInvariant(phase, compilation);
DebugAssert(target.ResultType == StackType.O);
DebugAssert(target.ResultType == StackType.Obj);
}
}
}
@ -6111,7 +6111,7 @@ namespace ICSharpCode.Decompiler.IL @@ -6111,7 +6111,7 @@ namespace ICSharpCode.Decompiler.IL
internal override void CheckInvariant(ILPhase phase, ICompilation compilation)
{
base.CheckInvariant(phase, compilation);
DebugAssert(target.ResultType == StackType.O);
DebugAssert(target.ResultType == StackType.Obj);
}
}
}
@ -6554,7 +6554,7 @@ namespace ICSharpCode.Decompiler.IL @@ -6554,7 +6554,7 @@ namespace ICSharpCode.Decompiler.IL
internal override void CheckInvariant(ILPhase phase, ICompilation compilation)
{
base.CheckInvariant(phase, compilation);
DebugAssert(argument.ResultType == StackType.O);
DebugAssert(argument.ResultType == StackType.Obj);
}
}
}

2
ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs

@ -134,7 +134,7 @@ namespace ICSharpCode.Decompiler.IL @@ -134,7 +134,7 @@ namespace ICSharpCode.Decompiler.IL
public StackType UnderlyingResultType => resultType;
public sealed override StackType ResultType {
get => IsLifted ? StackType.O : resultType;
get => IsLifted ? StackType.VT : resultType;
}
public override IType InferType(ICompilation compilation)

4
ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs

@ -94,7 +94,7 @@ namespace ICSharpCode.Decompiler.IL @@ -94,7 +94,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// Gets the expected stack type for passing the this pointer in a method call.
/// Returns StackType.Ref if constrainedTo is not null,
/// StackType.O for reference types (this pointer passed as object reference),
/// StackType.Obj for reference types (this pointer passed as object reference),
/// and StackType.Ref for type parameters and value types (this pointer passed as managed reference).
///
/// Returns StackType.Unknown if the input type is unknown.
@ -108,7 +108,7 @@ namespace ICSharpCode.Decompiler.IL @@ -108,7 +108,7 @@ namespace ICSharpCode.Decompiler.IL
switch (declaringType.IsReferenceType)
{
case true:
return StackType.O;
return StackType.Obj;
case false:
return StackType.Ref;
default:

8
ICSharpCode.Decompiler/IL/Instructions/Comp.cs

@ -160,7 +160,7 @@ namespace ICSharpCode.Decompiler.IL @@ -160,7 +160,7 @@ namespace ICSharpCode.Decompiler.IL
this.Sign = sign;
}
public override StackType ResultType => LiftingKind == ComparisonLiftingKind.ThreeValuedLogic ? StackType.O : StackType.I4;
public override StackType ResultType => LiftingKind == ComparisonLiftingKind.ThreeValuedLogic ? StackType.VT : StackType.I4;
public override IType InferType(ICompilation compilation)
{
@ -188,8 +188,8 @@ namespace ICSharpCode.Decompiler.IL @@ -188,8 +188,8 @@ namespace ICSharpCode.Decompiler.IL
}
else
{
Debug.Assert(Left.ResultType == InputType || Left.ResultType == StackType.O);
Debug.Assert(Right.ResultType == InputType || Right.ResultType == StackType.O);
Debug.Assert(Left.ResultType == InputType || Left.ResultType == StackType.VT);
Debug.Assert(Right.ResultType == InputType || Right.ResultType == StackType.VT);
}
}
@ -250,7 +250,7 @@ namespace ICSharpCode.Decompiler.IL @@ -250,7 +250,7 @@ namespace ICSharpCode.Decompiler.IL
// Unsafe.As(ref a) op Unsafe.As(ref b), which requires that a and b are variables
// and not expressions. Returning false in those cases prevents inlining.
// However if one of the arguments is LdNull, then we don't need the Unsafe.As trickery, and can always inline.
if (kind.IsEqualityOrInequality() || this.InputType != StackType.O)
if (kind.IsEqualityOrInequality() || this.InputType != StackType.Obj)
{
// OK, won't need Unsafe.As.
return true;

2
ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs

@ -168,7 +168,7 @@ namespace ICSharpCode.Decompiler.IL @@ -168,7 +168,7 @@ namespace ICSharpCode.Decompiler.IL
this.type = type;
this.AddILRange(binary);
Debug.Assert(evalMode == CompoundEvalMode.EvaluatesToNewValue || Operator == BinaryNumericOperator.Add || Operator == BinaryNumericOperator.Sub);
Debug.Assert(this.ResultType == (IsLifted ? StackType.O : UnderlyingResultType));
Debug.Assert(this.ResultType == (IsLifted ? StackType.VT : UnderlyingResultType));
}
/// <summary>

10
ICSharpCode.Decompiler/IL/Instructions/Conv.cs

@ -146,7 +146,7 @@ namespace ICSharpCode.Decompiler.IL @@ -146,7 +146,7 @@ namespace ICSharpCode.Decompiler.IL
/// <remarks>
/// For lifted conversions, corresponds to the underlying target type.
///
/// Target type == PrimitiveType.None can happen for implicit conversions to O in invalid IL.
/// Target type == PrimitiveType.None can happen for implicit conversions to Obj in invalid IL.
/// </remarks>
public readonly PrimitiveType TargetType;
@ -173,7 +173,7 @@ namespace ICSharpCode.Decompiler.IL @@ -173,7 +173,7 @@ namespace ICSharpCode.Decompiler.IL
{
base.CheckInvariant(phase, compilation);
// Debug.Assert(Kind != ConversionKind.Invalid); // invalid conversion can happen with invalid IL/missing references
Debug.Assert(Argument.ResultType == (IsLifted ? StackType.O : InputType));
Debug.Assert(Argument.ResultType == (IsLifted ? StackType.VT : InputType));
Debug.Assert(!(IsLifted && Kind == ConversionKind.StopGCTracking));
}
@ -231,7 +231,7 @@ namespace ICSharpCode.Decompiler.IL @@ -231,7 +231,7 @@ namespace ICSharpCode.Decompiler.IL
case StackType.F8:
return ConversionKind.FloatToInt;
case StackType.Ref:
case StackType.O:
case StackType.Obj:
return ConversionKind.StopGCTracking;
default:
return ConversionKind.Invalid;
@ -253,7 +253,7 @@ namespace ICSharpCode.Decompiler.IL @@ -253,7 +253,7 @@ namespace ICSharpCode.Decompiler.IL
case StackType.F8:
return ConversionKind.FloatToInt;
case StackType.Ref:
case StackType.O:
case StackType.Obj:
return ConversionKind.StopGCTracking;
default:
return ConversionKind.Invalid;
@ -296,7 +296,7 @@ namespace ICSharpCode.Decompiler.IL @@ -296,7 +296,7 @@ namespace ICSharpCode.Decompiler.IL
case StackType.I:
case StackType.I8:
return ConversionKind.StartGCTracking;
case StackType.O:
case StackType.Obj:
return ConversionKind.ObjectInterior;
default:
return ConversionKind.Invalid;

18
ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs

@ -223,7 +223,7 @@ namespace ICSharpCode.Decompiler.IL @@ -223,7 +223,7 @@ namespace ICSharpCode.Decompiler.IL
WriteArgumentList(output, options, Arguments.Zip(ArgumentInfo.Skip(ArgumentInfoOffset)));
}
public override StackType ResultType => StackType.O;
public override StackType ResultType => StackType.Obj;
public override IType InferType(ICompilation compilation) => SpecialType.Dynamic;
@ -259,7 +259,7 @@ namespace ICSharpCode.Decompiler.IL @@ -259,7 +259,7 @@ namespace ICSharpCode.Decompiler.IL
WriteArgumentList(output, options, (Target, TargetArgumentInfo));
}
public override StackType ResultType => StackType.O;
public override StackType ResultType => StackType.Obj;
public override IType InferType(ICompilation compilation) => SpecialType.Dynamic;
public override CSharpArgumentInfo GetArgumentInfoOfChild(int index)
@ -296,7 +296,7 @@ namespace ICSharpCode.Decompiler.IL @@ -296,7 +296,7 @@ namespace ICSharpCode.Decompiler.IL
WriteArgumentList(output, options, (Target, TargetArgumentInfo), (Value, ValueArgumentInfo));
}
public override StackType ResultType => StackType.O;
public override StackType ResultType => StackType.Obj;
public override IType InferType(ICompilation compilation) => SpecialType.Dynamic;
public override CSharpArgumentInfo GetArgumentInfoOfChild(int index)
@ -335,7 +335,7 @@ namespace ICSharpCode.Decompiler.IL @@ -335,7 +335,7 @@ namespace ICSharpCode.Decompiler.IL
WriteArgumentList(output, options, Arguments.Zip(ArgumentInfo));
}
public override StackType ResultType => StackType.O;
public override StackType ResultType => StackType.Obj;
public override IType InferType(ICompilation compilation) => SpecialType.Dynamic;
public override CSharpArgumentInfo GetArgumentInfoOfChild(int index)
@ -368,7 +368,7 @@ namespace ICSharpCode.Decompiler.IL @@ -368,7 +368,7 @@ namespace ICSharpCode.Decompiler.IL
WriteArgumentList(output, options, Arguments.Zip(ArgumentInfo));
}
public override StackType ResultType => StackType.O;
public override StackType ResultType => StackType.Obj;
public override IType InferType(ICompilation compilation) => SpecialType.Dynamic;
public override CSharpArgumentInfo GetArgumentInfoOfChild(int index)
@ -448,7 +448,7 @@ namespace ICSharpCode.Decompiler.IL @@ -448,7 +448,7 @@ namespace ICSharpCode.Decompiler.IL
WriteArgumentList(output, options, (Left, LeftArgumentInfo), (Right, RightArgumentInfo));
}
public override StackType ResultType => StackType.O;
public override StackType ResultType => StackType.Obj;
public override IType InferType(ICompilation compilation) => SpecialType.Dynamic;
public override CSharpArgumentInfo GetArgumentInfoOfChild(int index)
@ -491,7 +491,7 @@ namespace ICSharpCode.Decompiler.IL @@ -491,7 +491,7 @@ namespace ICSharpCode.Decompiler.IL
WriteArgumentList(output, options, (Left, LeftArgumentInfo), (Right, RightArgumentInfo));
}
public override StackType ResultType => StackType.O;
public override StackType ResultType => StackType.Obj;
public override IType InferType(ICompilation compilation) => SpecialType.Dynamic;
protected override InstructionFlags ComputeFlags()
@ -547,7 +547,7 @@ namespace ICSharpCode.Decompiler.IL @@ -547,7 +547,7 @@ namespace ICSharpCode.Decompiler.IL
case ExpressionType.IsTrue:
return StackType.I4; // bool
default:
return StackType.O;
return StackType.Obj; // dynamic
}
}
}
@ -597,7 +597,7 @@ namespace ICSharpCode.Decompiler.IL @@ -597,7 +597,7 @@ namespace ICSharpCode.Decompiler.IL
WriteArgumentList(output, options, Arguments.Zip(ArgumentInfo));
}
public override StackType ResultType => StackType.O;
public override StackType ResultType => StackType.Obj;
public override IType InferType(ICompilation compilation) => SpecialType.Dynamic;
public override CSharpArgumentInfo GetArgumentInfoOfChild(int index)

5
ICSharpCode.Decompiler/IL/Instructions/LdFlda.cs

@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.IL @@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.IL
switch (field.DeclaringType.IsReferenceType)
{
case true:
Debug.Assert(target.ResultType == StackType.O,
Debug.Assert(target.ResultType == StackType.Obj,
"Class fields can only be accessed with an object on the stack");
break;
case false:
@ -40,8 +40,7 @@ namespace ICSharpCode.Decompiler.IL @@ -40,8 +40,7 @@ namespace ICSharpCode.Decompiler.IL
break;
case null:
// field of unresolved type
Debug.Assert(target.ResultType == StackType.O || target.ResultType == StackType.I
|| target.ResultType == StackType.Ref || target.ResultType == StackType.Unknown,
Debug.Assert(target.ResultType is StackType.Obj or StackType.VT or StackType.I or StackType.Ref or StackType.Unknown,
"Field of unresolved type with invalid target");
break;
}

8
ICSharpCode.Decompiler/IL/Instructions/LogicInstructions.cs

@ -31,13 +31,13 @@ namespace ICSharpCode.Decompiler.IL @@ -31,13 +31,13 @@ namespace ICSharpCode.Decompiler.IL
bool ILiftableInstruction.IsLifted => true;
StackType ILiftableInstruction.UnderlyingResultType => StackType.I4;
public override StackType ResultType => StackType.O;
public override StackType ResultType => StackType.VT;
public override IType InferType(ICompilation compilation) => NullableType.Create(compilation, compilation.FindType(KnownTypeCode.Boolean));
internal override void CheckInvariant(ILPhase phase, ICompilation compilation)
{
base.CheckInvariant(phase, compilation);
Debug.Assert(Left.ResultType == StackType.I4 || Left.ResultType == StackType.O);
Debug.Assert(Left.ResultType == StackType.I4 || Left.ResultType == StackType.VT);
}
}
@ -46,13 +46,13 @@ namespace ICSharpCode.Decompiler.IL @@ -46,13 +46,13 @@ namespace ICSharpCode.Decompiler.IL
bool ILiftableInstruction.IsLifted => true;
StackType ILiftableInstruction.UnderlyingResultType => StackType.I4;
public override StackType ResultType => StackType.O;
public override StackType ResultType => StackType.VT;
public override IType InferType(ICompilation compilation) => NullableType.Create(compilation, compilation.FindType(KnownTypeCode.Boolean));
internal override void CheckInvariant(ILPhase phase, ICompilation compilation)
{
base.CheckInvariant(phase, compilation);
Debug.Assert(Left.ResultType == StackType.I4 || Left.ResultType == StackType.O);
Debug.Assert(Left.ResultType == StackType.I4 || Left.ResultType == StackType.VT);
}
}

2
ICSharpCode.Decompiler/IL/Instructions/NullableInstructions.cs

@ -88,7 +88,7 @@ namespace ICSharpCode.Decompiler.IL @@ -88,7 +88,7 @@ namespace ICSharpCode.Decompiler.IL
}
else
{
Debug.Assert(Argument.ResultType == StackType.O, "nullable.unwrap expects nullable type as input");
Debug.Assert(Argument.ResultType == StackType.VT, "nullable.unwrap expects nullable type as input");
}
Debug.Assert(Ancestors.Any(a => a is NullableRewrap));
}

2
ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs

@ -172,7 +172,7 @@ namespace ICSharpCode.Decompiler.IL @@ -172,7 +172,7 @@ namespace ICSharpCode.Decompiler.IL
}
Debug.Assert(sets.SetEquals(LongSet.Universe), "switch does not handle all possible cases");
Debug.Assert(!expectNullSection, "Lifted switch is missing 'case null'");
Debug.Assert(this.IsLifted ? (value.ResultType == StackType.O) : (value.ResultType == StackType.I4 || value.ResultType == StackType.I8));
Debug.Assert(this.IsLifted ? (value.ResultType == StackType.VT) : (value.ResultType == StackType.I4 || value.ResultType == StackType.I8));
}
public SwitchSection GetDefaultSection()

2
ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs

@ -45,7 +45,7 @@ namespace ICSharpCode.Decompiler.IL @@ -45,7 +45,7 @@ namespace ICSharpCode.Decompiler.IL
internal override void CheckInvariant(ILPhase phase, ICompilation compilation)
{
base.CheckInvariant(phase, compilation);
Debug.Assert(IsLifted == (ResultType == StackType.O));
Debug.Assert(IsLifted == (ResultType == StackType.VT));
Debug.Assert(IsLifted || ResultType == UnderlyingResultType);
}

4
ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

@ -152,12 +152,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -152,12 +152,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
inst.Left.ReplaceWith(new LdLen(StackType.I4, array).WithILRange(inst.Left));
inst.Right = rightWithoutConv;
}
else if (inst.Left is Conv conv && conv.TargetType == PrimitiveType.I && conv.Argument.ResultType == StackType.O)
else if (inst.Left is Conv conv && conv.TargetType == PrimitiveType.I && conv.Argument.ResultType == StackType.Obj)
{
// C++/CLI sometimes uses this weird comparison with null:
context.Step("comp(conv o->i (ldloc obj) == conv i4->i <sign extend>(ldc.i4 0))", inst);
// -> comp(ldloc obj == ldnull)
inst.InputType = StackType.O;
inst.InputType = StackType.Obj;
inst.Left = conv.Argument;
inst.Right = new LdNull().WithILRange(inst.Right);
inst.Right.AddILRange(rightWithoutConv);

4
ICSharpCode.Decompiler/IL/Transforms/PatternMatchingTransform.cs

@ -386,7 +386,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -386,7 +386,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
context.Step("Nullable.HasValue check -> null pattern", block);
var nullComp = new Comp(ComparisonKind.Equality, ComparisonLiftingKind.CSharp, StackType.O, Sign.None, varPattern.TestedOperand, new LdNull());
var nullComp = new Comp(ComparisonKind.Equality, ComparisonLiftingKind.CSharp, StackType.VT, Sign.None, varPattern.TestedOperand, new LdNull());
varPattern.ReplaceWith(nullComp);
context.EndStep(nullComp);
block.Instructions.Clear();
@ -398,7 +398,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -398,7 +398,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (varPattern.Variable.AddressCount == 1 && context.Settings.PatternCombinators)
{
context.Step("Nullable.HasValue check -> not null pattern", block);
var notNullComp = new Comp(ComparisonKind.Inequality, ComparisonLiftingKind.CSharp, StackType.O, Sign.None, varPattern.TestedOperand, new LdNull());
var notNullComp = new Comp(ComparisonKind.Inequality, ComparisonLiftingKind.CSharp, StackType.VT, Sign.None, varPattern.TestedOperand, new LdNull());
varPattern.ReplaceWith(notNullComp);
context.EndStep(notNullComp);
block.Instructions.Clear();

2
ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs

@ -1350,7 +1350,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -1350,7 +1350,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
case StackType.F8:
left = new LdcF8(0);
break;
case StackType.O when underlyingType.IsKnownType(KnownTypeCode.Decimal):
case StackType.VT when underlyingType.IsKnownType(KnownTypeCode.Decimal):
left = new LdcDecimal(0);
break;
default:

39
ICSharpCode.Decompiler/TypeSystem/TypeUtils.cs

@ -267,7 +267,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -267,7 +267,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
case TypeKind.Unknown:
if (type.IsReferenceType == true)
{
return StackType.O;
return StackType.Obj;
}
return StackType.Unknown;
case TypeKind.ByReference:
@ -278,17 +278,18 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -278,17 +278,18 @@ namespace ICSharpCode.Decompiler.TypeSystem
case TypeKind.FunctionPointer:
return StackType.I;
case TypeKind.TypeParameter:
// Type parameters are always considered StackType.O, even
// though they might be instantiated with primitive types.
return StackType.O;
// Type parameters are always considered StackType.Obj or StackType.VT,
// even though they might be instantiated with primitive types.
if (type.IsReferenceType == true)
return StackType.Obj;
else
return StackType.VT;
case TypeKind.ModOpt:
case TypeKind.ModReq:
return type.SkipModifiers().GetStackType();
}
ITypeDefinition typeDef = type.GetEnumUnderlyingType().GetDefinition();
if (typeDef == null)
return StackType.O;
switch (typeDef.KnownTypeCode)
switch (typeDef?.KnownTypeCode)
{
case KnownTypeCode.Boolean:
case KnownTypeCode.Char:
@ -312,25 +313,11 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -312,25 +313,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
case KnownTypeCode.UIntPtr:
return StackType.I;
default:
return StackType.O;
}
}
/// <summary>
/// Returns true for types where compilation.FindType(type.GetStackType()) will
/// be completely unsuitable (e.g. lead to miscompilation if the stack type
/// alone is used for when a variable is created for a stack slot):
/// * managed reference types
/// * value types with StackType.O
/// </summary>
public static bool CannotBeReconstructedFromStackType(this IType type)
{
var stackType = type.GetStackType();
if (stackType == StackType.Ref)
{
return true;
if (type.IsReferenceType == true)
return StackType.Obj;
else
return StackType.VT;
}
return stackType == StackType.O && type.IsReferenceType == false;
}
/// <summary>
@ -502,7 +489,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -502,7 +489,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
return KnownTypeCode.Single;
case StackType.F8:
return KnownTypeCode.Double;
case StackType.O:
case StackType.Obj:
return KnownTypeCode.Object;
case StackType.Void:
return KnownTypeCode.Void;

Loading…
Cancel
Save