internal void LoadStage3() { Console.WriteLine("================================================== Stage 3: {0} ==================================================", File.ReferenceName); for (int methodIndex = 0; methodIndex < Methods.Count; ++methodIndex) { Methods[methodIndex].ConvertInstructions(File.MethodDefTable[methodIndex]); Methods[methodIndex].ControlFlowGraph = IRControlFlowGraph.Build(Methods[methodIndex]); Methods[methodIndex].LinearizeInstructions(File.MethodDefTable[methodIndex]); Methods[methodIndex].TransformInstructions(File.MethodDefTable[methodIndex]); } }
public static IRControlFlowGraph Build(IRMethod pMethod) { if (pMethod.Instructions.Count == 0) { return(null); } HashSet <IRInstruction> sourceNodeBreaks = new HashSet <IRInstruction>(); HashSet <IRInstruction> destinationNodeBreaks = new HashSet <IRInstruction>(); foreach (IRInstruction instruction in pMethod.Instructions) { switch (instruction.Opcode) { case IROpcode.Branch: { IRBranchInstruction branchInstruction = (IRBranchInstruction)instruction; if (!sourceNodeBreaks.Contains(instruction)) { sourceNodeBreaks.Add(instruction); } if (!destinationNodeBreaks.Contains(branchInstruction.TargetIRInstruction)) { destinationNodeBreaks.Add(branchInstruction.TargetIRInstruction); } break; } case IROpcode.Switch: { IRSwitchInstruction switchInstruction = (IRSwitchInstruction)instruction; if (!sourceNodeBreaks.Contains(instruction)) { sourceNodeBreaks.Add(instruction); } foreach (IRInstruction targetIRInstruction in switchInstruction.TargetIRInstructions) { if (!destinationNodeBreaks.Contains(targetIRInstruction)) { destinationNodeBreaks.Add(targetIRInstruction); } } break; } case IROpcode.Leave: { IRLeaveInstruction leaveInstruction = (IRLeaveInstruction)instruction; if (!sourceNodeBreaks.Contains(instruction)) { sourceNodeBreaks.Add(instruction); } if (!destinationNodeBreaks.Contains(leaveInstruction.TargetIRInstruction)) { destinationNodeBreaks.Add(leaveInstruction.TargetIRInstruction); } break; } default: break; } } IRControlFlowGraph cfg = new IRControlFlowGraph(); Node currentNode = new Node(0); cfg.Nodes.Add(currentNode); foreach (IRInstruction instruction in pMethod.Instructions) { bool lastInstruction = instruction == pMethod.Instructions[pMethod.Instructions.Count - 1]; bool startFromSource = sourceNodeBreaks.Contains(instruction); bool startFromDestination = destinationNodeBreaks.Contains(instruction); if (startFromSource && startFromDestination) { if (currentNode.Instructions.Count > 0) { currentNode = new Node((uint)cfg.Nodes.Count); cfg.Nodes.Add(currentNode); } currentNode.Instructions.Add(instruction); currentNode = new Node((uint)cfg.Nodes.Count); cfg.Nodes.Add(currentNode); } else if (startFromSource) { currentNode.Instructions.Add(instruction); currentNode = new Node((uint)cfg.Nodes.Count); cfg.Nodes.Add(currentNode); } else if (startFromDestination) { if (currentNode.Instructions.Count > 0) { currentNode = new Node((uint)cfg.Nodes.Count); cfg.Nodes.Add(currentNode); } currentNode.Instructions.Add(instruction); } else { currentNode.Instructions.Add(instruction); } } for (int nodeIndex = 0; nodeIndex < cfg.Nodes.Count; ++nodeIndex) { Node node = cfg.Nodes[nodeIndex]; IRInstruction instruction = node.Instructions[node.Instructions.Count - 1]; switch (instruction.Opcode) { case IROpcode.Branch: { IRBranchInstruction branchInstruction = (IRBranchInstruction)instruction; Node childNode = cfg.Nodes.Find(n => n.Instructions[0] == branchInstruction.TargetIRInstruction); if (childNode == null) { throw new NullReferenceException(); } if (branchInstruction.BranchCondition != IRBranchCondition.Always) { node.LinkTo(cfg.Nodes[nodeIndex + 1]); } node.LinkTo(childNode); break; } case IROpcode.Switch: { IRSwitchInstruction switchInstruction = (IRSwitchInstruction)instruction; node.LinkTo(cfg.Nodes[nodeIndex + 1]); foreach (IRInstruction targetInstruction in switchInstruction.TargetIRInstructions) { Node childNode = cfg.Nodes.Find(n => n.Instructions[0] == targetInstruction); if (childNode == null) { throw new NullReferenceException(); } node.LinkTo(childNode); } break; } case IROpcode.Leave: { IRLeaveInstruction leaveInstruction = (IRLeaveInstruction)instruction; Node childNode = cfg.Nodes.Find(n => n.Instructions[0] == leaveInstruction.TargetIRInstruction); if (childNode == null) { throw new NullReferenceException(); } node.LinkTo(childNode); break; } case IROpcode.Throw: case IROpcode.Return: continue; default: node.LinkTo(cfg.Nodes[nodeIndex + 1]); break; } } return(cfg); }
public static IRControlFlowGraph Build(IRMethod pMethod) { if (pMethod.Instructions.Count == 0) return null; HashSet<IRInstruction> sourceNodeBreaks = new HashSet<IRInstruction>(); HashSet<IRInstruction> destinationNodeBreaks = new HashSet<IRInstruction>(); foreach (IRInstruction instruction in pMethod.Instructions) { switch (instruction.Opcode) { case IROpcode.Branch: { IRBranchInstruction branchInstruction = (IRBranchInstruction)instruction; if (!sourceNodeBreaks.Contains(instruction)) sourceNodeBreaks.Add(instruction); if (!destinationNodeBreaks.Contains(branchInstruction.TargetIRInstruction)) destinationNodeBreaks.Add(branchInstruction.TargetIRInstruction); break; } case IROpcode.Switch: { IRSwitchInstruction switchInstruction = (IRSwitchInstruction)instruction; if (!sourceNodeBreaks.Contains(instruction)) sourceNodeBreaks.Add(instruction); foreach (IRInstruction targetIRInstruction in switchInstruction.TargetIRInstructions) { if (!destinationNodeBreaks.Contains(targetIRInstruction)) { destinationNodeBreaks.Add(targetIRInstruction); } } break; } case IROpcode.Leave: { IRLeaveInstruction leaveInstruction = (IRLeaveInstruction)instruction; if (!sourceNodeBreaks.Contains(instruction)) sourceNodeBreaks.Add(instruction); if (!destinationNodeBreaks.Contains(leaveInstruction.TargetIRInstruction)) destinationNodeBreaks.Add(leaveInstruction.TargetIRInstruction); break; } default: break; } } IRControlFlowGraph cfg = new IRControlFlowGraph(); Node currentNode = new Node(0); cfg.Nodes.Add(currentNode); foreach (IRInstruction instruction in pMethod.Instructions) { bool lastInstruction = instruction == pMethod.Instructions[pMethod.Instructions.Count - 1]; bool startFromSource = sourceNodeBreaks.Contains(instruction); bool startFromDestination = destinationNodeBreaks.Contains(instruction); if (startFromSource && startFromDestination) { if (currentNode.Instructions.Count > 0) { currentNode = new Node((uint)cfg.Nodes.Count); cfg.Nodes.Add(currentNode); } currentNode.Instructions.Add(instruction); currentNode = new Node((uint)cfg.Nodes.Count); cfg.Nodes.Add(currentNode); } else if (startFromSource) { currentNode.Instructions.Add(instruction); currentNode = new Node((uint)cfg.Nodes.Count); cfg.Nodes.Add(currentNode); } else if (startFromDestination) { if (currentNode.Instructions.Count > 0) { currentNode = new Node((uint)cfg.Nodes.Count); cfg.Nodes.Add(currentNode); } currentNode.Instructions.Add(instruction); } else currentNode.Instructions.Add(instruction); } for (int nodeIndex = 0; nodeIndex < cfg.Nodes.Count; ++nodeIndex) { Node node = cfg.Nodes[nodeIndex]; IRInstruction instruction = node.Instructions[node.Instructions.Count - 1]; switch (instruction.Opcode) { case IROpcode.Branch: { IRBranchInstruction branchInstruction = (IRBranchInstruction)instruction; Node childNode = cfg.Nodes.Find(n => n.Instructions[0] == branchInstruction.TargetIRInstruction); if (childNode == null) throw new NullReferenceException(); if (branchInstruction.BranchCondition != IRBranchCondition.Always) node.LinkTo(cfg.Nodes[nodeIndex + 1]); node.LinkTo(childNode); break; } case IROpcode.Switch: { IRSwitchInstruction switchInstruction = (IRSwitchInstruction)instruction; node.LinkTo(cfg.Nodes[nodeIndex + 1]); foreach (IRInstruction targetInstruction in switchInstruction.TargetIRInstructions) { Node childNode = cfg.Nodes.Find(n => n.Instructions[0] == targetInstruction); if (childNode == null) throw new NullReferenceException(); node.LinkTo(childNode); } break; } case IROpcode.Leave: { IRLeaveInstruction leaveInstruction = (IRLeaveInstruction)instruction; Node childNode = cfg.Nodes.Find(n => n.Instructions[0] == leaveInstruction.TargetIRInstruction); if (childNode == null) throw new NullReferenceException(); node.LinkTo(childNode); break; } case IROpcode.Throw: case IROpcode.Return: continue; default: node.LinkTo(cfg.Nodes[nodeIndex + 1]); break; } } return cfg; }