/ICSharpCode.Decompiler/FlowAnalysis/SsaForm.cs

http://github.com/icsharpcode/ILSpy · C# · 162 lines · 127 code · 14 blank · 21 comment · 28 complexity · b78f5fdd757310e6e1441df3a3059b3c MD5 · raw file

  1. // Copyright (c) 2010 Daniel Grunwald
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy of this
  4. // software and associated documentation files (the "Software"), to deal in the Software
  5. // without restriction, including without limitation the rights to use, copy, modify, merge,
  6. // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
  7. // to whom the Software is furnished to do so, subject to the following conditions:
  8. //
  9. // The above copyright notice and this permission notice shall be included in all copies or
  10. // substantial portions of the Software.
  11. //
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  13. // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  14. // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
  15. // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  16. // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  17. // DEALINGS IN THE SOFTWARE.
  18. using System;
  19. using System.Collections.Generic;
  20. using System.Collections.ObjectModel;
  21. using System.Diagnostics;
  22. using System.Linq;
  23. using ICSharpCode.NRefactory.Utils;
  24. using Mono.Cecil;
  25. using Mono.Cecil.Cil;
  26. namespace ICSharpCode.Decompiler.FlowAnalysis
  27. {
  28. /// <summary>
  29. /// Represents a graph of SsaBlocks.
  30. /// </summary>
  31. public sealed class SsaForm
  32. {
  33. readonly SsaVariable[] parameters;
  34. readonly SsaVariable[] locals;
  35. public readonly ReadOnlyCollection<SsaVariable> OriginalVariables;
  36. public readonly ReadOnlyCollection<SsaBlock> Blocks;
  37. readonly bool methodHasThis;
  38. public SsaBlock EntryPoint {
  39. get { return this.Blocks[0]; }
  40. }
  41. public SsaBlock RegularExit {
  42. get { return this.Blocks[1]; }
  43. }
  44. public SsaBlock ExceptionalExit {
  45. get { return this.Blocks[2]; }
  46. }
  47. internal SsaForm(SsaBlock[] blocks, SsaVariable[] parameters, SsaVariable[] locals, SsaVariable[] stackLocations, bool methodHasThis)
  48. {
  49. this.parameters = parameters;
  50. this.locals = locals;
  51. this.Blocks = new ReadOnlyCollection<SsaBlock>(blocks);
  52. this.OriginalVariables = new ReadOnlyCollection<SsaVariable>(parameters.Concat(locals).Concat(stackLocations).ToList());
  53. this.methodHasThis = methodHasThis;
  54. Debug.Assert(EntryPoint.NodeType == ControlFlowNodeType.EntryPoint);
  55. Debug.Assert(RegularExit.NodeType == ControlFlowNodeType.RegularExit);
  56. Debug.Assert(ExceptionalExit.NodeType == ControlFlowNodeType.ExceptionalExit);
  57. for (int i = 0; i < this.OriginalVariables.Count; i++) {
  58. this.OriginalVariables[i].OriginalVariableIndex = i;
  59. }
  60. }
  61. public GraphVizGraph ExportBlockGraph(Func<SsaBlock, string> labelProvider = null)
  62. {
  63. if (labelProvider == null)
  64. labelProvider = b => b.ToString();
  65. GraphVizGraph graph = new GraphVizGraph();
  66. foreach (SsaBlock block in this.Blocks) {
  67. graph.AddNode(new GraphVizNode(block.BlockIndex) { label = labelProvider(block), shape = "box" });
  68. }
  69. foreach (SsaBlock block in this.Blocks) {
  70. foreach (SsaBlock s in block.Successors) {
  71. graph.AddEdge(new GraphVizEdge(block.BlockIndex, s.BlockIndex));
  72. }
  73. }
  74. return graph;
  75. }
  76. public GraphVizGraph ExportVariableGraph(Func<SsaVariable, string> labelProvider = null)
  77. {
  78. if (labelProvider == null)
  79. labelProvider = v => v.ToString();
  80. GraphVizGraph graph = new GraphVizGraph();
  81. foreach (SsaVariable v in this.AllVariables) {
  82. graph.AddNode(new GraphVizNode(v.Name) { label = labelProvider(v) });
  83. }
  84. int instructionIndex = 0;
  85. foreach (SsaBlock block in this.Blocks) {
  86. foreach (SsaInstruction inst in block.Instructions) {
  87. if (inst.Operands.Length == 0 && inst.Target == null)
  88. continue;
  89. string id = "instruction" + (++instructionIndex);
  90. graph.AddNode(new GraphVizNode(id) { label = inst.ToString(), shape = "box" });
  91. foreach (SsaVariable op in inst.Operands)
  92. graph.AddEdge(new GraphVizEdge(op.Name, id));
  93. if (inst.Target != null)
  94. graph.AddEdge(new GraphVizEdge(id, inst.Target.Name));
  95. }
  96. }
  97. return graph;
  98. }
  99. public SsaVariable GetOriginalVariable(ParameterReference parameter)
  100. {
  101. if (methodHasThis)
  102. return parameters[parameter.Index + 1];
  103. else
  104. return parameters[parameter.Index];
  105. }
  106. public SsaVariable GetOriginalVariable(VariableReference variable)
  107. {
  108. return locals[variable.Index];
  109. }
  110. #region ComputeVariableUsage
  111. public void ComputeVariableUsage()
  112. {
  113. // clear data from previous runs
  114. foreach (SsaBlock block in this.Blocks) {
  115. foreach (SsaInstruction inst in block.Instructions) {
  116. foreach (SsaVariable v in inst.Operands) {
  117. if (v.Usage != null)
  118. v.Usage.Clear();
  119. }
  120. if (inst.Target != null && inst.Target.Usage != null)
  121. inst.Target.Usage.Clear();
  122. }
  123. }
  124. foreach (SsaBlock block in this.Blocks) {
  125. foreach (SsaInstruction inst in block.Instructions) {
  126. foreach (SsaVariable v in inst.Operands) {
  127. if (v.Usage == null)
  128. v.Usage = new List<SsaInstruction>();
  129. v.Usage.Add(inst);
  130. }
  131. if (inst.Target != null && inst.Target.Usage == null)
  132. inst.Target.Usage = new List<SsaInstruction>();
  133. }
  134. }
  135. }
  136. #endregion
  137. public IEnumerable<SsaVariable> AllVariables {
  138. get {
  139. return (
  140. from block in this.Blocks
  141. from instruction in block.Instructions
  142. where instruction.Target != null
  143. select instruction.Target
  144. ).Distinct();
  145. }
  146. }
  147. }
  148. }