public void OutputEntireGraph() { System.Console.WriteLine("Graph:"); System.Console.WriteLine(); System.Console.WriteLine("List of entries blocks:"); System.Console.WriteLine(new String(' ', 4) + "Node" + new string(' ', 4) + "Method"); foreach (CFGVertex n in this._entries) { System.Console.Write("{0,8}", n); System.Console.Write(new string(' ', 4)); System.Console.WriteLine(n.Method.FullName); } System.Console.WriteLine(); System.Console.WriteLine("List of callers:"); System.Console.WriteLine(new String(' ', 4) + "Node" + new string(' ', 4) + "Instruction"); foreach (Inst caller in Inst.CallInstructions) { CFGVertex n = caller.Block; System.Console.Write("{0,8}", n); System.Console.Write(new string(' ', 4)); System.Console.WriteLine(caller); } if (this._entries.Any()) { System.Console.WriteLine(); System.Console.WriteLine("List of orphan blocks:"); System.Console.WriteLine(new String(' ', 4) + "Node" + new string(' ', 4) + "Method"); foreach (CFGVertex n in this._entries) { if (n.StateIn != null && n.StateIn._bindings != null && n.StateIn._bindings.Count == 1) { System.Console.Write("{0,8}", n); System.Console.Write(new string(' ', 4)); if (n.StateIn._bindings.First()._caller != null) { System.Console.WriteLine("hmm?? "); } System.Console.WriteLine(n.Method.FullName); } } System.Console.WriteLine(); } foreach (CFGVertex n in VertexNodes) { if (n._ordered_list_of_blocks != null) { foreach (CFGVertex v in n._ordered_list_of_blocks) { v.OutputEntireNode(); } } } }
/// <summary> /// Return block corresponding to the instruction. /// </summary> /// <param name="inst"></param> /// <returns></returns> public CFGVertex FindEntry(Inst inst) { CFGVertex result = null; // Find owning block. result = inst.Block; // Return entry block for method. return(result._entry); }
public CFGVertex FindEntry(Mono.Cecil.Cil.Instruction inst) { CFGVertex result = null; foreach (CFG.CFGVertex node in this.VertexNodes) { if (node._instructions.First().Instruction == inst) { return(node); } } return(result); }
public CFGVertex(CFGVertex o) : base(o) { StackLevelOut = null; StackLevelIn = null; }
private void ExtractBasicBlocksOfMethod(MethodDefinition definition) { _done.Add(definition); // Make sure definition assembly is loaded. String full_name = definition.Module.FullyQualifiedName; LoadAssembly(full_name); if (definition.Body == null) { System.Console.WriteLine("WARNING: METHOD BODY NULL! " + definition); return; } int instruction_count = definition.Body.Instructions.Count; StackQueue <Mono.Cecil.Cil.Instruction> leader_list = new StackQueue <Mono.Cecil.Cil.Instruction>(); // Each method is a leader of a block. CFGVertex v = (CFGVertex)this.AddVertex(_node_number++); v.Method = definition; v.HasReturnValue = definition.IsReuseSlot; v._entry = v; this._entries.Add(v); v._ordered_list_of_blocks = new List <CFGVertex>(); v._ordered_list_of_blocks.Add(v); for (int j = 0; j < instruction_count; ++j) { // accumulate jump to locations since these split blocks. Mono.Cecil.Cil.Instruction mi = definition.Body.Instructions[j]; //System.Console.WriteLine(mi); Inst i = Inst.Wrap(mi, this); Mono.Cecil.Cil.OpCode op = i.OpCode; Mono.Cecil.Cil.FlowControl fc = op.FlowControl; v._instructions.Add(i); // Verify that mi not owned already. CFG.CFGVertex asdfasdf; Debug.Assert(!partition_of_instructions.TryGetValue(mi, out asdfasdf)); // Update ownership. partition_of_instructions.Add(mi, v); if (fc == Mono.Cecil.Cil.FlowControl.Next) { continue; } if (fc == Mono.Cecil.Cil.FlowControl.Branch || fc == Mono.Cecil.Cil.FlowControl.Cond_Branch) { // Save leader target of branch. object o = i.Operand; // Two cases that I know of: operand is just and instruction, // or operand is an array of instructions (via a switch instruction). Mono.Cecil.Cil.Instruction oo = o as Mono.Cecil.Cil.Instruction; Mono.Cecil.Cil.Instruction[] ooa = o as Mono.Cecil.Cil.Instruction[]; if (oo != null) { leader_list.Push(oo); } else if (ooa != null) { foreach (Mono.Cecil.Cil.Instruction ins in ooa) { Debug.Assert(ins != null); leader_list.Push(ins); } } else { throw new Exception("Unknown operand type for basic block partitioning."); } } } StackQueue <int> ordered_leader_list = new StackQueue <int>(); for (int j = 0; j < instruction_count; ++j) { // Order jump targets. These denote locations // where to split blocks. However, it's ordered, // so that splitting is done from last instruction in block // to first instruction in block. Mono.Cecil.Cil.Instruction i = definition.Body.Instructions[j]; //System.Console.WriteLine("Looking for " + i); if (leader_list.Contains(i)) { ordered_leader_list.Push(j); } } // Split block at jump targets in reverse. while (ordered_leader_list.Count > 0) { int i = ordered_leader_list.Pop(); CFG.CFGVertex new_node = v.Split(i); } //this.Dump(); StackQueue <CFG.CFGVertex> stack = new StackQueue <CFG.CFGVertex>(); foreach (CFG.CFGVertex node in this.VertexNodes) { stack.Push(node); } while (stack.Count > 0) { // Split blocks at branches, not including calls, with following // instruction a leader of new block. CFG.CFGVertex node = stack.Pop(); int node_instruction_count = node._instructions.Count; for (int j = 0; j < node_instruction_count; ++j) { Inst i = node._instructions[j]; Mono.Cecil.Cil.OpCode op = i.OpCode; Mono.Cecil.Cil.FlowControl fc = op.FlowControl; if (fc == Mono.Cecil.Cil.FlowControl.Next) { continue; } if (fc == Mono.Cecil.Cil.FlowControl.Call) { continue; } if (fc == Mono.Cecil.Cil.FlowControl.Meta) { continue; } if (fc == Mono.Cecil.Cil.FlowControl.Phi) { continue; } if (j + 1 >= node_instruction_count) { continue; } CFG.CFGVertex new_node = node.Split(j + 1); stack.Push(new_node); break; } } //this.Dump(); stack = new StackQueue <CFG.CFGVertex>(); foreach (CFG.CFGVertex node in this.VertexNodes) { stack.Push(node); } while (stack.Count > 0) { // Add in all final non-fallthrough branch edges. CFG.CFGVertex node = stack.Pop(); int node_instruction_count = node._instructions.Count; Inst i = node._instructions[node_instruction_count - 1]; Mono.Cecil.Cil.OpCode op = i.OpCode; Mono.Cecil.Cil.FlowControl fc = op.FlowControl; switch (fc) { case Mono.Cecil.Cil.FlowControl.Branch: case Mono.Cecil.Cil.FlowControl.Cond_Branch: { // Two cases: i.Operand is a single instruction, or an array of instructions. if (i.Operand as Mono.Cecil.Cil.Instruction != null) { Mono.Cecil.Cil.Instruction target_instruction = i.Operand as Mono.Cecil.Cil.Instruction; CFGVertex target_node = this.VertexNodes.First( (CFGVertex x) => { if (!x._instructions.First().Instruction.Equals(target_instruction)) { return(false); } return(true); }); if (Options.Singleton.Get(Options.OptionType.DisplaySSAComputation)) { System.Console.WriteLine("Create edge a " + node.Name + " to " + target_node.Name); } this.AddEdge(node, target_node); } else if (i.Operand as Mono.Cecil.Cil.Instruction[] != null) { foreach (Mono.Cecil.Cil.Instruction target_instruction in (i.Operand as Mono.Cecil.Cil.Instruction[])) { CFGVertex target_node = this.VertexNodes.First( (CFGVertex x) => { if (!x._instructions.First().Instruction.Equals(target_instruction)) { return(false); } return(true); }); System.Console.WriteLine("Create edge a " + node.Name + " to " + target_node.Name); this.AddEdge(node, target_node); } } else { throw new Exception("Unknown operand type for conditional branch."); } break; } case Mono.Cecil.Cil.FlowControl.Break: break; case Mono.Cecil.Cil.FlowControl.Call: { // We no longer split at calls. Splitting causes // problems because interprocedural edges are // produced. That's not good because it makes // code too "messy". break; object o = i.Operand; if (o as Mono.Cecil.MethodReference != null) { Mono.Cecil.MethodReference r = o as Mono.Cecil.MethodReference; Mono.Cecil.MethodDefinition d = r.Resolve(); IEnumerable <CFGVertex> target_node_list = this.VertexNodes.Where( (CFGVertex x) => { return(x.Method.FullName == r.FullName && x._entry == x); }); int c = target_node_list.Count(); if (c >= 1) { // target_node is the entry for a method. Also get the exit. CFGVertex target_node = target_node_list.First(); CFGVertex exit_node = target_node.Exit; // check if this is a recursive call. DO NOT BOTHER!! if (node.Method == target_node.Method) { } else { // Create edges from exit to successor blocks of the call. foreach (CFGEdge e in node._Successors) { System.Console.WriteLine("Create edge c " + exit_node.Name + " to " + e.to.Name); this._interprocedure_graph.AddEdge(exit_node, e.to); } // Create edge from node to method entry. System.Console.WriteLine("Create edge b " + node.Name + " to " + target_node.Name); this._interprocedure_graph.AddEdge(node, target_node); } } } break; } case Mono.Cecil.Cil.FlowControl.Meta: break; case Mono.Cecil.Cil.FlowControl.Next: break; case Mono.Cecil.Cil.FlowControl.Phi: break; case Mono.Cecil.Cil.FlowControl.Return: break; case Mono.Cecil.Cil.FlowControl.Throw: break; } } //this.Dump(); }
public CFGVertex Split(int i) { if (Options.Singleton.Get(Options.OptionType.DisplaySSAComputation)) { System.Console.WriteLine("Split at " + i + " " + _instructions[i]); } Debug.Assert(_instructions.Count != 0); // Split this node into two nodes, with all instructions after "i" in new node. CFG cfg = (CFG)this._Graph; CFGVertex result = (CFGVertex)cfg.AddVertex(_node_number++); result.Method = this.Method; result.HasReturnValue = this.HasReturnValue; result._entry = this._entry; // Insert new block after this block. this._entry._ordered_list_of_blocks.Insert( this._entry._ordered_list_of_blocks.IndexOf(this) + 1, result); int count = _instructions.Count; // Add instructions from split point to new block. for (int j = i; j < count; ++j) { result._instructions.Add(_instructions[j]); // Verify instruction ownership. Debug.Assert(cfg.partition_of_instructions[_instructions[j].Instruction] == this); // Update ownership. cfg.partition_of_instructions.Remove(_instructions[j].Instruction); cfg.partition_of_instructions.Add(_instructions[j].Instruction, result); } // Remove instructions from previous block. for (int j = i; j < count; ++j) { this._instructions.RemoveAt(i); } Debug.Assert(this._instructions.Count != 0); Debug.Assert(result._instructions.Count != 0); Debug.Assert(this._instructions.Count + result._instructions.Count == count); Inst last_instruction = this._instructions[ this._instructions.Count - 1]; // Transfer any out edges to pred block to new block. while (cfg.SuccessorNodes(this).Count() > 0) { CFG.CFGVertex succ = cfg.SuccessorNodes(this).First(); cfg.DeleteEdge(this, succ); cfg.AddEdge(result, succ); } // Add fall-through branch from pred to succ block. switch (last_instruction.OpCode.FlowControl) { case Mono.Cecil.Cil.FlowControl.Branch: break; case Mono.Cecil.Cil.FlowControl.Break: break; case Mono.Cecil.Cil.FlowControl.Call: cfg._interprocedure_graph.AddEdge(this.Name, result.Name); break; case Mono.Cecil.Cil.FlowControl.Cond_Branch: cfg.AddEdge(this.Name, result.Name); break; case Mono.Cecil.Cil.FlowControl.Meta: break; case Mono.Cecil.Cil.FlowControl.Next: cfg.AddEdge(this.Name, result.Name); break; case Mono.Cecil.Cil.FlowControl.Phi: break; case Mono.Cecil.Cil.FlowControl.Return: break; case Mono.Cecil.Cil.FlowControl.Throw: break; } //System.Console.WriteLine("After split"); //cfg.Dump(); //System.Console.WriteLine("-----------"); return(result); }