Browse Source

Avoid using equality operator on TypeReferences; Cecil does not guarantee that there is only one instance for a type.

pull/37/head
Daniel Grunwald 15 years ago
parent
commit
f0fc66bff6
  1. 16
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  2. 124
      ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

16
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -699,17 +699,19 @@ namespace Decompiler
if (reqType == null || actualType == reqType) { if (reqType == null || actualType == reqType) {
return expr; return expr;
} else { } else {
bool actualIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(typeSystem, actualType); bool actualIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(actualType);
bool requiredIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(typeSystem, reqType); bool requiredIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(reqType);
if (reqType == typeSystem.Boolean) { if (TypeAnalysis.IsBoolean(reqType)) {
if (TypeAnalysis.IsBoolean(actualType))
return expr;
if (actualIsIntegerOrEnum) { if (actualIsIntegerOrEnum) {
return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, PrimitiveExpression(0, actualType)); return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, PrimitiveExpression(0, actualType));
} else { } else {
return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, new NullReferenceExpression()); return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, new NullReferenceExpression());
} }
} }
if (actualType == typeSystem.Boolean && requiredIsIntegerOrEnum) { if (TypeAnalysis.IsBoolean(actualType) && requiredIsIntegerOrEnum) {
return new ConditionalExpression { return new ConditionalExpression {
Condition = expr, Condition = expr,
TrueExpression = PrimitiveExpression(1, reqType), TrueExpression = PrimitiveExpression(1, reqType),
@ -725,9 +727,9 @@ namespace Decompiler
Expression PrimitiveExpression(long val, TypeReference type) Expression PrimitiveExpression(long val, TypeReference type)
{ {
if (type == typeSystem.Boolean && val == 0) if (TypeAnalysis.IsBoolean(type) && val == 0)
return new Ast.PrimitiveExpression(false); return new Ast.PrimitiveExpression(false);
else if (type == typeSystem.Boolean && val == 1) else if (TypeAnalysis.IsBoolean(type) && val == 1)
return new Ast.PrimitiveExpression(true); return new Ast.PrimitiveExpression(true);
if (type != null) { // cannot rely on type.IsValueType, it's not set for typerefs (but is set for typespecs) if (type != null) { // cannot rely on type.IsValueType, it's not set for typerefs (but is set for typespecs)
TypeDefinition enumDefinition = type.Resolve(); TypeDefinition enumDefinition = type.Resolve();
@ -740,7 +742,7 @@ namespace Decompiler
} }
} }
} }
TypeCode code = TypeAnalysis.GetTypeCode(typeSystem, type); TypeCode code = TypeAnalysis.GetTypeCode(type);
if (code == TypeCode.Object) if (code == TypeCode.Object)
return new Ast.PrimitiveExpression((int)val); return new Ast.PrimitiveExpression((int)val);
else else

124
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -286,7 +286,7 @@ namespace Decompiler
case ILCode.Ldvirtftn: case ILCode.Ldvirtftn:
return typeSystem.IntPtr; return typeSystem.IntPtr;
case ILCode.Ldc_I4: case ILCode.Ldc_I4:
return (IsIntegerOrEnum(expectedType) || expectedType == typeSystem.Boolean) ? expectedType : typeSystem.Int32; return (IsIntegerOrEnum(expectedType) || IsBoolean(expectedType)) ? expectedType : typeSystem.Int32;
case ILCode.Ldc_I8: case ILCode.Ldc_I8:
return (IsIntegerOrEnum(expectedType)) ? expectedType : typeSystem.Int64; return (IsIntegerOrEnum(expectedType)) ? expectedType : typeSystem.Int64;
case ILCode.Ldc_R4: case ILCode.Ldc_R4:
@ -393,7 +393,7 @@ namespace Decompiler
case ILCode.Conv_R8: case ILCode.Conv_R8:
return typeSystem.Double; return typeSystem.Double;
case ILCode.Conv_R_Un: case ILCode.Conv_R_Un:
return (expectedType == typeSystem.Single) ? typeSystem.Single : typeSystem.Double; return (expectedType != null && expectedType.MetadataType == MetadataType.Single) ? typeSystem.Single : typeSystem.Double;
case ILCode.Castclass: case ILCode.Castclass:
case ILCode.Isinst: case ILCode.Isinst:
case ILCode.Unbox_Any: case ILCode.Unbox_Any:
@ -568,22 +568,17 @@ namespace Decompiler
TypeReference TypeWithMoreInformation(TypeReference leftPreferred, TypeReference rightPreferred) TypeReference TypeWithMoreInformation(TypeReference leftPreferred, TypeReference rightPreferred)
{ {
int left = GetInformationAmount(typeSystem, leftPreferred); int left = GetInformationAmount(leftPreferred);
int right = GetInformationAmount(typeSystem, rightPreferred); int right = GetInformationAmount(rightPreferred);
if (left < right) if (left < right)
return rightPreferred; return rightPreferred;
else else
return leftPreferred; return leftPreferred;
} }
int GetInformationAmount(TypeReference type)
{
return GetInformationAmount(typeSystem, type);
}
const int nativeInt = 33; // treat native int as between int32 and int64 const int nativeInt = 33; // treat native int as between int32 and int64
static int GetInformationAmount(TypeSystem typeSystem, TypeReference type) static int GetInformationAmount(TypeReference type)
{ {
if (type == null) if (type == null)
return 0; return 0;
@ -592,40 +587,48 @@ namespace Decompiler
TypeDefinition typeDef = type.Resolve() as TypeDefinition; TypeDefinition typeDef = type.Resolve() as TypeDefinition;
if (typeDef != null && typeDef.IsEnum) { if (typeDef != null && typeDef.IsEnum) {
TypeReference underlyingType = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType; TypeReference underlyingType = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType;
return GetInformationAmount(typeDef.Module.TypeSystem, underlyingType); return GetInformationAmount(underlyingType);
} }
} }
if (type == typeSystem.Boolean) switch (type.MetadataType) {
case MetadataType.Void:
return 0;
case MetadataType.Boolean:
return 1; return 1;
else if (type == typeSystem.Byte || type == typeSystem.SByte) case MetadataType.SByte:
case MetadataType.Byte:
return 8; return 8;
else if (type == typeSystem.Int16 || type == typeSystem.UInt16) case MetadataType.Char:
case MetadataType.Int16:
case MetadataType.UInt16:
return 16; return 16;
else if (type == typeSystem.Int32 || type == typeSystem.UInt32) case MetadataType.Int32:
case MetadataType.UInt32:
case MetadataType.Single:
return 32; return 32;
else if (type == typeSystem.IntPtr || type == typeSystem.UIntPtr) case MetadataType.Int64:
return nativeInt; case MetadataType.UInt64:
else if (type == typeSystem.Int64 || type == typeSystem.UInt64) case MetadataType.Double:
return 64; return 64;
case MetadataType.IntPtr:
case MetadataType.UIntPtr:
return nativeInt;
default:
return 100; // we consider structs/objects to have more information than any primitives return 100; // we consider structs/objects to have more information than any primitives
} }
bool IsIntegerOrEnum(TypeReference type)
{
return IsIntegerOrEnum(typeSystem, type);
} }
public static bool IsIntegerOrEnum(TypeSystem typeSystem, TypeReference type) public static bool IsBoolean(TypeReference type)
{ {
return IsSigned(typeSystem, type) != null; return type != null && type.MetadataType == MetadataType.Boolean;
} }
bool? IsSigned(TypeReference type) public static bool IsIntegerOrEnum(TypeReference type)
{ {
return IsSigned(typeSystem, type); return IsSigned(type) != null;
} }
static bool? IsSigned(TypeSystem typeSystem, TypeReference type) static bool? IsSigned(TypeReference type)
{ {
if (type == null) if (type == null)
return null; return null;
@ -633,47 +636,60 @@ namespace Decompiler
TypeDefinition typeDef = type.Resolve() as TypeDefinition; TypeDefinition typeDef = type.Resolve() as TypeDefinition;
if (typeDef != null && typeDef.IsEnum) { if (typeDef != null && typeDef.IsEnum) {
TypeReference underlyingType = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType; TypeReference underlyingType = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType;
return IsSigned(typeDef.Module.TypeSystem, underlyingType); return IsSigned(underlyingType);
} }
if (type == typeSystem.Byte || type == typeSystem.UInt16 || type == typeSystem.UInt32 || type == typeSystem.UInt64 || type == typeSystem.UIntPtr) switch (type.MetadataType) {
return false; case MetadataType.SByte:
if (type == typeSystem.SByte || type == typeSystem.Int16 || type == typeSystem.Int32 || type == typeSystem.Int64 || type == typeSystem.IntPtr) case MetadataType.Int16:
case MetadataType.Int32:
case MetadataType.Int64:
case MetadataType.IntPtr:
return true; return true;
case MetadataType.Byte:
case MetadataType.UInt16:
case MetadataType.UInt32:
case MetadataType.UInt64:
case MetadataType.UIntPtr:
return false;
default:
return null; return null;
} }
}
public static TypeCode GetTypeCode(TypeSystem typeSystem, TypeReference type) public static TypeCode GetTypeCode(TypeReference type)
{ {
if (type == typeSystem.Boolean) if (type == null)
return TypeCode.Empty;
switch (type.MetadataType) {
case MetadataType.Boolean:
return TypeCode.Boolean; return TypeCode.Boolean;
else if (type == typeSystem.Byte) case MetadataType.Char:
return TypeCode.Byte;
else if (type == typeSystem.Char)
return TypeCode.Char; return TypeCode.Char;
else if (type == typeSystem.Double) case MetadataType.SByte:
return TypeCode.Double; return TypeCode.SByte;
else if (type == typeSystem.Int16) case MetadataType.Byte:
return TypeCode.Byte;
case MetadataType.Int16:
return TypeCode.Int16; return TypeCode.Int16;
else if (type == typeSystem.Int32) case MetadataType.UInt16:
return TypeCode.UInt16;
case MetadataType.Int32:
return TypeCode.Int32; return TypeCode.Int32;
else if (type == typeSystem.Int64) case MetadataType.UInt32:
return TypeCode.UInt32;
case MetadataType.Int64:
return TypeCode.Int64; return TypeCode.Int64;
else if (type == typeSystem.Single) case MetadataType.UInt64:
return TypeCode.UInt64;
case MetadataType.Single:
return TypeCode.Single; return TypeCode.Single;
else if (type == typeSystem.Double) case MetadataType.Double:
return TypeCode.Double; return TypeCode.Double;
else if (type == typeSystem.SByte) case MetadataType.String:
return TypeCode.SByte;
else if (type == typeSystem.UInt16)
return TypeCode.UInt16;
else if (type == typeSystem.UInt32)
return TypeCode.UInt32;
else if (type == typeSystem.UInt64)
return TypeCode.UInt64;
else if (type == typeSystem.String)
return TypeCode.String; return TypeCode.String;
else default:
return TypeCode.Object; return TypeCode.Object;
} }
} }
}
} }

Loading…
Cancel
Save