This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mcs / ilasm / codegen / Instructions.cs
1 // Instructions.cs\r
2 // (C) Sergey Chaban (serge@wildwestsoftware.com)\r
3 \r
4 using System;\r
5 using System.Reflection;\r
6 using System.Reflection.Emit;\r
7 using System.Collections;\r
8 \r
9 namespace Mono.ILASM {\r
10 \r
11 \r
12         /// <summary>\r
13         /// </summary>\r
14         public class InstrNone : InstrBase {\r
15 \r
16                 /// <summary>\r
17                 /// </summary>\r
18                 /// <param name="tok"></param>\r
19                 public InstrNone (OpCode op) : base (op)\r
20                 {\r
21                 }\r
22 \r
23                 /// <summary>\r
24                 /// </summary>\r
25                 /// <param name="ilgen"></param>\r
26                 public override void Emit (ILGenerator ilgen, Class host)\r
27                 {\r
28                         ilgen.Emit (this.Opcode);\r
29                 }\r
30         }\r
31 \r
32 \r
33         /// <summary>\r
34         /// </summary>\r
35         public class InstrVar : InstrBase {\r
36 \r
37                 private object operand;\r
38 \r
39                 /// <summary>\r
40                 /// </summary>\r
41                 /// <param name="tok"></param>\r
42                 public InstrVar (OpCode op, object operand) : base (op)\r
43                 {\r
44                         this.operand = operand;\r
45                 }\r
46 \r
47 \r
48                 /// <summary>\r
49                 /// </summary>\r
50                 /// <param name="ilgen"></param>\r
51                 public override void Emit (ILGenerator ilgen, Class host)\r
52                 {\r
53                         if (operand is string) {\r
54                                 ilgen.Emit (Opcode, operand as string);\r
55                         } else if (operand is Int32) {\r
56                                 ilgen.Emit (Opcode, (Int32)operand);\r
57                         }\r
58                 }\r
59         }\r
60 \r
61 \r
62         /// <summary>\r
63         /// </summary>\r
64         public class InstrI : InstrBase {\r
65 \r
66                 private int operand;\r
67 \r
68                 /// <summary>\r
69                 /// </summary>\r
70                 /// <param name="tok"></param>\r
71                 public InstrI (OpCode op, int operand) : base (op) {\r
72                         this.operand = operand;\r
73                 }\r
74 \r
75 \r
76                 /// <summary>\r
77                 /// </summary>\r
78                 /// <param name="ilgen"></param>\r
79                 public override void Emit (ILGenerator ilgen, Class host) {\r
80                                 ilgen.Emit (Opcode, operand);\r
81                 }\r
82         }\r
83 \r
84 \r
85         /// <summary>\r
86         /// </summary>\r
87         public class InstrI8 : InstrBase {\r
88 \r
89                 private long operand;\r
90 \r
91                 /// <summary>\r
92                 /// </summary>\r
93                 /// <param name="tok"></param>\r
94                 public InstrI8 (OpCode op, long operand) : base (op) {\r
95                         this.operand = operand;\r
96                 }\r
97 \r
98 \r
99                 /// <summary>\r
100                 /// </summary>\r
101                 /// <param name="ilgen"></param>\r
102                 public override void Emit (ILGenerator ilgen, Class host) {\r
103                         ilgen.Emit (Opcode, operand);\r
104                 }\r
105         }\r
106 \r
107 \r
108         /// <summary>\r
109         /// </summary>\r
110         public class InstrR : InstrBase {\r
111 \r
112                 private double operand;\r
113 \r
114                 /// <summary>\r
115                 /// </summary>\r
116                 /// <param name="tok"></param>\r
117                 public InstrR (OpCode op, double operand) : base (op) {\r
118                         this.operand = operand;\r
119                 }\r
120 \r
121 \r
122                 /// <summary>\r
123                 /// </summary>\r
124                 /// <param name="ilgen"></param>\r
125                 public override void Emit (ILGenerator ilgen, Class host) {\r
126                         if (Opcode.Name.IndexOf (".r4") != -1) {\r
127                                 ilgen.Emit (Opcode, (float) operand);\r
128                         } else {\r
129                                 ilgen.Emit (Opcode, operand);\r
130                         }\r
131                 }\r
132         }\r
133 \r
134 \r
135 \r
136         /// <summary>\r
137         /// </summary>\r
138         public class InstrString : InstrBase {\r
139 \r
140                 private string operand;\r
141 \r
142                 /// <summary>\r
143                 /// </summary>\r
144                 /// <param name="tok"></param>\r
145                 public InstrString (OpCode op, string operand) : base (op) {\r
146                         this.operand = operand;\r
147                 }\r
148 \r
149 \r
150                 /// <summary>\r
151                 /// </summary>\r
152                 /// <param name="ilgen"></param>\r
153                 public override void Emit (ILGenerator ilgen, Class host) {\r
154                         ilgen.Emit (Opcode, operand);\r
155                 }\r
156         }\r
157 \r
158 \r
159         /// <summary>\r
160         ///   Base class for instructions that call methods\r
161         /// </summary>\r
162         public abstract class InstrCallBase : InstrBase {\r
163                 \r
164                 private string return_type;\r
165                 private string binding_flags;\r
166                 private string calling_type;\r
167                 private string method_name;\r
168                 private ArrayList arg_list;\r
169         \r
170                 /// <summary>\r
171                 /// </summary>\r
172                 /// <param name="tok"></param>\r
173                 public InstrCallBase (OpCode op, string binding_flags, string return_type, \r
174                                 string calling_type, string method_name, ArrayList arg_list) : base (op) {\r
175 \r
176                         this.binding_flags = binding_flags;\r
177                         this.return_type = return_type;\r
178                         this.calling_type = calling_type;\r
179                         this.method_name = method_name;\r
180                         this.arg_list = arg_list;\r
181                         \r
182                 }\r
183 \r
184                 protected Type[] CreateArgsTypeArray (CodeGen code_gen)\r
185                 {\r
186                         if (arg_list == null)\r
187                                 return new Type[0];\r
188 \r
189                         int size = arg_list.Count;\r
190                         Type[] type_array = new Type[size];\r
191 \r
192                         for (int i=0; i<size; i++) {\r
193                                 type_array[i] = code_gen.TypeManager[(string)arg_list[i]];\r
194                         }\r
195 \r
196                         return type_array;\r
197                 }\r
198 \r
199                 protected BindingFlags CreateBindingFlags ()\r
200                 {       \r
201                         if ((binding_flags == null) || (binding_flags == String.Empty))\r
202                                 return (BindingFlags.Static | BindingFlags.Public);\r
203         \r
204                         BindingFlags return_flags = BindingFlags.Public;\r
205                         \r
206                         switch (binding_flags) {\r
207                         case "instance":\r
208                                 return_flags |= BindingFlags.Instance;\r
209                                 break;\r
210                         }                       \r
211 \r
212                         return return_flags;\r
213                 }\r
214                 \r
215 \r
216         }\r
217 \r
218         /// <summary>\r
219         ///   call void System.Console::WriteLine(string)\r
220         /// </summary>\r
221         public class InstrCall : InstrCallBase {\r
222         \r
223                 /// <summary>\r
224                 /// </summary>\r
225                 /// <param name="tok"></param>\r
226                 public InstrCall (OpCode op, string binding_flags, string return_type, string calling_type, \r
227                         string method_name, ArrayList arg_list) : base (op, binding_flags, \r
228                                 return_type, calling_type, method_name, arg_list) {\r
229 \r
230                 }\r
231 \r
232 \r
233                 /// <summary>\r
234                 /// </summary>\r
235                 /// <param name="ilgen"></param>\r
236                 public override void Emit (ILGenerator ilgen, Class host) {\r
237                         Type type_to_call = host.CodeGen.TypeManager[calling_type];\r
238                         MethodInfo calling_method;\r
239                         \r
240                         if (type_to_call == host.TypeBuilder) {\r
241                                 calling_method = host.GetMethod (method_name, CreateBindingFlags (), \r
242                                         CreateArgsTypeArray (host.CodeGen));\r
243                         } else {\r
244                                 calling_method = type_to_call.GetMethod (method_name, CreateBindingFlags (), \r
245                                         null, CreateArgsTypeArray (host.CodeGen), null);\r
246                         }\r
247 \r
248                         if (calling_method == null) {\r
249                                 Console.WriteLine ("Method does not exist: {0}.{1}", type_to_call, method_name);\r
250                                 return;\r
251                         }\r
252 \r
253                         ilgen.Emit (Opcode, calling_method);\r
254                 \r
255                 }\r
256                 \r
257         }\r
258 \r
259                 /// <summary>\r
260         /// </summary>\r
261         public class InstrNewobj : InstrCallBase {\r
262         \r
263                 /// <summary>\r
264                 /// </summary>\r
265                 /// <param name="tok"></param>\r
266                 public InstrNewobj (OpCode op, string binding_flags, string return_type, string calling_type, \r
267                         string method_name, ArrayList arg_list) : base (op, binding_flags,\r
268                                 return_type, calling_type, method_name, arg_list) {\r
269 \r
270                 }\r
271 \r
272 \r
273                 /// <summary>\r
274                 /// </summary>\r
275                 /// <param name="ilgen"></param>\r
276                 public override void Emit (ILGenerator ilgen, Class host) {\r
277                         Type type_to_call = host.CodeGen.TypeManager[calling_type];\r
278                         ConstructorInfo calling_constructor = null;\r
279 \r
280                         calling_constructor = type_to_call.GetConstructor (CreateArgsTypeArray (host.CodeGen));\r
281                         \r
282                         if (calling_constructor == null) {\r
283                                 Console.WriteLine ("Constructor does not exist for: {0}", type_to_call);\r
284                                 return;\r
285                         }\r
286 \r
287                         ilgen.Emit (Opcode, calling_constructor);\r
288                 }\r
289         }\r
290 }\r
291 \r