2 Copyright (C) 2009-2011 Jeroen Frijters
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
25 using System.Collections.Generic;
26 using System.Diagnostics;
27 using IKVM.Reflection.Reader;
28 using IKVM.Reflection.Writer;
29 using IKVM.Reflection.Emit;
31 namespace IKVM.Reflection
33 sealed class MethodSignature : Signature
35 private readonly Type returnType;
36 private readonly Type[] parameterTypes;
37 private readonly PackedCustomModifiers modifiers;
38 private readonly CallingConventions callingConvention;
39 private readonly int genericParamCount;
41 internal MethodSignature(Type returnType, Type[] parameterTypes, PackedCustomModifiers modifiers, CallingConventions callingConvention, int genericParamCount)
43 this.returnType = returnType;
44 this.parameterTypes = parameterTypes;
45 this.modifiers = modifiers;
46 this.callingConvention = callingConvention;
47 this.genericParamCount = genericParamCount;
50 public override bool Equals(object obj)
52 MethodSignature other = obj as MethodSignature;
54 && other.callingConvention == callingConvention
55 && other.genericParamCount == genericParamCount
56 && other.returnType.Equals(returnType)
57 && Util.ArrayEquals(other.parameterTypes, parameterTypes)
58 && other.modifiers.Equals(modifiers);
61 public override int GetHashCode()
63 return genericParamCount ^ 77 * (int)callingConvention
64 ^ 3 * returnType.GetHashCode()
65 ^ Util.GetHashCode(parameterTypes) * 5
66 ^ modifiers.GetHashCode() * 55;
69 private sealed class UnboundGenericMethodContext : IGenericContext
71 private readonly IGenericContext original;
73 internal UnboundGenericMethodContext(IGenericContext original)
75 this.original = original;
78 public Type GetGenericTypeArgument(int index)
80 return original.GetGenericTypeArgument(index);
83 public Type GetGenericMethodArgument(int index)
85 return UnboundGenericMethodParameter.Make(index);
89 internal static MethodSignature ReadSig(ModuleReader module, ByteReader br, IGenericContext context)
91 CallingConventions callingConvention;
92 int genericParamCount;
94 Type[] parameterTypes;
95 byte flags = br.ReadByte();
99 callingConvention = CallingConventions.Standard;
102 callingConvention = CallingConventions.VarArgs;
105 throw new BadImageFormatException();
107 if ((flags & HASTHIS) != 0)
109 callingConvention |= CallingConventions.HasThis;
111 if ((flags & EXPLICITTHIS) != 0)
113 callingConvention |= CallingConventions.ExplicitThis;
115 genericParamCount = 0;
116 if ((flags & GENERIC) != 0)
118 genericParamCount = br.ReadCompressedInt();
119 context = new UnboundGenericMethodContext(context);
121 int paramCount = br.ReadCompressedInt();
122 CustomModifiers[] modifiers = null;
123 PackedCustomModifiers.Pack(ref modifiers, 0, CustomModifiers.Read(module, br, context), paramCount + 1);
124 returnType = ReadRetType(module, br, context);
125 parameterTypes = new Type[paramCount];
126 for (int i = 0; i < parameterTypes.Length; i++)
128 if ((callingConvention & CallingConventions.VarArgs) != 0 && br.PeekByte() == SENTINEL)
130 Array.Resize(ref parameterTypes, i);
131 if (modifiers != null)
133 Array.Resize(ref modifiers, i + 1);
137 PackedCustomModifiers.Pack(ref modifiers, i + 1, CustomModifiers.Read(module, br, context), paramCount + 1);
138 parameterTypes[i] = ReadParam(module, br, context);
140 return new MethodSignature(returnType, parameterTypes, PackedCustomModifiers.Wrap(modifiers), callingConvention, genericParamCount);
143 internal static __StandAloneMethodSig ReadStandAloneMethodSig(ModuleReader module, ByteReader br, IGenericContext context)
145 CallingConventions callingConvention = 0;
146 System.Runtime.InteropServices.CallingConvention unmanagedCallingConvention = 0;
148 byte flags = br.ReadByte();
152 callingConvention = CallingConventions.Standard;
156 unmanagedCallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl;
159 case 0x02: // STDCALL
160 unmanagedCallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall;
163 case 0x03: // THISCALL
164 unmanagedCallingConvention = System.Runtime.InteropServices.CallingConvention.ThisCall;
167 case 0x04: // FASTCALL
168 unmanagedCallingConvention = System.Runtime.InteropServices.CallingConvention.FastCall;
172 callingConvention = CallingConventions.VarArgs;
176 throw new BadImageFormatException();
178 if ((flags & HASTHIS) != 0)
180 callingConvention |= CallingConventions.HasThis;
182 if ((flags & EXPLICITTHIS) != 0)
184 callingConvention |= CallingConventions.ExplicitThis;
186 if ((flags & GENERIC) != 0)
188 throw new BadImageFormatException();
190 int paramCount = br.ReadCompressedInt();
191 CustomModifiers[] customModifiers = null;
192 PackedCustomModifiers.Pack(ref customModifiers, 0, CustomModifiers.Read(module, br, context), paramCount + 1);
193 Type returnType = ReadRetType(module, br, context);
194 List<Type> parameterTypes = new List<Type>();
195 List<Type> optionalParameterTypes = new List<Type>();
196 List<Type> curr = parameterTypes;
197 for (int i = 0; i < paramCount; i++)
199 if (br.PeekByte() == SENTINEL)
202 curr = optionalParameterTypes;
204 PackedCustomModifiers.Pack(ref customModifiers, i + 1, CustomModifiers.Read(module, br, context), paramCount + 1);
205 curr.Add(ReadParam(module, br, context));
207 return new __StandAloneMethodSig(unmanaged, unmanagedCallingConvention, callingConvention, returnType, parameterTypes.ToArray(), optionalParameterTypes.ToArray(), PackedCustomModifiers.Wrap(customModifiers));
210 internal int GetParameterCount()
212 return parameterTypes.Length;
215 internal Type GetParameterType(int index)
217 return parameterTypes[index];
220 internal Type GetReturnType(IGenericBinder binder)
222 return returnType.BindTypeParameters(binder);
225 internal CustomModifiers GetReturnTypeCustomModifiers(IGenericBinder binder)
227 return modifiers.GetReturnTypeCustomModifiers().Bind(binder);
230 internal Type GetParameterType(IGenericBinder binder, int index)
232 return parameterTypes[index].BindTypeParameters(binder);
235 internal CustomModifiers GetParameterCustomModifiers(IGenericBinder binder, int index)
237 return modifiers.GetParameterCustomModifiers(index).Bind(binder);
240 internal CallingConventions CallingConvention
242 get { return callingConvention; }
245 internal int GenericParameterCount
247 get { return genericParamCount; }
250 private sealed class Binder : IGenericBinder
252 private readonly Type declaringType;
253 private readonly Type[] methodArgs;
255 internal Binder(Type declaringType, Type[] methodArgs)
257 this.declaringType = declaringType;
258 this.methodArgs = methodArgs;
261 public Type BindTypeParameter(Type type)
263 return declaringType.GetGenericTypeArgument(type.GenericParameterPosition);
266 public Type BindMethodParameter(Type type)
268 if (methodArgs == null)
272 return methodArgs[type.GenericParameterPosition];
276 internal MethodSignature Bind(Type type, Type[] methodArgs)
278 Binder binder = new Binder(type, methodArgs);
279 return new MethodSignature(returnType.BindTypeParameters(binder),
280 BindTypeParameters(binder, parameterTypes),
281 modifiers.Bind(binder),
282 callingConvention, genericParamCount);
285 private sealed class Unbinder : IGenericBinder
287 internal static readonly Unbinder Instance = new Unbinder();
293 public Type BindTypeParameter(Type type)
298 public Type BindMethodParameter(Type type)
300 return UnboundGenericMethodParameter.Make(type.GenericParameterPosition);
304 internal static MethodSignature MakeFromBuilder(Type returnType, Type[] parameterTypes, PackedCustomModifiers modifiers, CallingConventions callingConvention, int genericParamCount)
306 if (genericParamCount > 0)
308 returnType = returnType.BindTypeParameters(Unbinder.Instance);
309 parameterTypes = BindTypeParameters(Unbinder.Instance, parameterTypes);
310 modifiers = modifiers.Bind(Unbinder.Instance);
312 return new MethodSignature(returnType, parameterTypes, modifiers, callingConvention, genericParamCount);
315 internal bool MatchParameterTypes(Type[] types)
317 if (types == parameterTypes)
323 return parameterTypes.Length == 0;
325 if (parameterTypes == null)
327 return types.Length == 0;
329 if (types.Length == parameterTypes.Length)
331 for (int i = 0; i < types.Length; i++)
333 if (!Util.TypeEquals(types[i], parameterTypes[i]))
343 internal override void WriteSig(ModuleBuilder module, ByteBuffer bb)
345 WriteSigImpl(module, bb, parameterTypes.Length);
348 internal void WriteMethodRefSig(ModuleBuilder module, ByteBuffer bb, Type[] optionalParameterTypes, CustomModifiers[] customModifiers)
350 WriteSigImpl(module, bb, parameterTypes.Length + optionalParameterTypes.Length);
351 if (optionalParameterTypes.Length > 0)
354 for (int i = 0; i < optionalParameterTypes.Length; i++)
356 WriteCustomModifiers(module, bb, Util.NullSafeElementAt(customModifiers, i));
357 WriteType(module, bb, optionalParameterTypes[i]);
362 private void WriteSigImpl(ModuleBuilder module, ByteBuffer bb, int parameterCount)
365 if ((callingConvention & CallingConventions.Any) == CallingConventions.VarArgs)
367 Debug.Assert(genericParamCount == 0);
370 else if (genericParamCount > 0)
378 if ((callingConvention & CallingConventions.HasThis) != 0)
382 if ((callingConvention & CallingConventions.ExplicitThis) != 0)
384 first |= EXPLICITTHIS;
387 if (genericParamCount > 0)
389 bb.WriteCompressedInt(genericParamCount);
391 bb.WriteCompressedInt(parameterCount);
393 WriteCustomModifiers(module, bb, modifiers.GetReturnTypeCustomModifiers());
394 WriteType(module, bb, returnType);
396 for (int i = 0; i < parameterTypes.Length; i++)
398 WriteCustomModifiers(module, bb, modifiers.GetParameterCustomModifiers(i));
399 WriteType(module, bb, parameterTypes[i]);
404 struct PackedCustomModifiers
406 // element 0 is the return type, the rest are the parameters
407 private readonly CustomModifiers[] customModifiers;
409 private PackedCustomModifiers(CustomModifiers[] customModifiers)
411 this.customModifiers = customModifiers;
414 public override int GetHashCode()
416 return Util.GetHashCode(customModifiers);
419 public override bool Equals(object obj)
421 PackedCustomModifiers? other = obj as PackedCustomModifiers?;
422 return other != null && Equals(other.Value);
425 internal bool Equals(PackedCustomModifiers other)
427 return Util.ArrayEquals(customModifiers, other.customModifiers);
430 internal CustomModifiers GetReturnTypeCustomModifiers()
432 if (customModifiers == null)
434 return new CustomModifiers();
436 return customModifiers[0];
439 internal CustomModifiers GetParameterCustomModifiers(int index)
441 if (customModifiers == null)
443 return new CustomModifiers();
445 return customModifiers[index + 1];
448 internal PackedCustomModifiers Bind(IGenericBinder binder)
450 if (customModifiers == null)
452 return new PackedCustomModifiers();
454 CustomModifiers[] expanded = new CustomModifiers[customModifiers.Length];
455 for (int i = 0; i < customModifiers.Length; i++)
457 expanded[i] = customModifiers[i].Bind(binder);
459 return new PackedCustomModifiers(expanded);
462 // this method make a copy of the incoming arrays (where necessary) and returns a normalized modifiers array
463 internal static PackedCustomModifiers CreateFromExternal(Type[] returnOptional, Type[] returnRequired, Type[][] parameterOptional, Type[][] parameterRequired, int parameterCount)
465 CustomModifiers[] modifiers = null;
466 Pack(ref modifiers, 0, CustomModifiers.FromReqOpt(returnRequired, returnOptional), parameterCount + 1);
467 for (int i = 0; i < parameterCount; i++)
469 Pack(ref modifiers, i + 1, CustomModifiers.FromReqOpt(Util.NullSafeElementAt(parameterRequired, i), Util.NullSafeElementAt(parameterOptional, i)), parameterCount + 1);
471 return new PackedCustomModifiers(modifiers);
474 internal static PackedCustomModifiers CreateFromExternal(CustomModifiers returnTypeCustomModifiers, CustomModifiers[] parameterTypeCustomModifiers, int parameterCount)
476 CustomModifiers[] customModifiers = null;
477 Pack(ref customModifiers, 0, returnTypeCustomModifiers, parameterCount + 1);
478 if (parameterTypeCustomModifiers != null)
480 for (int i = 0; i < parameterCount; i++)
482 Pack(ref customModifiers, i + 1, parameterTypeCustomModifiers[i], parameterCount + 1);
485 return new PackedCustomModifiers(customModifiers);
488 internal static PackedCustomModifiers Wrap(CustomModifiers[] modifiers)
490 return new PackedCustomModifiers(modifiers);
493 internal static void Pack(ref CustomModifiers[] array, int index, CustomModifiers mods, int count)
499 array = new CustomModifiers[count];