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 24 #if !FULL_AOT_RUNTIME 25 using System; 26 using System.Collections; 27 using System.IO; 28 using System.Reflection; 29 using System.Reflection.Emit; 30 31 namespace Mono.CodeGeneration 32 { 33 public class CodeMethod 34 { 35 MethodBase methodBase; 36 CodeBuilder builder; 37 string name; 38 MethodAttributes attributes; 39 Type returnType; 40 TypeBuilder typeBuilder; 41 Type[] parameterTypes; 42 ArrayList customAttributes = new ArrayList (); 43 CodeClass cls; 44 DefineMethod(CodeClass cls, string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)45 internal static CodeMethod DefineMethod (CodeClass cls, string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes) 46 { 47 return new CodeMethod (cls, name, attributes, returnType, parameterTypes); 48 } 49 DefineConstructor(CodeClass cls, MethodAttributes attributes, Type[] parameterTypes)50 public static CodeMethod DefineConstructor (CodeClass cls, MethodAttributes attributes, Type[] parameterTypes) 51 { 52 return new CodeMethod (cls, attributes, parameterTypes); 53 } 54 CodeMethod(CodeClass cls, string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)55 internal CodeMethod (CodeClass cls, string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes) 56 { 57 this.cls = cls; 58 this.typeBuilder = cls.TypeBuilder; 59 this.name = name; 60 this.attributes = attributes; 61 this.returnType = returnType; 62 this.parameterTypes = parameterTypes; 63 64 methodBase = typeBuilder.DefineMethod (name, attributes, returnType, parameterTypes); 65 builder = new CodeBuilder (cls); 66 } 67 CodeMethod(CodeClass cls, MethodAttributes attributes, Type[] parameterTypes)68 CodeMethod (CodeClass cls, MethodAttributes attributes, Type[] parameterTypes) 69 { 70 this.cls = cls; 71 this.typeBuilder = cls.TypeBuilder; 72 this.attributes = attributes; 73 this.parameterTypes = parameterTypes; 74 this.name = typeBuilder.Name; 75 76 methodBase = typeBuilder.DefineConstructor (attributes, CallingConventions.Standard, parameterTypes); 77 builder = new CodeBuilder (cls); 78 } 79 80 public TypeBuilder DeclaringType 81 { 82 get { return typeBuilder; } 83 } 84 85 public MethodInfo MethodInfo 86 { 87 get { return methodBase as MethodInfo; } 88 } 89 90 public MethodBase MethodBase 91 { 92 get { return methodBase; } 93 } 94 95 public string Name 96 { 97 get { return name; } 98 } 99 100 public MethodAttributes Attributes 101 { 102 get { return attributes; } 103 } 104 105 public Type ReturnType 106 { 107 get { return returnType; } 108 } 109 110 public Type[] ParameterTypes 111 { 112 get { return parameterTypes; } 113 } 114 115 public CodeBuilder CodeBuilder 116 { 117 get { return builder; } 118 } 119 120 public bool IsStatic 121 { 122 get { return (attributes & MethodAttributes.Static) != 0; } 123 } 124 CreateCustomAttribute(Type attributeType)125 public CodeCustomAttribute CreateCustomAttribute (Type attributeType) 126 { 127 return CreateCustomAttribute (attributeType, 128 Type.EmptyTypes, new object [0]); 129 } 130 CreateCustomAttribute(Type attributeType, Type [] ctorArgTypes, object [] ctorArgs)131 public CodeCustomAttribute CreateCustomAttribute (Type attributeType, Type [] ctorArgTypes, object [] ctorArgs) 132 { 133 return CreateCustomAttribute (attributeType, 134 ctorArgTypes, ctorArgs, new string [0], new object [0]); 135 } 136 CreateCustomAttribute(Type attributeType, Type [] ctorArgTypes, object [] ctorArgs, string [] namedArgFieldNames, object [] namedArgValues)137 public CodeCustomAttribute CreateCustomAttribute (Type attributeType, Type [] ctorArgTypes, object [] ctorArgs, string [] namedArgFieldNames, object [] namedArgValues) 138 { 139 CodeCustomAttribute cca = CodeCustomAttribute.Create ( 140 attributeType, ctorArgTypes, ctorArgs, namedArgFieldNames, namedArgValues); 141 SetCustomAttribute (cca); 142 return cca; 143 } 144 CreateCustomAttribute(Type attributeType, Type [] ctorArgTypes, CodeLiteral [] ctorArgs, FieldInfo [] fields, CodeLiteral [] fieldValues)145 public CodeCustomAttribute CreateCustomAttribute (Type attributeType, Type [] ctorArgTypes, CodeLiteral [] ctorArgs, FieldInfo [] fields, CodeLiteral [] fieldValues) 146 { 147 CodeCustomAttribute cca = CodeCustomAttribute.Create ( 148 attributeType, ctorArgTypes, ctorArgs, fields, fieldValues); 149 SetCustomAttribute (cca); 150 return cca; 151 } 152 SetCustomAttribute(CodeCustomAttribute cca)153 void SetCustomAttribute (CodeCustomAttribute cca) 154 { 155 if (methodBase is MethodBuilder) 156 ((MethodBuilder) methodBase).SetCustomAttribute (cca.Builder); 157 else if (methodBase is ConstructorBuilder) 158 ((ConstructorBuilder) methodBase).SetCustomAttribute (cca.Builder); 159 customAttributes.Add (cca); 160 } 161 PrintCode()162 public string PrintCode () 163 { 164 StringWriter sw = new StringWriter (); 165 CodeWriter cw = new CodeWriter (sw); 166 PrintCode (cw); 167 return sw.ToString (); 168 } 169 PrintCode(CodeWriter cp)170 public virtual void PrintCode (CodeWriter cp) 171 { 172 cp.BeginLine (); 173 foreach (CodeCustomAttribute a in customAttributes) 174 a.PrintCode (cp); 175 if ((methodBase.Attributes & MethodAttributes.Static) != 0) 176 cp.Write ("static "); 177 if ((methodBase.Attributes & MethodAttributes.Public) != 0) 178 cp.Write ("public "); 179 if (returnType != null) cp.Write (returnType + " "); 180 cp.Write (name + " ("); 181 for (int n=0; n<parameterTypes.Length; n++) { 182 if (n > 0) cp.Write (", "); 183 cp.Write (parameterTypes[n] + " arg" + n); 184 } 185 cp.Write (")"); 186 cp.EndLine (); 187 cp.WriteLineInd ("{"); 188 189 builder.PrintCode (cp); 190 191 cp.WriteLineUnind ("}"); 192 } 193 GetArg(int n)194 public CodeArgumentReference GetArg (int n) 195 { 196 if (n < 0 || n >= parameterTypes.Length) 197 throw new InvalidOperationException ("Invalid argument number"); 198 199 int narg = IsStatic ? n : n + 1; 200 return new CodeArgumentReference (parameterTypes[n], narg, "arg" + n); 201 } 202 GetThis()203 public CodeArgumentReference GetThis () 204 { 205 if (IsStatic) 206 throw new InvalidOperationException ("'this' not available in static methods"); 207 208 return new CodeArgumentReference (DeclaringType, 0, "this"); 209 } 210 Generate()211 public void Generate () 212 { 213 ILGenerator gen = methodBase is MethodInfo ? ((MethodBuilder)methodBase).GetILGenerator() : ((ConstructorBuilder)methodBase).GetILGenerator(); 214 Label returnLabel = gen.DefineLabel (); 215 builder.ReturnLabel = returnLabel; 216 builder.Generate (gen); 217 gen.MarkLabel(returnLabel); 218 gen.Emit(OpCodes.Ret); 219 } 220 UpdateMethodBase(Type type)221 public void UpdateMethodBase (Type type) 222 { 223 if (methodBase is MethodInfo) 224 methodBase = type.GetMethod (methodBase.Name, parameterTypes); 225 else 226 methodBase = type.GetConstructor (parameterTypes); 227 } 228 } 229 } 230 #endif 231