|
|
|
@ -385,23 +385,29 @@ namespace ICSharpCode.Decompiler.ILAst
@@ -385,23 +385,29 @@ namespace ICSharpCode.Decompiler.ILAst
|
|
|
|
|
case ILCode.Ldobj: |
|
|
|
|
{ |
|
|
|
|
TypeReference type = (TypeReference)expr.Operand; |
|
|
|
|
if (expectedType != null) { |
|
|
|
|
int infoAmount = GetInformationAmount(expectedType); |
|
|
|
|
var argType = InferTypeForExpression(expr.Arguments[0], null); |
|
|
|
|
if (argType is PointerType || argType is ByReferenceType) { |
|
|
|
|
var elementType = ((TypeSpecification)argType).ElementType; |
|
|
|
|
int infoAmount = GetInformationAmount(elementType); |
|
|
|
|
if (infoAmount == 1 && GetInformationAmount(type) == 8) { |
|
|
|
|
// A bool can be loaded from both bytes and sbytes.
|
|
|
|
|
type = expectedType; |
|
|
|
|
type = elementType; |
|
|
|
|
} |
|
|
|
|
if (infoAmount >= 8 && infoAmount <= 64 && infoAmount == GetInformationAmount(type)) { |
|
|
|
|
// An integer can be loaded as another integer of the same size.
|
|
|
|
|
// For integers smaller than 32 bit, the signs must match (as loading performs sign extension)
|
|
|
|
|
if (infoAmount >= 32 || IsSigned(expectedType) == IsSigned(type)) |
|
|
|
|
type = expectedType; |
|
|
|
|
bool? elementTypeIsSigned = IsSigned(elementType); |
|
|
|
|
bool? typeIsSigned = IsSigned(type); |
|
|
|
|
if (elementTypeIsSigned != null && typeIsSigned != null) { |
|
|
|
|
if (infoAmount >= 32 || elementTypeIsSigned == typeIsSigned) |
|
|
|
|
type = elementType; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (forceInferChildren) { |
|
|
|
|
if (InferTypeForExpression(expr.Arguments[0], new ByReferenceType(type)) is PointerType) |
|
|
|
|
InferTypeForExpression(expr.Arguments[0], new PointerType(type)); |
|
|
|
|
} |
|
|
|
|
if (argType is PointerType) |
|
|
|
|
InferTypeForExpression(expr.Arguments[0], new PointerType(type)); |
|
|
|
|
else |
|
|
|
|
InferTypeForExpression(expr.Arguments[0], new ByReferenceType(type)); |
|
|
|
|
return type; |
|
|
|
|
} |
|
|
|
|
case ILCode.Stobj: |
|
|
|
|