// 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);
}
}
}