コード例 #1
0
ファイル: AddReferenceProcessor.cs プロジェクト: cg123/xenko
        public bool Process(AssemblyProcessorContext context)
        {
            bool changed = false;

            // Make sure all assemblies in serializatonProjectReferencePaths are referenced (sometimes they might be optimized out if no direct references)
            foreach (var serializatonProjectReferencePath in referencesToAdd)
            {
                var shortAssemblyName = Path.GetFileNameWithoutExtension(serializatonProjectReferencePath);
            
                // Still in references (not optimized)
                if (context.Assembly.MainModule.AssemblyReferences.Any(x => x.Name == shortAssemblyName))
                    continue;
            
                if (!File.Exists(serializatonProjectReferencePath))
                    continue;
            
                // For now, use AssemblyDefinition.ReadAssembly to compute full name -- maybe not very efficient but it shouldn't happen often anyway)
                var referencedAssembly = AssemblyDefinition.ReadAssembly(serializatonProjectReferencePath, new ReaderParameters { AssemblyResolver = context.AssemblyResolver });

                context.Assembly.MainModule.AssemblyReferences.Add(AssemblyNameReference.Parse(referencedAssembly.FullName));
                changed = true;
            }

            return changed;
        }
コード例 #2
0
        public bool Process(AssemblyProcessorContext context)
        {
            context.Assembly.Name.Name = assemblyName;
            context.Assembly.MainModule.Name = assemblyName + ".dll";

            return true;
        }
コード例 #3
0
        public bool Process(AssemblyProcessorContext context)
        {
            var serializerSourceCode = ComplexSerializerGenerator.GenerateSerializationAssembly(context.AssemblyResolver, context.Assembly, context.Log);
            sourceCodeRegisterAction(serializerSourceCode);

            return true;
        }
コード例 #4
0
ファイル: InteropProcessor.cs プロジェクト: rohitshe/Code
        public bool Process(AssemblyProcessorContext context)
        {
            this.assembly = context.Assembly;
            // Import void* and int32 from assembly using mscorlib specific version (2.0 or 4.0 depending on assembly)
            voidPointerType = new PointerType(assembly.MainModule.TypeSystem.Void);
            intType         = assembly.MainModule.TypeSystem.Int32;

            // Remove CompilationRelaxationsAttribute
            if (context.Platform == PlatformType.WindowsStore || context.Platform == PlatformType.WindowsPhone)
            {
                for (int i = 0; i < assembly.CustomAttributes.Count; i++)
                {
                    var customAttribute = assembly.CustomAttributes[i];
                    if (customAttribute.AttributeType.FullName == typeof(CompilationRelaxationsAttribute).FullName)
                    {
                        assembly.CustomAttributes.RemoveAt(i);
                        i--;
                    }
                }
            }

            context.Log.WriteLine($"Patch for assembly [{assembly.FullName}]");
            foreach (var type in assembly.MainModule.Types)
            {
                PatchType(type);
            }

            // Remove All Interop classes
            foreach (var type in classToRemoveList)
            {
                assembly.MainModule.Types.Remove(type);
            }

            return(true);
        }
コード例 #5
0
ファイル: InteropProcessor.cs プロジェクト: whztt07/xenko
        public bool Process(AssemblyProcessorContext context)
        {
            this.assembly = context.Assembly;
            // Import void* and int32 from assembly using mscorlib specific version (2.0 or 4.0 depending on assembly)
            voidPointerType = new PointerType(assembly.MainModule.TypeSystem.Void);
            intType = assembly.MainModule.TypeSystem.Int32;

            // Remove CompilationRelaxationsAttribute
            if (context.Platform == PlatformType.WindowsStore || context.Platform == PlatformType.WindowsPhone)
            {
                for (int i = 0; i < assembly.CustomAttributes.Count; i++)
                {
                    var customAttribute = assembly.CustomAttributes[i];
                    if (customAttribute.AttributeType.FullName == typeof(CompilationRelaxationsAttribute).FullName)
                    {
                        assembly.CustomAttributes.RemoveAt(i);
                        i--;
                    }
                }
            }

            Log("Patch for assembly [{0}]", assembly.FullName);
            foreach (var type in assembly.MainModule.Types)
                PatchType(type);

            // Remove All Interop classes
            foreach (var type in classToRemoveList)
                assembly.MainModule.Types.Remove(type);

            return true;
        }
コード例 #6
0
        public bool Process(AssemblyProcessorContext context)
        {
            context.Assembly.Name.Name       = assemblyName;
            context.Assembly.MainModule.Name = assemblyName + ".dll";

            return(true);
        }
コード例 #7
0
        public bool Process(AssemblyProcessorContext context)
        {
            var serializerSourceCode = ComplexSerializerGenerator.GenerateSerializationAssembly(context.AssemblyResolver, context.Assembly, context.Log);

            sourceCodeRegisterAction(serializerSourceCode, "DataSerializers");

            return(true);
        }
コード例 #8
0
        public bool Process(AssemblyProcessorContext context)
        {
            // Generate serialization assembly
            var serializationAssemblyFilepath = ComplexSerializerGenerator.GenerateSerializationAssemblyLocation(context.Assembly.MainModule.FullyQualifiedName);
            context.Assembly = ComplexSerializerGenerator.GenerateSerializationAssembly(context.Platform, context.AssemblyResolver, context.Assembly, serializationAssemblyFilepath, SignKeyFile, References, MemoryReferences, Log);

            return true;
        }
コード例 #9
0
        public bool Process(AssemblyProcessorContext context)
        {
            // Generate serialization assembly
            var serializationAssemblyFilepath = ComplexSerializerGenerator.GenerateSerializationAssemblyLocation(context.Assembly.MainModule.FullyQualifiedName);

            context.Assembly = ComplexSerializerGenerator.GenerateSerializationAssembly(context.Platform, context.AssemblyResolver, context.Assembly, serializationAssemblyFilepath, SignKeyFile, SerializatonProjectReferencePaths);

            return(true);
        }
コード例 #10
0
        public bool Process(AssemblyProcessorContext context)
        {
            var basePath = Path.Combine(Path.GetDirectoryName(inputFile) ?? "", Path.GetFileNameWithoutExtension(inputFile) ?? "");
            var xmlFile = basePath + ".xml";
            var targetFile = basePath + ".usrdoc";

            // No xml documentation file available, stop here.
            if (!File.Exists(xmlFile))
                return false;

            var result = new Dictionary<string, string>();

            var document = XElement.Load(xmlFile);
            foreach (var member in document.Descendants("member"))
            {
                var nameAttribute = member.Attribute("name");
                if (nameAttribute == null)
                    continue;
                string key = nameAttribute.Value;

                string userdoc = null;
                foreach (var userdocElement in member.Descendants("userdoc"))
                {
                    if (userdoc != null)
                    {
                        LogLine("Warning: the member {0} has multiple userdoc, only the first one will be used.", key);
                        break;
                    }
                    if (userdocElement.Descendants().Any())
                    {
                        LogLine("Warning: the userdoc of member {0} has descendant nodes, which is not supported.", key);
                        break;
                    }
                    userdoc = userdocElement.Value;
                    userdoc = userdoc.Replace('\t', ' ').Replace('\r', ' ').Replace('\n', ' ').Trim();
                    // Removes double space.
                    var regex = new Regex(@"[ ]{2,}", RegexOptions.None);
                    userdoc = regex.Replace(userdoc, @" ");
                }
                if (userdoc != null)
                {
                    result.Add(key, userdoc);
                }
            }

            using (var writer = new StreamWriter(targetFile))
            {
                foreach (var entry in result)
                {
                    writer.WriteLine("{0}={1}", entry.Key, entry.Value);
                }
            }

            return true;
        }
コード例 #11
0
        public bool Process(AssemblyProcessorContext context)
        {
            if (SourceCodes.Count == 0)
                return false;

            // Generate serialization assembly
            var serializationAssemblyFilepath = RoslynCodeMerger.GenerateRolsynAssemblyLocation(context.Assembly.MainModule.FullyQualifiedName);
            context.Assembly = RoslynCodeMerger.GenerateRoslynAssembly(context.AssemblyResolver, context.Assembly, serializationAssemblyFilepath, SignKeyFile, References, MemoryReferences, Log, SourceCodes);

            return true;
        }
コード例 #12
0
        public bool Process(AssemblyProcessorContext context)
        {
            if (SourceCodes.Count == 0)
            {
                return(false);
            }

            // Generate serialization assembly
            var serializationAssemblyFilepath = RoslynCodeMerger.GenerateRolsynAssemblyLocation(context.Assembly.MainModule.FullyQualifiedName);

            context.Assembly = RoslynCodeMerger.GenerateRoslynAssembly(context.AssemblyResolver, context.Assembly, serializationAssemblyFilepath, SignKeyFile, References, MemoryReferences, Log, SourceCodes);

            return(true);
        }
コード例 #13
0
        public bool Process(AssemblyProcessorContext context)
        {
            var assembly         = context.Assembly;
            var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assembly);

            if (mscorlibAssembly == null)
            {
                throw new InvalidOperationException("Missing mscorlib.dll from assembly");
            }


            // Resolve mscorlib types
            var assemblyFileVersionAttributeType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(AssemblyFileVersionAttribute).FullName);
            var assemblyMethodConstructor        = assembly.MainModule.ImportReference(assemblyFileVersionAttributeType.Methods.FirstOrDefault(method => method.IsConstructor && method.Parameters.Count == 1));
            var stringType = assembly.MainModule.TypeSystem.String;

            // TODO: Git Commit SHA
            var gitCommitShortId = "0";

            // Use epoch time to get a "unique" build number (different each time)
            var build = (long)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds;

            // Get current AssemblyVersion and clone it
            var version     = assembly.Name.Version;
            var fileVersion = string.Format("{0}.{1}.{2}.{3}", version.Major, version.Minor, build, gitCommitShortId);

            // Copy build/revision to the AssemblyFileVersion
            bool fileVersionUpdated = false;

            for (int i = 0; i < assembly.CustomAttributes.Count; i++)
            {
                var customAttribute = assembly.CustomAttributes[i];
                if (customAttribute.AttributeType.FullName == typeof(AssemblyFileVersionAttribute).FullName)
                {
                    customAttribute.ConstructorArguments.Clear();
                    customAttribute.ConstructorArguments.Add(new CustomAttributeArgument(stringType, fileVersion));
                    fileVersionUpdated = true;
                    break;
                }
            }

            if (!fileVersionUpdated)
            {
                var assemblyFileVersion = new CustomAttribute(assemblyMethodConstructor);
                assemblyFileVersion.ConstructorArguments.Add(new CustomAttributeArgument(stringType, fileVersion));
                assembly.CustomAttributes.Add(assemblyFileVersion);
            }

            return(true);
        }
コード例 #14
0
        public bool Process(AssemblyProcessorContext context)
        {
            var assembly           = context.Assembly;
            var moduleInitializers = new List <KeyValuePair <int, MethodReference> >();

            // Generate a module initializer for all types, including nested types
            foreach (var type in assembly.EnumerateTypes())
            {
                foreach (var method in type.Methods)
                {
                    var moduleInitializerAttribute = method.CustomAttributes.FirstOrDefault(x => x.AttributeType.FullName == "SiliconStudio.Core.ModuleInitializerAttribute");
                    if (moduleInitializerAttribute != null)
                    {
                        var order = moduleInitializerAttribute.HasConstructorArguments ? (int)moduleInitializerAttribute.ConstructorArguments[0].Value : 0;
                        moduleInitializers.Add(new KeyValuePair <int, MethodReference>(order, method));
                    }
                }
            }

            if (moduleInitializers.Count == 0)
            {
                return(false);
            }

            // Sort by Order property
            moduleInitializers = moduleInitializers.OrderBy(x => x.Key).ToList();

            // Get or create module static constructor
            Instruction returnInstruction;
            var         staticConstructor = OpenModuleConstructor(assembly, out returnInstruction);

            var il = staticConstructor.Body.GetILProcessor();

            var newReturnInstruction = Instruction.Create(returnInstruction.OpCode);

            newReturnInstruction.Operand = returnInstruction.Operand;

            returnInstruction.OpCode  = OpCodes.Nop;
            returnInstruction.Operand = null;

            staticConstructor.Body.SimplifyMacros();
            foreach (var moduleInitializer in moduleInitializers)
            {
                il.Append(Instruction.Create(OpCodes.Call, moduleInitializer.Value));
            }
            il.Append(newReturnInstruction);
            staticConstructor.Body.OptimizeMacros();

            return(true);
        }
コード例 #15
0
        public bool Process(AssemblyProcessorContext context)
        {
            this.assembly = context.Assembly;
            asyncBridgeAssembly = context.AssemblyResolver.Resolve("AsyncBridge");

            assembly.MainModule.AssemblyReferences.Add(asyncBridgeAssembly.Name);

            foreach (var type in assembly.MainModule.Types)
            {
                ProcessType(type);
            }

            return true;
        }
コード例 #16
0
        public bool Process(AssemblyProcessorContext context)
        {
            this.assembly       = context.Assembly;
            asyncBridgeAssembly = context.AssemblyResolver.Resolve("AsyncBridge");

            assembly.MainModule.AssemblyReferences.Add(asyncBridgeAssembly.Name);

            foreach (var type in assembly.MainModule.Types)
            {
                ProcessType(type);
            }

            return(true);
        }
コード例 #17
0
ファイル: DispatcherProcessor.cs プロジェクト: vol16bit/xenko
        private void EnsureInitialized(AssemblyProcessorContext context)
        {
            if (isInitialized)
            {
                return;
            }

            var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(context.Assembly);

            siliconStudioCoreAssembly = context.Assembly.Name.Name == "SiliconStudio.Core" ? context.Assembly :
                                        context.AssemblyResolver.Resolve(new AssemblyNameReference("SiliconStudio.Core", null));

            pooledClosureType = context.Assembly.MainModule.ImportReference(siliconStudioCoreAssembly.MainModule.GetType("SiliconStudio.Core.Threading.IPooledClosure"));

            // Func type and it's contructor
            var funcType = mscorlibAssembly.MainModule.GetTypeResolved("System.Func`1");

            funcConstructor = context.Assembly.MainModule.ImportReference(funcType.Methods.FirstOrDefault(x => x.Name == ".ctor"));

            // Pool type and it's constructor
            var poolTypeDefinition = siliconStudioCoreAssembly.MainModule.GetType("SiliconStudio.Core.Threading.ConcurrentPool`1");

            poolType          = context.Assembly.MainModule.ImportReference(poolTypeDefinition);
            poolConstructor   = context.Assembly.MainModule.ImportReference(poolTypeDefinition.Methods.FirstOrDefault(x => x.Name == ".ctor"));
            poolAcquireMethod = context.Assembly.MainModule.ImportReference(poolTypeDefinition.Methods.FirstOrDefault(x => x.Name == "Acquire"));
            poolReleaseMethod = context.Assembly.MainModule.ImportReference(poolTypeDefinition.Methods.FirstOrDefault(x => x.Name == "Release"));

            // Interlocked (either from mscorlib.dll or System.Threading.dll)
            var interlockedTypeDefinition = mscorlibAssembly.MainModule.GetTypeResolved("System.Threading.Interlocked");

            if (interlockedTypeDefinition == null)
            {
                var threadingAssembly = context.AssemblyResolver.Resolve(new AssemblyNameReference("System.Threading", null));
                interlockedTypeDefinition = threadingAssembly.MainModule.GetTypeResolved("System.Threading.Interlocked");
            }
            var interlockedType = context.Assembly.MainModule.ImportReference(interlockedTypeDefinition);

            // NOTE: We create method references manually, because ImportReference imports a different version of the runtime, causing
            interlockedIncrementMethod = new MethodReference("Increment", context.Assembly.MainModule.TypeSystem.Int32, interlockedType);
            interlockedIncrementMethod.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, context.Assembly.MainModule.TypeSystem.Int32.MakeByReferenceType()));
            //interlockedIncrementMethod = context.Assembly.MainModule.ImportReference(interlockedType.Methods.FirstOrDefault(x => x.Name == "Increment" && x.ReturnType.MetadataType == MetadataType.Int32));

            interlockedDecrementMethod = new MethodReference("Decrement", context.Assembly.MainModule.TypeSystem.Int32, interlockedType);
            interlockedDecrementMethod.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, context.Assembly.MainModule.TypeSystem.Int32.MakeByReferenceType()));
            //interlockedDecrementMethod = context.Assembly.MainModule.ImportReference(interlockedType.Methods.FirstOrDefault(x => x.Name == "Decrement" && x.ReturnType.MetadataType == MetadataType.Int32));

            isInitialized = true;
        }
コード例 #18
0
        public bool Process(AssemblyProcessorContext context)
        {
            this.assembly = context.Assembly;
            // Import void* and int32 from assembly using mscorlib specific version (2.0 or 4.0 depending on assembly)
            voidPointerType = new PointerType(assembly.MainModule.TypeSystem.Void);
            intType = assembly.MainModule.TypeSystem.Int32;

            context.Log.WriteLine($"Patch for assembly [{assembly.FullName}]");
            foreach (var type in assembly.MainModule.Types)
                PatchType(type);

            // Remove All Interop classes
            foreach (var type in classToRemoveList)
                assembly.MainModule.Types.Remove(type);

            return true;
        }
コード例 #19
0
        public bool Process(AssemblyProcessorContext context)
        {
            var assembly = context.Assembly;
            var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assembly);
            if (mscorlibAssembly == null)
                throw new InvalidOperationException("Missing mscorlib.dll from assembly");


            // Resolve mscorlib types
            var assemblyFileVersionAttributeType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(AssemblyFileVersionAttribute).FullName);
            var assemblyMethodConstructor = assembly.MainModule.ImportReference(assemblyFileVersionAttributeType.Methods.FirstOrDefault(method => method.IsConstructor && method.Parameters.Count == 1));
            var stringType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(string).FullName);

            // TODO: Git Commit SHA
            var gitCommitShortId = "0";

            // Use epoch time to get a "unique" build number (different each time)
            var build = (long)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds;

            // Get current AssemblyVersion and clone it
            var version = assembly.Name.Version;
            var fileVersion = string.Format("{0}.{1}.{2}.{3}", version.Major, version.Minor, build, gitCommitShortId);

            // Copy build/revision to the AssemblyFileVersion
            bool fileVersionUpdated = false;
            for (int i = 0; i < assembly.CustomAttributes.Count; i++)
            {
                var customAttribute = assembly.CustomAttributes[i];
                if (customAttribute.AttributeType.FullName == typeof(AssemblyFileVersionAttribute).FullName)
                {
                    customAttribute.ConstructorArguments.Clear();
                    customAttribute.ConstructorArguments.Add(new CustomAttributeArgument(stringType, fileVersion));
                    fileVersionUpdated = true;
                    break;
                }
            }

            if (!fileVersionUpdated)
            {
                var assemblyFileVersion = new CustomAttribute(assemblyMethodConstructor);
                assemblyFileVersion.ConstructorArguments.Add(new CustomAttributeArgument(stringType, fileVersion));
                assembly.CustomAttributes.Add(assemblyFileVersion);
            }

            return true;
        }
コード例 #20
0
        public bool Process(AssemblyProcessorContext context)
        {
            var assembly           = context.Assembly;
            var moduleInitializers = new List <MethodReference>();

            // Generate a module initializer for all types, including nested types
            foreach (var type in assembly.EnumerateTypes())
            {
                foreach (var method in type.Methods)
                {
                    if (method.CustomAttributes.Any(x => x.AttributeType.FullName == "SiliconStudio.Core.ModuleInitializerAttribute"))
                    {
                        moduleInitializers.Add(method);
                    }
                }
            }

            if (moduleInitializers.Count == 0)
            {
                return(false);
            }

            // Get or create module static constructor
            Instruction returnInstruction;
            var         staticConstructor = OpenModuleConstructor(assembly, out returnInstruction);

            var il = staticConstructor.Body.GetILProcessor();

            var newReturnInstruction = Instruction.Create(returnInstruction.OpCode);

            newReturnInstruction.Operand = returnInstruction.Operand;

            returnInstruction.OpCode  = OpCodes.Nop;
            returnInstruction.Operand = null;

            staticConstructor.Body.SimplifyMacros();
            foreach (var moduleInitializer in moduleInitializers)
            {
                il.Append(Instruction.Create(OpCodes.Call, moduleInitializer));
            }
            il.Append(newReturnInstruction);
            staticConstructor.Body.OptimizeMacros();

            return(true);
        }
コード例 #21
0
        public bool Process(AssemblyProcessorContext context)
        {
            this.assembly    = context.Assembly;
            mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assembly);

            if (mscorlibAssembly == null)
            {
                LogError("Missing mscorlib.dll from assembly {0}", assembly.FullName);
                throw new InvalidOperationException("Missing mscorlib.dll from assembly");
            }

            // Import void* and int32 from assembly using mscorlib specific version (2.0 or 4.0 depending on assembly)
            voidType        = mscorlibAssembly.MainModule.GetTypeResolved("System.Void");
            voidPointerType = new PointerType(assembly.MainModule.Import(voidType));
            intType         = assembly.MainModule.Import(mscorlibAssembly.MainModule.GetTypeResolved("System.Int32"));

            // Remove CompilationRelaxationsAttribute
            if (context.Platform == PlatformType.WindowsStore || context.Platform == PlatformType.WindowsPhone)
            {
                for (int i = 0; i < assembly.CustomAttributes.Count; i++)
                {
                    var customAttribute = assembly.CustomAttributes[i];
                    if (customAttribute.AttributeType.FullName == typeof(CompilationRelaxationsAttribute).FullName)
                    {
                        assembly.CustomAttributes.RemoveAt(i);
                        i--;
                    }
                }
            }

            Log("Patch for assembly [{0}]", assembly.FullName);
            foreach (var type in assembly.MainModule.Types)
            {
                PatchType(type);
            }

            // Remove All Interop classes
            foreach (var type in classToRemoveList)
            {
                assembly.MainModule.Types.Remove(type);
            }

            return(true);
        }
コード例 #22
0
        public bool Process(AssemblyProcessorContext context)
        {
            var assembly = context.Assembly;

            // Only process if there is a public key
            if (!assembly.Name.HasPublicKey)
                return false;

            // Check if already strong signed
            if ((assembly.MainModule.Attributes & ModuleAttributes.StrongNameSigned) == ModuleAttributes.StrongNameSigned)
                return false;

            // We have a delay signed assembly that is not strong name signed yet.
            // Let's strong sign it now (a.k.a. OSS, OpenSourceSign)
            // Note: Maybe we should make sure it's actually Paradox key?
            assembly.MainModule.Attributes |= ModuleAttributes.StrongNameSigned;

            return true;
        }
コード例 #23
0
        private void EnsureInitialized(AssemblyProcessorContext context)
        {
            if (isInitialized)
                return;

            var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(context.Assembly);

            siliconStudioCoreAssembly = context.Assembly.Name.Name == "SiliconStudio.Core" ? context.Assembly :
                context.AssemblyResolver.Resolve("SiliconStudio.Core");

            pooledClosureType = context.Assembly.MainModule.ImportReference(siliconStudioCoreAssembly.MainModule.GetType("SiliconStudio.Core.Threading.IPooledClosure"));

            // Func type and it's contructor
            var funcType = mscorlibAssembly.MainModule.GetTypeResolved("System.Func`1");
            funcConstructor = context.Assembly.MainModule.ImportReference(funcType.Methods.FirstOrDefault(x => x.Name == ".ctor"));

            // Pool type and it's constructor
            var poolTypeDefinition = siliconStudioCoreAssembly.MainModule.GetType("SiliconStudio.Core.Threading.ConcurrentPool`1");
            poolType = context.Assembly.MainModule.ImportReference(poolTypeDefinition);
            poolConstructor = context.Assembly.MainModule.ImportReference(poolTypeDefinition.Methods.FirstOrDefault(x => x.Name == ".ctor"));
            poolAcquireMethod = context.Assembly.MainModule.ImportReference(poolTypeDefinition.Methods.FirstOrDefault(x => x.Name == "Acquire"));
            poolReleaseMethod = context.Assembly.MainModule.ImportReference(poolTypeDefinition.Methods.FirstOrDefault(x => x.Name == "Release"));

            // Interlocked (either from mscorlib.dll or System.Threading.dll)
            var interlockedTypeDefinition = mscorlibAssembly.MainModule.GetTypeResolved("System.Threading.Interlocked");
            if (interlockedTypeDefinition == null)
            {
                var threadingAssembly = context.AssemblyResolver.Resolve("System.Threading");
                interlockedTypeDefinition = threadingAssembly.MainModule.GetTypeResolved("System.Threading.Interlocked");
            }
            var interlockedType = context.Assembly.MainModule.ImportReference(interlockedTypeDefinition);

            // NOTE: We create method references manually, because ImportReference imports a different version of the runtime, causing  
            interlockedIncrementMethod = new MethodReference("Increment", context.Assembly.MainModule.TypeSystem.Int32, interlockedType);
            interlockedIncrementMethod.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, context.Assembly.MainModule.TypeSystem.Int32.MakeByReferenceType()));
            //interlockedIncrementMethod = context.Assembly.MainModule.ImportReference(interlockedType.Methods.FirstOrDefault(x => x.Name == "Increment" && x.ReturnType.MetadataType == MetadataType.Int32));

            interlockedDecrementMethod = new MethodReference("Decrement", context.Assembly.MainModule.TypeSystem.Int32, interlockedType);
            interlockedDecrementMethod.Parameters.Add(new ParameterDefinition("", ParameterAttributes.None, context.Assembly.MainModule.TypeSystem.Int32.MakeByReferenceType()));
            //interlockedDecrementMethod = context.Assembly.MainModule.ImportReference(interlockedType.Methods.FirstOrDefault(x => x.Name == "Decrement" && x.ReturnType.MetadataType == MetadataType.Int32));

            isInitialized = true;
        }
コード例 #24
0
        public bool Process(AssemblyProcessorContext context)
        {
            var assembly = context.Assembly;
            var moduleInitializers = new List<MethodReference>();

            // Generate a module initializer for all types, including nested types
            foreach (var type in assembly.EnumerateTypes())
            {
                foreach (var method in type.Methods)
                {
                    if (method.CustomAttributes.Any(x => x.AttributeType.FullName == "SiliconStudio.Core.ModuleInitializerAttribute"))
                    {
                        moduleInitializers.Add(method);
                    }
                }
            }

            if (moduleInitializers.Count == 0)
                return false;

            // Get or create module static constructor
            Instruction returnInstruction;
            var staticConstructor = OpenModuleConstructor(assembly, out returnInstruction);

            var il = staticConstructor.Body.GetILProcessor();
            
            var newReturnInstruction = Instruction.Create(returnInstruction.OpCode);
            newReturnInstruction.Operand = returnInstruction.Operand;

            returnInstruction.OpCode = OpCodes.Nop;
            returnInstruction.Operand = null;

            staticConstructor.Body.SimplifyMacros();
            foreach (var moduleInitializer in moduleInitializers)
            {
                il.Append(Instruction.Create(OpCodes.Call, moduleInitializer));
            }
            il.Append(newReturnInstruction);
            staticConstructor.Body.OptimizeMacros();

            return true;
        }
コード例 #25
0
ファイル: InteropProcessor.cs プロジェクト: vol16bit/xenko
        public bool Process(AssemblyProcessorContext context)
        {
            this.assembly = context.Assembly;
            // Import void* and int32 from assembly using mscorlib specific version (2.0 or 4.0 depending on assembly)
            voidPointerType = new PointerType(assembly.MainModule.TypeSystem.Void);
            intType         = assembly.MainModule.TypeSystem.Int32;

            context.Log.WriteLine($"Patch for assembly [{assembly.FullName}]");
            foreach (var type in assembly.MainModule.Types)
            {
                PatchType(type);
            }

            // Remove All Interop classes
            foreach (var type in classToRemoveList)
            {
                assembly.MainModule.Types.Remove(type);
            }

            return(true);
        }
コード例 #26
0
        public bool Process(AssemblyProcessorContext context)
        {
            this.assembly = context.Assembly;
            mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assembly);

            if (mscorlibAssembly == null)
            {
                LogError("Missing mscorlib.dll from assembly {0}", assembly.FullName);
                throw new InvalidOperationException("Missing mscorlib.dll from assembly");
            }

            // Import void* and int32 from assembly using mscorlib specific version (2.0 or 4.0 depending on assembly)
            voidType = mscorlibAssembly.MainModule.GetTypeResolved("System.Void");
            voidPointerType = new PointerType(assembly.MainModule.Import(voidType));
            intType = assembly.MainModule.Import(mscorlibAssembly.MainModule.GetTypeResolved("System.Int32"));

            // Remove CompilationRelaxationsAttribute
            if (context.Platform == PlatformType.WindowsStore || context.Platform == PlatformType.WindowsPhone)
            {
                for (int i = 0; i < assembly.CustomAttributes.Count; i++)
                {
                    var customAttribute = assembly.CustomAttributes[i];
                    if (customAttribute.AttributeType.FullName == typeof(CompilationRelaxationsAttribute).FullName)
                    {
                        assembly.CustomAttributes.RemoveAt(i);
                        i--;
                    }
                }
            }

            Log("Patch for assembly [{0}]", assembly.FullName);
            foreach (var type in assembly.MainModule.Types)
                PatchType(type);

            // Remove All Interop classes
            foreach (var type in classToRemoveList)
                assembly.MainModule.Types.Remove(type);

            return true;
        }
コード例 #27
0
        public bool Process(AssemblyProcessorContext context)
        {
            bool changed = false;
            foreach (var type in context.Assembly.EnumerateTypes())
            {
                foreach (var method in type.Methods)
                {
                    if (method.CustomAttributes.Any(x => x.AttributeType.FullName == "SiliconStudio.Core.IL.RemoveInitLocalsAttribute"))
                    {
                        if (method.Body == null)
                        {
                            throw new InvalidOperationException($"Trying to remove initlocals from method {method.FullName} without body.");
                        }

                        method.Body.InitLocals = false;
                        changed = true;
                    }
                }
            }

            return changed;
        }
コード例 #28
0
ファイル: InitLocalsProcessor.cs プロジェクト: vol16bit/xenko
        public bool Process(AssemblyProcessorContext context)
        {
            bool changed = false;

            foreach (var type in context.Assembly.MainModule.GetAllTypes())
            {
                foreach (var method in type.Methods)
                {
                    if (method.CustomAttributes.Any(x => x.AttributeType.FullName == "SiliconStudio.Core.IL.RemoveInitLocalsAttribute"))
                    {
                        if (method.Body == null)
                        {
                            throw new InvalidOperationException($"Trying to remove initlocals from method {method.FullName} without body.");
                        }

                        method.Body.InitLocals = false;
                        changed = true;
                    }
                }
            }

            return(changed);
        }
コード例 #29
0
        public bool Process(AssemblyProcessorContext context)
        {
            var assembly = context.Assembly;

            // Only process if there is a public key
            if (!assembly.Name.HasPublicKey)
            {
                return(false);
            }

            // Check if already strong signed
            if ((assembly.MainModule.Attributes & ModuleAttributes.StrongNameSigned) == ModuleAttributes.StrongNameSigned)
            {
                return(false);
            }

            // We have a delay signed assembly that is not strong name signed yet.
            // Let's strong sign it now (a.k.a. OSS, OpenSourceSign)
            // Note: Maybe we should make sure it's actually Xenko key?
            assembly.MainModule.Attributes |= ModuleAttributes.StrongNameSigned;

            return(true);
        }
コード例 #30
0
ファイル: DispatcherProcessor.cs プロジェクト: vol16bit/xenko
        private MethodReference ChangeGenericArguments(AssemblyProcessorContext context, MethodReference method, TypeReference relativeType)
        {
            var genericInstance = method as GenericInstanceMethod;

            if (genericInstance == null)
            {
                return(method.Resolve().MakeGeneric(relativeType.Resolve().GenericParameters.ToArray()));
            }

            Debugger.Launch();

            var genericArguments = new List <TypeReference>();

            foreach (var genericArgument in genericInstance.GenericArguments)
            {
                if (genericArgument.IsGenericParameter)
                {
                    var genericParameter = GetGenericParameterForArgument(relativeType, genericArgument);
                    if (genericParameter != null)
                    {
                        genericArguments.Add(genericParameter);
                    }
                }
                else
                {
                    var newGenericArgument = ChangeGenericArguments(context, genericArgument, relativeType);
                    genericArguments.Add(newGenericArgument);
                }
            }

            if (genericArguments.Count != genericInstance.GenericArguments.Count)
            {
                throw new InvalidOperationException("Could not resolve generic arguments");
            }

            return(context.Assembly.MainModule.ImportReference(genericInstance.Resolve()).MakeGeneric(genericArguments.ToArray()));
        }
コード例 #31
0
        public bool Process(AssemblyProcessorContext context)
        {
            var assemblyScanCodeGenerator = new AssemblyScanCodeGenerator(context.Assembly);

            foreach (var type in context.Assembly.MainModule.GetAllTypes())
            {
                // Ignore interface types as well as types with generics
                // Note: we could support generic types at some point but we probably need
                //       to get static generic instantiation type list from serializer code generator
                if (type.IsInterface || type.HasGenericParameters)
                {
                    continue;
                }

                var currentType = type;
                // Scan type and parent types
                while (currentType != null)
                {
                    // Scan interfaces
                    foreach (var @interface in currentType.Interfaces)
                    {
                        ScanAttributes(context.Log, assemblyScanCodeGenerator, @interface.InterfaceType, type);
                    }

                    ScanAttributes(context.Log, assemblyScanCodeGenerator, currentType, type);
                    currentType = currentType.BaseType?.Resolve();
                }
            }

            if (assemblyScanCodeGenerator.HasScanTypes)
            {
                // Generate code
                sourceCodeRegisterAction(assemblyScanCodeGenerator.TransformText(), "AssemblyScan");
            }

            return(assemblyScanCodeGenerator.HasScanTypes);
        }
コード例 #32
0
        public bool Process(AssemblyProcessorContext context)
        {
            var basePath   = Path.Combine(Path.GetDirectoryName(inputFile) ?? "", Path.GetFileNameWithoutExtension(inputFile) ?? "");
            var xmlFile    = basePath + ".xml";
            var targetFile = basePath + ".usrdoc";

            // No xml documentation file available, stop here.
            if (!File.Exists(xmlFile))
            {
                return(false);
            }

            var result = new Dictionary <string, string>();

            var document = XElement.Load(xmlFile);

            foreach (var member in document.Descendants("member"))
            {
                var nameAttribute = member.Attribute("name");
                if (nameAttribute == null)
                {
                    continue;
                }


                foreach (var userdocElement in member.Descendants("userdoc"))
                {
                    string userdoc = null;
                    var    key     = nameAttribute.Value;

                    var docOverride = userdocElement.Attribute("override");
                    if (docOverride != null && key.StartsWith("T"))             // if on top of the class we have some overrides we must process them now
                    {
                        key = "P" + key.Substring(1) + "." + docOverride.Value; //replace T with M
                    }

                    if (result.ContainsKey(key))
                    {
                        context.Log.WriteLine($"Warning: the member {key} has multiple userdoc, only the first one will be used.");
                        continue;
                    }
                    if (userdocElement.Descendants().Any())
                    {
                        context.Log.WriteLine($"Warning: the userdoc of member {key} has descendant nodes, which is not supported.");
                        continue;
                    }

                    userdoc = userdocElement.Value;
                    userdoc = userdoc.Replace('\t', ' ').Replace('\r', ' ').Replace('\n', ' ').Trim();
                    // Removes double space.
                    var regex = new Regex(@"[ ]{2,}", RegexOptions.None);
                    userdoc = regex.Replace(userdoc, @" ");

                    result.Add(key, userdoc);
                }
            }

            using (var writer = new StreamWriter(targetFile))
            {
                foreach (var entry in result)
                {
                    writer.WriteLine("{0}={1}", entry.Key, entry.Value);
                }
            }

            return(true);
        }
コード例 #33
0
        public bool Process(AssemblyProcessorContext context)
        {
            var basePath = Path.Combine(Path.GetDirectoryName(inputFile) ?? "", Path.GetFileNameWithoutExtension(inputFile) ?? "");
            var xmlFile = basePath + ".xml";
            var targetFile = basePath + ".usrdoc";

            // No xml documentation file available, stop here.
            if (!File.Exists(xmlFile))
                return false;

            var result = new Dictionary<string, string>();

            var document = XElement.Load(xmlFile);
            foreach (var member in document.Descendants("member"))
            {
                var nameAttribute = member.Attribute("name");
                if (nameAttribute == null)
                    continue;
                
            
                foreach (var userdocElement in member.Descendants("userdoc"))
                {
                    string userdoc = null;
                    var key = nameAttribute.Value;

                    var docOverride = userdocElement.Attribute("override");
                    if (docOverride != null && key.StartsWith("T")) // if on top of the class we have some overrides we must process them now
                    {
                        key = "P" + key.Substring(1) + "." + docOverride.Value; //replace T with M
                    }

                    if (result.ContainsKey(key))
                    {
                        context.Log.WriteLine($"Warning: the member {key} has multiple userdoc, only the first one will be used.");
                        continue;
                    }
                    if (userdocElement.Descendants().Any())
                    {
                        context.Log.WriteLine($"Warning: the userdoc of member {key} has descendant nodes, which is not supported.");
                        continue;
                    }

                    userdoc = userdocElement.Value;
                    userdoc = userdoc.Replace('\t', ' ').Replace('\r', ' ').Replace('\n', ' ').Trim();
                    // Removes double space.
                    var regex = new Regex(@"[ ]{2,}", RegexOptions.None);
                    userdoc = regex.Replace(userdoc, @" ");

                    result.Add(key, userdoc);
                }
            }

            using (var writer = new StreamWriter(targetFile))
            {
                foreach (var entry in result)
                {
                    writer.WriteLine("{0}={1}", entry.Key, entry.Value);
                }
            }

            return true;
        }
コード例 #34
0
ファイル: AssemblyProcessorApp.cs プロジェクト: rohitshe/Code
        public bool Run(ref AssemblyDefinition assemblyDefinition, ref bool readWriteSymbols, out bool modified)
        {
            modified = false;

            try
            {
                var assemblyResolver = (CustomAssemblyResolver)assemblyDefinition.MainModule.AssemblyResolver;

                // Register self
                assemblyResolver.Register(assemblyDefinition);

                var processors = new List <IAssemblyDefinitionProcessor>();

                // We are no longer using it so we are deactivating it for now to avoid processing
                //if (AutoNotifyProperty)
                //{
                //    processors.Add(new NotifyPropertyProcessor());
                //}

                processors.Add(new AddReferenceProcessor(ReferencesToAdd));

                if (ParameterKey)
                {
                    processors.Add(new ParameterKeyProcessor());
                }

                if (NewAssemblyName != null)
                {
                    processors.Add(new RenameAssemblyProcessor(NewAssemblyName));
                }

                //processors.Add(new AsyncBridgeProcessor());

                // Always applies the interop processor
                processors.Add(new InteropProcessor());

                processors.Add(new AssemblyVersionProcessor());

                if (DocumentationFile != null)
                {
                    processors.Add(new GenerateUserDocumentationProcessor(DocumentationFile));
                }

                var roslynExtraCodeProcessor = new RoslynExtraCodeProcessor(SignKeyFile, References, MemoryReferences, log);

                if (SerializationAssembly)
                {
                    processors.Add(new SerializationProcessor(roslynExtraCodeProcessor.SourceCodes.Add));
                }

                processors.Add(roslynExtraCodeProcessor);

                if (ModuleInitializer)
                {
                    processors.Add(new ModuleInitializerProcessor());
                }

                processors.Add(new InitLocalsProcessor());
                processors.Add(new OpenSourceSignProcessor());

                // Check if pdb was actually read
                readWriteSymbols = assemblyDefinition.MainModule.HasDebugHeader;

                // Check if there is already a AssemblyProcessedAttribute (in which case we can skip processing, it has already been done).
                // Note that we should probably also match the command line as well so that we throw an error if processing is different (need to rebuild).
                if (assemblyDefinition.CustomAttributes.Any(x => x.AttributeType.FullName == "SiliconStudio.Core.AssemblyProcessedAttribute"))
                {
                    OnInfoAction($"Assembly [{assemblyDefinition.Name}] has already been processed, skip it.");
                    return(true);
                }

                // Register references so that our assembly resolver can use them
                foreach (var reference in References)
                {
                    assemblyResolver.RegisterReference(reference);
                }

                if (SerializationAssembly)
                {
                    // Resave a first version of assembly with [InteralsVisibleTo] for future serialization assembly.
                    // It will be used by serialization assembly compilation.
                    // It's recommended to do it in the original code to avoid this extra step.

                    var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assemblyDefinition);
                    if (mscorlibAssembly == null)
                    {
                        OnErrorAction("Missing reference to mscorlib.dll or System.Runtime.dll in assembly!");
                        return(false);
                    }

                    var  internalsVisibleToAttribute    = mscorlibAssembly.MainModule.GetTypeResolved(typeof(InternalsVisibleToAttribute).FullName);
                    var  serializationAssemblyName      = assemblyDefinition.Name.Name + ".Serializers";
                    bool internalsVisibleAlreadyApplied = false;

                    // Check if already applied
                    foreach (var customAttribute in assemblyDefinition.CustomAttributes.Where(x => x.AttributeType.FullName == internalsVisibleToAttribute.FullName))
                    {
                        var assemblyName = (string)customAttribute.ConstructorArguments[0].Value;

                        int publicKeyIndex;
                        if ((publicKeyIndex = assemblyName.IndexOf(", PublicKey=", StringComparison.InvariantCulture)) != -1 || (publicKeyIndex = assemblyName.IndexOf(",PublicKey=", StringComparison.InvariantCulture)) != -1)
                        {
                            assemblyName = assemblyName.Substring(0, publicKeyIndex);
                        }

                        if (assemblyName == serializationAssemblyName)
                        {
                            internalsVisibleAlreadyApplied = true;
                            break;
                        }
                    }

                    if (!internalsVisibleAlreadyApplied)
                    {
                        // Apply public key
                        if (assemblyDefinition.Name.HasPublicKey)
                        {
                            serializationAssemblyName += ", PublicKey=" + ByteArrayToString(assemblyDefinition.Name.PublicKey);
                        }

                        // Add [InteralsVisibleTo] attribute
                        var internalsVisibleToAttributeCtor = assemblyDefinition.MainModule.ImportReference(internalsVisibleToAttribute.GetConstructors().Single());
                        var internalsVisibleAttribute       = new CustomAttribute(internalsVisibleToAttributeCtor)
                        {
                            ConstructorArguments =
                            {
                                new CustomAttributeArgument(assemblyDefinition.MainModule.TypeSystem.String, serializationAssemblyName)
                            }
                        };
                        assemblyDefinition.CustomAttributes.Add(internalsVisibleAttribute);

                        var assemblyFilePath = assemblyDefinition.MainModule.FullyQualifiedName;
                        if (string.IsNullOrEmpty(assemblyFilePath))
                        {
                            assemblyFilePath = Path.ChangeExtension(Path.GetTempFileName(), ".dll");
                        }

                        // Save updated file
                        assemblyDefinition.Write(assemblyFilePath, new WriterParameters()
                        {
                            WriteSymbols = readWriteSymbols
                        });

                        // Reread file (otherwise it seems Mono Cecil is buggy and generate invalid PDB)
                        assemblyDefinition = AssemblyDefinition.ReadAssembly(assemblyFilePath, new ReaderParameters {
                            AssemblyResolver = assemblyResolver, ReadSymbols = readWriteSymbols
                        });

                        // Check if pdb was actually read
                        readWriteSymbols = assemblyDefinition.MainModule.HasDebugHeader;
                    }
                }

                var assemblyProcessorContext = new AssemblyProcessorContext(assemblyResolver, assemblyDefinition, Platform, log);

                foreach (var processor in processors)
                {
                    modified = processor.Process(assemblyProcessorContext) || modified;
                }

                // Assembly might have been recreated (i.e. il-repack), so let's use it from now on
                assemblyDefinition = assemblyProcessorContext.Assembly;

                if (modified)
                {
                    // In case assembly has been modified,
                    // add AssemblyProcessedAttribute to assembly so that it doesn't get processed again
                    var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assemblyDefinition);
                    if (mscorlibAssembly == null)
                    {
                        OnErrorAction("Missing reference to mscorlib.dll or System.Runtime.dll in assembly!");
                        return(false);
                    }

                    var attributeType    = mscorlibAssembly.MainModule.GetTypeResolved(typeof(Attribute).FullName);
                    var attributeTypeRef = assemblyDefinition.MainModule.ImportReference(attributeType);
                    var attributeCtorRef = assemblyDefinition.MainModule.ImportReference(attributeType.GetConstructors().Single(x => x.Parameters.Count == 0));
                    var voidType         = assemblyDefinition.MainModule.TypeSystem.Void;

                    // Create custom attribute
                    var assemblyProcessedAttributeType = new TypeDefinition("SiliconStudio.Core", "AssemblyProcessedAttribute", TypeAttributes.BeforeFieldInit | TypeAttributes.AnsiClass | TypeAttributes.AutoClass | TypeAttributes.Public, attributeTypeRef);

                    // Add constructor (call parent constructor)
                    var assemblyProcessedAttributeConstructor = new MethodDefinition(".ctor", MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Public, voidType);
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Call, attributeCtorRef));
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
                    assemblyProcessedAttributeType.Methods.Add(assemblyProcessedAttributeConstructor);

                    // Add AssemblyProcessedAttribute to assembly
                    assemblyDefinition.MainModule.Types.Add(assemblyProcessedAttributeType);
                    assemblyDefinition.CustomAttributes.Add(new CustomAttribute(assemblyProcessedAttributeConstructor));
                }
            }
            catch (Exception e)
            {
                OnErrorAction(null, e);
                return(false);
            }

            return(true);
        }
コード例 #35
0
        public bool Process(AssemblyProcessorContext context)
        {
            var assembly = context.Assembly;
            var fields   = new List <FieldDefinition>();

            var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assembly);

            if (mscorlibAssembly == null)
            {
                throw new InvalidOperationException("Missing mscorlib.dll from assembly");
            }

            MethodDefinition parameterKeysMergeMethod        = null;
            TypeDefinition   assemblyEffectKeysAttributeType = null;
            var getTypeFromHandleMethod = new Lazy <MethodReference>(() =>
            {
                // Find Type.GetTypeFromHandle
                var typeType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(Type).FullName);
                return(assembly.MainModule.Import(typeType.Methods.First(x => x.Name == "GetTypeFromHandle")));
            });

            var effectKeysStaticConstructors = new List <MethodReference>();

            foreach (var type in assembly.MainModule.GetTypes())
            {
                fields.Clear();

                foreach (var field in type.Fields.Where(x => x.IsStatic))
                {
                    var fieldBaseType = field.FieldType;
                    while (fieldBaseType != null)
                    {
                        if (fieldBaseType.FullName == "SiliconStudio.Paradox.Effects.ParameterKey")
                        {
                            break;
                        }

                        var resolvedFieldBaseType = fieldBaseType.Resolve();
                        if (resolvedFieldBaseType == null)
                        {
                            fieldBaseType = null;
                            break;
                        }

                        fieldBaseType = resolvedFieldBaseType.BaseType;
                    }

                    if (fieldBaseType == null)
                    {
                        continue;
                    }

                    fields.Add(field);
                }

                if (fields.Count == 0)
                {
                    continue;
                }

                // ParameterKey present means we should have a static cctor.
                var cctor = type.GetStaticConstructor();
                if (cctor == null)
                {
                    continue;
                }

                // Load necessary SiliconStudio.Paradox methods/attributes
                if (parameterKeysMergeMethod == null)
                {
                    AssemblyDefinition paradoxEngineAssembly;
                    try
                    {
                        paradoxEngineAssembly = assembly.Name.Name == "SiliconStudio.Paradox"
                            ? assembly
                            : context.AssemblyResolver.Resolve("SiliconStudio.Paradox");
                    }
                    catch (Exception)
                    {
                        Console.WriteLine("Error, cannot find [SiliconStudio.Paradox] assembly for processing ParameterKeyProcessor");
                        // We can't generate an exception, so we are just returning. It means that SiliconStudio.Paradox has not been generated so far.
                        return(true);
                    }

                    var parameterKeysType = paradoxEngineAssembly.MainModule.GetTypes().First(x => x.Name == "ParameterKeys");
                    parameterKeysMergeMethod        = parameterKeysType.Methods.First(x => x.Name == "Merge");
                    assemblyEffectKeysAttributeType = paradoxEngineAssembly.MainModule.GetTypes().First(x => x.Name == "AssemblyEffectKeysAttribute");
                }

                var cctorIL           = cctor.Body.GetILProcessor();
                var cctorInstructions = cctor.Body.Instructions;

                var keyClassName = type.Name;
                if (keyClassName.EndsWith("Keys"))
                {
                    keyClassName = keyClassName.Substring(0, keyClassName.Length - 4);
                }

                keyClassName += '.';

                bool cctorModified = false;

                // Find field store instruction
                for (int i = 0; i < cctorInstructions.Count; ++i)
                {
                    var fieldInstruction = cctorInstructions[i];

                    if (fieldInstruction.OpCode == OpCodes.Stsfld &&
                        fields.Contains(fieldInstruction.Operand))
                    {
                        var activeField = (FieldReference)fieldInstruction.Operand;

                        var nextInstruction = cctorInstructions[i + 1];
                        cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Ldsfld, activeField));
                        cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Ldtoken, type));
                        cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Call, getTypeFromHandleMethod.Value));
                        cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Ldstr, keyClassName + activeField.Name));
                        cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Call, assembly.MainModule.Import(parameterKeysMergeMethod)));
                        cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Castclass, activeField.FieldType));
                        cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Stsfld, activeField));
                        i             = cctorInstructions.IndexOf(nextInstruction);
                        cctorModified = true;
                    }
                }

                if (cctorModified)
                {
                    effectKeysStaticConstructors.Add(cctor);
                }
            }

            if (effectKeysStaticConstructors.Count > 0)
            {
                // Add [AssemblyEffectKeysAttribute] to the assembly
                assembly.CustomAttributes.Add(new CustomAttribute(assembly.MainModule.Import(assemblyEffectKeysAttributeType.GetConstructors().First(x => !x.HasParameters))));

                // Get or create module static constructor
                var voidType          = assembly.MainModule.Import(mscorlibAssembly.MainModule.GetTypeResolved(typeof(void).FullName));
                var moduleClass       = assembly.MainModule.Types.First(t => t.Name == "<Module>");
                var staticConstructor = moduleClass.GetStaticConstructor();
                if (staticConstructor == null)
                {
                    staticConstructor = new MethodDefinition(".cctor",
                                                             MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                                                             voidType);
                    staticConstructor.Body.GetILProcessor().Append(Instruction.Create(OpCodes.Ret));

                    moduleClass.Methods.Add(staticConstructor);
                }

                var il = staticConstructor.Body.GetILProcessor();

                var returnInstruction    = staticConstructor.Body.Instructions.Last();
                var newReturnInstruction = Instruction.Create(returnInstruction.OpCode);
                newReturnInstruction.Operand = returnInstruction.Operand;

                returnInstruction.OpCode  = OpCodes.Nop;
                returnInstruction.Operand = null;

                var typeType            = mscorlibAssembly.MainModule.GetTypeResolved(typeof(Type).FullName);
                var typeHandleProperty  = typeType.Properties.First(x => x.Name == "TypeHandle");
                var getTypeHandleMethod = assembly.MainModule.Import(typeHandleProperty.GetMethod);

                var runtimeHelpersType        = mscorlibAssembly.MainModule.GetTypeResolved(typeof(RuntimeHelpers).FullName);
                var runClassConstructorMethod = assembly.MainModule.Import(runtimeHelpersType.Methods.Single(x => x.IsPublic && x.Name == "RunClassConstructor" && x.Parameters.Count == 1 && x.Parameters[0].ParameterType.FullName == typeof(RuntimeTypeHandle).FullName));

                // Call every key class static constructor from the module static constructor so that they are properly constructed (because accessing through reflection might cause problems)
                staticConstructor.Body.SimplifyMacros();
                foreach (var effectKeysStaticConstructor in effectKeysStaticConstructors)
                {
                    il.Append(Instruction.Create(OpCodes.Ldtoken, effectKeysStaticConstructor.DeclaringType));
                    il.Append(Instruction.Create(OpCodes.Call, getTypeFromHandleMethod.Value));
                    il.Append(Instruction.Create(OpCodes.Callvirt, getTypeHandleMethod));
                    il.Append(Instruction.Create(OpCodes.Call, runClassConstructorMethod));
                }
                il.Append(newReturnInstruction);
                staticConstructor.Body.OptimizeMacros();
            }

            return(true);
        }
コード例 #36
0
        public bool Run(ref AssemblyDefinition assemblyDefinition, ref bool readWriteSymbols, out bool modified)
        {
            modified = false;

            try
            {
                var assemblyResolver = (CustomAssemblyResolver)assemblyDefinition.MainModule.AssemblyResolver;

                var processors = new List <IAssemblyDefinitionProcessor>();

                // We are no longer using it so we are deactivating it for now to avoid processing
                //if (AutoNotifyProperty)
                //{
                //    processors.Add(new NotifyPropertyProcessor());
                //}

                if (ParameterKey)
                {
                    processors.Add(new ParameterKeyProcessor());
                }

                if (NewAssemblyName != null)
                {
                    processors.Add(new RenameAssemblyProcessor(NewAssemblyName));
                }

                //processors.Add(new AsyncBridgeProcessor());

                // Always applies the interop processor
                processors.Add(new InteropProcessor());

                processors.Add(new AssemblyVersionProcessor());

                if (SerializationAssembly)
                {
                    processors.Add(new SerializationProcessor(SignKeyFile, SerializationProjectReferences));
                }

                if (GenerateUserDocumentation)
                {
                    processors.Add(new GenerateUserDocumentationProcessor(assemblyDefinition.MainModule.FullyQualifiedName));
                }

                if (ModuleInitializer)
                {
                    processors.Add(new ModuleInitializerProcessor());
                }

                processors.Add(new OpenSourceSignProcessor());

                // Check if pdb was actually read
                readWriteSymbols = assemblyDefinition.MainModule.HasDebugHeader;

                // Check if there is already a AssemblyProcessedAttribute (in which case we can skip processing, it has already been done).
                // Note that we should probably also match the command line as well so that we throw an error if processing is different (need to rebuild).
                if (assemblyDefinition.CustomAttributes.Any(x => x.AttributeType.FullName == "SiliconStudio.Core.AssemblyProcessedAttribute"))
                {
                    OnInfoAction("Assembly has already been processed, skip it.");
                    return(true);
                }

                var targetFrameworkAttribute = assemblyDefinition.CustomAttributes
                                               .FirstOrDefault(x => x.AttributeType.FullName == typeof(TargetFrameworkAttribute).FullName);
                var targetFramework = targetFrameworkAttribute != null ? (string)targetFrameworkAttribute.ConstructorArguments[0].Value : null;

                // Special handling for MonoAndroid
                // Default frameworkFolder
                var frameworkFolder = Path.Combine(CecilExtensions.ProgramFilesx86(), @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\");

                switch (Platform)
                {
                case PlatformType.Android:
                {
                    if (string.IsNullOrEmpty(TargetFramework))
                    {
                        throw new InvalidOperationException("Expecting option target framework for Android");
                    }

                    var monoAndroidPath = Path.Combine(CecilExtensions.ProgramFilesx86(), @"Reference Assemblies\Microsoft\Framework\MonoAndroid");
                    frameworkFolder = Path.Combine(monoAndroidPath, "v1.0");
                    var additionalFrameworkFolder = Path.Combine(monoAndroidPath, TargetFramework);
                    assemblyResolver.AddSearchDirectory(additionalFrameworkFolder);
                    assemblyResolver.AddSearchDirectory(frameworkFolder);
                    break;
                }

                case PlatformType.iOS:
                {
                    if (string.IsNullOrEmpty(TargetFramework))
                    {
                        throw new InvalidOperationException("Expecting option target framework for iOS");
                    }

                    var monoAndroidPath = Path.Combine(CecilExtensions.ProgramFilesx86(), @"Reference Assemblies\Microsoft\Framework\MonoTouch");
                    frameworkFolder = Path.Combine(monoAndroidPath, "v1.0");
                    var additionalFrameworkFolder = Path.Combine(monoAndroidPath, TargetFramework);
                    assemblyResolver.AddSearchDirectory(additionalFrameworkFolder);
                    assemblyResolver.AddSearchDirectory(frameworkFolder);

                    break;
                }

                case PlatformType.WindowsStore:
                {
                    if (string.IsNullOrEmpty(TargetFramework))
                    {
                        throw new InvalidOperationException("Expecting option target framework for WindowsStore");
                    }

                    frameworkFolder = Path.Combine(CecilExtensions.ProgramFilesx86(), @"Reference Assemblies\Microsoft\Framework\.NETCore", TargetFramework);
                    assemblyResolver.AddSearchDirectory(frameworkFolder);

                    // Add path to look for WinRT assemblies (Windows.winmd)
                    var windowsAssemblyPath = Path.Combine(CecilExtensions.ProgramFilesx86(), @"Windows Kits\8.1\References\CommonConfiguration\Neutral\", "Windows.winmd");
                    var windowsAssembly     = AssemblyDefinition.ReadAssembly(windowsAssemblyPath, new ReaderParameters {
                            AssemblyResolver = assemblyResolver, ReadSymbols = false
                        });
                    assemblyResolver.Register(windowsAssembly);

                    break;
                }

                case PlatformType.WindowsPhone:
                {
                    if (string.IsNullOrEmpty(TargetFramework))
                    {
                        throw new InvalidOperationException("Expecting option target framework for WindowsPhone");
                    }

                    // Note: v8.1 is hardcoded because we currently receive v4.5.x as TargetFramework (different from TargetPlatformVersion)
                    frameworkFolder = Path.Combine(CecilExtensions.ProgramFilesx86(), @"Reference Assemblies\Microsoft\Framework\WindowsPhoneApp", "v8.1");
                    assemblyResolver.AddSearchDirectory(frameworkFolder);

                    // Add path to look for WinRT assemblies (Windows.winmd)
                    var windowsAssemblyPath = Path.Combine(CecilExtensions.ProgramFilesx86(), @"Windows Phone Kits\8.1\References\CommonConfiguration\Neutral\", "Windows.winmd");
                    var windowsAssembly     = AssemblyDefinition.ReadAssembly(windowsAssemblyPath, new ReaderParameters {
                            AssemblyResolver = assemblyResolver, ReadSymbols = false
                        });
                    assemblyResolver.Register(windowsAssembly);

                    break;
                }
                }

                if (SerializationAssembly)
                {
                    // Resave a first version of assembly with [InteralsVisibleTo] for future serialization assembly.
                    // It will be used by serialization assembly compilation.
                    // It's recommended to do it in the original code to avoid this extra step.

                    var  mscorlibAssembly               = CecilExtensions.FindCorlibAssembly(assemblyDefinition);
                    var  stringType                     = mscorlibAssembly.MainModule.GetTypeResolved(typeof(string).FullName);
                    var  internalsVisibleToAttribute    = mscorlibAssembly.MainModule.GetTypeResolved(typeof(InternalsVisibleToAttribute).FullName);
                    var  serializationAssemblyName      = assemblyDefinition.Name.Name + ".Serializers";
                    bool internalsVisibleAlreadyApplied = false;

                    // Check if already applied
                    foreach (var customAttribute in assemblyDefinition.CustomAttributes.Where(x => x.AttributeType.FullName == internalsVisibleToAttribute.FullName))
                    {
                        var assemblyName = (string)customAttribute.ConstructorArguments[0].Value;

                        int publicKeyIndex;
                        if ((publicKeyIndex = assemblyName.IndexOf(", PublicKey=", StringComparison.InvariantCulture)) != -1 || (publicKeyIndex = assemblyName.IndexOf(",PublicKey=", StringComparison.InvariantCulture)) != -1)
                        {
                            assemblyName = assemblyName.Substring(0, publicKeyIndex);
                        }

                        if (assemblyName == serializationAssemblyName)
                        {
                            internalsVisibleAlreadyApplied = true;
                            break;
                        }
                    }

                    if (!internalsVisibleAlreadyApplied)
                    {
                        // Apply public key
                        if (assemblyDefinition.Name.HasPublicKey)
                        {
                            serializationAssemblyName += ", PublicKey=" + ByteArrayToString(assemblyDefinition.Name.PublicKey);
                        }

                        // Add [InteralsVisibleTo] attribute
                        var internalsVisibleToAttributeCtor = assemblyDefinition.MainModule.Import(internalsVisibleToAttribute.GetConstructors().Single());
                        var internalsVisibleAttribute       = new CustomAttribute(internalsVisibleToAttributeCtor)
                        {
                            ConstructorArguments =
                            {
                                new CustomAttributeArgument(assemblyDefinition.MainModule.Import(stringType), serializationAssemblyName)
                            }
                        };
                        assemblyDefinition.CustomAttributes.Add(internalsVisibleAttribute);

                        var assemblyFilePath = assemblyDefinition.MainModule.FullyQualifiedName;
                        if (string.IsNullOrEmpty(assemblyFilePath))
                        {
                            assemblyFilePath = Path.ChangeExtension(Path.GetTempFileName(), ".dll");
                        }

                        // Save updated file
                        assemblyDefinition.Write(assemblyFilePath, new WriterParameters()
                        {
                            WriteSymbols = readWriteSymbols
                        });

                        // Reread file (otherwise it seems Mono Cecil is buggy and generate invalid PDB)
                        assemblyDefinition = AssemblyDefinition.ReadAssembly(assemblyFilePath, new ReaderParameters {
                            AssemblyResolver = assemblyResolver, ReadSymbols = readWriteSymbols
                        });

                        // Check if pdb was actually read
                        readWriteSymbols = assemblyDefinition.MainModule.HasDebugHeader;
                    }
                }

                var assemblyProcessorContext = new AssemblyProcessorContext(assemblyResolver, assemblyDefinition, Platform);

                foreach (var processor in processors)
                {
                    modified = processor.Process(assemblyProcessorContext) || modified;
                }

                // Assembly might have been recreated (i.e. il-repack), so let's use it from now on
                assemblyDefinition = assemblyProcessorContext.Assembly;

                if (modified)
                {
                    // In case assembly has been modified,
                    // add AssemblyProcessedAttribute to assembly so that it doesn't get processed again
                    var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assemblyDefinition);
                    if (mscorlibAssembly == null)
                    {
                        OnErrorAction("Missing mscorlib.dll from assembly");
                        return(false);
                    }

                    var attributeType    = mscorlibAssembly.MainModule.GetTypeResolved(typeof(Attribute).FullName);
                    var attributeTypeRef = assemblyDefinition.MainModule.Import(attributeType);
                    var attributeCtorRef = assemblyDefinition.MainModule.Import(attributeType.GetConstructors().Single(x => x.Parameters.Count == 0));
                    var voidType         = assemblyDefinition.MainModule.Import(mscorlibAssembly.MainModule.GetTypeResolved("System.Void"));

                    // Create custom attribute
                    var assemblyProcessedAttributeType = new TypeDefinition("SiliconStudio.Core", "AssemblyProcessedAttribute", TypeAttributes.BeforeFieldInit | TypeAttributes.AnsiClass | TypeAttributes.AutoClass | TypeAttributes.Public, attributeTypeRef);

                    // Add constructor (call parent constructor)
                    var assemblyProcessedAttributeConstructor = new MethodDefinition(".ctor", MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Public, voidType);
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Call, attributeCtorRef));
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
                    assemblyProcessedAttributeType.Methods.Add(assemblyProcessedAttributeConstructor);

                    // Add AssemblyProcessedAttribute to assembly
                    assemblyDefinition.MainModule.Types.Add(assemblyProcessedAttributeType);
                    assemblyDefinition.CustomAttributes.Add(new CustomAttribute(assemblyProcessedAttributeConstructor));
                }
            }
            catch (Exception e)
            {
                OnErrorAction(e.Message, e);
                return(false);
            }

            return(true);
        }
コード例 #37
0
ファイル: DispatcherProcessor.cs プロジェクト: vol16bit/xenko
        public bool Process(AssemblyProcessorContext context)
        {
            isInitialized = false;

            bool changed = false;

            foreach (var type in context.Assembly.MainModule.GetAllTypes().ToArray())
            {
                foreach (var method in type.Methods.ToArray())
                {
                    if (method.Body == null)
                    {
                        continue;
                    }

                    foreach (var instruction in method.Body.Instructions.ToArray())
                    {
                        if (instruction.OpCode != OpCodes.Call && instruction.OpCode != OpCodes.Callvirt)
                        {
                            continue;
                        }

                        var calledMethod = ((MethodReference)instruction.Operand).Resolve();
                        if (calledMethod == null)
                        {
                            continue;
                        }

                        for (int parameterIndex = 0; parameterIndex < calledMethod.Parameters.Count; parameterIndex++)
                        {
                            var parameter = calledMethod.Parameters[parameterIndex];

                            // Parameter must be decorated with PooledAttribute
                            if (parameter.CustomAttributes.All(x => x.AttributeType.FullName != "SiliconStudio.Core.Threading.PooledAttribute"))
                            {
                                continue;
                            }

                            // Parameter must be a delegate
                            if (parameter.ParameterType.Resolve().BaseType.FullName != typeof(MulticastDelegate).FullName)
                            {
                                continue;
                            }

                            // Find the instruction that pushes the parameter on the stack
                            // Non-trivial control flow is not supported
                            var pushParameterInstruction = WalkStack(instruction, calledMethod.Parameters.Count - parameterIndex);

                            // Try to replace delegate and closure allocations
                            {
                                EnsureInitialized(context);

                                changed |= ProcessDelegateAllocation(context, method, pushParameterInstruction);
                            }
                        }
                    }
                }
            }

            return(changed);
        }
コード例 #38
0
        private bool ProcessDelegateAllocation(AssemblyProcessorContext context, MethodDefinition method, Instruction delegateAllocationInstruction)
        {
            // The instruction must be a delegate allocation
            // If not, this might be a static delegate, or some unsupported construct
            if (delegateAllocationInstruction.OpCode != OpCodes.Newobj)
                return false;

            var delegateInstanceConstructor = (MethodReference)delegateAllocationInstruction.Operand;
            var delegateInstanceType = delegateInstanceConstructor.DeclaringType;

            // The previous instruction pushes the delegate method onto the stack
            var functionPointerInstruction = delegateAllocationInstruction.Previous;
            if (functionPointerInstruction.OpCode != OpCodes.Ldftn)
                return false;

            var delegateMethod = (MethodReference)functionPointerInstruction.Operand;

            // The previous instruction pushes the target onto the stack
            // If it's the this-parameter, we can create an instance field, and reuse the same delegate
            var loadClosureInstruction = functionPointerInstruction.Previous;
            if (loadClosureInstruction.OpCode == OpCodes.Ldarg_0 && !method.IsStatic)
            {
                // TODO: Handle generic methods/delegates
                // TODO: Handle multiple constructors propertly
                var constructor = method.DeclaringType.Methods.FirstOrDefault(x => x.Name == ".ctor" && !x.HasParameters);
                var retInstruction3 = constructor?.Body.Instructions.FirstOrDefault(x => x.OpCode == OpCodes.Ret);
                if (retInstruction3 == null)
                    return false;

                // Create an instance field for the shared delegate
                var sharedDelegateField = new FieldDefinition($"<delegate>{delegateMethod.Name}", FieldAttributes.Private, delegateInstanceType);
                method.DeclaringType.Fields.Add(sharedDelegateField);

                // Create and store the delegate in constructor
                var ilProcessor5 = constructor.Body.GetILProcessor();
                ilProcessor5.InsertBefore(retInstruction3, ilProcessor5.Create(OpCodes.Ldarg_0));
                ilProcessor5.InsertBefore(retInstruction3, ilProcessor5.Create(OpCodes.Ldarg_0));
                ilProcessor5.InsertBefore(retInstruction3, ilProcessor5.Create(OpCodes.Ldftn, delegateMethod));
                ilProcessor5.InsertBefore(retInstruction3, ilProcessor5.Create(OpCodes.Newobj, delegateInstanceConstructor));
                ilProcessor5.InsertBefore(retInstruction3, ilProcessor5.Create(OpCodes.Stfld, sharedDelegateField));

                // Load from field instead of allocating
                var ilProcessor4 = method.Body.GetILProcessor();
                ilProcessor4.Remove(functionPointerInstruction);
                ilProcessor4.Replace(delegateAllocationInstruction, ilProcessor4.Create(OpCodes.Ldfld, sharedDelegateField));

                return true;
            }

            // If the target is a compiler generated closure, we only handle local variable load instructions
            int variableIndex;
            OpCode storeOpCode;
            if (!TryGetStoreOpcode(loadClosureInstruction, out storeOpCode, out variableIndex))
                return false;

            // Find the instruction that stores the closure variable
            var storeClosureInstruction = loadClosureInstruction.Previous;
            VariableReference closureVarible = null;

            while (storeClosureInstruction != null)
            {
                closureVarible = storeClosureInstruction.Operand as VariableReference;
                if (storeClosureInstruction.OpCode == storeOpCode && (closureVarible == null || variableIndex == closureVarible.Index))
                    break;

                storeClosureInstruction = storeClosureInstruction.Previous;
            }
            if (storeClosureInstruction == null)
                return false;

            var closureInstanceType = method.Body.Variables[variableIndex].VariableType;
            var closureType = closureInstanceType.Resolve();
            var genericParameters = closureType.GenericParameters.Cast<TypeReference>().ToArray();

            // Patch closure
            var closure = ProcessClosure(context, closureType, genericParameters);

            // Create delegate field
            var delegateFieldType = ChangeGenericArguments(context, delegateInstanceType, closureInstanceType);
            var delegateField = new FieldDefinition($"<delegate>{delegateMethod.Name}", FieldAttributes.Public, delegateFieldType);
            closureType.Fields.Add(delegateField);
            var localDelegateFieldInstance = delegateField.MakeGeneric(genericParameters);

            // Initialize delegate field (the closure instance (local 0) is already on the stack)
            var delegateConstructorInstance = (MethodReference)delegateAllocationInstruction.Operand;
            var delegateGenericArguments = (delegateFieldType as GenericInstanceType)?.GenericArguments.ToArray() ?? new TypeReference[0];
            var genericDelegateConstructor = context.Assembly.MainModule.ImportReference(delegateConstructorInstance.Resolve()).MakeGeneric(delegateGenericArguments);

            var methodInstance = (MethodReference)functionPointerInstruction.Operand;
            var genericMethod = methodInstance.Resolve().MakeGeneric(closureType.GenericParameters.ToArray());

            if (methodInstance is GenericInstanceMethod)
                throw new NotImplementedException();

            var ilProcessor3 = closure.FactoryMethod.Body.GetILProcessor();
            var returnInstruction = ilProcessor3.Body.Instructions.FirstOrDefault(x => x.OpCode == OpCodes.Ret);
            ilProcessor3.InsertBefore(returnInstruction, ilProcessor3.Create(OpCodes.Ldloc_0));
            ilProcessor3.InsertBefore(returnInstruction, ilProcessor3.Create(OpCodes.Ldftn, genericMethod));
            ilProcessor3.InsertBefore(returnInstruction, ilProcessor3.Create(OpCodes.Newobj, genericDelegateConstructor));
            ilProcessor3.InsertBefore(returnInstruction, ilProcessor3.Create(OpCodes.Stfld, localDelegateFieldInstance));
            ilProcessor3.InsertBefore(returnInstruction, ilProcessor3.Create(OpCodes.Ldloc_0));

            var ilProcessor = method.Body.GetILProcessor();

            // Retrieve from pool
            var closureGenericArguments = (closureInstanceType as GenericInstanceType)?.GenericArguments.ToArray() ?? new TypeReference[0];
            var closureAllocation = storeClosureInstruction.Previous;
            if (closureAllocation.OpCode == OpCodes.Newobj)
            {
                // Retrieve closure from pool, instead of allocating
                var acquireClosure = ilProcessor.Create(OpCodes.Callvirt, poolAcquireMethod.MakeGeneric(closureInstanceType));
                ilProcessor.InsertAfter(closureAllocation, acquireClosure);
                ilProcessor.InsertAfter(closureAllocation, ilProcessor.Create(OpCodes.Ldsfld, closure.PoolField.MakeGeneric(closureGenericArguments)));
                closureAllocation.OpCode = OpCodes.Nop; // Change to Nop instead of removing it, as this instruction might be reference somewhere?
                closureAllocation.Operand = null;

                // Add a reference
                ilProcessor.InsertAfter(storeClosureInstruction, ilProcessor.Create(OpCodes.Callvirt, closure.AddReferenceMethod.MakeGeneric(closureGenericArguments)));
                ilProcessor.InsertAfter(storeClosureInstruction, closureVarible == null ? ilProcessor.Create(loadClosureInstruction.OpCode) : ilProcessor.Create(loadClosureInstruction.OpCode, closureVarible.Resolve()));

                // TODO: Multiple returns + try/finally
                // Release reference
                var retInstructions = method.Body.Instructions.Where(x => x.OpCode == OpCodes.Ret).ToArray();

                Instruction beforeReturn = closureVarible == null ? ilProcessor.Create(loadClosureInstruction.OpCode) : ilProcessor.Create(loadClosureInstruction.OpCode, closureVarible.Resolve());
                Instruction newReturnInstruction = ilProcessor.Create(OpCodes.Ret);
                ilProcessor.Append(beforeReturn);
                ilProcessor.Append(ilProcessor.Create(OpCodes.Ldnull));
                ilProcessor.Append(ilProcessor.Create(OpCodes.Beq, newReturnInstruction));
                ilProcessor.Append(closureVarible == null ? ilProcessor.Create(loadClosureInstruction.OpCode) : ilProcessor.Create(loadClosureInstruction.OpCode, closureVarible.Resolve()));
                ilProcessor.Append(ilProcessor.Create(OpCodes.Callvirt, closure.ReleaseMethod.MakeGeneric(closureGenericArguments)));
                ilProcessor.Append(newReturnInstruction);

                foreach (var retInstruction2 in retInstructions)
                {
                    retInstruction2.OpCode = OpCodes.Br;
                    retInstruction2.Operand = beforeReturn;
                }
            }

            // Get delegate from closure, instead of allocating
            ilProcessor.Remove(functionPointerInstruction);
            ilProcessor.Replace(delegateAllocationInstruction, ilProcessor.Create(OpCodes.Ldfld, delegateField.MakeGeneric(closureGenericArguments))); // Closure object is already on the stack

            return true;
        }
コード例 #39
0
        public bool Process(AssemblyProcessorContext context)
        {
            isInitialized = false;

            bool changed = false;

            foreach (var type in context.Assembly.EnumerateTypes().ToArray())
            {
                foreach (var method in type.Methods.ToArray())
                {
                    if (method.Body == null)
                        continue;

                    foreach (var instruction in method.Body.Instructions.ToArray())
                    {
                        if (instruction.OpCode != OpCodes.Call && instruction.OpCode != OpCodes.Callvirt)
                            continue;

                        var calledMethod = ((MethodReference)instruction.Operand).Resolve();
                        if (calledMethod == null)
                            continue;

                        for (int parameterIndex = 0; parameterIndex < calledMethod.Parameters.Count; parameterIndex++)
                        {
                            var parameter = calledMethod.Parameters[parameterIndex];

                            // Parameter must be decorated with PooledAttribute
                            if (parameter.CustomAttributes.All(x => x.AttributeType.FullName != "SiliconStudio.Core.Threading.PooledAttribute"))
                                continue;

                            // Parameter must be a delegate
                            if (parameter.ParameterType.Resolve().BaseType.FullName != typeof(MulticastDelegate).FullName)
                                continue;

                            // Find the instruction that pushes the parameter on the stack
                            // Non-trivial control flow is not supported
                            var pushParameterInstruction = WalkStack(instruction, calledMethod.Parameters.Count - parameterIndex);

                            // Try to replace delegate and closure allocations
                            {
                                EnsureInitialized(context);

                                changed |= ProcessDelegateAllocation(context, method, pushParameterInstruction);
                            }
                        }
                    }
                }
            }

            return changed;
        }
コード例 #40
0
        public bool Run(ref AssemblyDefinition assemblyDefinition, ref bool readWriteSymbols, out bool modified, ILogger logger)
        {
            log = new Logger(assemblyDefinition.Name.Name, TreatWarningsAsErrors, logger);

            modified = false;

            try
            {
                var assemblyResolver = (CustomAssemblyResolver)assemblyDefinition.MainModule.AssemblyResolver;

                // Register self
                assemblyResolver.Register(assemblyDefinition);

                var processors = new List<IAssemblyDefinitionProcessor>();

                // We are no longer using it so we are deactivating it for now to avoid processing
                //if (AutoNotifyProperty)
                //{
                //    processors.Add(new NotifyPropertyProcessor());
                //}

                processors.Add(new AddReferenceProcessor(ReferencesToAdd));

                if (ParameterKey)
                {
                    processors.Add(new ParameterKeyProcessor());
                }

                if (NewAssemblyName != null)
                {
                    processors.Add(new RenameAssemblyProcessor(NewAssemblyName));
                }

                //processors.Add(new AsyncBridgeProcessor());

                // Always applies the interop processor
                processors.Add(new InteropProcessor());

                processors.Add(new AssemblyVersionProcessor());

                if (SerializationAssembly)
                {
                    processors.Add(new SerializationProcessor(SignKeyFile, References, MemoryReferences, log));
                }

                if (DocumentationFile != null)
                {
                    processors.Add(new GenerateUserDocumentationProcessor(DocumentationFile));
                }

                if (ModuleInitializer)
                {
                    processors.Add(new ModuleInitializerProcessor());
                }

                processors.Add(new OpenSourceSignProcessor());

                // Check if pdb was actually read
                readWriteSymbols = assemblyDefinition.MainModule.HasDebugHeader;

                // Check if there is already a AssemblyProcessedAttribute (in which case we can skip processing, it has already been done).
                // Note that we should probably also match the command line as well so that we throw an error if processing is different (need to rebuild).
                if (assemblyDefinition.CustomAttributes.Any(x => x.AttributeType.FullName == "SiliconStudio.Core.AssemblyProcessedAttribute"))
                {
                    OnInfoAction("Assembly has already been processed, skip it.");
                    return true;
                }

                // Register references so that our assembly resolver can use them
                foreach (var reference in References)
                {
                    assemblyResolver.RegisterReference(reference);
                }

                if (SerializationAssembly)
                {
                    // Resave a first version of assembly with [InteralsVisibleTo] for future serialization assembly.
                    // It will be used by serialization assembly compilation.
                    // It's recommended to do it in the original code to avoid this extra step.

                    var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assemblyDefinition);
                    var stringType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(string).FullName);
                    var internalsVisibleToAttribute = mscorlibAssembly.MainModule.GetTypeResolved(typeof(InternalsVisibleToAttribute).FullName);
                    var serializationAssemblyName = assemblyDefinition.Name.Name + ".Serializers";
                    bool internalsVisibleAlreadyApplied = false;

                    // Check if already applied
                    foreach (var customAttribute in assemblyDefinition.CustomAttributes.Where(x => x.AttributeType.FullName == internalsVisibleToAttribute.FullName))
                    {
                        var assemblyName = (string)customAttribute.ConstructorArguments[0].Value;

                        int publicKeyIndex;
                        if ((publicKeyIndex = assemblyName.IndexOf(", PublicKey=", StringComparison.InvariantCulture)) != -1 || (publicKeyIndex = assemblyName.IndexOf(",PublicKey=", StringComparison.InvariantCulture)) != -1)
                        {
                            assemblyName = assemblyName.Substring(0, publicKeyIndex);
                        }

                        if (assemblyName == serializationAssemblyName)
                        {
                            internalsVisibleAlreadyApplied = true;
                            break;
                        }
                    }

                    if (!internalsVisibleAlreadyApplied)
                    {
                        // Apply public key
                        if (assemblyDefinition.Name.HasPublicKey)
                            serializationAssemblyName += ", PublicKey=" + ByteArrayToString(assemblyDefinition.Name.PublicKey);

                        // Add [InteralsVisibleTo] attribute
                        var internalsVisibleToAttributeCtor = assemblyDefinition.MainModule.Import(internalsVisibleToAttribute.GetConstructors().Single());
                        var internalsVisibleAttribute = new CustomAttribute(internalsVisibleToAttributeCtor)
                        {
                            ConstructorArguments =
                            {
                                new CustomAttributeArgument(assemblyDefinition.MainModule.Import(stringType), serializationAssemblyName)
                            }
                        };
                        assemblyDefinition.CustomAttributes.Add(internalsVisibleAttribute);

                        var assemblyFilePath = assemblyDefinition.MainModule.FullyQualifiedName;
                        if (string.IsNullOrEmpty(assemblyFilePath))
                        {
                            assemblyFilePath = Path.ChangeExtension(Path.GetTempFileName(), ".dll");
                        }

                        // Save updated file
                        assemblyDefinition.Write(assemblyFilePath, new WriterParameters() { WriteSymbols = readWriteSymbols });

                        // Reread file (otherwise it seems Mono Cecil is buggy and generate invalid PDB)
                        assemblyDefinition = AssemblyDefinition.ReadAssembly(assemblyFilePath, new ReaderParameters { AssemblyResolver = assemblyResolver, ReadSymbols = readWriteSymbols });

                        // Check if pdb was actually read
                        readWriteSymbols = assemblyDefinition.MainModule.HasDebugHeader;
                    }
                }

                var assemblyProcessorContext = new AssemblyProcessorContext(assemblyResolver, assemblyDefinition, Platform);

                foreach (var processor in processors)
                    modified = processor.Process(assemblyProcessorContext) || modified;

                // Assembly might have been recreated (i.e. il-repack), so let's use it from now on
                assemblyDefinition = assemblyProcessorContext.Assembly;

                if (modified)
                {
                    // In case assembly has been modified,
                    // add AssemblyProcessedAttribute to assembly so that it doesn't get processed again
                    var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assemblyDefinition);
                    if (mscorlibAssembly == null)
                    {
                        OnErrorAction("Missing mscorlib.dll from assembly");
                        return false;
                    }

                    var attributeType = mscorlibAssembly.MainModule.GetTypeResolved(typeof (Attribute).FullName);
                    var attributeTypeRef = assemblyDefinition.MainModule.Import(attributeType);
                    var attributeCtorRef = assemblyDefinition.MainModule.Import(attributeType.GetConstructors().Single(x => x.Parameters.Count == 0));
                    var voidType = assemblyDefinition.MainModule.Import(mscorlibAssembly.MainModule.GetTypeResolved("System.Void"));

                    // Create custom attribute
                    var assemblyProcessedAttributeType = new TypeDefinition("SiliconStudio.Core", "AssemblyProcessedAttribute", TypeAttributes.BeforeFieldInit | TypeAttributes.AnsiClass | TypeAttributes.AutoClass | TypeAttributes.Public, attributeTypeRef);

                    // Add constructor (call parent constructor)
                    var assemblyProcessedAttributeConstructor = new MethodDefinition(".ctor", MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Public, voidType);
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Call, attributeCtorRef));
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
                    assemblyProcessedAttributeType.Methods.Add(assemblyProcessedAttributeConstructor);

                    // Add AssemblyProcessedAttribute to assembly
                    assemblyDefinition.MainModule.Types.Add(assemblyProcessedAttributeType);
                    assemblyDefinition.CustomAttributes.Add(new CustomAttribute(assemblyProcessedAttributeConstructor));
                }
            }
            catch (Exception e)
            {
                OnErrorAction(e.Message, e);
                return false;
            }

            return true;
        }
コード例 #41
0
        private MethodReference ChangeGenericArguments(AssemblyProcessorContext context, MethodReference method, TypeReference relativeType)
        {
            var genericInstance = method as GenericInstanceMethod;
            if (genericInstance == null)
                return method.Resolve().MakeGeneric(relativeType.Resolve().GenericParameters.ToArray());

            Debugger.Launch();

            var genericArguments = new List<TypeReference>();
            foreach (var genericArgument in genericInstance.GenericArguments)
            {
                if (genericArgument.IsGenericParameter)
                {
                    var genericParameter = GetGenericParameterForArgument(relativeType, genericArgument);
                    if (genericParameter != null)
                    {
                        genericArguments.Add(genericParameter);
                    }
                }
                else
                {
                    var newGenericArgument = ChangeGenericArguments(context, genericArgument, relativeType);
                    genericArguments.Add(newGenericArgument);
                }
            }

            if (genericArguments.Count != genericInstance.GenericArguments.Count)
            {
                throw new InvalidOperationException("Could not resolve generic arguments");
            }

            return context.Assembly.MainModule.ImportReference(genericInstance.Resolve()).MakeGeneric(genericArguments.ToArray());
        }
コード例 #42
0
        public bool Process(AssemblyProcessorContext context)
        {
            var assembly         = context.Assembly;
            var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assembly);

            if (mscorlibAssembly == null)
            {
                throw new InvalidOperationException("Missing mscorlib.dll from assembly");
            }

            // For now, use import, but this can cause mixed framework versions when processing an assembly with a different framework version.
            voidType   = assembly.MainModule.TypeSystem.Void;
            stringType = assembly.MainModule.TypeSystem.String;
            objectType = assembly.MainModule.TypeSystem.Object;
            var propertyInfoType = assembly.MainModule.ImportReference(mscorlibAssembly.MainModule.GetTypeResolved(typeof(PropertyInfo).FullName));
            var typeType         = mscorlibAssembly.MainModule.GetTypeResolved(typeof(Type).FullName);


            TypeDefinition propertyChangedExtendedEventArgsType;

            AssemblyDefinition siliconStudioCoreAssembly;

            try
            {
                siliconStudioCoreAssembly = assembly.Name.Name == "SiliconStudio.Core"
                    ? assembly
                    : context.AssemblyResolver.Resolve("SiliconStudio.Core");
            }
            catch (Exception)
            {
                return(true);
            }

            propertyChangedExtendedEventArgsType = siliconStudioCoreAssembly.MainModule.GetTypes().First(x => x.Name == "PropertyChangedExtendedEventArgs").Resolve();

            var typeTokenInfoEx         = mscorlibAssembly.MainModule.GetType("System.Reflection.TypeInfo").Resolve();
            var getPropertyMethod       = typeTokenInfoEx.Methods.First(x => x.Name == "GetDeclaredProperty" && x.Parameters.Count == 1);
            var getTypeFromHandleMethod = typeType.Methods.First(x => x.Name == "GetTypeFromHandle");
            var getTokenInfoExMethod    = mscorlibAssembly.MainModule.GetType("System.Reflection.IntrospectionExtensions").Resolve().Methods.First(x => x.Name == "GetTypeInfo");

            var propertyChangedExtendedEventArgsConstructor = assembly.MainModule.ImportReference(propertyChangedExtendedEventArgsType.Methods.First(x => x.IsConstructor));

            bool modified = false;

            foreach (var type in assembly.MainModule.GetTypes())
            {
                MethodReference getPropertyChangedMethod;

                getPropertyChangedMethod = GetGetPropertyChangedMethod(assembly, type);
                //var propertyChangedField = GetPropertyChangedField(type);
                //if (propertyChangedField == null)
                //    continue;

                var propertyChangedField = GetPropertyChangedField(type);

                if (getPropertyChangedMethod == null && propertyChangedField == null)
                {
                    continue;
                }

                TypeReference propertyChangedFieldType;

                if (getPropertyChangedMethod == null)
                {
                    modified = true;
                    getPropertyChangedMethod = GetOrCreateGetPropertyChangedMethod(assembly, type, propertyChangedField);
                }

                if (propertyChangedField != null)
                {
                    propertyChangedField     = assembly.MainModule.ImportReference(propertyChangedField);
                    propertyChangedFieldType = propertyChangedField.FieldType;
                }
                else
                {
                    propertyChangedFieldType = getPropertyChangedMethod.ReturnType;
                }

                // Add generic to declaring type
                if (getPropertyChangedMethod.DeclaringType.HasGenericParameters)
                {
                    getPropertyChangedMethod = getPropertyChangedMethod.MakeGeneric(getPropertyChangedMethod.DeclaringType.GenericParameters.ToArray());
                }

                var propertyChangedInvoke = assembly.MainModule.ImportReference(propertyChangedFieldType.Resolve().Methods.First(x => x.Name == "Invoke"));

                foreach (var property in type.Properties)
                {
                    if (property.SetMethod == null || !property.HasThis)
                    {
                        continue;
                    }

                    MethodReference propertyGetMethod = property.GetMethod;

                    // Only patch properties that have a public Getter
                    var methodDefinition = propertyGetMethod.Resolve();
                    if ((methodDefinition.Attributes & MethodAttributes.Public) != MethodAttributes.Public)
                    {
                        continue;
                    }

                    // Add generic to declaring type
                    if (propertyGetMethod.DeclaringType.HasGenericParameters)
                    {
                        propertyGetMethod = propertyGetMethod.MakeGeneric(propertyGetMethod.DeclaringType.GenericParameters.ToArray());
                    }

                    //var versionableAttribute = property.CustomAttributes.FirstOrDefault(x => x.AttributeType.FullName == typeof(VersionableAttribute).FullName);
                    //if (versionableAttribute == null)
                    //    continue;

                    modified = true;

                    FieldReference staticField = new FieldDefinition(property.Name + "PropertyInfo", FieldAttributes.Static | FieldAttributes.Private | FieldAttributes.InitOnly, propertyInfoType);
                    type.Fields.Add((FieldDefinition)staticField);

                    // Add generic to declaring type
                    if (staticField.DeclaringType.HasGenericParameters)
                    {
                        staticField = staticField.MakeGeneric(staticField.DeclaringType.GenericParameters.ToArray());
                    }

                    // In static constructor, find PropertyInfo and store it in static field
                    {
                        var staticConstructor = type.GetStaticConstructor();
                        if (staticConstructor == null)
                        {
                            staticConstructor = new MethodDefinition(".cctor",
                                                                     MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                                                                     voidType);
                            staticConstructor.Body.GetILProcessor().Append(Instruction.Create(OpCodes.Ret));

                            type.Methods.Add(staticConstructor);
                        }


                        VariableReference localTokenEx = null;
                        int localTokenExIndex          = 0;
                        for (int i = 0; i < staticConstructor.Body.Variables.Count; i++)
                        {
                            var localVar = staticConstructor.Body.Variables[i];
                            if (localVar.VariableType.FullName == typeTokenInfoEx.FullName)
                            {
                                localTokenEx      = localVar;
                                localTokenExIndex = i;
                                break;
                            }
                        }

                        if (localTokenEx == null)
                        {
                            localTokenEx = new VariableDefinition(assembly.MainModule.ImportReference(typeTokenInfoEx));
                            staticConstructor.Body.Variables.Add((VariableDefinition)localTokenEx);
                            localTokenExIndex = staticConstructor.Body.Variables.Count - 1;
                        }

                        var ilProcessor       = staticConstructor.Body.GetILProcessor();
                        var returnInstruction = staticConstructor.Body.Instructions.Last();

                        var newReturnInstruction = Instruction.Create(returnInstruction.OpCode);
                        newReturnInstruction.Operand = returnInstruction.Operand;

                        returnInstruction.OpCode  = OpCodes.Nop;
                        returnInstruction.Operand = null;

                        // Find PropertyInfo and store it in static field
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldtoken, type));
                        ilProcessor.Append(Instruction.Create(OpCodes.Call, assembly.MainModule.ImportReference(getTypeFromHandleMethod)));
                        ilProcessor.Append(Instruction.Create(OpCodes.Call, assembly.MainModule.ImportReference(getTokenInfoExMethod)));
                        ilProcessor.Append(LocationToStloc(ilProcessor, localTokenExIndex));
                        ilProcessor.Append(ilProcessor.Create(OpCodes.Ldloca_S, (byte)localTokenExIndex));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldstr, property.Name));
                        ilProcessor.Append(Instruction.Create(OpCodes.Call, assembly.MainModule.ImportReference(getPropertyMethod)));
                        ilProcessor.Append(Instruction.Create(OpCodes.Stsfld, staticField));

                        ilProcessor.Append(newReturnInstruction);
                    }

                    {
                        var ilProcessor       = property.SetMethod.Body.GetILProcessor();
                        var returnInstruction = property.SetMethod.Body.Instructions.Last();

                        var firstInstruction = property.SetMethod.Body.Instructions[0];

                        if (property.SetMethod.Body.Instructions[0].OpCode != OpCodes.Nop)
                        {
                            ilProcessor.InsertBefore(property.SetMethod.Body.Instructions[0], Instruction.Create(OpCodes.Nop));
                        }

                        var newReturnInstruction = Instruction.Create(returnInstruction.OpCode);
                        newReturnInstruction.Operand = returnInstruction.Operand;

                        returnInstruction.OpCode  = OpCodes.Nop;
                        returnInstruction.Operand = null;

                        var propertyChangedVariable = new VariableDefinition("propertyChanged", assembly.MainModule.ImportReference(propertyChangedFieldType));
                        property.SetMethod.Body.Variables.Add(propertyChangedVariable);

                        var oldValueVariable = new VariableDefinition("oldValue", objectType);
                        property.SetMethod.Body.Variables.Add(oldValueVariable);

                        Instruction jump1, jump2;

                        // Prepend:
                        // var propertyChanged = GetPropertyChanged();
                        // var oldValue = propertyChanged != null ? (object)Property : null;
                        property.SetMethod.Body.SimplifyMacros();
                        ilProcessor.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Ldarg_0));
                        ilProcessor.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Call, getPropertyChangedMethod));
                        ilProcessor.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Stloc, propertyChangedVariable));
                        ilProcessor.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Ldloc, propertyChangedVariable));
                        ilProcessor.InsertBefore(firstInstruction, jump1 = Instruction.Create(OpCodes.Brtrue, Instruction.Create(OpCodes.Nop)));
                        ilProcessor.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Ldnull));
                        ilProcessor.InsertBefore(firstInstruction, jump2 = Instruction.Create(OpCodes.Br, Instruction.Create(OpCodes.Nop)));
                        ilProcessor.InsertBefore(firstInstruction, (Instruction)(jump1.Operand = Instruction.Create(OpCodes.Ldarg_0)));
                        ilProcessor.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Call, propertyGetMethod));
                        if (property.PropertyType.IsValueType)
                        {
                            ilProcessor.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Box, property.PropertyType));
                        }
                        ilProcessor.InsertBefore(firstInstruction, (Instruction)(jump2.Operand = Instruction.Create(OpCodes.Nop)));
                        ilProcessor.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Stloc, oldValueVariable));

                        // Append:
                        // if (propertyChanged != null)
                        //     propertyChanged(this, new PropertyChangedExtendedEventArgs("Property", oldValue, Property));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldloc, propertyChangedVariable));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldnull));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ceq));
                        ilProcessor.Append(Instruction.Create(OpCodes.Brtrue, newReturnInstruction));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldloc, propertyChangedVariable));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldarg_0));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldsfld, staticField));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldloc, oldValueVariable));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldarg_0));
                        ilProcessor.Append(Instruction.Create(OpCodes.Call, propertyGetMethod));
                        if (property.PropertyType.IsValueType)
                        {
                            ilProcessor.Append(Instruction.Create(OpCodes.Box, property.PropertyType));
                        }
                        ilProcessor.Append(Instruction.Create(OpCodes.Newobj, propertyChangedExtendedEventArgsConstructor));
                        ilProcessor.Append(Instruction.Create(OpCodes.Callvirt, propertyChangedInvoke));
                        ilProcessor.Append(Instruction.Create(OpCodes.Nop));
                        ilProcessor.Append(newReturnInstruction);
                        property.SetMethod.Body.OptimizeMacros();
                    }
                }
            }

            return(modified);
        }
コード例 #43
0
        private ClosureInfo ProcessClosure(AssemblyProcessorContext context, TypeDefinition closureType, TypeReference[] genericParameters)
        {
            ClosureInfo closure;
            if (closures.TryGetValue(closureType, out closure))
                return closure;

            var closureTypeConstructor = closureType.Methods.FirstOrDefault(x => x.Name == ".ctor");
            var closureGenericType = closureType.MakeGenericType(genericParameters);

            // Create factory method for pool items
            var factoryMethod = new MethodDefinition("<Factory>", MethodAttributes.HideBySig | MethodAttributes.Private | MethodAttributes.Static, closureGenericType);
            closureType.Methods.Add(factoryMethod);
            factoryMethod.Body.InitLocals = true;
            factoryMethod.Body.Variables.Add(new VariableDefinition(closureGenericType));
            var factoryMethodProcessor = factoryMethod.Body.GetILProcessor();
            // Create and store closure
            factoryMethodProcessor.Emit(OpCodes.Newobj, closureTypeConstructor.MakeGeneric(genericParameters));
            factoryMethodProcessor.Emit(OpCodes.Stloc_0);
            //// Return closure
            factoryMethodProcessor.Emit(OpCodes.Ldloc_0);
            factoryMethodProcessor.Emit(OpCodes.Ret);

            // Create pool field
            var poolField = new FieldDefinition("<pool>", FieldAttributes.Public | FieldAttributes.Static, poolType.MakeGenericType(closureGenericType));
            closureType.Fields.Add(poolField);
            var poolFieldReference = poolField.MakeGeneric(genericParameters);

            // Initialize pool
            var cctor = GetOrCreateClassConstructor(closureType);
            var ilProcessor2 = cctor.Body.GetILProcessor();
            var retInstruction = cctor.Body.Instructions.FirstOrDefault(x => x.OpCode == OpCodes.Ret);
            ilProcessor2.InsertBefore(retInstruction, ilProcessor2.Create(OpCodes.Ldnull));
            ilProcessor2.InsertBefore(retInstruction, ilProcessor2.Create(OpCodes.Ldftn, factoryMethod.MakeGeneric(genericParameters)));
            ilProcessor2.InsertBefore(retInstruction, ilProcessor2.Create(OpCodes.Newobj, funcConstructor.MakeGeneric(closureGenericType)));
            ilProcessor2.InsertBefore(retInstruction, ilProcessor2.Create(OpCodes.Newobj, poolConstructor.MakeGeneric(closureGenericType)));
            ilProcessor2.InsertBefore(retInstruction, ilProcessor2.Create(OpCodes.Stsfld, poolFieldReference));

            // Implement IPooledClosure
            closureType.Interfaces.Add(pooledClosureType);

            // Create reference count field
            var countField = new FieldDefinition("<referenceCount>", FieldAttributes.Public, context.Assembly.MainModule.TypeSystem.Int32);
            closureType.Fields.Add(countField);
            var oountFieldReference = countField.MakeGeneric(genericParameters);

            // Create AddReference method
            var addReferenceMethod = new MethodDefinition("AddReference", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual | MethodAttributes.NewSlot, context.Assembly.MainModule.TypeSystem.Void);
            var ilProcessor4 = addReferenceMethod.Body.GetILProcessor();
            ilProcessor4.Emit(OpCodes.Ldarg_0);
            ilProcessor4.Emit(OpCodes.Ldflda, oountFieldReference);
            ilProcessor4.Emit(OpCodes.Call, interlockedIncrementMethod);
            ilProcessor4.Emit(OpCodes.Pop);
            ilProcessor4.Emit(OpCodes.Ret);
            closureType.Methods.Add(addReferenceMethod);

            // Create Release method
            var releaseMethod = new MethodDefinition("Release", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual | MethodAttributes.NewSlot, context.Assembly.MainModule.TypeSystem.Void);
            ilProcessor4 = releaseMethod.Body.GetILProcessor();
            retInstruction = ilProcessor4.Create(OpCodes.Ret);
            // Check decremented reference count
            ilProcessor4.Emit(OpCodes.Ldarg_0);
            ilProcessor4.Emit(OpCodes.Ldflda, oountFieldReference);
            ilProcessor4.Emit(OpCodes.Call, interlockedDecrementMethod);
            ilProcessor4.Emit(OpCodes.Ldc_I4_0);
            ilProcessor4.Emit(OpCodes.Ceq);
            ilProcessor4.Emit(OpCodes.Brfalse_S, retInstruction);
            // Release this to pool
            ilProcessor4.Emit(OpCodes.Ldsfld, poolFieldReference);
            ilProcessor4.Emit(OpCodes.Ldarg_0);
            ilProcessor4.Emit(OpCodes.Callvirt, poolReleaseMethod.MakeGeneric(closureGenericType));
            ilProcessor4.Append(retInstruction);
            closureType.Methods.Add(releaseMethod);

            closures.Add(closureType, closure = new ClosureInfo
            {
                FactoryMethod = factoryMethod,
                AddReferenceMethod = addReferenceMethod,
                ReleaseMethod = releaseMethod,
                PoolField = poolField
            });

            return closure;
        }
コード例 #44
0
        public bool Process(AssemblyProcessorContext context)
        {
            var assembly = context.Assembly;
            var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assembly);
            if (mscorlibAssembly == null)
                throw new InvalidOperationException("Missing mscorlib.dll from assembly");

            // For now, use import, but this can cause mixed framework versions when processing an assembly with a different framework version.
            voidType = assembly.MainModule.TypeSystem.Void;
            stringType = assembly.MainModule.TypeSystem.String;
            objectType = assembly.MainModule.TypeSystem.Object;
            var propertyInfoType = assembly.MainModule.ImportReference(mscorlibAssembly.MainModule.GetTypeResolved(typeof(PropertyInfo).FullName));
            var typeType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(Type).FullName);


            TypeDefinition propertyChangedExtendedEventArgsType;

            AssemblyDefinition siliconStudioCoreAssembly;
            try
            {
                siliconStudioCoreAssembly = assembly.Name.Name == "SiliconStudio.Core"
                    ? assembly
                    : context.AssemblyResolver.Resolve("SiliconStudio.Core");

            }
            catch (Exception)
            {
                return true;
            }

            propertyChangedExtendedEventArgsType = siliconStudioCoreAssembly.MainModule.GetTypes().First(x => x.Name == "PropertyChangedExtendedEventArgs").Resolve();

            var typeTokenInfoEx = mscorlibAssembly.MainModule.GetType("System.Reflection.TypeInfo").Resolve();
            var getPropertyMethod = typeTokenInfoEx.Methods.First(x => x.Name == "GetDeclaredProperty" && x.Parameters.Count == 1);
            var getTypeFromHandleMethod = typeType.Methods.First(x => x.Name == "GetTypeFromHandle");
            var getTokenInfoExMethod = mscorlibAssembly.MainModule.GetType("System.Reflection.IntrospectionExtensions").Resolve().Methods.First(x => x.Name == "GetTypeInfo");
            
            var propertyChangedExtendedEventArgsConstructor = assembly.MainModule.ImportReference(propertyChangedExtendedEventArgsType.Methods.First(x => x.IsConstructor));

            bool modified = false;

            foreach (var type in assembly.MainModule.GetTypes())
            {
                MethodReference getPropertyChangedMethod;

                getPropertyChangedMethod = GetGetPropertyChangedMethod(assembly, type);
                //var propertyChangedField = GetPropertyChangedField(type);
                //if (propertyChangedField == null)
                //    continue;

                var propertyChangedField = GetPropertyChangedField(type);

                if (getPropertyChangedMethod == null && propertyChangedField == null)
                    continue;

                TypeReference propertyChangedFieldType;

                if (getPropertyChangedMethod == null)
                {
                    modified = true;
                    getPropertyChangedMethod = GetOrCreateGetPropertyChangedMethod(assembly, type, propertyChangedField);
                }

                if (propertyChangedField != null)
                {
                    propertyChangedField = assembly.MainModule.ImportReference(propertyChangedField);
                    propertyChangedFieldType = propertyChangedField.FieldType;
                }
                else
                {
                    propertyChangedFieldType = getPropertyChangedMethod.ReturnType;
                }

                // Add generic to declaring type
                if (getPropertyChangedMethod.DeclaringType.HasGenericParameters)
                    getPropertyChangedMethod = getPropertyChangedMethod.MakeGeneric(getPropertyChangedMethod.DeclaringType.GenericParameters.ToArray());

                var propertyChangedInvoke = assembly.MainModule.ImportReference(propertyChangedFieldType.Resolve().Methods.First(x => x.Name == "Invoke"));

                foreach (var property in type.Properties)
                {
                    if (property.SetMethod == null || !property.HasThis)
                        continue;

                    MethodReference propertyGetMethod = property.GetMethod;

                    // Only patch properties that have a public Getter
                    var methodDefinition = propertyGetMethod.Resolve();
                    if ((methodDefinition.Attributes & MethodAttributes.Public) != MethodAttributes.Public)
                    {
                        continue;
                    }

                    // Add generic to declaring type
                    if (propertyGetMethod.DeclaringType.HasGenericParameters)
                        propertyGetMethod = propertyGetMethod.MakeGeneric(propertyGetMethod.DeclaringType.GenericParameters.ToArray());

                    //var versionableAttribute = property.CustomAttributes.FirstOrDefault(x => x.AttributeType.FullName == typeof(VersionableAttribute).FullName);
                    //if (versionableAttribute == null)
                    //    continue;

                    modified = true;

                    FieldReference staticField = new FieldDefinition(property.Name + "PropertyInfo", FieldAttributes.Static | FieldAttributes.Private | FieldAttributes.InitOnly, propertyInfoType);
                    type.Fields.Add((FieldDefinition)staticField);

                    // Add generic to declaring type
                    if (staticField.DeclaringType.HasGenericParameters)
                        staticField = staticField.MakeGeneric(staticField.DeclaringType.GenericParameters.ToArray());

                    // In static constructor, find PropertyInfo and store it in static field
                    {
                        var staticConstructor = type.GetStaticConstructor();
                        if (staticConstructor == null)
                        {
                            staticConstructor = new MethodDefinition(".cctor",
                                                                     MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                                                                     voidType);
                            staticConstructor.Body.GetILProcessor().Append(Instruction.Create(OpCodes.Ret));

                            type.Methods.Add(staticConstructor);
                        }


                        VariableReference localTokenEx = null;
                        int localTokenExIndex = 0;
                        for (int i = 0; i < staticConstructor.Body.Variables.Count; i++)
                        {
                            var localVar = staticConstructor.Body.Variables[i];
                            if (localVar.VariableType.FullName == typeTokenInfoEx.FullName)
                            {
                                localTokenEx = localVar;
                                localTokenExIndex = i;
                                break;
                            }
                        }

                        if (localTokenEx == null)
                        {
                            localTokenEx = new VariableDefinition(assembly.MainModule.ImportReference(typeTokenInfoEx));
                            staticConstructor.Body.Variables.Add((VariableDefinition)localTokenEx);
                            localTokenExIndex = staticConstructor.Body.Variables.Count - 1;
                        }

                        var ilProcessor = staticConstructor.Body.GetILProcessor();
                        var returnInstruction = staticConstructor.Body.Instructions.Last();

                        var newReturnInstruction = Instruction.Create(returnInstruction.OpCode);
                        newReturnInstruction.Operand = returnInstruction.Operand;

                        returnInstruction.OpCode = OpCodes.Nop;
                        returnInstruction.Operand = null;

                        // Find PropertyInfo and store it in static field
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldtoken, type));
                        ilProcessor.Append(Instruction.Create(OpCodes.Call, assembly.MainModule.ImportReference(getTypeFromHandleMethod)));
                        ilProcessor.Append(Instruction.Create(OpCodes.Call, assembly.MainModule.ImportReference(getTokenInfoExMethod)));
                        ilProcessor.Append(LocationToStloc(ilProcessor, localTokenExIndex));
                        ilProcessor.Append(ilProcessor.Create(OpCodes.Ldloca_S, (byte)localTokenExIndex));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldstr, property.Name));
                        ilProcessor.Append(Instruction.Create(OpCodes.Call, assembly.MainModule.ImportReference(getPropertyMethod)));
                        ilProcessor.Append(Instruction.Create(OpCodes.Stsfld, staticField));

                        ilProcessor.Append(newReturnInstruction);
                    }
                    
                    {
                        var ilProcessor = property.SetMethod.Body.GetILProcessor();
                        var returnInstruction = property.SetMethod.Body.Instructions.Last();

                        var firstInstruction = property.SetMethod.Body.Instructions[0];

                        if (property.SetMethod.Body.Instructions[0].OpCode != OpCodes.Nop)
                            ilProcessor.InsertBefore(property.SetMethod.Body.Instructions[0], Instruction.Create(OpCodes.Nop));

                        var newReturnInstruction = Instruction.Create(returnInstruction.OpCode);
                        newReturnInstruction.Operand = returnInstruction.Operand;

                        returnInstruction.OpCode = OpCodes.Nop;
                        returnInstruction.Operand = null;

                        var propertyChangedVariable = new VariableDefinition("propertyChanged", assembly.MainModule.ImportReference(propertyChangedFieldType));
                        property.SetMethod.Body.Variables.Add(propertyChangedVariable);

                        var oldValueVariable = new VariableDefinition("oldValue", objectType);
                        property.SetMethod.Body.Variables.Add(oldValueVariable);

                        Instruction jump1, jump2;

                        // Prepend:
                        // var propertyChanged = GetPropertyChanged();
                        // var oldValue = propertyChanged != null ? (object)Property : null;
                        property.SetMethod.Body.SimplifyMacros();
                        ilProcessor.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Ldarg_0));
                        ilProcessor.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Call, getPropertyChangedMethod));
                        ilProcessor.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Stloc, propertyChangedVariable));
                        ilProcessor.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Ldloc, propertyChangedVariable));
                        ilProcessor.InsertBefore(firstInstruction, jump1 = Instruction.Create(OpCodes.Brtrue, Instruction.Create(OpCodes.Nop)));
                        ilProcessor.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Ldnull));
                        ilProcessor.InsertBefore(firstInstruction, jump2 = Instruction.Create(OpCodes.Br, Instruction.Create(OpCodes.Nop)));
                        ilProcessor.InsertBefore(firstInstruction, (Instruction)(jump1.Operand = Instruction.Create(OpCodes.Ldarg_0)));
                        ilProcessor.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Call, propertyGetMethod));
                        if (property.PropertyType.IsValueType)
                            ilProcessor.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Box, property.PropertyType));
                        ilProcessor.InsertBefore(firstInstruction, (Instruction)(jump2.Operand = Instruction.Create(OpCodes.Nop)));
                        ilProcessor.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Stloc, oldValueVariable));

                        // Append:
                        // if (propertyChanged != null)
                        //     propertyChanged(this, new PropertyChangedExtendedEventArgs("Property", oldValue, Property));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldloc, propertyChangedVariable));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldnull));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ceq));
                        ilProcessor.Append(Instruction.Create(OpCodes.Brtrue, newReturnInstruction));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldloc, propertyChangedVariable));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldarg_0));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldsfld, staticField));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldloc, oldValueVariable));
                        ilProcessor.Append(Instruction.Create(OpCodes.Ldarg_0));
                        ilProcessor.Append(Instruction.Create(OpCodes.Call, propertyGetMethod));
                        if (property.PropertyType.IsValueType)
                            ilProcessor.Append(Instruction.Create(OpCodes.Box, property.PropertyType));
                        ilProcessor.Append(Instruction.Create(OpCodes.Newobj, propertyChangedExtendedEventArgsConstructor));
                        ilProcessor.Append(Instruction.Create(OpCodes.Callvirt, propertyChangedInvoke));
                        ilProcessor.Append(Instruction.Create(OpCodes.Nop));
                        ilProcessor.Append(newReturnInstruction);
                        property.SetMethod.Body.OptimizeMacros();
                    }
                }
            }

            return modified;
        }
コード例 #45
0
        public bool Process(AssemblyProcessorContext context)
        {
            var assembly = context.Assembly;
            var fields = new List<FieldDefinition>();

            var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assembly);
            if (mscorlibAssembly == null)
                throw new InvalidOperationException("Missing mscorlib.dll from assembly");

            MethodDefinition parameterKeysMergeMethod = null;
            TypeDefinition assemblyEffectKeysAttributeType = null;
            var getTypeFromHandleMethod = new Lazy<MethodReference>(() =>
            {
                // Find Type.GetTypeFromHandle
                var typeType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(Type).FullName);
                return assembly.MainModule.ImportReference(typeType.Methods.First(x => x.Name == "GetTypeFromHandle"));
            });

            var effectKeysStaticConstructors = new List<MethodReference>();
            var effectKeysArrayElemementTypes = new HashSet<TypeReference>();

            foreach (var type in assembly.MainModule.GetTypes())
            {
                fields.Clear();

                foreach (var field in type.Fields.Where(x => x.IsStatic))
                {
                    var fieldBaseType = field.FieldType;
                    while (fieldBaseType != null)
                    {
                        if (fieldBaseType.FullName == "SiliconStudio.Xenko.Rendering.ParameterKey")
                            break;

                        // TODO: Get PropertyKey.PropertyType instead
                        var genericInstance = fieldBaseType as GenericInstanceType;
                        if (genericInstance != null && genericInstance.ElementType.FullName == "SiliconStudio.Xenko.Rendering.ParameterKey`1")
                        {
                            var genericArgument = genericInstance.GenericArguments.First();
                            if (genericArgument.IsArray)
                            {
                                effectKeysArrayElemementTypes.Add(genericArgument.GetElementType());
                            }
                        }

                        var resolvedFieldBaseType = fieldBaseType.Resolve();
                        if (resolvedFieldBaseType == null)
                        {
                            fieldBaseType = null;
                            break;
                        }

                        fieldBaseType = resolvedFieldBaseType.BaseType;
                    }

                    if (fieldBaseType == null)
                        continue;

                    fields.Add(field);
                }

                if (fields.Count == 0)
                    continue;

                // ParameterKey present means we should have a static cctor.
                var cctor = type.GetStaticConstructor();
                if (cctor == null)
                    continue;

                // Load necessary SiliconStudio.Xenko methods/attributes
                if (parameterKeysMergeMethod == null)
                {
                    AssemblyDefinition xenkoEngineAssembly;
                    try
                    {
                        xenkoEngineAssembly = assembly.Name.Name == "SiliconStudio.Xenko"
                            ? assembly
                            : context.AssemblyResolver.Resolve("SiliconStudio.Xenko");
                    }
                    catch (Exception)
                    {
                        Console.WriteLine("Error, cannot find [SiliconStudio.Xenko] assembly for processing ParameterKeyProcessor");
                        // We can't generate an exception, so we are just returning. It means that SiliconStudio.Xenko has not been generated so far.
                        return true;
                    }

                    var parameterKeysType = xenkoEngineAssembly.MainModule.GetTypes().First(x => x.Name == "ParameterKeys");
                    parameterKeysMergeMethod = parameterKeysType.Methods.First(x => x.Name == "Merge");
                    assemblyEffectKeysAttributeType = xenkoEngineAssembly.MainModule.GetTypes().First(x => x.Name == "AssemblyEffectKeysAttribute");
                }

                var cctorIL = cctor.Body.GetILProcessor();
                var cctorInstructions = cctor.Body.Instructions;

                var keyClassName = type.Name;
                if (keyClassName.EndsWith("Keys"))
                    keyClassName = keyClassName.Substring(0, keyClassName.Length - 4);

                keyClassName += '.';

                bool cctorModified = false;

                // Find field store instruction
                for (int i = 0; i < cctorInstructions.Count; ++i)
                {
                    var fieldInstruction = cctorInstructions[i];

                    if (fieldInstruction.OpCode == OpCodes.Stsfld
                        && fields.Contains(fieldInstruction.Operand))
                    {
                        var activeField = (FieldReference)fieldInstruction.Operand;

                        var nextInstruction = cctorInstructions[i + 1];
                        cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Ldsfld, activeField));
                        cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Ldtoken, type));
                        cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Call, getTypeFromHandleMethod.Value));
                        cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Ldstr, keyClassName + activeField.Name));
                        cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Call, assembly.MainModule.ImportReference(parameterKeysMergeMethod)));
                        cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Castclass, activeField.FieldType));
                        cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Stsfld, activeField));
                        i = cctorInstructions.IndexOf(nextInstruction);
                        cctorModified = true;
                    }
                }

                if (cctorModified)
                {
                    effectKeysStaticConstructors.Add(cctor);
                }
            }

            if (effectKeysStaticConstructors.Count > 0)
            {
                // Add [AssemblyEffectKeysAttribute] to the assembly
                assembly.CustomAttributes.Add(new CustomAttribute(assembly.MainModule.ImportReference(assemblyEffectKeysAttributeType.GetConstructors().First(x => !x.HasParameters))));

                // Get or create module static constructor
                var voidType = assembly.MainModule.TypeSystem.Void;
                var moduleClass = assembly.MainModule.Types.First(t => t.Name == "<Module>");
                var staticConstructor = moduleClass.GetStaticConstructor();
                if (staticConstructor == null)
                {
                    staticConstructor = new MethodDefinition(".cctor",
                                                             MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                                                             voidType);
                    staticConstructor.Body.GetILProcessor().Append(Instruction.Create(OpCodes.Ret));

                    moduleClass.Methods.Add(staticConstructor);
                }

                var il = staticConstructor.Body.GetILProcessor();

                var returnInstruction = staticConstructor.Body.Instructions.Last();
                var newReturnInstruction = Instruction.Create(returnInstruction.OpCode);
                newReturnInstruction.Operand = returnInstruction.Operand;

                returnInstruction.OpCode = OpCodes.Nop;
                returnInstruction.Operand = null;

                var typeType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(Type).FullName);
                var typeHandleProperty = typeType.Properties.First(x => x.Name == "TypeHandle");
                var getTypeHandleMethod = assembly.MainModule.ImportReference(typeHandleProperty.GetMethod);

                var runtimeHelpersType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(RuntimeHelpers).FullName);
                var runClassConstructorMethod = assembly.MainModule.ImportReference(runtimeHelpersType.Methods.Single(x => x.IsPublic && x.Name == "RunClassConstructor" && x.Parameters.Count == 1 && x.Parameters[0].ParameterType.FullName == typeof(RuntimeTypeHandle).FullName));

                // Call every key class static constructor from the module static constructor so that they are properly constructed (because accessing through reflection might cause problems)
                staticConstructor.Body.SimplifyMacros();
                foreach (var effectKeysStaticConstructor in effectKeysStaticConstructors)
                {
                    il.Append(Instruction.Create(OpCodes.Ldtoken, effectKeysStaticConstructor.DeclaringType));
                    il.Append(Instruction.Create(OpCodes.Call, getTypeFromHandleMethod.Value));
                    il.Append(Instruction.Create(OpCodes.Callvirt, getTypeHandleMethod));
                    il.Append(Instruction.Create(OpCodes.Call, runClassConstructorMethod));
                }

                if (effectKeysArrayElemementTypes.Count > 0)
                {
                    var methodImplAttributeType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(MethodImplAttribute).FullName);
                    var methodImplAttributesType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(MethodImplOptions).FullName);

                    var attribute = new CustomAttribute(methodImplAttributeType.GetConstructors().First(x => x.HasParameters && x.Parameters[0].ParameterType.FullName == methodImplAttributesType.FullName));
                    attribute.ConstructorArguments.Add(new CustomAttributeArgument(methodImplAttributesType, MethodImplOptions.NoOptimization));

                    staticConstructor.CustomAttributes.Add(attribute);
                }

                // Create instances of InternalValueArray<T>. Required for LLVM AOT
                foreach (var elementType in effectKeysArrayElemementTypes)
                {
                    var siliconStudioXenkoAssembly = assembly.Name.Name == "SiliconStudio.Xenko" ? assembly : assembly.MainModule.AssemblyResolver.Resolve("SiliconStudio.Xenko");
                    var parameterCollectionType = siliconStudioXenkoAssembly.MainModule.GetTypeResolved("SiliconStudio.Xenko.Rendering.ParameterCollection");
                    var internalValueArrayType = parameterCollectionType.NestedTypes.First(x => x.Name == "InternalValueArray`1");
                    var constructor = internalValueArrayType.GetConstructors().First();
                    var internalValueArrayConstructor = siliconStudioXenkoAssembly.MainModule.ImportReference(constructor).MakeGeneric(elementType);

                    il.Append(Instruction.Create(OpCodes.Ldc_I4_0));
                    il.Append(Instruction.Create(OpCodes.Newobj, internalValueArrayConstructor));
                    il.Append(Instruction.Create(OpCodes.Pop));
                }

                il.Append(newReturnInstruction);
                staticConstructor.Body.OptimizeMacros();
            }

            return true;
        }
コード例 #46
0
        public bool Run(ref AssemblyDefinition assemblyDefinition, ref bool readWriteSymbols, out bool modified)
        {
            modified = false;

            try
            {
                var assemblyResolver = (CustomAssemblyResolver)assemblyDefinition.MainModule.AssemblyResolver;

                var processors = new List<IAssemblyDefinitionProcessor>();

                // We are no longer using it so we are deactivating it for now to avoid processing
                //if (AutoNotifyProperty)
                //{
                //    processors.Add(new NotifyPropertyProcessor());
                //}

                if (ParameterKey)
                {
                    processors.Add(new ParameterKeyProcessor());
                }

                if (NewAssemblyName != null)
                {
                    processors.Add(new RenameAssemblyProcessor(NewAssemblyName));
                }

                //processors.Add(new AsyncBridgeProcessor());

                // Always applies the interop processor
                processors.Add(new InteropProcessor());

                processors.Add(new AssemblyVersionProcessor());

                if (SerializationAssembly)
                {
                    processors.Add(new SerializationProcessor(SignKeyFile, SerializationProjectReferences));
                }

                if (GenerateUserDocumentation)
                {
                    processors.Add(new GenerateUserDocumentationProcessor(assemblyDefinition.MainModule.FullyQualifiedName));
                }

                if (ModuleInitializer)
                {
                    processors.Add(new ModuleInitializerProcessor());
                }

                processors.Add(new OpenSourceSignProcessor());

                // Check if pdb was actually read
                readWriteSymbols = assemblyDefinition.MainModule.HasDebugHeader;

                // Check if there is already a AssemblyProcessedAttribute (in which case we can skip processing, it has already been done).
                // Note that we should probably also match the command line as well so that we throw an error if processing is different (need to rebuild).
                if (assemblyDefinition.CustomAttributes.Any(x => x.AttributeType.FullName == "SiliconStudio.Core.AssemblyProcessedAttribute"))
                {
                    OnInfoAction("Assembly has already been processed, skip it.");
                    return true;
                }

                var targetFrameworkAttribute = assemblyDefinition.CustomAttributes
                    .FirstOrDefault(x => x.AttributeType.FullName == typeof(TargetFrameworkAttribute).FullName);
                var targetFramework = targetFrameworkAttribute != null ? (string)targetFrameworkAttribute.ConstructorArguments[0].Value : null;

                // Special handling for MonoAndroid
                // Default frameworkFolder
                var frameworkFolder = Path.Combine(CecilExtensions.ProgramFilesx86(), @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\");

                switch (Platform)
                {
                    case PlatformType.Android:
                    {
                        if (string.IsNullOrEmpty(TargetFramework))
                        {
                            throw new InvalidOperationException("Expecting option target framework for Android");
                        }

                        var monoAndroidPath = Path.Combine(CecilExtensions.ProgramFilesx86(), @"Reference Assemblies\Microsoft\Framework\MonoAndroid");
                        frameworkFolder = Path.Combine(monoAndroidPath, "v1.0");
                        var additionalFrameworkFolder = Path.Combine(monoAndroidPath, TargetFramework);
                        assemblyResolver.AddSearchDirectory(additionalFrameworkFolder);
                        assemblyResolver.AddSearchDirectory(frameworkFolder);
                        break;
                    }

                    case PlatformType.iOS:
                    {
                        if (string.IsNullOrEmpty(TargetFramework))
                        {
                            throw new InvalidOperationException("Expecting option target framework for iOS");
                        }

                        var monoTouchPath = Path.Combine(CecilExtensions.ProgramFilesx86(), @"Reference Assemblies\Microsoft\Framework\Xamarin.iOS");
                        frameworkFolder = Path.Combine(monoTouchPath, "v1.0");
                        var additionalFrameworkFolder = Path.Combine(monoTouchPath, TargetFramework);
                        assemblyResolver.AddSearchDirectory(additionalFrameworkFolder);
                        assemblyResolver.AddSearchDirectory(frameworkFolder);

                        break;
                    }

                    case PlatformType.WindowsStore:
                    {
                        if (string.IsNullOrEmpty(TargetFramework))
                        {
                            throw new InvalidOperationException("Expecting option target framework for WindowsStore");
                        }

                        frameworkFolder = Path.Combine(CecilExtensions.ProgramFilesx86(), @"Reference Assemblies\Microsoft\Framework\.NETCore", TargetFramework);
                        assemblyResolver.AddSearchDirectory(frameworkFolder);

                        // Add path to look for WinRT assemblies (Windows.winmd)
                        var windowsAssemblyPath = Path.Combine(CecilExtensions.ProgramFilesx86(), @"Windows Kits\8.1\References\CommonConfiguration\Neutral\", "Windows.winmd");
                        var windowsAssembly = AssemblyDefinition.ReadAssembly(windowsAssemblyPath, new ReaderParameters { AssemblyResolver = assemblyResolver, ReadSymbols = false });
                        assemblyResolver.Register(windowsAssembly);

                        break;
                    }

                    case PlatformType.WindowsPhone:
                    {
                        if (string.IsNullOrEmpty(TargetFramework))
                        {
                            throw new InvalidOperationException("Expecting option target framework for WindowsPhone");
                        }

                        // Note: v8.1 is hardcoded because we currently receive v4.5.x as TargetFramework (different from TargetPlatformVersion)
                        frameworkFolder = Path.Combine(CecilExtensions.ProgramFilesx86(), @"Reference Assemblies\Microsoft\Framework\WindowsPhoneApp", "v8.1");
                        assemblyResolver.AddSearchDirectory(frameworkFolder);

                        // Add path to look for WinRT assemblies (Windows.winmd)
                        var windowsAssemblyPath = Path.Combine(CecilExtensions.ProgramFilesx86(), @"Windows Phone Kits\8.1\References\CommonConfiguration\Neutral\", "Windows.winmd");
                        var windowsAssembly = AssemblyDefinition.ReadAssembly(windowsAssemblyPath, new ReaderParameters { AssemblyResolver = assemblyResolver, ReadSymbols = false });
                        assemblyResolver.Register(windowsAssembly);

                        break;
                    }
                }

                if (SerializationAssembly)
                {
                    // Resave a first version of assembly with [InteralsVisibleTo] for future serialization assembly.
                    // It will be used by serialization assembly compilation.
                    // It's recommended to do it in the original code to avoid this extra step.

                    var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assemblyDefinition);
                    var stringType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(string).FullName);
                    var internalsVisibleToAttribute = mscorlibAssembly.MainModule.GetTypeResolved(typeof(InternalsVisibleToAttribute).FullName);
                    var serializationAssemblyName = assemblyDefinition.Name.Name + ".Serializers";
                    bool internalsVisibleAlreadyApplied = false;

                    // Check if already applied
                    foreach (var customAttribute in assemblyDefinition.CustomAttributes.Where(x => x.AttributeType.FullName == internalsVisibleToAttribute.FullName))
                    {
                        var assemblyName = (string)customAttribute.ConstructorArguments[0].Value;

                        int publicKeyIndex;
                        if ((publicKeyIndex = assemblyName.IndexOf(", PublicKey=", StringComparison.InvariantCulture)) != -1 || (publicKeyIndex = assemblyName.IndexOf(",PublicKey=", StringComparison.InvariantCulture)) != -1)
                        {
                            assemblyName = assemblyName.Substring(0, publicKeyIndex);
                        }

                        if (assemblyName == serializationAssemblyName)
                        {
                            internalsVisibleAlreadyApplied = true;
                            break;
                        }
                    }

                    if (!internalsVisibleAlreadyApplied)
                    {
                        // Apply public key
                        if (assemblyDefinition.Name.HasPublicKey)
                            serializationAssemblyName += ", PublicKey=" + ByteArrayToString(assemblyDefinition.Name.PublicKey);

                        // Add [InteralsVisibleTo] attribute
                        var internalsVisibleToAttributeCtor = assemblyDefinition.MainModule.Import(internalsVisibleToAttribute.GetConstructors().Single());
                        var internalsVisibleAttribute = new CustomAttribute(internalsVisibleToAttributeCtor)
                        {
                            ConstructorArguments =
                            {
                                new CustomAttributeArgument(assemblyDefinition.MainModule.Import(stringType), serializationAssemblyName)
                            }
                        };
                        assemblyDefinition.CustomAttributes.Add(internalsVisibleAttribute);

                        var assemblyFilePath = assemblyDefinition.MainModule.FullyQualifiedName;
                        if (string.IsNullOrEmpty(assemblyFilePath))
                        {
                            assemblyFilePath = Path.ChangeExtension(Path.GetTempFileName(), ".dll");
                        }

                        // Save updated file
                        assemblyDefinition.Write(assemblyFilePath, new WriterParameters() { WriteSymbols = readWriteSymbols });

                        // Reread file (otherwise it seems Mono Cecil is buggy and generate invalid PDB)
                        assemblyDefinition = AssemblyDefinition.ReadAssembly(assemblyFilePath, new ReaderParameters { AssemblyResolver = assemblyResolver, ReadSymbols = readWriteSymbols });

                        // Check if pdb was actually read
                        readWriteSymbols = assemblyDefinition.MainModule.HasDebugHeader;
                    }
                }

                var assemblyProcessorContext = new AssemblyProcessorContext(assemblyResolver, assemblyDefinition, Platform);

                foreach (var processor in processors)
                    modified = processor.Process(assemblyProcessorContext) || modified;

                // Assembly might have been recreated (i.e. il-repack), so let's use it from now on
                assemblyDefinition = assemblyProcessorContext.Assembly;

                if (modified)
                {
                    // In case assembly has been modified,
                    // add AssemblyProcessedAttribute to assembly so that it doesn't get processed again
                    var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assemblyDefinition);
                    if (mscorlibAssembly == null)
                    {
                        OnErrorAction("Missing mscorlib.dll from assembly");
                        return false;
                    }

                    var attributeType = mscorlibAssembly.MainModule.GetTypeResolved(typeof (Attribute).FullName);
                    var attributeTypeRef = assemblyDefinition.MainModule.Import(attributeType);
                    var attributeCtorRef = assemblyDefinition.MainModule.Import(attributeType.GetConstructors().Single(x => x.Parameters.Count == 0));
                    var voidType = assemblyDefinition.MainModule.Import(mscorlibAssembly.MainModule.GetTypeResolved("System.Void"));

                    // Create custom attribute
                    var assemblyProcessedAttributeType = new TypeDefinition("SiliconStudio.Core", "AssemblyProcessedAttribute", TypeAttributes.BeforeFieldInit | TypeAttributes.AnsiClass | TypeAttributes.AutoClass | TypeAttributes.Public, attributeTypeRef);

                    // Add constructor (call parent constructor)
                    var assemblyProcessedAttributeConstructor = new MethodDefinition(".ctor", MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Public, voidType);
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Call, attributeCtorRef));
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
                    assemblyProcessedAttributeType.Methods.Add(assemblyProcessedAttributeConstructor);

                    // Add AssemblyProcessedAttribute to assembly
                    assemblyDefinition.MainModule.Types.Add(assemblyProcessedAttributeType);
                    assemblyDefinition.CustomAttributes.Add(new CustomAttribute(assemblyProcessedAttributeConstructor));
                }
            }
            catch (Exception e)
            {
                OnErrorAction(e.Message, e);
                return false;
            }

            return true;
        }
コード例 #47
0
ファイル: DispatcherProcessor.cs プロジェクト: vol16bit/xenko
        private ClosureInfo ProcessClosure(AssemblyProcessorContext context, TypeDefinition closureType, TypeReference[] genericParameters)
        {
            ClosureInfo closure;

            if (closures.TryGetValue(closureType, out closure))
            {
                return(closure);
            }

            var closureTypeConstructor = closureType.Methods.FirstOrDefault(x => x.Name == ".ctor");
            var closureGenericType     = closureType.MakeGenericType(genericParameters);

            // Create factory method for pool items
            var factoryMethod = new MethodDefinition("<Factory>", MethodAttributes.HideBySig | MethodAttributes.Private | MethodAttributes.Static, closureGenericType);

            closureType.Methods.Add(factoryMethod);
            factoryMethod.Body.InitLocals = true;
            factoryMethod.Body.Variables.Add(new VariableDefinition(closureGenericType));
            var factoryMethodProcessor = factoryMethod.Body.GetILProcessor();

            // Create and store closure
            factoryMethodProcessor.Emit(OpCodes.Newobj, closureTypeConstructor.MakeGeneric(genericParameters));
            factoryMethodProcessor.Emit(OpCodes.Stloc_0);
            //// Return closure
            factoryMethodProcessor.Emit(OpCodes.Ldloc_0);
            factoryMethodProcessor.Emit(OpCodes.Ret);

            // Create pool field
            var poolField = new FieldDefinition("<pool>", FieldAttributes.Public | FieldAttributes.Static, poolType.MakeGenericType(closureGenericType));

            closureType.Fields.Add(poolField);
            var poolFieldReference = poolField.MakeGeneric(genericParameters);

            // Initialize pool
            var cctor          = GetOrCreateClassConstructor(closureType);
            var ilProcessor2   = cctor.Body.GetILProcessor();
            var retInstruction = cctor.Body.Instructions.FirstOrDefault(x => x.OpCode == OpCodes.Ret);

            ilProcessor2.InsertBefore(retInstruction, ilProcessor2.Create(OpCodes.Ldnull));
            ilProcessor2.InsertBefore(retInstruction, ilProcessor2.Create(OpCodes.Ldftn, factoryMethod.MakeGeneric(genericParameters)));
            ilProcessor2.InsertBefore(retInstruction, ilProcessor2.Create(OpCodes.Newobj, funcConstructor.MakeGeneric(closureGenericType)));
            ilProcessor2.InsertBefore(retInstruction, ilProcessor2.Create(OpCodes.Newobj, poolConstructor.MakeGeneric(closureGenericType)));
            ilProcessor2.InsertBefore(retInstruction, ilProcessor2.Create(OpCodes.Stsfld, poolFieldReference));

            // Implement IPooledClosure
            closureType.Interfaces.Add(new InterfaceImplementation(pooledClosureType));

            // Create reference count field
            var countField = new FieldDefinition("<referenceCount>", FieldAttributes.Public, context.Assembly.MainModule.TypeSystem.Int32);

            closureType.Fields.Add(countField);
            var oountFieldReference = countField.MakeGeneric(genericParameters);

            // Create AddReference method
            var addReferenceMethod = new MethodDefinition("AddReference", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual | MethodAttributes.NewSlot, context.Assembly.MainModule.TypeSystem.Void);
            var ilProcessor4       = addReferenceMethod.Body.GetILProcessor();

            ilProcessor4.Emit(OpCodes.Ldarg_0);
            ilProcessor4.Emit(OpCodes.Ldflda, oountFieldReference);
            ilProcessor4.Emit(OpCodes.Call, interlockedIncrementMethod);
            ilProcessor4.Emit(OpCodes.Pop);
            ilProcessor4.Emit(OpCodes.Ret);
            closureType.Methods.Add(addReferenceMethod);

            // Create Release method
            var releaseMethod = new MethodDefinition("Release", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual | MethodAttributes.NewSlot, context.Assembly.MainModule.TypeSystem.Void);

            ilProcessor4   = releaseMethod.Body.GetILProcessor();
            retInstruction = ilProcessor4.Create(OpCodes.Ret);
            // Check decremented reference count
            ilProcessor4.Emit(OpCodes.Ldarg_0);
            ilProcessor4.Emit(OpCodes.Ldflda, oountFieldReference);
            ilProcessor4.Emit(OpCodes.Call, interlockedDecrementMethod);
            ilProcessor4.Emit(OpCodes.Ldc_I4_0);
            ilProcessor4.Emit(OpCodes.Ceq);
            ilProcessor4.Emit(OpCodes.Brfalse_S, retInstruction);
            // Clear fields
            foreach (var field in closureType.Fields)
            {
                if (field.IsStatic || field.FieldType.IsPrimitive || field == countField)
                {
                    continue;
                }

                ilProcessor4.Emit(OpCodes.Ldarg_0);
                if (field.FieldType.IsValueType)
                {
                    ilProcessor4.Emit(OpCodes.Ldflda, field.MakeGeneric(genericParameters));
                    ilProcessor4.Emit(OpCodes.Initobj, field.FieldType);
                }
                else
                {
                    ilProcessor4.Emit(OpCodes.Ldnull);
                    ilProcessor4.Emit(OpCodes.Stfld, field.MakeGeneric(genericParameters));
                }
            }
            // Release this to pool
            ilProcessor4.Emit(OpCodes.Ldsfld, poolFieldReference);
            ilProcessor4.Emit(OpCodes.Ldarg_0);
            ilProcessor4.Emit(OpCodes.Callvirt, poolReleaseMethod.MakeGeneric(closureGenericType));
            ilProcessor4.Append(retInstruction);
            closureType.Methods.Add(releaseMethod);

            closures.Add(closureType, closure = new ClosureInfo
            {
                FactoryMethod      = factoryMethod,
                AddReferenceMethod = addReferenceMethod,
                ReleaseMethod      = releaseMethod,
                PoolField          = poolField
            });

            return(closure);
        }
コード例 #48
0
ファイル: MonoFixedProcessor.cs プロジェクト: vol16bit/xenko
        public bool Process(AssemblyProcessorContext context)
        {
            if (context.Platform != Core.PlatformType.Android && context.Platform != Core.PlatformType.iOS)
            {
                return(false);
            }

            bool changed = false;

            foreach (var type in context.Assembly.MainModule.GetAllTypes())
            {
                foreach (var method in type.Methods)
                {
                    if (method.Body == null)
                    {
                        continue;
                    }

                    for (var index = 0; index < method.Body.Instructions.Count; index++)
                    {
                        var instruction = method.Body.Instructions[index];
                        if (instruction.OpCode == OpCodes.Conv_U)
                        {
                            VariableDefinition variable = null;

                            // Check if next store is in a pointer variable
                            switch (instruction.Next.OpCode.Code)
                            {
                            case Code.Stloc_0:
                                variable = method.Body.Variables[0];
                                break;

                            case Code.Stloc_1:
                                variable = method.Body.Variables[1];
                                break;

                            case Code.Stloc_2:
                                variable = method.Body.Variables[2];
                                break;

                            case Code.Stloc_3:
                                variable = method.Body.Variables[3];
                                break;

                            case Code.Stloc:
                                variable = (VariableDefinition)instruction.Operand;
                                break;
                            }

                            if (variable != null && variable.VariableType.IsPointer)
                            {
                                // We are in a fixed instruction, let's fix it
                                instruction.OpCode = OpCodes.Conv_I;
                                changed            = true;
                            }
                        }
                    }
                }
            }

            return(changed);
        }
コード例 #49
0
ファイル: DispatcherProcessor.cs プロジェクト: vol16bit/xenko
        private bool ProcessDelegateAllocation(AssemblyProcessorContext context, MethodDefinition method, Instruction delegateAllocationInstruction)
        {
            // The instruction must be a delegate allocation
            // If not, this might be a static delegate, or some unsupported construct
            if (delegateAllocationInstruction.OpCode != OpCodes.Newobj)
            {
                return(false);
            }

            var delegateInstanceConstructor = (MethodReference)delegateAllocationInstruction.Operand;
            var delegateInstanceType        = delegateInstanceConstructor.DeclaringType;

            // The previous instruction pushes the delegate method onto the stack
            var functionPointerInstruction = delegateAllocationInstruction.Previous;

            if (functionPointerInstruction.OpCode != OpCodes.Ldftn)
            {
                return(false);
            }

            var delegateMethod = (MethodReference)functionPointerInstruction.Operand;

            // The previous instruction pushes the target onto the stack
            // If it's the this-parameter, we can create an instance field, and reuse the same delegate
            var loadClosureInstruction = functionPointerInstruction.Previous;

            if (loadClosureInstruction.OpCode == OpCodes.Ldarg_0 && !method.IsStatic)
            {
                // TODO: Handle generic methods/delegates
                // TODO: Handle multiple constructors propertly
                var constructor     = method.DeclaringType.Methods.FirstOrDefault(x => x.Name == ".ctor" && !x.HasParameters);
                var retInstruction3 = constructor?.Body.Instructions.FirstOrDefault(x => x.OpCode == OpCodes.Ret);
                if (retInstruction3 == null)
                {
                    return(false);
                }

                // Create an instance field for the shared delegate
                var sharedDelegateField = new FieldDefinition($"<delegate>{delegateMethod.Name}", FieldAttributes.Private, delegateInstanceType);
                method.DeclaringType.Fields.Add(sharedDelegateField);

                // Create and store the delegate in constructor
                var ilProcessor5 = constructor.Body.GetILProcessor();
                ilProcessor5.InsertBefore(retInstruction3, ilProcessor5.Create(OpCodes.Ldarg_0));
                ilProcessor5.InsertBefore(retInstruction3, ilProcessor5.Create(OpCodes.Ldarg_0));
                ilProcessor5.InsertBefore(retInstruction3, ilProcessor5.Create(OpCodes.Ldftn, delegateMethod));
                ilProcessor5.InsertBefore(retInstruction3, ilProcessor5.Create(OpCodes.Newobj, delegateInstanceConstructor));
                ilProcessor5.InsertBefore(retInstruction3, ilProcessor5.Create(OpCodes.Stfld, sharedDelegateField));

                // Load from field instead of allocating
                var ilProcessor4 = method.Body.GetILProcessor();
                ilProcessor4.Remove(functionPointerInstruction);
                ilProcessor4.Replace(delegateAllocationInstruction, ilProcessor4.Create(OpCodes.Ldfld, sharedDelegateField));

                return(true);
            }

            // If the target is a compiler generated closure, we only handle local variable load instructions
            int    variableIndex;
            OpCode storeOpCode;

            if (!TryGetStoreOpcode(loadClosureInstruction, out storeOpCode, out variableIndex))
            {
                return(false);
            }

            // Find the instruction that stores the closure variable
            var storeClosureInstruction      = loadClosureInstruction.Previous;
            VariableReference closureVarible = null;

            while (storeClosureInstruction != null)
            {
                closureVarible = storeClosureInstruction.Operand as VariableReference;
                if (storeClosureInstruction.OpCode == storeOpCode && (closureVarible == null || variableIndex == closureVarible.Index))
                {
                    break;
                }

                storeClosureInstruction = storeClosureInstruction.Previous;
            }
            if (storeClosureInstruction == null)
            {
                return(false);
            }

            var closureInstanceType = method.Body.Variables[variableIndex].VariableType;
            var closureType         = closureInstanceType.Resolve();
            var genericParameters   = closureType.GenericParameters.Cast <TypeReference>().ToArray();

            // Patch closure
            var closure = ProcessClosure(context, closureType, genericParameters);

            // Create delegate field
            var delegateFieldType = ChangeGenericArguments(context, delegateInstanceType, closureInstanceType);
            var delegateField     = new FieldDefinition($"<delegate>{delegateMethod.Name}", FieldAttributes.Public, delegateFieldType);

            closureType.Fields.Add(delegateField);
            var localDelegateFieldInstance = delegateField.MakeGeneric(genericParameters);

            // Initialize delegate field (the closure instance (local 0) is already on the stack)
            var delegateConstructorInstance = (MethodReference)delegateAllocationInstruction.Operand;
            var delegateGenericArguments    = (delegateFieldType as GenericInstanceType)?.GenericArguments.ToArray() ?? new TypeReference[0];
            var genericDelegateConstructor  = context.Assembly.MainModule.ImportReference(delegateConstructorInstance.Resolve()).MakeGeneric(delegateGenericArguments);

            var methodInstance = (MethodReference)functionPointerInstruction.Operand;
            var genericMethod  = methodInstance.Resolve().MakeGeneric(closureType.GenericParameters.ToArray());

            if (methodInstance is GenericInstanceMethod)
            {
                throw new NotImplementedException();
            }

            var ilProcessor3      = closure.FactoryMethod.Body.GetILProcessor();
            var returnInstruction = ilProcessor3.Body.Instructions.FirstOrDefault(x => x.OpCode == OpCodes.Ret);

            ilProcessor3.InsertBefore(returnInstruction, ilProcessor3.Create(OpCodes.Ldloc_0));
            ilProcessor3.InsertBefore(returnInstruction, ilProcessor3.Create(OpCodes.Ldftn, genericMethod));
            ilProcessor3.InsertBefore(returnInstruction, ilProcessor3.Create(OpCodes.Newobj, genericDelegateConstructor));
            ilProcessor3.InsertBefore(returnInstruction, ilProcessor3.Create(OpCodes.Stfld, localDelegateFieldInstance));
            ilProcessor3.InsertBefore(returnInstruction, ilProcessor3.Create(OpCodes.Ldloc_0));

            var ilProcessor = method.Body.GetILProcessor();

            // Retrieve from pool
            var closureGenericArguments = (closureInstanceType as GenericInstanceType)?.GenericArguments.ToArray() ?? new TypeReference[0];
            var closureAllocation       = storeClosureInstruction.Previous;

            if (closureAllocation.OpCode == OpCodes.Newobj)
            {
                // Retrieve closure from pool, instead of allocating
                var acquireClosure = ilProcessor.Create(OpCodes.Callvirt, poolAcquireMethod.MakeGeneric(closureInstanceType));
                ilProcessor.InsertAfter(closureAllocation, acquireClosure);
                ilProcessor.InsertAfter(closureAllocation, ilProcessor.Create(OpCodes.Ldsfld, closure.PoolField.MakeGeneric(closureGenericArguments)));
                closureAllocation.OpCode  = OpCodes.Nop; // Change to Nop instead of removing it, as this instruction might be reference somewhere?
                closureAllocation.Operand = null;

                // Add a reference
                ilProcessor.InsertAfter(storeClosureInstruction, ilProcessor.Create(OpCodes.Callvirt, closure.AddReferenceMethod.MakeGeneric(closureGenericArguments)));
                ilProcessor.InsertAfter(storeClosureInstruction, closureVarible == null ? ilProcessor.Create(loadClosureInstruction.OpCode) : ilProcessor.Create(loadClosureInstruction.OpCode, closureVarible.Resolve()));

                // TODO: Multiple returns + try/finally
                // Release reference
                var retInstructions = method.Body.Instructions.Where(x => x.OpCode == OpCodes.Ret).ToArray();

                Instruction beforeReturn = closureVarible == null?ilProcessor.Create(loadClosureInstruction.OpCode) : ilProcessor.Create(loadClosureInstruction.OpCode, closureVarible.Resolve());

                Instruction newReturnInstruction = ilProcessor.Create(OpCodes.Ret);
                ilProcessor.Append(beforeReturn);
                ilProcessor.Append(ilProcessor.Create(OpCodes.Ldnull));
                ilProcessor.Append(ilProcessor.Create(OpCodes.Beq, newReturnInstruction));
                ilProcessor.Append(closureVarible == null ? ilProcessor.Create(loadClosureInstruction.OpCode) : ilProcessor.Create(loadClosureInstruction.OpCode, closureVarible.Resolve()));
                ilProcessor.Append(ilProcessor.Create(OpCodes.Callvirt, closure.ReleaseMethod.MakeGeneric(closureGenericArguments)));
                ilProcessor.Append(newReturnInstruction);

                foreach (var retInstruction2 in retInstructions)
                {
                    retInstruction2.OpCode  = OpCodes.Br;
                    retInstruction2.Operand = beforeReturn;
                }
            }

            // Get delegate from closure, instead of allocating
            ilProcessor.Remove(functionPointerInstruction);
            ilProcessor.Replace(delegateAllocationInstruction, ilProcessor.Create(OpCodes.Ldfld, delegateField.MakeGeneric(closureGenericArguments))); // Closure object is already on the stack

            return(true);
        }