internal static CFG Singleton(Analysis analysis) { if (_singleton == null) { _singleton = new CFG(analysis); } return(_singleton); }
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(); } }
Analysis() { // Construct control flow graph from lambda delegate method. _control_flow_graph = CFG.Singleton(this); }
// 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); }
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); }