private Structure(Structure parent, object target) { parent._nested_structures.Add(this); this._class_instance = target; }
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); }
private static void AssignmentManagedStruct(Structure structure, ref object staging_object) { Type s = staging_object.GetType(); SR.FieldInfo[] sfi = s.GetFields(); foreach (SR.FieldInfo fi in structure.simple_fields) { object field_value = fi.GetValue(structure._class_instance); String na = fi.Name; String tys = Campy.Utils.Utility.GetFriendlyTypeName(fi.FieldType); // Copy. SR.FieldInfo hostObjectField = fi; object value = field_value; // Never copy tile_statics... if (TypesUtility.IsCampyTileStaticType(fi.FieldType)) { continue; } var deviceObjectField = sfi.Where(f => f.Name == fi.Name).FirstOrDefault(); if (deviceObjectField == null) { throw new ArgumentException("Field not found."); } if (field_value != null) { deviceObjectField.SetValue(staging_object, value); } else { // In order to prevent a lot of segv's ... // Create a default value based on field type? if (TypesUtility.IsCampyArrayViewType(fi.FieldType)) { deviceObjectField.SetValue(staging_object, Array_View <int> .Default_Value); } else if (TypesUtility.IsCampyArrayType(fi.FieldType)) { deviceObjectField.SetValue(staging_object, Array <int> .Default_Value); } else if (TypesUtility.IsCampyAcceleratorType(fi.FieldType)) { deviceObjectField.SetValue(staging_object, Accelerator.Default_Value); } else if (TypesUtility.IsCampyAcceleratorViewType(fi.FieldType)) { deviceObjectField.SetValue(staging_object, Accelerator_View.Default_Value); } else if (TypesUtility.IsCampyIndexType(fi.FieldType)) { deviceObjectField.SetValue(staging_object, Index.Default_Value); } else if (TypesUtility.IsCampyExtentType(fi.FieldType)) { deviceObjectField.SetValue(staging_object, Extent.Default_Value); } else { } } } // Add in other structures. foreach (Structure child in structure.nested_structures) { SR.FieldInfo sn = sfi.Where(f => child.Name == f.Name).FirstOrDefault(); if (sn == null) { throw new ArgumentException("Field not found."); } object vsn = sn.GetValue(staging_object); if (vsn == null) { throw new ArgumentException("Value not found."); } AssignmentManagedStruct(child, ref vsn); } }
// 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); }
private static Type GetThunk(Delegate kernel, Campy.Types.Extent extent, Structure structure) { // Get MethodInfo for lambda. SR.MethodInfo mi = kernel.Method; object target = kernel.Target; Type target_type = target.GetType(); String target_type_name = target_type.FullName; target_type_name = Campy.Utils.Utility.NormalizeSystemReflectionName(target_type_name); // Get assembly name which encloses code for kernel. String kernel_assembly_file_name = mi.DeclaringType.Assembly.Location; // Get directory containing the assembly. String full_path = Path.GetFullPath(kernel_assembly_file_name); full_path = Path.GetDirectoryName(full_path); // Get full name of kernel, including normalization because they cannot be compared directly with Mono.Cecil names. String kernel_full_name = string.Format("{0} {1}.{2}({3})", mi.ReturnType.FullName, Campy.Utils.Utility.RemoveGenericParameters(mi.ReflectedType), mi.Name, string.Join(",", mi.GetParameters().Select(o => string.Format("{0}", o.ParameterType)).ToArray())); kernel_full_name = Campy.Utils.Utility.NormalizeSystemReflectionName(kernel_full_name) + "_managed"; // Get short name of Campy kernel. String campy_kernel_class_short_name = target_type_name + "_managed"; // Derive name of assembly containing corresponding Campy code for lambda. String campy_assembly_file_name = full_path + "\\" + kernel_full_name; //String ext = Path.GetExtension(campy_assembly_file_name); //campy_assembly_file_name = campy_assembly_file_name.Replace(ext, ""); campy_assembly_file_name = campy_assembly_file_name + "_aux"; campy_assembly_file_name = campy_assembly_file_name + ".dll"; bool rebuild = false; SR.Assembly dll = null; Type thunk = null; // Determine if this campy assembly has been seen before. Assembly assembly = null; bool found = assemblies.TryGetValue(campy_assembly_file_name, out assembly); if (!found) { assembly = new Assembly(campy_assembly_file_name); assemblies.Add(campy_assembly_file_name, assembly); } // Create app domain in order to test the dll. //SR.AssemblyName assemblyName = new SR.AssemblyName(); //assemblyName.CodeBase = assembly.Name; try { dll = SR.Assembly.LoadFile(campy_assembly_file_name); } catch { rebuild = true; } // Determine if this kernel has been executed before. if (!assembly.executed_lambdas.Contains(kernel_full_name)) { // Check timestamps. if (!rebuild) { DateTime dt_kernel_assembly = File.GetLastWriteTime(kernel_assembly_file_name); DateTime dt_campy_kernel_assembly = File.GetLastWriteTime(campy_assembly_file_name); if (dt_campy_kernel_assembly < dt_kernel_assembly) { rebuild = true; } } if (!rebuild) { //dll = dom.Load(assemblyName); // Get address of thunk class corresponding to lambda. thunk = dll.GetType(kernel_full_name); if (thunk == null) { rebuild = true; } } if (rebuild) { Converter converter = new Converter(assembly); // Convert lambda into GPU target code. converter.Convert(kernel, extent, structure); // Compile target code into object code. builder.Compile(assembly); // Link object code. builder.Link(assembly); } // Note that lambda was generated and compiled. assembly.executed_lambdas.Add(kernel_full_name); } // Load/reload assembly. //dll = dom.Load(assemblyName); dll = SR.Assembly.LoadFile(campy_assembly_file_name); // Get address of thunk class corresponding to lambda. thunk = dll.GetType(kernel_full_name); return(thunk); }