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:
10 // The above copyright notice and this permission notice shall be
11 // included in all copies or substantial portions of the Software.
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.
21 // Copyright (C) Lluis Sanchez Gual, 2004
25 using System.Collections;
26 using System.Reflection.Emit;
27 using System.Reflection;
29 namespace Mono.CodeGeneration
31 public class CodeGenerationHelper
33 public static void GenerateMethodCall (ILGenerator gen, CodeExpression target, MethodBase method, params CodeExpression[] parameters)
35 Type[] ptypes = Type.EmptyTypes;
36 // It could raise an error since GetParameters() on MethodBuilder is not supported.
37 if (parameters.Length > 0) {
38 ParameterInfo[] pars = method.GetParameters ();
39 ptypes = new Type[pars.Length];
40 for (int n=0; n<ptypes.Length; n++) ptypes[n] = pars[n].ParameterType;
42 GenerateMethodCall (gen, target, method, ptypes, parameters);
45 public static void GenerateMethodCall (ILGenerator gen, CodeExpression target, CodeMethod method, params CodeExpression[] parameters)
47 GenerateMethodCall (gen, target, method.MethodBase, method.ParameterTypes, parameters);
50 static void GenerateMethodCall (ILGenerator gen, CodeExpression target, MethodBase method, Type[] parameterTypes, params CodeExpression[] parameters)
54 if (parameterTypes.Length != parameters.Length)
55 throw GetMethodException (method, "Invalid number of parameters, expected " + parameterTypes.Length + ", found " + parameters.Length + ".");
57 if (!object.ReferenceEquals (target, null))
59 target.Generate (gen);
61 Type targetType = target.GetResultType();
62 if (targetType.IsValueType) {
63 LocalBuilder lb = gen.DeclareLocal (targetType);
64 gen.Emit (OpCodes.Stloc, lb);
65 gen.Emit (OpCodes.Ldloca, lb);
66 callOp = OpCodes.Call;
69 callOp = OpCodes.Callvirt;
72 callOp = OpCodes.Call;
74 for (int n=0; n<parameterTypes.Length; n++) {
76 CodeExpression par = parameters[n];
78 GenerateSafeConversion (gen, parameterTypes[n], par.GetResultType());
80 catch (InvalidOperationException ex) {
81 throw GetMethodException (method, "Parameter " + n + ". " + ex.Message);
85 if (method is MethodInfo)
86 gen.Emit (callOp, (MethodInfo)method);
87 else if (method is ConstructorInfo)
88 gen.Emit (callOp, (ConstructorInfo)method);
91 public static Exception GetMethodException (MethodBase method, string msg)
93 return new InvalidOperationException ("Call to method " + method.DeclaringType + "." + method.Name + ": " + msg);
96 public static void GenerateSafeConversion (ILGenerator gen, Type targetType, Type sourceType)
98 if (!targetType.IsAssignableFrom (sourceType)) {
99 throw new InvalidOperationException ("Invalid type conversion. Found '" + sourceType + "', expected '" + targetType + "'.");
102 if (targetType == typeof(object) && sourceType.IsValueType) {
103 gen.Emit (OpCodes.Box, sourceType);
107 public static void LoadFromPtr (ILGenerator ig, Type t)
109 if (t == typeof(int))
110 ig.Emit (OpCodes.Ldind_I4);
111 else if (t == typeof(uint))
112 ig.Emit (OpCodes.Ldind_U4);
113 else if (t == typeof(short))
114 ig.Emit (OpCodes.Ldind_I2);
115 else if (t == typeof(ushort))
116 ig.Emit (OpCodes.Ldind_U2);
117 else if (t == typeof(char))
118 ig.Emit (OpCodes.Ldind_U2);
119 else if (t == typeof(byte))
120 ig.Emit (OpCodes.Ldind_U1);
121 else if (t == typeof(sbyte))
122 ig.Emit (OpCodes.Ldind_I1);
123 else if (t == typeof(ulong))
124 ig.Emit (OpCodes.Ldind_I8);
125 else if (t == typeof(long))
126 ig.Emit (OpCodes.Ldind_I8);
127 else if (t == typeof(float))
128 ig.Emit (OpCodes.Ldind_R4);
129 else if (t == typeof(double))
130 ig.Emit (OpCodes.Ldind_R8);
131 else if (t == typeof(bool))
132 ig.Emit (OpCodes.Ldind_I1);
133 else if (t == typeof(IntPtr))
134 ig.Emit (OpCodes.Ldind_I);
136 if (t == typeof(Enum))
137 ig.Emit (OpCodes.Ldind_Ref);
139 LoadFromPtr (ig, System.Enum.GetUnderlyingType (t));
140 } else if (t.IsValueType)
141 ig.Emit (OpCodes.Ldobj, t);
143 ig.Emit (OpCodes.Ldind_Ref);
146 public static void SaveToPtr (ILGenerator ig, Type t)
148 if (t == typeof(int))
149 ig.Emit (OpCodes.Stind_I4);
150 else if (t == typeof(uint))
151 ig.Emit (OpCodes.Stind_I4);
152 else if (t == typeof(short))
153 ig.Emit (OpCodes.Stind_I2);
154 else if (t == typeof(ushort))
155 ig.Emit (OpCodes.Stind_I2);
156 else if (t == typeof(char))
157 ig.Emit (OpCodes.Stind_I2);
158 else if (t == typeof(byte))
159 ig.Emit (OpCodes.Stind_I1);
160 else if (t == typeof(sbyte))
161 ig.Emit (OpCodes.Stind_I1);
162 else if (t == typeof(ulong))
163 ig.Emit (OpCodes.Stind_I8);
164 else if (t == typeof(long))
165 ig.Emit (OpCodes.Stind_I8);
166 else if (t == typeof(float))
167 ig.Emit (OpCodes.Stind_R4);
168 else if (t == typeof(double))
169 ig.Emit (OpCodes.Stind_R8);
170 else if (t == typeof(bool))
171 ig.Emit (OpCodes.Stind_I1);
172 else if (t == typeof(IntPtr))
173 ig.Emit (OpCodes.Stind_I);
175 if (t == typeof(Enum))
176 ig.Emit (OpCodes.Stind_Ref);
178 SaveToPtr (ig, System.Enum.GetUnderlyingType (t));
179 } else if (t.IsValueType)
180 ig.Emit (OpCodes.Stobj, t);
182 ig.Emit (OpCodes.Stind_Ref);
185 public static bool IsNumber (Type t)
187 switch (Type.GetTypeCode (t))
190 case TypeCode.Double:
195 case TypeCode.Single:
196 case TypeCode.UInt16:
197 case TypeCode.UInt32:
198 case TypeCode.UInt64:
205 public static void GeneratePrimitiveValue ()