Browse Source

Use type hints for pointers.

pull/2218/head
Daniel Grunwald 5 years ago
parent
commit
8e10ab2d80
  1. 34
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 4
      ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

34
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -2448,7 +2448,19 @@ namespace ICSharpCode.Decompiler.CSharp
} }
else else
{ {
var translatedTarget = Translate(target, memberDeclaringType); IType targetTypeHint = memberDeclaringType;
if (CallInstruction.ExpectedTypeForThisPointer(memberDeclaringType) == StackType.Ref)
{
if (target.ResultType == StackType.Ref)
{
targetTypeHint = new ByReferenceType(targetTypeHint);
}
else
{
targetTypeHint = new PointerType(targetTypeHint);
}
}
var translatedTarget = Translate(target, targetTypeHint);
if (CallInstruction.ExpectedTypeForThisPointer(memberDeclaringType) == StackType.Ref) if (CallInstruction.ExpectedTypeForThisPointer(memberDeclaringType) == StackType.Ref)
{ {
// When accessing members on value types, ensure we use a reference of the correct type, // When accessing members on value types, ensure we use a reference of the correct type,
@ -2541,6 +2553,14 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitLdObj(LdObj inst, TranslationContext context) protected internal override TranslatedExpression VisitLdObj(LdObj inst, TranslationContext context)
{ {
IType loadType = inst.Type;
bool loadTypeUsedInGeneric = inst.UnalignedPrefix != 0 || inst.Target.ResultType == StackType.Ref;
if (context.TypeHint.Kind != TypeKind.Unknown
&& TypeUtils.IsCompatibleTypeForMemoryAccess(context.TypeHint, loadType)
&& !(loadTypeUsedInGeneric && context.TypeHint.Kind.IsAnyPointer()))
{
loadType = context.TypeHint;
}
if (inst.UnalignedPrefix != 0) if (inst.UnalignedPrefix != 0)
{ {
// Use one of: Unsafe.ReadUnaligned<T>(void*) // Use one of: Unsafe.ReadUnaligned<T>(void*)
@ -2557,12 +2577,12 @@ namespace ICSharpCode.Decompiler.CSharp
return CallUnsafeIntrinsic( return CallUnsafeIntrinsic(
name: "ReadUnaligned", name: "ReadUnaligned",
arguments: new Expression[] { pointer }, arguments: new Expression[] { pointer },
returnType: inst.Type, returnType: loadType,
inst: inst, inst: inst,
typeArguments: new IType[] { inst.Type } typeArguments: new IType[] { loadType }
); );
} }
var result = LdObj(inst.Target, inst.Type); var result = LdObj(inst.Target, loadType);
//if (target.Type.IsSmallIntegerType() && loadType.IsSmallIntegerType() && target.Type.GetSign() != loadType.GetSign()) //if (target.Type.IsSmallIntegerType() && loadType.IsSmallIntegerType() && target.Type.GetSign() != loadType.GetSign())
// return result.ConvertTo(loadType, this); // return result.ConvertTo(loadType, this);
return result.WithILInstruction(inst); return result.WithILInstruction(inst);
@ -2570,7 +2590,8 @@ namespace ICSharpCode.Decompiler.CSharp
ExpressionWithResolveResult LdObj(ILInstruction address, IType loadType) ExpressionWithResolveResult LdObj(ILInstruction address, IType loadType)
{ {
var target = Translate(address); IType addressTypeHint = address.ResultType == StackType.Ref ? new ByReferenceType(loadType) : (IType)new PointerType(loadType);
var target = Translate(address, typeHint: addressTypeHint);
if (TypeUtils.IsCompatiblePointerTypeForMemoryAccess(target.Type, loadType)) if (TypeUtils.IsCompatiblePointerTypeForMemoryAccess(target.Type, loadType))
{ {
ExpressionWithResolveResult result; ExpressionWithResolveResult result;
@ -2637,7 +2658,8 @@ namespace ICSharpCode.Decompiler.CSharp
return UnalignedStObj(inst); return UnalignedStObj(inst);
} }
var pointer = Translate(inst.Target); IType pointerTypeHint = inst.Target.ResultType == StackType.Ref ? new ByReferenceType(inst.Type) : (IType)new PointerType(inst.Type);
var pointer = Translate(inst.Target, typeHint: pointerTypeHint);
TranslatedExpression target; TranslatedExpression target;
TranslatedExpression value = default; TranslatedExpression value = default;
// Cast pointer type if necessary: // Cast pointer type if necessary:

4
ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

@ -330,7 +330,7 @@ namespace ICSharpCode.Decompiler.CSharp
// Everything else can be worked around by casting via long. // Everything else can be worked around by casting via long.
if (!(targetType.IsKnownType(KnownTypeCode.Int64) || targetType.Kind == TypeKind.NInt if (!(targetType.IsKnownType(KnownTypeCode.Int64) || targetType.Kind == TypeKind.NInt
|| (checkForOverflow && targetType.IsKnownType(KnownTypeCode.Int32)) || (checkForOverflow && targetType.IsKnownType(KnownTypeCode.Int32))
|| targetType.Kind.IsAnyPointer())) || targetType.Kind.IsAnyPointer() || targetType.Kind == TypeKind.ByReference))
{ {
var convertVia = expressionBuilder.settings.NativeIntegers ? SpecialType.NInt : compilation.FindType(KnownTypeCode.Int64); var convertVia = expressionBuilder.settings.NativeIntegers ? SpecialType.NInt : compilation.FindType(KnownTypeCode.Int64);
return this.ConvertTo(convertVia, expressionBuilder, checkForOverflow) return this.ConvertTo(convertVia, expressionBuilder, checkForOverflow)
@ -344,7 +344,7 @@ namespace ICSharpCode.Decompiler.CSharp
// Everything else can be worked around by casting via ulong. // Everything else can be worked around by casting via ulong.
if (!(targetType.IsKnownType(KnownTypeCode.UInt64) || targetType.Kind == TypeKind.NUInt if (!(targetType.IsKnownType(KnownTypeCode.UInt64) || targetType.Kind == TypeKind.NUInt
|| (checkForOverflow && targetType.IsKnownType(KnownTypeCode.UInt32)) || (checkForOverflow && targetType.IsKnownType(KnownTypeCode.UInt32))
|| targetType.Kind.IsAnyPointer())) || targetType.Kind.IsAnyPointer() || targetType.Kind == TypeKind.ByReference))
{ {
var convertVia = expressionBuilder.settings.NativeIntegers ? SpecialType.NUInt : compilation.FindType(KnownTypeCode.UInt64); var convertVia = expressionBuilder.settings.NativeIntegers ? SpecialType.NUInt : compilation.FindType(KnownTypeCode.UInt64);
return this.ConvertTo(convertVia, expressionBuilder, checkForOverflow) return this.ConvertTo(convertVia, expressionBuilder, checkForOverflow)

Loading…
Cancel
Save