ILClass *ILClassInstantiate(ILImage *image, ILType *classType, ILType *classArgs, ILType *methodArgs) { ILClass *classInfo; ILType *type; /* Bail out early if the type does not need instantiation */ if(!ILType_IsWith(classType) && !ILTypeNeedsInstantiation(classType)) { return ILClassFromType(image, 0, classType, 0); } /* Search for a synthetic type that matches the expanded form of the class type, in case we already instantiated this class previously. We do this in such a way that we won't need to call "ILTypeInstantiate" unless necessary */ classInfo = _ILTypeToSyntheticInstantiation(image, classType, classArgs, methodArgs); if(classInfo) { if((classInfo->attributes & IL_META_TYPEDEF_CLASS_EXPANDED) == 0) { classArgs = ILClassToType(classInfo); if(!ExpandInstantiations(image, classInfo, classType, classArgs)) { return 0; } } return classInfo; } /* Instantiate the class type */ type = ILTypeInstantiate(image->context, classType, classArgs, methodArgs); if(!type) { return 0; } /* Create a synthetic type for the expanded form */ classInfo = ILClassFromType(image, 0, type, 0); if(!classInfo) { return 0; } if(!ExpandInstantiations(image, classInfo, type, type)) { return 0; } return classInfo; }
/* * Determine if a type is a sub-class of a specific class. */ static int IsSubClass(ILType *type, ILClass *classInfo) { ILClass *typeClass; if(type == 0) { /* The type is "null", which is always a sub-class */ return 1; } else if(ILType_IsClass(type) || ILType_IsValueType(type)) { typeClass = ILType_ToClass(type); if(ILClassInheritsFrom(typeClass, classInfo) || ILClassImplements(typeClass, classInfo)) { return 1; } return 0; } else if((typeClass = ILClassFromType(ILClassToImage(classInfo), 0, type, 0)) != 0) { if(ILClassInheritsFrom(typeClass, classInfo) || ILClassImplements(typeClass, classInfo)) { return 1; } return 0; } else { return 0; } }
ILClass *ILClassGetUnderlying(ILClass *info) { ILType *synType = info->synthetic; if(ILType_IsWith(synType) && !ILClassIsExpanded(info)) { synType = ILTypeGetWithMain(synType); return ILClassFromType(info->programItem.image, 0, synType, 0); } else { return info; } }
/* * 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; }
ILProgramItem *ILProgramItemFromType(ILImage *image, ILType *type) { if(!type) { return 0; } if(ILType_IsComplex(type)) { switch(ILType_Kind(type)) { case IL_TYPE_COMPLEX_WITH: case IL_TYPE_COMPLEX_ARRAY: case IL_TYPE_COMPLEX_ARRAY_CONTINUE: case IL_TYPE_COMPLEX_PTR: case IL_TYPE_COMPLEX_METHOD: case (IL_TYPE_COMPLEX_METHOD | IL_TYPE_COMPLEX_METHOD_SENTINEL): { ILTypeSpec *spec; spec = ILTypeSpecCreate(image, 0, type); return ILToProgramItem(spec); } } } else { ILClass *info; info = ILClassFromType(image, 0, type, 0); if(info) { info = ILClassImport(image, info); } return ILToProgramItem(info); } return 0; }
/* * Find the nearest type in the type2 heirarchy that is assign * compatible to type1. */ static ILType* TryCommonType(ILImage* image, ILType * type1, ILType *type2) { ILClass *classInfo; if(type1==NULL) return type2; if(type2==NULL) return type1; /* Note: boxing conversions are not allowed because both * types have to be reference types. */ if(ILTypeAssignCompatibleNonBoxing(image, type1,type2)) { return type2; } classInfo=ILClassFromType(image, 0, type2, 0); if((classInfo = ILClass_ParentClass(classInfo)) != NULL) { return TryCommonType(image, type1, ILClassToType(classInfo)); } return type2; }
/* * 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; }