// Instructions.cs // (C) Sergey Chaban (serge@wildwestsoftware.com) using System; using System.Reflection; using System.Reflection.Emit; using System.Collections; namespace Mono.ILASM { /// /// public class InstrNone : InstrBase { /// /// /// public InstrNone (OpCode op) : base (op) { } /// /// /// public override void Emit (ILGenerator ilgen, Class host) { ilgen.Emit (this.Opcode); } } /// /// public class InstrVar : InstrBase { private object operand; /// /// /// public InstrVar (OpCode op, object operand) : base (op) { this.operand = operand; } /// /// /// public override void Emit (ILGenerator ilgen, Class host) { if (operand is string) { ilgen.Emit (Opcode, operand as string); } else if (operand is Int32) { ilgen.Emit (Opcode, (Int32)operand); } } } /// /// public class InstrI : InstrBase { private int operand; /// /// /// public InstrI (OpCode op, int operand) : base (op) { this.operand = operand; } /// /// /// public override void Emit (ILGenerator ilgen, Class host) { ilgen.Emit (Opcode, operand); } } /// /// public class InstrI8 : InstrBase { private long operand; /// /// /// public InstrI8 (OpCode op, long operand) : base (op) { this.operand = operand; } /// /// /// public override void Emit (ILGenerator ilgen, Class host) { ilgen.Emit (Opcode, operand); } } /// /// public class InstrR : InstrBase { private double operand; /// /// /// public InstrR (OpCode op, double operand) : base (op) { this.operand = operand; } /// /// /// public override void Emit (ILGenerator ilgen, Class host) { if (Opcode.Name.IndexOf (".r4") != -1) { ilgen.Emit (Opcode, (float) operand); } else { ilgen.Emit (Opcode, operand); } } } /// /// public class InstrString : InstrBase { private string operand; /// /// /// public InstrString (OpCode op, string operand) : base (op) { this.operand = operand; } /// /// /// public override void Emit (ILGenerator ilgen, Class host) { ilgen.Emit (Opcode, operand); } } /// /// Base class for instructions that call methods /// public abstract class InstrCallBase : InstrBase { private string return_type; private string binding_flags; private string calling_type; private string method_name; private ArrayList arg_list; /// /// /// public InstrCallBase (OpCode op, string binding_flags, string return_type, string calling_type, string method_name, ArrayList arg_list) : base (op) { this.binding_flags = binding_flags; this.return_type = return_type; this.calling_type = calling_type; this.method_name = method_name; this.arg_list = arg_list; } protected Type[] CreateArgsTypeArray (CodeGen code_gen) { if (arg_list == null) return new Type[0]; int size = arg_list.Count; Type[] type_array = new Type[size]; for (int i=0; i /// call void System.Console::WriteLine(string) /// public class InstrCall : InstrCallBase { /// /// /// public InstrCall (OpCode op, string binding_flags, string return_type, string calling_type, string method_name, ArrayList arg_list) : base (op, binding_flags, return_type, calling_type, method_name, arg_list) { } /// /// /// public override void Emit (ILGenerator ilgen, Class host) { Type type_to_call = host.CodeGen.TypeManager[calling_type]; MethodInfo calling_method; if (type_to_call == host.TypeBuilder) { calling_method = host.GetMethod (method_name, CreateBindingFlags (), CreateArgsTypeArray (host.CodeGen)); } else { calling_method = type_to_call.GetMethod (method_name, CreateBindingFlags (), null, CreateArgsTypeArray (host.CodeGen), null); } if (calling_method == null) { Console.WriteLine ("Method does not exist: {0}.{1}", type_to_call, method_name); return; } ilgen.Emit (Opcode, calling_method); } } /// /// public class InstrNewobj : InstrCallBase { /// /// /// public InstrNewobj (OpCode op, string binding_flags, string return_type, string calling_type, string method_name, ArrayList arg_list) : base (op, binding_flags, return_type, calling_type, method_name, arg_list) { } /// /// /// public override void Emit (ILGenerator ilgen, Class host) { Type type_to_call = host.CodeGen.TypeManager[calling_type]; ConstructorInfo calling_constructor = null; calling_constructor = type_to_call.GetConstructor (CreateArgsTypeArray (host.CodeGen)); if (calling_constructor == null) { Console.WriteLine ("Constructor does not exist for: {0}", type_to_call); return; } ilgen.Emit (Opcode, calling_constructor); } } }