/* * public static bool ClrSetTypedReference(TypedReference target, * Object value); */ ILBool _IL_TypedReference_ClrSetTypedReference(ILExecThread *_thread, ILTypedRef target, ILObject *value) { ILType *type; if(target.type == 0 || target.value == 0) { /* This is an invalid typed reference */ return 0; } type = ILClassToType(target.type); if(ILType_IsPrimitive(type) || ILType_IsValueType(type)) { if(!ILExecThreadUnbox(_thread, type, value, target.value)) { return 0; } return 1; } else if(ILTypeAssignCompatible (ILProgramItem_Image(_thread->method), (value ? ILClassToType(GetObjectClass(value)) : 0), type)) { *((ILObject **)(target.value)) = value; return 1; } else { return 0; } }
/* * Convert an IL type into an "ffi" type descriptor. */ static ffi_type *TypeToFFI(ILExecProcess *process, ILType *type, int isInternal) { if(ILType_IsPrimitive(type)) { /* Determine how to marshal a primitive type */ switch(ILType_ToElement(type)) { case IL_META_ELEMTYPE_VOID: return &ffi_type_void; case IL_META_ELEMTYPE_BOOLEAN: return &ffi_type_sint8; case IL_META_ELEMTYPE_I1: return &ffi_type_sint8; case IL_META_ELEMTYPE_U1: return &ffi_type_uint8; case IL_META_ELEMTYPE_I2: return &ffi_type_sint16; case IL_META_ELEMTYPE_U2: return &ffi_type_uint16; case IL_META_ELEMTYPE_CHAR: return &ffi_type_uint16; case IL_META_ELEMTYPE_I4: return &ffi_type_sint32; case IL_META_ELEMTYPE_U4: return &ffi_type_uint32; #ifdef IL_NATIVE_INT32 case IL_META_ELEMTYPE_I: return &ffi_type_sint32; case IL_META_ELEMTYPE_U: return &ffi_type_uint32; #else case IL_META_ELEMTYPE_I: return &ffi_type_sint64; case IL_META_ELEMTYPE_U: return &ffi_type_uint64; #endif case IL_META_ELEMTYPE_I8: return &ffi_type_sint64; case IL_META_ELEMTYPE_U8: return &ffi_type_uint64; case IL_META_ELEMTYPE_R4: return &ffi_type_float; case IL_META_ELEMTYPE_R8: return &ffi_type_double; #ifdef IL_NATIVE_FLOAT case IL_META_ELEMTYPE_R: return &ffi_type_longdouble; #else case IL_META_ELEMTYPE_R: return &ffi_type_double; #endif case IL_META_ELEMTYPE_TYPEDBYREF: return &ffi_type_typedref; } return &ffi_type_pointer; } #ifdef IL_CONFIG_PINVOKE else if(!isInternal && ILType_IsValueType(type)) { /* Structure that is passed by value to a PInvoke method */ ffi_type *ffi = StructToFFI(process, ILClassResolve(ILType_ToValueType(type))); return (ffi ? ffi : &ffi_type_pointer); } #endif else { /* Everything else is passed as a pointer */ return &ffi_type_pointer; } }
/* * private static Object InternalGetUnitializaedObject(Type type); */ ILObject *_IL_FormatterServices_InternalGetUninitializedObject (ILExecThread *_thread, ILObject *type) { ILClass *classInfo = _ILGetClrClass(_thread, type); ILType *classType; if(classInfo) { classType = ILClassToType(classInfo); if(classType && (ILType_IsClass(classType) || ILType_IsValueType(classType) || ILType_IsPrimitive(classType)) && !ILTypeIsStringClass(classType)) { return _ILEngineAllocObject(_thread, classInfo); } } return 0; }
/* * Convert a type into an engine type. */ static ILEngineType TypeToEngineType(ILType *type) { type = ILTypeGetEnumType(type); if(ILType_IsPrimitive(type)) { switch(ILType_ToElement(type)) { case IL_META_ELEMTYPE_BOOLEAN: case IL_META_ELEMTYPE_I1: case IL_META_ELEMTYPE_U1: case IL_META_ELEMTYPE_I2: case IL_META_ELEMTYPE_U2: case IL_META_ELEMTYPE_CHAR: case IL_META_ELEMTYPE_I4: case IL_META_ELEMTYPE_U4: return ILEngineType_I4; case IL_META_ELEMTYPE_I8: case IL_META_ELEMTYPE_U8: return ILEngineType_I8; case IL_META_ELEMTYPE_I: case IL_META_ELEMTYPE_U: return ILEngineType_I; case IL_META_ELEMTYPE_R4: case IL_META_ELEMTYPE_R8: case IL_META_ELEMTYPE_R: return ILEngineType_F; case IL_META_ELEMTYPE_TYPEDBYREF: return ILEngineType_TypedRef; } return ILEngineType_I4; } else if(ILType_IsValueType(type)) { return ILEngineType_MV; } else if(ILType_IsComplex(type) && type != 0) { switch(ILType_Kind(type)) { case IL_TYPE_COMPLEX_PTR: { /* Unsafe pointers are represented as native integers */ return ILEngineType_I; } /* Not reached */ case IL_TYPE_COMPLEX_BYREF: { /* Reference values are managed pointers */ return ILEngineType_M; } /* Not reached */ case IL_TYPE_COMPLEX_PINNED: { /* Pinned types are the same as their underlying type */ return TypeToEngineType(ILType_Ref(type)); } /* Not reached */ case IL_TYPE_COMPLEX_CMOD_REQD: case IL_TYPE_COMPLEX_CMOD_OPT: { /* Strip the modifier and inspect the underlying type */ return TypeToEngineType(type->un.modifier__.type__); } /* Not reached */ case IL_TYPE_COMPLEX_METHOD: case IL_TYPE_COMPLEX_METHOD | IL_TYPE_COMPLEX_METHOD_SENTINEL: { /* Pass method pointers around the system as "I". Higher level code will also set the "typeInfo" field to reflect the signature so that method pointers become verifiable */ return ILEngineType_I; } /* Not reached */ } } return ILEngineType_O; }
/* * Convert a type into its primitive form, ignoring slight differences * in type that don't matter because we can blindly cast between the * equivalents without losing type-safety. */ static int ArgTypeToPrimitive(ILType *type) { if(ILType_IsPrimitive(type)) { switch(ILType_ToElement(type)) { case IL_META_ELEMTYPE_BOOLEAN: case IL_META_ELEMTYPE_I1: case IL_META_ELEMTYPE_U1: return IL_META_ELEMTYPE_I1; case IL_META_ELEMTYPE_I2: case IL_META_ELEMTYPE_U2: case IL_META_ELEMTYPE_CHAR: return IL_META_ELEMTYPE_I2; case IL_META_ELEMTYPE_I4: case IL_META_ELEMTYPE_U4: #ifdef IL_NATIVE_INT32 case IL_META_ELEMTYPE_I: case IL_META_ELEMTYPE_U: #endif return IL_META_ELEMTYPE_I4; case IL_META_ELEMTYPE_I8: case IL_META_ELEMTYPE_U8: #ifdef IL_NATIVE_INT64 case IL_META_ELEMTYPE_I: case IL_META_ELEMTYPE_U: #endif return IL_META_ELEMTYPE_I8; case IL_META_ELEMTYPE_R4: return IL_META_ELEMTYPE_R4; case IL_META_ELEMTYPE_R8: case IL_META_ELEMTYPE_R: return IL_META_ELEMTYPE_R8; default: break; } return IL_META_ELEMTYPE_END; } else if(ILType_IsValueType(type)) { if(ILTypeIsEnum(type)) { return ArgTypeToPrimitive(ILTypeGetEnumType(type)); } else { return IL_META_ELEMTYPE_VALUETYPE; } } else if(ILType_IsPointer(type)) { #ifdef IL_NATIVE_INT32 return IL_META_ELEMTYPE_I4; #else return IL_META_ELEMTYPE_I8; #endif } else { return IL_META_ELEMTYPE_END; } }
/* * Unpack the result of a delegate closure call. */ static void UnpackDelegateResult(ILExecThread *thread, ILMethod *method, int isCtor, void *result, void *userData) { ILMethod *pinvokeInfo = ((PackDelegateUserData *)userData)->pinvokeInfo; ILType *signature = ILMethod_Signature(method); ILType *paramType; ILUInt32 size, sizeInWords; ILNativeFloat tempFloat; ILUInt32 marshalType; char *customName; int customNameLen; char *customCookie; int customCookieLen; /* Marshal return types that need special handling */ marshalType = ILPInvokeGetMarshalType (0, pinvokeInfo, 0, &customName, &customNameLen, &customCookie, &customCookieLen, ILTypeGetReturn(signature)); if(marshalType != IL_META_MARSHAL_DIRECT) { switch(marshalType) { case IL_META_MARSHAL_ANSI_STRING: { /* Marshal an ANSI string back to the native world */ *((char **)result) = ILStringToAnsi (thread, (ILString *)(thread->stackTop[-1].ptrValue)); --(thread->stackTop); } return; case IL_META_MARSHAL_UTF8_STRING: { /* Marshal a UTF-8 string back to the native world */ *((char **)result) = ILStringToUTF8 (thread, (ILString *)(thread->stackTop[-1].ptrValue)); --(thread->stackTop); } return; case IL_META_MARSHAL_UTF16_STRING: { /* Marshal a UTF-16 string back to the native world */ *((ILUInt16 **)result) = ILStringToUTF16 (thread, (ILString *)(thread->stackTop[-1].ptrValue)); --(thread->stackTop); } return; case IL_META_MARSHAL_FNPTR: { /* Convert a delegate into a function closure pointer */ *((void **)result) = _ILDelegateGetClosure (thread, (ILObject *)(thread->stackTop[-1].ptrValue)); --(thread->stackTop); } return; case IL_META_MARSHAL_ARRAY: { /* Convert an array into a pointer to its first member */ void *array = thread->stackTop[-1].ptrValue; --(thread->stackTop); if(array) { *((void **)result) = ArrayToBuffer(array); } else { *((void **)result) = 0; } } return; case IL_META_MARSHAL_CUSTOM: { /* Marshal a custom value to the native world */ *((void **)result) = _ILObjectToCustom (thread, (ILObject *)(thread->stackTop[-1].ptrValue), customName, customNameLen, customCookie, customCookieLen); --(thread->stackTop); } return; } } /* Copy the return value into place */ paramType = ILTypeGetEnumType(ILTypeGetReturn(signature)); if(ILType_IsPrimitive(paramType)) { /* Process a primitive value */ switch(ILType_ToElement(paramType)) { case IL_META_ELEMTYPE_VOID: break; case IL_META_ELEMTYPE_BOOLEAN: case IL_META_ELEMTYPE_I1: case IL_META_ELEMTYPE_U1: case IL_META_ELEMTYPE_I2: case IL_META_ELEMTYPE_U2: case IL_META_ELEMTYPE_CHAR: case IL_META_ELEMTYPE_I4: case IL_META_ELEMTYPE_U4: #ifdef IL_NATIVE_INT32 case IL_META_ELEMTYPE_I: case IL_META_ELEMTYPE_U: #endif { *((ILInt32 *)result) = thread->stackTop[-1].intValue; --(thread->stackTop); } break; case IL_META_ELEMTYPE_I8: case IL_META_ELEMTYPE_U8: #ifdef IL_NATIVE_INT64 case IL_META_ELEMTYPE_I: case IL_META_ELEMTYPE_U: #endif { ILMemCpy(result, thread->stackTop - CVM_WORDS_PER_LONG, sizeof(ILInt64)); thread->stackTop -= CVM_WORDS_PER_LONG; } break; case IL_META_ELEMTYPE_R4: { ILMemCpy(&tempFloat, thread->stackTop - CVM_WORDS_PER_NATIVE_FLOAT, sizeof(ILNativeFloat)); *((ILFloat *)result) = (ILFloat)tempFloat; thread->stackTop -= CVM_WORDS_PER_NATIVE_FLOAT; } break; case IL_META_ELEMTYPE_R8: { ILMemCpy(&tempFloat, thread->stackTop - CVM_WORDS_PER_NATIVE_FLOAT, sizeof(ILNativeFloat)); *((ILDouble *)result) = (ILDouble)tempFloat; thread->stackTop -= CVM_WORDS_PER_NATIVE_FLOAT; } break; case IL_META_ELEMTYPE_R: { ILMemCpy(result, thread->stackTop - CVM_WORDS_PER_NATIVE_FLOAT, sizeof(ILNativeFloat)); thread->stackTop -= CVM_WORDS_PER_NATIVE_FLOAT; } break; case IL_META_ELEMTYPE_TYPEDBYREF: { ILMemCpy(result, thread->stackTop - CVM_WORDS_PER_TYPED_REF, sizeof(ILTypedRef)); thread->stackTop -= CVM_WORDS_PER_TYPED_REF; } break; } } else if(ILType_IsClass(paramType)) { /* Process an object reference */ *((void **)result) = thread->stackTop[-1].ptrValue; --(thread->stackTop); } else if(ILType_IsValueType(paramType)) { /* Process a value type */ size = ILSizeOfType(thread, paramType); sizeInWords = ((size + sizeof(CVMWord) - 1) / sizeof(CVMWord)); ILMemCpy(result, thread->stackTop - sizeInWords, size); thread->stackTop -= sizeInWords; } else { /* Assume that everything else is an object reference */ *((void **)result) = thread->stackTop[-1].ptrValue; --(thread->stackTop); } }
/* * Pack the parameters for a delegate closure call onto the CVM stack. */ static int PackDelegateParams(ILExecThread *thread, ILMethod *method, int isCtor, void *_this, void *userData) { void **args = ((PackDelegateUserData *)userData)->args; ILMethod *pinvokeInfo = ((PackDelegateUserData *)userData)->pinvokeInfo; ILType *signature = ILMethod_Signature(method); CVMWord *stacktop, *stacklimit; ILUInt32 param, numParams; ILType *paramType; void *ptr; ILUInt32 size, sizeInWords; ILNativeFloat tempFloat; ILUInt32 marshalType; char *customName; int customNameLen; char *customCookie; int customCookieLen; char *strValue; /* Get the top and extent of the stack */ stacktop = thread->stackTop; stacklimit = thread->stackLimit; /* Push the arguments onto the evaluation stack */ if(ILType_HasThis(signature)) { /* Push the "this" argument */ CHECK_SPACE(1); if(((PackDelegateUserData *)userData)->needThis) { /* We get the "this" value from the incoming arguments */ stacktop->ptrValue = *((void **)(*args)); ++args; } else { /* We get the "this" value from the delegate object */ stacktop->ptrValue = _this; } ++stacktop; } numParams = ILTypeNumParams(signature); for(param = 1; param <= numParams; ++param) { /* Marshal parameters that need special handling */ marshalType = ILPInvokeGetMarshalType(0, pinvokeInfo, param, &customName, &customNameLen, &customCookie, &customCookieLen, ILTypeGetParam(signature, param)); if(marshalType != IL_META_MARSHAL_DIRECT) { switch(marshalType) { case IL_META_MARSHAL_ANSI_STRING: { /* Marshal an ANSI string from the native world */ CHECK_SPACE(1); strValue = *((char **)(*args)); if(strValue) { stacktop->ptrValue = ILStringCreate(thread, strValue); /* Free the native string */ ILFreeNativeString(strValue); if(!(stacktop->ptrValue)) { return 1; } } else { stacktop->ptrValue = 0; } ++args; ++stacktop; } continue; case IL_META_MARSHAL_UTF8_STRING: { /* Marshal a UTF-8 string from the native world */ CHECK_SPACE(1); strValue = *((char **)(*args)); if(strValue) { stacktop->ptrValue = ILStringCreateUTF8(thread, strValue); /* Free the native string */ ILFreeNativeString(strValue); if(!(stacktop->ptrValue)) { return 1; } } else { stacktop->ptrValue = 0; } ++args; ++stacktop; } continue; case IL_META_MARSHAL_UTF16_STRING: { /* Marshal a UTF-16 string from the native world */ CHECK_SPACE(1); strValue = *((char **)(*args)); if(strValue) { stacktop->ptrValue = ILStringWCreate(thread, (ILUInt16 *)strValue); /* Free the native string */ ILFreeNativeString(strValue); if(!(stacktop->ptrValue)) { return 1; } } else { stacktop->ptrValue = 0; } ++args; ++stacktop; } continue; case IL_META_MARSHAL_CUSTOM: { /* Marshal a custom value from the native world */ CHECK_SPACE(1); stacktop->ptrValue = _ILCustomToObject (thread, *((void **)(*args)), customName, customNameLen, customCookie, customCookieLen); if(_ILExecThreadHasException(thread)) { return 1; } ++args; ++stacktop; } continue; } } /* Marshal the parameter directly */ paramType = ILTypeGetEnumType(ILTypeGetParam(signature, param)); if(ILType_IsPrimitive(paramType)) { /* Process a primitive value */ switch(ILType_ToElement(paramType)) { case IL_META_ELEMTYPE_VOID: break; case IL_META_ELEMTYPE_BOOLEAN: case IL_META_ELEMTYPE_I1: case IL_META_ELEMTYPE_U1: case IL_META_ELEMTYPE_I2: case IL_META_ELEMTYPE_U2: case IL_META_ELEMTYPE_CHAR: case IL_META_ELEMTYPE_I4: case IL_META_ELEMTYPE_U4: #ifdef IL_NATIVE_INT32 case IL_META_ELEMTYPE_I: case IL_META_ELEMTYPE_U: #endif { CHECK_SPACE(1); stacktop->intValue = *((ILInt32 *)(*args)); ++args; ++stacktop; } break; case IL_META_ELEMTYPE_I8: case IL_META_ELEMTYPE_U8: #ifdef IL_NATIVE_INT64 case IL_META_ELEMTYPE_I: case IL_META_ELEMTYPE_U: #endif { CHECK_SPACE(CVM_WORDS_PER_LONG); ILMemCpy(stacktop, *args, sizeof(ILInt64)); ++args; stacktop += CVM_WORDS_PER_LONG; } break; case IL_META_ELEMTYPE_R4: { CHECK_SPACE(CVM_WORDS_PER_NATIVE_FLOAT); tempFloat = (ILNativeFloat)(*((ILFloat *)(*args))); ILMemCpy(stacktop, &tempFloat, sizeof(ILNativeFloat)); ++args; stacktop += CVM_WORDS_PER_NATIVE_FLOAT; } break; case IL_META_ELEMTYPE_R8: { CHECK_SPACE(CVM_WORDS_PER_NATIVE_FLOAT); tempFloat = (ILNativeFloat)(*((ILDouble *)(*args))); ILMemCpy(stacktop, &tempFloat, sizeof(ILNativeFloat)); ++args; stacktop += CVM_WORDS_PER_NATIVE_FLOAT; } break; case IL_META_ELEMTYPE_R: { CHECK_SPACE(CVM_WORDS_PER_NATIVE_FLOAT); ILMemCpy(stacktop, *args, sizeof(ILNativeFloat)); ++args; stacktop += CVM_WORDS_PER_NATIVE_FLOAT; } break; case IL_META_ELEMTYPE_TYPEDBYREF: { CHECK_SPACE(CVM_WORDS_PER_TYPED_REF); ILMemCpy(stacktop, *args, sizeof(ILTypedRef)); ++args; stacktop += CVM_WORDS_PER_TYPED_REF; } break; } } else if(ILType_IsClass(paramType)) { /* Process an object reference */ CHECK_SPACE(1); stacktop->ptrValue = *((void **)(*args)); ++args; ++stacktop; } else if(ILType_IsValueType(paramType)) { /* Process a value type which was passed by value */ ptr = *args; ++args; size = ILSizeOfType(thread, paramType); sizeInWords = ((size + sizeof(CVMWord) - 1) / sizeof(CVMWord)); CHECK_SPACE(sizeInWords); ILMemCpy(stacktop, ptr, size); stacktop += sizeInWords; } else if(paramType != 0 && ILType_IsComplex(paramType) && (ILType_Kind(paramType) == IL_TYPE_COMPLEX_BYREF || ILType_Kind(paramType) == IL_TYPE_COMPLEX_PTR)) { /* Process a value that is being passed by reference */ CHECK_SPACE(1); stacktop->ptrValue = *((void **)(*args)); ++args; ++stacktop; } else { /* Assume that everything else is an object reference */ CHECK_SPACE(1); stacktop->ptrValue = *args; ++args; ++stacktop; } } /* Update the stack top */ thread->stackTop = stacktop; return 0; }