2 // (C) Sergey Chaban (serge@wildwestsoftware.com)
\r
5 using System.Reflection;
\r
6 using System.Reflection.Emit;
\r
7 using System.Collections;
\r
9 namespace Mono.ILASM {
\r
14 public class InstrNone : InstrBase {
\r
18 /// <param name="tok"></param>
\r
19 public InstrNone (OpCode op) : base (op)
\r
25 /// <param name="ilgen"></param>
\r
26 public override void Emit (ILGenerator ilgen, Class host)
\r
28 ilgen.Emit (this.Opcode);
\r
35 public class InstrVar : InstrBase {
\r
37 private object operand;
\r
41 /// <param name="tok"></param>
\r
42 public InstrVar (OpCode op, object operand) : base (op)
\r
44 this.operand = operand;
\r
50 /// <param name="ilgen"></param>
\r
51 public override void Emit (ILGenerator ilgen, Class host)
\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
64 public class InstrI : InstrBase {
\r
66 private int operand;
\r
70 /// <param name="tok"></param>
\r
71 public InstrI (OpCode op, int operand) : base (op) {
\r
72 this.operand = operand;
\r
78 /// <param name="ilgen"></param>
\r
79 public override void Emit (ILGenerator ilgen, Class host) {
\r
80 ilgen.Emit (Opcode, operand);
\r
87 public class InstrI8 : InstrBase {
\r
89 private long operand;
\r
93 /// <param name="tok"></param>
\r
94 public InstrI8 (OpCode op, long operand) : base (op) {
\r
95 this.operand = operand;
\r
101 /// <param name="ilgen"></param>
\r
102 public override void Emit (ILGenerator ilgen, Class host) {
\r
103 ilgen.Emit (Opcode, operand);
\r
110 public class InstrR : InstrBase {
\r
112 private double operand;
\r
116 /// <param name="tok"></param>
\r
117 public InstrR (OpCode op, double operand) : base (op) {
\r
118 this.operand = operand;
\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
129 ilgen.Emit (Opcode, operand);
\r
138 public class InstrString : InstrBase {
\r
140 private string operand;
\r
144 /// <param name="tok"></param>
\r
145 public InstrString (OpCode op, string operand) : base (op) {
\r
146 this.operand = operand;
\r
152 /// <param name="ilgen"></param>
\r
153 public override void Emit (ILGenerator ilgen, Class host) {
\r
154 ilgen.Emit (Opcode, operand);
\r
160 /// Base class for instructions that call methods
\r
162 public abstract class InstrCallBase : InstrBase {
\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
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
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
184 protected Type[] CreateArgsTypeArray (CodeGen code_gen)
\r
186 if (arg_list == null)
\r
187 return new Type[0];
\r
189 int size = arg_list.Count;
\r
190 Type[] type_array = new Type[size];
\r
192 for (int i=0; i<size; i++) {
\r
193 type_array[i] = code_gen.TypeManager[(string)arg_list[i]];
\r
199 protected BindingFlags CreateBindingFlags ()
\r
201 if ((binding_flags == null) || (binding_flags == String.Empty))
\r
202 return (BindingFlags.Static | BindingFlags.Public);
\r
204 BindingFlags return_flags = BindingFlags.Public;
\r
206 switch (binding_flags) {
\r
208 return_flags |= BindingFlags.Instance;
\r
212 return return_flags;
\r
219 /// call void System.Console::WriteLine(string)
\r
221 public class InstrCall : InstrCallBase {
\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
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
240 if (type_to_call == host.TypeBuilder) {
\r
241 calling_method = host.GetMethod (method_name, CreateBindingFlags (),
\r
242 CreateArgsTypeArray (host.CodeGen));
\r
244 calling_method = type_to_call.GetMethod (method_name, CreateBindingFlags (),
\r
245 null, CreateArgsTypeArray (host.CodeGen), null);
\r
248 if (calling_method == null) {
\r
249 Console.WriteLine ("Method does not exist: {0}.{1}", type_to_call, method_name);
\r
253 ilgen.Emit (Opcode, calling_method);
\r
261 public class InstrNewobj : InstrCallBase {
\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
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
280 calling_constructor = type_to_call.GetConstructor (CreateArgsTypeArray (host.CodeGen));
\r
282 if (calling_constructor == null) {
\r
283 Console.WriteLine ("Constructor does not exist for: {0}", type_to_call);
\r
287 ilgen.Emit (Opcode, calling_constructor);
\r