2 Copyright (C) 2008-2012 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.Runtime.InteropServices;
27 using IKVM.Reflection;
28 using IKVM.Reflection.Writer;
30 namespace IKVM.Reflection.Emit
32 public abstract class SignatureHelper
34 protected readonly byte type;
35 protected ushort paramCount;
37 sealed class Lazy : SignatureHelper
39 private readonly List<Type> args = new List<Type>();
41 internal Lazy(byte type)
46 internal override Type ReturnType
48 get { return args[0]; }
51 public override byte[] GetSignature()
53 throw new NotSupportedException();
56 internal override ByteBuffer GetSignature(ModuleBuilder module)
58 ByteBuffer bb = new ByteBuffer(16);
59 Signature.WriteSignatureHelper(module, bb, type, paramCount, args);
63 public override void AddSentinel()
65 args.Add(MarkerType.Sentinel);
68 public override void __AddArgument(Type argument, bool pinned, CustomModifiers customModifiers)
72 args.Add(MarkerType.Pinned);
74 foreach (CustomModifiers.Entry mod in customModifiers)
76 args.Add(mod.IsRequired ? MarkerType.ModReq : MarkerType.ModOpt);
84 sealed class Eager : SignatureHelper
86 private readonly ModuleBuilder module;
87 private readonly ByteBuffer bb = new ByteBuffer(16);
88 private readonly Type returnType;
90 internal Eager(ModuleBuilder module, byte type, Type returnType)
94 this.returnType = returnType;
96 if (type != Signature.FIELD)
98 // space for parameterCount
103 internal override Type ReturnType
105 get { return returnType; }
108 public override byte[] GetSignature()
110 return GetSignature(null).ToArray();
113 internal override ByteBuffer GetSignature(ModuleBuilder module)
115 if (type != Signature.FIELD)
118 bb.Insert(MetadataWriter.GetCompressedIntLength(paramCount) - bb.GetCompressedIntLength());
119 bb.WriteCompressedInt(paramCount);
124 public override void AddSentinel()
126 bb.Write(Signature.SENTINEL);
129 public override void __AddArgument(Type argument, bool pinned, CustomModifiers customModifiers)
133 bb.Write(Signature.ELEMENT_TYPE_PINNED);
135 foreach (CustomModifiers.Entry mod in customModifiers)
137 bb.Write(mod.IsRequired ? Signature.ELEMENT_TYPE_CMOD_REQD : Signature.ELEMENT_TYPE_CMOD_OPT);
138 Signature.WriteTypeSpec(module, bb, mod.Type);
140 Signature.WriteTypeSpec(module, bb, argument ?? module.universe.System_Void);
145 private SignatureHelper(byte type)
150 internal bool HasThis
152 get { return (type & Signature.HASTHIS) != 0; }
155 internal abstract Type ReturnType
160 internal int ParameterCount
162 get { return paramCount; }
165 private static SignatureHelper Create(Module mod, byte type, Type returnType)
167 ModuleBuilder mb = mod as ModuleBuilder;
169 ? (SignatureHelper)new Lazy(type)
170 : new Eager(mb, type, returnType);
173 public static SignatureHelper GetFieldSigHelper(Module mod)
175 return Create(mod, Signature.FIELD, null);
178 public static SignatureHelper GetLocalVarSigHelper()
180 return new Lazy(Signature.LOCAL_SIG);
183 public static SignatureHelper GetLocalVarSigHelper(Module mod)
185 return Create(mod, Signature.LOCAL_SIG, null);
188 public static SignatureHelper GetPropertySigHelper(Module mod, Type returnType, Type[] parameterTypes)
190 SignatureHelper sig = Create(mod, Signature.PROPERTY, returnType);
191 sig.AddArgument(returnType);
193 sig.AddArguments(parameterTypes, null, null);
197 public static SignatureHelper GetPropertySigHelper(Module mod, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
199 return GetPropertySigHelper(mod, CallingConventions.Standard, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
202 public static SignatureHelper GetPropertySigHelper(Module mod, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
204 byte type = Signature.PROPERTY;
205 if ((callingConvention & CallingConventions.HasThis) != 0)
207 type |= Signature.HASTHIS;
209 SignatureHelper sig = Create(mod, type, returnType);
210 sig.AddArgument(returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers);
212 sig.AddArguments(parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
216 public static SignatureHelper GetMethodSigHelper(CallingConvention unmanagedCallingConvention, Type returnType)
218 return GetMethodSigHelper(null, unmanagedCallingConvention, returnType);
221 public static SignatureHelper GetMethodSigHelper(CallingConventions callingConvention, Type returnType)
223 return GetMethodSigHelper(null, callingConvention, returnType);
226 public static SignatureHelper GetMethodSigHelper(Module mod, CallingConvention unmanagedCallConv, Type returnType)
229 switch (unmanagedCallConv)
231 case CallingConvention.Cdecl:
234 case CallingConvention.StdCall:
235 case CallingConvention.Winapi:
236 type = 0x02; // STDCALL
238 case CallingConvention.ThisCall:
239 type = 0x03; // THISCALL
241 case CallingConvention.FastCall:
242 type = 0x04; // FASTCALL
245 throw new ArgumentOutOfRangeException("unmanagedCallConv");
247 SignatureHelper sig = Create(mod, type, returnType);
248 sig.AddArgument(returnType);
253 public static SignatureHelper GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType)
256 if ((callingConvention & CallingConventions.HasThis) != 0)
258 type |= Signature.HASTHIS;
260 if ((callingConvention & CallingConventions.ExplicitThis) != 0)
262 type |= Signature.EXPLICITTHIS;
264 if ((callingConvention & CallingConventions.VarArgs) != 0)
266 type |= Signature.VARARG;
268 SignatureHelper sig = Create(mod, type, returnType);
269 sig.AddArgument(returnType);
274 public static SignatureHelper GetMethodSigHelper(Module mod, Type returnType, Type[] parameterTypes)
276 SignatureHelper sig = Create(mod, 0, returnType);
277 sig.AddArgument(returnType);
279 sig.AddArguments(parameterTypes, null, null);
283 public abstract byte[] GetSignature();
285 internal abstract ByteBuffer GetSignature(ModuleBuilder module);
287 public abstract void AddSentinel();
289 public void AddArgument(Type clsArgument)
291 AddArgument(clsArgument, false);
294 public void AddArgument(Type argument, bool pinned)
296 __AddArgument(argument, pinned, new CustomModifiers());
299 public void AddArgument(Type argument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
301 __AddArgument(argument, false, CustomModifiers.FromReqOpt(requiredCustomModifiers, optionalCustomModifiers));
304 public abstract void __AddArgument(Type argument, bool pinned, CustomModifiers customModifiers);
306 public void AddArguments(Type[] arguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
308 if (arguments != null)
310 for (int i = 0; i < arguments.Length; i++)
312 __AddArgument(arguments[i], false, CustomModifiers.FromReqOpt(Util.NullSafeElementAt(requiredCustomModifiers, i), Util.NullSafeElementAt(optionalCustomModifiers, i)));