diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs index 4ba4af434..8095453ef 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs @@ -150,7 +150,7 @@ namespace System.Runtime.CompilerServices [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static T Read(void* source) { - return *(T*)source; + return Unsafe.Read(source); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -168,7 +168,7 @@ namespace System.Runtime.CompilerServices [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Write(void* destination, T value) { - *(T*)destination = value; + Unsafe.Write(destination, value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -186,13 +186,13 @@ namespace System.Runtime.CompilerServices [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Copy(void* destination, ref T source) { - *(T*)destination = source; + Unsafe.Write(destination, source); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Copy(ref T destination, void* source) { - destination = *(T*)source; + destination = Unsafe.Read(source); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index b03f38b4a..70d39da45 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -2797,6 +2797,17 @@ namespace ICSharpCode.Decompiler.CSharp { target = target.ConvertTo(new ByReferenceType(loadType), this); } + else if (!loadType.IsUnmanagedType(settings.IntroduceUnmanagedConstraint)) + { + // Use: Unsafe.Read(void*) + target = target.ConvertTo(new PointerType(compilation.FindType(KnownTypeCode.Void)), this, allowImplicitConversion: true); + return CallUnsafeIntrinsic( + name: "Read", + arguments: new Expression[] { target }, + returnType: loadType, + typeArguments: new IType[] { loadType } + ); + } else { target = target.ConvertTo(new PointerType(loadType), this); @@ -2815,9 +2826,9 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitStObj(StObj inst, TranslationContext context) { - if (inst.UnalignedPrefix != 0) + if (inst.UnalignedPrefix != 0 || (inst.Target.ResultType != StackType.Ref && !inst.Type.IsUnmanagedType(settings.IntroduceUnmanagedConstraint))) { - return UnalignedStObj(inst); + return StObjViaHelperCall(inst); } IType pointerTypeHint = inst.Target.ResultType == StackType.Ref ? new ByReferenceType(inst.Type) : (IType)new PointerType(inst.Type); @@ -2892,14 +2903,16 @@ namespace ICSharpCode.Decompiler.CSharp } } - private TranslatedExpression UnalignedStObj(StObj inst) + private TranslatedExpression StObjViaHelperCall(StObj inst) { // "unaligned.1; stobj" -> decompile to a call of // Unsafe.WriteUnaligned(void*, T) // or Unsafe.WriteUnaligned(ref byte, T) + // "stobj ManagedType" -> decompile to a call of + // Unsafe.Write(void*, T) var pointer = Translate(inst.Target); var value = Translate(inst.Value, typeHint: inst.Type); - if (pointer.Expression is DirectionExpression) + if (pointer.Expression is DirectionExpression && inst.UnalignedPrefix != 0) { pointer = pointer.ConvertTo(new ByReferenceType(compilation.FindType(KnownTypeCode.Byte)), this); } @@ -2911,12 +2924,24 @@ namespace ICSharpCode.Decompiler.CSharp { value = value.ConvertTo(inst.Type, this); } - return CallUnsafeIntrinsic( - name: "WriteUnaligned", - arguments: new Expression[] { pointer, value }, - returnType: compilation.FindType(KnownTypeCode.Void), - inst: inst - ); + if (inst.UnalignedPrefix != 0) + { + return CallUnsafeIntrinsic( + name: "WriteUnaligned", + arguments: new Expression[] { pointer, value }, + returnType: compilation.FindType(KnownTypeCode.Void), + inst: inst + ); + } + else + { + return CallUnsafeIntrinsic( + name: "Write", + arguments: new Expression[] { pointer, value }, + returnType: inst.Type, + inst: inst + ); + } } protected internal override TranslatedExpression VisitLdLen(LdLen inst, TranslationContext context)