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. 158
      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

158
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) {
return 1; case MetadataType.Void:
else if (type == typeSystem.Byte || type == typeSystem.SByte) return 0;
return 8; case MetadataType.Boolean:
else if (type == typeSystem.Int16 || type == typeSystem.UInt16) return 1;
return 16; case MetadataType.SByte:
else if (type == typeSystem.Int32 || type == typeSystem.UInt32) case MetadataType.Byte:
return 32; return 8;
else if (type == typeSystem.IntPtr || type == typeSystem.UIntPtr) case MetadataType.Char:
return nativeInt; case MetadataType.Int16:
else if (type == typeSystem.Int64 || type == typeSystem.UInt64) case MetadataType.UInt16:
return 64; return 16;
return 100; // we consider structs/objects to have more information than any primitives case MetadataType.Int32:
} case MetadataType.UInt32:
case MetadataType.Single:
bool IsIntegerOrEnum(TypeReference type) return 32;
{ case MetadataType.Int64:
return IsIntegerOrEnum(typeSystem, type); case MetadataType.UInt64:
case MetadataType.Double:
return 64;
case MetadataType.IntPtr:
case MetadataType.UIntPtr:
return nativeInt;
default:
return 100; // we consider structs/objects to have more information than any primitives
}
} }
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);
}
switch (type.MetadataType) {
case MetadataType.SByte:
case MetadataType.Int16:
case MetadataType.Int32:
case MetadataType.Int64:
case MetadataType.IntPtr:
return true;
case MetadataType.Byte:
case MetadataType.UInt16:
case MetadataType.UInt32:
case MetadataType.UInt64:
case MetadataType.UIntPtr:
return false;
default:
return null;
} }
if (type == typeSystem.Byte || type == typeSystem.UInt16 || type == typeSystem.UInt32 || type == typeSystem.UInt64 || type == typeSystem.UIntPtr)
return false;
if (type == typeSystem.SByte || type == typeSystem.Int16 || type == typeSystem.Int32 || type == typeSystem.Int64 || type == typeSystem.IntPtr)
return true;
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.Boolean; return TypeCode.Empty;
else if (type == typeSystem.Byte) switch (type.MetadataType) {
return TypeCode.Byte; case MetadataType.Boolean:
else if (type == typeSystem.Char) return TypeCode.Boolean;
return TypeCode.Char; case MetadataType.Char:
else if (type == typeSystem.Double) return TypeCode.Char;
return TypeCode.Double; case MetadataType.SByte:
else if (type == typeSystem.Int16) return TypeCode.SByte;
return TypeCode.Int16; case MetadataType.Byte:
else if (type == typeSystem.Int32) return TypeCode.Byte;
return TypeCode.Int32; case MetadataType.Int16:
else if (type == typeSystem.Int64) return TypeCode.Int16;
return TypeCode.Int64; case MetadataType.UInt16:
else if (type == typeSystem.Single) return TypeCode.UInt16;
return TypeCode.Single; case MetadataType.Int32:
else if (type == typeSystem.Double) return TypeCode.Int32;
return TypeCode.Double; case MetadataType.UInt32:
else if (type == typeSystem.SByte) return TypeCode.UInt32;
return TypeCode.SByte; case MetadataType.Int64:
else if (type == typeSystem.UInt16) return TypeCode.Int64;
return TypeCode.UInt16; case MetadataType.UInt64:
else if (type == typeSystem.UInt32) return TypeCode.UInt64;
return TypeCode.UInt32; case MetadataType.Single:
else if (type == typeSystem.UInt64) return TypeCode.Single;
return TypeCode.UInt64; case MetadataType.Double:
else if (type == typeSystem.String) return TypeCode.Double;
return TypeCode.String; case MetadataType.String:
else return TypeCode.String;
return TypeCode.Object; default:
return TypeCode.Object;
}
} }
} }
} }

Loading…
Cancel
Save