static unsafe object to_object(TysosType enum_type, object value) { /* Convert value (of an integral type) to an enum of type 'enum_type' * and return its boxed value */ if (enum_type == null) { throw new ArgumentNullException("enumType"); } if (value == null) { throw new ArgumentException("value"); } /* The incoming value type 'value' is already boxed. * * We can therefore just copy its data to a new enum object */ void *value_obj = CastOperations.ReinterpretAsPointer(value); void *value_vtbl = *(void **)value_obj; int value_csize = *(int *)((byte *)value_vtbl + ClassOperations.GetVtblTypeSizeOffset()); void *ret_obj = MemoryOperations.GcMalloc(value_csize); MemoryOperations.MemCpy(ret_obj, value_obj, value_csize); void *ret_vtbl = *(void **)((byte *)CastOperations.ReinterpretAsPointer(enum_type) + ClassOperations.GetSystemTypeImplOffset()); *(void **)ret_obj = ret_vtbl; *(void **)((byte *)ret_obj + ClassOperations.GetMutexLockOffset()) = null; return(CastOperations.ReinterpretAsObject(ret_obj)); }
public unsafe override System.Reflection.ParameterInfo[] GetParameters() { if (_Params == null) { var pc = mspec.m.GetMethodDefSigParamCount(mspec.msig); var rt_idx = mspec.m.GetMethodDefSigRetTypeIndex(mspec.msig); mspec.m.GetTypeSpec(ref rt_idx, mspec.gtparams, mspec.gmparams); var _params = new TysosParameterInfo[pc]; var _ptypes = new TysosType[pc]; for (int i = 0; i < pc; i++) { var tspec = mspec.m.GetTypeSpec(ref rt_idx, mspec.gtparams, mspec.gmparams); TysosType tt = tspec; _ptypes[i] = tt; TysosParameterInfo tpi = new TysosParameterInfo(tt, i, this); _params[i] = tpi; } if (System.Threading.Interlocked.CompareExchange(ref _Params, _params, null) == null) { _ParamTypes = _ptypes; } } return(_Params); }
static unsafe void InternalSetValue(void *typedref, void *objval) { // get the type from the typed reference to see if we need to unbox the object // or store as a reference type void *et = *(void **)((byte *)typedref + ClassOperations.GetTypedReferenceTypeOffset()); void *ptr = *(void **)((byte *)typedref + ClassOperations.GetTypedReferenceValueOffset()); void *etextends = *(void **)((byte *)et + ClassOperations.GetVtblExtendsVtblPtrOffset()); if (etextends == OtherOperations.GetStaticObjectAddress("_Zu1L") || etextends == OtherOperations.GetStaticObjectAddress("_ZW6System4Enum")) { // this is a boxed value type. Get its size var vt_size = TysosType.GetValueTypeSize(et); // src ptr void *src = *(void **)((byte *)objval + ClassOperations.GetBoxedTypeDataOffset()); CopyMem((byte *)ptr, (byte *)src, vt_size); } else { // simply copy the reference *(void **)ptr = objval; } }
static unsafe void *InternalToObject(void *typedref) { // get the type from the typed reference to see if we need to box the object // or simply return the address as a reference type void *et = *(void **)((byte *)typedref + ClassOperations.GetTypedReferenceTypeOffset()); void *src = *(void **)((byte *)typedref + ClassOperations.GetTypedReferenceValueOffset()); void *etextends = *(void **)((byte *)et + ClassOperations.GetVtblExtendsVtblPtrOffset()); if (etextends == OtherOperations.GetStaticObjectAddress("_Zu1L") || etextends == OtherOperations.GetStaticObjectAddress("_ZW6System4Enum")) { // this is a boxed value type. Get its size var vt_size = TysosType.GetValueTypeSize(et); // build a new boxed type var ret = MemoryOperations.GcMalloc(*(int *)((byte *)et + ClassOperations.GetVtblTypeSizeOffset())); // dst ptr var dst = (byte *)ret + ClassOperations.GetBoxedTypeDataOffset(); CopyMem(dst, (byte *)src, vt_size); return(ret); } else { // simply copy the reference return(*(void **)src); } }
internal ConstructorInfo(TysosMethod meth, TysosType type) { if (meth == null) { throw new Exception("libsupcs.ConstructorInfo constructor called with meth as null"); } if (type == null) { throw new Exception("libsupcs.ConstructorInfo constructor called with type as null"); } _meth = meth; _type = type; }
static unsafe void get_enum_values_and_names(TysosType enum_type, HandleOnStack values_ptr, HandleOnStack names_ptr, bool getNames) { //System.Diagnostics.Debugger.Log(0, "libsupcs", "get_enum_values_and_names: enum_type: " + ((ulong)enum_vtbl).ToString("X16")); //var enum_type = TysosType.internal_from_vtbl(enum_vtbl); MonoEnumInfo info; get_enum_info(enum_type, out info); ulong[] values = new ulong[info.values.Length]; int[] v = info.values as int[]; for (int i = 0; i < info.values.Length; i++) { values[i] = (ulong)v[i]; } *values_ptr.ptr = CastOperations.ReinterpretAsPointer(values); if (getNames) { *names_ptr.ptr = CastOperations.ReinterpretAsPointer(info.names); } }
/* Build an array of a particular type */ public static unsafe T[] CreateSZArray <T>(int nitems, void *data_addr) { TysosType arrtt = (TysosType)typeof(T[]); TysosType elemtt = (TysosType)typeof(T); int elemsize; if (elemtt.IsValueType) { elemsize = elemtt.GetClassSize() - ClassOperations.GetBoxedTypeDataOffset(); } else { elemsize = OtherOperations.GetPointerSize(); } if (data_addr == null) { data_addr = MemoryOperations.GcMalloc(elemsize * nitems); } byte *ret = (byte *)MemoryOperations.GcMalloc(ArrayOperations.GetArrayClassSize() + 8); // extra space for lobounds and length array void *vtbl = *(void **)((byte *)CastOperations.ReinterpretAsPointer(arrtt) + ClassOperations.GetSystemTypeImplOffset()); *(void **)(ret + ClassOperations.GetVtblFieldOffset()) = vtbl; *(ulong *)(ret + ClassOperations.GetMutexLockOffset()) = 0; *(void **)(ret + ArrayOperations.GetElemTypeOffset()) = *(void **)((byte *)CastOperations.ReinterpretAsPointer(elemtt) + ClassOperations.GetSystemTypeImplOffset()); *(int *)(ret + ArrayOperations.GetElemSizeOffset()) = elemsize; *(void **)(ret + ArrayOperations.GetInnerArrayOffset()) = data_addr; *(void **)(ret + ArrayOperations.GetLoboundsOffset()) = ret + ArrayOperations.GetArrayClassSize(); *(void **)(ret + ArrayOperations.GetSizesOffset()) = ret + ArrayOperations.GetArrayClassSize() + 4; *(int *)(ret + ArrayOperations.GetRankOffset()) = 1; *(int *)(ret + ArrayOperations.GetArrayClassSize()) = 0; // lobounds[0] *(int *)(ret + ArrayOperations.GetArrayClassSize() + 4) = nitems; // sizes[0] return((T[])CastOperations.ReinterpretAsObject(ret)); }
internal static unsafe metadata.TypeSpec GetTypeSpec(TysosType t) { void **impl_ptr = t.GetImplOffset(); return(GetTypeSpec(*impl_ptr)); }
static internal unsafe TysosType GetUnderlyingEnumType(TysosType enum_type) { void *e_type_vtbl = *enum_type.GetImplOffset(); return(TysosType.internal_from_vtbl(GetUnderlyingEnumTypeVtbl(*(void **)e_type_vtbl))); }
static unsafe void get_enum_info(TysosType enumType, out MonoEnumInfo info) { MonoEnumInfo ret = new MonoEnumInfo(); ret.utype = GetUnderlyingEnumType(enumType); if (!ret.utype.Equals(typeof(int))) { throw new Exception("get_enum_info: currently only enums with an underlying type of int are supported"); } var ets = enumType.tspec; /* Iterate through methods looking for requested * one */ var first_fdef = ets.m.GetIntEntry(metadata.MetadataStream.tid_TypeDef, ets.tdrow, 4); var last_fdef = ets.m.GetLastFieldDef(ets.tdrow); // First iterate to get number of satic fields int static_fields = 0; for (uint fdef_row = first_fdef; fdef_row < last_fdef; fdef_row++) { var flags = ets.m.GetIntEntry(metadata.MetadataStream.tid_Field, (int)fdef_row, 0); if ((flags & 0x10) == 0x10) { static_fields++; } } ret.names = new string[static_fields]; int[] values = new int[static_fields]; System.Diagnostics.Debugger.Log(0, "libsupcs", "Enum.get_enum_info: found " + static_fields.ToString() + " entries"); static_fields = 0; // Iterate again to get the details for (uint fdef_row = first_fdef; fdef_row < last_fdef; fdef_row++) { var flags = ets.m.GetIntEntry(metadata.MetadataStream.tid_Field, (int)fdef_row, 0); if ((flags & 0x10) == 0x10) { var name = ets.m.GetStringEntry(metadata.MetadataStream.tid_Field, (int)fdef_row, 1); ret.names[static_fields] = name; System.Diagnostics.Debugger.Log(0, "libsupcs", "Enum.get_enum_info: field: " + name); var const_row = ets.m.const_field_owners[fdef_row]; if (const_row != 0) { var const_offset = (int)ets.m.GetIntEntry(metadata.MetadataStream.tid_Constant, const_row, 2); ets.m.SigReadUSCompressed(ref const_offset); var const_val = ets.m.sh_blob.di.ReadInt(const_offset); values[static_fields] = const_val; System.Diagnostics.Debugger.Log(0, "libsupcs", "Enum.get_enum_info: value: " + const_val.ToString()); } static_fields++; } } ret.values = values; info = ret; }
public TysosMethod(metadata.MethodSpec ms, TysosType owning_type) { mspec = ms; OwningType = owning_type; }
public override object Invoke(object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] parameters, System.Globalization.CultureInfo culture) { uint flags = 0; if (MethodAddress == null) { var mangled_name = mspec.MangleMethod(); System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosMethod.Invoke: requesting run-time address for " + mangled_name); MethodAddress = JitOperations.GetAddressOfObject(mspec.MangleMethod()); if (MethodAddress == null) { System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosMethod.Invoke: jit compiling method"); MethodAddress = JitOperations.JitCompile(this.mspec); } } if (MethodAddress == null) { throw new System.Reflection.TargetException("Method does not have a defined implementation (" + OwningType.FullName + "." + Name + "())"); } if (!IsStatic && (obj == null)) { throw new System.Reflection.TargetException("Instance method and obj is null (" + OwningType.FullName + "." + Name + "())"); } // TODO: check number and type of parameters is what the method expects // Get total number of parameters int p_length = 0; if (parameters != null) { p_length = parameters.Length; } if (!IsStatic) { p_length++; } // See InternalStrCpy for the rationale here int max_stack_alloc = p_length > 512 ? 512 : p_length; IntPtr *pstack = stackalloc IntPtr[max_stack_alloc]; IntPtr *tstack = stackalloc IntPtr[max_stack_alloc]; void **ps, ts; if (max_stack_alloc <= 512) { ps = (void **)pstack; ts = (void **)tstack; } else { ps = (void **)MemoryOperations.GcMalloc(p_length * sizeof(void *)); ts = (void **)MemoryOperations.GcMalloc(p_length * sizeof(void *)); } // Build a new params array to include obj if necessary, and a tysos type array int curptr = 0; if (!IsStatic) { ps[0] = CastOperations.ReinterpretAsPointer(obj); ts[0] = OtherOperations.GetStaticObjectAddress("_Zu1O"); curptr++; } if (parameters != null) { for (int i = 0; i < parameters.Length; i++, curptr++) { var cp = CastOperations.ReinterpretAsPointer(parameters[i]); ps[curptr] = cp; ts[curptr] = *(void **)cp; } } if (!IsStatic) { flags |= invoke_flag_instance; } if (OwningType.IsValueType) { flags |= invoke_flag_vt; } if (ReturnType != null && ReturnType.IsValueType) { flags |= invoke_flag_vt_ret; } return(CastOperations.ReinterpretAsObject(InternalInvoke(MethodAddress, p_length, ps, ts, (ReturnType != null) ? TysosType.ReinterpretAsType(ReturnType)._impl : null, flags))); }
static unsafe void Copy(void *srcArr, int srcIndex, void *dstArr, int dstIndex, int length, bool reliable) { /* Ensure arrays are valid */ if (srcArr == null || dstArr == null) { throw new ArgumentNullException(); } /* Ensure length is valid */ if (length < 0) { throw new ArgumentOutOfRangeException(); } /* Ensure both arrays are of the same rank */ var srcRank = *(int *)((byte *)srcArr + ArrayOperations.GetRankOffset()); var dstRank = *(int *)((byte *)dstArr + ArrayOperations.GetRankOffset()); if (srcRank != dstRank) { throw new RankException(); } /* Get source and dest element types */ var srcET = *(void **)((byte *)srcArr + ArrayOperations.GetElemTypeOffset()); var dstET = *(void **)((byte *)dstArr + ArrayOperations.GetElemTypeOffset()); /* See if we can do a quick copy */ bool can_quick_copy = false; if (srcET == dstET) { can_quick_copy = true; } else if (TysosType.CanCast(srcET, dstET)) { can_quick_copy = true; } else if (reliable) { throw new ArrayTypeMismatchException(); /* ConstrainedCopy requires types to be the same or derived */ } else { can_quick_copy = false; } /* For now we don't handle arrays with lobounds != 0 */ var srcLobounds = *(int **)((byte *)srcArr + ArrayOperations.GetLoboundsOffset()); var dstLobounds = *(int **)((byte *)dstArr + ArrayOperations.GetLoboundsOffset()); for (int i = 0; i < srcRank; i++) { if (srcLobounds[i] != 0) { throw new NotImplementedException("srcLobounds != 0"); } if (dstLobounds[i] != 0) { throw new NotImplementedException("dstLobounds != 0"); } } if (srcIndex < 0 || dstIndex < 0) { throw new ArgumentOutOfRangeException(); } /* Ensure we don't overflow */ var src_len = GetLength(srcArr); var dst_len = GetLength(dstArr); if (srcIndex + length > src_len) { System.Diagnostics.Debugger.Log(0, "libsupcs", "Array.Copy srcIndex/length out of range"); System.Diagnostics.Debugger.Log(length, "libsupcs", "length"); System.Diagnostics.Debugger.Log(srcIndex, "libsupcs", "srcIndex"); System.Diagnostics.Debugger.Log(src_len, "libsupcs", "src_len"); throw new ArgumentOutOfRangeException(); } if (dstIndex + length > dst_len) { System.Diagnostics.Debugger.Log(0, "libsupcs", "Array.Copy dstIndex/length out of range"); System.Diagnostics.Debugger.Log(length, "libsupcs", "length"); System.Diagnostics.Debugger.Log(dstIndex, "libsupcs", "dstIndex"); System.Diagnostics.Debugger.Log(dst_len, "libsupcs", "dst_len"); throw new ArgumentOutOfRangeException(); } if (can_quick_copy) { /* Elem size of both arrays is guaranteed to be the same and we can do a shallow copy */ var e_size = *(int *)((byte *)srcArr + ArrayOperations.GetElemSizeOffset()); var src_ia = *(byte **)((byte *)srcArr + ArrayOperations.GetInnerArrayOffset()); var dst_ia = *(byte **)((byte *)dstArr + ArrayOperations.GetInnerArrayOffset()); MemoryOperations.MemMove(dst_ia + dstIndex * e_size, src_ia + srcIndex * e_size, length * e_size); } else { /* TODO: implement as per System.Array.Copy() semantics */ throw new NotImplementedException("Cannot quick copy " + ((ulong)srcET).ToString("X") + " to " + ((ulong)dstET).ToString("X")); } }