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); } } }
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); }
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); } } }
// 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); } } }
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()); }
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); }
// 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 LValue(StackQueue <ValueBase> stack) { _space = stack.Section(1); _relative = 0; _absolute = _space.Base + _relative; }
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(); }