Пример #1
0
        public void Dump()
        {
            if (!Options.Singleton.Get(Options.OptionType.DisplayStructureComputation))
            {
                return;
            }
            System.Console.WriteLine("Dump of structure IR.");
            StackQueue <Structure> stack = new StackQueue <Structure>();

            stack.Push(this);
            while (stack.Count > 0)
            {
                Structure structure = stack.Pop();
                // Set up string for this structure.
                String result = "";
                String eol    = "\r\n";
                result += "Struct" + eol;
                result += ("Name " + structure.Name + eol);
                result += ("Fullname " + structure.FullName + eol);
                result += ("Rewrite Names " + (rewrite_names.Count() > 0 ? rewrite_names.Aggregate((i, j) => i + " " + j) : "")) + eol;
                result += ("level " + structure.level + eol);
                result += ("instance of " + structure._class_instance + eol);
                result += ("Simple Fields:" + eol);
                foreach (FieldInfo fi in structure._simple_fields)
                {
                    result += (fi + eol);
                }
                result += ("Class Fields:" + eol);
                foreach (Tuple <FieldInfo, object> pair in structure._class_fields)
                {
                    result += (pair.Item1.Name + " " + pair.Item2 + eol);
                }
                result += ("Delegate Fields:" + eol);
                foreach (Tuple <FieldInfo, Delegate> pair in structure._delegate_fields)
                {
                    result += (pair.Item1.Name + " " + pair.Item2 + eol);
                }
                result += ("Method Fields:" + eol);
                foreach (System.Reflection.MethodBase met in structure._methods)
                {
                    result += (met + eol);
                }
                String indent = "";
                for (int i = 0; i < structure.level; ++i)
                {
                    indent += "   ";
                }
                if (Options.Singleton.Get(Options.OptionType.DisplayStructureComputation))
                {
                    System.Console.WriteLine(indent + result.Replace("\n", "\n" + indent));
                }
                foreach (Structure child in structure._nested_structures)
                {
                    stack.Push(child);
                }
            }
        }
Пример #2
0
 public State(State other)
 {
     _stack = new StackQueue <SSA.Value>();
     for (int i = 0; i < other._stack.Count; ++i)
     {
         _stack.Push(other._stack.PeekBottom(i));
     }
     _arguments = _stack.Section(other._arguments.Base, other._arguments.Len);
     _locals    = _stack.Section(other._locals.Base, other._locals.Len);
     _bindings  = new List <Nesting>();
     _bindings.AddRange(other._bindings);
 }
Пример #3
0
            public IEnumerator <Structure> GetEnumerator()
            {
                StackQueue <Structure> stack = new StackQueue <Structure>();

                stack.Push(top_level_structure);
                while (stack.Count > 0)
                {
                    Structure current = stack.Pop();
                    yield return(current);

                    foreach (Structure child in current._nested_structures)
                    {
                        stack.Push(child);
                    }
                }
            }
Пример #4
0
        // Add all methods of assembly to graph.
        public void AddAssembly(String assembly_file_name)
        {
            Mono.Cecil.ModuleDefinition module = LoadAssembly(assembly_file_name);
            String full_name = System.IO.Path.GetFullPath(assembly_file_name);

            foreach (Mono.Cecil.ModuleDefinition md in this._analyzed_modules)
            {
                if (md.FullyQualifiedName.Equals(full_name))
                {
                    return;
                }
            }
            _analyzed_modules.Add(module);
            StackQueue <Mono.Cecil.TypeDefinition> type_definitions         = new StackQueue <Mono.Cecil.TypeDefinition>();
            StackQueue <Mono.Cecil.TypeDefinition> type_definitions_closure = new StackQueue <Mono.Cecil.TypeDefinition>();

            foreach (Mono.Cecil.TypeDefinition td in module.Types)
            {
                type_definitions.Push(td);
            }
            while (type_definitions.Count > 0)
            {
                Mono.Cecil.TypeDefinition ty = type_definitions.Pop();
                type_definitions_closure.Push(ty);
                foreach (Mono.Cecil.TypeDefinition ntd in ty.NestedTypes)
                {
                    type_definitions.Push(ntd);
                }
            }
            foreach (Mono.Cecil.TypeDefinition td in type_definitions_closure)
            {
                foreach (Mono.Cecil.MethodDefinition definition in td.Methods)
                {
                    Add(definition);
                }
            }
        }
Пример #5
0
        public State(Mono.Cecil.MethodDefinition md, int level)
        {
            int args = 0;

            if (md.HasThis)
            {
                args++;
            }
            args += md.Parameters.Count;
            int locals = md.Body.Variables.Count;

            // Create a stack with variables, which will be
            // bound to phi functions.
            _stack = new StackQueue <SSA.Value>();
            // Allocate parameters, even though we don't what they may be.
            _arguments = _stack.Section(_stack.Count, args);
            for (int i = 0; i < args; ++i)
            {
                _stack.Push(new SSA.Variable());
            }

            // Allocate local variables.
            _locals = _stack.Section(_stack.Count, locals);
            for (int i = 0; i < locals; ++i)
            {
                _stack.Push(new SSA.Variable());
            }

            for (int i = _stack.Size(); i < level; ++i)
            {
                _stack.Push(new SSA.Variable());
            }

            _bindings = new List <Nesting>();
            _bindings.Add(new Nesting());
        }
Пример #6
0
        public Structure FindAllTargets(object obj)
        {
            Dictionary <Delegate, object> delegate_to_instance = new Dictionary <Delegate, object>();
            Delegate     lambda_delegate = (Delegate)obj;
            BindingFlags findFlags       = BindingFlags.NonPublic |
                                           BindingFlags.Public |
                                           BindingFlags.Static |
                                           BindingFlags.Instance |
                                           BindingFlags.InvokeMethod |
                                           BindingFlags.OptionalParamBinding |
                                           BindingFlags.DeclaredOnly;

            _control_flow_graph.Add(Campy.Types.Utils.ReflectionCecilInterop.ConvertToMonoCecilMethodDefinition(lambda_delegate.Method));
            _control_flow_graph.ExtractBasicBlocks();

            // Construct graph containing all objects used in lambda.
            StackQueue <object> stack = new StackQueue <object>();

            stack.Push(lambda_delegate);
            Campy.Graphs.GraphLinkedList <object> data_graph = new GraphLinkedList <object>();
            while (stack.Count > 0)
            {
                object node = stack.Pop();

                // Case 1: object is multicast delegate.
                // A multicast delegate is a list of delegates called in the order
                // they appear in the list.
                System.MulticastDelegate md = node as System.MulticastDelegate;
                if (md != null)
                {
                    foreach (System.Delegate node2 in md.GetInvocationList())
                    {
                        if ((object)node2 != (object)node)
                        {
                            if (Options.Singleton.Get(Options.OptionType.DisplayStructureComputation))
                            {
                                System.Console.WriteLine("Pushing2 " + MyToString(node2));
                            }
                            stack.Push(node2);
                        }
                    }
                    // Note, if multicast delegate, then it does not make sense to continue.
                    // Handle normal delegates.
                    //continue;
                }

                // Case 2: object is plain delegate.
                System.Delegate del = node as System.Delegate;
                if (del != null)
                {
                    object target = del.Target;
                    if (target == null)
                    {
                        // If target is null, then the delegate is a function that
                        // uses either static data, or does not require any additional
                        // data. If target isn't null, then it's probably a class.
                        target = Activator.CreateInstance(del.Method.DeclaringType);
                        if (data_graph.Vertices.Contains(target))
                        {
                            continue;
                        }
                        if (!delegate_to_instance.ContainsKey(del))
                        {
                            Debug.Assert(!TypesUtility.IsBaseType(target.GetType(), typeof(Delegate)));
                            data_graph.AddVertex(target);
                            delegate_to_instance.Add(del, target);
                            stack.Push(target);
                        }
                    }
                    else
                    {
                        // Target isn't null for delegate. Most likely, the method
                        // is part of the target, so let's assert that.
                        bool found = false;
                        foreach (System.Reflection.MethodInfo mi in target.GetType().GetMethods(findFlags))
                        {
                            if (mi == del.Method)
                            {
                                found = true;
                                break;
                            }
                        }
                        Debug.Assert(found);
                        if (Options.Singleton.Get(Options.OptionType.DisplayStructureComputation))
                        {
                            System.Console.WriteLine("Pushing " + MyToString(target));
                        }
                        if (delegate_to_instance.ContainsKey(del))
                        {
                            Debug.Assert(delegate_to_instance[del] == target);
                        }
                        else
                        {
                            delegate_to_instance.Add(del, target);
                        }
                        stack.Push(target);
                    }
                    continue;
                }

                if (data_graph.Vertices.Contains(node))
                {
                    continue;
                }

                Debug.Assert(!TypesUtility.IsBaseType(node.GetType(), typeof(Delegate)));
                data_graph.AddVertex(node);

                // Case 3: object is a class, and potentially could point to delegate.
                // Examine all fields, looking for list_of_targets.

                Type target_type = node.GetType();

                FieldInfo[] target_type_fieldinfo = target_type.GetFields();
                foreach (var field in target_type_fieldinfo)
                {
                    var value = field.GetValue(node);
                    if (value != null)
                    {
                        if (field.FieldType.IsValueType)
                        {
                            continue;
                        }
                        if (TypesUtility.IsCampyArrayType(field.FieldType))
                        {
                            continue;
                        }
                        if (TypesUtility.IsSimpleCampyType(field.FieldType))
                        {
                            continue;
                        }
                        // chase pointer type.
                        if (Options.Singleton.Get(Options.OptionType.DisplayStructureComputation))
                        {
                            System.Console.WriteLine("Pushingf " + MyToString(value));
                        }
                        stack.Push(value);
                    }
                }
            }

            if (Options.Singleton.Get(Options.OptionType.DisplayStructureComputation))
            {
                System.Console.WriteLine();
                System.Console.WriteLine("Dump of nodes.");
                foreach (object node in data_graph.Vertices)
                {
                    System.Console.WriteLine("Node "
                                             + MyToString(node));
                    System.Console.WriteLine("typeof node = "
                                             + node.GetType());
                    System.Console.WriteLine("Node "
                                             + (((node as Delegate) != null) ? "is " : "is not ")
                                             + "a delegate.");
                    System.Console.WriteLine();
                }
            }

            // Add edges.
            foreach (object node in data_graph.Vertices)
            {
                Type node_type = node.GetType();

                FieldInfo[] node_type_fieldinfo = node_type.GetFields();
                foreach (var field in node_type_fieldinfo)
                {
                    if (field.FieldType.IsValueType)
                    {
                        continue;
                    }
                    if (TypesUtility.IsCampyArrayType(field.FieldType))
                    {
                        continue;
                    }
                    if (TypesUtility.IsSimpleCampyType(field.FieldType))
                    {
                        continue;
                    }
                    var value = field.GetValue(node);
                    if (value == null)
                    {
                    }
                    else if (TypesUtility.IsBaseType(value.GetType(), typeof(Delegate)))
                    {
                        Delegate del          = value as Delegate;
                        object   value_target = del.Target;
                        if (value_target == node)
                        {
                            ;
                        }
                        else if (value_target != null)
                        {
                            Debug.Assert(data_graph.Vertices.Contains(node));
                            Debug.Assert(data_graph.Vertices.Contains(value_target));
                            data_graph.AddEdge(node, value_target);
                        }
                        else
                        {
                            value_target = delegate_to_instance[del];
                            if (value_target != node)
                            {
                                Debug.Assert(data_graph.Vertices.Contains(node));
                                Debug.Assert(data_graph.Vertices.Contains(value_target));
                                data_graph.AddEdge(node, value_target);
                            }
                        }
                    }
                    else
                    {
                        Debug.Assert(data_graph.Vertices.Contains(node));
                        Debug.Assert(data_graph.Vertices.Contains(value));
                        data_graph.AddEdge(node, value);
                    }
                }
            }

            if (Options.Singleton.Get(Options.OptionType.DisplayStructureComputation))
            {
                foreach (object node in data_graph.Vertices)
                {
                    System.Console.WriteLine("Node "
                                             + MyToString(node));
                    System.Console.WriteLine("typeof node = "
                                             + node.GetType());
                    System.Console.WriteLine("Node "
                                             + (((node as Delegate) != null) ? "is " : "is not ")
                                             + "a delegate.");
                    foreach (object succ in data_graph.Successors(node))
                    {
                        System.Console.WriteLine("-> "
                                                 + succ.GetHashCode() + " " + MyToString(succ));
                    }
                    System.Console.WriteLine();
                }
                System.Console.WriteLine();
            }

            Structure res = Structure.Initialize(delegate_to_instance, lambda_delegate.Method, data_graph, _control_flow_graph);

            if (Options.Singleton.Get(Options.OptionType.DisplayStructureComputation))
            {
                res.Dump();
            }

            return(res);
        }
Пример #7
0
        // Create an intermediate representation of data_graph and control_flow_graph
        // that contains the nodes in the graphs as Structures, and edges between
        // nodes represented by nesting of Structures. This representation is
        // needed for translation to C++ AMP.
        public static Structure Initialize(Dictionary <Delegate, object> delegate_to_instance, System.Reflection.MethodInfo main_method, GraphLinkedList <object> data_graph, CFG control_flow_graph)
        {
            map_target_to_structure = new Dictionary <object, Structure>();
            Structure top_level_structure = new Structure();
            var       ddlist = data_graph.Vertices;
            object    dd     = data_graph.Vertices.First();

            top_level_structure._class_instance = dd;
            top_level_structure._main_method    = main_method;
            int    last_depth  = 1;
            String last_prefix = "";

            top_level_structure.Name     = "s" + last_depth;
            top_level_structure.FullName = last_prefix + top_level_structure.Name;
            top_level_structure.level    = last_depth;
            List <object>          targets             = new List <object>();
            StackQueue <String>    stack_of_prefix     = new StackQueue <string>();
            StackQueue <object>    stack_of_nodes      = new StackQueue <object>();
            StackQueue <Structure> stack_of_structures = new StackQueue <Structure>();

            stack_of_prefix.Push(last_prefix);
            stack_of_nodes.Push(dd);
            stack_of_structures.Push(top_level_structure);
            Dictionary <object, int> depth = new Dictionary <object, int>();

            depth.Add(dd, last_depth);
            while (stack_of_nodes.Count > 0)
            {
                object current_node   = stack_of_nodes.Pop();
                String current_prefix = stack_of_prefix.Pop();
                int    current_depth  = depth[current_node];
                if (targets.Contains(current_node))
                {
                    continue;
                }

                object target = current_node;
                targets.Add(target);
                if (Options.Singleton.Get(Options.OptionType.DisplayStructureComputation))
                {
                    System.Console.WriteLine("Target " + Utility.GetFriendlyTypeName(target.GetType()));
                }

                foreach (object next in data_graph.Successors(current_node))
                {
                    stack_of_nodes.Push(next);
                    depth.Add(next, current_depth + 1);
                    stack_of_prefix.Push(current_prefix + "s" + current_depth + ".");
                }
                if (current_depth > last_depth)
                {
                    Structure p = stack_of_structures.PeekTop();
                    stack_of_structures.Push(new Structure(p, target));
                    Structure c = stack_of_structures.PeekTop();
                    c.Name     = "s" + current_depth;
                    c.FullName = current_prefix + c.Name;
                    c.level    = current_depth;
                }
                else if (current_depth < last_depth)
                {
                    stack_of_structures.Pop();
                }

                Structure current_structure = stack_of_structures.PeekTop();
                current_structure._delegate_fields = new List <Tuple <System.Reflection.FieldInfo, Delegate> >();
                current_structure._class_fields    = new List <Tuple <System.Reflection.FieldInfo, object> >();

                last_depth  = current_depth;
                last_prefix = current_prefix;
                Structure try_structure = null;
                map_target_to_structure.TryGetValue(target, out try_structure);
                if (try_structure != null)
                {
                    Debug.Assert(try_structure == current_structure);
                }
                else
                {
                    map_target_to_structure.Add(target, current_structure);
                }
                Type target_type = target.GetType();
                foreach (FieldInfo fi in target_type.GetFields())
                {
                    // Add field if it's a simple value type or campy type.
                    // If it's a class, we'll be converting it into a struct.
                    object field_value = fi.GetValue(target);
                    if (field_value as System.Delegate == null &&
                        (fi.FieldType.IsValueType ||
                         TypesUtility.IsSimpleCampyType(fi.FieldType)))
                    {
                        current_structure.AddField(fi);
                    }
                    else if (field_value != null && field_value as System.Delegate == null)
                    {
                        // It's a class. Note rewrite here.
                        current_structure._class_fields.Add(new Tuple <System.Reflection.FieldInfo, object>(fi, field_value));
                    }

                    // When field of the target/class is a delegate, the intent in the code
                    // is to call the delegate via the field. Since pointers to anything
                    // are not allowed in C++ AMP, we need to actually either rewrite the
                    // structure so that the field is a method (not preferred),
                    // rewrite the name to the true name of the method called, or
                    // rewrite the method to be the name of the field (not preferred).
                    // In any case, note the association of the field with
                    // the delegate.
                    Type field_type = fi.FieldType;
                    if (field_value != null && TypesUtility.IsBaseType(field_type, typeof(Delegate)))
                    {
                        Delegate d = field_value as Delegate;
                        current_structure._delegate_fields.Add(new Tuple <System.Reflection.FieldInfo, Delegate>(fi, d));
                    }
                }
            }

            //foreach (object node in data_graph.Vertices)
            //{
            //    Structure current_structure = null;
            //    map_target_to_structure.TryGetValue(node, out current_structure);
            //    if (current_structure != null)
            //    {
            //        foreach (Tuple<object, string> pair in _class_fields)
            //        {
            //            if (pair.Item1 == node)
            //                current_structure.rewrite_names.Add(pair.Item2);
            //        }
            //    }
            //}

            // Add methods from control flow graph.
            foreach (CFG.CFGVertex node in control_flow_graph.VertexNodes)
            {
                if (node.IsEntry)
                {
                    // Scan structure and see if the instance contains the method.
                    foreach (KeyValuePair <object, Structure> pair in map_target_to_structure)
                    {
                        object    o = pair.Key;
                        Structure s = pair.Value;
                        Type      t = o.GetType();
                        Mono.Cecil.TypeDefinition td = node.Method.DeclaringType;
                        Type tdt = Campy.Types.Utils.ReflectionCecilInterop.ConvertToSystemReflectionType(td);
                        if (tdt == t)
                        {
                            // Add method to structure.
                            MethodBase mi = Campy.Types.Utils.ReflectionCecilInterop.ConvertToSystemReflectionMethodInfo(node.Method);
                            s.AddMethod(mi);
                            // Get calls.
                            foreach (CFG.CFGVertex c in control_flow_graph.AllInterproceduralCalls(node))
                            {
                                MethodBase mic = Campy.Types.Utils.ReflectionCecilInterop.ConvertToSystemReflectionMethodInfo(c.Method);
                                s.AddMethod(mic);
                            }
                        }
                    }
                }
            }


            // For each field that is a delegate, find the target structure corresponding to the delegate,
            // and add the delegate method to the structure.
            foreach (KeyValuePair <Delegate, object> pair in delegate_to_instance)
            {
                Delegate  k = pair.Key;
                object    v = pair.Value;
                Structure target_structure = null;
                map_target_to_structure.TryGetValue(v, out target_structure);
                Debug.Assert(target_structure != null);
                target_structure.AddMethod(k.Method);
            }

            //stack_of_structures = new StackQueue<Structure>();
            //stack_of_structures.Push(top_level_structure);
            //while (stack_of_structures.Count > 0)
            //{
            //    Structure cur_structure = stack_of_structures.Pop();
            //    foreach (Tuple<System.Reflection.FieldInfo, Delegate> tuple in cur_structure._delegate_fields)
            //    {
            //        if (tuple.Item2.Target != null)
            //        {
            //            Structure target_structure = null;
            //            map_target_to_structure.TryGetValue(tuple.Item2.Target, out target_structure);
            //            Debug.Assert(target_structure != null);
            //            target_structure.AddMethod(tuple.Item2.Method, tuple.Item2.Method.Name);
            //        }
            //        else
            //        {
            //            // Target empty. Map delegate to target.

            //        }
            //    }
            //    foreach (Structure child in cur_structure.nested_structures)
            //    {
            //        stack_of_structures.Push(child);
            //    }
            //}

            return(top_level_structure);
        }
Пример #8
0
 public LValue(StackQueue <ValueBase> stack)
 {
     _space    = stack.Section(1);
     _relative = 0;
     _absolute = _space.Base + _relative;
 }
Пример #9
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();
        }