public static ModuleReader Read(ModuleDefinition module) { var reader = new ModuleReader(); if (module.AssemblyReferences.All(reference => reference.Name != "Stiletto")) { return reader; } var allTypes = module.GetTypes(); foreach (var t in allTypes) { if (IsModule(t)) { reader.ModuleTypes.Add(t); } if (IsInject(t)) { reader.InjectTypes.Add(t); } } return reader; }
public static List<MethodDefinition> findAll(ModuleDefinition module) { var list = new List<MethodDefinition>(); foreach (var type in module.GetTypes()) { foreach (var method in type.Methods) { if (isInvalidMethod(method)) list.Add(method); } } return list; }
public static List<MethodDefinition> find(ModuleDefinition module) { var inlinedMethods = new List<MethodDefinition>(); foreach (var type in module.GetTypes()) { foreach (var method in type.Methods) { if (MethodCallInliner.canInline(method)) inlinedMethods.Add(method); } } return inlinedMethods; }
public static TypeReference FindBCLType(System.Type type) { var runtime = new RUNTIME(); TypeReference result = null; Mono.Cecil.ModuleDefinition md = Mono.Cecil.ModuleDefinition.ReadModule(FindCoreLib()); foreach (var bcl_type in md.GetTypes()) { if (bcl_type.FullName == type.FullName) { return(bcl_type); } } return(result); }
public static List<MethodDefinition> find(ModuleDefinition module, IEnumerable<MethodDefinition> notInlinedMethods) { var notInlinedMethodsDict = new Dictionary<MethodDefinition, bool>(); foreach (var method in notInlinedMethods) notInlinedMethodsDict[method] = true; var inlinedMethods = new List<MethodDefinition>(); foreach (var type in module.GetTypes()) { foreach (var method in type.Methods) { if (!notInlinedMethodsDict.ContainsKey(method) && canInline(method)) inlinedMethods.Add(method); } } return inlinedMethods; }
public IEnumerable<TypeDefinition> Select(ModuleDefinition moduleDefinition) { var typesToProcess = new List<TypeDefinition>(); foreach (TypeDefinition type in moduleDefinition.GetTypes()) { if (CanVirtualize(type)) { if ((!IsContainer(type) && !ImplementsInterfaces(type)) || HasDoVirtualizeAttribute(type)) { typesToProcess.Add(type); } } } return typesToProcess; }
// before yielding type def A it yields every nested type in A // it could be improved by doing an iterative dfs public static IEnumerable <Cecil.TypeDefinition> TraverseTypes(this Cecil.ModuleDefinition module) { ISet <Cecil.TypeDefinition> visited = new HashSet <Cecil.TypeDefinition>(); foreach (Cecil.TypeDefinition typeDefinition in module.GetTypes()) { if (visited.Contains(typeDefinition)) { continue; } foreach (Cecil.TypeDefinition t in DFS(typeDefinition, visited)) { yield return(t); } } }
private static IEnumerable <TypeDefinition> GetTypes(Collection <TypeDefinition> types) { for (int i = 0; i < types.Count; i++) { TypeDefinition item = types[i]; yield return(item); if (item.HasNestedTypes) { foreach (TypeDefinition typeDefinition in ModuleDefinition.GetTypes(item.NestedTypes)) { yield return(typeDefinition); } item = null; } } }
public void MapCallsToVirtual(IEnumerable<MethodDefinition> members, ModuleDefinition moduleDefinition) { foreach (TypeDefinition typeDefinition in moduleDefinition.GetTypes()) { if (typeDefinition.IsAbstract || typeDefinition.IsEnum) { continue; } foreach (MethodDefinition methodDefinition in typeDefinition.Methods) { if (methodDefinition.HasBody) { ReplaceCallsTo(methodDefinition, members); } } } }
private IEnumerable<LocalizedString> Parse (ModuleDefinition module) { return from type in module.GetTypes() where !LOCALIZATION_TYPES.Contains (type.FullName) from method in type.Methods where method.HasBody && method.Body.Instructions.Count > 0 from invocation in ParseLocalizedStringInvocations (method.Body.Instructions [0]) from localized_string in ParseLocalizedStringInvocation (invocation) select localized_string; }
/// <summary> /// Weaves the specified module definition. /// </summary> /// <param name="moduleDefinition">The module definition.</param> public void Weave(ModuleDefinition moduleDefinition) { var auditTimer = new AuditTimer(); var stopwatch = new Stopwatch(); stopwatch.Start(); // sanity check auditTimer.NewZone("IAdvice location"); var adviceInterface = TypeResolver.Resolve(moduleDefinition, Binding.AdviceInterfaceName, true); if (adviceInterface == null) { Logger.WriteWarning("IAdvice interface not found here, exiting"); return; } // runtime check auditTimer.NewZone("Runtime check"); var targetFramework = GetTargetFramework(moduleDefinition); InjectAsPrivate = targetFramework.Silverlight == null && targetFramework.WindowsPhone == null; //Logger.WriteDebug("t1: {0}ms", (int)stopwatch.ElapsedMilliseconds); // weave methods (they can be property-related, too) auditTimer.NewZone("Weavable methods detection"); var weavableMethods = GetMarkedMethods(moduleDefinition, adviceInterface).ToArray(); auditTimer.NewZone("Methods weaving"); weavableMethods.AsParallel().ForAll(m => WeaveMethod(moduleDefinition, m, adviceInterface)); auditTimer.NewZone("Weavable interfaces detection"); var weavableInterfaces = GetAdviceHandledInterfaces(moduleDefinition).ToArray(); auditTimer.NewZone("Interface methods weaving"); weavableInterfaces.AsParallel().ForAll(i => WeaveInterface(moduleDefinition, i)); //Logger.WriteDebug("t2: {0}ms", (int)stopwatch.ElapsedMilliseconds); // and then, the info advices auditTimer.NewZone("Info advices weaving"); var infoAdviceInterface = TypeResolver.Resolve(moduleDefinition, Binding.InfoAdviceInterfaceName, true); moduleDefinition.GetTypes().AsParallel().ForAll(t => WeaveInfoAdvices(moduleDefinition, t, infoAdviceInterface)); auditTimer.LastZone(); //Logger.WriteDebug("t3: {0}ms", (int)stopwatch.ElapsedMilliseconds); var report = auditTimer.GetReport(); var maxLength = report.Keys.Max(k => k.Length); Logger.WriteDebug("--- Timings --------------------------"); foreach (var reportPart in report) Logger.WriteDebug("{0} : {1}ms", reportPart.Key.PadRight(maxLength), (int)reportPart.Value.TotalMilliseconds); Logger.WriteDebug("--------------------------------------"); Logger.Write("MrAdvice {3} weaved module '{0}' (targeting framework {2}) in {1}ms", moduleDefinition.Assembly.FullName, (int)stopwatch.ElapsedMilliseconds, targetFramework, Product.Version); }
/// <summary> /// Gets the advice handled interfaces. /// This is done by analyzing calls in all methods from module /// </summary> /// <param name="moduleDefinition">The module definition.</param> /// <param name="invokedMethod">The invoked method.</param> /// <param name="genericParameterIndex">Index of the generic parameter.</param> /// <returns></returns> private static IEnumerable<Tuple<TypeReference, MethodDefinition>> GetAdviceHandledInterfaces(ModuleDefinition moduleDefinition, MethodReference invokedMethod, int genericParameterIndex) { return moduleDefinition.GetTypes().SelectMany(t => t.GetMethods().Where(m => m.HasBody) .AsParallel().SelectMany(definition => GetAdviceHandledInterfaces(definition, invokedMethod, genericParameterIndex))); }
/// <summary> /// Weaves the interface. /// What we do here is: /// - creating a class (wich is named after the interface name) /// - this class implements all interface members /// - all members invoke Invocation.ProcessInterfaceMethod /// </summary> /// <param name="moduleDefinition">The module definition.</param> /// <param name="interfaceType">Type of the interface.</param> private void WeaveInterface(ModuleDefinition moduleDefinition, TypeReference interfaceType) { Logger.WriteDebug("Weaving interface '{0}'", interfaceType.FullName); TypeDefinition implementationType; TypeDefinition advisedInterfaceType; TypeDefinition interfaceTypeDefinition; lock (moduleDefinition) { // ensure we're creating the interface only once var implementationTypeName = GetImplementationTypeName(interfaceType.Name); var implementationTypeNamespace = interfaceType.Namespace; if (moduleDefinition.GetTypes().Any(t => t.Namespace == implementationTypeNamespace && t.Name == implementationTypeName)) return; // now, create the implementation type interfaceTypeDefinition = interfaceType.Resolve(); var typeAttributes = (InjectAsPrivate ? TypeAttributes.NotPublic : TypeAttributes.Public) | TypeAttributes.Class | TypeAttributes.BeforeFieldInit; advisedInterfaceType = TypeResolver.Resolve(moduleDefinition, Binding.AdvisedInterfaceTypeName, true); var advisedInterfaceTypeReference = moduleDefinition.SafeImport(advisedInterfaceType); implementationType = new TypeDefinition(implementationTypeNamespace, implementationTypeName, typeAttributes, advisedInterfaceTypeReference); lock (moduleDefinition) moduleDefinition.Types.Add(implementationType); } implementationType.Interfaces.Add(interfaceType); // create empty .ctor. This .NET mofo wants it! var baseEmptyConstructor = moduleDefinition.SafeImport(advisedInterfaceType.Resolve().GetConstructors().Single()); const MethodAttributes ctorAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; var method = new MethodDefinition(".ctor", ctorAttributes, moduleDefinition.TypeSystem.Void); method.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0)); method.Body.Instructions.Add(Instruction.Create(OpCodes.Call, baseEmptyConstructor)); method.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); implementationType.Methods.Add(method); // create implementation methods foreach (var interfaceMethod in interfaceTypeDefinition.GetMethods().Where(m => !m.IsSpecialName)) WeaveInterfaceMethod(interfaceMethod, implementationType, true); // create implementation properties foreach (var interfaceProperty in interfaceTypeDefinition.Properties) { var implementationProperty = new PropertyDefinition(interfaceProperty.Name, PropertyAttributes.None, interfaceProperty.PropertyType); implementationType.Properties.Add(implementationProperty); if (interfaceProperty.GetMethod != null) implementationProperty.GetMethod = WeaveInterfaceMethod(interfaceProperty.GetMethod, implementationType, InjectAsPrivate); if (interfaceProperty.SetMethod != null) implementationProperty.SetMethod = WeaveInterfaceMethod(interfaceProperty.SetMethod, implementationType, InjectAsPrivate); } // create implementation events foreach (var interfaceEvent in interfaceTypeDefinition.Events) { var implementationEvent = new EventDefinition(interfaceEvent.Name, EventAttributes.None, moduleDefinition.SafeImport(interfaceEvent.EventType)); implementationType.Events.Add(implementationEvent); if (interfaceEvent.AddMethod != null) implementationEvent.AddMethod = WeaveInterfaceMethod(interfaceEvent.AddMethod, implementationType, InjectAsPrivate); if (interfaceEvent.RemoveMethod != null) implementationEvent.RemoveMethod = WeaveInterfaceMethod(interfaceEvent.RemoveMethod, implementationType, InjectAsPrivate); } }
public IEnumerable <TypeDefinition> GetTypes() { return(ModuleDefinition.GetTypes(this.Types)); }
private static List<TypeDefinition> GetOrderedTypes( ModuleDefinition mainModule, List<String> explicitTypesOrder) { var unorderedTypes = mainModule.GetTypes() .Where(item => item.FullName != "<Module>") .ToList(); if (explicitTypesOrder == null || explicitTypesOrder.Count == 0) { return SortTypesAccordingUsages( unorderedTypes, mainModule.FullyQualifiedName); } return explicitTypesOrder .Join(unorderedTypes, outer => outer, inner => inner.FullName, (inner, outer) => outer) .ToList(); }
public static List<MethodDefinition> find(ModuleDefinition module) { // Not all garbage methods are inlined, possibly because we remove some code that calls // the garbage method before the methods inliner has a chance to inline it. Try to find // all garbage methods and other code will figure out if there are any calls left. var inlinedMethods = new List<MethodDefinition>(); foreach (var type in module.GetTypes()) { foreach (var method in type.Methods) { if (!method.IsStatic) continue; if (!method.IsAssembly && !method.IsCompilerControlled && !method.IsPrivate) continue; if (method.GenericParameters.Count > 0) continue; if (method.Name == ".cctor") continue; if (method.Body == null) continue; var instrs = method.Body.Instructions; if (instrs.Count < 2) continue; switch (instrs[0].OpCode.Code) { case Code.Ldc_I4: case Code.Ldc_I4_0: case Code.Ldc_I4_1: case Code.Ldc_I4_2: case Code.Ldc_I4_3: case Code.Ldc_I4_4: case Code.Ldc_I4_5: case Code.Ldc_I4_6: case Code.Ldc_I4_7: case Code.Ldc_I4_8: case Code.Ldc_I4_M1: case Code.Ldc_I4_S: case Code.Ldc_I8: case Code.Ldc_R4: case Code.Ldc_R8: case Code.Ldftn: case Code.Ldnull: case Code.Ldstr: case Code.Ldtoken: case Code.Ldsfld: case Code.Ldsflda: if (instrs[1].OpCode.Code != Code.Ret) continue; break; case Code.Ldarg: case Code.Ldarg_S: case Code.Ldarg_0: case Code.Ldarg_1: case Code.Ldarg_2: case Code.Ldarg_3: case Code.Ldarga: case Code.Ldarga_S: case Code.Call: case Code.Newobj: if (!isCallMethod(method)) continue; break; default: continue; } inlinedMethods.Add(method); } } return inlinedMethods; }
public static TypeDefinition getType(ModuleDefinition module, TypeReference typeReference) { if (typeReference == null) return null; if (typeReference is TypeDefinition) return (TypeDefinition)typeReference; foreach (var type in module.GetTypes()) { if (MemberReferenceHelper.compareTypes(type, typeReference)) return type; } return null; }
public static void Initialize() { // Load C# library for BCL, and grab all types and methods. // The tables that this method sets up are: // _substituted_bcl -- maps types in program (represented in Mono.Cecil) into GPU BCL types (represented in Mono.Cecil). // _system_type_to_mono_type_for_bcl -- associates types in GPU BCL with NET Core/NET Framework/... in user program. // Note, there seems to be an underlying bug in System.Type.GetType for certain generics, like System.Collections.Generic.HashSet. // The method returns null. var xx = typeof(System.Collections.Generic.HashSet <>); var x2 = typeof(System.Collections.Generic.HashSet <int>); var yy = System.Type.GetType("System.Collections.Generic.HashSet"); var y2 = System.Type.GetType("System.Collections.Generic.HashSet<>"); var y3 = System.Type.GetType("System.Collections.Generic.HashSet`1"); var y4 = System.Type.GetType("System.Collections.Generic.HashSet<T>"); var y5 = System.Type.GetType(xx.FullName); var y6 = System.Type.GetType(@"System.Collections.Generic.HashSet`1[System.Int32]"); var y7 = System.Type.GetType(@"System.Collections.Generic.Dictionary`2[System.String,System.String]"); var y8 = System.Type.GetType(x2.FullName); // Set up _substituted_bcl. var runtime = new RUNTIME(); // Find corlib.dll. It could be anywhere, but let's check the usual spots. Mono.Cecil.ModuleDefinition md = Mono.Cecil.ModuleDefinition.ReadModule(FindCoreLib()); foreach (var bcl_type in md.GetTypes()) { // Filter out <Module> and <PrivateImplementationDetails>, among possible others. Regex regex = new Regex(@"^[<]\w+[>]"); if (regex.IsMatch(bcl_type.FullName)) { continue; } // Try to map the type into native NET type. Some things just won't. var t_system_type = System.Type.GetType(bcl_type.FullName); if (t_system_type == null) { continue; } var to_mono = t_system_type.ToMonoTypeReference(); // Add entry for converting intrinsic NET BCL type to GPU BCL type. _substituted_bcl.Add(to_mono, bcl_type); foreach (var m in bcl_type.Methods) { var x = m.ImplAttributes; if ((x & MethodImplAttributes.InternalCall) != 0) { if (Campy.Utils.Options.IsOn("runtime_trace")) { System.Console.WriteLine("Internal call set up " + bcl_type + " " + m); } _internalCalls.Add(new BclNativeMethod(bcl_type, m)); } } } // Set up _system_type_to_mono_type_for_bcl. // There really isn't any good way to set this up because NET Core System.Reflection does not work // on .LIB files. So begins the kludge... // Parse PTX files for all "visible" functions, and create LLVM declarations. // For "Internal Calls", these functions appear here, but also on the _internalCalls list. var assembly = Assembly.GetAssembly(typeof(Campy.Compiler.RUNTIME)); var resource_names = assembly.GetManifestResourceNames(); foreach (var resource_name in resource_names) { using (Stream stream = assembly.GetManifestResourceStream(resource_name)) using (StreamReader reader = new StreamReader(stream)) { string gpu_bcl_ptx = reader.ReadToEnd(); // Parse the PTX for ".visible" functions, and enter each in // the runtime table. // This should match ".visible" <spaces> ".func" <spaces> <function-return>? <function-name> // over many lines, many times. Regex regex = new Regex( @"\.visible\s+\.func\s+(?<return>[(][^)]*[)]\s+)?(?<name>\w+)\s*(?<params>[(][^)]*[)]\s+)"); foreach (Match match in regex.Matches(gpu_bcl_ptx)) { Regex space = new Regex(@"\s\s+"); string mangled_name = match.Groups["name"].Value.Trim(); string return_type = match.Groups["return"].Value.Trim(); return_type = space.Replace(return_type, " "); string parameters = match.Groups["params"].Value.Trim(); parameters = space.Replace(parameters, " "); if (Campy.Utils.Options.IsOn("runtime_trace")) { System.Console.WriteLine(mangled_name + " " + return_type + " " + parameters); } if (JITER.functions_in_internal_bcl_layer.ContainsKey(mangled_name)) { continue; } TypeRef llvm_return_type = default(TypeRef); TypeRef[] args; // Construct LLVM extern that corresponds to type of function. // Parse return_type and parameters strings... Regex param_regex = new Regex(@"\.param(\s+\.align\s+\d+)?\s+(?<type>\S+)\s"); { // parse return. if (return_type == "") { llvm_return_type = LLVM.VoidType(); } else { foreach (Match ret in param_regex.Matches(return_type)) { var x = ret.Groups["type"].Value; _ptx_type_to_llvm_typeref.TryGetValue( x, out TypeRef y); if (Campy.Utils.Options.IsOn("runtime_trace")) { System.Console.WriteLine("name " + x + " value " + y.ToString()); } llvm_return_type = y; } } } { // parse parameters. List <TypeRef> args_list = new List <TypeRef>(); foreach (Match ret in param_regex.Matches(parameters)) { var x = ret.Groups["type"].Value; if (!_ptx_type_to_llvm_typeref.TryGetValue( x, out TypeRef y)) { throw new Exception("Unknown type syntax in ptx parameter."); } if (Campy.Utils.Options.IsOn("runtime_trace")) { System.Console.Write("parameter "); System.Console.WriteLine("name " + x + " value " + y.ToString()); } args_list.Add(y); } args = args_list.ToArray(); } var decl = LLVM.AddFunction( JITER.global_llvm_module, mangled_name, LLVM.FunctionType( llvm_return_type, args, false)); PtxFunction ptxf = new PtxFunction(mangled_name, decl); if (Campy.Utils.Options.IsOn("runtime_trace")) { System.Console.WriteLine(ptxf._mangled_name + " " + ptxf._short_name + " " + ptxf._valueref); } JITER.functions_in_internal_bcl_layer.Add(mangled_name, decl); _ptx_functions.Add(ptxf); } } } }