Moved ProviderCollectionTest.cs from System assembly to System.Configuration.
[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 using System;
25 using System.Collections;
26 using System.Reflection.Emit;
27 using System.Reflection;
28
29 namespace Mono.CodeGeneration
30 {
31         public class CodeGenerationHelper
32         {
33                 public static void GenerateMethodCall (ILGenerator gen, CodeExpression target, MethodBase method, params CodeExpression[] parameters)
34                 {
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;
41                         }
42                         GenerateMethodCall (gen, target, method, ptypes, parameters);
43                 }
44                 
45                 public static void GenerateMethodCall (ILGenerator gen, CodeExpression target, CodeMethod method, params CodeExpression[] parameters)
46                 {
47                         GenerateMethodCall (gen, target, method.MethodBase, method.ParameterTypes, parameters);
48                 }
49                 
50                 static void GenerateMethodCall (ILGenerator gen, CodeExpression target, MethodBase method, Type[] parameterTypes, params CodeExpression[] parameters)
51                 {
52                         OpCode callOp;
53                         
54                         if (parameterTypes.Length != parameters.Length)
55                                 throw GetMethodException (method, "Invalid number of parameters, expected " + parameterTypes.Length + ", found " + parameters.Length + ".");  
56                         
57                         if (!object.ReferenceEquals (target, null)) 
58                         {
59                                 target.Generate (gen);
60                                 
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;
67                                 }
68                                 else
69                                         callOp = OpCodes.Callvirt;
70                         }
71                         else
72                                 callOp = OpCodes.Call;
73
74                         for (int n=0; n<parameterTypes.Length; n++) {
75                                 try {
76                                         CodeExpression par = parameters[n];
77                                         par.Generate (gen);
78                                         GenerateSafeConversion (gen, parameterTypes[n], par.GetResultType());
79                                 }
80                                 catch (InvalidOperationException ex) {
81                                         throw GetMethodException (method, "Parameter " + n + ". " + ex.Message);  
82                                 }
83                         }
84                         
85                         if (method is MethodInfo)
86                                 gen.Emit (callOp, (MethodInfo)method);
87                         else if (method is ConstructorInfo)
88                                 gen.Emit (callOp, (ConstructorInfo)method);
89                 }
90                 
91                 public static Exception GetMethodException (MethodBase method, string msg)
92                 {
93                         return new InvalidOperationException ("Call to method " + method.DeclaringType + "." + method.Name + ": " + msg);  
94                 }
95                 
96                 public static void GenerateSafeConversion (ILGenerator gen, Type targetType, Type sourceType)
97                 {
98                         if (!targetType.IsAssignableFrom (sourceType)) {
99                                 throw new InvalidOperationException ("Invalid type conversion. Found '" + sourceType + "', expected '" + targetType + "'.");
100                         }
101                         
102                         if (targetType == typeof(object) && sourceType.IsValueType) {
103                                 gen.Emit (OpCodes.Box, sourceType);
104                         }
105                 }
106
107                 public static void LoadFromPtr (ILGenerator ig, Type t)
108                 {
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);
135                         else if (t.IsEnum) {
136                                 if (t == typeof(Enum))
137                                         ig.Emit (OpCodes.Ldind_Ref);
138                                 else
139                                         LoadFromPtr (ig, System.Enum.GetUnderlyingType (t));
140                         } else if (t.IsValueType)
141                                 ig.Emit (OpCodes.Ldobj, t);
142                         else
143                                 ig.Emit (OpCodes.Ldind_Ref);
144                 }
145
146                 public static void SaveToPtr (ILGenerator ig, Type t)
147                 {
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);
174                         else if (t.IsEnum) {
175                                 if (t == typeof(Enum))
176                                         ig.Emit (OpCodes.Stind_Ref);
177                                 else
178                                         SaveToPtr (ig, System.Enum.GetUnderlyingType (t));
179                         } else if (t.IsValueType)
180                                 ig.Emit (OpCodes.Stobj, t);
181                         else
182                                 ig.Emit (OpCodes.Stind_Ref);
183                 }
184
185                 public static bool IsNumber (Type t)
186                 {
187                         switch (Type.GetTypeCode (t))
188                         {
189                                 case TypeCode.Byte:
190                                 case TypeCode.Double:
191                                 case TypeCode.Int16:
192                                 case TypeCode.Int32:
193                                 case TypeCode.Int64:
194                                 case TypeCode.SByte:
195                                 case TypeCode.Single:
196                                 case TypeCode.UInt16:
197                                 case TypeCode.UInt32:
198                                 case TypeCode.UInt64:
199                                         return true;
200                                 default:
201                                         return false;
202                         }
203                 }
204                 
205                 public static void GeneratePrimitiveValue ()
206                 {
207                 }
208         }
209 }