Skip to content

Commit fc84462

Browse files
authored
Fix support for prefix opcodes (#304)
Fixes #303 +semver:fix
1 parent 295d941 commit fc84462

File tree

3 files changed

+33
-18
lines changed

3 files changed

+33
-18
lines changed

src/DelegateDecompiler.Tests/Issue298.cs

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,46 @@ public class Issue298 : DecompilerTestsBase
1010
[Test]
1111
public void TestNotConstrained()
1212
{
13-
static int NotConstrained<T>(T value) where T : ITestInterface => ((ITestInterface)value).Value;
14-
15-
Expression<Func<TestClass, int>> expected = value => value.Value;
16-
Test(NotConstrained, expected);
13+
static int Actual<T>(T value) where T : ITestInterface => ((ITestInterface)value).Field;
14+
15+
Test(Actual<TestClass>,
16+
value => value.Field,
17+
value => ((ITestInterface)value).Field
18+
);
1719
}
1820

1921
[Test]
2022
public void TestConstrained()
2123
{
22-
static int Constrained<T>(T value) where T : ITestInterface => value.Value;
24+
static int Actual<T>(T value) where T : ITestInterface => value.Field;
2325

24-
Expression<Func<TestClass, int>> expected = value => value.Value;
25-
Test(Constrained, expected);
26+
Test(Actual<ITestInterface>, value => value.Field);
27+
Test(Actual<TestClass>, value => value.Field);
2628
}
2729

30+
#if NET6_0_OR_GREATER
31+
[Test]
32+
public void TestConstrainedDefaultImplementation()
33+
{
34+
static int Actual<T>(T value, int i) where T : ITestInterface => value.Method(i);
35+
static Expression<Func<T, int, int>> Expected<T>() where T : ITestInterface => (value, i) => value.Method(i);
36+
37+
Test(Actual, Expected<ITestInterface>());
38+
Test(Actual, Expected<TestClass>());
39+
}
40+
#endif
41+
2842
interface ITestInterface
2943
{
30-
public int Value { get; }
44+
public int Field { get; }
45+
46+
#if NET6_0_OR_GREATER
47+
public int Method(int i) => i;
48+
#endif
3149
}
3250

3351
class TestClass : ITestInterface
3452
{
35-
public int Value { get; set; }
53+
public int Field { get; set; }
3654
}
3755
}

src/DelegateDecompiler/Processor.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,10 @@ static int ProcessInstruction(ProcessorState state, Instruction instruction)
145145
{
146146
Debug.WriteLine(instruction);
147147

148-
if (instruction.OpCode == OpCodes.Nop ||
148+
if (instruction.OpCode == OpCodes.Nop ||
149149
instruction.OpCode == OpCodes.Break ||
150150
instruction.OpCode == OpCodes.Ret ||
151+
instruction.OpCode.OpCodeType == OpCodeType.Prefix ||
151152
instruction.OpCode.FlowControl == FlowControl.Branch)
152153
{
153154
// Do nothing

src/DelegateDecompiler/Processors/ConvertTypeProcessor.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,16 @@ internal class ConvertTypeProcessor : IProcessor
1010
{
1111
public static void Register(Dictionary<OpCode, IProcessor> processors)
1212
{
13-
processors.Register(new ConvertTypeProcessor(),
14-
OpCodes.Castclass,
13+
processors.Register(new ConvertTypeProcessor(),
14+
OpCodes.Castclass,
1515
OpCodes.Unbox,
16-
OpCodes.Unbox_Any,
17-
OpCodes.Constrained);
16+
OpCodes.Unbox_Any);
1817
}
1918

2019
public void Process(ProcessorState state, Instruction instruction)
2120
{
2221
var expression = state.Stack.Pop();
23-
var targetType = (Type)instruction.Operand;
24-
state.Stack.Push(expression.Type != targetType
25-
? Expression.Convert(expression, targetType)
26-
: expression);
22+
state.Stack.Push(Expression.Convert(expression, (Type)instruction.Operand));
2723
}
2824
}
2925
}

0 commit comments

Comments
 (0)