|
|
|
@ -2797,6 +2797,17 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -2797,6 +2797,17 @@ namespace ICSharpCode.Decompiler.CSharp
|
|
|
|
|
{ |
|
|
|
|
target = target.ConvertTo(new ByReferenceType(loadType), this); |
|
|
|
|
} |
|
|
|
|
else if (!loadType.IsUnmanagedType(settings.IntroduceUnmanagedConstraint)) |
|
|
|
|
{ |
|
|
|
|
// Use: Unsafe.Read<T>(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
@@ -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
@@ -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<T>(void*, T)
|
|
|
|
|
// or Unsafe.WriteUnaligned<T>(ref byte, T)
|
|
|
|
|
// "stobj ManagedType" -> decompile to a call of
|
|
|
|
|
// Unsafe.Write<T>(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
@@ -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) |
|
|
|
|