Example #1
0
        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;
        }
Example #2
0
 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;
        }
Example #4
0
        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);
        }
Example #5
0
        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;
        }
Example #7
0
        // 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);
                }
            }
        }
Example #8
0
        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);
                    }
                }
            }
        }
Example #10
0
 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;
 }
Example #11
0
        /// <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);
        }
Example #12
0
 /// <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)));
 }
Example #13
0
        /// <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);
            }
        }
Example #14
0
 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();
        }
Example #16
0
        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;
        }
Example #17
0
 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;
 }
Example #18
0
        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);
                        }
                    }
            }
        }