ILClass *ILClassResolveToInstance(ILClass *classInfo, ILMethod *methodCaller) { ILType *classTypeArgs = 0; ILType *methodTypeArgs = 0; ILType *classType; classInfo = ILClassResolve(classInfo); classType = ILClass_SynType(classInfo); if(!classType || (!ILTypeNeedsInstantiation(classType) && !ILClassNeedsExpansion(classInfo))) { return classInfo; } if(ILMember_IsGenericInstance(methodCaller)) { ILMethodInstance *methodInstance = (ILMethodInstance *)methodCaller; classTypeArgs = methodInstance->classTypeArguments; methodTypeArgs = methodInstance->methodTypeArguments; } classInfo = ILClassExpand(ILClassToImage(classInfo), classInfo, classTypeArgs, methodTypeArgs); return classInfo; }
/* * Get the total spanning size of an interface inheritance tree. */ static int GetSpanningSize(ILClass *interface) { int size = 1; ILImplements *impl = 0; while((impl = ILClassNextImplements(interface, impl)) != 0) { size += GetSpanningSize(ILClassResolve(ILImplementsGetInterface(impl))); } return size; }
ILObject *_ILGetClrType(ILExecThread *thread, ILClass *classInfo) { ILObject *obj; classInfo = ILClassResolve(classInfo); if(!classInfo) { thread->thrownException = _ILSystemException (thread, "System.TypeInitializationException"); return 0; } /* Make sure that the class has been laid out */ IL_METADATA_WRLOCK(_ILExecThreadProcess(thread)); if(!_ILLayoutClass(_ILExecThreadProcess(thread), classInfo)) { IL_METADATA_UNLOCK(_ILExecThreadProcess(thread)); thread->thrownException = _ILSystemException (thread, "System.TypeInitializationException"); return 0; } IL_METADATA_UNLOCK(_ILExecThreadProcess(thread)); /* Does the class already have a "ClrType" instance? */ if(((ILClassPrivate *)(classInfo->userData))->clrType) { return ((ILClassPrivate *)(classInfo->userData))->clrType; } /* Create a new "ClrType" instance */ if(!(thread->process->clrTypeClass)) { thread->thrownException = _ILSystemException (thread, "System.TypeInitializationException"); return 0; } obj = _ILEngineAllocObject(thread, thread->process->clrTypeClass); if(!obj) { return 0; } /* Fill in the object with the class information */ ((System_Reflection *)obj)->privateData = classInfo; /* Attach the object to the class so that it will be returned for future calls to this function */ ((ILClassPrivate *)(classInfo->userData))->clrType = obj; /* Return the object to the caller */ return obj; }
/* * 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 TypedReference ClrMakeTypedReference(Object target, * FieldInfo[] flds); */ ILTypedRef _IL_TypedReference_ClrMakeTypedReference(ILExecThread *_thread, ILObject *target, System_Array *flds) { ILClass *classInfo; ILInt32 index; ILUInt32 offset; ILTypedRef ref; ILField *field; /* Get the initial class and offset */ classInfo = GetObjectClass(target); offset = 0; /* Resolve the fields within the object, level by level */ for(index = 0; index < ArrayLength(flds); ++index) { field = *((ILField **)(((ILObject **)(ArrayToBuffer(flds)))[index])); if(!field) { ILExecThreadThrowSystem (_thread, "System.ArgumentException", "Arg_MakeTypedRefFields"); ref.type = 0; ref.value = 0; return ref; } offset += field->offset; classInfo = ILClassFromType (ILContextNextImage(_thread->process->context, 0), 0, ILField_Type(field), 0); classInfo = ILClassResolve(classInfo); if(!classInfo || (index < (ArrayLength(flds) - 1) && !ILClassIsValueType(classInfo))) { ILExecThreadThrowSystem (_thread, "System.ArgumentException", "Arg_MakeTypedRefFields"); ref.type = 0; ref.value = 0; return ref; } } /* Populate the typed reference */ ref.type = (void *)classInfo; ref.value = (void *)(((unsigned char *)target) + offset); return ref; }
/* * Determine if "classInfo" fully implements all parent interfaces * of "refClass". Note: Returns non-zero on error. */ static int ImplementsAllInterfaces(ILNode *node, ILClass *classInfo, ILClass *refClass, ILGenInterfaceErrorFunc error, ILGenInterfaceProxyFunc proxy, ILClass **visited, int *visitedSize) { ILImplements *impl = 0; int sawErrors = 0; while((impl = ILClassNextImplements(refClass, impl)) != 0) { sawErrors |= ImplementsInterface (node, classInfo, ILClassResolve(ILImplementsGetInterface(impl)), error, proxy, visited, visitedSize); } return sawErrors; }
/* * Determine if a stack item is assignment-compatible with * a particular memory slot (argument, local, field, etc). */ static int AssignCompatible(ILMethod *method, ILEngineStackItem *item, ILType *type, int unsafeAllowed) { ILImage *image; ILClass *classInfo; ILClass *classInfo2; ILMethod *methodRef; ILType *objType; /* Check for safe and unsafe pointer assignments */ if(item->engineType == ILEngineType_I) { methodRef = MethodRefToMethod(item->typeInfo); if(methodRef) { /* Assigning a method reference, obtained via "ldftn" or "ldvirtftn", to a method pointer destination */ if(ILTypeIdentical(ILMethod_Signature(methodRef), type)) { return 1; } } else if(item->typeInfo != 0 && ILType_IsComplex(item->typeInfo)) { /* May be trying to assign a method pointer to a method type */ if(ILType_IsMethod(item->typeInfo)) { if(ILTypeIdentical(item->typeInfo, type)) { return 1; } } } if(unsafeAllowed) { if(type != 0 && ILType_IsComplex(type)) { if((ILType_Kind(type) & IL_TYPE_COMPLEX_METHOD) != 0 || ILType_Kind(type) == IL_TYPE_COMPLEX_PTR) { return 1; } } } } /* Check for regular assignments */ if(item->engineType == ILEngineType_I4 || item->engineType == ILEngineType_I) { type = ILTypeGetEnumType(type); switch((unsigned long)type) { case (unsigned long)ILType_Boolean: case (unsigned long)ILType_Int8: case (unsigned long)ILType_UInt8: case (unsigned long)ILType_Int16: case (unsigned long)ILType_UInt16: case (unsigned long)ILType_Char: case (unsigned long)ILType_Int32: case (unsigned long)ILType_UInt32: case (unsigned long)ILType_Int: case (unsigned long)ILType_UInt: return 1; default: break; } if(!unsafeAllowed) { return 0; } /* Allow a native int to be assigned to a complex type */ if(type != 0 && ILType_IsComplex(type) && item->engineType == ILEngineType_I) { if(ILType_Kind(type) == IL_TYPE_COMPLEX_PTR || ILType_Kind(type) == IL_TYPE_COMPLEX_BYREF) { return 1; } } return 0; } else if(item->engineType == ILEngineType_I8) { type = ILTypeGetEnumType(type); return (type == ILType_Int64 || type == ILType_UInt64); } else if(item->engineType == ILEngineType_F) { return (type == ILType_Float32 || type == ILType_Float64 || type == ILType_Float); } else if(item->engineType == ILEngineType_O) { if(!(item->typeInfo)) { /* A "null" constant was pushed, which is compatible with any object reference type */ return IsObjectRef(type); } if(!IsObjectRef(type) || !IsObjectRef(item->typeInfo)) { /* Both types must be object references */ return 0; } /* make a copy to avoid unecessary complications */ objType=item->typeInfo; if(ILType_IsArray(type) && ILType_IsArray(objType) && (ILTypeGetRank(type) == ILTypeGetRank(objType))) { objType=ILTypeGetElemType(objType); type=ILTypeGetElemType(type); } image = ILProgramItem_Image(method); classInfo = ILClassResolve(ILClassFromType(image, 0, type, 0)); classInfo2 = ILClassResolve (ILClassFromType(image, 0, objType, 0)); if(classInfo && classInfo2) { /* Is the type a regular class or an interface? */ if(!ILClass_IsInterface(classInfo)) { /* Regular class: the value must inherit from the type */ if(ILClassInheritsFrom(classInfo2, classInfo)) { return 1; } /* If "classInfo2" is an interface, then the conversion is OK if "type" is "System.Object", because all interfaces inherit from "System.Object", even though the metadata doesn't explicitly say so */ if(ILClass_IsInterface(classInfo2)) { return ILTypeIsObjectClass(type); } /* The conversion is not OK */ return 0; } else { /* Interface which the value must implement or inherit from */ return ILClassImplements(classInfo2, classInfo) || ILClassInheritsFrom(classInfo2, classInfo); } } else { return 0; } } else if(item->engineType == ILEngineType_MV) { /* Can only assign managed values to an exact type destination */ return ILTypeIdentical(item->typeInfo, type); } else if(item->engineType == ILEngineType_TypedRef) { /* The type must be "typedref" */ return (type == ILType_TypedRef); } else if(item->engineType == ILEngineType_M || item->engineType == ILEngineType_T) { /* Cannot assign managed pointers to variables or fields, unless we are in "unsafe" mode */ if(!unsafeAllowed) { return 0; } /* Allow an assignment to any pointer, reference, or native destination, regardless of type. This allows C/C++ code to arbitrarily cast pointers via assignment */ if(type != 0 && ILType_IsComplex(type)) { if(ILType_Kind(type) == IL_TYPE_COMPLEX_PTR || ILType_Kind(type) == IL_TYPE_COMPLEX_BYREF || (ILType_Kind(type) & IL_TYPE_COMPLEX_METHOD) != 0) { return 1; } } else if(type == ILType_Int || type == ILType_UInt) { return 1; } return 0; } else { /* Invalid type: never assignment-compatible with anything */ return 0; } }
/* * Expand the instantiations in a class. Returns zero if out of memory. */ static int ExpandInstantiations(ILImage *image, ILClass *classInfo, ILType *classType, ILType *classParams) { ILClass *origClass; ILMember *member; ILMethod *newMethod; ILField *newField; ILEvent *newEvent; ILType *signature; ILImplements *impl; ILClass *tempInfo; /* Bail out if not a "with" type, since the instantiation would have already been taken care of by "ILClassFromType" */ if(!ILType_IsWith(classType)) { return 1; } /* Find the original class underlying the type */ origClass = ILClassFromType(image, 0, ILTypeGetWithMain(classType), 0); if(!origClass) { return 0; } origClass = ILClassResolve(origClass); /* Copy across the class attributes */ ILClassSetAttrs(classInfo, ~((ILUInt32)0), ILClass_Attrs(origClass)); /* Mark this class as being expanded, to deal with circularities */ classInfo->attributes |= IL_META_TYPEDEF_CLASS_EXPANDED; /* Expand the parent class and interfaces */ if(origClass->parent) { ILClass *parentClass; parentClass = ILClassExpand (image, ILClass_ParentClass(origClass), classParams, 0); if(!parentClass) { classInfo->parent = 0; return 0; } classInfo->parent = ILToProgramItem(parentClass); } impl = _ILClass_Implements(origClass); while(impl) { tempInfo = ILImplements_InterfaceClass(impl); tempInfo = ILClassExpand(image, tempInfo, classParams, 0); if(!tempInfo) { return 0; } if(!ILClassAddImplements(classInfo, ILToProgramItem(tempInfo), 0)) { return 0; } impl = _ILImplements_NextImplements(impl); } /* Expand the methods and fields */ member = 0; while((member = ILClassNextMember(origClass, member)) != 0) { switch(ILMemberGetKind(member)) { case IL_META_MEMBERKIND_METHOD: { newMethod = ILMethodCreateInstance(image, (ILMethod *)member, classInfo, classParams, 0); if(!newMethod) { return 0; } } break; case IL_META_MEMBERKIND_FIELD: { /* Create a new field */ newField = (ILField *)ILMemberCreateInstance(member, classInfo); if(!newField) { return 0; } /* Copy the original field's properties */ signature = ILTypeInstantiate(image->context, ILMember_Signature(member), classParams, 0); if(!signature) { return 0; } else { ILMemberSetSignature((ILMember *)newField, signature); } } break; case IL_META_MEMBERKIND_EVENT: { /* Create a new event */ newEvent = (ILEvent *)ILMemberCreateInstance(member, classInfo); if(!newEvent) { return 0; } /* Copy the original field's properties */ signature = ILTypeInstantiate(image->context, ILMember_Signature(member), classParams, 0); if(!signature) { return 0; } else { ILMemberSetSignature((ILMember *)newEvent, signature); } } break; case IL_META_MEMBERKIND_PROPERTY: { /* TODO */ } break; case IL_META_MEMBERKIND_OVERRIDE: { /* TODO */ } break; case IL_META_MEMBERKIND_PINVOKE: { /* TODO */ } break; } } /* Done */ return 1; }