Esempio n. 1
0
 internal static CFG Singleton(Analysis analysis)
 {
     if (_singleton == null)
     {
         _singleton = new CFG(analysis);
     }
     return(_singleton);
 }
Esempio n. 2
0
        static public void AnalyzeThisAssembly()
        {
            Options.Singleton.Set(Options.OptionType.DisplayFinalGraph, true);
            Options.Singleton.Set(Options.OptionType.DoNotAnalyzeCampyAssemblies, true);

            if (Environment.Is64BitProcess)
            {
                System.Console.WriteLine("Thunk between 64-bit C# and C++ AMP unimplemented.");
                throw new Exception("Thunk between 64-bit C# and C++ AMP unimplemented.");
            }
            builder = new Build();
            System.Diagnostics.StackTrace stack_trace = new System.Diagnostics.StackTrace(true);
            System.Diagnostics.StackFrame stack_frame = stack_trace.GetFrame(1);
            System.Reflection.Assembly    assembly    = stack_frame.GetMethod().DeclaringType.Assembly;
            CFG control_flow_graph = CFG.Singleton(Analysis.Singleton());

            // Handle the following code:
            //    delegate int fun(int xxx);
            //    fun x = (int y) => { return y + 1; };
            //
            // I don't really understand, but when a delegate type is created,
            // it seems to call the function System.MulticastDelegate.CtorClosed(Object, IntPtr).
            // There is no body for the constructor of the delegate "fun"
            // which does this--at least, I can't find it anywhere. So, when we see a newobj
            // of an object derived from MulticastDelegate, make SSA match this function.
            // This function DOES hava a method body which does seem to do what is
            // necessary.
            SR.MethodInfo delegate_constructor = ReflectionCecilInterop.FindMethod("System.MulticastDelegate.CtorClosed(Object, IntPtr)");
            control_flow_graph.Add(delegate_constructor);
            control_flow_graph.ExtractBasicBlocks();

            control_flow_graph.AddAssembly(assembly);
            control_flow_graph.ExtractBasicBlocks();

            control_flow_graph.FindNewBlocks(assembly);

            if (Options.Singleton.Get(Options.OptionType.DisplayFinalGraph))
            {
                System.Console.WriteLine("Final graph:");
                control_flow_graph.OutputEntireGraph();
            }
        }
Esempio n. 3
0
 Analysis()
 {
     // Construct control flow graph from lambda delegate method.
     _control_flow_graph = CFG.Singleton(this);
 }
Esempio n. 4
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);
        }
Esempio n. 5
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);
            }