Update PointConverter.cs
[mono.git] / mcs / class / System.ServiceModel / Mono.CodeGeneration / CodeGenerationHelper.cs
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 !MONOTOUCH
25 using System;
26 using System.Collections;
27 using System.Reflection.Emit;
28 using System.Reflection;
29
30 namespace Mono.CodeGeneration
31 {
32         public class CodeGenerationHelper
33         {
34                 public static void GenerateMethodCall (ILGenerator gen, CodeExpression target, MethodBase method, params CodeExpression[] parameters)
35                 {
36                         Type[] ptypes = Type.EmptyTypes;
37                         // It could raise an error since GetParameters() on MethodBuilder is not supported.
38                         if (parameters.Length > 0) {
39                                 ParameterInfo[] pars = method.GetParameters ();
40                                 ptypes = new Type[pars.Length];
41                                 for (int n=0; n<ptypes.Length; n++) ptypes[n] = pars[n].ParameterType;
42                         }
43                         GenerateMethodCall (gen, target, method, ptypes, parameters);
44                 }
45                 
46                 public static void GenerateMethodCall (ILGenerator gen, CodeExpression target, CodeMethod method, params CodeExpression[] parameters)
47                 {
48                         GenerateMethodCall (gen, target, method.MethodBase, method.ParameterTypes, parameters);
49                 }
50                 
51                 static void GenerateMethodCall (ILGenerator gen, CodeExpression target, MethodBase method, Type[] parameterTypes, params CodeExpression[] parameters)
52                 {
53                         OpCode callOp;
54                         
55                         if (parameterTypes.Length != parameters.Length)
56                                 throw GetMethodException (method, "Invalid number of parameters, expected " + parameterTypes.Length + ", found " + parameters.Length + ".");  
57                         
58                         if (!object.ReferenceEquals (target, null)) 
59                         {
60                                 target.Generate (gen);
61                                 
62                                 Type targetType = target.GetResultType();
63                                 if (targetType.IsValueType) {
64                                         LocalBuilder lb = gen.DeclareLocal (targetType);
65                                         gen.Emit (OpCodes.Stloc, lb);
66                                         gen.Emit (OpCodes.Ldloca, lb);
67                                         callOp = OpCodes.Call;
68                                 }
69                                 else
70                                         callOp = OpCodes.Callvirt;
71                         }
72                         else
73                                 callOp = OpCodes.Call;
74
75                         for (int n=0; n<parameterTypes.Length; n++) {
76                                 try {
77                                         CodeExpression par = parameters[n];
78                                         par.Generate (gen);
79                                         GenerateSafeConversion (gen, parameterTypes[n], par.GetResultType());
80                                 }
81                                 catch (InvalidOperationException ex) {
82                                         throw GetMethodException (method, "Parameter " + n + ". " + ex.Message);  
83                                 }
84                         }
85                         
86                         if (method is MethodInfo)
87                                 gen.Emit (callOp, (MethodInfo)method);
88                         else if (method is ConstructorInfo)
89                                 gen.Emit (callOp, (ConstructorInfo)method);
90                 }
91                 
92                 public static Exception GetMethodException (MethodBase method, string msg)
93                 {
94                         return new InvalidOperationException ("Call to method " + method.DeclaringType + "." + method.Name + ": " + msg);  
95                 }
96                 
97                 public static void GenerateSafeConversion (ILGenerator gen, Type targetType, Type sourceType)
98                 {
99                         if (!targetType.IsAssignableFrom (sourceType)) {
100                                 throw new InvalidOperationException ("Invalid type conversion. Found '" + sourceType + "', expected '" + targetType + "'.");
101                         }
102                         
103                         if (targetType == typeof(object) && sourceType.IsValueType) {
104                                 gen.Emit (OpCodes.Box, sourceType);
105                         }
106                 }
107
108                 public static void LoadFromPtr (ILGenerator ig, Type t)
109                 {
110                         if (t == typeof(int))
111                                 ig.Emit (OpCodes.Ldind_I4);
112                         else if (t == typeof(uint))
113                                 ig.Emit (OpCodes.Ldind_U4);
114                         else if (t == typeof(short))
115                                 ig.Emit (OpCodes.Ldind_I2);
116                         else if (t == typeof(ushort))
117                                 ig.Emit (OpCodes.Ldind_U2);
118                         else if (t == typeof(char))
119                                 ig.Emit (OpCodes.Ldind_U2);
120                         else if (t == typeof(byte))
121                                 ig.Emit (OpCodes.Ldind_U1);
122                         else if (t == typeof(sbyte))
123                                 ig.Emit (OpCodes.Ldind_I1);
124                         else if (t == typeof(ulong))
125                                 ig.Emit (OpCodes.Ldind_I8);
126                         else if (t == typeof(long))
127                                 ig.Emit (OpCodes.Ldind_I8);
128                         else if (t == typeof(float))
129                                 ig.Emit (OpCodes.Ldind_R4);
130                         else if (t == typeof(double))
131                                 ig.Emit (OpCodes.Ldind_R8);
132                         else if (t == typeof(bool))
133                                 ig.Emit (OpCodes.Ldind_I1);
134                         else if (t == typeof(IntPtr))
135                                 ig.Emit (OpCodes.Ldind_I);
136                         else if (t.IsEnum) {
137                                 if (t == typeof(Enum))
138                                         ig.Emit (OpCodes.Ldind_Ref);
139                                 else
140                                         LoadFromPtr (ig, System.Enum.GetUnderlyingType (t));
141                         } else if (t.IsValueType)
142                                 ig.Emit (OpCodes.Ldobj, t);
143                         else
144                                 ig.Emit (OpCodes.Ldind_Ref);
145                 }
146
147                 public static void SaveToPtr (ILGenerator ig, Type t)
148                 {
149                         if (t == typeof(int))
150                                 ig.Emit (OpCodes.Stind_I4);
151                         else if (t == typeof(uint))
152                                 ig.Emit (OpCodes.Stind_I4);
153                         else if (t == typeof(short))
154                                 ig.Emit (OpCodes.Stind_I2);
155                         else if (t == typeof(ushort))
156                                 ig.Emit (OpCodes.Stind_I2);
157                         else if (t == typeof(char))
158                                 ig.Emit (OpCodes.Stind_I2);
159                         else if (t == typeof(byte))
160                                 ig.Emit (OpCodes.Stind_I1);
161                         else if (t == typeof(sbyte))
162                                 ig.Emit (OpCodes.Stind_I1);
163                         else if (t == typeof(ulong))
164                                 ig.Emit (OpCodes.Stind_I8);
165                         else if (t == typeof(long))
166                                 ig.Emit (OpCodes.Stind_I8);
167                         else if (t == typeof(float))
168                                 ig.Emit (OpCodes.Stind_R4);
169                         else if (t == typeof(double))
170                                 ig.Emit (OpCodes.Stind_R8);
171                         else if (t == typeof(bool))
172                                 ig.Emit (OpCodes.Stind_I1);
173                         else if (t == typeof(IntPtr))
174                                 ig.Emit (OpCodes.Stind_I);
175                         else if (t.IsEnum) {
176                                 if (t == typeof(Enum))
177                                         ig.Emit (OpCodes.Stind_Ref);
178                                 else
179                                         SaveToPtr (ig, System.Enum.GetUnderlyingType (t));
180                         } else if (t.IsValueType)
181                                 ig.Emit (OpCodes.Stobj, t);
182                         else
183                                 ig.Emit (OpCodes.Stind_Ref);
184                 }
185
186                 public static bool IsNumber (Type t)
187                 {
188                         switch (Type.GetTypeCode (t))
189                         {
190                                 case TypeCode.Byte:
191                                 case TypeCode.Double:
192                                 case TypeCode.Int16:
193                                 case TypeCode.Int32:
194                                 case TypeCode.Int64:
195                                 case TypeCode.SByte:
196                                 case TypeCode.Single:
197                                 case TypeCode.UInt16:
198                                 case TypeCode.UInt32:
199                                 case TypeCode.UInt64:
200                                         return true;
201                                 default:
202                                         return false;
203                         }
204                 }
205                 
206                 public static void GeneratePrimitiveValue ()
207                 {
208                 }
209         }
210 }
211 #endif