예제 #1
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);
        }
예제 #2
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);
        }