Browse Source

Fix ref<->pointer conversions.

pull/728/head
Daniel Grunwald 10 years ago
parent
commit
14c87caea4
  1. 9
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 13
      ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs
  3. 176
      ICSharpCode.Decompiler/Tests/TestCases/UnsafeCode.cs
  4. 6
      ICSharpCode.Decompiler/Tests/TestRunner.cs

9
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -589,6 +589,15 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitConv(Conv inst) protected internal override TranslatedExpression VisitConv(Conv inst)
{ {
var arg = Translate(inst.Argument); var arg = Translate(inst.Argument);
if (inst.Kind == ConversionKind.StopGCTracking && arg.Type.Kind == TypeKind.ByReference) {
// cast to corresponding pointer type:
var pointerType = new PointerType(((ByReferenceType)arg.Type).ElementType);
arg = arg.ConvertTo(pointerType, this);
// if we want a native int, just return the pointer directly
if (inst.ResultType == StackType.I)
return arg;
// otherwise, continue converting
}
if (inst.Sign != Sign.None && arg.Type.GetSign() != inst.Sign) { if (inst.Sign != Sign.None && arg.Type.GetSign() != inst.Sign) {
// we need to cast the input to a type of appropriate sign // we need to cast the input to a type of appropriate sign
var inputType = inst.Argument.ResultType.ToKnownTypeCode(inst.Sign); var inputType = inst.Argument.ResultType.ToKnownTypeCode(inst.Sign);

13
ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

@ -176,6 +176,19 @@ namespace ICSharpCode.Decompiler.CSharp
.WithRR(new ResolveResult(pointerType)); .WithRR(new ResolveResult(pointerType));
// perform remaining pointer cast, if necessary // perform remaining pointer cast, if necessary
return pointerExpr.ConvertTo(targetType, expressionBuilder); return pointerExpr.ConvertTo(targetType, expressionBuilder);
} else if (targetType.Kind == TypeKind.ByReference) {
// Convert from integer/pointer to reference.
// First, convert to the corresponding pointer type:
var elementType = ((ByReferenceType)targetType).ElementType;
var arg = this.ConvertTo(new PointerType(elementType), expressionBuilder, checkForOverflow, addUncheckedAnnotations);
// Then dereference the pointer:
var derefExpr = new UnaryOperatorExpression(UnaryOperatorType.Dereference, arg.Expression);
var elementRR = new ResolveResult(elementType);
derefExpr.AddAnnotation(elementRR);
// And then take a reference:
return new DirectionExpression(FieldDirection.Ref, derefExpr)
.WithoutILInstruction()
.WithRR(new ByReferenceResolveResult(elementRR, false));
} }
if (type.IsKnownType(KnownTypeCode.Boolean) && targetType.GetStackType().IsIntegerType()) { if (type.IsKnownType(KnownTypeCode.Boolean) && targetType.GetStackType().IsIntegerType()) {
// convert from boolean to integer (or enum) // convert from boolean to integer (or enum)

176
ICSharpCode.Decompiler/Tests/TestCases/UnsafeCode.cs

@ -0,0 +1,176 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
public class UnsafeCode
{
static void Main()
{
// TODO: test behavior, or convert this into a pretty-test
// (but for now, it's already valuable knowing that the decompiled code can be re-compiled)
}
public unsafe int* NullPointer
{
get
{
return null;
}
}
public unsafe long ConvertDoubleToLong(double d)
{
return *(long*)(&d);
}
public unsafe double ConvertLongToDouble(long d)
{
return *(double*)(&d);
}
public unsafe int ConvertFloatToInt(float d)
{
return *(int*)(&d);
}
public unsafe float ConvertIntToFloat(int d)
{
return *(float*)(&d);
}
public unsafe void PassRefParameterAsPointer(ref int p)
{
fixed (int* ptr = &p)
{
this.PassPointerAsRefParameter(ptr);
}
}
public unsafe void PassPointerAsRefParameter(int* p)
{
this.PassRefParameterAsPointer(ref *p);
}
public unsafe void AddressInMultiDimensionalArray(double[,] matrix)
{
fixed (double* ptr = &matrix[1, 2])
{
this.PointerReferenceExpression(ptr);
}
}
public unsafe void FixedStringAccess(string text)
{
fixed (char* ptr = text)
{
char* ptr2 = ptr;
while (*ptr2 != '\0')
{
*ptr2 = 'A';
ptr2++;
}
}
}
public unsafe void PutDoubleIntoLongArray1(long[] array, int index, double val)
{
fixed (long* ptr = array)
{
((double*)ptr)[index] = val;
}
}
public unsafe void PutDoubleIntoLongArray2(long[] array, int index, double val)
{
fixed (long* ptr = &array[index])
{
*(double*)ptr = val;
}
}
public unsafe string PointerReferenceExpression(double* d)
{
return d->ToString();
}
public unsafe void FixMultipleStrings(string text)
{
fixed (char* ptr = text, userName = Environment.UserName, ptr2 = text)
{
*ptr = 'c';
*userName = 'd';
*ptr2 = 'e';
}
}
public unsafe string StackAlloc(int count)
{
char* ptr = stackalloc char[count];
for (int i = 0; i < count; i++)
{
ptr[i] = (char)i;
}
return this.PointerReferenceExpression((double*)ptr);
}
public unsafe int* PointerArithmetic(int* p)
{
return p + 2;
}
public unsafe byte* PointerArithmetic2(long* p, int y, int x)
{
return (byte*)((short*)p + (y * x));
}
public unsafe long* PointerArithmetic3(long* p)
{
return (long*)((byte*)p + 3);
}
public unsafe long* PointerArithmetic4(void* p)
{
return (long*)((byte*)p + 3);
}
public unsafe int PointerArithmetic5(void* p, byte* q, int i)
{
return (int)(q[i] + *(byte*)p);
}
public unsafe int PointerSubtraction(long* p, long* q)
{
return (int)((long)(p - q));
}
public unsafe int PointerSubtraction2(long* p, short* q)
{
return (int)((long)((byte*)p - (byte*)q));
}
public unsafe int PointerSubtraction3(void* p, void* q)
{
return (int)((long)((byte*)p - (byte*)q));
}
unsafe ~UnsafeCode()
{
this.PassPointerAsRefParameter(this.NullPointer);
}
}

6
ICSharpCode.Decompiler/Tests/TestRunner.cs

@ -114,6 +114,12 @@ namespace ICSharpCode.Decompiler.Tests
TestAssembleDecompileCompileOutput("ILTest.il"); TestAssembleDecompileCompileOutput("ILTest.il");
} }
[Test, Ignore("Fixed statements and pointer arithmetic are broken")]
public void UnsafeCode()
{
TestCompileDecompileCompileOutputAll("UnsafeCode.cs");
}
void TestCompileDecompileCompileOutputAll(string testFileName) void TestCompileDecompileCompileOutputAll(string testFileName)
{ {
TestCompileDecompileCompileOutput(testFileName, CompilerOptions.None); TestCompileDecompileCompileOutput(testFileName, CompilerOptions.None);

Loading…
Cancel
Save