示例#1
0
        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();
                    }
                }
            }
        }
示例#2
0
        /// <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);
        }
示例#3
0
        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);
        }
示例#4
0
 public CFGVertex(CFGVertex o)
     : base(o)
 {
     StackLevelOut = null;
     StackLevelIn  = null;
 }
示例#5
0
        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();
        }
示例#6
0
            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);
            }