Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
AsyncBridgeProcessor.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.Linq;
5 using System.Runtime.CompilerServices;
6 using Mono.Cecil;
7 using Mono.Cecil.Rocks;
8 using Mono.Collections.Generic;
9 
10 namespace SiliconStudio.AssemblyProcessor
11 {
12  /// <summary>
13  /// Makes the assembly use AsyncBridge instead of mscorlib for async.
14  /// </summary>
16  {
17  private AssemblyDefinition assembly;
18 
19  private AssemblyDefinition asyncBridgeAssembly;
20 
21  public bool Process(AssemblyProcessorContext context)
22  {
23  this.assembly = context.Assembly;
24  asyncBridgeAssembly = context.AssemblyResolver.Resolve("AsyncBridge");
25 
26  assembly.MainModule.AssemblyReferences.Add(asyncBridgeAssembly.Name);
27 
28  foreach (var type in assembly.MainModule.Types)
29  {
30  ProcessType(type);
31  }
32 
33  return true;
34  }
35 
36  private TypeReference ProcessTypeReference(TypeReference type, IGenericParameterProvider owner)
37  {
38  if (type == null)
39  return null;
40 
41  // ref types
42  if (type is ByReferenceType)
43  {
44  var elementType = ProcessTypeReference(type.GetElementType(), owner);
45  if (elementType != type.GetElementType())
46  type = new ByReferenceType(elementType);
47  return type;
48  }
49 
50  // Generic MVar/Var
51  if (type is GenericParameter)
52  {
53  var genericParameter = (GenericParameter)type;
54  if ((genericParameter.MetadataType == MetadataType.MVar
55  || genericParameter.MetadataType == MetadataType.Var) && genericParameter.Owner is MethodReference)
56  {
57  if (genericParameter.Owner != null && owner != null)
58  {
59  return owner.GenericParameters.Concat(genericParameter.Owner.GenericParameters).First(x => x.Name == type.Name);
60  }
61  }
62  return type;
63  }
64 
65  // Is it an async-related type?
66  var asyncBridgeType = asyncBridgeAssembly.MainModule.GetTypeResolved(type.Namespace, type.Name);
67  if (asyncBridgeType == null)
68  return type;
69 
70  // First work on inner TypeReference if there is a GenericInstanceType around it.
71  var genericInstanceType = type as GenericInstanceType;
72  if (genericInstanceType != null)
73  {
74  type = genericInstanceType.ElementType;
75  }
76 
77  var newType = assembly.MainModule.Import(new TypeReference(type.Namespace, type.Name, asyncBridgeAssembly.MainModule, asyncBridgeAssembly.Name, type.IsValueType));
78 
79  for (int i = 0; i < type.GenericParameters.Count; ++i)
80  {
81  newType.GenericParameters.Add(new GenericParameter(type.GenericParameters[i].Name, newType));
82  foreach (var constraint in type.GenericParameters[i].Constraints)
83  newType.GenericParameters[i].Constraints.Add(ProcessTypeReference(constraint, newType));
84  }
85 
86  if (genericInstanceType != null)
87  {
88  var newGenericType = new GenericInstanceType(newType);
89  foreach (var genericArgument in genericInstanceType.GenericArguments)
90  {
91  newGenericType.GenericArguments.Add(ProcessTypeReference(genericArgument, newGenericType));
92  }
93  newType = newGenericType;
94  }
95 
96  return newType;
97  }
98 
99  private FieldReference ProcessFieldReference(FieldReference field)
100  {
101  if (field == null)
102  return null;
103 
104  field.FieldType = ProcessTypeReference(field.FieldType, field.DeclaringType);
105  return field;
106  }
107 
108  private MethodReference ProcessMethodReference(MethodReference method)
109  {
110  if (method == null)
111  return null;
112 
113  var declaringType = ProcessTypeReference(method.DeclaringType, null);
114  if (declaringType == method.DeclaringType)
115  {
116  return method;
117  }
118 
119  var genericInstanceMethod = method as GenericInstanceMethod;
120  if (genericInstanceMethod != null)
121  {
122  method = genericInstanceMethod.ElementMethod;
123  }
124 
125  var newMethod = new MethodReference(method.Name, assembly.MainModule.Import(typeof(void)), declaringType);
126  newMethod.HasThis = method.HasThis;
127  newMethod.ExplicitThis = method.ExplicitThis;
128  newMethod.CallingConvention = method.CallingConvention;
129  newMethod.MethodReturnType = method.MethodReturnType;
130  newMethod.ReturnType = ProcessTypeReference(method.ReturnType, newMethod);
131 
132  for (int i = 0; i < method.GenericParameters.Count; ++i)
133  {
134  newMethod.GenericParameters.Add(new GenericParameter(method.GenericParameters[i].Name, newMethod));
135  foreach (var constraint in method.GenericParameters[i].Constraints)
136  newMethod.GenericParameters[i].Constraints.Add(ProcessTypeReference(constraint, newMethod));
137  }
138 
139  for (int i = 0; i < method.Parameters.Count; ++i)
140  {
141  var parameterDefinition = new ParameterDefinition(method.Parameters[i].Name, method.Parameters[i].Attributes, ProcessTypeReference(method.Parameters[i].ParameterType, newMethod));
142  newMethod.Parameters.Add(parameterDefinition);
143  }
144 
145  if (genericInstanceMethod != null)
146  {
147  var newGenericMethod = new GenericInstanceMethod(newMethod);
148  foreach (var genericArgument in genericInstanceMethod.GenericArguments)
149  {
150  newGenericMethod.GenericArguments.Add(ProcessTypeReference(genericArgument, newMethod));
151  }
152  newMethod = newGenericMethod;
153  }
154 
155  return newMethod;
156  }
157 
158  private void ProcessType(TypeDefinition type)
159  {
160  foreach (var nestedType in type.NestedTypes)
161  {
162  ProcessType(nestedType);
163  }
164 
165  type.BaseType = ProcessTypeReference(type.BaseType, null);
166 
167  for (int i = 0; i < type.Interfaces.Count; ++i)
168  {
169  type.Interfaces[i] = ProcessTypeReference(type.Interfaces[i], null);
170  }
171 
172  foreach (var field in type.Fields)
173  {
174  field.FieldType = ProcessTypeReference(field.FieldType, null);
175  }
176 
177  foreach (var property in type.Properties)
178  {
179  property.PropertyType = ProcessTypeReference(property.PropertyType, null);
180  }
181 
182  foreach (var method in type.Methods)
183  {
184  ProcessMethod(method);
185  }
186 
187  foreach (var attribute in type.CustomAttributes)
188  {
189  attribute.Constructor = ProcessMethodReference(attribute.Constructor);
190  }
191  }
192 
193  private void ProcessMethod(MethodDefinition method)
194  {
195  for (int i = 0; i < method.Overrides.Count; ++i)
196  {
197  method.Overrides[i] = ProcessMethodReference(method.Overrides[i]);
198  }
199 
200  foreach (var parameter in method.Parameters)
201  {
202  parameter.ParameterType = ProcessTypeReference(parameter.ParameterType, null);
203  }
204 
205  foreach (var attribute in method.CustomAttributes)
206  {
207  attribute.Constructor = ProcessMethodReference(attribute.Constructor);
208  }
209 
210  var methodBody = method.Body;
211 
212  if (methodBody == null)
213  return;
214 
215  foreach (var variable in methodBody.Variables)
216  {
217  variable.VariableType = ProcessTypeReference(variable.VariableType, null);
218  }
219 
220  foreach (var instruction in methodBody.Instructions)
221  {
222  if (instruction.Operand == null)
223  continue;
224 
225  if (instruction.Operand is TypeReference)
226  instruction.Operand = ProcessTypeReference((TypeReference)instruction.Operand, null);
227  else if (instruction.Operand is MethodReference)
228  instruction.Operand = ProcessMethodReference((MethodReference)instruction.Operand);
229  else if (instruction.Operand is FieldReference)
230  instruction.Operand = ProcessFieldReference((FieldReference)instruction.Operand);
231  }
232  }
233  }
234 }
Makes the assembly use AsyncBridge instead of mscorlib for async.
bool Process(AssemblyProcessorContext context)