diff options
Diffstat (limited to 'ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs')
-rw-r--r-- | ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs | 257 |
1 files changed, 0 insertions, 257 deletions
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs b/ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs deleted file mode 100644 index c7c86a57..00000000 --- a/ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright (c) 2010 Daniel Grunwald -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Diagnostics; - -using Mono.Cecil; -using Mono.Cecil.Cil; - -namespace ICSharpCode.Decompiler.FlowAnalysis -{ - /// <summary> - /// Constructs "SsaForm" graph for a CFG. - /// This class transforms the method from stack-based IL to a register-based IL language. - /// Then it calls into TransformToSsa to convert the resulting graph to static single assignment form. - /// </summary> - public sealed class SsaFormBuilder - { - public static SsaForm Build(MethodDefinition method) - { - if (method == null) - throw new ArgumentNullException("method"); - var cfg = ControlFlowGraphBuilder.Build(method.Body); - cfg.ComputeDominance(); - cfg.ComputeDominanceFrontier(); - var ssa = BuildRegisterIL(method, cfg); - TransformToSsa.Transform(cfg, ssa); - return ssa; - } - - public static SsaForm BuildRegisterIL(MethodDefinition method, ControlFlowGraph cfg) - { - if (method == null) - throw new ArgumentNullException("method"); - if (cfg == null) - throw new ArgumentNullException("cfg"); - return new SsaFormBuilder(method, cfg).Build(); - } - - readonly MethodDefinition method; - readonly ControlFlowGraph cfg; - - readonly SsaBlock[] blocks; // array index = block index - readonly int[] stackSizeAtBlockStart; // array index = block index - - readonly SsaVariable[] parameters; // array index = parameter number - readonly SsaVariable[] locals; // array index = local number - readonly SsaVariable[] stackLocations; // array index = position on the IL evaluation stack - SsaForm ssaForm; - - SsaFormBuilder(MethodDefinition method, ControlFlowGraph cfg) - { - this.method = method; - this.cfg = cfg; - - blocks = new SsaBlock[cfg.Nodes.Count]; - stackSizeAtBlockStart = new int[cfg.Nodes.Count]; - for (int i = 0; i < stackSizeAtBlockStart.Length; i++) { - stackSizeAtBlockStart[i] = -1; - } - stackSizeAtBlockStart[cfg.EntryPoint.BlockIndex] = 0; - - parameters = new SsaVariable[method.Parameters.Count + (method.HasThis ? 1 : 0)]; - if (method.HasThis) - parameters[0] = new SsaVariable(method.Body.ThisParameter); - for (int i = 0; i < method.Parameters.Count; i++) - parameters[i + (method.HasThis ? 1 : 0)] = new SsaVariable(method.Parameters[i]); - - locals = new SsaVariable[method.Body.Variables.Count]; - for (int i = 0; i < locals.Length; i++) - locals[i] = new SsaVariable(method.Body.Variables[i]); - - stackLocations = new SsaVariable[method.Body.MaxStackSize]; - for (int i = 0; i < stackLocations.Length; i++) { - stackLocations[i] = new SsaVariable(i); - } - } - - internal SsaForm Build() - { - CreateGraphStructure(); - ssaForm = new SsaForm(blocks, parameters, locals, stackLocations, method.HasThis); - CreateInstructions(cfg.EntryPoint.BlockIndex); - CreateSpecialInstructions(); - return ssaForm; - } - - void CreateGraphStructure() - { - for (int i = 0; i < blocks.Length; i++) { - blocks[i] = new SsaBlock(cfg.Nodes[i]); - } - for (int i = 0; i < blocks.Length; i++) { - foreach (ControlFlowNode node in cfg.Nodes[i].Successors) { - blocks[i].Successors.Add(blocks[node.BlockIndex]); - blocks[node.BlockIndex].Predecessors.Add(blocks[i]); - } - } - } - - void CreateInstructions(int blockIndex) - { - ControlFlowNode cfgNode = cfg.Nodes[blockIndex]; - SsaBlock block = blocks[blockIndex]; - - int stackSize = stackSizeAtBlockStart[blockIndex]; - Debug.Assert(stackSize >= 0); - - List<Instruction> prefixes = new List<Instruction>(); - foreach (Instruction inst in cfgNode.Instructions) { - if (inst.OpCode.OpCodeType == OpCodeType.Prefix) { - prefixes.Add(inst); - continue; - } - - int popCount = inst.GetPopDelta(method) ?? stackSize; - stackSize -= popCount; - if (stackSize < 0) - throw new InvalidProgramException("IL stack underflow"); - - int pushCount = inst.GetPushDelta(); - if (stackSize + pushCount > stackLocations.Length) - throw new InvalidProgramException("IL stack overflow"); - - SsaVariable target; - SsaVariable[] operands; - DetermineOperands(stackSize, inst, popCount, pushCount, out target, out operands); - - Instruction[] prefixArray = prefixes.Count > 0 ? prefixes.ToArray() : null; - prefixes.Clear(); - - // ignore NOP instructions - if (!(inst.OpCode == OpCodes.Nop || inst.OpCode == OpCodes.Pop)) { - block.Instructions.Add(new SsaInstruction(block, inst, target, operands, prefixArray)); - } - stackSize += pushCount; - } - - foreach (ControlFlowEdge edge in cfgNode.Outgoing) { - int newStackSize; - switch (edge.Type) { - case JumpType.Normal: - newStackSize = stackSize; - break; - case JumpType.EndFinally: - if (stackSize != 0) - throw new NotSupportedException("stacksize must be 0 in endfinally edge"); - newStackSize = 0; - break; - case JumpType.JumpToExceptionHandler: - switch (edge.Target.NodeType) { - case ControlFlowNodeType.FinallyOrFaultHandler: - newStackSize = 0; - break; - case ControlFlowNodeType.ExceptionalExit: - case ControlFlowNodeType.CatchHandler: - newStackSize = 1; - break; - default: - throw new NotSupportedException("unsupported target node type: " + edge.Target.NodeType); - } - break; - default: - throw new NotSupportedException("unsupported jump type: " + edge.Type); - } - - int nextStackSize = stackSizeAtBlockStart[edge.Target.BlockIndex]; - if (nextStackSize == -1) { - stackSizeAtBlockStart[edge.Target.BlockIndex] = newStackSize; - CreateInstructions(edge.Target.BlockIndex); - } else if (nextStackSize != newStackSize) { - throw new InvalidProgramException("Stack size doesn't match"); - } - } - } - - void DetermineOperands(int stackSize, Instruction inst, int popCount, int pushCount, out SsaVariable target, out SsaVariable[] operands) - { - switch (inst.OpCode.Code) { - case Code.Ldarg: - operands = new SsaVariable[] { ssaForm.GetOriginalVariable((ParameterReference)inst.Operand) }; - target = stackLocations[stackSize]; - break; - case Code.Starg: - operands = new SsaVariable[] { stackLocations[stackSize] }; - target = ssaForm.GetOriginalVariable((ParameterReference)inst.Operand); - break; - case Code.Ldloc: - operands = new SsaVariable[] { ssaForm.GetOriginalVariable((VariableReference)inst.Operand) }; - target = stackLocations[stackSize]; - break; - case Code.Stloc: - operands = new SsaVariable[] { stackLocations[stackSize] }; - target = ssaForm.GetOriginalVariable((VariableReference)inst.Operand); - break; - case Code.Dup: - operands = new SsaVariable[] { stackLocations[stackSize] }; - target = stackLocations[stackSize + 1]; - break; - default: - operands = new SsaVariable[popCount]; - for (int i = 0; i < popCount; i++) { - operands[i] = stackLocations[stackSize + i]; - } - - switch (pushCount) { - case 0: - target = null; - break; - case 1: - target = stackLocations[stackSize]; - break; - default: - throw new NotSupportedException("unsupported pushCount=" + pushCount); - } - break; - } - } - - void CreateSpecialInstructions() - { - // Everything needs an initial write for the SSA transformation to work correctly. - foreach (SsaVariable v in parameters) { - ssaForm.EntryPoint.Instructions.Add(new SsaInstruction(ssaForm.EntryPoint, null, v, null, specialOpCode: SpecialOpCode.Parameter)); - } - foreach (SsaVariable v in locals) { - ssaForm.EntryPoint.Instructions.Add(new SsaInstruction(ssaForm.EntryPoint, null, v, null, specialOpCode: SpecialOpCode.Uninitialized)); - } - foreach (SsaVariable v in stackLocations) { - ssaForm.EntryPoint.Instructions.Add(new SsaInstruction(ssaForm.EntryPoint, null, v, null, specialOpCode: SpecialOpCode.Uninitialized)); - } - foreach (SsaBlock b in blocks) { - if (b.NodeType == ControlFlowNodeType.CatchHandler) { - b.Instructions.Add(new SsaInstruction(b, null, stackLocations[0], null, - specialOpCode: SpecialOpCode.Exception, - typeOperand: cfg.Nodes[b.BlockIndex].ExceptionHandler.CatchType)); - } - } - } - } -} |