@ -2541,6 +2541,27 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -2541,6 +2541,27 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitLdObj ( LdObj inst , TranslationContext context )
{
if ( inst . UnalignedPrefix ! = 0 )
{
// Use one of: Unsafe.ReadUnaligned<T>(void*)
// or: Unsafe.ReadUnaligned<T>(ref byte)
var pointer = Translate ( inst . Target ) ;
if ( pointer . Expression is DirectionExpression )
{
pointer = pointer . ConvertTo ( new ByReferenceType ( compilation . FindType ( KnownTypeCode . Byte ) ) , this ) ;
}
else
{
pointer = pointer . ConvertTo ( new PointerType ( compilation . FindType ( KnownTypeCode . Void ) ) , this , allowImplicitConversion : true ) ;
}
return CallUnsafeIntrinsic (
name : "ReadUnaligned" ,
arguments : new Expression [ ] { pointer } ,
returnType : inst . Type ,
inst : inst ,
typeArguments : new IType [ ] { inst . Type }
) ;
}
var result = LdObj ( inst . Target , inst . Type ) ;
//if (target.Type.IsSmallIntegerType() && loadType.IsSmallIntegerType() && target.Type.GetSign() != loadType.GetSign())
// return result.ConvertTo(loadType, this);
@ -2589,37 +2610,66 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -2589,37 +2610,66 @@ namespace ICSharpCode.Decompiler.CSharp
else
{
// We need to cast the pointer type:
if ( target . Expression is DirectionExpression )
{
target = target . ConvertTo ( new ByReferenceType ( loadType ) , this ) ;
}
else
{
target = target . ConvertTo ( new PointerType ( loadType ) , this ) ;
}
if ( target . Expression is DirectionExpression dirExpr )
{
return target . UnwrapChild ( dirExpr . Expression ) ;
}
else
{
return new UnaryOperatorExpression ( UnaryOperatorType . Dereference , target . Expression )
. WithRR ( new ResolveResult ( loadType ) ) ;
}
}
}
protected internal override TranslatedExpression VisitStObj ( StObj inst , TranslationContext context )
{
if ( inst . UnalignedPrefix ! = 0 )
{
return UnalignedStObj ( inst ) ;
}
var pointer = Translate ( inst . Target ) ;
TranslatedExpression target ;
TranslatedExpression value = default ;
if ( pointer . Expression is DirectionExpression & & TypeUtils . IsCompatiblePointerTypeForMemoryAccess ( pointer . Type , inst . Type ) )
{
// we can deference the managed reference by stripping away the 'ref'
target = pointer . UnwrapChild ( ( ( DirectionExpression ) pointer . Expression ) . Expression ) ;
}
else
{
// Cast pointer type if necessary:
if ( ! TypeUtils . IsCompatiblePointerTypeForMemoryAccess ( pointer . Type , inst . Type ) )
{
value = Translate ( inst . Value , typeHint : inst . Type ) ;
IType castTargetType ;
if ( TypeUtils . IsCompatibleTypeForMemoryAccess ( value . Type , inst . Type ) )
{
pointer = pointer . ConvertTo ( new PointerType ( value . Type ) , this ) ;
castTargetType = value . Type ;
}
else
{
castTargetType = inst . Type ;
}
if ( pointer . Expression is DirectionExpression )
{
pointer = pointer . ConvertTo ( new ByReferenceType ( castTargetType ) , this ) ;
}
else
{
pointer = pointer . ConvertTo ( new PointerType ( inst . Type ) , this ) ;
pointer = pointer . ConvertTo ( new PointerType ( castTarget Type) , this ) ;
}
}
if ( pointer . Expression is DirectionExpression )
{
// we can deference the managed reference by stripping away the 'ref'
target = pointer . UnwrapChild ( ( ( DirectionExpression ) pointer . Expression ) . Expression ) ;
}
else
{
if ( pointer . Expression is UnaryOperatorExpression uoe & & uoe . Operator = = UnaryOperatorType . AddressOf )
{
// *&ptr -> ptr
@ -2639,6 +2689,33 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -2639,6 +2689,33 @@ namespace ICSharpCode.Decompiler.CSharp
return Assignment ( target , value ) . WithILInstruction ( inst ) ;
}
private TranslatedExpression UnalignedStObj ( StObj inst )
{
// "unaligned.1; stobj" -> decompile to a call of
// Unsafe.WriteUnaligned<T>(void*, T)
// or Unsafe.WriteUnaligned<T>(ref byte, T)
var pointer = Translate ( inst . Target ) ;
var value = Translate ( inst . Value , typeHint : inst . Type ) ;
if ( pointer . Expression is DirectionExpression )
{
pointer = pointer . ConvertTo ( new ByReferenceType ( compilation . FindType ( KnownTypeCode . Byte ) ) , this ) ;
}
else
{
pointer = pointer . ConvertTo ( new PointerType ( compilation . FindType ( KnownTypeCode . Void ) ) , this , allowImplicitConversion : true ) ;
}
if ( ! TypeUtils . IsCompatibleTypeForMemoryAccess ( value . Type , inst . Type ) )
{
value = value . ConvertTo ( inst . Type , this ) ;
}
return CallUnsafeIntrinsic (
name : "WriteUnaligned" ,
arguments : new Expression [ ] { pointer , value } ,
returnType : compilation . FindType ( KnownTypeCode . Void ) ,
inst : inst
) ;
}
protected internal override TranslatedExpression VisitLdLen ( LdLen inst , TranslationContext context )
{
IType arrayType = compilation . FindType ( KnownTypeCode . Array ) ;