static bool GetValue(ILValue value, out double result) { if (value is ConstantFloatILValue f) { result = f.Value; return(true); } result = 0; return(false); }
static bool GetValue(ILValue value, int pointerSize, out long result) { if (value is ConstantInt32ILValue c32) { result = c32.Value; return(true); } else if (value is ConstantInt64ILValue c64) { result = c64.Value; return(true); } else if (value is ConstantNativeIntILValue cni) { result = pointerSize == 4 ? cni.Value32 : cni.Value64; return(true); } result = 0; return(false); }
/// <summary> /// Stores a value in a static field or returns false on failure /// </summary> /// <param name="field">Field</param> /// <param name="value">Value to store in the field</param> public abstract bool StoreStaticField(DmdFieldInfo field, ILValue value);
/// <summary> /// Calls a static method or returns false on failure /// </summary> /// <param name="methodAddress">Method address</param> /// <param name="methodSig">Method signature</param> /// <param name="arguments">Method arguments</param> /// <param name="returnValue">Return value. It's ignored if the method returns <see cref="void"/></param> /// <returns></returns> public abstract bool CallStaticIndirect(DmdMethodSignature methodSig, ILValue methodAddress, ILValue[] arguments, out ILValue returnValue);
/// <summary> /// Calls a static method or returns false on failure /// </summary> /// <param name="method">Method to call</param> /// <param name="arguments">Method arguments</param> /// <param name="returnValue">Return value. It's ignored if the method returns <see cref="void"/></param> /// <returns></returns> public abstract bool CallStatic(DmdMethodBase method, ILValue[] arguments, out ILValue returnValue);
/// <summary> /// Boxes a value or returns null on failure /// </summary> /// <param name="value">Value to box</param> /// <param name="type">Target type</param> /// <returns></returns> public abstract ILValue Box(ILValue value, DmdType type);
/// <summary> /// Subtracts <paramref name="value"/> from a copy of this value and returns the result. Returns null if it's not supported. /// </summary> /// <param name="kind">Opcode kind</param> /// <param name="value">Value to subtract</param> /// <param name="pointerSize">Size of a pointer in bytes</param> /// <returns></returns> public virtual ILValue?Sub(SubOpCodeKind kind, ILValue value, int pointerSize) => null;
/// <summary> /// Writes to an argument or returns false on failure /// </summary> /// <param name="index">Argument index</param> /// <param name="type">Type of the argument</param> /// <param name="value">New value</param> public abstract bool StoreArgument(int index, DmdType type, ILValue value);
/// <summary> /// Stores a value. Returns false if it's not supported. /// </summary> /// <param name="type">Type</param> /// <param name="loadValueType">Type of value to store</param> /// <param name="value">Value</param> /// <returns></returns> public virtual bool StoreIndirect(DmdType type, LoadValueType loadValueType, ILValue value) => false;
/// <summary> /// Writes an SZ array element. Returns false if it's not supported. /// </summary> /// <param name="loadValueType">Type of value to store</param> /// <param name="index">Index</param> /// <param name="value">Value</param> /// <param name="elementType">Optional element type (eg. it's the stelem instruction)</param> /// <returns></returns> public virtual bool StoreSZArrayElement(LoadValueType loadValueType, long index, ILValue value, DmdType elementType) => false;
/// <summary> /// Calls an instance method or returns false on failure /// </summary> /// <param name="methodAddress">Method address</param> /// <param name="methodSig">Method signature</param> /// <param name="arguments">Method arguments</param> /// <param name="returnValue">Return value. It's ignored if the method returns <see cref="void"/></param> /// <returns></returns> public virtual bool CallIndirect(DmdMethodSignature methodSig, ILValue methodAddress, ILValue[] arguments, out ILValue?returnValue) { returnValue = null; return(false); }
/// <summary> /// Stores a value in an instance field. Returns false if it's not supported. /// </summary> /// <param name="field">Field</param> /// <param name="value">Value</param> /// <returns></returns> public virtual bool StoreField(DmdFieldInfo field, ILValue value) => false;
/// <summary> /// Stores a value. Returns false if it's not supported. /// </summary> /// <param name="type">Type</param> /// <param name="loadValueType">Type of value to store</param> /// <param name="value">Value</param> /// <returns></returns> public override bool StoreIndirect(DmdType type, LoadValueType loadValueType, ILValue value) { int pointerSize = type.AppDomain.Runtime.PointerSize; long v; double d; switch (loadValueType) { case LoadValueType.I: if (pointerSize == 4) { if (offset + 4 - 1 < offset || (ulong)offset + 4 - 1 >= (ulong)data.Length) { return(false); } if (!GetValue(value, pointerSize, out v)) { return(false); } WriteInt32(data, (int)offset, v); return(true); } else { Debug.Assert(pointerSize == 8); if (offset + 8 - 1 < offset || (ulong)offset + 8 - 1 >= (ulong)data.Length) { return(false); } if (!GetValue(value, pointerSize, out v)) { return(false); } WriteInt64(data, (int)offset, v); return(true); } case LoadValueType.I1: case LoadValueType.U1: if ((ulong)offset >= (ulong)data.Length) { return(false); } if (!GetValue(value, pointerSize, out v)) { return(false); } WriteInt8(data, (int)offset, v); return(true); case LoadValueType.I2: case LoadValueType.U2: if (offset + 2 - 1 < offset || (ulong)offset + 2 - 1 >= (ulong)data.Length) { return(false); } if (!GetValue(value, pointerSize, out v)) { return(false); } WriteInt16(data, (int)offset, v); return(true); case LoadValueType.I4: case LoadValueType.U4: if (offset + 4 - 1 < offset || (ulong)offset + 4 - 1 >= (ulong)data.Length) { return(false); } if (!GetValue(value, pointerSize, out v)) { return(false); } WriteInt32(data, (int)offset, v); return(true); case LoadValueType.I8: if (offset + 8 - 1 < offset || (ulong)offset + 8 - 1 >= (ulong)data.Length) { return(false); } if (!GetValue(value, pointerSize, out v)) { return(false); } WriteInt64(data, (int)offset, v); return(true); case LoadValueType.R4: if (offset + 4 - 1 < offset || (ulong)offset + 4 - 1 >= (ulong)data.Length) { return(false); } if (!GetValue(value, out d)) { return(false); } WriteSingle(data, (int)offset, (float)d); return(true); case LoadValueType.R8: if (offset + 8 - 1 < offset || (ulong)offset + 8 - 1 >= (ulong)data.Length) { return(false); } if (!GetValue(value, out d)) { return(false); } WriteDouble(data, (int)offset, d); return(true); case LoadValueType.Ref: return(false); default: return(false); } }
/// <summary> /// Constructor (used by ldvirtftn instruction) /// </summary> /// <param name="method">Method</param> /// <param name="thisValue">This object</param> public FunctionPointerILValue(DmdMethodBase method, ILValue thisValue) { Method = method; Type = method.AppDomain.System_Void.MakePointerType(); VirtualThisObject = thisValue; }
/// <summary> /// Compares <paramref name="left"/> and <paramref name="right"/>, returning less than 0, 0 or greater than 0. /// This method is called if one of the inputs is a non-constant native int or by-ref. /// </summary> /// <param name="left">Left operand</param> /// <param name="right">Right operand</param> /// <returns></returns> public abstract int?CompareUnsigned(ILValue left, ILValue right);
/// <summary> /// Copies <paramref name="source"/> to this value. Returns false if it's not supported. /// </summary> /// <param name="type">Type</param> /// <param name="source">Source value</param> /// <returns></returns> public virtual bool CopyObject(DmdType type, ILValue source) => false;
/// <summary> /// Checks if <paramref name="left"/> equals <paramref name="right"/> or returns null on failure /// </summary> /// <param name="left">Left operand</param> /// <param name="right">Right operand</param> /// <returns></returns> public abstract bool?Equals(ILValue left, ILValue right);
/// <summary> /// Copies memory to this value. Returns false if it's not supported. /// </summary> /// <param name="source">Source value</param> /// <param name="size">Size in bytes</param> /// <returns></returns> public virtual bool CopyMemory(ILValue source, long size) => false;
/// <summary> /// Writes to a local or returns false on failure /// </summary> /// <param name="index">Local index</param> /// <param name="type">Type of the local</param> /// <param name="value">New value</param> public abstract bool StoreLocal(int index, DmdType type, ILValue value);
/// <summary> /// Calls an instance method. The method could be a CLR-generated method, eg. an array Address() method, see <see cref="DmdSpecialMethodKind"/>. /// Returns false if it's not supported. /// </summary> /// <param name="isCallvirt">true if this is a virtual call, false if it's a non-virtual call</param> /// <param name="method">Method</param> /// <param name="arguments">Arguments. The hidden 'this' value isn't included, it's this instance.</param> /// <param name="returnValue">Updated with the return value. Can be null if the return type is <see cref="void"/></param> /// <returns></returns> public virtual bool Call(bool isCallvirt, DmdMethodBase method, ILValue[] arguments, out ILValue returnValue) { returnValue = null; return(false); }