Update mcs/class/Commons.Xml.Relaxng/Commons.Xml.Relaxng/RelaxngPattern.cs
[mono.git] / mcs / class / IKVM.Reflection / Reader / Method.cs
1 /*
2   Copyright (C) 2009-2012 Jeroen Frijters
3
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.
7
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:
11
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.
19
20   Jeroen Frijters
21   jeroen@frijters.net
22   
23 */
24 using System;
25 using System.Collections.Generic;
26 using System.Text;
27 using IKVM.Reflection.Metadata;
28
29 namespace IKVM.Reflection.Reader
30 {
31         sealed class MethodDefImpl : MethodInfo
32         {
33                 private readonly ModuleReader module;
34                 private readonly int index;
35                 private readonly TypeDefImpl declaringType;
36                 private MethodSignature lazyMethodSignature;
37                 private ParameterInfo returnParameter;
38                 private ParameterInfo[] parameters;
39                 private Type[] typeArgs;
40
41                 internal MethodDefImpl(ModuleReader module, TypeDefImpl declaringType, int index)
42                 {
43                         this.module = module;
44                         this.index = index;
45                         this.declaringType = declaringType;
46                 }
47
48                 public override MethodBody GetMethodBody()
49                 {
50                         return GetMethodBody(this);
51                 }
52
53                 internal MethodBody GetMethodBody(IGenericContext context)
54                 {
55                         if ((GetMethodImplementationFlags() & MethodImplAttributes.CodeTypeMask) != MethodImplAttributes.IL)
56                         {
57                                 // method is not IL
58                                 return null;
59                         }
60                         int rva = module.MethodDef.records[index].RVA;
61                         return rva == 0 ? null : new MethodBody(module, rva, context);
62                 }
63
64                 public override int __MethodRVA
65                 {
66                         get { return module.MethodDef.records[index].RVA; }
67                 }
68
69                 public override CallingConventions CallingConvention
70                 {
71                         get { return this.MethodSignature.CallingConvention; }
72                 }
73
74                 public override MethodAttributes Attributes
75                 {
76                         get { return (MethodAttributes)module.MethodDef.records[index].Flags; }
77                 }
78
79                 public override MethodImplAttributes GetMethodImplementationFlags()
80                 {
81                         return (MethodImplAttributes)module.MethodDef.records[index].ImplFlags;
82                 }
83
84                 public override ParameterInfo[] GetParameters()
85                 {
86                         PopulateParameters();
87                         return (ParameterInfo[])parameters.Clone();
88                 }
89
90                 private void PopulateParameters()
91                 {
92                         if (parameters == null)
93                         {
94                                 MethodSignature methodSignature = this.MethodSignature;
95                                 parameters = new ParameterInfo[methodSignature.GetParameterCount()];
96                                 int parameter = module.MethodDef.records[index].ParamList - 1;
97                                 int end = module.MethodDef.records.Length > index + 1 ? module.MethodDef.records[index + 1].ParamList - 1 : module.Param.records.Length;
98                                 for (; parameter < end; parameter++)
99                                 {
100                                         int seq = module.Param.records[parameter].Sequence - 1;
101                                         if (seq == -1)
102                                         {
103                                                 returnParameter = new ParameterInfoImpl(this, seq, parameter);
104                                         }
105                                         else
106                                         {
107                                                 parameters[seq] = new ParameterInfoImpl(this, seq, parameter);
108                                         }
109                                 }
110                                 for (int i = 0; i < parameters.Length; i++)
111                                 {
112                                         if (parameters[i] == null)
113                                         {
114                                                 parameters[i] = new ParameterInfoImpl(this, i, -1);
115                                         }
116                                 }
117                                 if (returnParameter == null)
118                                 {
119                                         returnParameter = new ParameterInfoImpl(this, -1, -1);
120                                 }
121                         }
122                 }
123
124                 internal override int ParameterCount
125                 {
126                         get { return this.MethodSignature.GetParameterCount(); }
127                 }
128
129                 public override ParameterInfo ReturnParameter
130                 {
131                         get
132                         {
133                                 PopulateParameters();
134                                 return returnParameter;
135                         }
136                 }
137
138                 public override Type ReturnType
139                 {
140                         get
141                         {
142                                 return this.ReturnParameter.ParameterType;
143                         }
144                 }
145
146                 public override Type DeclaringType
147                 {
148                         get { return declaringType.IsModulePseudoType ? null : declaringType; }
149                 }
150
151                 public override string Name
152                 {
153                         get { return module.GetString(module.MethodDef.records[index].Name); }
154                 }
155
156                 public override int MetadataToken
157                 {
158                         get { return (MethodDefTable.Index << 24) + index + 1; }
159                 }
160
161                 public override bool IsGenericMethodDefinition
162                 {
163                         get
164                         {
165                                 PopulateGenericArguments();
166                                 return typeArgs.Length > 0;
167                         }
168                 }
169
170                 public override bool IsGenericMethod
171                 {
172                         get { return IsGenericMethodDefinition; }
173                 }
174
175                 public override Type[] GetGenericArguments()
176                 {
177                         PopulateGenericArguments();
178                         return Util.Copy(typeArgs);
179                 }
180
181                 private void PopulateGenericArguments()
182                 {
183                         if (typeArgs == null)
184                         {
185                                 int token = this.MetadataToken;
186                                 int first = module.GenericParam.FindFirstByOwner(token);
187                                 if (first == -1)
188                                 {
189                                         typeArgs = Type.EmptyTypes;
190                                 }
191                                 else
192                                 {
193                                         List<Type> list = new List<Type>();
194                                         int len = module.GenericParam.records.Length;
195                                         for (int i = first; i < len && module.GenericParam.records[i].Owner == token; i++)
196                                         {
197                                                 list.Add(new GenericTypeParameter(module, i));
198                                         }
199                                         typeArgs = list.ToArray();
200                                 }
201                         }
202                 }
203
204                 internal override Type GetGenericMethodArgument(int index)
205                 {
206                         PopulateGenericArguments();
207                         return typeArgs[index];
208                 }
209
210                 internal override int GetGenericMethodArgumentCount()
211                 {
212                         PopulateGenericArguments();
213                         return typeArgs.Length;
214                 }
215
216                 public override MethodInfo GetGenericMethodDefinition()
217                 {
218                         if (this.IsGenericMethodDefinition)
219                         {
220                                 return this;
221                         }
222                         throw new InvalidOperationException();
223                 }
224
225                 public override MethodInfo MakeGenericMethod(params Type[] typeArguments)
226                 {
227                         return new GenericMethodInstance(declaringType, this, typeArguments);
228                 }
229
230                 public override Module Module
231                 {
232                         get { return module; }
233                 }
234
235                 internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
236                 {
237                         List<CustomAttributeData> list = module.GetCustomAttributes(this.MetadataToken, attributeType);
238                         if ((this.Attributes & MethodAttributes.PinvokeImpl) != 0
239                                 && (attributeType == null || attributeType.IsAssignableFrom(module.universe.System_Runtime_InteropServices_DllImportAttribute)))
240                         {
241                                 CreateDllImportPseudoCustomAttribute(list);
242                         }
243                         return list;
244                 }
245
246                 private void CreateDllImportPseudoCustomAttribute(List<CustomAttributeData> attribs)
247                 {
248                         foreach (int i in module.ImplMap.Filter(this.MetadataToken))
249                         {
250                                 const short NoMangle = 0x0001;
251                                 const short CharSetMask = 0x0006;
252                                 const short CharSetNotSpec = 0x0000;
253                                 const short CharSetAnsi = 0x0002;
254                                 const short CharSetUnicode = 0x0004;
255                                 const short CharSetAuto = 0x0006;
256                                 const short SupportsLastError = 0x0040;
257                                 const short CallConvMask = 0x0700;
258                                 const short CallConvWinapi = 0x0100;
259                                 const short CallConvCdecl = 0x0200;
260                                 const short CallConvStdcall = 0x0300;
261                                 const short CallConvThiscall = 0x0400;
262                                 const short CallConvFastcall = 0x0500;
263                                 // non-standard flags
264                                 const short BestFitOn = 0x0010;
265                                 const short BestFitOff = 0x0020;
266                                 const short CharMapErrorOn = 0x1000;
267                                 const short CharMapErrorOff = 0x2000;
268
269                                 Type type = module.universe.System_Runtime_InteropServices_DllImportAttribute;
270                                 ConstructorInfo constructor = type.GetPseudoCustomAttributeConstructor(module.universe.System_String);
271                                 List<CustomAttributeNamedArgument> list = new List<CustomAttributeNamedArgument>();
272                                 int flags = module.ImplMap.records[i].MappingFlags;
273                                 string entryPoint = module.GetString(module.ImplMap.records[i].ImportName);
274                                 string dllName = module.GetString(module.ModuleRef.records[(module.ImplMap.records[i].ImportScope & 0xFFFFFF) - 1]);
275                                 System.Runtime.InteropServices.CharSet? charSet;
276                                 switch (flags & CharSetMask)
277                                 {
278                                         case CharSetAnsi:
279                                                 charSet = System.Runtime.InteropServices.CharSet.Ansi;
280                                                 break;
281                                         case CharSetUnicode:
282                                                 charSet = System.Runtime.InteropServices.CharSet.Unicode;
283                                                 break;
284                                         case CharSetAuto:
285                                                 charSet = System.Runtime.InteropServices.CharSet.Auto;
286                                                 break;
287                                         case CharSetNotSpec:
288                                         default:
289                                                 charSet = null;
290                                                 break;
291                                 }
292                                 System.Runtime.InteropServices.CallingConvention callingConvention;
293                                 switch (flags & CallConvMask)
294                                 {
295                                         case CallConvCdecl:
296                                                 callingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl;
297                                                 break;
298                                         case CallConvFastcall:
299                                                 callingConvention = System.Runtime.InteropServices.CallingConvention.FastCall;
300                                                 break;
301                                         case CallConvStdcall:
302                                                 callingConvention = System.Runtime.InteropServices.CallingConvention.StdCall;
303                                                 break;
304                                         case CallConvThiscall:
305                                                 callingConvention = System.Runtime.InteropServices.CallingConvention.ThisCall;
306                                                 break;
307                                         case CallConvWinapi:
308                                                 callingConvention = System.Runtime.InteropServices.CallingConvention.Winapi;
309                                                 break;
310                                         default:
311                                                 callingConvention = 0;
312                                                 break;
313                                 }
314                                 AddNamedArgument(list, type, "EntryPoint", entryPoint);
315                                 AddNamedArgument(list, type, "ExactSpelling", flags, NoMangle);
316                                 AddNamedArgument(list, type, "SetLastError", flags, SupportsLastError);
317                                 AddNamedArgument(list, type, "PreserveSig", (int)GetMethodImplementationFlags(), (int)MethodImplAttributes.PreserveSig);
318                                 AddNamedArgument(list, type, "CallingConvention", module.universe.System_Runtime_InteropServices_CallingConvention, (int)callingConvention);
319                                 if (charSet.HasValue)
320                                 {
321                                         AddNamedArgument(list, type, "CharSet", module.universe.System_Runtime_InteropServices_CharSet, (int)charSet.Value);
322                                 }
323                                 if ((flags & (BestFitOn | BestFitOff)) != 0)
324                                 {
325                                         AddNamedArgument(list, type, "BestFitMapping", flags, BestFitOn);
326                                 }
327                                 if ((flags & (CharMapErrorOn | CharMapErrorOff)) != 0)
328                                 {
329                                         AddNamedArgument(list, type, "ThrowOnUnmappableChar", flags, CharMapErrorOn);
330                                 }
331                                 attribs.Add(new CustomAttributeData(module, constructor, new object[] { dllName }, list));
332                                 return;
333                         }
334                 }
335
336                 private static void AddNamedArgument(List<CustomAttributeNamedArgument> list, Type type, string fieldName, string value)
337                 {
338                         AddNamedArgument(list, type, fieldName, type.Module.universe.System_String, value);
339                 }
340
341                 private static void AddNamedArgument(List<CustomAttributeNamedArgument> list, Type type, string fieldName, int flags, int flagMask)
342                 {
343                         AddNamedArgument(list, type, fieldName, type.Module.universe.System_Boolean, (flags & flagMask) != 0);
344                 }
345
346                 private static void AddNamedArgument(List<CustomAttributeNamedArgument> list, Type attributeType, string fieldName, Type valueType, object value)
347                 {
348                         // some fields are not available on the .NET Compact Framework version of DllImportAttribute
349                         FieldInfo field = attributeType.FindField(fieldName, FieldSignature.Create(valueType, new CustomModifiers()));
350                         if (field != null)
351                         {
352                                 list.Add(new CustomAttributeNamedArgument(field, new CustomAttributeTypedArgument(valueType, value)));
353                         }
354                 }
355
356                 internal override MethodSignature MethodSignature
357                 {
358                         get { return lazyMethodSignature ?? (lazyMethodSignature = MethodSignature.ReadSig(module, module.GetBlob(module.MethodDef.records[index].Signature), this)); }
359                 }
360
361                 internal override int ImportTo(Emit.ModuleBuilder module)
362                 {
363                         return module.ImportMethodOrField(declaringType, this.Name, this.MethodSignature);
364                 }
365
366                 public override MethodInfo[] __GetMethodImpls()
367                 {
368                         Type[] typeArgs = null;
369                         List<MethodInfo> list = null;
370                         foreach (int i in module.MethodImpl.Filter(declaringType.MetadataToken))
371                         {
372                                 if (module.MethodImpl.records[i].MethodBody == this.MetadataToken)
373                                 {
374                                         if (typeArgs == null)
375                                         {
376                                                 typeArgs = declaringType.GetGenericArguments();
377                                         }
378                                         if (list == null)
379                                         {
380                                                 list = new List<MethodInfo>();
381                                         }
382                                         list.Add((MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodDeclaration, typeArgs, null));
383                                 }
384                         }
385                         return Util.ToArray(list, Empty<MethodInfo>.Array);
386                 }
387         }
388
389         sealed class ParameterInfoImpl : ParameterInfo
390         {
391                 private readonly MethodDefImpl method;
392                 private readonly int position;
393                 private readonly int index;
394
395                 internal ParameterInfoImpl(MethodDefImpl method, int position, int index)
396                 {
397                         this.method = method;
398                         this.position = position;
399                         this.index = index;
400                 }
401
402                 public override string Name
403                 {
404                         get { return index == -1 ? null : ((ModuleReader)this.Module).GetString(this.Module.Param.records[index].Name); }
405                 }
406
407                 public override Type ParameterType
408                 {
409                         get { return position == -1 ? method.MethodSignature.GetReturnType(method) : method.MethodSignature.GetParameterType(method, position); }
410                 }
411
412                 public override ParameterAttributes Attributes
413                 {
414                         get { return index == -1 ? ParameterAttributes.None : (ParameterAttributes)this.Module.Param.records[index].Flags; }
415                 }
416
417                 public override int Position
418                 {
419                         get { return position; }
420                 }
421
422                 public override object RawDefaultValue
423                 {
424                         get
425                         {
426                                 if ((this.Attributes & ParameterAttributes.HasDefault) != 0)
427                                 {
428                                         return this.Module.Constant.GetRawConstantValue(this.Module, this.MetadataToken);
429                                 }
430                                 Universe universe = this.Module.universe;
431                                 if (this.ParameterType == universe.System_Decimal)
432                                 {
433                                         Type attr = universe.System_Runtime_CompilerServices_DecimalConstantAttribute;
434                                         if (attr != null)
435                                         {
436                                                 foreach (CustomAttributeData cad in GetCustomAttributesData(attr))
437                                                 {
438                                                         IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
439                                                         if (args.Count == 5)
440                                                         {
441                                                                 if (args[0].ArgumentType == universe.System_Byte
442                                                                         && args[1].ArgumentType == universe.System_Byte
443                                                                         && args[2].ArgumentType == universe.System_Int32
444                                                                         && args[3].ArgumentType == universe.System_Int32
445                                                                         && args[4].ArgumentType == universe.System_Int32)
446                                                                 {
447                                                                         return new Decimal((int)args[4].Value, (int)args[3].Value, (int)args[2].Value, (byte)args[1].Value != 0, (byte)args[0].Value);
448                                                                 }
449                                                                 else if (args[0].ArgumentType == universe.System_Byte
450                                                                         && args[1].ArgumentType == universe.System_Byte
451                                                                         && args[2].ArgumentType == universe.System_UInt32
452                                                                         && args[3].ArgumentType == universe.System_UInt32
453                                                                         && args[4].ArgumentType == universe.System_UInt32)
454                                                                 {
455                                                                         return new Decimal(unchecked((int)(uint)args[4].Value), unchecked((int)(uint)args[3].Value), unchecked((int)(uint)args[2].Value), (byte)args[1].Value != 0, (byte)args[0].Value);
456                                                                 }
457                                                         }
458                                                 }
459                                         }
460                                 }
461                                 if ((this.Attributes & ParameterAttributes.Optional) != 0)
462                                 {
463                                         return Missing.Value;
464                                 }
465                                 return null;
466                         }
467                 }
468
469                 public override CustomModifiers __GetCustomModifiers()
470                 {
471                         return position == -1
472                                 ? method.MethodSignature.GetReturnTypeCustomModifiers(method)
473                                 : method.MethodSignature.GetParameterCustomModifiers(method, position);
474                 }
475
476                 public override MemberInfo Member
477                 {
478                         get
479                         {
480                                 // return the right ConstructorInfo wrapper
481                                 return method.Module.ResolveMethod(method.MetadataToken);
482                         }
483                 }
484
485                 public override int MetadataToken
486                 {
487                         get
488                         {
489                                 // for parameters that don't have a row in the Param table, we return 0x08000000 (because index is -1 in that case),
490                                 // just like .NET
491                                 return (ParamTable.Index << 24) + index + 1;
492                         }
493                 }
494
495                 internal override Module Module
496                 {
497                         get { return method.Module; }
498                 }
499
500                 internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
501                 {
502                         IList<CustomAttributeData> list = base.GetCustomAttributesData(attributeType);
503                         if ((this.Attributes & ParameterAttributes.HasFieldMarshal) != 0
504                                 && (attributeType == null || attributeType.IsAssignableFrom(this.Module.universe.System_Runtime_InteropServices_MarshalAsAttribute)))
505                         {
506                                 list.Add(MarshalSpec.GetMarshalAsAttribute(this.Module, this.MetadataToken));
507                         }
508                         return list;
509                 }
510         }
511 }