public void AddInstruction(uint pILOffset, IRInstruction pInstruction) { pInstruction.ILOffset = (int)pILOffset; pInstruction.IRIndex = (uint)Instructions.Count; pInstruction.ParentMethod = this; Instructions.Add(pInstruction); }
/// <summary> /// This does a shallow copy of all of the members of the /// abstract IRInstruction class to the specified instruction. /// </summary> /// <param name="i">The instruction to copy to.</param> /// <param name="newMethod">The method this instruction will be added to.</param> /// <returns><see cref="i"/></returns> protected IRInstruction CopyTo(IRInstruction i, IRMethod newMethod) { i.ILOffset = this.ILOffset; i.IRIndex = this.IRIndex; i.Opcode = this.Opcode; i.ParentMethod = newMethod; i.Destination = this.Destination.Clone(); foreach (IRLinearizedLocation t in this.Sources) { i.Sources.Add(t.Clone()); } return i; }
/// <summary> /// This does a shallow copy of all of the members of the /// abstract IRInstruction class to the specified instruction. /// </summary> /// <param name="i">The instruction to copy to.</param> /// <param name="newMethod">The method this instruction will be added to.</param> /// <returns><see cref="i"/></returns> protected IRInstruction CopyTo(IRInstruction i, IRMethod newMethod) { i.ILOffset = this.ILOffset; i.IRIndex = this.IRIndex; i.Opcode = this.Opcode; i.ParentMethod = newMethod; i.Destination = this.Destination.Clone(); foreach (IRLinearizedLocation t in this.Sources) { i.Sources.Add(t.Clone()); } return(i); }
public Node FindInstructionNode(IRInstruction pInstruction) { foreach (Node node in Nodes) { foreach (IRInstruction instruction in node.Instructions) { if (pInstruction == instruction) { return(node); } } } throw new NullReferenceException(); }
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 Node FindInstructionNode(IRInstruction pInstruction) { foreach (Node node in Nodes) { foreach (IRInstruction instruction in node.Instructions) { if (pInstruction == instruction) return node; } } throw new NullReferenceException(); }
private void LinearizePath(MethodDefData pMethodDefData, IRInstruction pStartInstruction, Stack <IRStackObject> pStack, Queue <Tuple <IRInstruction, Stack <IRStackObject> > > pBranches) { int stackReturn = pStack.Count; IRInstruction currentInstruction = pStartInstruction; MethodDefData.MethodDefBodyData.MethodDefBodyExceptionData exceptionData = null; while (currentInstruction != null) { if (currentInstruction.Linearized && pStack.Count == stackReturn) { break; } if ((exceptionData = Array.Find(pMethodDefData.Body.Exceptions, e => e.Flags == 0 && e.HandlerOffset == currentInstruction.ILOffset)) != null) { IRType exceptionType = Assembly.AppDomain.PresolveType(Assembly.File.ExpandMetadataToken(exceptionData.ClassTokenOrFilterOffset)); IRStackObject exceptionObj = new IRStackObject(); exceptionObj.Type = exceptionType; exceptionObj.LinearizedTarget = new IRLinearizedLocation(IRLinearizedLocationType.Local); exceptionObj.LinearizedTarget.Local.LocalIndex = currentInstruction.AddLinearizedLocal(pStack, exceptionType); pStack.Push(exceptionObj); } currentInstruction.Linearize(pStack); currentInstruction.Linearized = true; switch (currentInstruction.Opcode) { case IROpcode.Branch: { IRBranchInstruction branchInstruction = (IRBranchInstruction)currentInstruction; if (branchInstruction.BranchCondition == IRBranchCondition.Always) { currentInstruction = branchInstruction.TargetIRInstruction; } else { pBranches.Enqueue(new Tuple <IRInstruction, Stack <IRStackObject> >(branchInstruction.TargetIRInstruction, pStack.Duplicate())); currentInstruction = Instructions[currentInstruction.IRIndex + 1]; } break; } case IROpcode.Switch: { IRSwitchInstruction switchInstruction = (IRSwitchInstruction)currentInstruction; foreach (IRInstruction targetInstruction in switchInstruction.TargetIRInstructions) { pBranches.Enqueue(new Tuple <IRInstruction, Stack <IRStackObject> >(targetInstruction, pStack.Duplicate())); } currentInstruction = Instructions[currentInstruction.IRIndex + 1]; break; } case IROpcode.Leave: { IRLeaveInstruction leaveInstruction = (IRLeaveInstruction)currentInstruction; currentInstruction = leaveInstruction.TargetIRInstruction; break; } case IROpcode.Jump: case IROpcode.Throw: case IROpcode.Return: currentInstruction = null; break; default: currentInstruction = currentInstruction.IRIndex >= Instructions.Count ? null : Instructions[currentInstruction.IRIndex + 1]; break; } } }
private void LinearizePath(MethodDefData pMethodDefData, IRInstruction pStartInstruction, Stack<IRStackObject> pStack, Queue<Tuple<IRInstruction, Stack<IRStackObject>>> pBranches) { int stackReturn = pStack.Count; IRInstruction currentInstruction = pStartInstruction; MethodDefData.MethodDefBodyData.MethodDefBodyExceptionData exceptionData = null; while (currentInstruction != null) { if (currentInstruction.Linearized && pStack.Count == stackReturn) break; if ((exceptionData = Array.Find(pMethodDefData.Body.Exceptions, e => e.Flags == 0 && e.HandlerOffset == currentInstruction.ILOffset)) != null) { IRType exceptionType = Assembly.AppDomain.PresolveType(Assembly.File.ExpandMetadataToken(exceptionData.ClassTokenOrFilterOffset)); IRStackObject exceptionObj = new IRStackObject(); exceptionObj.Type = exceptionType; exceptionObj.LinearizedTarget = new IRLinearizedLocation(IRLinearizedLocationType.Local); exceptionObj.LinearizedTarget.Local.LocalIndex = currentInstruction.AddLinearizedLocal(pStack, exceptionType); pStack.Push(exceptionObj); } currentInstruction.Linearize(pStack); currentInstruction.Linearized = true; switch (currentInstruction.Opcode) { case IROpcode.Branch: { IRBranchInstruction branchInstruction = (IRBranchInstruction)currentInstruction; if (branchInstruction.BranchCondition == IRBranchCondition.Always) currentInstruction = branchInstruction.TargetIRInstruction; else { pBranches.Enqueue(new Tuple<IRInstruction, Stack<IRStackObject>>(branchInstruction.TargetIRInstruction, pStack.Duplicate())); currentInstruction = Instructions[currentInstruction.IRIndex + 1]; } break; } case IROpcode.Switch: { IRSwitchInstruction switchInstruction = (IRSwitchInstruction)currentInstruction; foreach (IRInstruction targetInstruction in switchInstruction.TargetIRInstructions) { pBranches.Enqueue(new Tuple<IRInstruction, Stack<IRStackObject>>(targetInstruction, pStack.Duplicate())); } currentInstruction = Instructions[currentInstruction.IRIndex + 1]; break; } case IROpcode.Leave: { IRLeaveInstruction leaveInstruction = (IRLeaveInstruction)currentInstruction; currentInstruction = leaveInstruction.TargetIRInstruction; break; } case IROpcode.Jump: case IROpcode.Throw: case IROpcode.Return: currentInstruction = null; break; default: currentInstruction = currentInstruction.IRIndex >= Instructions.Count ? null : Instructions[currentInstruction.IRIndex + 1]; break; } } }