Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
ModuleInitializerProcessor.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 using Mono.Cecil;
7 using Mono.Cecil.Cil;
8 using Mono.Cecil.Rocks;
9 using SiliconStudio.AssemblyProcessor;
10 
11 namespace SiliconStudio.AssemblyProcessor
12 {
14  {
15  public bool Process(AssemblyProcessorContext context)
16  {
17  var assembly = context.Assembly;
18  var moduleInitializers = new List<MethodReference>();
19 
20  // Generate a module initializer for all types, including nested types
21  foreach (var type in assembly.EnumerateTypes())
22  {
23  foreach (var method in type.Methods)
24  {
25  if (method.CustomAttributes.Any(x => x.AttributeType.FullName == "SiliconStudio.Core.ModuleInitializerAttribute"))
26  {
27  moduleInitializers.Add(method);
28  }
29  }
30  }
31 
32  if (moduleInitializers.Count == 0)
33  return false;
34 
35  // Get or create module static constructor
36  Instruction returnInstruction;
37  var staticConstructor = OpenModuleConstructor(assembly, out returnInstruction);
38 
39  var il = staticConstructor.Body.GetILProcessor();
40 
41  var newReturnInstruction = Instruction.Create(returnInstruction.OpCode);
42  newReturnInstruction.Operand = returnInstruction.Operand;
43 
44  returnInstruction.OpCode = OpCodes.Nop;
45  returnInstruction.Operand = null;
46 
47  staticConstructor.Body.SimplifyMacros();
48  foreach (var moduleInitializer in moduleInitializers)
49  {
50  il.Append(Instruction.Create(OpCodes.Call, moduleInitializer));
51  }
52  il.Append(newReturnInstruction);
53  staticConstructor.Body.OptimizeMacros();
54 
55  return true;
56  }
57 
58  public static MethodDefinition OpenModuleConstructor(AssemblyDefinition assembly, out Instruction returnInstruction)
59  {
60  var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assembly);
61  if (mscorlibAssembly == null)
62  throw new InvalidOperationException("Missing mscorlib.dll from assembly");
63 
64  // Get or create module static constructor
65  var voidType = assembly.MainModule.Import(mscorlibAssembly.MainModule.GetTypeResolved(typeof(void).FullName));
66  var moduleClass = assembly.MainModule.Types.First(t => t.Name == "<Module>");
67  var staticConstructor = moduleClass.GetStaticConstructor();
68  if (staticConstructor == null)
69  {
70  staticConstructor = new MethodDefinition(".cctor",
71  MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
72  voidType);
73  staticConstructor.Body.GetILProcessor().Append(Instruction.Create(OpCodes.Ret));
74 
75  moduleClass.Methods.Add(staticConstructor);
76  }
77  returnInstruction = staticConstructor.Body.Instructions.Last();
78 
79  return staticConstructor;
80  }
81  }
82 }
Mono.Cecil.MethodAttributes MethodAttributes
static MethodDefinition OpenModuleConstructor(AssemblyDefinition assembly, out Instruction returnInstruction)