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(MethodSignature other)
317 return Util.ArrayEquals(other.parameterTypes, parameterTypes);
320 internal bool MatchParameterTypes(Type[] types)
322 return Util.ArrayEquals(types, parameterTypes);
325 internal override void WriteSig(ModuleBuilder module, ByteBuffer bb)
327 WriteSigImpl(module, bb, parameterTypes.Length);
330 internal void WriteMethodRefSig(ModuleBuilder module, ByteBuffer bb, Type[] optionalParameterTypes, CustomModifiers[] customModifiers)
332 WriteSigImpl(module, bb, parameterTypes.Length + optionalParameterTypes.Length);
333 if (optionalParameterTypes.Length > 0)
336 for (int i = 0; i < optionalParameterTypes.Length; i++)
338 WriteCustomModifiers(module, bb, Util.NullSafeElementAt(customModifiers, i));
339 WriteType(module, bb, optionalParameterTypes[i]);
344 private void WriteSigImpl(ModuleBuilder module, ByteBuffer bb, int parameterCount)
347 if ((callingConvention & CallingConventions.Any) == CallingConventions.VarArgs)
349 Debug.Assert(genericParamCount == 0);
352 else if (genericParamCount > 0)
360 if ((callingConvention & CallingConventions.HasThis) != 0)
364 if ((callingConvention & CallingConventions.ExplicitThis) != 0)
366 first |= EXPLICITTHIS;
369 if (genericParamCount > 0)
371 bb.WriteCompressedInt(genericParamCount);
373 bb.WriteCompressedInt(parameterCount);
375 WriteCustomModifiers(module, bb, modifiers.GetReturnTypeCustomModifiers());
376 WriteType(module, bb, returnType);
378 for (int i = 0; i < parameterTypes.Length; i++)
380 WriteCustomModifiers(module, bb, modifiers.GetParameterCustomModifiers(i));
381 WriteType(module, bb, parameterTypes[i]);
386 struct PackedCustomModifiers
388 // element 0 is the return type, the rest are the parameters
389 private readonly CustomModifiers[] customModifiers;
391 private PackedCustomModifiers(CustomModifiers[] customModifiers)
393 this.customModifiers = customModifiers;
396 public override int GetHashCode()
398 return Util.GetHashCode(customModifiers);
401 public override bool Equals(object obj)
403 PackedCustomModifiers? other = obj as PackedCustomModifiers?;
404 return other != null && Equals(other.Value);
407 internal bool Equals(PackedCustomModifiers other)
409 return Util.ArrayEquals(customModifiers, other.customModifiers);
412 internal CustomModifiers GetReturnTypeCustomModifiers()
414 if (customModifiers == null)
416 return new CustomModifiers();
418 return customModifiers[0];
421 internal CustomModifiers GetParameterCustomModifiers(int index)
423 if (customModifiers == null)
425 return new CustomModifiers();
427 return customModifiers[index + 1];
430 internal PackedCustomModifiers Bind(IGenericBinder binder)
432 if (customModifiers == null)
434 return new PackedCustomModifiers();
436 CustomModifiers[] expanded = new CustomModifiers[customModifiers.Length];
437 for (int i = 0; i < customModifiers.Length; i++)
439 expanded[i] = customModifiers[i].Bind(binder);
441 return new PackedCustomModifiers(expanded);
444 // this method make a copy of the incoming arrays (where necessary) and returns a normalized modifiers array
445 internal static PackedCustomModifiers CreateFromExternal(Type[] returnOptional, Type[] returnRequired, Type[][] parameterOptional, Type[][] parameterRequired, int parameterCount)
447 CustomModifiers[] modifiers = null;
448 Pack(ref modifiers, 0, CustomModifiers.FromReqOpt(returnRequired, returnOptional), parameterCount + 1);
449 for (int i = 0; i < parameterCount; i++)
451 Pack(ref modifiers, i + 1, CustomModifiers.FromReqOpt(Util.NullSafeElementAt(parameterRequired, i), Util.NullSafeElementAt(parameterOptional, i)), parameterCount + 1);
453 return new PackedCustomModifiers(modifiers);
456 internal static PackedCustomModifiers CreateFromExternal(CustomModifiers returnTypeCustomModifiers, CustomModifiers[] parameterTypeCustomModifiers, int parameterCount)
458 CustomModifiers[] customModifiers = null;
459 Pack(ref customModifiers, 0, returnTypeCustomModifiers, parameterCount + 1);
460 if (parameterTypeCustomModifiers != null)
462 for (int i = 0; i < parameterCount; i++)
464 Pack(ref customModifiers, i + 1, parameterTypeCustomModifiers[i], parameterCount + 1);
467 return new PackedCustomModifiers(customModifiers);
470 internal static PackedCustomModifiers Wrap(CustomModifiers[] modifiers)
472 return new PackedCustomModifiers(modifiers);
475 internal static void Pack(ref CustomModifiers[] array, int index, CustomModifiers mods, int count)
481 array = new CustomModifiers[count];