using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.CLR.Utils; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Stack; using ILRuntime.Reflection; using System.Collections; #if DEBUG && !DISABLE_ILRUNTIME_DEBUG using AutoList = System.Collections.Generic.List; #else using AutoList = ILRuntime.Other.UncheckedList; #endif namespace ILRuntime.Runtime.Enviorment { unsafe static class CLRRedirections { public static StackObject* GetCurrentStackTrace(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { StackObject* ret = esp - 1 - 1; intp.Free(esp - 1); return ILIntepreter.PushObject(ret, mStack, intp.AppDomain.DebugService.GetStackTrace(intp)); } public static StackObject* CreateInstance(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { IType[] genericArguments = method.GenericArguments; if (genericArguments != null && genericArguments.Length == 1) { var t = genericArguments[0]; if (t is ILType) { if (t.IsValueType && !t.IsEnum) { intp.AllocValueType(esp++, t); return esp; } else return ILIntepreter.PushObject(esp, mStack, ((ILType)t).Instantiate()); } else { if (intp.AppDomain.ValueTypeBinders.ContainsKey(t.TypeForCLR)) { intp.AllocValueType(esp++, t); return esp; } else return ILIntepreter.PushObject(esp, mStack, ((CLRType)t).CreateDefaultInstance()); } } else throw new EntryPointNotFoundException(); } /*public static object CreateInstance(ILContext ctx, object instance, object[] param, IType[] genericArguments) { if (genericArguments != null && genericArguments.Length == 1) { var t = genericArguments[0]; if (t is ILType) { return ((ILType)t).Instantiate(); } else return Activator.CreateInstance(t.TypeForCLR); } else throw new EntryPointNotFoundException(); }*/ public static StackObject* CreateInstance2(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var p = esp - 1; var t = mStack[p->Value] as Type; intp.Free(p); if (t != null) { if (t is ILRuntimeType) { return ILIntepreter.PushObject(p, mStack, ((ILRuntimeType)t).ILType.Instantiate()); } else return ILIntepreter.PushObject(p, mStack, Activator.CreateInstance(t)); } else return ILIntepreter.PushNull(p); } /*public static object CreateInstance2(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var t = param[0] as Type; if (t != null) { if (t is ILRuntimeType) { return ((ILRuntimeType)t).ILType.Instantiate(); } else return Activator.CreateInstance(t); } else return null; }*/ public static StackObject* CreateInstance3(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var p = esp - 1 - 1; var t = mStack[p->Value] as Type; var p2 = esp - 1; var t2 = mStack[p2->Value] as Object[]; intp.Free(p); if (t != null) { for (int i = 0; i < t2.Length; i++) { if (t2[i] == null) { throw new ArgumentNullException(); } } if (t is ILRuntimeType) { return ILIntepreter.PushObject(p, mStack, ((ILRuntimeType)t).ILType.Instantiate(t2)); } else return ILIntepreter.PushObject(p, mStack, Activator.CreateInstance(t, t2)); } else return ILIntepreter.PushNull(p); } public static StackObject* GetType(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var p = esp - 1; AppDomain dommain = intp.AppDomain; string fullname = (string)StackObject.ToObject(p, dommain, mStack); ; intp.Free(p); var t = intp.AppDomain.GetType(fullname); if (t != null) return ILIntepreter.PushObject(p, mStack, t.ReflectionType); else return ILIntepreter.PushNull(p); } public static StackObject* TypeEquals(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var ret = ILIntepreter.Minus(esp, 2); var p = esp - 1; AppDomain dommain = intp.AppDomain; var other = StackObject.ToObject(p, dommain, mStack); intp.Free(p); p = ILIntepreter.Minus(esp, 2); var instance = StackObject.ToObject(p, dommain, mStack); intp.Free(p); if (instance is ILRuntimeType) { if (other is ILRuntimeType) { if (((ILRuntimeType)instance).ILType == ((ILRuntimeType)other).ILType) return ILIntepreter.PushOne(ret); else return ILIntepreter.PushZero(ret); } else return ILIntepreter.PushZero(ret); } else { if (((Type)typeof(Type).CheckCLRTypes(instance)).Equals(((Type)typeof(Type).CheckCLRTypes(other)))) return ILIntepreter.PushOne(ret); else return ILIntepreter.PushZero(ret); } } /*public static object GetType(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var t = ctx.AppDomain.GetType((string)param[0]); if (t != null) return t.ReflectionType; else return null; }*/ public static StackObject* IsAssignableFrom(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var ret = ILIntepreter.Minus(esp, 2); var p = esp - 1; AppDomain dommain = intp.AppDomain; var other = StackObject.ToObject(p, dommain, mStack); intp.Free(p); p = ILIntepreter.Minus(esp, 2); var instance = StackObject.ToObject(p, dommain, mStack); intp.Free(p); if (instance is ILRuntimeType) { if (other is ILRuntimeType) { if (((ILRuntimeType)instance).IsAssignableFrom((ILRuntimeType)other)) return ILIntepreter.PushOne(ret); else return ILIntepreter.PushZero(ret); } else return ILIntepreter.PushZero(ret); } else { if (instance is ILRuntimeWrapperType) { if (((ILRuntimeWrapperType)instance).IsAssignableFrom((Type)other)) return ILIntepreter.PushOne(ret); else return ILIntepreter.PushZero(ret); } else { if (((Type)instance).IsAssignableFrom((Type)other)) return ILIntepreter.PushOne(ret); else return ILIntepreter.PushZero(ret); } } } public unsafe static StackObject* InitializeArray(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var param = esp - 1; byte[] data = StackObject.ToObject(param, domain, mStack) as byte[]; intp.Free(param); param = esp - 1 - 1; object array = StackObject.ToObject(param, domain, mStack); intp.Free(param); if (data == null) return ret; fixed (byte* p = data) { /*Array oArr = (Array)array; if (oArr.Rank == 1) { if (array is int[]) { int[] arr = array as int[]; int* ptr = (int*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is byte[]) { byte[] arr = array as byte[]; for (int i = 0; i < arr.Length; i++) { arr[i] = p[i]; } } else if (array is sbyte[]) { sbyte[] arr = array as sbyte[]; sbyte* ptr = (sbyte*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is short[]) { short[] arr = array as short[]; short* ptr = (short*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is ushort[]) { ushort[] arr = array as ushort[]; ushort* ptr = (ushort*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is char[]) { char[] arr = array as char[]; char* ptr = (char*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is uint[]) { uint[] arr = array as uint[]; uint* ptr = (uint*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is Int64[]) { long[] arr = array as long[]; long* ptr = (long*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is UInt64[]) { ulong[] arr = array as ulong[]; ulong* ptr = (ulong*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is float[]) { float[] arr = array as float[]; float* ptr = (float*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is double[]) { double[] arr = array as double[]; double* ptr = (double*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is bool[]) { bool[] arr = array as bool[]; bool* ptr = (bool*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else { throw new NotImplementedException("array=" + array.GetType()); } } else { int* dst = (int*)System.Runtime.InteropServices.Marshal.UnsafeAddrOfPinnedArrayElement(oArr, 0).ToPointer(); int* src = (int*)p; int len = data.Length / sizeof(int); for (int i = 0; i < len; i++) dst[i] = src[i]; }*/ Array arr = (Array)array; var handle = System.Runtime.InteropServices.GCHandle.Alloc(arr, System.Runtime.InteropServices.GCHandleType.Pinned); var dst = System.Runtime.InteropServices.Marshal.UnsafeAddrOfPinnedArrayElement(arr, 0); System.Runtime.InteropServices.Marshal.Copy(data, 0, dst, data.Length); handle.Free(); } return ret; } /*public unsafe static object InitializeArray(ILContext ctx, object instance, object[] param, IType[] genericArguments) { object array = param[0]; byte[] data = param[1] as byte[]; if (data == null) return null; fixed (byte* p = data) { if (array is int[]) { int[] arr = array as int[]; int* ptr = (int*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is byte[]) { byte[] arr = array as byte[]; for (int i = 0; i < arr.Length; i++) { arr[i] = p[i]; } } else if (array is sbyte[]) { sbyte[] arr = array as sbyte[]; sbyte* ptr = (sbyte*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is short[]) { short[] arr = array as short[]; short* ptr = (short*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is ushort[]) { ushort[] arr = array as ushort[]; ushort* ptr = (ushort*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is char[]) { char[] arr = array as char[]; char* ptr = (char*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is uint[]) { uint[] arr = array as uint[]; uint* ptr = (uint*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is Int64[]) { long[] arr = array as long[]; long* ptr = (long*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is UInt64[]) { ulong[] arr = array as ulong[]; ulong* ptr = (ulong*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is float[]) { float[] arr = array as float[]; float* ptr = (float*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is double[]) { double[] arr = array as double[]; double* ptr = (double*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else if (array is bool[]) { bool[] arr = array as bool[]; bool* ptr = (bool*)p; for (int i = 0; i < arr.Length; i++) { arr[i] = ptr[i]; } } else { throw new NotImplementedException("array=" + array.GetType()); } } return null; }*/ public unsafe static StackObject* DelegateCombine(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { //Don't ask me why not esp -2, unity won't return the right result var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var param = esp - 1; object dele2 = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = esp - 1 - 1; object dele1 = StackObject.ToObject(param, domain, mStack); intp.Free(param); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) { var dele = ((IDelegateAdapter)dele1); //This means it's the original delegate which should be untouch if (!dele.IsClone) { dele = dele.Clone(); } if (!((IDelegateAdapter)dele2).IsClone) { dele2 = ((IDelegateAdapter)dele2).Clone(); } dele.Combine((IDelegateAdapter)dele2); return ILIntepreter.PushObject(ret, mStack, dele); } else { if (!((IDelegateAdapter)dele1).IsClone) { dele1 = ((IDelegateAdapter)dele1).Clone(); } ((IDelegateAdapter)dele1).Combine((Delegate)dele2); return ILIntepreter.PushObject(ret, mStack, dele1); } } else { if (dele2 is IDelegateAdapter) return ILIntepreter.PushObject(ret, mStack, Delegate.Combine((Delegate)dele1, ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()))); else return ILIntepreter.PushObject(ret, mStack, Delegate.Combine((Delegate)dele1, (Delegate)dele2)); } } else return ILIntepreter.PushObject(ret, mStack, dele1); } else return ILIntepreter.PushObject(ret, mStack, dele2); } /*public unsafe static object DelegateCombine(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var esp = ctx.ESP; var mStack = ctx.ManagedStack; var domain = ctx.AppDomain; //Don't ask me why not esp -2, unity won't return the right result var dele1 = StackObject.ToObject((esp - 1 - 1), domain, mStack); var dele2 = StackObject.ToObject((esp - 1), domain, mStack); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) { var dele = ((IDelegateAdapter)dele1); //This means it's the default delegate which should be singleton to support == operator if (dele.Next == null) { dele = dele.Instantiate(domain, dele.Instance, dele.Method); } dele.Combine((IDelegateAdapter)dele2); return dele; } else { ((IDelegateAdapter)dele1).Combine((Delegate)dele2); return dele1; } } else { if (dele2 is IDelegateAdapter) return Delegate.Combine((Delegate)dele1, ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType())); else return Delegate.Combine((Delegate)dele1, (Delegate)dele2); } } else return dele1; } else return dele2; }*/ public unsafe static StackObject* DelegateRemove(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { //Don't ask me why not esp -2, unity won't return the right result var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var param = esp - 1; object dele2 = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = esp - 1 - 1; object dele1 = StackObject.ToObject(param, domain, mStack); intp.Free(param); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) { if (((IDelegateAdapter)dele1).Equals((IDelegateAdapter)dele2)) return ILIntepreter.PushObject(ret, mStack, ((IDelegateAdapter)dele1).Next); else ((IDelegateAdapter)dele1).Remove((IDelegateAdapter)dele2); } else ((IDelegateAdapter)dele1).Remove((Delegate)dele2); return ILIntepreter.PushObject(ret, mStack, dele1); } else { if (dele2 is IDelegateAdapter) return ILIntepreter.PushObject(ret, mStack, Delegate.Remove((Delegate)dele1, ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()))); else return ILIntepreter.PushObject(ret, mStack, Delegate.Remove((Delegate)dele1, (Delegate)dele2)); } } else return ILIntepreter.PushObject(ret, mStack, dele1); } else return ILIntepreter.PushNull(ret); } /*public unsafe static object DelegateRemove(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var esp = ctx.ESP; var mStack = ctx.ManagedStack; var domain = ctx.AppDomain; var dele1 = StackObject.ToObject((esp - 1 - 1), domain, mStack); var dele2 = StackObject.ToObject((esp - 1), domain, mStack); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) { if (dele1 == dele2) return ((IDelegateAdapter)dele1).Next; else ((IDelegateAdapter)dele1).Remove((IDelegateAdapter)dele2); } else ((IDelegateAdapter)dele1).Remove((Delegate)dele2); return dele1; } else { if (dele2 is IDelegateAdapter) return Delegate.Remove((Delegate)dele1, ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType())); else return Delegate.Remove((Delegate)dele1, (Delegate)dele2); } } else return dele1; } else return null; }*/ public unsafe static StackObject* DelegateGetTarget(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var ret = esp - 1; AppDomain domain = intp.AppDomain; var param = esp - 1; object dele = StackObject.ToObject(param, domain, mStack); intp.Free(param); if (dele != null) { if (dele is IDelegateAdapter) { return ILIntepreter.PushObject(ret, mStack, ((IDelegateAdapter)dele).Instance); } else { return ILIntepreter.PushObject(ret, mStack, ((Delegate)dele).Target); } } else throw new NullReferenceException(); } public unsafe static StackObject* DelegateEqulity(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { //Don't ask me why not esp -2, unity won't return the right result var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var param = esp - 1; object dele2 = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = esp - 1 - 1; object dele1 = StackObject.ToObject(param, domain, mStack); intp.Free(param); bool res = false; if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) res = ((IDelegateAdapter)dele1).Equals((IDelegateAdapter)dele2); else res = ((IDelegateAdapter)dele1).Equals((Delegate)dele2); } else { if (dele2 is IDelegateAdapter) { res = (Delegate)dele1 == ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()); } else res = (Delegate)dele1 == (Delegate)dele2; } } else res = dele1 == null; } else res = dele2 == null; if (res) return ILIntepreter.PushOne(ret); else return ILIntepreter.PushZero(ret); } /*public unsafe static object DelegateEqulity(ILContext ctx, object instance, object[] param, IType[] genericArguments) { //op_Equality,op_Inequality var esp = ctx.ESP; var mStack = ctx.ManagedStack; var domain = ctx.AppDomain; var dele1 = StackObject.ToObject((esp - 1 - 1), domain, mStack); var dele2 = StackObject.ToObject((esp - 1), domain, mStack); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) return ((IDelegateAdapter)dele1).Equals((IDelegateAdapter)dele2); else return ((IDelegateAdapter)dele1).Equals((Delegate)dele2); } else { if (dele2 is IDelegateAdapter) { return (Delegate)dele1 == ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()); } else return (Delegate)dele1 == (Delegate)dele2; } } else return dele1 == null; } else return dele2 == null; }*/ public unsafe static StackObject* DelegateInequlity(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { //Don't ask me why not esp -2, unity won't return the right result var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var param = esp - 1; object dele2 = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = esp - 1 - 1; object dele1 = StackObject.ToObject(param, domain, mStack); intp.Free(param); bool res = false; if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) res = !((IDelegateAdapter)dele1).Equals((IDelegateAdapter)dele2); else res = !((IDelegateAdapter)dele1).Equals((Delegate)dele2); } else { if (dele2 is IDelegateAdapter) res = (Delegate)dele1 != ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()); else res = (Delegate)dele1 != (Delegate)dele2; } } else res = dele1 != null; } else res = dele2 != null; if (res) return ILIntepreter.PushOne(ret); else return ILIntepreter.PushZero(ret); } /*public unsafe static object DelegateInequlity(ILContext ctx, object instance, object[] param, IType[] genericArguments) { //op_Equality,op_Inequality var esp = ctx.ESP; var mStack = ctx.ManagedStack; var domain = ctx.AppDomain; var dele1 = StackObject.ToObject((esp - 1 - 1), domain, mStack); var dele2 = StackObject.ToObject((esp - 1), domain, mStack); if (dele1 != null) { if (dele2 != null) { if (dele1 is IDelegateAdapter) { if (dele2 is IDelegateAdapter) return !((IDelegateAdapter)dele1).Equals((IDelegateAdapter)dele2); else return !((IDelegateAdapter)dele1).Equals((Delegate)dele2); } else { if (dele2 is IDelegateAdapter) return (Delegate)dele1 != ((IDelegateAdapter)dele2).GetConvertor(dele1.GetType()); else return (Delegate)dele1 != (Delegate)dele2; } } else return dele1 != null; } else return dele2 != null; }*/ public static StackObject* GetTypeFromHandle(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { //Nothing to do return esp; } /*public static object GetTypeFromHandle(ILContext ctx, object instance, object[] param, IType[] genericArguments) { return param[0]; }*/ public unsafe static StackObject* MethodInfoInvoke(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { AppDomain domain = intp.AppDomain; //Don't ask me why not esp - 3, unity won't return the right result var ret = ILIntepreter.Minus(esp, 3); var param = esp - 1; var p = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = esp - 1 - 1; var obj = StackObject.ToObject(param, domain, mStack); intp.Free(param); param = ILIntepreter.Minus(esp, 3); object instance = CheckCrossBindingAdapter(StackObject.ToObject(param, domain, mStack)); intp.Free(param); if (instance is ILRuntimeMethodInfo) { if (obj != null) esp = ILIntepreter.PushObject(ret, mStack, obj); else esp = ret; var ilmethod = ((ILRuntimeMethodInfo)instance).ILMethod; bool useRegister = ilmethod.ShouldUseRegisterVM; if (p != null) { object[] arr = (object[])p; for (int i = 0; i < ilmethod.ParameterCount; i++) { var res = ILIntepreter.PushObject(esp, mStack, CheckCrossBindingAdapter(arr[i])); if (esp->ObjectType < ObjectTypes.Object && useRegister) mStack.Add(null); esp = res; } } bool unhandled; if (useRegister) ret = intp.ExecuteR(ilmethod, esp, out unhandled); else ret = intp.Execute(ilmethod, esp, out unhandled); ILRuntimeMethodInfo imi = (ILRuntimeMethodInfo)instance; var rt = imi.ILMethod.ReturnType; if (rt != domain.VoidType) { var res = ret - 1; if (res->ObjectType < ObjectTypes.Object) { return ILIntepreter.PushObject(res, mStack, rt.TypeForCLR.CheckCLRTypes(StackObject.ToObject(res, domain, mStack)), true); } else return ret; } else return ILIntepreter.PushNull(ret); } else return ILIntepreter.PushObject(ret, mStack, ((MethodInfo)instance).Invoke(obj, (object[])p)); } static object CheckCrossBindingAdapter(object obj) { if (obj is CrossBindingAdaptorType) { return ((CrossBindingAdaptorType)obj).ILInstance; } return obj; } /*public unsafe static object MethodInfoInvoke(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var esp = ctx.ESP; var mStack = ctx.ManagedStack; var domain = ctx.AppDomain; var intp = ctx.Interpreter; //Don't ask me why not esp - 3, unity won't return the right result var obj = param[0]; var p = param[1]; if (instance is ILRuntimeMethodInfo) { if (obj != null) esp = ILIntepreter.PushObject(esp, mStack, obj); if (p != null) { object[] arr = (object[])p; foreach (var i in arr) { esp = ILIntepreter.PushObject(esp, mStack, i); } } bool unhandled; var ilmethod = ((ILRuntimeMethodInfo)instance).ILMethod; esp = intp.Execute(ilmethod, esp, out unhandled); object res = null; if (ilmethod.ReturnType != domain.VoidType) { res = StackObject.ToObject((esp - 1),domain, mStack); intp.Free(esp - 1); } return res; } else return ((MethodInfo)instance).Invoke(obj, (object[])p); }*/ public unsafe static StackObject* ObjectGetType(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { AppDomain domain = intp.AppDomain; var ret = esp - 1; var param = esp - 1; var instance = StackObject.ToObject(param, domain, mStack); intp.Free(param); var type = instance.GetType(); if (type == typeof(ILTypeInstance) || type == typeof(ILEnumTypeInstance)) { return ILIntepreter.PushObject(ret, mStack, ((ILTypeInstance)instance).Type.ReflectionType); } else return ILIntepreter.PushObject(ret, mStack, type); } /*public unsafe static object ObjectGetType(ILContext ctx, object instance, object[] param, IType[] genericArguments) { var type = instance.GetType(); if (type == typeof(ILTypeInstance)) { return ((ILTypeInstance)instance).Type.ReflectionType; } else return type; }*/ public static StackObject* EnumParse(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var p = esp - 1; string name = (string)StackObject.ToObject(p, domain, mStack); intp.Free(p); p = esp - 1 - 1; Type t = (Type)StackObject.ToObject(p, domain, mStack); intp.Free(p); if (t is ILRuntimeType) { ILType it = ((ILRuntimeType)t).ILType; if (it.IsEnum) { var fields = it.TypeDefinition.Fields; for (int i = 0; i < fields.Count; i++) { var f = fields[i]; if (f.IsStatic) { if (f.Name == name) { ILEnumTypeInstance ins = new ILEnumTypeInstance(it); ins[0] = f.Constant; ins.Boxed = true; return ILIntepreter.PushObject(ret, mStack, ins, true); } else { int val; if (int.TryParse(name, out val)) { if ((int)f.Constant == val) { ILEnumTypeInstance ins = new ILEnumTypeInstance(it); ins[0] = f.Constant; ins.Boxed = true; return ILIntepreter.PushObject(ret, mStack, ins, true); } } } } } return ILIntepreter.PushNull(ret); } else throw new Exception(string.Format("{0} is not Enum", t.FullName)); } else if (t is ILRuntimeWrapperType) { return ILIntepreter.PushObject(ret, mStack, Enum.Parse(((ILRuntimeWrapperType)t).RealType, name), true); } else return ILIntepreter.PushObject(ret, mStack, Enum.Parse(t, name), true); } public static StackObject* EnumGetValues(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var ret = esp - 1; AppDomain domain = intp.AppDomain; var p = esp - 1; Type t = (Type)StackObject.ToObject(p, domain, mStack); intp.Free(p); if (t is ILRuntimeType) { ILType it = ((ILRuntimeType)t).ILType; object res; //List res = new List(); if (it.IsEnum) { IList list = null; bool islong = false; var fields = it.TypeDefinition.Fields; for (int i = 0; i < fields.Count; i++) { var f = fields[i]; if (f.IsStatic) { if (list == null) { if (f.Constant is long) { list = new List(); islong = true; } else list = new List(); } list.Add(f.Constant); } } if (islong) res = ((List)list).ToArray(); else { if (list == null) res = new int[0]; else res = ((List)list).ToArray(); } return ILIntepreter.PushObject(ret, mStack, res, true); } else throw new Exception(string.Format("{0} is not Enum", t.FullName)); } else if (t is ILRuntimeWrapperType) { return ILIntepreter.PushObject(ret, mStack, Enum.GetValues(((ILRuntimeWrapperType)t).RealType), true); } else return ILIntepreter.PushObject(ret, mStack, Enum.GetValues(t), true); } public static StackObject* EnumGetNames(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var ret = esp - 1; AppDomain domain = intp.AppDomain; var p = esp - 1; Type t = (Type)StackObject.ToObject(p, domain, mStack); intp.Free(p); if (t is ILRuntimeType) { ILType it = ((ILRuntimeType)t).ILType; List res = new List(); if (it.IsEnum) { var fields = it.TypeDefinition.Fields; for (int i = 0; i < fields.Count; i++) { var f = fields[i]; if (f.IsStatic) { res.Add(f.Name); } } return ILIntepreter.PushObject(ret, mStack, res.ToArray(), true); } else throw new Exception(string.Format("{0} is not Enum", t.FullName)); } else if (t is ILRuntimeWrapperType) { return ILIntepreter.PushObject(ret, mStack, Enum.GetNames(((ILRuntimeWrapperType)t).RealType), true); } else return ILIntepreter.PushObject(ret, mStack, Enum.GetNames(t), true); } public static StackObject* EnumGetName(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var p = esp - 1; object val = StackObject.ToObject(p, domain, mStack); intp.Free(p); p = esp - 1 - 1; Type t = (Type)StackObject.ToObject(p, domain, mStack); intp.Free(p); if (t is ILRuntimeType) { ILType it = ((ILRuntimeType)t).ILType; List res = new List(); if (it.IsEnum) { if (val is ILEnumTypeInstance) { ILEnumTypeInstance ins = (ILEnumTypeInstance)val; return ILIntepreter.PushObject(ret, mStack, ins.ToString(), true); } else if (val.GetType().IsPrimitive) { ILEnumTypeInstance ins = new ILEnumTypeInstance(it); ins[0] = val; return ILIntepreter.PushObject(ret, mStack, ins.ToString(), true); } else throw new NotImplementedException(); } else throw new Exception(string.Format("{0} is not Enum", t.FullName)); } else if (t is ILRuntimeWrapperType) { return ILIntepreter.PushObject(ret, mStack, Enum.GetName(((ILRuntimeWrapperType)t).RealType, val), true); } else return ILIntepreter.PushObject(ret, mStack, Enum.GetName(t, val), true); } public static StackObject* EnumToObject(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var p = esp - 1; int val = p->Value; intp.Free(p); p = esp - 1 - 1; Type t = (Type)StackObject.ToObject(p, domain, mStack); intp.Free(p); if (t is ILRuntimeType) { ILType it = ((ILRuntimeType)t).ILType; List res = new List(); if (it.IsEnum) { ILEnumTypeInstance ins = new ILEnumTypeInstance(it); ins[0] = val; return ILIntepreter.PushObject(ret, mStack, ins, true); } else throw new Exception(string.Format("{0} is not Enum", t.FullName)); } else if (t is ILRuntimeWrapperType) { return ILIntepreter.PushObject(ret, mStack, Enum.GetName(((ILRuntimeWrapperType)t).RealType, val), true); } else return ILIntepreter.PushObject(ret, mStack, Enum.GetName(t, val), true); } #if NET_4_6 || NET_STANDARD_2_0 public static StackObject* EnumHasFlag(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var p = esp - 1; object val = StackObject.ToObject(p, domain, mStack); intp.Free(p); p = esp - 1 - 1; object ins = StackObject.ToObject(p, domain, mStack); intp.Free(p); bool res = false; if (ins is ILEnumTypeInstance) { ILEnumTypeInstance enumIns = (ILEnumTypeInstance)ins; int num = enumIns.Fields[0].Value; int valNum = ((ILEnumTypeInstance)val).Fields[0].Value; res = (num & valNum) == valNum; } else { res = ((Enum)ins).HasFlag((Enum)val); } if (res) return ILIntepreter.PushOne(ret); else return ILIntepreter.PushZero(ret); } public static StackObject* EnumCompareTo(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var ret = esp - 1 - 1; AppDomain domain = intp.AppDomain; var p = esp - 1; object val = StackObject.ToObject(p, domain, mStack); intp.Free(p); p = esp - 1 - 1; object ins = StackObject.ToObject(p, domain, mStack); intp.Free(p); int res = 0; if (ins is ILEnumTypeInstance) { ILEnumTypeInstance enumIns = (ILEnumTypeInstance)ins; int num = enumIns.Fields[0].Value; int valNum = ((ILEnumTypeInstance)val).Fields[0].Value; res = (num - valNum); } else { res = ((Enum)ins).CompareTo(val); } ret->ObjectType = ObjectTypes.Integer; ret->Value = res; return ret + 1; } #endif public static StackObject* DelegateCreateDelegate(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var ret = esp - 2; AppDomain domain = intp.AppDomain; var p = esp - 1; MethodInfo mi = (MethodInfo)StackObject.ToObject(p, domain, mStack); intp.Free(p); p = esp - 1 - 1; Type t = (Type)StackObject.ToObject(p, domain, mStack); intp.Free(p); if (t is ILRuntimeType) { ILType it = ((ILRuntimeType)t).ILType; if (it.IsDelegate) { var m = it.GetMethod("Invoke") as ILMethod; object ins = null; if (mi is ILRuntimeMethodInfo) { ILRuntimeMethodInfo imi = (ILRuntimeMethodInfo)mi; var ilMethod = imi.ILMethod; if (ilMethod.DelegateAdapter == null) { ilMethod.DelegateAdapter = domain.DelegateManager.FindDelegateAdapter(null, ilMethod, m); } ins = ilMethod.DelegateAdapter; } else { throw new NotSupportedException(); } return ILIntepreter.PushObject(ret, mStack, ins, true); } else throw new NotSupportedException(string.Format("{0} is not Delegate", t.FullName)); } else if (t is ILRuntimeWrapperType) { ILRuntimeWrapperType iwt = (ILRuntimeWrapperType)t; object ins = null; if (mi is ILRuntimeMethodInfo) { ILRuntimeMethodInfo imi = (ILRuntimeMethodInfo)mi; ins = domain.DelegateManager.FindDelegateAdapter(iwt.CLRType, null, imi.ILMethod); } else { ins = Delegate.CreateDelegate(iwt.RealType, mi); } return ILIntepreter.PushObject(ret, mStack, ins, true); } else return ILIntepreter.PushObject(ret, mStack, Delegate.CreateDelegate(t, mi), true); } public static StackObject* DelegateCreateDelegate2(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var ret = esp - 3; AppDomain domain = intp.AppDomain; var p = esp - 1; string name = (string)StackObject.ToObject(p, domain, mStack); intp.Free(p); p = esp - 2; object obj = (object)StackObject.ToObject(p, domain, mStack); intp.Free(p); p = esp - 3; Type t = (Type)StackObject.ToObject(p, domain, mStack); intp.Free(p); if (obj == null) throw new ArgumentNullException("Argument target cannot be null"); if (t is ILRuntimeType) { ILType it = ((ILRuntimeType)t).ILType; if (it.IsDelegate) { var m = it.GetMethod("Invoke") as ILMethod; if (obj is ILTypeInstance) { ILTypeInstance ii = (ILTypeInstance)obj; var ilMethod = ii.Type.GetMethod(name) as ILMethod; if (ilMethod == null) throw new ArgumentException(string.Format("Cannot find method \"{0}\" in type {1}", name, it.FullName)); if (ilMethod.DelegateAdapter == null) { ilMethod.DelegateAdapter = domain.DelegateManager.FindDelegateAdapter(ii, ilMethod, m); } object ins = ilMethod.DelegateAdapter; return ILIntepreter.PushObject(ret, mStack, ins, true); } else throw new NotSupportedException(); } else throw new NotSupportedException(string.Format("{0} is not Delegate", t.FullName)); } else if (t is ILRuntimeWrapperType) { ILRuntimeWrapperType iwt = (ILRuntimeWrapperType)t; object ins = null; if (obj is ILTypeInstance) { ILTypeInstance ii = (ILTypeInstance)obj; var ilMethod = ii.Type.GetMethod(name) as ILMethod; if (ilMethod == null) throw new ArgumentException(string.Format("Cannot find method \"{0}\" in type {1}", name, ii.Type.FullName)); ins = domain.DelegateManager.FindDelegateAdapter(iwt.CLRType, ii, ilMethod); } else { ins = Delegate.CreateDelegate(iwt.RealType, obj, name); } return ILIntepreter.PushObject(ret, mStack, ins, true); } else return ILIntepreter.PushObject(ret, mStack, Delegate.CreateDelegate(t, obj, name), true); } public static StackObject* DelegateCreateDelegate3(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var ret = esp - 3; AppDomain domain = intp.AppDomain; var p = esp - 1; MethodInfo mi = (MethodInfo)StackObject.ToObject(p, domain, mStack); intp.Free(p); p = esp - 2; object obj = (object)StackObject.ToObject(p, domain, mStack); intp.Free(p); p = esp - 3; Type t = (Type)StackObject.ToObject(p, domain, mStack); intp.Free(p); if (t is ILRuntimeType) { ILType it = ((ILRuntimeType)t).ILType; if (it.IsDelegate) { object ins = null; if (mi is ILRuntimeMethodInfo) { ILRuntimeMethodInfo imi = (ILRuntimeMethodInfo)mi; var ilMethod = imi.ILMethod; if (obj != null) { ins = ((ILTypeInstance)obj).GetDelegateAdapter(ilMethod); if (ins == null) { var invokeMethod = it.GetMethod("Invoke", ilMethod.ParameterCount); if (invokeMethod == null && ilMethod.IsExtend) { invokeMethod = it.GetMethod("Invoke", ilMethod.ParameterCount - 1); } ins = domain.DelegateManager.FindDelegateAdapter( (ILTypeInstance)obj, ilMethod, invokeMethod); } } else { if (ilMethod.DelegateAdapter == null) { var m = it.GetMethod("Invoke") as ILMethod; ilMethod.DelegateAdapter = domain.DelegateManager.FindDelegateAdapter(null, ilMethod, m); } ins = ilMethod.DelegateAdapter; } } else { throw new NotSupportedException(); } return ILIntepreter.PushObject(ret, mStack, ins, true); } else throw new NotSupportedException(string.Format("{0} is not Delegate", t.FullName)); } else if (t is ILRuntimeWrapperType) { ILRuntimeWrapperType iwt = (ILRuntimeWrapperType)t; object ins = null; if (mi is ILRuntimeMethodInfo) { ILRuntimeMethodInfo imi = (ILRuntimeMethodInfo)mi; ins = domain.DelegateManager.FindDelegateAdapter(iwt.CLRType, obj as ILTypeInstance, imi.ILMethod); } else { ins = Delegate.CreateDelegate(iwt.RealType, obj, mi); } return ILIntepreter.PushObject(ret, mStack, ins, true); } else return ILIntepreter.PushObject(ret, mStack, Delegate.CreateDelegate(t, obj, mi), true); } public static StackObject* TypeMakeGenericType(ILIntepreter intp, StackObject* esp, AutoList mStack, CLRMethod method, bool isNewObj) { var ret = esp - 2; AppDomain domain = intp.AppDomain; var p = esp - 1; Type[] param = (Type[])StackObject.ToObject(p, domain, mStack); intp.Free(p); p = esp - 2; Type type = (Type)StackObject.ToObject(p, domain, mStack); IType t = ToIType(type, domain); intp.Free(p); if (!t.HasGenericParameter) throw new NotSupportedException(string.Format("{0} is not a generic type", t.FullName)); ILType iltype = t as ILType; if(iltype != null) { KeyValuePair[] arr = new KeyValuePair[iltype.TypeDefinition.GenericParameters.Count]; for(int i = 0; i < arr.Length; i++) { arr[i] = new KeyValuePair(iltype.TypeDefinition.GenericParameters[i].Name, ToIType(param[i], domain)); } return ILIntepreter.PushObject(ret, mStack, t.MakeGenericInstance(arr).ReflectionType, true); } CLRType clrType = t as CLRType; if(clrType != null) { KeyValuePair[] arr = new KeyValuePair[param.Length]; for (int i = 0; i < arr.Length; i++) { arr[i] = new KeyValuePair("!", ToIType(param[i], domain)); } return ILIntepreter.PushObject(ret, mStack, t.MakeGenericInstance(arr).ReflectionType, true); } throw new NotImplementedException(); } static IType ToIType(Type type, AppDomain domain) { if (type is ILRuntimeType) { return ((ILRuntimeType)type).ILType; } else if (type is ILRuntimeWrapperType) { return ((ILRuntimeWrapperType)type).CLRType; } else return domain.GetType(type); } } }