Browse Source

Use ILCode instead of Code in type analysis.

pull/37/head
Daniel Grunwald 15 years ago
parent
commit
72bb24167e
  1. 292
      ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

292
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -106,6 +106,7 @@ namespace Decompiler @@ -106,6 +106,7 @@ namespace Decompiler
TypeReference DoInferTypeForExpression(ILExpression expr, TypeReference expectedType, bool forceInferChildren = false)
{
switch (expr.Code) {
#region Logical operators
case ILCode.LogicNot:
if (forceInferChildren) {
InferTypeForExpression(expr.Arguments.Single(), typeSystem.Boolean);
@ -118,10 +119,9 @@ namespace Decompiler @@ -118,10 +119,9 @@ namespace Decompiler
InferTypeForExpression(expr.Arguments[0], typeSystem.Boolean);
}
return typeSystem.Boolean;
}
switch ((Code)expr.Code) {
#endregion
#region Variable load/store
case Code.Stloc:
case ILCode.Stloc:
{
ILVariable v = (ILVariable)expr.Operand;
if (forceInferChildren || v.Type == null) {
@ -131,7 +131,7 @@ namespace Decompiler @@ -131,7 +131,7 @@ namespace Decompiler
}
return v.Type;
}
case Code.Ldloc:
case ILCode.Ldloc:
{
ILVariable v = (ILVariable)expr.Operand;
if (v.Type == null) {
@ -143,20 +143,20 @@ namespace Decompiler @@ -143,20 +143,20 @@ namespace Decompiler
}
return v.Type;
}
case Code.Starg:
case ILCode.Starg:
if (forceInferChildren)
InferTypeForExpression(expr.Arguments.Single(), ((ParameterReference)expr.Operand).ParameterType);
return null;
case Code.Ldarg:
case ILCode.Ldarg:
return ((ParameterReference)expr.Operand).ParameterType;
case Code.Ldloca:
case ILCode.Ldloca:
return new ByReferenceType(((ILVariable)expr.Operand).Type);
case Code.Ldarga:
case ILCode.Ldarga:
return new ByReferenceType(((ParameterReference)expr.Operand).ParameterType);
#endregion
#region Call / NewObj
case Code.Call:
case Code.Callvirt:
case ILCode.Call:
case ILCode.Callvirt:
{
MethodReference method = (MethodReference)expr.Operand;
if (forceInferChildren) {
@ -174,7 +174,7 @@ namespace Decompiler @@ -174,7 +174,7 @@ namespace Decompiler
}
return SubstituteTypeArgs(method.ReturnType, method);
}
case Code.Newobj:
case ILCode.Newobj:
{
MethodReference ctor = (MethodReference)expr.Operand;
if (forceInferChildren) {
@ -186,139 +186,139 @@ namespace Decompiler @@ -186,139 +186,139 @@ namespace Decompiler
}
#endregion
#region Load/Store Fields
case Code.Ldfld:
case ILCode.Ldfld:
if (forceInferChildren)
InferTypeForExpression(expr.Arguments[0], ((FieldReference)expr.Operand).DeclaringType);
return GetFieldType((FieldReference)expr.Operand);
case Code.Ldsfld:
case ILCode.Ldsfld:
return GetFieldType((FieldReference)expr.Operand);
case Code.Ldflda:
case Code.Ldsflda:
case ILCode.Ldflda:
case ILCode.Ldsflda:
return new ByReferenceType(GetFieldType((FieldReference)expr.Operand));
case Code.Stfld:
case ILCode.Stfld:
if (forceInferChildren) {
InferTypeForExpression(expr.Arguments[0], ((FieldReference)expr.Operand).DeclaringType);
InferTypeForExpression(expr.Arguments[1], GetFieldType((FieldReference)expr.Operand));
}
return null;
case Code.Stsfld:
case ILCode.Stsfld:
if (forceInferChildren)
InferTypeForExpression(expr.Arguments[0], GetFieldType((FieldReference)expr.Operand));
return null;
#endregion
#region Reference/Pointer instructions
case Code.Ldind_I:
case Code.Ldind_I1:
case Code.Ldind_I2:
case Code.Ldind_I4:
case Code.Ldind_I8:
case Code.Ldind_U1:
case Code.Ldind_U2:
case Code.Ldind_U4:
case Code.Ldind_R4:
case Code.Ldind_R8:
case Code.Ldind_Ref:
case ILCode.Ldind_I:
case ILCode.Ldind_I1:
case ILCode.Ldind_I2:
case ILCode.Ldind_I4:
case ILCode.Ldind_I8:
case ILCode.Ldind_U1:
case ILCode.Ldind_U2:
case ILCode.Ldind_U4:
case ILCode.Ldind_R4:
case ILCode.Ldind_R8:
case ILCode.Ldind_Ref:
return UnpackPointer(InferTypeForExpression(expr.Arguments[0], null));
case Code.Stind_I1:
case Code.Stind_I2:
case Code.Stind_I4:
case Code.Stind_I8:
case Code.Stind_R4:
case Code.Stind_R8:
case Code.Stind_I:
case Code.Stind_Ref:
case ILCode.Stind_I1:
case ILCode.Stind_I2:
case ILCode.Stind_I4:
case ILCode.Stind_I8:
case ILCode.Stind_R4:
case ILCode.Stind_R8:
case ILCode.Stind_I:
case ILCode.Stind_Ref:
if (forceInferChildren) {
TypeReference elementType = UnpackPointer(InferTypeForExpression(expr.Arguments[0], null));
InferTypeForExpression(expr.Arguments[1], elementType);
}
return null;
case Code.Ldobj:
case ILCode.Ldobj:
return (TypeReference)expr.Operand;
case Code.Stobj:
case ILCode.Stobj:
if (forceInferChildren) {
InferTypeForExpression(expr.Arguments[1], (TypeReference)expr.Operand);
}
return null;
case Code.Initobj:
case ILCode.Initobj:
return null;
case Code.Localloc:
case ILCode.Localloc:
return typeSystem.IntPtr;
#endregion
#region Arithmetic instructions
case Code.Not: // bitwise complement
case Code.Neg:
case ILCode.Not: // bitwise complement
case ILCode.Neg:
return InferTypeForExpression(expr.Arguments.Single(), expectedType);
case Code.Add:
case Code.Sub:
case Code.Mul:
case Code.Or:
case Code.And:
case Code.Xor:
case ILCode.Add:
case ILCode.Sub:
case ILCode.Mul:
case ILCode.Or:
case ILCode.And:
case ILCode.Xor:
return InferArgumentsInBinaryOperator(expr, null);
case Code.Add_Ovf:
case Code.Sub_Ovf:
case Code.Mul_Ovf:
case Code.Div:
case Code.Rem:
case ILCode.Add_Ovf:
case ILCode.Sub_Ovf:
case ILCode.Mul_Ovf:
case ILCode.Div:
case ILCode.Rem:
return InferArgumentsInBinaryOperator(expr, true);
case Code.Add_Ovf_Un:
case Code.Sub_Ovf_Un:
case Code.Mul_Ovf_Un:
case Code.Div_Un:
case Code.Rem_Un:
case ILCode.Add_Ovf_Un:
case ILCode.Sub_Ovf_Un:
case ILCode.Mul_Ovf_Un:
case ILCode.Div_Un:
case ILCode.Rem_Un:
return InferArgumentsInBinaryOperator(expr, false);
case Code.Shl:
case Code.Shr:
case ILCode.Shl:
case ILCode.Shr:
if (forceInferChildren)
InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
return InferTypeForExpression(expr.Arguments[0], typeSystem.Int32);
case Code.Shr_Un:
case ILCode.Shr_Un:
if (forceInferChildren)
InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
return InferTypeForExpression(expr.Arguments[0], typeSystem.UInt32);
#endregion
#region Constant loading instructions
case Code.Ldnull:
case ILCode.Ldnull:
return typeSystem.Object;
case Code.Ldstr:
case ILCode.Ldstr:
return typeSystem.String;
case Code.Ldftn:
case Code.Ldvirtftn:
case ILCode.Ldftn:
case ILCode.Ldvirtftn:
return typeSystem.IntPtr;
case Code.Ldc_I4:
case ILCode.Ldc_I4:
return (IsIntegerOrEnum(expectedType) || expectedType == typeSystem.Boolean) ? expectedType : typeSystem.Int32;
case Code.Ldc_I8:
case ILCode.Ldc_I8:
return (IsIntegerOrEnum(expectedType)) ? expectedType : typeSystem.Int64;
case Code.Ldc_R4:
case ILCode.Ldc_R4:
return typeSystem.Single;
case Code.Ldc_R8:
case ILCode.Ldc_R8:
return typeSystem.Double;
case Code.Ldtoken:
case ILCode.Ldtoken:
if (expr.Operand is TypeReference)
return new TypeReference("System", "RuntimeTypeHandle", module, module, true);
else if (expr.Operand is FieldReference)
return new TypeReference("System", "RuntimeFieldHandle", module, module, true);
else
return new TypeReference("System", "RuntimeMethodHandle", module, module, true);
case Code.Arglist:
case ILCode.Arglist:
return new TypeReference("System", "RuntimeArgumentHandle", module, module, true);
#endregion
#region Array instructions
case Code.Newarr:
case ILCode.Newarr:
if (forceInferChildren)
InferTypeForExpression(expr.Arguments.Single(), typeSystem.Int32);
return new ArrayType((TypeReference)expr.Operand);
case Code.Ldlen:
case ILCode.Ldlen:
return typeSystem.Int32;
case Code.Ldelem_U1:
case Code.Ldelem_U2:
case Code.Ldelem_U4:
case Code.Ldelem_I1:
case Code.Ldelem_I2:
case Code.Ldelem_I4:
case Code.Ldelem_I8:
case Code.Ldelem_I:
case Code.Ldelem_Ref:
case ILCode.Ldelem_U1:
case ILCode.Ldelem_U2:
case ILCode.Ldelem_U4:
case ILCode.Ldelem_I1:
case ILCode.Ldelem_I2:
case ILCode.Ldelem_I4:
case ILCode.Ldelem_I8:
case ILCode.Ldelem_I:
case ILCode.Ldelem_Ref:
{
ArrayType arrayType = InferTypeForExpression(expr.Arguments[0], null) as ArrayType;
if (forceInferChildren) {
@ -327,27 +327,27 @@ namespace Decompiler @@ -327,27 +327,27 @@ namespace Decompiler
}
return arrayType != null ? arrayType.ElementType : null;
}
case Code.Ldelem_Any:
case ILCode.Ldelem_Any:
if (forceInferChildren) {
InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
}
return (TypeReference)expr.Operand;
case Code.Ldelema:
case ILCode.Ldelema:
{
ArrayType arrayType = InferTypeForExpression(expr.Arguments[0], null) as ArrayType;
if (forceInferChildren)
InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
return arrayType != null ? new ByReferenceType(arrayType.ElementType) : null;
}
case Code.Stelem_I:
case Code.Stelem_I1:
case Code.Stelem_I2:
case Code.Stelem_I4:
case Code.Stelem_I8:
case Code.Stelem_R4:
case Code.Stelem_R8:
case Code.Stelem_Ref:
case Code.Stelem_Any:
case ILCode.Stelem_I:
case ILCode.Stelem_I1:
case ILCode.Stelem_I2:
case ILCode.Stelem_I4:
case ILCode.Stelem_I8:
case ILCode.Stelem_R4:
case ILCode.Stelem_R8:
case ILCode.Stelem_Ref:
case ILCode.Stelem_Any:
if (forceInferChildren) {
ArrayType arrayType = InferTypeForExpression(expr.Arguments[0], null) as ArrayType;
InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
@ -358,107 +358,107 @@ namespace Decompiler @@ -358,107 +358,107 @@ namespace Decompiler
return null;
#endregion
#region Conversion instructions
case Code.Conv_I1:
case Code.Conv_Ovf_I1:
case ILCode.Conv_I1:
case ILCode.Conv_Ovf_I1:
return (GetInformationAmount(expectedType) == 8 && IsSigned(expectedType) == true) ? expectedType : typeSystem.SByte;
case Code.Conv_I2:
case Code.Conv_Ovf_I2:
case ILCode.Conv_I2:
case ILCode.Conv_Ovf_I2:
return (GetInformationAmount(expectedType) == 16 && IsSigned(expectedType) == true) ? expectedType : typeSystem.Int16;
case Code.Conv_I4:
case Code.Conv_Ovf_I4:
case ILCode.Conv_I4:
case ILCode.Conv_Ovf_I4:
return (GetInformationAmount(expectedType) == 32 && IsSigned(expectedType) == true) ? expectedType : typeSystem.Int32;
case Code.Conv_I8:
case Code.Conv_Ovf_I8:
case ILCode.Conv_I8:
case ILCode.Conv_Ovf_I8:
return (GetInformationAmount(expectedType) == 64 && IsSigned(expectedType) == true) ? expectedType : typeSystem.Int64;
case Code.Conv_U1:
case Code.Conv_Ovf_U1:
case ILCode.Conv_U1:
case ILCode.Conv_Ovf_U1:
return (GetInformationAmount(expectedType) == 8 && IsSigned(expectedType) == false) ? expectedType : typeSystem.Byte;
case Code.Conv_U2:
case Code.Conv_Ovf_U2:
case ILCode.Conv_U2:
case ILCode.Conv_Ovf_U2:
return (GetInformationAmount(expectedType) == 16 && IsSigned(expectedType) == false) ? expectedType : typeSystem.UInt16;
case Code.Conv_U4:
case Code.Conv_Ovf_U4:
case ILCode.Conv_U4:
case ILCode.Conv_Ovf_U4:
return (GetInformationAmount(expectedType) == 32 && IsSigned(expectedType) == false) ? expectedType : typeSystem.UInt32;
case Code.Conv_U8:
case Code.Conv_Ovf_U8:
case ILCode.Conv_U8:
case ILCode.Conv_Ovf_U8:
return (GetInformationAmount(expectedType) == 64 && IsSigned(expectedType) == false) ? expectedType : typeSystem.UInt64;
case Code.Conv_I:
case Code.Conv_Ovf_I:
case ILCode.Conv_I:
case ILCode.Conv_Ovf_I:
return (GetInformationAmount(expectedType) == nativeInt && IsSigned(expectedType) == true) ? expectedType : typeSystem.IntPtr;
case Code.Conv_U:
case Code.Conv_Ovf_U:
case ILCode.Conv_U:
case ILCode.Conv_Ovf_U:
return (GetInformationAmount(expectedType) == nativeInt && IsSigned(expectedType) == false) ? expectedType : typeSystem.UIntPtr;
case Code.Conv_R4:
case ILCode.Conv_R4:
return typeSystem.Single;
case Code.Conv_R8:
case ILCode.Conv_R8:
return typeSystem.Double;
case Code.Conv_R_Un:
case ILCode.Conv_R_Un:
return (expectedType == typeSystem.Single) ? typeSystem.Single : typeSystem.Double;
case Code.Castclass:
case Code.Isinst:
case Code.Unbox_Any:
case ILCode.Castclass:
case ILCode.Isinst:
case ILCode.Unbox_Any:
return (TypeReference)expr.Operand;
case Code.Box:
case ILCode.Box:
if (forceInferChildren)
InferTypeForExpression(expr.Arguments.Single(), (TypeReference)expr.Operand);
return (TypeReference)expr.Operand;
#endregion
#region Comparison instructions
case Code.Ceq:
case ILCode.Ceq:
if (forceInferChildren)
InferArgumentsInBinaryOperator(expr, null);
return typeSystem.Boolean;
case Code.Clt:
case Code.Cgt:
case ILCode.Clt:
case ILCode.Cgt:
if (forceInferChildren)
InferArgumentsInBinaryOperator(expr, true);
return typeSystem.Boolean;
case Code.Clt_Un:
case Code.Cgt_Un:
case ILCode.Clt_Un:
case ILCode.Cgt_Un:
if (forceInferChildren)
InferArgumentsInBinaryOperator(expr, false);
return typeSystem.Boolean;
#endregion
#region Branch instructions
case Code.Beq:
case Code.Bne_Un:
case ILCode.Beq:
case ILCode.Bne_Un:
if (forceInferChildren)
InferArgumentsInBinaryOperator(expr, null);
return null;
case Code.Brtrue:
case Code.Brfalse:
case ILCode.Brtrue:
case ILCode.Brfalse:
if (forceInferChildren)
InferTypeForExpression(expr.Arguments.Single(), typeSystem.Boolean);
return null;
case Code.Blt:
case Code.Ble:
case Code.Bgt:
case Code.Bge:
case ILCode.Blt:
case ILCode.Ble:
case ILCode.Bgt:
case ILCode.Bge:
if (forceInferChildren)
InferArgumentsInBinaryOperator(expr, true);
return null;
case Code.Blt_Un:
case Code.Ble_Un:
case Code.Bgt_Un:
case Code.Bge_Un:
case ILCode.Blt_Un:
case ILCode.Ble_Un:
case ILCode.Bgt_Un:
case ILCode.Bge_Un:
if (forceInferChildren)
InferArgumentsInBinaryOperator(expr, false);
return null;
case Code.Br:
case Code.Leave:
case Code.Endfinally:
case Code.Switch:
case Code.Throw:
case Code.Rethrow:
case ILCode.Br:
case ILCode.Leave:
case ILCode.Endfinally:
case ILCode.Switch:
case ILCode.Throw:
case ILCode.Rethrow:
return null;
case Code.Ret:
case ILCode.Ret:
if (forceInferChildren && expr.Arguments.Count == 1)
InferTypeForExpression(expr.Arguments[0], context.CurrentMethod.ReturnType);
return null;
#endregion
case Code.Pop:
case ILCode.Pop:
return null;
case Code.Dup:
case ILCode.Dup:
return InferTypeForExpression(expr.Arguments.Single(), expectedType);
default:
Debug.WriteLine("Type Inference: Can't handle " + expr.Code.GetName());

Loading…
Cancel
Save