Browse Source

#1240: Add support for Unsafe comparison intrinsics: `AreSame`, `IsAddressLessThan`, `IsAddressGreaterThan`

pull/2218/head
Daniel Grunwald 5 years ago
parent
commit
411457c4c7
  1. 6
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs
  2. 35
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

6
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs

@ -389,19 +389,19 @@ namespace System.Runtime.CompilerServices @@ -389,19 +389,19 @@ namespace System.Runtime.CompilerServices
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AreSame<T>(ref T left, ref T right)
{
return (ref left) == (ref right);
return Unsafe.AreSame(ref left, ref right);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsAddressGreaterThan<T>(ref T left, ref T right)
{
return (ref left) > (ref right);
return Unsafe.IsAddressGreaterThan(ref left, ref right);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsAddressLessThan<T>(ref T left, ref T right)
{
return (ref left) < (ref right);
return Unsafe.IsAddressLessThan(ref left, ref right);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

35
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -786,6 +786,41 @@ namespace ICSharpCode.Decompiler.CSharp @@ -786,6 +786,41 @@ namespace ICSharpCode.Decompiler.CSharp
}
return ErrorExpression("Nullable comparisons with three-valued-logic not supported in C#");
}
if (inst.InputType == StackType.Ref)
{
// Reference comparison using Unsafe intrinsics
Debug.Assert(!inst.IsLifted);
(string methodName, bool negate) = inst.Kind switch {
ComparisonKind.Equality => ("AreSame", false),
ComparisonKind.Inequality => ("AreSame", true),
ComparisonKind.LessThan => ("IsAddressLessThan", false),
ComparisonKind.LessThanOrEqual => ("IsAddressGreaterThan", true),
ComparisonKind.GreaterThan => ("IsAddressGreaterThan", false),
ComparisonKind.GreaterThanOrEqual => ("IsAddressLessThan", true),
_ => throw new InvalidOperationException("Invalid ComparisonKind")
};
var left = Translate(inst.Left);
var right = Translate(inst.Right);
if (left.Type.Kind != TypeKind.ByReference || !NormalizeTypeVisitor.TypeErasure.EquivalentTypes(left.Type, right.Type))
{
IType commonRefType = new ByReferenceType(compilation.FindType(KnownTypeCode.Byte));
left = left.ConvertTo(commonRefType, this);
right = right.ConvertTo(commonRefType, this);
}
IType boolType = compilation.FindType(KnownTypeCode.Boolean);
TranslatedExpression expr = CallUnsafeIntrinsic(
name: methodName,
arguments: new Expression[] { left, right },
returnType: boolType,
inst: inst
);
if (negate)
{
expr = new UnaryOperatorExpression(UnaryOperatorType.Not, expr)
.WithoutILInstruction().WithRR(new ResolveResult(boolType));
}
return expr;
}
if (inst.Kind.IsEqualityOrInequality())
{
var result = TranslateCeq(inst, out bool negateOutput);

Loading…
Cancel
Save