CodeMethod.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. //
  2. // Permission is hereby granted, free of charge, to any person obtaining
  3. // a copy of this software and associated documentation files (the
  4. // "Software"), to deal in the Software without restriction, including
  5. // without limitation the rights to use, copy, modify, merge, publish,
  6. // distribute, sublicense, and/or sell copies of the Software, and to
  7. // permit persons to whom the Software is furnished to do so, subject to
  8. // the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be
  11. // included in all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  15. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  17. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  18. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  19. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. //
  21. // Copyright (C) Lluis Sanchez Gual, 2004
  22. //
  23. #if !FULL_AOT_RUNTIME
  24. using System;
  25. using System.Collections;
  26. using System.IO;
  27. using System.Reflection;
  28. using System.Reflection.Emit;
  29. namespace Mono.CodeGeneration
  30. {
  31. public class CodeMethod
  32. {
  33. MethodBase methodBase;
  34. CodeBuilder builder;
  35. string name;
  36. MethodAttributes attributes;
  37. Type returnType;
  38. TypeBuilder typeBuilder;
  39. Type[] parameterTypes;
  40. ArrayList customAttributes = new ArrayList ();
  41. CodeClass cls;
  42. internal static CodeMethod DefineMethod (CodeClass cls, string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
  43. {
  44. return new CodeMethod (cls, name, attributes, returnType, parameterTypes);
  45. }
  46. public static CodeMethod DefineConstructor (CodeClass cls, MethodAttributes attributes, Type[] parameterTypes)
  47. {
  48. return new CodeMethod (cls, attributes, parameterTypes);
  49. }
  50. internal CodeMethod (CodeClass cls, string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
  51. {
  52. this.cls = cls;
  53. this.typeBuilder = cls.TypeBuilder;
  54. this.name = name;
  55. this.attributes = attributes;
  56. this.returnType = returnType;
  57. this.parameterTypes = parameterTypes;
  58. methodBase = typeBuilder.DefineMethod (name, attributes, returnType, parameterTypes);
  59. builder = new CodeBuilder (cls);
  60. }
  61. CodeMethod (CodeClass cls, MethodAttributes attributes, Type[] parameterTypes)
  62. {
  63. this.cls = cls;
  64. this.typeBuilder = cls.TypeBuilder;
  65. this.attributes = attributes;
  66. this.parameterTypes = parameterTypes;
  67. this.name = typeBuilder.Name;
  68. methodBase = typeBuilder.DefineConstructor (attributes, CallingConventions.Standard, parameterTypes);
  69. builder = new CodeBuilder (cls);
  70. }
  71. public TypeBuilder DeclaringType
  72. {
  73. get { return typeBuilder; }
  74. }
  75. public MethodInfo MethodInfo
  76. {
  77. get { return methodBase as MethodInfo; }
  78. }
  79. public MethodBase MethodBase
  80. {
  81. get { return methodBase; }
  82. }
  83. public string Name
  84. {
  85. get { return name; }
  86. }
  87. public MethodAttributes Attributes
  88. {
  89. get { return attributes; }
  90. }
  91. public Type ReturnType
  92. {
  93. get { return returnType; }
  94. }
  95. public Type[] ParameterTypes
  96. {
  97. get { return parameterTypes; }
  98. }
  99. public CodeBuilder CodeBuilder
  100. {
  101. get { return builder; }
  102. }
  103. public bool IsStatic
  104. {
  105. get { return (attributes & MethodAttributes.Static) != 0; }
  106. }
  107. public CodeCustomAttribute CreateCustomAttribute (Type attributeType)
  108. {
  109. return CreateCustomAttribute (attributeType,
  110. Type.EmptyTypes, new object [0]);
  111. }
  112. public CodeCustomAttribute CreateCustomAttribute (Type attributeType, Type [] ctorArgTypes, object [] ctorArgs)
  113. {
  114. return CreateCustomAttribute (attributeType,
  115. ctorArgTypes, ctorArgs, new string [0], new object [0]);
  116. }
  117. public CodeCustomAttribute CreateCustomAttribute (Type attributeType, Type [] ctorArgTypes, object [] ctorArgs, string [] namedArgFieldNames, object [] namedArgValues)
  118. {
  119. CodeCustomAttribute cca = CodeCustomAttribute.Create (
  120. attributeType, ctorArgTypes, ctorArgs, namedArgFieldNames, namedArgValues);
  121. SetCustomAttribute (cca);
  122. return cca;
  123. }
  124. public CodeCustomAttribute CreateCustomAttribute (Type attributeType, Type [] ctorArgTypes, CodeLiteral [] ctorArgs, FieldInfo [] fields, CodeLiteral [] fieldValues)
  125. {
  126. CodeCustomAttribute cca = CodeCustomAttribute.Create (
  127. attributeType, ctorArgTypes, ctorArgs, fields, fieldValues);
  128. SetCustomAttribute (cca);
  129. return cca;
  130. }
  131. void SetCustomAttribute (CodeCustomAttribute cca)
  132. {
  133. if (methodBase is MethodBuilder)
  134. ((MethodBuilder) methodBase).SetCustomAttribute (cca.Builder);
  135. else if (methodBase is ConstructorBuilder)
  136. ((ConstructorBuilder) methodBase).SetCustomAttribute (cca.Builder);
  137. customAttributes.Add (cca);
  138. }
  139. public string PrintCode ()
  140. {
  141. StringWriter sw = new StringWriter ();
  142. CodeWriter cw = new CodeWriter (sw);
  143. PrintCode (cw);
  144. return sw.ToString ();
  145. }
  146. public virtual void PrintCode (CodeWriter cp)
  147. {
  148. cp.BeginLine ();
  149. foreach (CodeCustomAttribute a in customAttributes)
  150. a.PrintCode (cp);
  151. if ((methodBase.Attributes & MethodAttributes.Static) != 0)
  152. cp.Write ("static ");
  153. if ((methodBase.Attributes & MethodAttributes.Public) != 0)
  154. cp.Write ("public ");
  155. if (returnType != null) cp.Write (returnType + " ");
  156. cp.Write (name + " (");
  157. for (int n=0; n<parameterTypes.Length; n++) {
  158. if (n > 0) cp.Write (", ");
  159. cp.Write (parameterTypes[n] + " arg" + n);
  160. }
  161. cp.Write (")");
  162. cp.EndLine ();
  163. cp.WriteLineInd ("{");
  164. builder.PrintCode (cp);
  165. cp.WriteLineUnind ("}");
  166. }
  167. public CodeArgumentReference GetArg (int n)
  168. {
  169. if (n < 0 || n >= parameterTypes.Length)
  170. throw new InvalidOperationException ("Invalid argument number");
  171. int narg = IsStatic ? n : n + 1;
  172. return new CodeArgumentReference (parameterTypes[n], narg, "arg" + n);
  173. }
  174. public CodeArgumentReference GetThis ()
  175. {
  176. if (IsStatic)
  177. throw new InvalidOperationException ("'this' not available in static methods");
  178. return new CodeArgumentReference (DeclaringType, 0, "this");
  179. }
  180. public void Generate ()
  181. {
  182. ILGenerator gen = methodBase is MethodInfo ? ((MethodBuilder)methodBase).GetILGenerator() : ((ConstructorBuilder)methodBase).GetILGenerator();
  183. Label returnLabel = gen.DefineLabel ();
  184. builder.ReturnLabel = returnLabel;
  185. builder.Generate (gen);
  186. gen.MarkLabel(returnLabel);
  187. gen.Emit(OpCodes.Ret);
  188. }
  189. public void UpdateMethodBase (Type type)
  190. {
  191. if (methodBase is MethodInfo)
  192. methodBase = type.GetMethod (methodBase.Name, parameterTypes);
  193. else
  194. methodBase = type.GetConstructor (parameterTypes);
  195. }
  196. }
  197. }
  198. #endif