/*
The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language
governing rights and limitations under the License.
The Original Code is RAIL(Runtime Assembly Instrumentation Library) Alpha Version.
The Initial Developer of the Original Code is University of Coimbra,
Computer Science Department, Dependable Systems Group. Copyright (C) University of Coimbra.
All Rights Reserved.
*/
using System;
using System.Reflection.Emit;
using System.Diagnostics;
using System.Reflection;
using System.Collections;
using Rail.Reflect;
namespace Rail.MSIL{
/// <summary>
///
/// </summary>
/// <remarks>
/// Guidelines:
///
/// <list type="numbered">
/// <item> Instructions that have an .un (unsigned or unordered version) are
/// represented only by one method, which takes a boolean parameter called signed.
/// For instance: <code>public void Add_Ovf(bool signed);</code>
/// </item>
///
/// <item> The calli opcode/EmitCalli method is not supported. Use the underlying
/// ILGenerator to emit it.
/// </item>
///
/// </list>
///
/// </remarks>
public sealed class ILFactory
{
#region Base Instructions
/*
* This includes:
*
* add, add.ovf, and, arglist, beq, bge, bge.un, ble, ble.un
* blt, blt.un, bne.un, br, break, brfalse, brtrue, call, calli, ceq, cgt,
* cgt.un, ckfinite, clt, clt.un, conv, conv.ovf.<totype>, conv.ovf.<totype>.un,
* cpblk, div, div.un, dup, endfilter, endfinally, initblk, jmp, jmpi, ldarg,
* ldarga, ldc, ldftn, ldind, ldloc, ldloca, ldnull, leave, localloc, mul, mul.ovf,
* neg, nop, not, or, pop, rem, rem.un, ret, shl, shr, shr.un, starg, stind, stloc,
* sub, sub.ovf, switch, tail, unaligned, volatile, xor
*
* A lot!!!
*/
/// <summary>
/// add - add numeric values
/// <code>value1, value2 -> result</code>
/// </summary>
public static Instruction Add()
{
return new ILNone(OpCodes.Add);
}
/// <summary>
/// add.ovf.<signed> - add integer values with overflow check
/// <code>value1, value2 -> result</code>
/// </summary>
/// <param name="signed">Whether add.ovf or add.ovf.un should be used</param>
public static Instruction Add_Ovf(bool signed)
{
OpCode op = signed ? OpCodes.Add_Ovf : OpCodes.Add_Ovf_Un;
return new ILNone(op);
}
/// <summary>
/// and - bitwise AND
/// <code>value1, value2 -> result</code>
/// </summary>
public static Instruction And()
{
return new ILNone(OpCodes.And);
}
/// <summary>
/// arglist - get argument list
/// <code> -> </code>
/// </summary>
public static Instruction Arglist()
{
return new ILNone(OpCodes.Arglist);
}
/// <summary>
/// beq.<length> branch on equal
/// <code>value1, value2 -> </code>
/// </summary>
/// <param name="target">The target instruction</param>
public static Instruction Beq(Instruction target)
{
return new ILBranch(OpCodes.Beq, target);
}
/// <summary>
/// bge.<length> branch on greater than or equal to
/// bge.un.<length> branch on greater/equal, unsigned or unordered
/// <code>value1, value2 -> </code>
/// </summary>
/// <param name="signed">Whether to use bge or bge.un</param>
/// <param name="target">The target instruction</param>
public static Instruction Bge(bool signed, Instruction target)
{
OpCode op = signed ? OpCodes.Bge: OpCodes.Bge_Un;
return new ILBranch(op, target);
}
/// <summary>
/// bgt.<length> branch on greater than
/// bgt.un.<length> branch on greater than, unsigned or unordered
/// <code>value1, value2 -> </code>
/// </summary>
/// <param name="signed">If the instruction is signed</param>
/// <param name="target">The target instruction</param>
public static Instruction Bgt(bool signed, Instruction target)
{
OpCode op = signed ? OpCodes.Bgt : OpCodes.Bgt_Un;
return new ILBranch(op, target);
}
/// <summary>
/// ble._ branch on less than or equal to
/// ble.un._ branch on less/equal, unsigned or unordered
/// <code>value1, value2 -> </code>
/// </summary>
/// <param name="signed">If the instruction is signed</param>
/// <param name="target">the target instruction</param>
public static Instruction Ble(bool signed, Instruction target)
{
OpCode op = signed ? OpCodes.Ble :OpCodes.Ble_Un;
return new ILBranch(op, target);
}
/// <summary>
/// blt._ branch on less than
/// blt.un._ branch on less than, unsigned or unordered
/// <code>value1, value2 -> </code>
/// </summary>
/// <param name="signed">If the instruction is signed</param>
/// <param name="target">The target instruction</param>
public static Instruction Blt(bool signed, Instruction target)
{
OpCode op = signed ? OpCodes.Blt :OpCodes.Blt_Un;
return new ILBranch(op, target);
}
/// <summary>
/// bne.un branch on not equal or unordered
/// <code> value1, value2 -> </code>
/// </summary>
/// <param name="target"></param>
public static Instruction Bne_Un(Instruction target)
{
return new ILBranch(OpCodes.Bne_Un, target);
}
/// <summary>
/// br._ unconditional branch
/// <code> -> </code>
/// </summary>
/// <param name="target"></param>
public static Instruction Br(Instruction target)
{
return new ILBranch(OpCodes.Br, target);
}
/// <summary>
/// Unconditional branch
/// </summary>
/// <param name="target"></param>
/// <returns></returns>
public static Instruction BrS(Instruction target)
{
return new ILBranch(OpCodes.Br_S,target);
}
/// <summary>
/// break breakpoint instruction
/// <code> -> </code>
/// </summary>
/// <param name="target"></param>
public static Instruction Break(Instruction target)
{
return new ILBranch(OpCodes.Break, target);
}
/// <summary>
/// brfalse._ - branch on false, null, or zero
/// brtrue._ - branch on non-false or non-null
/// <code>value -> </code>
/// </summary>
/// <param name="condition">True for <code>brtrue</code>, false for <code>brfalse</code></param>
/// <param name="target">The target instruction</param>
public static Instruction Br(bool condition, Instruction target)
{
OpCode op = condition ? OpCodes.Brtrue : OpCodes.Brfalse;
return new ILBranch(op, target);
}
/// <summary>
/// brfalse.S_ - branch on false, null, or zero
/// brtrue.S_ - branch on non-false or non-null
/// <code>value -> </code>
/// </summary>
/// <param name="condition">True for <code>brtrue</code>, false for <code>brfalse</code></param>
/// <param name="target">The target instruction</param>
public static Instruction BrS(bool condition, Instruction target)
{
OpCode op = condition ? OpCodes.Brtrue_S : OpCodes.Brfalse_S;
return new ILBranch(op, target);
}
/// <summary>
/// call call a method
/// callvirt call a method associated, at runtime, with an object
/// <code> obj, arg1, arg2 argn -> retVal (not always returned)</code>
/// </summary>
/// <remarks>
/// The obj argument is only necessary if calling an instance or virtual
/// method.
/// </remarks>
/// <param name="callVirtual">Whether to call the method virtually or statically.</param>
/// <param name="method">The method to be called. May be a ConstructorInfo
/// or a MethodInfo.</param>
public static Instruction Call(bool callVirtual, RMethodBase method)
{
OpCode op = callVirtual ? OpCodes.Callvirt : OpCodes.Call;
return new ILMethod(op, method);
}
/// <summary>
/// ceq - compare equal
/// <code>value1, value2 -> result</code>
/// </summary>
public static Instruction Ceq()
{
return new ILNone(OpCodes.Ceq);
}
/// <summary>
/// cgt - compare greater than
/// cgt.un - compare greater than, unsigned or unordered
/// <code> value1, value2 -> result</code>
/// </summary>
public static Instruction Cgt(bool signed)
{
return new ILNone(signed ? OpCodes.Cgt : OpCodes.Cgt_Un);
}
/// <summary>
/// <p>ckfinite check for a finite real number</p>
/// <code> value -> value</code>
/// </summary>
public static Instruction Ckfinite()
{
return new ILNone(OpCodes.Ckfinite);
}
/// <summary>
/// clt - compare less than
/// clt.un - compare less than, unsigned or unordered
/// <code>value1, value2 -> result</code>
/// </summary>
/// <param name="signed">Whether to use clt or clt.un</param>
public static Instruction Clt(bool signed)
{
OpCode op = signed ? OpCodes.Clt : OpCodes.Clt_Un;
return new ILNone(op);
}
/// <summary>
/// conv._to type - data conversion
/// <code> value -> result</code>
/// </summary>
/// <remarks>
/// The given type may be one of the primitive types and IntPtr or UIntPtr.
/// To emit the <code>conv.r.un</code> instruction use the internal
/// <code>ILGenerator</code>
/// </remarks>
/// <param name="type">The type for the conversion</param>
public static Instruction Conv(Type type)
{
CLROperandType op = (CLROperandType) typeToCLROperand[type];
if (op == null)
{
throw new ArgumentException("Only CLR types are allowed. Found: " + type);
}
if (Object.ReferenceEquals(op.Conv, OpCodes.Nop))
throw new InvalidProgramException();
return new ILNone(op.Conv);
}
/// <summary>
/// conv.ovf._to_type - data conversion with overflow detection
/// conv.ovf._to_type.un unsigned data conversion with overflow detection
/// <code> value -> result</code>
/// </summary>
/// <remarks>
/// The given type may be one of the primitive types including
/// IntPtr and UIntPtr, but excluding floating point values.
/// <code>ILGenerator</code>
/// </remarks>
/// <param name="signed">Whether to use <code>conv_ovf</code> or conv.ovf._type.un</param>
/// <param name="type"></param>
public static Instruction Conv_Ovf(bool signed, Type type)
{
// floating points values don't have conversion operators with overflow checking
if (type != typeof(System.Single) && type != typeof(System.Double))
{
CLROperandType opType = (CLROperandType)typeToCLROperand[type];
if (opType != null)
{
OpCode opCode;
opCode = signed ? opType.Conv_Ovf : opType.Conv_Ovf_Un;
//Debug.Assert(!Object.ReferenceEquals(opCode, OpCodes.Nop));
if (Object.ReferenceEquals(opCode, OpCodes.Nop))
throw new InvalidProgramException();
return new ILNone(opCode);
}
}
throw new ArgumentException("Valid types: Byte, SByte, Int16/32/64, Uint16/32/64, IntPtr, UIntPtr. Found: " + type);
}
/// <summary>
/// cpblk - copy data from memory to memory
/// <code>destaddr, srcaddr, size -> </code>
/// </summary>
public static Instruction Cpblk()
{
return new ILNone(OpCodes.Cpblk);
}
/// <summary>
/// div - divide values
/// div.un - divide integer values, unsigned
/// <code>value1, value2 -> result</code>
/// </summary>
/// <param name="signed">Whether to emit div or div.un</param>
public static Instruction Div(bool signed)
{
OpCode op = signed ? OpCodes.Div : OpCodes.Div_Un;
return new ILNone(op);
}
/// <summary>
/// dup duplicate the top value of the stack
/// <code>value -> value, value</code>
/// </summary>
public static Instruction Dup()
{
return new ILNone(OpCodes.Dup);
}
/// <summary>
/// endfilter end filter clause of SEH
/// <code>value -> </code>
/// </summary>
public static Instruction Endfilter()
{
return new ILNone(OpCodes.Endfilter);
}
/// <summary>
/// endfinally end finally clause of an exception block
/// <code> -> </code>
/// </summary>
public static Instruction Endfinaly()
{
return new ILNone(OpCodes.Endfinally);
}
/// <summary>
/// initblk - initialize a block of memory to a value
/// <code> addr, value, size -> </code>
/// </summary>
public static Instruction Initblk()
{
return new ILNone(OpCodes.Initblk);
}
/// <summary>
/// jmp jump to method
/// <code> -> </code>
/// </summary>
public static Instruction Jmp(RMethodBase method)
{
return new ILMethod(OpCodes.Jmp, method);
}
/// <summary>
/// ldarg.length - load argument onto the stack
/// <code> -> value </code>
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="parameter">The parameter to be loaded.</param>
public static Instruction Ldarg(RParameter parameter)
{
return new ILArgument(OpCodes.Ldarg, parameter);
}
/// <summary>
/// ldarga.length - load an argument address
/// <code> -> address of argument number argNum</code>
/// </summary>
/// <param name="parameter"></param>
public static Instruction Ldarga(RParameter parameter)
{
return new ILArgument(OpCodes.Ldarga, parameter);
}
/// <summary>
/// ldc.i4.x - load numeric constant
/// <code> -> num</code>
/// </summary>
/// <param name="iConst"></param>
public static Instruction Ldc(int iConst)
{
switch(iConst)
{
case 0:
return new ILNone(OpCodes.Ldc_I4_0);
case 1:
return new ILNone(OpCodes.Ldc_I4_1);
case 2:
return new ILNone(OpCodes.Ldc_I4_2);
case 3:
return new ILNone(OpCodes.Ldc_I4_3);
case 4:
return new ILNone(OpCodes.Ldc_I4_4);
case 5:
return new ILNone(OpCodes.Ldc_I4_5);
case 6:
return new ILNone(OpCodes.Ldc_I4_6);
case 7:
return new ILNone(OpCodes.Ldc_I4_7);
case 8:
return new ILNone(OpCodes.Ldc_I4_8);
default:
return new ILOperandI4(OpCodes.Ldc_I4, iConst);
}
}
/// <summary>
/// ldc.i8 - load numeric constant
/// <code> -> num</code>
/// </summary>
/// <param name="lConstant"></param>
public static Instruction Ldc(Int64 lConstant)
{
return new ILOperandI8(OpCodes.Ldc_I8, lConstant);
}
/// <summary>
/// ldc.r8 - load numeric constant
/// <code> -> num</code>
/// </summary>
/// <param name="fConstant"></param>
public static Instruction Ldc(Double fConstant)
{
return new ILOperandR8(OpCodes.Ldc_R8, fConstant);
}
/// <summary>
/// ldc.r4 - load numeric constant
/// <code> -> num</code>
/// </summary>
/// <param name="fConstant"></param>
public static Instruction Ldc(Single fConstant)
{
return new ILOperandR4(OpCodes.Ldc_R4, fConstant);
}
/// <summary>
/// ldftn - load method pointer
/// <code> -> ftn</code>
/// </summary>
public static Instruction Ldftn(RMethodBase mi)
{
return new ILMethod(OpCodes.Ldftn, mi);
}
/// <summary>
/// ldind._type_ - load value indirect onto the stack
/// <code>addr -> value</code>
/// </summary>
/// <remarks>
/// If <code>t</code> is not one of the CLR primitive types then
/// it must be System.Object. In this case, a <code>ldind.ref</code>
/// opcode is pushed onto the stack. Otherwise, an exception is raised.
/// </remarks>
/// <param name="t"></param>
public static Instruction Ldind(Type t)
{
CLROperandType op = (CLROperandType)typeToCLROperand[t];
if (op==null)
{
throw new ArgumentException("Type must be one of the CLR primitive types or System.Object. Found: " + t);
}
else
{
if (Object.ReferenceEquals(op.Ldind, OpCodes.Nop))
throw new InvalidProgramException();
return new ILNone(op.Ldind);
}
}
/// <summary>
/// ldloc - load local variable onto the stack
/// <code> -> value</code>
/// </summary>
/// <param name="local"></param>
public static Instruction Ldloc(LocalVariable local)
{
return new ILLocalVariable(OpCodes.Ldloc, local);
}
/// <summary>
/// ldloca._ - load local variable address
/// <code> -> address</code>
/// </summary>
/// <param name="local"></param>
public static Instruction Ldloca(LocalVariable local)
{
return new ILLocalVariable(OpCodes.Ldloca, local);
}
/// <summary>
/// ldnull load a null pointer
/// <code> -> null value</code>
/// </summary>
public static Instruction Ldnull()
{
return new ILNone(OpCodes.Ldnull);
}
/// <summary>
/// leave._ exit a protected region of code
/// <code> -> </code>
/// </summary>
/// <param name="target">The target instruction</param>
public static Instruction Leave(Instruction target)
{
return new ILBranch(OpCodes.Leave, target);
}
/// <summary>
/// localloc allocate space in the local dynamic memory pool
/// <code> size -> address </code>
/// </summary>
public static Instruction Localloc()
{
return new ILNone(OpCodes.Localloc);
}
/// <summary>
/// mul - multiply values
/// <code> value1, value2 -> result </code>
/// </summary>
public static Instruction Mul()
{
return new ILNone(OpCodes.Mul);
}
/// <summary>
/// mul.ovf - Multiply signed integer values. Signed result must fit in same size
/// mul.ovf.un - Multiply unsigned integer values. Unsigned result must fit in same size ///
/// <code> value1, value2 -> result </code>
/// </summary>
public static Instruction Mul_Ovf(bool signed)
{
OpCode op = signed ? OpCodes.Mul_Ovf : OpCodes.Mul_Ovf_Un;
return new ILNone(op);
}
/// <summary>
/// neg - negate
/// <code> value -> result </code>
/// </summary>
public static Instruction Neg()
{
return new ILNone(OpCodes.Neg);
}
/// <summary>
/// nop no operation
/// <code> -> </code>
/// </summary>
public static Instruction Nop()
{
return new ILNone(OpCodes.Nop);
}
/// <summary>
/// not - bitwise complement
/// <code> value -> result </code>
/// </summary>
public static Instruction Not()
{
return new ILNone(OpCodes.Not);
}
/// <summary>
/// or - bitwise OR
/// <code> value1, value2 -> result </code>
/// </summary>
public static Instruction Or()
{
return new ILNone(OpCodes.Or);
}
/// <summary>
/// pop remove the top element of the stack
/// <code> value -> </code>
/// </summary>
public static Instruction Pop()
{
return new ILNone(OpCodes.Pop);
}
/// <summary>
/// rem - compute remainder
/// rem.un - compute integer remainder, unsigned
/// <code> value1, value2 -> result </code>
/// </summary>
public static Instruction Rem(bool signed)
{
OpCode op = signed ? OpCodes.Rem : OpCodes.Rem_Un;
return new ILNone(op);
}
/// <summary>
/// ret return from method
/// <code> retVal on callee evaluation stack (not always present)
/// -> retVal on caller evaluation stack (not always present) </code>
/// </summary>
public static Instruction Ret()
{
return new ILNone(OpCodes.Ret);
}
/// <summary>
/// shl - shift integer left
/// <code> value, shiftAmount -> result </code>
/// </summary>
public static Instruction Shl()
{
return new ILNone(OpCodes.Shl);
}
/// <summary>
/// shr - shift integer right
/// shr.un - shift integer right, unsigned
/// <code> value, shiftAmount -> result </code>
/// </summary>
public static Instruction Shr(bool signed)
{
OpCode op = signed ? OpCodes.Shr : OpCodes.Shr_Un;
return new ILNone(op);
}
/// <summary>
/// starg._ - store a value in an argument slot
/// <code> value -> </code>
/// </summary>
/// <param name="arg"></param>
public static Instruction Starg(RParameter arg)
{
return new ILArgument(OpCodes.Starg, arg);
}
/// <summary>
/// stind._type - store value indirect from stack
/// <code>addr, value -> </code>
/// </summary>
/// <remarks>
/// If <code>t</code> is not one of the CLR primitive types then
/// it must be System.Object. In this case, a <code>ldind.ref</code>
/// opcode is pushed onto the stack. Otherwise, an exception is raised.
/// </remarks>
/// <param name="t"></param>
public static Instruction Stind(Type t)
{
CLROperandType op = (CLROperandType)typeToCLROperand[t];
if (op==null)
{
throw new ArgumentException("Type must be one of the CLR primitive types or System.Object. Found: " + t);
}
else
{
if (Object.ReferenceEquals(op.Stind, OpCodes.Nop))
throw new InvalidProgramException();
return new ILNone(op.Stind);
}
}
/// <summary>
/// stloc - pop value from stack to local variable
/// <code> value -> </code>
/// </summary>
public static Instruction Stloc(LocalVariable local)
{
return new ILLocalVariable(OpCodes.Stloc, local);
}
/// <summary>
/// sub - subtract numeric values
/// <code> value1, value2 -> result </code>
/// </summary>
public static Instruction Sub()
{
return new ILNone(OpCodes.Sub);
}
/// <summary>
/// sub.ovf - Subtract native int from a native int. Signed result must fit in same size
/// sub.ovf.un - Subtract native unsigned int from a native unsigned int. Unsigned result must fit in same size
/// <code> value, shiftAmount -> result </code>
/// </summary>
public static Instruction Sub_Ovf(bool signed)
{
OpCode op = signed ? OpCodes.Sub_Ovf : OpCodes.Sub_Ovf_Un;
return new ILNone(op);
}
/// <summary>
/// switch table switch on value
/// <code> value -> </code>
/// </summary>
/// <param name="targets">The jump points for this switch</param>
public static Instruction Switch(Instruction[] targets)
{
return new ILSwitch(OpCodes.Switch, targets);
}
/// <summary>
/// xor - bitwise XOR
/// <code> value1, value2 -> result </code>
/// </summary>
public static Instruction Xor()
{
return new ILNone(OpCodes.Xor);
}
#endregion
public static Instruction BeginExceptionBlock (ExceptionBlock eb) {
return new ILVirtualException(eb, true);
}
public static Instruction EndExceptionBlock (ExceptionBlock eb) {
return new ILVirtualException(eb, false);
}
public static Instruction BeginFaultBlock (ExceptionBlock eb) {
return new ILVirtualException(eb, ExceptionHandlerType.Fault);
}
public static Instruction BeginFinallyBlock (ExceptionBlock eb) {
return new ILVirtualException(eb, ExceptionHandlerType.Finally);
}
public static Instruction BeginExceptionBlock (ExceptionBlock eb, ExceptionHandler ch) {
return new ILVirtualException(eb, ExceptionHandlerType.Catch, ch.ExceptionType);
}
#region Object model support instructions
/// <summary>
/// box convert value type to object reference
/// <code> valueType -> obj </code>
/// </summary>
/// <param name="t"></param>
public static Instruction Box(RType t)
{
return new ILType(OpCodes.Box, t);
}
/// <summary>
/// castclass cast an object to a class
/// <code> obj1 -> obj2 </code>
/// </summary>
/// <param name="t"></param>
public static Instruction Castclass(RType t)
{
return new ILType(OpCodes.Castclass, t);
}
/// <summary>
/// cpobj - copy a value type
/// <code> destValObj, srcValObj -> </code>
/// </summary>
/// <param name="t"></param>
public static Instruction Cpobj(RType t)
{
return new ILType(OpCodes.Cpobj, t);
}
/// <summary>
/// initobj - initialize a value type
/// <code> addrOfValObj -> </code>
/// </summary>
/// <param name="t"></param>
public static Instruction Initobj(RType t)
{
return new ILType(OpCodes.Initobj, t);
}
/// <summary>
/// isinst test if an object is an instance of a class or interface
/// <code> obj -> result </code>
/// </summary>
/// <param name="t"></param>
public static Instruction Isinst(RType t)
{
return new ILType(OpCodes.Isinst, t);
}
/// <summary>
/// ldelem._type load an element of an array
/// <code> array, index -> value</code>
/// </summary>
/// <param name="t"></param>
public static Instruction Ldelem(Type t)
{
CLROperandType clrOp = (CLROperandType)typeToCLROperand[t];
if (clrOp == null)
{
throw new ArgumentException("Only CLR primitive types are allowed");
}
else
{
if (Object.ReferenceEquals(clrOp.Ldelem, OpCodes.Nop))
throw new InvalidProgramException();
return new ILNone(clrOp.Ldelem);
}
}
/// <summary>
/// ldelema load address of an element of an array
/// <code> array, index -> address </code>
/// </summary>
/// <param name="t"></param>
public static Instruction Ldelema(RType t)
{
return new ILType(OpCodes.Ldelema, t);
}
/// <summary>
/// ldfld load field of an object
/// <code> obj -> value </code>
/// </summary>
/// <param name="fi"></param>
public static Instruction Ldfld(RField fi)
{
return new ILField(OpCodes.Ldfld, fi);
}
/// <summary>
/// ldflda load field address
/// <code> obj -> address</code>
/// </summary>
/// <param name="fi"></param>
public static Instruction Ldflda(RField fi)
{
return new ILField(OpCodes.Ldflda, fi);
}
/// <summary>
/// ldlen load the length of an array
/// <code> array -> length </code>
/// </summary>
public static Instruction Ldlen()
{
return new ILNone(OpCodes.Ldlen);
}
/// <summary>
/// ldobj - copy value type to the stack
/// <code> addrOfValObj -> valObj</code>
/// </summary>
/// <param name="t"></param>
public static Instruction Ldobj(RType t)
{
return new ILType(OpCodes.Ldobj, t);
}
/// <summary>
/// ldsfld load static field of a class
/// <code> -> value </code>
/// </summary>
/// <param name="fi"></param>
public static Instruction Ldsfld(RField fi)
{
return new ILField(OpCodes.Ldsfld, fi);
}
/// <summary>
/// ldsflda load static field address
/// <code> -> address </code>
/// </summary>
/// <param name="fi"></param>
public static Instruction Ldsflda(RField fi)
{
return new ILField(OpCodes.Ldsflda, fi);
}
/// <summary>
/// ldstr load a literal string
/// <code> -> string </code>
/// </summary>
/// <param name="str"></param>
public static Instruction Ldstr(String str)
{
return new ILString(OpCodes.Ldstr, str);
}
/// <summary>
/// ldtoken - load the runtime representation of a metadata token
/// <code> -> RuntimeHandle </code>
/// </summary>
/// <param name="mi"></param>
public static Instruction Ldtoken(RMethod mi)
{
return new ILToken(OpCodes.Ldtoken, mi);
}
/// <summary>
/// ldtoken - load the runtime representation of a metadata token
/// <code> -> RuntimeHandle </code>
/// </summary>
/// <param name="fi"></param>
public static Instruction Ldtoken(RField fi)
{
return new ILToken(OpCodes.Ldtoken, fi);
}
/// <summary>
/// ldtoken - load the runtime representation of a metadata token
/// <code> -> RuntimeHandle </code>
/// </summary>
/// <param name="t"></param>
public static Instruction Ldtoken(RType t)
{
return new ILToken(OpCodes.Ldtoken, t);
}
/// <summary>
/// ldvirtftn - load a virtual method pointer
/// <code> object -> ftn </code>
/// </summary>
/// <param name="mi"></param>
public static Instruction Ldvirtftn(RMethodBase mi)
{
return new ILMethod(OpCodes.Ldvirtftn, mi);
}
/// <summary>
/// mkrefany push a typed reference on the stack
/// <code> ptr -> typedRef </code>
/// </summary>
/// <param name="t"></param>
public static Instruction Mkrefany(RType t)
{
return new ILType(OpCodes.Mkrefany, t);
}
/// <summary>
/// newarr create a zero-based, one-dimensional array
/// <code> numElems -> array </code>
/// </summary>
/// <param name="t"></param>
public static Instruction Newarr(RType t)
{
return new ILType(OpCodes.Newarr, t);
}
/// <summary>
/// newobj create a new object
/// <code> arg1, argN -> obj </code>
/// </summary>
/// <param name="ct"></param>
public static Instruction Newobj(RConstructor ct)
{
return new ILMethod(OpCodes.Newobj, ct);
}
/// <summary>
/// refanytype load the type out of a typed reference
/// <code> TypedRef -> type</code>
/// </summary>
public static Instruction Refanytype()
{
return new ILNone(OpCodes.Refanytype);
}
/// <summary>
/// refanyval load the address out of a typed reference
/// <code> TypedRef -> address</code>
/// </summary>
/// <param name="t"></param>
public static Instruction Refanyval(RType t)
{
return new ILType(OpCodes.Refanyval, t);
}
/// <summary>
/// rethrow rethrow the current exception
/// <code> -> </code>
/// </summary>
public static Instruction Rethrow()
{
return new ILNone(OpCodes.Rethrow);
}
/// <summary>
/// sizeof load the size in bytes of a value type
/// <code> -> size (4 bytes, unsigned) </code>
/// </summary>
/// <param name="t">Must be a value type.</param>
public static Instruction Sizeof(RType t)
{
return new ILType(OpCodes.Sizeof, t);
}
/// <summary>
/// stelem._type store an element of an array
/// <code> array, index, value -> </code>
/// </summary>
/// <param name="t"></param>
public static Instruction Stelem(Type t)
{
CLROperandType clrOp = (CLROperandType)typeToCLROperand[t];
if (clrOp == null)
{
throw new ArgumentException("Only CLR types are allowed");
}
else
{
if (Object.ReferenceEquals(clrOp.Stelem, OpCodes.Nop))
throw new InvalidProgramException();
return new ILNone(clrOp.Stelem);
}
}
/// <summary>
/// stfld store into a field of an object
/// <code> obj, value -> </code>
/// </summary>
/// <param name="fi"></param>
public static Instruction Stfld(RField fi)
{
return new ILField(OpCodes.Stfld, fi);
}
/// <summary>
/// stobj - store a value type from the stack into memory
/// <code> addr, valObj -> </code>
/// </summary>
/// <param name="t"></param>
public static Instruction Stobj(RType t)
{
return new ILType(OpCodes.Stobj, t);
}
/// <summary>
/// stsfld store a static field of a class
/// <code> val -> </code>
/// </summary>
/// <param name="fi"></param>
public static Instruction Stsfld(RField fi)
{
return new ILField(OpCodes.Stsfld, fi);
}
/// <summary>
/// throw throw an exception
/// <code> obj -> </code>
/// </summary>
public static Instruction Throw()
{
return new ILNone(OpCodes.Throw);
}
/// <summary>
/// unbox Convert boxed value type to its raw form
/// <code> obj -> valueTypePtr</code>
/// </summary>
/// <param name="t"></param>
public static Instruction Unbox(RType t)
{
return new ILType(OpCodes.Unbox, t);
}
#endregion
#region Static helper methods
static ILFactory()
{
typeToCLROperand = new Hashtable(24);
// Signed types
typeToCLROperand[typeof(System.SByte)] = CLROperandType.I1;
typeToCLROperand[typeof(System.Int16)] = CLROperandType.I2;
typeToCLROperand[typeof(System.Int32)] = CLROperandType.I4;
typeToCLROperand[typeof(System.Int64)] = CLROperandType.I8;
// Unsigned types
typeToCLROperand[typeof(System.Byte)] = CLROperandType.U1;
typeToCLROperand[typeof(System.UInt16)] = CLROperandType.U2;
typeToCLROperand[typeof(System.UInt32)] = CLROperandType.U4;
typeToCLROperand[typeof(System.UInt64)] = CLROperandType.U8;
// Floating point types
typeToCLROperand[typeof(System.Single)] = CLROperandType.R4;
typeToCLROperand[typeof(System.Double)] = CLROperandType.R8;
// Native type
typeToCLROperand[typeof(System.IntPtr)] = CLROperandType.I;
typeToCLROperand[typeof(System.UIntPtr)] = CLROperandType.U;
typeToCLROperand[typeof(System.Object)] = CLROperandType.O;
}
#endregion
/// <summary>
/// Define an instruction with the operanda as null
/// </summary>
/// <param name="ops">The opcode for the instructions</param>
/// <returns>The instruction</returns>
public static Instruction DefineInstruction(OpCode ops)
{
if (OpCodes.Add.Value==ops.Value)
return ILFactory.Add();
if (OpCodes.Add_Ovf.Value==ops.Value)
return ILFactory.Add_Ovf(false);
if (OpCodes.And.Value==ops.Value)
return ILFactory.And();
if (OpCodes.Arglist.Value==ops.Value)
return ILFactory.Arglist();
if (OpCodes.Beq.Value==ops.Value ||
OpCodes.Beq_S.Value==ops.Value)
return ILFactory.Beq(null);
if (OpCodes.Bge.Value==ops.Value ||
OpCodes.Bge_S.Value==ops.Value)
return ILFactory.Bge(true,null);
if (OpCodes.Bge_Un.Value==ops.Value ||
OpCodes.Bge_Un_S.Value==ops.Value)
return ILFactory.Bge(false,null);
if (OpCodes.Bgt.Value==ops.Value ||
OpCodes.Bgt_S.Value==ops.Value ||
OpCodes.Bgt_Un.Value==ops.Value ||
OpCodes.Bgt_Un_S.Value==ops.Value)
return ILFactory.Bgt(false,null);
if (OpCodes.Ble.Value==ops.Value ||
OpCodes.Ble_S.Value==ops.Value)
return ILFactory.Ble(true,null);
if (OpCodes.Ble_Un.Value==ops.Value ||
OpCodes.Ble_Un_S.Value==ops.Value)
return ILFactory.Ble(false,null);
if (OpCodes.Blt.Value==ops.Value ||
OpCodes.Blt_S.Value==ops.Value)
return ILFactory.Blt(true,null);
if (OpCodes.Blt_Un.Value==ops.Value ||
OpCodes.Blt_Un_S.Value==ops.Value)
return ILFactory.Blt(false,null);
if (OpCodes.Bne_Un.Value==ops.Value ||
OpCodes.Bne_Un_S.Value==ops.Value)
return ILFactory.Bne_Un(null);
if (OpCodes.Box.Value==ops.Value)
return ILFactory.Box(null);
if (OpCodes.Br.Value==ops.Value ||
OpCodes.Br_S.Value==ops.Value)
return ILFactory.Br(null);
if (OpCodes.Break.Value==ops.Value)
return ILFactory.Break(null);
if (OpCodes.Brfalse.Value==ops.Value ||
OpCodes.Brfalse_S.Value==ops.Value)
return ILFactory.Br(false,null);
if (OpCodes.Brtrue.Value==ops.Value ||
OpCodes.Brtrue_S.Value==ops.Value)
return ILFactory.Br(true,null);
if (OpCodes.Call.Value==ops.Value ||
OpCodes.Calli.Value==ops.Value)
return ILFactory.Call(false,null);
if (OpCodes.Callvirt.Value==ops.Value)
return ILFactory.Call(true,null);
if (OpCodes.Castclass.Value==ops.Value)
return ILFactory.Castclass(null);
if (OpCodes.Ceq.Value==ops.Value)
return ILFactory.Ceq();
if (OpCodes.Cgt.Value==ops.Value)
return ILFactory.Cgt(true);
if (OpCodes.Cgt_Un.Value==ops.Value)
return ILFactory.Cgt(false);
if (OpCodes.Ckfinite.Value==ops.Value)
return ILFactory.Ckfinite();
if (OpCodes.Clt.Value==ops.Value)
return ILFactory.Clt(true);
if (OpCodes.Clt_Un.Value==ops.Value)
return ILFactory.Clt(false);
if (OpCodes.Conv_I.Value==ops.Value)
return ILFactory.Conv(typeof(IntPtr));
if (OpCodes.Conv_I1.Value==ops.Value)
return ILFactory.Conv(typeof(SByte));
if (OpCodes.Conv_I2.Value==ops.Value)
return ILFactory.Conv(typeof(Int16));
if (OpCodes.Conv_I4.Value==ops.Value)
return ILFactory.Conv(typeof(Int32));
if (OpCodes.Conv_I8.Value==ops.Value)
return ILFactory.Conv(typeof(Int64));
if (OpCodes.Conv_Ovf_I.Value==ops.Value)
return ILFactory.Conv_Ovf(true,typeof(IntPtr));
if (OpCodes.Conv_Ovf_I1.Value==ops.Value)
return ILFactory.Conv_Ovf(true,typeof(SByte));
if (OpCodes.Conv_Ovf_I1_Un.Value==ops.Value)
return ILFactory.Conv_Ovf(false,typeof(SByte));
if (OpCodes.Conv_Ovf_I2.Value==ops.Value)
return ILFactory.Conv_Ovf(true,typeof(Int16));
if (OpCodes.Conv_Ovf_I2_Un.Value==ops.Value)
return ILFactory.Conv_Ovf(false,typeof(Int16));
if (OpCodes.Conv_Ovf_I4.Value==ops.Value)
return ILFactory.Conv_Ovf(true,typeof(Int32));
if (OpCodes.Conv_Ovf_I4_Un.Value==ops.Value)
return ILFactory.Conv_Ovf(false,typeof(Int32));
if (OpCodes.Conv_Ovf_I8.Value==ops.Value)
return ILFactory.Conv_Ovf(true,typeof(Int64));
if (OpCodes.Conv_Ovf_I8_Un.Value==ops.Value)
return ILFactory.Conv_Ovf(false,typeof(Int64));
if (OpCodes.Conv_Ovf_I_Un.Value==ops.Value)
return ILFactory.Conv_Ovf(false,typeof(IntPtr));
if (OpCodes.Conv_Ovf_U.Value==ops.Value)
return ILFactory.Conv_Ovf(true,typeof(UIntPtr));
if (OpCodes.Conv_Ovf_U1.Value==ops.Value)
return ILFactory.Conv_Ovf(true,typeof(Byte));
if (OpCodes.Conv_Ovf_U1_Un.Value==ops.Value)
return ILFactory.Conv_Ovf(false,typeof(Byte));
if (OpCodes.Conv_Ovf_U2.Value==ops.Value)
return ILFactory.Conv_Ovf(true,typeof(UInt16));
if (OpCodes.Conv_Ovf_U2_Un.Value==ops.Value)
return ILFactory.Conv_Ovf(false,typeof(UInt16));
if (OpCodes.Conv_Ovf_U4.Value==ops.Value)
return ILFactory.Conv_Ovf(true,typeof(UInt32));
if (OpCodes.Conv_Ovf_U4_Un.Value==ops.Value)
return ILFactory.Conv_Ovf(false,typeof(UInt32));
if (OpCodes.Conv_Ovf_U8.Value==ops.Value)
return ILFactory.Conv_Ovf(true,typeof(UInt64));
if (OpCodes.Conv_Ovf_U8_Un.Value==ops.Value)
return ILFactory.Conv_Ovf(false,typeof(UInt64));
if (OpCodes.Conv_Ovf_U_Un.Value==ops.Value)
return ILFactory.Conv_Ovf(false,typeof(UIntPtr));
if (OpCodes.Conv_R4.Value==ops.Value)
return ILFactory.Conv(typeof(Single));
if (OpCodes.Conv_R8.Value==ops.Value)
return ILFactory.Conv(typeof(Double));
if (OpCodes.Conv_R_Un.Value==ops.Value)
throw new InvalidOperationException("Wrong type");
if (OpCodes.Conv_U.Value==ops.Value)
return ILFactory.Conv(typeof(UIntPtr));
if (OpCodes.Conv_U1.Value==ops.Value)
return ILFactory.Conv(typeof(Byte));
if (OpCodes.Conv_U2.Value==ops.Value)
return ILFactory.Conv(typeof(UInt16));
if (OpCodes.Conv_U4.Value==ops.Value)
return ILFactory.Conv(typeof(UInt32));
if (OpCodes.Conv_U8.Value==ops.Value)
return ILFactory.Conv(typeof(UInt64));
if (OpCodes.Cpblk.Value==ops.Value)
return ILFactory.Cpblk();
if (OpCodes.Cpobj.Value==ops.Value)
return ILFactory.Cpobj(null);
if (OpCodes.Div.Value==ops.Value)
return ILFactory.Div(true);
if (OpCodes.Div_Un.Value==ops.Value)
return ILFactory.Div(false);
if (OpCodes.Dup.Value==ops.Value)
return ILFactory.Dup();
if (OpCodes.Endfilter.Value==ops.Value)
return ILFactory.Endfilter();
if (OpCodes.Endfinally.Value==ops.Value)
return ILFactory.Endfinaly();
if (OpCodes.Initblk.Value==ops.Value)
return ILFactory.Initblk();
if (OpCodes.Initobj.Value==ops.Value)
return ILFactory.Initobj(null);
if (OpCodes.Isinst.Value==ops.Value)
return ILFactory.Isinst(null);
if (OpCodes.Jmp.Value==ops.Value)
return ILFactory.Jmp(null);
if (OpCodes.Ldarg.Value==ops.Value ||
OpCodes.Ldarg_0.Value==ops.Value ||
OpCodes.Ldarg_1.Value==ops.Value ||
OpCodes.Ldarg_2.Value==ops.Value ||
OpCodes.Ldarg_3.Value==ops.Value ||
OpCodes.Ldarg_S.Value==ops.Value)
return ILFactory.Ldarg(null);
if (OpCodes.Ldarga.Value==ops.Value ||
OpCodes.Ldarga_S.Value==ops.Value)
return ILFactory.Ldarga(null);
if (OpCodes.Ldc_I4.Value==ops.Value)
return new ILNone(OpCodes.Ldc_I4);
if (OpCodes.Ldc_I4_0.Value==ops.Value)
return new ILOperandI4(OpCodes.Ldc_I4, 0);
if (OpCodes.Ldc_I4_1.Value==ops.Value)
return new ILOperandI4(OpCodes.Ldc_I4, 1);
if (OpCodes.Ldc_I4_2.Value==ops.Value)
return new ILOperandI4(OpCodes.Ldc_I4, 2);
if (OpCodes.Ldc_I4_3.Value==ops.Value)
return new ILOperandI4(OpCodes.Ldc_I4, 3);
if (OpCodes.Ldc_I4_4.Value==ops.Value)
return new ILOperandI4(OpCodes.Ldc_I4, 4);
if (OpCodes.Ldc_I4_5.Value==ops.Value)
return new ILOperandI4(OpCodes.Ldc_I4, 5);
if (OpCodes.Ldc_I4_6.Value==ops.Value)
return new ILOperandI4(OpCodes.Ldc_I4, 6);
if (OpCodes.Ldc_I4_7.Value==ops.Value)
return new ILOperandI4(OpCodes.Ldc_I4, 7);
if (OpCodes.Ldc_I4_8.Value==ops.Value)
return new ILOperandI4(OpCodes.Ldc_I4, 8);
if (OpCodes.Ldc_I4_M1.Value==ops.Value)
return new ILOperandI4(OpCodes.Ldc_I4, -1);
if (OpCodes.Ldc_I4_S.Value==ops.Value)
return new ILOperandI4(OpCodes.Ldc_I4, 0);
if (OpCodes.Ldc_I8.Value==ops.Value)
return new ILOperandI8(OpCodes.Ldc_I8, 0);
if (OpCodes.Ldc_R4.Value==ops.Value)
return new ILOperandR4(OpCodes.Ldc_R4, 0);
if (OpCodes.Ldc_R8.Value==ops.Value)
return new ILOperandR8(OpCodes.Ldc_R8, 0);
if (OpCodes.Ldelem_I.Value==ops.Value)
return ILFactory.Ldelem(typeof(IntPtr));
if (OpCodes.Ldelem_I1.Value==ops.Value)
return ILFactory.Ldelem(typeof(SByte));
if (OpCodes.Ldelem_I2.Value==ops.Value)
return ILFactory.Ldelem(typeof(Int16));
if (OpCodes.Ldelem_I4.Value==ops.Value)
return ILFactory.Ldelem(typeof(Int32));
if (OpCodes.Ldelem_I8.Value==ops.Value)
return ILFactory.Ldelem(typeof(Int64));
if (OpCodes.Ldelem_R4.Value==ops.Value)
return ILFactory.Ldelem(typeof(Single));
if (OpCodes.Ldelem_R8.Value==ops.Value)
return ILFactory.Ldelem(typeof(Double));
if (OpCodes.Ldelem_Ref.Value==ops.Value)
return ILFactory.Ldelem(typeof(System.Object));
if (OpCodes.Ldelem_U1.Value==ops.Value)
return ILFactory.Ldelem(typeof(Byte));
if (OpCodes.Ldelem_U2.Value==ops.Value)
return ILFactory.Ldelem(typeof(UInt16));
if (OpCodes.Ldelem_U4.Value==ops.Value)
return ILFactory.Ldelem(typeof(UInt32));
if (OpCodes.Ldelema.Value==ops.Value)
return ILFactory.Ldelema(null);
if (OpCodes.Ldfld.Value==ops.Value)
return ILFactory.Ldfld(null);
if (OpCodes.Ldflda.Value==ops.Value)
return ILFactory.Ldflda(null);
if (OpCodes.Ldftn.Value==ops.Value)
return ILFactory.Ldftn(null);
if (OpCodes.Ldind_I.Value==ops.Value)
return ILFactory.Ldind(typeof(IntPtr));
if (OpCodes.Ldind_I1.Value==ops.Value)
return ILFactory.Ldind(typeof(SByte));
if (OpCodes.Ldind_I2.Value==ops.Value)
return ILFactory.Ldind(typeof(Int16));
if (OpCodes.Ldind_I4.Value==ops.Value)
return ILFactory.Ldind(typeof(Int32));
if (OpCodes.Ldind_I8.Value==ops.Value)
return ILFactory.Ldind(typeof(Int64));
if (OpCodes.Ldind_R4.Value==ops.Value)
return ILFactory.Ldind(typeof(Single));
if (OpCodes.Ldind_R8.Value==ops.Value)
return ILFactory.Ldind(typeof(Double));
if (OpCodes.Ldind_Ref.Value==ops.Value)
return ILFactory.Ldind(typeof(System.Object));
if (OpCodes.Ldind_U1.Value==ops.Value)
return ILFactory.Ldind(typeof(Byte));
if (OpCodes.Ldind_U2.Value==ops.Value)
return ILFactory.Ldind(typeof(UInt16));
if (OpCodes.Ldind_U4.Value==ops.Value)
return ILFactory.Ldind(typeof(UInt32));
if (OpCodes.Ldlen.Value==ops.Value)
return ILFactory.Ldlen();
if (OpCodes.Ldloc.Value==ops.Value ||
OpCodes.Ldloc_0.Value==ops.Value ||
OpCodes.Ldloc_1.Value==ops.Value ||
OpCodes.Ldloc_2.Value==ops.Value ||
OpCodes.Ldloc_3.Value==ops.Value ||
OpCodes.Ldloc_S.Value==ops.Value)
return ILFactory.Ldloc(null);
if (OpCodes.Ldloca.Value==ops.Value ||
OpCodes.Ldloca_S.Value==ops.Value)
return ILFactory.Ldloca(null);
if (OpCodes.Ldnull.Value==ops.Value)
return ILFactory.Ldnull();
if (OpCodes.Ldobj.Value==ops.Value)
return ILFactory.Ldobj(null);
if (OpCodes.Ldsfld.Value==ops.Value)
return ILFactory.Ldsfld(null);
if (OpCodes.Ldsflda.Value==ops.Value)
return ILFactory.Ldsflda(null);
if (OpCodes.Ldstr.Value==ops.Value)
return ILFactory.Ldstr("");
if (OpCodes.Ldtoken.Value==ops.Value)
return ILFactory.Ldtoken((RMethod)null);
if (OpCodes.Ldvirtftn.Value==ops.Value)
return ILFactory.Ldvirtftn(null);
if (OpCodes.Leave.Value==ops.Value ||
OpCodes.Leave_S.Value==ops.Value)
return ILFactory.Leave(null);
if (OpCodes.Localloc.Value==ops.Value)
return ILFactory.Localloc();
if (OpCodes.Mkrefany.Value==ops.Value)
return ILFactory.Mkrefany(null);
if (OpCodes.Mul.Value==ops.Value)
return ILFactory.Mul();
if (OpCodes.Mul_Ovf.Value==ops.Value)
return ILFactory.Mul_Ovf(true);
if (OpCodes.Mul_Ovf_Un.Value==ops.Value)
return ILFactory.Mul_Ovf(false);
if (OpCodes.Neg.Value==ops.Value)
return ILFactory.Neg();
if (OpCodes.Newarr.Value==ops.Value)
return ILFactory.Newarr(null);
if (OpCodes.Newobj.Value==ops.Value)
return ILFactory.Newobj(null);
if (OpCodes.Nop.Value==ops.Value)
return ILFactory.Nop();
if (OpCodes.Not.Value==ops.Value)
return ILFactory.Not();
if (OpCodes.Or.Value==ops.Value)
return ILFactory.Or();
if (OpCodes.Pop.Value==ops.Value)
return ILFactory.Pop();
if (OpCodes.Prefix1.Value==ops.Value ||
OpCodes.Prefix2.Value==ops.Value ||
OpCodes.Prefix3.Value==ops.Value ||
OpCodes.Prefix4.Value==ops.Value ||
OpCodes.Prefix5.Value==ops.Value ||
OpCodes.Prefix6.Value==ops.Value ||
OpCodes.Prefix7.Value==ops.Value ||
OpCodes.Prefixref.Value==ops.Value)
throw new InvalidOperationException("Impossible to emit");
if (OpCodes.Refanytype.Value==ops.Value)
return ILFactory.Refanytype();
if (OpCodes.Refanyval.Value==ops.Value)
return ILFactory.Refanyval(null);
if (OpCodes.Rem.Value==ops.Value)
return ILFactory.Rem(true);
if (OpCodes.Rem_Un.Value==ops.Value)
return ILFactory.Rem(false);
if (OpCodes.Ret.Value==ops.Value)
return ILFactory.Ret();
if (OpCodes.Rethrow.Value==ops.Value)
return ILFactory.Rethrow();
if (OpCodes.Shl.Value==ops.Value)
return ILFactory.Shl();
if (OpCodes.Shr.Value==ops.Value)
return ILFactory.Shr(true);
if (OpCodes.Shr_Un.Value==ops.Value)
return ILFactory.Shr(false);
if (OpCodes.Sizeof.Value==ops.Value)
return ILFactory.Sizeof(null);
if (OpCodes.Starg.Value==ops.Value ||
OpCodes.Starg_S.Value==ops.Value)
return ILFactory.Starg(null);
if (OpCodes.Stelem_I.Value==ops.Value)
return ILFactory.Stelem(typeof(IntPtr));
if (OpCodes.Stelem_I1.Value==ops.Value)
return ILFactory.Stelem(typeof(SByte));
if (OpCodes.Stelem_I2.Value==ops.Value)
return ILFactory.Stelem(typeof(Int16));
if (OpCodes.Stelem_I4.Value==ops.Value)
return ILFactory.Stelem(typeof(Int32));
if (OpCodes.Stelem_I8.Value==ops.Value)
return ILFactory.Stelem(typeof(Int64));
if (OpCodes.Stelem_R4.Value==ops.Value)
return ILFactory.Stelem(typeof(Single));
if (OpCodes.Stelem_R8.Value==ops.Value)
return ILFactory.Stelem(typeof(Double));
if (OpCodes.Stelem_Ref.Value==ops.Value)
return ILFactory.Stelem(typeof(System.Object));
if (OpCodes.Stfld.Value==ops.Value)
return ILFactory.Stfld(null);
if (OpCodes.Stind_I.Value==ops.Value)
return ILFactory.Stind(typeof(IntPtr));
if (OpCodes.Stind_I1.Value==ops.Value)
return ILFactory.Stind(typeof(SByte));
if (OpCodes.Stind_I2.Value==ops.Value)
return ILFactory.Stind(typeof(Int16));
if (OpCodes.Stind_I4.Value==ops.Value)
return ILFactory.Stind(typeof(Int32));
if (OpCodes.Stind_I8.Value==ops.Value)
return ILFactory.Stind(typeof(Int64));
if (OpCodes.Stind_R4.Value==ops.Value)
return ILFactory.Stind(typeof(Single));
if (OpCodes.Stind_R8.Value==ops.Value)
return ILFactory.Stind(typeof(Double));
if (OpCodes.Stind_Ref.Value==ops.Value)
return ILFactory.Stind(typeof(System.Object));
if (OpCodes.Stloc.Value==ops.Value ||
OpCodes.Stloc_0.Value==ops.Value ||
OpCodes.Stloc_1.Value==ops.Value ||
OpCodes.Stloc_2.Value==ops.Value ||
OpCodes.Stloc_3.Value==ops.Value ||
OpCodes.Stloc_S.Value==ops.Value)
return ILFactory.Stloc(null);
if (OpCodes.Stobj.Value==ops.Value)
return ILFactory.Stobj(null);
if (OpCodes.Stsfld.Value==ops.Value)
return ILFactory.Stsfld(null);
if (OpCodes.Sub.Value==ops.Value)
return ILFactory.Sub();
if (OpCodes.Sub_Ovf.Value==ops.Value)
return ILFactory.Sub_Ovf(true);
if (OpCodes.Sub_Ovf_Un.Value==ops.Value)
return ILFactory.Sub_Ovf(false);
if (OpCodes.Switch.Value==ops.Value)
return ILFactory.Switch(new Instruction[0]);
if (OpCodes.Tailcall.Value==ops.Value)
throw new InvalidOperationException();
if (OpCodes.Throw.Value==ops.Value)
return ILFactory.Throw();
if (OpCodes.Unaligned.Value==ops.Value)
throw new InvalidOperationException();
if (OpCodes.Unbox.Value==ops.Value)
return ILFactory.Unbox(null);
if (OpCodes.Volatile.Value==ops.Value)
throw new InvalidOperationException();
if (OpCodes.Xor.Value==ops.Value)
return ILFactory.Xor();
return null;
}
private static readonly Hashtable typeToCLROperand;
}
/// <summary>
///
/// </summary>
sealed class CLROperandType
{
/// <summary>
///
/// </summary>
public readonly Type t;
/// <summary>
///
/// </summary>
public readonly OpCode Conv;
/// <summary>
///
/// </summary>
public readonly OpCode Conv_Ovf;
/// <summary>
///
/// </summary>
public readonly OpCode Conv_Ovf_Un;
/// <summary>
///
/// </summary>
public readonly OpCode Ldind;
/// <summary>
///
/// </summary>
public readonly OpCode Stind;
/// <summary>
///
/// </summary>
public readonly OpCode Ldelem;
/// <summary>
///
/// </summary>
public readonly OpCode Stelem;
/// <summary>
///
/// </summary>
public readonly static CLROperandType I1 =
new CLROperandType(typeof(System.SByte), OpCodes.Conv_I1, OpCodes.Conv_Ovf_I1, OpCodes.Conv_Ovf_I1_Un,
OpCodes.Ldind_I1, OpCodes.Stind_I1, OpCodes.Ldelem_I1, OpCodes.Stelem_I1);
/// <summary>
///
/// </summary>
public readonly static CLROperandType I2 =
new CLROperandType(typeof(System.Int16), OpCodes.Conv_I2, OpCodes.Conv_Ovf_I2, OpCodes.Conv_Ovf_I2_Un,
OpCodes.Ldind_I2, OpCodes.Stind_I2, OpCodes.Ldelem_I2, OpCodes.Stelem_I2);
/// <summary>
///
/// </summary>
public readonly static CLROperandType I4 =
new CLROperandType(typeof(System.Int32), OpCodes.Conv_I4, OpCodes.Conv_Ovf_I4, OpCodes.Conv_Ovf_I4_Un,
OpCodes.Ldind_I4, OpCodes.Stind_I4, OpCodes.Ldelem_I4, OpCodes.Stelem_I4);
/// <summary>
///
/// </summary>
public readonly static CLROperandType I8 =
new CLROperandType(typeof(System.Int64), OpCodes.Conv_I8, OpCodes.Conv_Ovf_I8, OpCodes.Conv_Ovf_I8_Un,
OpCodes.Ldind_I8, OpCodes.Stind_I8, OpCodes.Ldelem_I8, OpCodes.Stelem_I8);
// Unsigned types
/// <summary>
///
/// </summary>
public readonly static CLROperandType U1 =
new CLROperandType(typeof(System.Byte), OpCodes.Conv_U1, OpCodes.Conv_Ovf_U1, OpCodes.Conv_Ovf_U1_Un,
OpCodes.Ldind_U1, OpCodes.Stind_I1, OpCodes.Ldelem_U1, OpCodes.Stelem_I1);
/// <summary>
///
/// </summary>
public readonly static CLROperandType U2 =
new CLROperandType(typeof(System.UInt16), OpCodes.Conv_U2, OpCodes.Conv_Ovf_U1, OpCodes.Conv_Ovf_U2_Un,
OpCodes.Ldind_U2, OpCodes.Stind_I2, OpCodes.Ldelem_U2, OpCodes.Stelem_I2);
/// <summary>
///
/// </summary>
public readonly static CLROperandType U4 =
new CLROperandType(typeof(System.UInt32), OpCodes.Conv_U4, OpCodes.Conv_Ovf_U1, OpCodes.Conv_Ovf_U4_Un,
OpCodes.Ldind_U4, OpCodes.Stind_I4, OpCodes.Ldelem_U4, OpCodes.Stelem_I4);
// ldind.u8 is an alias for ldind.i8
/// <summary>
///
/// </summary>
public readonly static CLROperandType U8 =
new CLROperandType(typeof(System.UInt64), OpCodes.Conv_U8, OpCodes.Conv_Ovf_U1, OpCodes.Conv_Ovf_U8_Un,
OpCodes.Ldind_I8, OpCodes.Stind_I8, OpCodes.Ldelem_I8, OpCodes.Stelem_I8);
// Floating point types
/// <summary>
///
/// </summary>
public readonly static CLROperandType R4 =
new CLROperandType(typeof(System.Single), OpCodes.Conv_R4, OpCodes.Nop, OpCodes.Nop,
OpCodes.Ldind_R4, OpCodes.Stind_R4, OpCodes.Ldelem_R4, OpCodes.Stelem_R4);
/// <summary>
///
/// </summary>
public readonly static CLROperandType R8 =
new CLROperandType(typeof(System.Double), OpCodes.Conv_R8, OpCodes.Nop, OpCodes.Nop,
OpCodes.Ldind_R8, OpCodes.Stind_R8, OpCodes.Ldelem_R8, OpCodes.Stelem_R8);
// Native type
/// <summary>
///
/// </summary>
public readonly static CLROperandType I =
new CLROperandType(typeof(System.IntPtr), OpCodes.Conv_I, OpCodes.Conv_Ovf_I, OpCodes.Conv_Ovf_I_Un,
OpCodes.Ldind_I, OpCodes.Stind_I, OpCodes.Ldelem_I, OpCodes.Stelem_I);
/// <summary>
///
/// </summary>
public readonly static CLROperandType U =
new CLROperandType(typeof(System.UIntPtr), OpCodes.Conv_U, OpCodes.Conv_Ovf_U, OpCodes.Conv_Ovf_U_Un,
OpCodes.Ldind_I, OpCodes.Nop, OpCodes.Ldelem_I, OpCodes.Stelem_I);
/// <summary>
///
/// </summary>
public readonly static CLROperandType O =
new CLROperandType(typeof(System.Object), OpCodes.Nop, OpCodes.Nop, OpCodes.Nop,
OpCodes.Ldind_Ref, OpCodes.Stind_Ref, OpCodes.Ldelem_Ref, OpCodes.Stelem_Ref);
/// <summary>
///
/// </summary>
/// <remarks>
/// Not all CLR operand types support the full set of operations. For those
/// that don't support some operations, use OpCodes.Nop as the opcode for it.
/// </remarks>
/// <param name="t"></param>
/// <param name="conv"></param>
/// <param name="conv_Ovf"></param>
/// <param name="conv_Ovf_Un"></param>
/// <param name="ldind"></param>
/// <param name="stind"></param>
/// <param name="ldelem"></param>
/// <param name="stelem"></param>
private CLROperandType(Type t, OpCode conv, OpCode conv_Ovf, OpCode conv_Ovf_Un,
OpCode ldind, OpCode stind, OpCode ldelem, OpCode stelem)
{
this.t = t;
this.Conv = conv;
this.Conv_Ovf = conv_Ovf;
this.Conv_Ovf_Un = conv_Ovf_Un;
this.Ldind = ldind;
this.Stind = stind;
this.Ldelem = ldelem;
this.Stelem = stelem;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return t.GetHashCode();
}
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(Object obj)
{
CLROperandType oType = obj as CLROperandType;
if (oType == null)
{
return false;
}
else
{
return t.Equals(oType);
}
}
}
}
|