Browse Source

Improve TransformInlineAssignment

pull/734/head
Siegfried Pammer 9 years ago
parent
commit
92e8deaf30
  1. 64
      ICSharpCode.Decompiler/IL/Transforms/TransformInlineAssignment.cs
  2. 29
      ICSharpCode.Decompiler/Tests/TestCases/Pretty/InlineAssignmentTest.cs
  3. 105
      ICSharpCode.Decompiler/Tests/TestCases/Pretty/InlineAssignmentTest.il

64
ICSharpCode.Decompiler/IL/Transforms/TransformInlineAssignment.cs

@ -37,7 +37,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -37,7 +37,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
foreach (var block in function.Descendants.OfType<Block>()) {
for (int i = block.Instructions.Count - 1; i >= 0; i--) {
TransformInlineAssignmentStObj(block, i);
TransformInlineAssignmentLocal(block, i);
}
}
}
@ -45,43 +44,68 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -45,43 +44,68 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// <code>
/// stloc s(value)
/// stloc l(ldloc s)
/// stobj(..., ldloc s)
/// -->
/// stloc s(stloc l(value))
/// stloc l(stobj (..., value))
/// </code>
static void TransformInlineAssignmentLocal(Block block, int i)
/// -or-
/// <code>
/// stloc s(value)
/// stobj (..., ldloc s)
/// -->
/// stloc s(stobj (..., value))
/// </code>
static void TransformInlineAssignmentStObj(Block block, int i)
{
var inst = block.Instructions[i] as StLoc;
var nextInst = block.Instructions.ElementAtOrDefault(i + 1) as StLoc;
if (inst == null || nextInst == null)
return;
if (nextInst.Variable.Kind == VariableKind.StackSlot || !nextInst.Value.MatchLdLoc(inst.Variable))
if (inst == null || inst.Variable.Kind != VariableKind.StackSlot)
return;
var nextInst = block.Instructions.ElementAtOrDefault(i + 1);
ILInstruction value;
StObj fieldStore;
ILVariable local;
if (nextInst is StLoc) { // instance fields
var localStore = (StLoc)nextInst;
fieldStore = block.Instructions.ElementAtOrDefault(i + 2) as StObj;
if (fieldStore == null) { // otherwise it must local
TransformInlineAssignmentLocal(block, i);
return;
}
if (localStore.Variable.Kind == VariableKind.StackSlot || !localStore.Value.MatchLdLoc(inst.Variable) || !fieldStore.Value.MatchLdLoc(inst.Variable))
return;
value = inst.Value;
local = localStore.Variable;
block.Instructions.RemoveAt(i + 1);
} else if (nextInst is StObj) { // static fields
fieldStore = (StObj)nextInst;
if (!fieldStore.Value.MatchLdLoc(inst.Variable))
return;
value = inst.Value;
local = inst.Variable;
} else return;
block.Instructions.RemoveAt(i + 1);
var value = inst.Value.Clone();
inst.Value.ReplaceWith(new StLoc(nextInst.Variable, value));
inst.ReplaceWith(new StLoc(local, new StObj(fieldStore.Target, value, fieldStore.Type)));
}
/// <code>
/// stloc s(value)
/// stloc l(ldloc s)
/// stobj(..., ldloc s)
/// -->
/// stloc l(stobj (..., value))
/// stloc s(stloc l(value))
/// </code>
static void TransformInlineAssignmentStObj(Block block, int i)
static void TransformInlineAssignmentLocal(Block block, int i)
{
var inst = block.Instructions[i] as StLoc;
var nextInst = block.Instructions.ElementAtOrDefault(i + 1) as StLoc;
var fieldStore = block.Instructions.ElementAtOrDefault(i + 2) as StObj;
if (inst == null || nextInst == null || fieldStore == null)
if (inst == null || nextInst == null)
return;
if (nextInst.Variable.Kind == VariableKind.StackSlot || !nextInst.Value.MatchLdLoc(inst.Variable) || !fieldStore.Value.MatchLdLoc(inst.Variable))
if (nextInst.Variable.Kind == VariableKind.StackSlot || !nextInst.Value.MatchLdLoc(inst.Variable))
return;
var value = inst.Value.Clone();
var locVar = nextInst.Variable;
block.Instructions.RemoveAt(i + 1);
block.Instructions.RemoveAt(i + 1);
inst.ReplaceWith(new StLoc(locVar, new StObj(fieldStore.Target, value, fieldStore.Type)));
var value = inst.Value;
var var = nextInst.Variable;
var stackVar = inst.Variable;
block.Instructions.RemoveAt(i);
nextInst.ReplaceWith(new StLoc(stackVar, new StLoc(var, value)));
}
}
}

29
ICSharpCode.Decompiler/Tests/TestCases/Pretty/InlineAssignmentTest.cs

@ -23,7 +23,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -23,7 +23,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public class InlineAssignmentTest
{
private int field1;
private InlineAssignmentTest field2;
private static InlineAssignmentTest field2;
public static void Main()
{
@ -43,15 +43,36 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -43,15 +43,36 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void SimpleInlineWithFields()
{
Console.WriteLine(this.field1 = 5);
Console.WriteLine((object)(this.field2 = new InlineAssignmentTest()));
Console.WriteLine((object)(InlineAssignmentTest.field2 = new InlineAssignmentTest()));
}
public void SimpleInlineWithFields2()
{
Console.WriteLine(this.field1 = 5);
Console.WriteLine(this.field1);
Console.WriteLine((object)(this.field2 = new InlineAssignmentTest()));
Console.WriteLine((object)this.field2);
Console.WriteLine((object)(InlineAssignmentTest.field2 = new InlineAssignmentTest()));
Console.WriteLine((object)InlineAssignmentTest.field2);
}
// public void ReadLoop1(TextReader r)
// {
// string V_0;
// while ((V_0 = r.ReadLine()) != null)
// {
// Console.WriteLine(V_0);
// }
// }
public void AccessArray(int[] a)
{
int V_0;
Console.WriteLine(V_0 = a[0]);
Console.WriteLine(a[V_0] = V_0);
}
public int Return(ref int a)
{
return a = 3;
}
}
}

105
ICSharpCode.Decompiler/Tests/TestCases/Pretty/InlineAssignmentTest.il

@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly '3z5tjxm2'
.assembly '02lbfa11'
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
@ -20,15 +20,15 @@ @@ -20,15 +20,15 @@
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module '3z5tjxm2.exe'
// MVID: {3B1EB063-50AF-4CD4-83C3-9D26A66D9510}
.module '02lbfa11.exe'
// MVID: {47622B1B-1B9D-44A2-8E1D-D389FDB9C1FD}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x011D0000
// Image base: 0x03160000
// =============== CLASS MEMBERS DECLARATION ===================
@ -37,7 +37,7 @@ @@ -37,7 +37,7 @@
extends [mscorlib]System.Object
{
.field private int32 field1
.field private class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest field2
.field private static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest field2
.method public hidebysig static void Main() cil managed
{
.entrypoint
@ -77,10 +77,9 @@ @@ -77,10 +77,9 @@
.method public hidebysig instance void
SimpleInlineWithFields() cil managed
{
// Code size 38 (0x26)
// Code size 35 (0x23)
.maxstack 3
.locals init (int32 V_0,
class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest V_1)
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.5
@ -90,24 +89,20 @@ @@ -90,24 +89,20 @@
IL_000a: ldloc.0
IL_000b: call void [mscorlib]System.Console::WriteLine(int32)
IL_0010: nop
IL_0011: ldarg.0
IL_0012: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::.ctor()
IL_0017: dup
IL_0018: stloc.1
IL_0019: stfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2
IL_001e: ldloc.1
IL_001f: call void [mscorlib]System.Console::WriteLine(object)
IL_0024: nop
IL_0025: ret
IL_0011: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::.ctor()
IL_0016: dup
IL_0017: stsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2
IL_001c: call void [mscorlib]System.Console::WriteLine(object)
IL_0021: nop
IL_0022: ret
} // end of method InlineAssignmentTest::SimpleInlineWithFields
.method public hidebysig instance void
SimpleInlineWithFields2() cil managed
{
// Code size 62 (0x3e)
// Code size 58 (0x3a)
.maxstack 3
.locals init (int32 V_0,
class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest V_1)
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.5
@ -121,21 +116,65 @@ @@ -121,21 +116,65 @@
IL_0012: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field1
IL_0017: call void [mscorlib]System.Console::WriteLine(int32)
IL_001c: nop
IL_001d: ldarg.0
IL_001e: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::.ctor()
IL_0023: dup
IL_0024: stloc.1
IL_0025: stfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2
IL_002a: ldloc.1
IL_002b: call void [mscorlib]System.Console::WriteLine(object)
IL_0030: nop
IL_0031: ldarg.0
IL_0032: ldfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2
IL_0037: call void [mscorlib]System.Console::WriteLine(object)
IL_003c: nop
IL_003d: ret
IL_001d: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::.ctor()
IL_0022: dup
IL_0023: stsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2
IL_0028: call void [mscorlib]System.Console::WriteLine(object)
IL_002d: nop
IL_002e: ldsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2
IL_0033: call void [mscorlib]System.Console::WriteLine(object)
IL_0038: nop
IL_0039: ret
} // end of method InlineAssignmentTest::SimpleInlineWithFields2
.method public hidebysig instance void
AccessArray(int32[] a) cil managed
{
// Code size 26 (0x1a)
.maxstack 4
.locals init (int32 V_0,
int32 V_1)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldc.i4.0
IL_0003: ldelem.i4
IL_0004: dup
IL_0005: stloc.0
IL_0006: call void [mscorlib]System.Console::WriteLine(int32)
IL_000b: nop
IL_000c: ldarg.1
IL_000d: ldloc.0
IL_000e: ldloc.0
IL_000f: dup
IL_0010: stloc.1
IL_0011: stelem.i4
IL_0012: ldloc.1
IL_0013: call void [mscorlib]System.Console::WriteLine(int32)
IL_0018: nop
IL_0019: ret
} // end of method InlineAssignmentTest::AccessArray
.method public hidebysig instance int32
Test(int32& a) cil managed
{
// Code size 12 (0xc)
.maxstack 3
.locals init (int32 V_0,
int32 V_1)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldc.i4.3
IL_0003: dup
IL_0004: stloc.1
IL_0005: stind.i4
IL_0006: ldloc.1
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
} // end of method InlineAssignmentTest::Test
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{

Loading…
Cancel
Save