Browse Source

Remove /doc/Dissertation as it's no longer relevant.

pull/870/merge
Siegfried Pammer 8 years ago
parent
commit
fb092fdf5e
  1. BIN
      doc/Dissertation/Dissertation.pdf
  2. 3077
      doc/Dissertation/Dissertation.tex
  3. 190
      doc/Dissertation/Evolution/01_Disassemble.cs
  4. 368
      doc/Dissertation/Evolution/01b_Disassemble_StackStates.cs
  5. 190
      doc/Dissertation/Evolution/02_Peephole_decompilation.cs
  6. 203
      doc/Dissertation/Evolution/03_Dataflow.cs
  7. 378
      doc/Dissertation/Evolution/03_Dataflow_Comments.cs
  8. 49
      doc/Dissertation/Evolution/04_Inline_expressions.cs
  9. 78
      doc/Dissertation/Evolution/05_Find_basic_blocks.cs
  10. 87
      doc/Dissertation/Evolution/06_Find_loops.cs
  11. 122
      doc/Dissertation/Evolution/07_Find_conditionals.cs
  12. 69
      doc/Dissertation/Evolution/08_Remove_dead_jumps.cs
  13. 51
      doc/Dissertation/Evolution/09_Reduce_loops.cs
  14. 44
      doc/Dissertation/Evolution/10_Short_type_names.cs
  15. 43
      doc/Dissertation/Evolution/QuickSort_original.cs
  16. BIN
      doc/Dissertation/ProgressReport.pdf
  17. 243
      doc/Dissertation/ProgressReport.tex
  18. 356
      doc/Dissertation/Proposal.tex
  19. 44
      doc/Dissertation/figs/10_Short_type_names_2.cs
  20. BIN
      doc/Dissertation/figs/IfThen.png
  21. BIN
      doc/Dissertation/figs/IfThenElse.png
  22. BIN
      doc/Dissertation/figs/IfThenElseRechablility.png
  23. BIN
      doc/Dissertation/figs/IfThenElseReduction.png
  24. BIN
      doc/Dissertation/figs/Ireducible.png
  25. BIN
      doc/Dissertation/figs/Loop.png
  26. BIN
      doc/Dissertation/figs/NestedLoops.png
  27. BIN
      doc/Dissertation/figs/NestedLoops2.png
  28. BIN
      doc/Dissertation/figs/QuickSortMain.png
  29. 44
      doc/Dissertation/figs/QuickSort_original.cs
  30. BIN
      doc/Dissertation/figs/T1T2.png
  31. 3132
      doc/Dissertation/figs/figs.svg
  32. BIN
      doc/Dissertation/figs/shortcircuit.png

BIN
doc/Dissertation/Dissertation.pdf

Binary file not shown.

3077
doc/Dissertation/Dissertation.tex

File diff suppressed because it is too large Load Diff

190
doc/Dissertation/Evolution/01_Disassemble.cs

@ -1,190 +0,0 @@ @@ -1,190 +0,0 @@
abstract class QuickSortProgram
{
public static void Main(System.String[] args)
{
IL_00: nop # Pop0->Push0
IL_01: ldarg args # Pop0->Push1
IL_02: ldlen # Popref->Pushi
IL_03: conv.i4 # Pop1->Pushi
IL_04: newarr System.Int32# Popi->Pushref
IL_09: stloc V_0 # Pop1->Push0
IL_0A: ldc.i4 0 # Pop0->Pushi
IL_0B: stloc V_1 # Pop1->Push0
IL_0C: br IL_1F # Pop0->Push0 Flow=Branch
IL_0E: nop # Pop0->Push0
IL_0F: ldloc V_0 # Pop0->Push1
IL_10: ldloc V_1 # Pop0->Push1
IL_11: ldarg args # Pop0->Push1
IL_12: ldloc V_1 # Pop0->Push1
IL_13: ldelem.ref # Popref_popi->Pushref
IL_14: call Parse() # Varpop->Varpush Flow=Call
IL_19: stelem.i4 # Popref_popi_popi->Push0
IL_1A: nop # Pop0->Push0
IL_1B: ldloc V_1 # Pop0->Push1
IL_1C: ldc.i4 1 # Pop0->Pushi
IL_1D: add.ovf # Pop1_pop1->Push1
IL_1E: stloc V_1 # Pop1->Push0
IL_1F: ldloc V_1 # Pop0->Push1
IL_20: ldloc V_0 # Pop0->Push1
IL_21: ldlen # Popref->Pushi
IL_22: conv.i4 # Pop1->Pushi
IL_23: clt # Pop1_pop1->Pushi
IL_25: stloc V_2 # Pop1->Push0
IL_26: ldloc V_2 # Pop0->Push1
IL_27: brtrue IL_0E # Popi->Push0 Flow=Cond_Branch
IL_29: ldloc V_0 # Pop0->Push1
IL_2A: ldc.i4 0 # Pop0->Pushi
IL_2B: ldloc V_0 # Pop0->Push1
IL_2C: ldlen # Popref->Pushi
IL_2D: conv.i4 # Pop1->Pushi
IL_2E: ldc.i4 1 # Pop0->Pushi
IL_2F: sub.ovf # Pop1_pop1->Push1
IL_30: call QuickSort() # Varpop->Varpush Flow=Call
IL_35: nop # Pop0->Push0
IL_36: ldc.i4 0 # Pop0->Pushi
IL_37: stloc V_1 # Pop1->Push0
IL_38: br IL_5C # Pop0->Push0 Flow=Branch
IL_3A: nop # Pop0->Push0
IL_3B: ldloc V_0 # Pop0->Push1
IL_3C: ldloc V_1 # Pop0->Push1
IL_3D: ldelema System.Int32# Popref_popi->Pushi
IL_42: call ToString() # Varpop->Varpush Flow=Call
IL_47: ldstr \" \" # Pop0->Pushref
IL_4C: call Concat() # Varpop->Varpush Flow=Call
IL_51: call Write() # Varpop->Varpush Flow=Call
IL_56: nop # Pop0->Push0
IL_57: nop # Pop0->Push0
IL_58: ldloc V_1 # Pop0->Push1
IL_59: ldc.i4 1 # Pop0->Pushi
IL_5A: add.ovf # Pop1_pop1->Push1
IL_5B: stloc V_1 # Pop1->Push0
IL_5C: ldloc V_1 # Pop0->Push1
IL_5D: ldloc V_0 # Pop0->Push1
IL_5E: ldlen # Popref->Pushi
IL_5F: conv.i4 # Pop1->Pushi
IL_60: clt # Pop1_pop1->Pushi
IL_62: stloc V_2 # Pop1->Push0
IL_63: ldloc V_2 # Pop0->Push1
IL_64: brtrue IL_3A # Popi->Push0 Flow=Cond_Branch
IL_66: ret # Varpop->Push0 Flow=Return
}
public static void QuickSort(System.Int32[] array, int left, int right)
{
IL_00: nop # Pop0->Push0
IL_01: ldarg right # Pop0->Push1
IL_02: ldarg left # Pop0->Push1
IL_03: cgt # Pop1_pop1->Pushi
IL_05: ldc.i4 0 # Pop0->Pushi
IL_06: ceq # Pop1_pop1->Pushi
IL_08: stloc V_2 # Pop1->Push0
IL_09: ldloc V_2 # Pop0->Push1
IL_0A: brtrue IL_34 # Popi->Push0 Flow=Cond_Branch
IL_0C: nop # Pop0->Push0
IL_0D: ldarg left # Pop0->Push1
IL_0E: ldarg right # Pop0->Push1
IL_0F: add.ovf # Pop1_pop1->Push1
IL_10: ldc.i4 2 # Pop0->Pushi
IL_11: div # Pop1_pop1->Push1
IL_12: stloc V_0 # Pop1->Push0
IL_13: ldarg array # Pop0->Push1
IL_14: ldarg left # Pop0->Push1
IL_15: ldarg right # Pop0->Push1
IL_16: ldloc V_0 # Pop0->Push1
IL_17: call Partition() # Varpop->Varpush Flow=Call
IL_1C: stloc V_1 # Pop1->Push0
IL_1D: ldarg array # Pop0->Push1
IL_1E: ldarg left # Pop0->Push1
IL_1F: ldloc V_1 # Pop0->Push1
IL_20: ldc.i4 1 # Pop0->Pushi
IL_21: sub.ovf # Pop1_pop1->Push1
IL_22: call QuickSort() # Varpop->Varpush Flow=Call
IL_27: nop # Pop0->Push0
IL_28: ldarg array # Pop0->Push1
IL_29: ldloc V_1 # Pop0->Push1
IL_2A: ldc.i4 1 # Pop0->Pushi
IL_2B: add.ovf # Pop1_pop1->Push1
IL_2C: ldarg right # Pop0->Push1
IL_2D: call QuickSort() # Varpop->Varpush Flow=Call
IL_32: nop # Pop0->Push0
IL_33: nop # Pop0->Push0
IL_34: ret # Varpop->Push0 Flow=Return
}
private static int Partition(System.Int32[] array, int left, int right, int pivotIndex)
{
IL_00: nop # Pop0->Push0
IL_01: ldarg array # Pop0->Push1
IL_02: ldarg pivotIndex # Pop0->Push1
IL_03: ldelem.i4 # Popref_popi->Pushi
IL_04: stloc V_0 # Pop1->Push0
IL_05: ldarg array # Pop0->Push1
IL_06: ldarg pivotIndex # Pop0->Push1
IL_07: ldarg right # Pop0->Push1
IL_08: call Swap() # Varpop->Varpush Flow=Call
IL_0D: nop # Pop0->Push0
IL_0E: ldarg left # Pop0->Push1
IL_0F: stloc V_1 # Pop1->Push0
IL_10: ldarg left # Pop0->Push1
IL_11: stloc V_2 # Pop1->Push0
IL_12: br IL_35 # Pop0->Push0 Flow=Branch
IL_14: nop # Pop0->Push0
IL_15: ldarg array # Pop0->Push1
IL_16: ldloc V_2 # Pop0->Push1
IL_17: ldelem.i4 # Popref_popi->Pushi
IL_18: ldloc V_0 # Pop0->Push1
IL_19: cgt # Pop1_pop1->Pushi
IL_1B: stloc V_4 # Pop1->Push0
IL_1D: ldloc V_4 # Pop0->Push1
IL_1F: brtrue IL_30 # Popi->Push0 Flow=Cond_Branch
IL_21: nop # Pop0->Push0
IL_22: ldarg array # Pop0->Push1
IL_23: ldloc V_1 # Pop0->Push1
IL_24: ldloc V_2 # Pop0->Push1
IL_25: call Swap() # Varpop->Varpush Flow=Call
IL_2A: nop # Pop0->Push0
IL_2B: ldloc V_1 # Pop0->Push1
IL_2C: ldc.i4 1 # Pop0->Pushi
IL_2D: add.ovf # Pop1_pop1->Push1
IL_2E: stloc V_1 # Pop1->Push0
IL_2F: nop # Pop0->Push0
IL_30: nop # Pop0->Push0
IL_31: ldloc V_2 # Pop0->Push1
IL_32: ldc.i4 1 # Pop0->Pushi
IL_33: add.ovf # Pop1_pop1->Push1
IL_34: stloc V_2 # Pop1->Push0
IL_35: ldloc V_2 # Pop0->Push1
IL_36: ldarg right # Pop0->Push1
IL_37: clt # Pop1_pop1->Pushi
IL_39: stloc V_4 # Pop1->Push0
IL_3B: ldloc V_4 # Pop0->Push1
IL_3D: brtrue IL_14 # Popi->Push0 Flow=Cond_Branch
IL_3F: ldarg array # Pop0->Push1
IL_40: ldarg right # Pop0->Push1
IL_41: ldloc V_1 # Pop0->Push1
IL_42: call Swap() # Varpop->Varpush Flow=Call
IL_47: nop # Pop0->Push0
IL_48: ldloc V_1 # Pop0->Push1
IL_49: stloc V_3 # Pop1->Push0
IL_4A: br IL_4C # Pop0->Push0 Flow=Branch
IL_4C: ldloc V_3 # Pop0->Push1
IL_4D: ret # Varpop->Push0 Flow=Return
}
private static void Swap(System.Int32[] array, int index1, int index2)
{
IL_00: nop # Pop0->Push0
IL_01: ldarg array # Pop0->Push1
IL_02: ldarg index1 # Pop0->Push1
IL_03: ldelem.i4 # Popref_popi->Pushi
IL_04: stloc V_0 # Pop1->Push0
IL_05: ldarg array # Pop0->Push1
IL_06: ldarg index1 # Pop0->Push1
IL_07: ldarg array # Pop0->Push1
IL_08: ldarg index2 # Pop0->Push1
IL_09: ldelem.i4 # Popref_popi->Pushi
IL_0A: stelem.i4 # Popref_popi_popi->Push0
IL_0B: ldarg array # Pop0->Push1
IL_0C: ldarg index2 # Pop0->Push1
IL_0D: ldloc V_0 # Pop0->Push1
IL_0E: stelem.i4 # Popref_popi_popi->Push0
IL_0F: ret # Varpop->Push0 Flow=Return
}
}

368
doc/Dissertation/Evolution/01b_Disassemble_StackStates.cs

@ -1,368 +0,0 @@ @@ -1,368 +0,0 @@
namespace
{
abstract class QuickSortProgram
{
public static void Main(System.String[] args)
{
IL_00: nop # Pop0->Push0
// Stack: {}
IL_01: ldarg args # Pop0->Push1
// Stack: {IL_01}
IL_02: ldlen # Popref->Pushi
// Stack: {IL_02}
IL_03: conv.i4 # Pop1->Pushi
// Stack: {IL_03}
IL_04: newarr System.Int32 # Popi->Pushref
// Stack: {IL_04}
IL_09: stloc V_0 # Pop1->Push0
// Stack: {}
IL_0A: ldc.i4 0 # Pop0->Pushi
// Stack: {IL_0A}
IL_0B: stloc V_1 # Pop1->Push0
// Stack: {}
IL_0C: br IL_1F # Pop0->Push0 Flow=Branch
// Stack: {}
IL_0E: nop # Pop0->Push0
// Stack: {}
IL_0F: ldloc V_0 # Pop0->Push1
// Stack: {IL_0F}
IL_10: ldloc V_1 # Pop0->Push1
// Stack: {IL_0F, IL_10}
IL_11: ldarg args # Pop0->Push1
// Stack: {IL_0F, IL_10, IL_11}
IL_12: ldloc V_1 # Pop0->Push1
// Stack: {IL_0F, IL_10, IL_11, IL_12}
IL_13: ldelem.ref # Popref_popi->Pushref
// Stack: {IL_0F, IL_10, IL_13}
IL_14: call Parse() # Varpop->Varpush Flow=Call
// Stack: {IL_0F, IL_10, IL_14}
IL_19: stelem.i4 # Popref_popi_popi->Push0
// Stack: {}
IL_1A: nop # Pop0->Push0
// Stack: {}
IL_1B: ldloc V_1 # Pop0->Push1
// Stack: {IL_1B}
IL_1C: ldc.i4 1 # Pop0->Pushi
// Stack: {IL_1B, IL_1C}
IL_1D: add.ovf # Pop1_pop1->Push1
// Stack: {IL_1D}
IL_1E: stloc V_1 # Pop1->Push0
// Stack: {}
IL_1F: ldloc V_1 # Pop0->Push1
// Stack: {IL_1F}
IL_20: ldloc V_0 # Pop0->Push1
// Stack: {IL_1F, IL_20}
IL_21: ldlen # Popref->Pushi
// Stack: {IL_1F, IL_21}
IL_22: conv.i4 # Pop1->Pushi
// Stack: {IL_1F, IL_22}
IL_23: clt # Pop1_pop1->Pushi
// Stack: {IL_23}
IL_25: stloc V_2 # Pop1->Push0
// Stack: {}
IL_26: ldloc V_2 # Pop0->Push1
// Stack: {IL_26}
IL_27: brtrue IL_0E # Popi->Push0 Flow=Cond_Branch
// Stack: {}
IL_29: ldloc V_0 # Pop0->Push1
// Stack: {IL_29}
IL_2A: ldc.i4 0 # Pop0->Pushi
// Stack: {IL_29, IL_2A}
IL_2B: ldloc V_0 # Pop0->Push1
// Stack: {IL_29, IL_2A, IL_2B}
IL_2C: ldlen # Popref->Pushi
// Stack: {IL_29, IL_2A, IL_2C}
IL_2D: conv.i4 # Pop1->Pushi
// Stack: {IL_29, IL_2A, IL_2D}
IL_2E: ldc.i4 1 # Pop0->Pushi
// Stack: {IL_29, IL_2A, IL_2D, IL_2E}
IL_2F: sub.ovf # Pop1_pop1->Push1
// Stack: {IL_29, IL_2A, IL_2F}
IL_30: call QuickSort() # Varpop->Varpush Flow=Call
// Stack: {}
IL_35: nop # Pop0->Push0
// Stack: {}
IL_36: ldc.i4 0 # Pop0->Pushi
// Stack: {IL_36}
IL_37: stloc V_1 # Pop1->Push0
// Stack: {}
IL_38: br IL_5C # Pop0->Push0 Flow=Branch
// Stack: {}
IL_3A: nop # Pop0->Push0
// Stack: {}
IL_3B: ldloc V_0 # Pop0->Push1
// Stack: {IL_3B}
IL_3C: ldloc V_1 # Pop0->Push1
// Stack: {IL_3B, IL_3C}
IL_3D: ldelema System.Int32 # Popref_popi->Pushi
// Stack: {IL_3D}
IL_42: call ToString() # Varpop->Varpush Flow=Call
// Stack: {IL_42}
IL_47: ldstr \" \" # Pop0->Pushref
// Stack: {IL_42, IL_47}
IL_4C: call Concat() # Varpop->Varpush Flow=Call
// Stack: {IL_4C}
IL_51: call Write() # Varpop->Varpush Flow=Call
// Stack: {}
IL_56: nop # Pop0->Push0
// Stack: {}
IL_57: nop # Pop0->Push0
// Stack: {}
IL_58: ldloc V_1 # Pop0->Push1
// Stack: {IL_58}
IL_59: ldc.i4 1 # Pop0->Pushi
// Stack: {IL_58, IL_59}
IL_5A: add.ovf # Pop1_pop1->Push1
// Stack: {IL_5A}
IL_5B: stloc V_1 # Pop1->Push0
// Stack: {}
IL_5C: ldloc V_1 # Pop0->Push1
// Stack: {IL_5C}
IL_5D: ldloc V_0 # Pop0->Push1
// Stack: {IL_5C, IL_5D}
IL_5E: ldlen # Popref->Pushi
// Stack: {IL_5C, IL_5E}
IL_5F: conv.i4 # Pop1->Pushi
// Stack: {IL_5C, IL_5F}
IL_60: clt # Pop1_pop1->Pushi
// Stack: {IL_60}
IL_62: stloc V_2 # Pop1->Push0
// Stack: {}
IL_63: ldloc V_2 # Pop0->Push1
// Stack: {IL_63}
IL_64: brtrue IL_3A # Popi->Push0 Flow=Cond_Branch
// Stack: {}
IL_66: ret # Varpop->Push0 Flow=Return
// Stack: {}
}
public static void QuickSort(System.Int32[] array, int left, int right)
{
IL_00: nop # Pop0->Push0
// Stack: {}
IL_01: ldarg right # Pop0->Push1
// Stack: {IL_01}
IL_02: ldarg left # Pop0->Push1
// Stack: {IL_01, IL_02}
IL_03: cgt # Pop1_pop1->Pushi
// Stack: {IL_03}
IL_05: ldc.i4 0 # Pop0->Pushi
// Stack: {IL_03, IL_05}
IL_06: ceq # Pop1_pop1->Pushi
// Stack: {IL_06}
IL_08: stloc V_2 # Pop1->Push0
// Stack: {}
IL_09: ldloc V_2 # Pop0->Push1
// Stack: {IL_09}
IL_0A: brtrue IL_34 # Popi->Push0 Flow=Cond_Branch
// Stack: {}
IL_0C: nop # Pop0->Push0
// Stack: {}
IL_0D: ldarg left # Pop0->Push1
// Stack: {IL_0D}
IL_0E: ldarg right # Pop0->Push1
// Stack: {IL_0D, IL_0E}
IL_0F: add.ovf # Pop1_pop1->Push1
// Stack: {IL_0F}
IL_10: ldc.i4 2 # Pop0->Pushi
// Stack: {IL_0F, IL_10}
IL_11: div # Pop1_pop1->Push1
// Stack: {IL_11}
IL_12: stloc V_0 # Pop1->Push0
// Stack: {}
IL_13: ldarg array # Pop0->Push1
// Stack: {IL_13}
IL_14: ldarg left # Pop0->Push1
// Stack: {IL_13, IL_14}
IL_15: ldarg right # Pop0->Push1
// Stack: {IL_13, IL_14, IL_15}
IL_16: ldloc V_0 # Pop0->Push1
// Stack: {IL_13, IL_14, IL_15, IL_16}
IL_17: call Partition() # Varpop->Varpush Flow=Call
// Stack: {IL_17}
IL_1C: stloc V_1 # Pop1->Push0
// Stack: {}
IL_1D: ldarg array # Pop0->Push1
// Stack: {IL_1D}
IL_1E: ldarg left # Pop0->Push1
// Stack: {IL_1D, IL_1E}
IL_1F: ldloc V_1 # Pop0->Push1
// Stack: {IL_1D, IL_1E, IL_1F}
IL_20: ldc.i4 1 # Pop0->Pushi
// Stack: {IL_1D, IL_1E, IL_1F, IL_20}
IL_21: sub.ovf # Pop1_pop1->Push1
// Stack: {IL_1D, IL_1E, IL_21}
IL_22: call QuickSort() # Varpop->Varpush Flow=Call
// Stack: {}
IL_27: nop # Pop0->Push0
// Stack: {}
IL_28: ldarg array # Pop0->Push1
// Stack: {IL_28}
IL_29: ldloc V_1 # Pop0->Push1
// Stack: {IL_28, IL_29}
IL_2A: ldc.i4 1 # Pop0->Pushi
// Stack: {IL_28, IL_29, IL_2A}
IL_2B: add.ovf # Pop1_pop1->Push1
// Stack: {IL_28, IL_2B}
IL_2C: ldarg right # Pop0->Push1
// Stack: {IL_28, IL_2B, IL_2C}
IL_2D: call QuickSort() # Varpop->Varpush Flow=Call
// Stack: {}
IL_32: nop # Pop0->Push0
// Stack: {}
IL_33: nop # Pop0->Push0
// Stack: {}
IL_34: ret # Varpop->Push0 Flow=Return
// Stack: {}
}
private static int Partition(System.Int32[] array, int left, int right, int pivotIndex)
{
IL_00: nop # Pop0->Push0
// Stack: {}
IL_01: ldarg array # Pop0->Push1
// Stack: {IL_01}
IL_02: ldarg pivotIndex # Pop0->Push1
// Stack: {IL_01, IL_02}
IL_03: ldelem.i4 # Popref_popi->Pushi
// Stack: {IL_03}
IL_04: stloc V_0 # Pop1->Push0
// Stack: {}
IL_05: ldarg array # Pop0->Push1
// Stack: {IL_05}
IL_06: ldarg pivotIndex # Pop0->Push1
// Stack: {IL_05, IL_06}
IL_07: ldarg right # Pop0->Push1
// Stack: {IL_05, IL_06, IL_07}
IL_08: call Swap() # Varpop->Varpush Flow=Call
// Stack: {}
IL_0D: nop # Pop0->Push0
// Stack: {}
IL_0E: ldarg left # Pop0->Push1
// Stack: {IL_0E}
IL_0F: stloc V_1 # Pop1->Push0
// Stack: {}
IL_10: ldarg left # Pop0->Push1
// Stack: {IL_10}
IL_11: stloc V_2 # Pop1->Push0
// Stack: {}
IL_12: br IL_35 # Pop0->Push0 Flow=Branch
// Stack: {}
IL_14: nop # Pop0->Push0
// Stack: {}
IL_15: ldarg array # Pop0->Push1
// Stack: {IL_15}
IL_16: ldloc V_2 # Pop0->Push1
// Stack: {IL_15, IL_16}
IL_17: ldelem.i4 # Popref_popi->Pushi
// Stack: {IL_17}
IL_18: ldloc V_0 # Pop0->Push1
// Stack: {IL_17, IL_18}
IL_19: cgt # Pop1_pop1->Pushi
// Stack: {IL_19}
IL_1B: stloc V_4 # Pop1->Push0
// Stack: {}
IL_1D: ldloc V_4 # Pop0->Push1
// Stack: {IL_1D}
IL_1F: brtrue IL_30 # Popi->Push0 Flow=Cond_Branch
// Stack: {}
IL_21: nop # Pop0->Push0
// Stack: {}
IL_22: ldarg array # Pop0->Push1
// Stack: {IL_22}
IL_23: ldloc V_1 # Pop0->Push1
// Stack: {IL_22, IL_23}
IL_24: ldloc V_2 # Pop0->Push1
// Stack: {IL_22, IL_23, IL_24}
IL_25: call Swap() # Varpop->Varpush Flow=Call
// Stack: {}
IL_2A: nop # Pop0->Push0
// Stack: {}
IL_2B: ldloc V_1 # Pop0->Push1
// Stack: {IL_2B}
IL_2C: ldc.i4 1 # Pop0->Pushi
// Stack: {IL_2B, IL_2C}
IL_2D: add.ovf # Pop1_pop1->Push1
// Stack: {IL_2D}
IL_2E: stloc V_1 # Pop1->Push0
// Stack: {}
IL_2F: nop # Pop0->Push0
// Stack: {}
IL_30: nop # Pop0->Push0
// Stack: {}
IL_31: ldloc V_2 # Pop0->Push1
// Stack: {IL_31}
IL_32: ldc.i4 1 # Pop0->Pushi
// Stack: {IL_31, IL_32}
IL_33: add.ovf # Pop1_pop1->Push1
// Stack: {IL_33}
IL_34: stloc V_2 # Pop1->Push0
// Stack: {}
IL_35: ldloc V_2 # Pop0->Push1
// Stack: {IL_35}
IL_36: ldarg right # Pop0->Push1
// Stack: {IL_35, IL_36}
IL_37: clt # Pop1_pop1->Pushi
// Stack: {IL_37}
IL_39: stloc V_4 # Pop1->Push0
// Stack: {}
IL_3B: ldloc V_4 # Pop0->Push1
// Stack: {IL_3B}
IL_3D: brtrue IL_14 # Popi->Push0 Flow=Cond_Branch
// Stack: {}
IL_3F: ldarg array # Pop0->Push1
// Stack: {IL_3F}
IL_40: ldarg right # Pop0->Push1
// Stack: {IL_3F, IL_40}
IL_41: ldloc V_1 # Pop0->Push1
// Stack: {IL_3F, IL_40, IL_41}
IL_42: call Swap() # Varpop->Varpush Flow=Call
// Stack: {}
IL_47: nop # Pop0->Push0
// Stack: {}
IL_48: ldloc V_1 # Pop0->Push1
// Stack: {IL_48}
IL_49: stloc V_3 # Pop1->Push0
// Stack: {}
IL_4A: br IL_4C # Pop0->Push0 Flow=Branch
// Stack: {}
IL_4C: ldloc V_3 # Pop0->Push1
// Stack: {IL_4C}
IL_4D: ret # Varpop->Push0 Flow=Return
// Stack: {}
}
private static void Swap(System.Int32[] array, int index1, int index2)
{
IL_00: nop # Pop0->Push0
// Stack: {}
IL_01: ldarg array # Pop0->Push1
// Stack: {IL_01}
IL_02: ldarg index1 # Pop0->Push1
// Stack: {IL_01, IL_02}
IL_03: ldelem.i4 # Popref_popi->Pushi
// Stack: {IL_03}
IL_04: stloc V_0 # Pop1->Push0
// Stack: {}
IL_05: ldarg array # Pop0->Push1
// Stack: {IL_05}
IL_06: ldarg index1 # Pop0->Push1
// Stack: {IL_05, IL_06}
IL_07: ldarg array # Pop0->Push1
// Stack: {IL_05, IL_06, IL_07}
IL_08: ldarg index2 # Pop0->Push1
// Stack: {IL_05, IL_06, IL_07, IL_08}
IL_09: ldelem.i4 # Popref_popi->Pushi
// Stack: {IL_05, IL_06, IL_09}
IL_0A: stelem.i4 # Popref_popi_popi->Push0
// Stack: {}
IL_0B: ldarg array # Pop0->Push1
// Stack: {IL_0B}
IL_0C: ldarg index2 # Pop0->Push1
// Stack: {IL_0B, IL_0C}
IL_0D: ldloc V_0 # Pop0->Push1
// Stack: {IL_0B, IL_0C, IL_0D}
IL_0E: stelem.i4 # Popref_popi_popi->Push0
// Stack: {}
IL_0F: ret # Varpop->Push0 Flow=Return
// Stack: {}
}
}
}

190
doc/Dissertation/Evolution/02_Peephole_decompilation.cs

@ -1,190 +0,0 @@ @@ -1,190 +0,0 @@
abstract class QuickSortProgram
{
public static void Main(System.String[] args)
{
IL_00: // No-op
IL_01: System.String[] expr01 = args;
IL_02: int expr02 = arg1.Length;
IL_03: int expr03 = (Int32)arg1;
IL_04: object expr04 = new int[arg1];
IL_09: V_0 = arg1;
IL_0A: short expr0A = 0;
IL_0B: V_1 = arg1;
IL_0C: goto IL_1F;
IL_0E: // No-op
IL_0F: System.Int32[] expr0F = V_0;
IL_10: int expr10 = V_1;
IL_11: System.String[] expr11 = args;
IL_12: int expr12 = V_1;
IL_13: object expr13 = arg1[arg2];
IL_14: int expr14 = System.Int32.Parse(arg0);
IL_19: arg1[arg2] = arg3;
IL_1A: // No-op
IL_1B: int expr1B = V_1;
IL_1C: short expr1C = 1;
IL_1D: int expr1D = arg1 + arg2;
IL_1E: V_1 = arg1;
IL_1F: int expr1F = V_1;
IL_20: System.Int32[] expr20 = V_0;
IL_21: int expr21 = arg1.Length;
IL_22: int expr22 = (Int32)arg1;
IL_23: bool expr23 = arg1 < arg2;
IL_25: V_2 = arg1;
IL_26: bool expr26 = V_2;
IL_27: if (arg1) goto IL_0E;
IL_29: System.Int32[] expr29 = V_0;
IL_2A: short expr2A = 0;
IL_2B: System.Int32[] expr2B = V_0;
IL_2C: int expr2C = arg1.Length;
IL_2D: int expr2D = (Int32)arg1;
IL_2E: short expr2E = 1;
IL_2F: int expr2F = arg1 - arg2;
IL_30: QuickSortProgram.QuickSort(arg0, arg1, arg2);
IL_35: // No-op
IL_36: short expr36 = 0;
IL_37: V_1 = arg1;
IL_38: goto IL_5C;
IL_3A: // No-op
IL_3B: System.Int32[] expr3B = V_0;
IL_3C: int expr3C = V_1;
IL_3D: object expr3D = arg1[arg2];
IL_42: string expr42 = arg1.ToString();
IL_47: string expr47 = " ";
IL_4C: string expr4C = System.String.Concat(arg0, arg1);
IL_51: System.Console.Write(arg0);
IL_56: // No-op
IL_57: // No-op
IL_58: int expr58 = V_1;
IL_59: short expr59 = 1;
IL_5A: int expr5A = arg1 + arg2;
IL_5B: V_1 = arg1;
IL_5C: int expr5C = V_1;
IL_5D: System.Int32[] expr5D = V_0;
IL_5E: int expr5E = arg1.Length;
IL_5F: int expr5F = (Int32)arg1;
IL_60: bool expr60 = arg1 < arg2;
IL_62: V_2 = arg1;
IL_63: bool expr63 = V_2;
IL_64: if (arg1) goto IL_3A;
IL_66: return;
}
public static void QuickSort(System.Int32[] array, int left, int right)
{
IL_00: // No-op
IL_01: int expr01 = right;
IL_02: int expr02 = left;
IL_03: bool expr03 = arg1 > arg2;
IL_05: short expr05 = 0;
IL_06: bool expr06 = arg1 == arg2;
IL_08: V_2 = arg1;
IL_09: bool expr09 = V_2;
IL_0A: if (arg1) goto IL_34;
IL_0C: // No-op
IL_0D: int expr0D = left;
IL_0E: int expr0E = right;
IL_0F: int expr0F = arg1 + arg2;
IL_10: short expr10 = 2;
IL_11: int expr11 = arg1 / arg2;
IL_12: V_0 = arg1;
IL_13: System.Int32[] expr13 = array;
IL_14: int expr14 = left;
IL_15: int expr15 = right;
IL_16: int expr16 = V_0;
IL_17: int expr17 = QuickSortProgram.Partition(arg0, arg1, arg2, arg3);
IL_1C: V_1 = arg1;
IL_1D: System.Int32[] expr1D = array;
IL_1E: int expr1E = left;
IL_1F: int expr1F = V_1;
IL_20: short expr20 = 1;
IL_21: int expr21 = arg1 - arg2;
IL_22: QuickSortProgram.QuickSort(arg0, arg1, arg2);
IL_27: // No-op
IL_28: System.Int32[] expr28 = array;
IL_29: int expr29 = V_1;
IL_2A: short expr2A = 1;
IL_2B: int expr2B = arg1 + arg2;
IL_2C: int expr2C = right;
IL_2D: QuickSortProgram.QuickSort(arg0, arg1, arg2);
IL_32: // No-op
IL_33: // No-op
IL_34: return;
}
private static int Partition(System.Int32[] array, int left, int right, int pivotIndex)
{
IL_00: // No-op
IL_01: System.Int32[] expr01 = array;
IL_02: int expr02 = pivotIndex;
IL_03: int expr03 = arg1[arg2];
IL_04: V_0 = arg1;
IL_05: System.Int32[] expr05 = array;
IL_06: int expr06 = pivotIndex;
IL_07: int expr07 = right;
IL_08: QuickSortProgram.Swap(arg0, arg1, arg2);
IL_0D: // No-op
IL_0E: int expr0E = left;
IL_0F: V_1 = arg1;
IL_10: int expr10 = left;
IL_11: V_2 = arg1;
IL_12: goto IL_35;
IL_14: // No-op
IL_15: System.Int32[] expr15 = array;
IL_16: int expr16 = V_2;
IL_17: int expr17 = arg1[arg2];
IL_18: int expr18 = V_0;
IL_19: bool expr19 = arg1 > arg2;
IL_1B: V_4 = arg1;
IL_1D: bool expr1D = V_4;
IL_1F: if (arg1) goto IL_30;
IL_21: // No-op
IL_22: System.Int32[] expr22 = array;
IL_23: int expr23 = V_1;
IL_24: int expr24 = V_2;
IL_25: QuickSortProgram.Swap(arg0, arg1, arg2);
IL_2A: // No-op
IL_2B: int expr2B = V_1;
IL_2C: short expr2C = 1;
IL_2D: int expr2D = arg1 + arg2;
IL_2E: V_1 = arg1;
IL_2F: // No-op
IL_30: // No-op
IL_31: int expr31 = V_2;
IL_32: short expr32 = 1;
IL_33: int expr33 = arg1 + arg2;
IL_34: V_2 = arg1;
IL_35: int expr35 = V_2;
IL_36: int expr36 = right;
IL_37: bool expr37 = arg1 < arg2;
IL_39: V_4 = arg1;
IL_3B: bool expr3B = V_4;
IL_3D: if (arg1) goto IL_14;
IL_3F: System.Int32[] expr3F = array;
IL_40: int expr40 = right;
IL_41: int expr41 = V_1;
IL_42: QuickSortProgram.Swap(arg0, arg1, arg2);
IL_47: // No-op
IL_48: int expr48 = V_1;
IL_49: V_3 = arg1;
IL_4A: goto IL_4C;
IL_4C: int expr4C = V_3;
IL_4D: return arg1;
}
private static void Swap(System.Int32[] array, int index1, int index2)
{
IL_00: // No-op
IL_01: System.Int32[] expr01 = array;
IL_02: int expr02 = index1;
IL_03: int expr03 = arg1[arg2];
IL_04: V_0 = arg1;
IL_05: System.Int32[] expr05 = array;
IL_06: int expr06 = index1;
IL_07: System.Int32[] expr07 = array;
IL_08: int expr08 = index2;
IL_09: int expr09 = arg1[arg2];
IL_0A: arg1[arg2] = arg3;
IL_0B: System.Int32[] expr0B = array;
IL_0C: int expr0C = index2;
IL_0D: int expr0D = V_0;
IL_0E: arg1[arg2] = arg3;
IL_0F: return;
}
}

203
doc/Dissertation/Evolution/03_Dataflow.cs

@ -1,203 +0,0 @@ @@ -1,203 +0,0 @@
using System;
abstract class QuickSortProgram
{
public static void Main(System.String[] args)
{
System.Int32[] V_0;
int V_1;
bool V_2;
// No-op
System.String[] expr01 = args;
int expr02 = expr01.Length;
int expr03 = (Int32)expr02;
System.Int32[] expr04 = new int[expr03];
V_0 = expr04;
int expr0A = 0;
V_1 = expr0A;
goto IL_1F;
IL_0E: // No-op
System.Int32[] expr0F = V_0;
int expr10 = V_1;
System.String[] expr11 = args;
int expr12 = V_1;
string expr13 = expr11[expr12];
int expr14 = System.Int32.Parse(expr13);
expr0F[expr10] = expr14;
// No-op
int expr1B = V_1;
int expr1C = 1;
int expr1D = expr1B + expr1C;
V_1 = expr1D;
IL_1F: int expr1F = V_1;
System.Int32[] expr20 = V_0;
int expr21 = expr20.Length;
int expr22 = (Int32)expr21;
bool expr23 = expr1F < expr22;
V_2 = expr23;
bool expr26 = V_2;
if (expr26) goto IL_0E;
System.Int32[] expr29 = V_0;
int expr2A = 0;
System.Int32[] expr2B = V_0;
int expr2C = expr2B.Length;
int expr2D = (Int32)expr2C;
int expr2E = 1;
int expr2F = expr2D - expr2E;
QuickSortProgram.QuickSort(expr29, expr2A, expr2F);
// No-op
int expr36 = 0;
V_1 = expr36;
goto IL_5C;
IL_3A: // No-op
System.Int32[] expr3B = V_0;
int expr3C = V_1;
object expr3D = expr3B[expr3C];
string expr42 = expr3D.ToString();
string expr47 = " ";
string expr4C = System.String.Concat(expr42, expr47);
System.Console.Write(expr4C);
// No-op
// No-op
int expr58 = V_1;
int expr59 = 1;
int expr5A = expr58 + expr59;
V_1 = expr5A;
IL_5C: int expr5C = V_1;
System.Int32[] expr5D = V_0;
int expr5E = expr5D.Length;
int expr5F = (Int32)expr5E;
bool expr60 = expr5C < expr5F;
V_2 = expr60;
bool expr63 = V_2;
if (expr63) goto IL_3A;
return;
}
public static void QuickSort(System.Int32[] array, int left, int right)
{
int V_0;
int V_1;
bool V_2;
// No-op
int expr01 = right;
int expr02 = left;
bool expr03 = expr01 > expr02;
int expr05 = 0;
bool expr06 = expr03 == (expr05 != 0);
V_2 = expr06;
bool expr09 = V_2;
if (expr09) goto IL_34;
// No-op
int expr0D = left;
int expr0E = right;
int expr0F = expr0D + expr0E;
int expr10 = 2;
int expr11 = expr0F / expr10;
V_0 = expr11;
System.Int32[] expr13 = array;
int expr14 = left;
int expr15 = right;
int expr16 = V_0;
int expr17 = QuickSortProgram.Partition(expr13, expr14, expr15, expr16);
V_1 = expr17;
System.Int32[] expr1D = array;
int expr1E = left;
int expr1F = V_1;
int expr20 = 1;
int expr21 = expr1F - expr20;
QuickSortProgram.QuickSort(expr1D, expr1E, expr21);
// No-op
System.Int32[] expr28 = array;
int expr29 = V_1;
int expr2A = 1;
int expr2B = expr29 + expr2A;
int expr2C = right;
QuickSortProgram.QuickSort(expr28, expr2B, expr2C);
// No-op
// No-op
IL_34: return;
}
private static int Partition(System.Int32[] array, int left, int right, int pivotIndex)
{
int V_0;
int V_1;
int V_2;
int V_3;
bool V_4;
// No-op
System.Int32[] expr01 = array;
int expr02 = pivotIndex;
int expr03 = expr01[expr02];
V_0 = expr03;
System.Int32[] expr05 = array;
int expr06 = pivotIndex;
int expr07 = right;
QuickSortProgram.Swap(expr05, expr06, expr07);
// No-op
int expr0E = left;
V_1 = expr0E;
int expr10 = left;
V_2 = expr10;
goto IL_35;
IL_14: // No-op
System.Int32[] expr15 = array;
int expr16 = V_2;
int expr17 = expr15[expr16];
int expr18 = V_0;
bool expr19 = expr17 > expr18;
V_4 = expr19;
bool expr1D = V_4;
if (expr1D) goto IL_30;
// No-op
System.Int32[] expr22 = array;
int expr23 = V_1;
int expr24 = V_2;
QuickSortProgram.Swap(expr22, expr23, expr24);
// No-op
int expr2B = V_1;
int expr2C = 1;
int expr2D = expr2B + expr2C;
V_1 = expr2D;
// No-op
IL_30: // No-op
int expr31 = V_2;
int expr32 = 1;
int expr33 = expr31 + expr32;
V_2 = expr33;
IL_35: int expr35 = V_2;
int expr36 = right;
bool expr37 = expr35 < expr36;
V_4 = expr37;
bool expr3B = V_4;
if (expr3B) goto IL_14;
System.Int32[] expr3F = array;
int expr40 = right;
int expr41 = V_1;
QuickSortProgram.Swap(expr3F, expr40, expr41);
// No-op
int expr48 = V_1;
V_3 = expr48;
goto IL_4C;
IL_4C: int expr4C = V_3;
return expr4C;
}
private static void Swap(System.Int32[] array, int index1, int index2)
{
int V_0;
// No-op
System.Int32[] expr01 = array;
int expr02 = index1;
int expr03 = expr01[expr02];
V_0 = expr03;
System.Int32[] expr05 = array;
int expr06 = index1;
System.Int32[] expr07 = array;
int expr08 = index2;
int expr09 = expr07[expr08];
expr05[expr06] = expr09;
System.Int32[] expr0B = array;
int expr0C = index2;
int expr0D = V_0;
expr0B[expr0C] = expr0D;
return;
}
}

378
doc/Dissertation/Evolution/03_Dataflow_Comments.cs

@ -1,378 +0,0 @@ @@ -1,378 +0,0 @@
using System;
abstract class QuickSortProgram
{
public static void Main(System.String[] args)
{
System.Int32[] V_0;
int V_1;
bool V_2;
// No-op
// Stack: {}
System.String[] expr01 = args;
// Stack: {expr01}
int expr02 = expr01.Length;
// Stack: {expr02}
int expr03 = (Int32)expr02;
// Stack: {expr03}
System.Int32[] expr04 = new int[expr03];
// Stack: {expr04}
V_0 = expr04;
// Stack: {}
int expr0A = 0;
// Stack: {expr0A}
V_1 = expr0A;
// Stack: {}
goto IL_1F;
// Stack: {}
IL_0E: // No-op
// Stack: {}
System.Int32[] expr0F = V_0;
// Stack: {expr0F}
int expr10 = V_1;
// Stack: {expr0F, expr10}
System.String[] expr11 = args;
// Stack: {expr0F, expr10, expr11}
int expr12 = V_1;
// Stack: {expr0F, expr10, expr11, expr12}
string expr13 = expr11[expr12];
// Stack: {expr0F, expr10, expr13}
int expr14 = System.Int32.Parse(expr13);
// Stack: {expr0F, expr10, expr14}
expr0F[expr10] = expr14;
// Stack: {}
// No-op
// Stack: {}
int expr1B = V_1;
// Stack: {expr1B}
int expr1C = 1;
// Stack: {expr1B, expr1C}
int expr1D = expr1B + expr1C;
// Stack: {expr1D}
V_1 = expr1D;
// Stack: {}
IL_1F: int expr1F = V_1;
// Stack: {expr1F}
System.Int32[] expr20 = V_0;
// Stack: {expr1F, expr20}
int expr21 = expr20.Length;
// Stack: {expr1F, expr21}
int expr22 = (Int32)expr21;
// Stack: {expr1F, expr22}
bool expr23 = expr1F < expr22;
// Stack: {expr23}
V_2 = expr23;
// Stack: {}
bool expr26 = V_2;
// Stack: {expr26}
if (expr26) goto IL_0E;
// Stack: {}
System.Int32[] expr29 = V_0;
// Stack: {expr29}
int expr2A = 0;
// Stack: {expr29, expr2A}
System.Int32[] expr2B = V_0;
// Stack: {expr29, expr2A, expr2B}
int expr2C = expr2B.Length;
// Stack: {expr29, expr2A, expr2C}
int expr2D = (Int32)expr2C;
// Stack: {expr29, expr2A, expr2D}
int expr2E = 1;
// Stack: {expr29, expr2A, expr2D, expr2E}
int expr2F = expr2D - expr2E;
// Stack: {expr29, expr2A, expr2F}
QuickSortProgram.QuickSort(expr29, expr2A, expr2F);
// Stack: {}
// No-op
// Stack: {}
int expr36 = 0;
// Stack: {expr36}
V_1 = expr36;
// Stack: {}
goto IL_5C;
// Stack: {}
IL_3A: // No-op
// Stack: {}
System.Int32[] expr3B = V_0;
// Stack: {expr3B}
int expr3C = V_1;
// Stack: {expr3B, expr3C}
object expr3D = expr3B[expr3C];
// Stack: {expr3D}
string expr42 = expr3D.ToString();
// Stack: {expr42}
string expr47 = " ";
// Stack: {expr42, expr47}
string expr4C = System.String.Concat(expr42, expr47);
// Stack: {expr4C}
System.Console.Write(expr4C);
// Stack: {}
// No-op
// Stack: {}
// No-op
// Stack: {}
int expr58 = V_1;
// Stack: {expr58}
int expr59 = 1;
// Stack: {expr58, expr59}
int expr5A = expr58 + expr59;
// Stack: {expr5A}
V_1 = expr5A;
// Stack: {}
IL_5C: int expr5C = V_1;
// Stack: {expr5C}
System.Int32[] expr5D = V_0;
// Stack: {expr5C, expr5D}
int expr5E = expr5D.Length;
// Stack: {expr5C, expr5E}
int expr5F = (Int32)expr5E;
// Stack: {expr5C, expr5F}
bool expr60 = expr5C < expr5F;
// Stack: {expr60}
V_2 = expr60;
// Stack: {}
bool expr63 = V_2;
// Stack: {expr63}
if (expr63) goto IL_3A;
// Stack: {}
return;
// Stack: {}
}
public static void QuickSort(System.Int32[] array, int left, int right)
{
int V_0;
int V_1;
bool V_2;
// No-op
// Stack: {}
int expr01 = right;
// Stack: {expr01}
int expr02 = left;
// Stack: {expr01, expr02}
bool expr03 = expr01 > expr02;
// Stack: {expr03}
int expr05 = 0;
// Stack: {expr03, expr05}
bool expr06 = expr03 == (expr05 != 0);
// Stack: {expr06}
V_2 = expr06;
// Stack: {}
bool expr09 = V_2;
// Stack: {expr09}
if (expr09) goto IL_34;
// Stack: {}
// No-op
// Stack: {}
int expr0D = left;
// Stack: {expr0D}
int expr0E = right;
// Stack: {expr0D, expr0E}
int expr0F = expr0D + expr0E;
// Stack: {expr0F}
int expr10 = 2;
// Stack: {expr0F, expr10}
int expr11 = expr0F / expr10;
// Stack: {expr11}
V_0 = expr11;
// Stack: {}
System.Int32[] expr13 = array;
// Stack: {expr13}
int expr14 = left;
// Stack: {expr13, expr14}
int expr15 = right;
// Stack: {expr13, expr14, expr15}
int expr16 = V_0;
// Stack: {expr13, expr14, expr15, expr16}
int expr17 = QuickSortProgram.Partition(expr13, expr14, expr15, expr16);
// Stack: {expr17}
V_1 = expr17;
// Stack: {}
System.Int32[] expr1D = array;
// Stack: {expr1D}
int expr1E = left;
// Stack: {expr1D, expr1E}
int expr1F = V_1;
// Stack: {expr1D, expr1E, expr1F}
int expr20 = 1;
// Stack: {expr1D, expr1E, expr1F, expr20}
int expr21 = expr1F - expr20;
// Stack: {expr1D, expr1E, expr21}
QuickSortProgram.QuickSort(expr1D, expr1E, expr21);
// Stack: {}
// No-op
// Stack: {}
System.Int32[] expr28 = array;
// Stack: {expr28}
int expr29 = V_1;
// Stack: {expr28, expr29}
int expr2A = 1;
// Stack: {expr28, expr29, expr2A}
int expr2B = expr29 + expr2A;
// Stack: {expr28, expr2B}
int expr2C = right;
// Stack: {expr28, expr2B, expr2C}
QuickSortProgram.QuickSort(expr28, expr2B, expr2C);
// Stack: {}
// No-op
// Stack: {}
// No-op
// Stack: {}
IL_34: return;
// Stack: {}
}
private static int Partition(System.Int32[] array, int left, int right, int pivotIndex)
{
int V_0;
int V_1;
int V_2;
int V_3;
bool V_4;
// No-op
// Stack: {}
System.Int32[] expr01 = array;
// Stack: {expr01}
int expr02 = pivotIndex;
// Stack: {expr01, expr02}
int expr03 = expr01[expr02];
// Stack: {expr03}
V_0 = expr03;
// Stack: {}
System.Int32[] expr05 = array;
// Stack: {expr05}
int expr06 = pivotIndex;
// Stack: {expr05, expr06}
int expr07 = right;
// Stack: {expr05, expr06, expr07}
QuickSortProgram.Swap(expr05, expr06, expr07);
// Stack: {}
// No-op
// Stack: {}
int expr0E = left;
// Stack: {expr0E}
V_1 = expr0E;
// Stack: {}
int expr10 = left;
// Stack: {expr10}
V_2 = expr10;
// Stack: {}
goto IL_35;
// Stack: {}
IL_14: // No-op
// Stack: {}
System.Int32[] expr15 = array;
// Stack: {expr15}
int expr16 = V_2;
// Stack: {expr15, expr16}
int expr17 = expr15[expr16];
// Stack: {expr17}
int expr18 = V_0;
// Stack: {expr17, expr18}
bool expr19 = expr17 > expr18;
// Stack: {expr19}
V_4 = expr19;
// Stack: {}
bool expr1D = V_4;
// Stack: {expr1D}
if (expr1D) goto IL_30;
// Stack: {}
// No-op
// Stack: {}
System.Int32[] expr22 = array;
// Stack: {expr22}
int expr23 = V_1;
// Stack: {expr22, expr23}
int expr24 = V_2;
// Stack: {expr22, expr23, expr24}
QuickSortProgram.Swap(expr22, expr23, expr24);
// Stack: {}
// No-op
// Stack: {}
int expr2B = V_1;
// Stack: {expr2B}
int expr2C = 1;
// Stack: {expr2B, expr2C}
int expr2D = expr2B + expr2C;
// Stack: {expr2D}
V_1 = expr2D;
// Stack: {}
// No-op
// Stack: {}
IL_30: // No-op
// Stack: {}
int expr31 = V_2;
// Stack: {expr31}
int expr32 = 1;
// Stack: {expr31, expr32}
int expr33 = expr31 + expr32;
// Stack: {expr33}
V_2 = expr33;
// Stack: {}
IL_35: int expr35 = V_2;
// Stack: {expr35}
int expr36 = right;
// Stack: {expr35, expr36}
bool expr37 = expr35 < expr36;
// Stack: {expr37}
V_4 = expr37;
// Stack: {}
bool expr3B = V_4;
// Stack: {expr3B}
if (expr3B) goto IL_14;
// Stack: {}
System.Int32[] expr3F = array;
// Stack: {expr3F}
int expr40 = right;
// Stack: {expr3F, expr40}
int expr41 = V_1;
// Stack: {expr3F, expr40, expr41}
QuickSortProgram.Swap(expr3F, expr40, expr41);
// Stack: {}
// No-op
// Stack: {}
int expr48 = V_1;
// Stack: {expr48}
V_3 = expr48;
// Stack: {}
goto IL_4C;
// Stack: {}
IL_4C: int expr4C = V_3;
// Stack: {expr4C}
return expr4C;
// Stack: {}
}
private static void Swap(System.Int32[] array, int index1, int index2)
{
int V_0;
// No-op
// Stack: {}
System.Int32[] expr01 = array;
// Stack: {expr01}
int expr02 = index1;
// Stack: {expr01, expr02}
int expr03 = expr01[expr02];
// Stack: {expr03}
V_0 = expr03;
// Stack: {}
System.Int32[] expr05 = array;
// Stack: {expr05}
int expr06 = index1;
// Stack: {expr05, expr06}
System.Int32[] expr07 = array;
// Stack: {expr05, expr06, expr07}
int expr08 = index2;
// Stack: {expr05, expr06, expr07, expr08}
int expr09 = expr07[expr08];
// Stack: {expr05, expr06, expr09}
expr05[expr06] = expr09;
// Stack: {}
System.Int32[] expr0B = array;
// Stack: {expr0B}
int expr0C = index2;
// Stack: {expr0B, expr0C}
int expr0D = V_0;
// Stack: {expr0B, expr0C, expr0D}
expr0B[expr0C] = expr0D;
// Stack: {}
return;
// Stack: {}
}
}

49
doc/Dissertation/Evolution/04_Inline_expressions.cs

@ -1,49 +0,0 @@ @@ -1,49 +0,0 @@
using System;
abstract class QuickSortProgram
{
public static void Main(System.String[] args)
{
System.Int32[] V_0 = new int[((Int32)args.Length)];
int V_1 = 0;
goto IL_1C;
IL_0D: V_0[V_1] = System.Int32.Parse(args[V_1]);
V_1 = (V_1 + 1);
IL_1C: if (V_1 < ((Int32)V_0.Length)) goto IL_0D;
QuickSortProgram.QuickSort(V_0, 0, (((Int32)V_0.Length) - 1));
int V_2 = 0;
goto IL_51;
IL_32: System.Console.Write(System.String.Concat((V_0[V_2]).ToString(), " "));
V_2 = (V_2 + 1);
IL_51: if (V_2 < ((Int32)V_0.Length)) goto IL_32;
}
public static void QuickSort(System.Int32[] array, int left, int right)
{
if (right <= left) goto IL_28;
int V_0 = ((left + right) / 2);
int V_1 = QuickSortProgram.Partition(array, left, right, V_0);
QuickSortProgram.QuickSort(array, left, (V_1 - 1));
QuickSortProgram.QuickSort(array, (V_1 + 1), right);
IL_28: return;
}
private static int Partition(System.Int32[] array, int left, int right, int pivotIndex)
{
int V_0 = array[pivotIndex];
QuickSortProgram.Swap(array, pivotIndex, right);
int V_1 = left;
int V_2 = left;
goto IL_28;
IL_12: if (array[V_2] > V_0) goto IL_24;
QuickSortProgram.Swap(array, V_1, V_2);
V_1 = (V_1 + 1);
IL_24: V_2 = (V_2 + 1);
IL_28: if (V_2 < right) goto IL_12;
QuickSortProgram.Swap(array, right, V_1);
return V_1;
}
private static void Swap(System.Int32[] array, int index1, int index2)
{
int V_0 = array[index1];
array[index1] = array[index2];
array[index2] = V_0;
}
}

78
doc/Dissertation/Evolution/05_Find_basic_blocks.cs

@ -1,78 +0,0 @@ @@ -1,78 +0,0 @@
using System;
abstract class QuickSortProgram
{
public static void Main(System.String[] args)
{
BasicBlock_1:
System.Int32[] V_0 = new int[((int)args.Length)];
int i = 0;
goto BasicBlock_3;
BasicBlock_2:
V_0[i] = System.Int32.Parse(args[i]);
i = (i + 1);
goto BasicBlock_3;
BasicBlock_3:
if (i < ((int)V_0.Length)) goto BasicBlock_2;
goto BasicBlock_4;
BasicBlock_4:
QuickSortProgram.QuickSort(V_0, 0, (((int)V_0.Length) - 1));
int j = 0;
goto BasicBlock_6;
BasicBlock_5:
System.Console.Write(System.String.Concat((V_0[j]).ToString(), " "));
j = (j + 1);
goto BasicBlock_6;
BasicBlock_6:
if (j < ((int)V_0.Length)) goto BasicBlock_5;
goto BasicBlock_7;
BasicBlock_7:
return;
}
public static void QuickSort(System.Int32[] array, int left, int right)
{
BasicBlock_9:
if (right <= left) goto BasicBlock_11;
goto BasicBlock_10;
BasicBlock_10:
int i = ((left + right) / 2);
int j = QuickSortProgram.Partition(array, left, right, i);
QuickSortProgram.QuickSort(array, left, (j - 1));
QuickSortProgram.QuickSort(array, (j + 1), right);
goto BasicBlock_11;
BasicBlock_11:
return;
}
private static int Partition(System.Int32[] array, int left, int right, int pivotIndex)
{
BasicBlock_13:
int i = array[pivotIndex];
QuickSortProgram.Swap(array, pivotIndex, right);
int j = left;
int k = left;
goto BasicBlock_17;
BasicBlock_14:
if (array[k] > i) goto BasicBlock_16;
goto BasicBlock_15;
BasicBlock_15:
QuickSortProgram.Swap(array, j, k);
j = (j + 1);
goto BasicBlock_16;
BasicBlock_16:
k = (k + 1);
goto BasicBlock_17;
BasicBlock_17:
if (k < right) goto BasicBlock_14;
goto BasicBlock_18;
BasicBlock_18:
QuickSortProgram.Swap(array, right, j);
return j;
}
private static void Swap(System.Int32[] array, int index1, int index2)
{
BasicBlock_20:
int i = array[index1];
array[index1] = array[index2];
array[index2] = i;
return;
}
}

87
doc/Dissertation/Evolution/06_Find_loops.cs

@ -1,87 +0,0 @@ @@ -1,87 +0,0 @@
using System;
abstract class QuickSortProgram
{
public static void Main(System.String[] args)
{
BasicBlock_1:
System.Int32[] V_0 = new int[((int)args.Length)];
int i = 0;
goto Loop_8;
Loop_8:
for (;;) {
BasicBlock_3:
if (i < ((int)V_0.Length)) goto BasicBlock_2;
break;
BasicBlock_2:
V_0[i] = System.Int32.Parse(args[i]);
i = (i + 1);
continue;
}
BasicBlock_4:
QuickSortProgram.QuickSort(V_0, 0, (((int)V_0.Length) - 1));
int j = 0;
goto Loop_11;
Loop_11:
for (;;) {
BasicBlock_6:
if (j < ((int)V_0.Length)) goto BasicBlock_5;
break;
BasicBlock_5:
System.Console.Write(System.String.Concat((V_0[j]).ToString(), " "));
j = (j + 1);
continue;
}
BasicBlock_7:
return;
}
public static void QuickSort(System.Int32[] array, int left, int right)
{
BasicBlock_15:
if (right <= left) goto BasicBlock_17;
goto BasicBlock_16;
BasicBlock_16:
int i = ((left + right) / 2);
int j = QuickSortProgram.Partition(array, left, right, i);
QuickSortProgram.QuickSort(array, left, (j - 1));
QuickSortProgram.QuickSort(array, (j + 1), right);
goto BasicBlock_17;
BasicBlock_17:
return;
}
private static int Partition(System.Int32[] array, int left, int right, int pivotIndex)
{
BasicBlock_21:
int i = array[pivotIndex];
QuickSortProgram.Swap(array, pivotIndex, right);
int j = left;
int k = left;
goto Loop_29;
Loop_29:
for (;;) {
BasicBlock_25:
if (k < right) goto BasicBlock_22;
break;
BasicBlock_22:
if (array[k] > i) goto BasicBlock_24;
goto BasicBlock_23;
BasicBlock_23:
QuickSortProgram.Swap(array, j, k);
j = (j + 1);
goto BasicBlock_24;
BasicBlock_24:
k = (k + 1);
continue;
}
BasicBlock_26:
QuickSortProgram.Swap(array, right, j);
return j;
}
private static void Swap(System.Int32[] array, int index1, int index2)
{
BasicBlock_33:
int i = array[index1];
array[index1] = array[index2];
array[index2] = i;
return;
}
}

122
doc/Dissertation/Evolution/07_Find_conditionals.cs

@ -1,122 +0,0 @@ @@ -1,122 +0,0 @@
using System;
abstract class QuickSortProgram
{
public static void Main(System.String[] args)
{
BasicBlock_1:
System.Int32[] V_0 = new int[((int)args.Length)];
int i = 0;
goto Loop_8;
Loop_8:
for (;;) {
ConditionalNode_16:
BasicBlock_3:
if (!(i < ((int)V_0.Length))) {
break;
Block_14:
}
else {
goto BasicBlock_2;
Block_15:
}
BasicBlock_2:
V_0[i] = System.Int32.Parse(args[i]);
i = (i + 1);
continue;
}
BasicBlock_4:
QuickSortProgram.QuickSort(V_0, 0, (((int)V_0.Length) - 1));
int j = 0;
goto Loop_11;
Loop_11:
for (;;) {
ConditionalNode_19:
BasicBlock_6:
if (!(j < ((int)V_0.Length))) {
break;
Block_17:
}
else {
goto BasicBlock_5;
Block_18:
}
BasicBlock_5:
System.Console.Write(System.String.Concat((V_0[j]).ToString(), " "));
j = (j + 1);
continue;
}
BasicBlock_7:
return;
}
public static void QuickSort(System.Int32[] array, int left, int right)
{
ConditionalNode_28:
BasicBlock_21:
if (!(right <= left)) {
goto Block_26;
Block_26:
BasicBlock_22:
int i = ((left + right) / 2);
int j = QuickSortProgram.Partition(array, left, right, i);
QuickSortProgram.QuickSort(array, left, (j - 1));
QuickSortProgram.QuickSort(array, (j + 1), right);
goto BasicBlock_23;
}
else {
goto BasicBlock_23;
Block_27:
}
BasicBlock_23:
return;
}
private static int Partition(System.Int32[] array, int left, int right, int pivotIndex)
{
BasicBlock_30:
int i = array[pivotIndex];
QuickSortProgram.Swap(array, pivotIndex, right);
int j = left;
int k = left;
goto Loop_38;
Loop_38:
for (;;) {
ConditionalNode_43:
BasicBlock_34:
if (!(k < right)) {
break;
Block_41:
}
else {
goto ConditionalNode_46;
Block_42:
}
ConditionalNode_46:
BasicBlock_31:
if (!(array[k] > i)) {
goto Block_44;
Block_44:
BasicBlock_32:
QuickSortProgram.Swap(array, j, k);
j = (j + 1);
goto BasicBlock_33;
}
else {
goto BasicBlock_33;
Block_45:
}
BasicBlock_33:
k = (k + 1);
continue;
}
BasicBlock_35:
QuickSortProgram.Swap(array, right, j);
return j;
}
private static void Swap(System.Int32[] array, int index1, int index2)
{
BasicBlock_48:
int i = array[index1];
array[index1] = array[index2];
array[index2] = i;
return;
}
}

69
doc/Dissertation/Evolution/08_Remove_dead_jumps.cs

@ -1,69 +0,0 @@ @@ -1,69 +0,0 @@
using System;
abstract class QuickSortProgram
{
public static void Main(System.String[] args)
{
System.Int32[] V_0 = new int[((int)args.Length)];
int i = 0;
for (;;) {
if (!(i < ((int)V_0.Length))) {
break;
}
else {
}
V_0[i] = System.Int32.Parse(args[i]);
i = (i + 1);
}
QuickSortProgram.QuickSort(V_0, 0, (((int)V_0.Length) - 1));
int j = 0;
for (;;) {
if (!(j < ((int)V_0.Length))) {
break;
}
else {
}
System.Console.Write(System.String.Concat((V_0[j]).ToString(), " "));
j = (j + 1);
}
}
public static void QuickSort(System.Int32[] array, int left, int right)
{
if (!(right <= left)) {
int i = ((left + right) / 2);
int j = QuickSortProgram.Partition(array, left, right, i);
QuickSortProgram.QuickSort(array, left, (j - 1));
QuickSortProgram.QuickSort(array, (j + 1), right);
}
else {
}
}
private static int Partition(System.Int32[] array, int left, int right, int pivotIndex)
{
int i = array[pivotIndex];
QuickSortProgram.Swap(array, pivotIndex, right);
int j = left;
int k = left;
for (;;) {
if (!(k < right)) {
break;
}
else {
}
if (!(array[k] > i)) {
QuickSortProgram.Swap(array, j, k);
j = (j + 1);
}
else {
}
k = (k + 1);
}
QuickSortProgram.Swap(array, right, j);
return j;
}
private static void Swap(System.Int32[] array, int index1, int index2)
{
int i = array[index1];
array[index1] = array[index2];
array[index2] = i;
}
}

51
doc/Dissertation/Evolution/09_Reduce_loops.cs

@ -1,51 +0,0 @@ @@ -1,51 +0,0 @@
using System;
abstract class QuickSortProgram
{
public static void Main(System.String[] args)
{
System.Int32[] V_0 = new int[((int)args.Length)];
for (int i = 0; (i < ((int)V_0.Length)); i = (i + 1)) {
V_0[i] = System.Int32.Parse(args[i]);
}
QuickSortProgram.QuickSort(V_0, 0, (((int)V_0.Length) - 1));
for (int j = 0; (j < ((int)V_0.Length)); j = (j + 1)) {
System.Console.Write(System.String.Concat((V_0[j]).ToString(), " "));
}
}
public static void QuickSort(System.Int32[] array, int left, int right)
{
if (!(right <= left)) {
int i = ((left + right) / 2);
int j = QuickSortProgram.Partition(array, left, right, i);
QuickSortProgram.QuickSort(array, left, (j - 1));
QuickSortProgram.QuickSort(array, (j + 1), right);
}
else {
}
}
private static int Partition(System.Int32[] array, int left, int right, int pivotIndex)
{
int i = array[pivotIndex];
QuickSortProgram.Swap(array, pivotIndex, right);
int j = left;
for (int k = left; (k < right); k = (k + 1)) {
if (!(array[k] > i)) {
QuickSortProgram.Swap(array, j, k);
j = (j + 1);
}
else {
}
}
QuickSortProgram.Swap(array, right, j);
return j;
}
private static void Swap(System.Int32[] array, int index1, int index2)
{
int i = array[index1];
array[index1] = array[index2];
array[index2] = i;
}
}

44
doc/Dissertation/Evolution/10_Short_type_names.cs

@ -1,44 +0,0 @@ @@ -1,44 +0,0 @@
using System;
abstract class QuickSortProgram
{
public static void Main(string[] args)
{
int[] V_0 = new int[((int)args.Length)];
for (int i = 0; (i < ((int)V_0.Length)); i = (i + 1)) {
V_0[i] = Int32.Parse(args[i]);
}
QuickSort(V_0, 0, (((int)V_0.Length) - 1));
for (int j = 0; (j < ((int)V_0.Length)); j = (j + 1)) {
Console.Write((V_0[j]).ToString() + " ");
}
}
public static void QuickSort(int[] array, int left, int right)
{
if (!(right <= left)) {
int i = ((left + right) / 2);
int j = Partition(array, left, right, i);
QuickSort(array, left, (j - 1));
QuickSort(array, (j + 1), right);
}
}
private static int Partition(int[] array, int left, int right, int pivotIndex)
{
int i = array[pivotIndex];
Swap(array, pivotIndex, right);
int j = left;
for (int k = left; (k < right); k = (k + 1)) {
if (!(array[k] > i)) {
Swap(array, j, k);
j = (j + 1);
}
}
Swap(array, right, j);
return j;
}
private static void Swap(int[] array, int index1, int index2)
{
int i = array[index1];
array[index1] = array[index2];
array[index2] = i;
}
}

43
doc/Dissertation/Evolution/QuickSort_original.cs

@ -1,43 +0,0 @@ @@ -1,43 +0,0 @@
static class QuickSortProgram
{
public static void Main(string[] args)
{
int[] intArray = new int[args.Length];
for (int i = 0; i < intArray.Length; i++) {
intArray[i] = int.Parse(args[i]);
}
QuickSort(intArray, 0, intArray.Length - 1);
for (int i = 0; i < intArray.Length; i++) {
System.Console.Write(intArray[i].ToString() + " ");
}
}
public static void QuickSort(int[] array, int left, int right)
{
if (right > left) {
int pivotIndex = (left + right) / 2;
int pivotNew = Partition(array, left, right, pivotIndex);
QuickSort(array, left, pivotNew - 1);
QuickSort(array, pivotNew + 1, right);
}
}
static int Partition(int[] array, int left, int right, int pivotIndex)
{
int pivotValue = array[pivotIndex];
Swap(array, pivotIndex, right);
int storeIndex = left;
for(int i = left; i < right; i++) {
if (array[i] <= pivotValue) {
Swap(array, storeIndex, i);
storeIndex = storeIndex + 1;
}
}
Swap(array, right, storeIndex);
return storeIndex;
}
static void Swap(int[] array, int index1, int index2)
{
int tmp = array[index1];
array[index1] = array[index2];
array[index2] = tmp;
}
}

BIN
doc/Dissertation/ProgressReport.pdf

Binary file not shown.

243
doc/Dissertation/ProgressReport.tex

@ -1,243 +0,0 @@ @@ -1,243 +0,0 @@
\documentclass[12pt]{article}
\usepackage{a4wide}
\usepackage{listings}
\parindent 0pt
\parskip 6pt
\begin{document}
\thispagestyle{empty}
\rightline{\large\emph{David Srbeck\'y}}
\medskip
\rightline{\large\emph{Jesus College}}
\medskip
\rightline{\large\emph{ds417}}
\vspace{0.675in}
\centerline{\large Progress Report}
\vspace{0.4in}
\centerline{\Large\bf .NET Decompiler}
\vspace{0.3in}
\centerline{\large\emph{January~30,~2008}}
\vspace{0.675in}
{\bf Project Originator:} \emph{David Srbeck\'y}
\vspace{0.1in}
{\bf Project Supervisor:} \emph{Alan Mycroft}
\vspace{0.1in}
{\bf Director of Studies:} \emph{Jean Bacon} and \emph{David Ingram}
\vspace{0.1in}
{\bf Overseers:} \emph{Anuj Dawar} and \emph{Andrew Moore}
\vspace{0.1in}
\vfil
\eject
\newcommand{\CS}{\emph{C\#} }
\lstset{
basicstyle=\small,
language={[Sharp]C},
tabsize=4,
numbers=left,
frame=single,
frameround=tfft
}
\section*{Work completed so far}
\subsection*{Disassemble \emph{.NET} bytecode}
The \emph{.NET} assembly is read using the \emph{Cecil} library
and the class structure is created. Method bodies contain the
disassembly of the IL bytecode. The debugging comment on the
right indicates the stack behavior of the given instruction.
This, of course, is not valid \CS code yet.
\lstinputlisting[lastline=32]
{./Evolution/01_Disassemble.cs}
\newpage
\subsection*{Start creating expressions}
The bytecodes are converted to \CS expressions on individual basis.
Only one bytecode is considered at a time and thus the expressions
are completely independent. The resulting output is a valid \CS code
which however does not compile since the dummy arguments \verb|arg1|,
\verb|arg2|, etc\dots{} are never defined. Conditional and unconditional
branches are converted to \verb|goto| goto statements.
\lstinputlisting[lastline=32]
{./Evolution/02_Peephole_decompilation.cs}
\newpage
\subsection*{Data-flow analysis}
The execution of the bytecode is simulated and the state of the stack is
recorded for each position. We are interested in the number of
elements on the stack as well as which instruction has pushed the
individual elements on the stack. This information can then be used to eliminate
the dummy \verb|arg1| arguments. Result of each instruction is stored
in new temporary variable. When an instruction pops a stack value
we look-up which instruction has allocated the value and use the temporary
variable of the allocating instruction.
This code compiles and works correctly.
\lstinputlisting[firstline=21, lastline=52]
{./Evolution/03_Dataflow_Comments.cs}
\newpage
\subsection*{In-lineing expressions}
Many of the temporary variables can be in-lined into the expressions in which
they are used. This is in general non-trivial optimization, however it is
simpler in this case since the temporary variables generated to store the
stack values are guaranteed to be single static assignment variables (the
variable is assigned only once during the push instruction and is used
only once during the pop instruction).
Having said that, we still need to check that doing the optimization is
safe with regards to expression evaluation order and with regrads to branching.
\lstinputlisting[firstline=1, lastline=32]
{./Evolution/04_Inline_expressions.cs}
\newpage
\subsection*{Finding basic blocks}
The first step of reconstructing any high-level structures is the
decomposition of the program into basic blocks. This is an easy
algorithm to implement.
I chose to use the following constraint for the output:
``Each basic block starts with a label and is exited by an explicit
\verb|goto| statement.''
Therefore except for the method entry, the order
of the blocks is completely irrelevant. Any swapping of the basic
blocks is not going change the semantics of the program in any way.
\lstinputlisting[firstline=1, lastline=30]
{./Evolution/05_Find_basic_blocks.cs}
\newpage
\subsection*{Finding loops}
The algorithm for finding loops is inspired by T1-T2 transformations.
T1-T2 transformations are used to determine whether a graph is
reducible or not. The core idea is that if a block of code has
only one predecessor then the block of code can be merged
with its predecessor to form a directed acyclic graph. Using this,
loops will reduce to single self-referencing nodes.
This also works for nested loops.
Note that merely adding a loop does not change the program in any way --
the loop is completely redundant as far as control flow goes.
The basic blocks still explicitly transfer control using \verb|goto|
statements, so the control flow never reaches the loop.
This is desirable property. It ensures that the program will run
correctly. The order of basic blocks and their nesting within loops
does not have any effect on program correctness.
The only advantage of the loop is readability and that some \verb|goto|
statements can be replaced by \verb|break| and \verb|continue| statements
if they have the same semantics in the given context.
\lstinputlisting[firstline=1, lastline=25]
{./Evolution/06_Find_loops.cs}
\newpage
\subsection*{Finding conditionals}
The current algorithm for finding conditionals works as follows:
First find a node that has two successors. Get all nodes accessible
\emph{only} from the `true' branch -- these form the `true' body of
the conditional. Similarly, all nodes accessible \emph{only} from the
`false' branch form the `false' body. The rest of the nodes is
not part of the conditional.
Similarly as for the loops, adding a conditional does not have any
effect on program correctness.
\lstinputlisting[firstline=1, lastline=32]
{./Evolution/07_Find_conditionals.cs}
\newpage
\subsection*{Remove dead jumps}
There are many \verb|goto| statements in the form:
\begin{verbatim}
goto BasicBlock_X;
BasicBlock_X:
\end{verbatim}
These \verb|goto| statement can be removed. As a result of
doing that, several labels will become dead; these can be
removed as well.
\lstinputlisting[firstline=1, lastline=32]
{./Evolution/08_Remove_dead_jumps.cs}
\newpage
\subsection*{Reduce loops}
It is common for loops to be preceded by a temporary variable
initialization, start by evaluating a condition and finally
end by doing an increment on a variable. We can look
for these patterns and if they are found move the code
to the \verb|for(;;)| part of the statement.
\lstinputlisting[firstline=1, lastline=32]
{./Evolution/09_Reduce_loops.cs}
\newpage
\subsection*{Clean up}
Finally some minor cleanups like removing empty statements and
simplifying type names.
\lstinputlisting[firstline=1, lastline=42]
{./Evolution/10_Short_type_names.cs}
\newpage
\subsection*{Original source code}
Here is the original source code for reference.
\lstinputlisting[firstline=1, lastline=41]
{./Evolution/QuickSort_original.cs}
\newpage
\subsection*{Unexpected difficulties}
The \emph{CodeDom} library that I have initially intended to use
to output source code in arbitrary \emph{.NET} language has turned out to be
quite incomplete. That is, since the library aims to be
able to represent source code for any language, it has
feature set limited to the lowest common denominator.
Therefore, I have switched to \emph{NRefactory} library which
is specifically designed with \CS and \emph{VB.NET} in mind.
Using \emph{T1-T2} transformations for loop finding turned out to be
a slightly more difficult since the algorithm is, after all,
originally intended to produce a yes or no answer to whether the graph
is reducible. However, it was not problematic to refactor
the idea to suit a different purpose.
\subsection*{Summary}
The project tasks were performed in the planned order and
the project is progressing according to the schedule.
The quality of decompilation of the Quick-Sort algorithm is
almost `as good as it gets' so I intend to look for some more
complex assembly to tackle.
\end{document}

356
doc/Dissertation/Proposal.tex

@ -1,356 +0,0 @@ @@ -1,356 +0,0 @@
%\thispagestyle{empty}
%\rightline{\large\emph{David Srbeck\'y}}
%\medskip
%\rightline{\large\emph{Jesus College}}
%\medskip
%\rightline{\large\emph{ds417}}
\vfil
\vspace{0.4in}
\centerline{\large Part II of the Computer Science Project Proposal}
\vspace{0.4in}
\centerline{\Large\bf .NET Decompiler}
\vspace{0.3in}
\centerline{\large\emph{October~14,~2007}}
\vfil
{\bf Project Originator:} \emph{David Srbeck\'y}
\vspace{0.1in}
{\bf Resources Required:} See attached Project Resource Form
\vspace{0.3in}
{\bf Project Supervisor:} \emph{Alan Mycroft}
\vspace{0.3in}
{\bf Director of Studies:} \emph{Jean Bacon} and \emph{David Ingram}
\vspace{0.3in}
{\bf Overseers:} \emph{Anuj Dawar} and \emph{Andrew Moore}
\vfil
\eject
\section*{Introduction and Description of the Work}
The \emph{.NET Framework} is a general-purpose software development platform
which is very similar to \emph{Java}. It includes extensive class library
and, similarly to Java, is based on the virtual machine model. The executable
code for a \emph{.NET} program is stored in a file called \emph{assembly}
which consists of class metadata and a stack-based bytecode called Common
Intermediate Language (\emph{CIL} or \emph{IL}).
In general, any programming language can be compiled to \emph{.NET} and
there are dozens of compilers that compile into \emph{CIL}. The most
common language used for \emph{.NET} development is \emph{C\#}.
The goal of this project is to decompile \emph{.NET} assemblies back into
equivalent \emph{C\#} source code. Compared to decompilation of
conventional assembly code, this task is hugely simplified by the
presence of metadata in the \emph{.NET} assemblies. The metadata contains
complete information about classes, methods and fields. The method bodies
consist of stack-based \emph{IL} code which needs to be decompiled into
higher-level \emph{C\#} statements. Data-flow analysis will need to be
employed to transform the stack-based data model into one that uses
temporary local variables and composition of expressions. Control-flow
analysis will be used to recreate high level control structures like
\verb|for| loops and conditional branching.
\section*{Resources Required}
\begin{itemize}
\item{\textbf{My own machine}\\
(1.6 GHz CPU, 1.5 GB of RAM, 50 GB \& 75 GB Disks,
Windows XP SP2 OS) \\
Used for development
}
\item{\textbf{Student-Run Computing Facility (SRCF)}\\
Used for running the \emph{SVN} server
}
\item{\textbf{Public Workstation Facility (PWF)}\\
Used for storage of back-ups
}
\end{itemize}
\newpage
\section*{Starting Point}
I plan to implement the project in \emph{C\#}. I have been using this
language for over five years now and so I do not have to spend any time
learning a new language. It also means that I will not be having any
problems neither with the syntax of the language nor with any peculiar
error messages produced by the compiler or by the runtime.
I have written an integrated \emph{.NET} debugger for the
\emph{SharpDevelop} IDE. During that I have obtained some basic knowledge
about metadata and lower-level functionality in \emph{.NET}. I can read
\emph{.NET} bytecode and, with the help of reference manual, I can write
short programs in it.
The metadata and bytecode needs to be read form the assembly files.
I plan to use the \emph{Cecil} library for it. I am not familiar with this
library, but I do not expect to have any difficulties with it.
\section*{Substance and Structure of the Project}
The project consists of the following major work items:
\begin{enumerate}
\newcommand{\milestone}[1]{\item \textbf{#1} \\}
\milestone{Preliminary research}
I will have to research the following topics:
\begin{itemize}
\item {\emph{Cecil} library}
- \emph{Cecil} is the library which I will use for reading of the
metadata. It will need to get familiar with its public API.
Because it is open-source, it might be valuable to get some basic
understanding of its source code as well.
\item {\emph{CIL} bytecode}
- The runtime of the \emph{.NET Framework} is described in
ECMA-335 Standard: \emph{``CLI Specification -- Virtual Machine''}
(556 pages). I will need to get familiar with this document since
I will be using it as the main reference. I will be especially
interested in \emph{Partition III -- CIL Instruction Set}.
\item {Decompilation theory} - I will need to get familiar with the
theory behind decompilation of programs. Cristina Cifuentes'
PhD thesis \emph{``Reverse Compilation Techniques''} might prove as
especially useful starting point.
\end{itemize}
The research of these topics should not be too extensive. I only indeed to
get sufficient background knowledge in these areas and then return to the
finner details when I needed them.
\milestone{Create a skeleton of the code}
It will be necessary to read the assembly metadata and create a \emph{C\#}
source code that has the same classes, fields and methods. The method
signatures have to match the ones in the assembly. At this point the method
bodies can be left empty.
\milestone{Read and disassemble \emph{.NET} bytecode}
The next step is to read the bytecode for each method, disassemble it and
output it as comments (for example, \verb|// IL_01: ldstr "Hello world"|).
This will help me learn how to use the \emph{Cecil} library to read the
bytecode and how to process it. I also expect that this output will be
extremely helpful for debugging purposes later on.
\milestone{Start creating r-value expressions}
Ignoring the stack of the virtual machine, some bytecodes can be
straightforwardly converted into expressions. For example:
\begin{verbatim}
ldstr "Hello world" - string "Hello world"
ldnull - 'null' reference
ldc.i4.0 - 4 byte integer of value 0
ldc.i4 123 - 4 byte integer of value 123
ldarg.0 - the first method argument
ldloc.0 - the first local variable in the method
\end{verbatim}
The goal of this stage is to create \emph{C\#} expressions for several of
the most important bytecodes.
Function calls and arithmetic operations are also expressions, but at this
stage I do not know their inputs and so I will have to use dummy values as
their inputs.
\milestone{Conditional and unconditional branching}
There are several bytecodes that investigate one or two values on the top
of stack and then, if a given condition is met, branch to different
location. (\verb|br|, \verb|brfalse|, \verb|brtrue|, \verb|beq|,
\verb|bge|, \verb|bgt|, etc...)
The goal of this stage is to use \emph{C\#} labels and \verb|goto|
statements to recreate this flow of control. (eg translate
\verb|brfalse IL_02| to \verb|if (input == false) goto Label_02;|)
As in the previous stage the inputs (ie the values at the top of stack) are
still not know.
\milestone{Simple data-flow analysis}
This is where it begins to be difficult. Consider the code:
\begin{verbatim}
// Load "Hello, world!" on top of the stack
IL_01: ldstr "Hello, world!"
// Print the top of the stack to the console
IL_02: call void [mscorlib]System.Console::WriteLine(string)
\end{verbatim}
Both of these are already decompiled as expressions, however the call
has a dummy value as its argument. The goal of this stage is to perform
as simple data-flow analysis as possible. The text "Hello, world!" must
find its way to the method call. At this point it will probably be through
one or even two temporary variables. For example:
\begin{verbatim}
String il_01_expression = "Hello, world!";
String il_02_argument_1 = il_01_expression;
System.Console.WriteLine(il_02_argument_1);
\end{verbatim}
The most difficult part will be handling of control flow. Different values
can be on stack depending on which branch of code was executed. At this
stage it will be necessary to create and analyse control flow graph. As a
result of this stage, many temporary variables might be introduced to the
code.
\milestone{Round-trip quick-sort algorithm}
At this point very simple applications should probably successfully
decompile and compile again (round-trip).
The goal of this stage is to fix bugs and to add features so that simple
algorithm like quick-sort can be successfully round-tripped without need to
manually change the produced \emph{C\#} source code. At this point there is
no restriction on the aesthetics of the source code. The only requirement
is that it does compile.
There are many features of \emph{.NET} that I do not plan to support at
this point. For example, boxing \& unboxing, casting, generics and
exception handling. In general, all non-essential features are excluded.
\milestone{Further data-flow analysis}
Employ more advanced data-flow analysis to simplify the generated \emph{C\#}
code. Many temporary variables can be probably removed, relocated or
renamed according to their use.
\emph{[This task has variable scope and if the project starts falling behind
schedule, simpler algorithms can be employed and vice versa.]}
\milestone{Control-flow analysis}
The goal of this stage is to use control-flow analysis to regenerate
high-level structures like \verb|if| statements and \verb|for| loops.
It will not be possible to eliminated all \verb|goto| statements, but they
should be avoided whenever possible.
\emph{[This task has variable scope and if the project starts falling behind
schedule, simpler algorithms can be employed and vice versa.]}
\milestone{Assembly resources}
\emph{.NET} assemblies can have files embed in them. These files can then
be accessed at runtime and thus the programs might require them.
The goal is to extract the resources so that they can be included during
the recompilation process.
\emph{[Optional. This is an optional goal which will be done only if the
project development goes much better then originally anticipated.]}
\milestone{Advanced features}
Add commonly used features which where ignored so far - for example,
boxing \& unboxing, casting, generics and exception handling.
\emph{[Optional. This is an optional goal which will be done only if the
project development goes much better then originally anticipated.]}
\milestone{Round-trip Mono}
The ultimate goal of this project is to be able to round-trip any
\emph{.NET} assembly. This means that for any given assembly the
Decompiler should produce \emph{C\#} source code which is valid (does
compile again without error). Even more importantly, the program produced
by the compilation of the source code should be semantically same as the
original one. Since the bytecode will in general differ, this condition is
difficult to verify. One way to check that the Decompiler preserves the
meaning of programs is to simply try it.
\emph{Mono} is open-source reimplantation of the \emph{.NET Framework}.
The major part of it are the \emph{.NET} class libraries which can be
used for testing of the Decompiler. The project is open-source and so if
any decompilation problems occur, it is possible to investigate the
source code of these libraries. Furthermore, the libraries come with
extensive unit testing suite so it is possible to verify that the
round-tripped libraries are not broken.
The goal of this final stage is to successfully round-trip all \emph{Mono}
libraries and pass the unit tests. This would probably involve enormous
amount of bugfixing, investigation and handling of corner cases. All
remaining \emph{.NET} features would have to be implemented.
\emph{[Optional. This last stage is huge and impossible to be finished
within the time frame of Part II project. If all goes well, I expect
that it will take at least one more year for the project to mature to
this point.]}
\milestone{Write the dissertation}
The last and most important piece of work is to write the dissertation.
Being a non-native English speaker, I expect this to take considerable
amount of time. I plan to spend the last seven weeks of project time
on it. This includes the end of Lent Term and the whole Easter vacation.
I plan to have the dissertation finished by the start of Easter term.
\end{enumerate}
\newpage
\section*{Success Criteria}
The Decompiler should successfully round-trip a quick-sort algorithm
(or any algorithm of comparable complexity).
That is, when an assembly containing the algorithm is
decompiled, the produced \emph{C\#} source code should be both
syntactically and semantically correct. The bytecode produced
by compilation of the generated source code is not expected to be
identical to the original one, but it is expected to be equivalent.
That is, the binary may be different but it still needs to be a correct
implementation of the algorithm.
To achieve this the Decompiler will need to have the following features:
\begin{itemize}
\item Handle integers and integer arithmetic
\item Create and be able to use integer arrays
\item Branching must be successfully decompiled
\item Several methods can be defined
\item Methods can have arguments and return values
\item Methods can be called recursively
\item Integer command line arguments can be read and parsed
\item Text can be outputted to the standard console output
\end{itemize}
See the following page for a \emph{C\#} implementation of a quick-sort
algorithm which will be used to demonstrate successful implementation
of these features.
I plan to achieve the success criteria by the progress report dead-line
and then spend the rest of the time available by increasing the quality
of the generated source code (ie ``Further data-flow analysis'' and
``Control-flow analysis'').
\newpage
{
\linespread{0.90}
\lstinputlisting[
basicstyle=\footnotesize,
language={[Sharp]C},
tabsize=4,
numbers=left,
frame=single,
title=Quick-sort algorithm
]{
../../tests/QuickSort/Program.cs
}
}
\newpage
\section*{Timetable and Milestones}
The work shall start on the Monday 22.10.2007 and is expected to
take 20 weeks in total.
\vspace{0.1in}
\newcommand{\milestone}[3]{\emph{#1} & \emph{#2} & \textbf{#3} \\}
\begin{tabular}{l l l}
\milestone{22 Oct - 28 Oct}{(week 1)}{Preliminary research}
\milestone{29 Oct - 4 Nov}{(week 2)}{Create a skeleton of the code}
\milestone{5 Nov - 11 Nov}{(week 3)}{Read and disassemble \emph{.NET} bytecode}
\milestone{12 Nov - 18 Nov}{(week 4)}{Start creating r-value expressions}
\milestone{19 Nov - 25 Nov}{(week 5)}{Conditional and unconditional branching}
\milestone{26 Nov - 9 Dec}{(weeks 6 and 7)}{Simple data-flow analysis}
\milestone{10 Dec - 20 Jan}{}{\textnormal{Christmas vacation}}
\milestone{21 Jan - 27 Jan}{(week 8)}{Round-trip quick-sort algorithm}
\milestone{26 Jan - 27 Jan}{}{Write the Progress Report}
\milestone{28 Jan - 10 Feb}{(weeks 9 and 10)}{Further data-flow analysis}
\milestone{11 Feb - 2 Mar}{(weeks 11 to 13)}{Control-flow analysis}
\milestone{3 Mar - 20 Apr}{(weeks 14 to 20)}{Write the dissertation \textnormal{(over Easter vacation)}}
\milestone{21 Apr onwards }{}{\textnormal{Easter term -- Preparation for exams}}
\end{tabular}
\vspace{0.1in}
Unscheduled tasks: \textbf{Assembly resources}; \textbf{Advanced features};
\textbf{Round-trip Mono}

44
doc/Dissertation/figs/10_Short_type_names_2.cs

@ -1,44 +0,0 @@ @@ -1,44 +0,0 @@
using System;
abstract class QuickSortProgram
{
public static void Main(string[] args)
{
int[] V_0 = new int[args.Length];
for (int i = 0; i < V_0.Length; i++) {
V_0[i] = Int32.Parse(args[i]);
}
QuickSortProgram.QuickSort(V_0, 0, V_0.Length - 1);
for (int j = 0; j < V_0.Length; j++) {
Console.Write(V_0[j].ToString() + " ");
}
}
public static void QuickSort(int[] array, int left, int right)
{
if (right > left) {
int i = (left + right) / 2;
int j = QuickSortProgram.Partition(array, left, right, i);
QuickSortProgram.QuickSort(array, left, j - 1);
QuickSortProgram.QuickSort(array, j + 1, right);
}
}
private static int Partition(int[] array, int left, int right, int pivotIndex)
{
int i = array[pivotIndex];
QuickSortProgram.Swap(array, pivotIndex, right);
int j = left;
for (int k = left; k < right; k++) {
if (array[k] <= i) {
QuickSortProgram.Swap(array, j, k);
j++;
}
}
QuickSortProgram.Swap(array, right, j);
return j;
}
private static void Swap(int[] array, int index1, int index2)
{
int i = array[index1];
array[index1] = array[index2];
array[index2] = i;
}
}

BIN
doc/Dissertation/figs/IfThen.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

BIN
doc/Dissertation/figs/IfThenElse.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

BIN
doc/Dissertation/figs/IfThenElseRechablility.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

BIN
doc/Dissertation/figs/IfThenElseReduction.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

BIN
doc/Dissertation/figs/Ireducible.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

BIN
doc/Dissertation/figs/Loop.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

BIN
doc/Dissertation/figs/NestedLoops.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

BIN
doc/Dissertation/figs/NestedLoops2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

BIN
doc/Dissertation/figs/QuickSortMain.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

44
doc/Dissertation/figs/QuickSort_original.cs

@ -1,44 +0,0 @@ @@ -1,44 +0,0 @@
using System;
static class QuickSortProgram
{
public static void Main(string[] args)
{
int[] intArray = new int[args.Length];
for (int i = 0; i < intArray.Length; i++) {
intArray[i] = int.Parse(args[i]);
}
QuickSort(intArray, 0, intArray.Length - 1);
for (int i = 0; i < intArray.Length; i++) {
Console.Write(intArray[i].ToString() + " ");
}
}
public static void QuickSort(int[] array, int left, int right)
{
if (right > left) {
int pivotIndex = (left + right) / 2;
int pivotNew = Partition(array, left, right, pivotIndex);
QuickSort(array, left, pivotNew - 1);
QuickSort(array, pivotNew + 1, right);
}
}
static int Partition(int[] array, int left, int right, int pivotIndex)
{
int pivotValue = array[pivotIndex];
Swap(array, pivotIndex, right);
int storeIndex = left;
for(int i = left; i < right; i++) {
if (array[i] <= pivotValue) {
Swap(array, storeIndex, i);
storeIndex = storeIndex + 1;
}
}
Swap(array, right, storeIndex);
return storeIndex;
}
static void Swap(int[] array, int index1, int index2)
{
int tmp = array[index1];
array[index1] = array[index2];
array[index2] = tmp;
}
}

BIN
doc/Dissertation/figs/T1T2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

3132
doc/Dissertation/figs/figs.svg

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 152 KiB

BIN
doc/Dissertation/figs/shortcircuit.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Loading…
Cancel
Save