示例#1
0
tCLIFile* CLIFile_Load(char *pFileName) {
	void *pRawFile;
	tCLIFile *pRet;
	tFilesLoaded *pNewFile;

	pRawFile = LoadFileFromDisk(pFileName);

	if (pRawFile == NULL) {
		Crash("Cannot load file: %s", pFileName);
	}

	log_f(1, "\n\n\nLoading file: %s\n", pFileName);

	pRet = LoadPEFile(pRawFile);
	pRet->pFileName = (char*)mallocForever((U32)strlen(pFileName) + 1);
	strcpy(pRet->pFileName, pFileName);

	// Record that we've loaded this file
	pNewFile = TMALLOCFOREVER(tFilesLoaded);
	pNewFile->pCLIFile = pRet;
	pNewFile->pNext = pFilesLoaded;
	pFilesLoaded = pNewFile;

	return pRet;
}
示例#2
0
void Type_Init() {
	U32 i;

	// Build all the types needed by the interpreter.
	numInitTypes = sizeof(typeInit) / sizeof(typeInit[0]);
	types = (tMD_TypeDef**)mallocForever(numInitTypes * sizeof(tMD_TypeDef*));
	for (i=0; i<numInitTypes; i++) {
		if (typeInit[i].assemblyName != NULL) {
			// Normal type initialisation
			types[i] = MetaData_GetTypeDefFromFullName(typeInit[i].assemblyName, typeInit[i].nameSpace, typeInit[i].name);
			// For the pre-defined system types, fill in the well-known memory sizes
			types[i]->stackType = typeInit[i].stackType;
			types[i]->stackSize = typeInit[i].stackSize;
			types[i]->arrayElementSize = typeInit[i].arrayElementSize;
			types[i]->instanceMemSize = typeInit[i].instanceMemSize;
		}
	}
	for (i=0; i<numInitTypes; i++) {
		if (typeInit[i].assemblyName != NULL) {
			MetaData_Fill_TypeDef(types[i], NULL, NULL);
		} else {
			// Special initialisation for arrays of particular types.
			types[i] = Type_GetArrayTypeDef(types[(U32)(typeInit[i].name)], NULL, NULL);
		}
	}
	CorLibDone = 1;
}
示例#3
0
文件: Generics.c 项目: Astaelan/SEMOS
tMD_MethodDef* Generics_GetMethodDefFromCoreMethod
	(tMD_MethodDef *pCoreMethod, tMD_TypeDef *pParentType, U32 numTypeArgs, tMD_TypeDef **ppTypeArgs) {

	tGenericMethodInstance *pInst;
	tMD_MethodDef *pMethod;

	// See if we already have an instance with the given type args
	pInst = pCoreMethod->pGenericMethodInstances;
	while (pInst != NULL) {
		if (pInst->numTypeArgs == numTypeArgs &&
			memcmp(pInst->pTypeArgs, ppTypeArgs, numTypeArgs * sizeof(tMD_TypeDef*)) == 0) {
			return pInst->pInstanceMethodDef;
		}
		pInst = pInst->pNext;
	}

	// We don't have an instance so create one now.
	pInst = mallocForever(sizeof(tGenericMethodInstance) + numTypeArgs * sizeof(tMD_TypeDef*));
	pInst->pNext = pCoreMethod->pGenericMethodInstances;
	pCoreMethod->pGenericMethodInstances = pInst;
	pInst->numTypeArgs = numTypeArgs;
	memcpy(pInst->pTypeArgs, ppTypeArgs, numTypeArgs * sizeof(tMD_TypeDef*));

	pInst->pInstanceMethodDef = pMethod = TMALLOCFOREVER(tMD_MethodDef);
	memset(pMethod, 0, sizeof(tMD_MethodDef));
	pMethod->pMethodDef = pMethod;
	pMethod->pMetaData = pCoreMethod->pMetaData;
	pMethod->pCIL = pCoreMethod->pCIL;
	pMethod->implFlags = pCoreMethod->implFlags;
	pMethod->flags = pCoreMethod->flags;
	pMethod->name = pCoreMethod->name;
	pMethod->signature = pCoreMethod->signature;
	pMethod->vTableOfs = pCoreMethod->vTableOfs;
	pMethod->ppMethodTypeArgs = pInst->pTypeArgs;

	MetaData_Fill_MethodDef(pParentType, pMethod, pParentType->ppClassTypeArgs, pInst->pTypeArgs);

	return pMethod;
}
示例#4
0
static void* LoadFileFromDisk(char *pFileName) {
	int f;
	void *pData = NULL;

	f = open(pFileName, O_RDONLY|O_BINARY);
	if (f >= 0) {
		int len;
		len = lseek(f, 0, SEEK_END);
		lseek(f, 0, SEEK_SET);
		// TODO: Change to use mmap() or windows equivilent
		pData = mallocForever(len);
		if (pData != NULL) {
			int r = read(f, pData, len);
			if (r != len) {
				free(pData);
				pData = NULL;
			}
		}
		close(f);
	}

	return pData;
}
示例#5
0
void MetaData_Fill_TypeDef_(tMD_TypeDef *pTypeDef, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) 
{
	IDX_TABLE firstIdx, lastIdx, token;
	U32 instanceMemSize, staticMemSize, virtualOfs, i, j;
	tMetaData *pMetaData;
	tMD_TypeDef *pParent;

	pMetaData = pTypeDef->pMetaData;
	pTypeDef->isFilled = 1;
	pTypeDef->pTypeDef = pTypeDef;

	pTypeDef->pParent = MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, pTypeDef->extends, ppClassTypeArgs, ppMethodTypeArgs);
	pParent = pTypeDef->pParent;

	if (pParent != NULL) 
	{
		MetaData_Fill_TypeDef(pParent, NULL, NULL);
		virtualOfs = pParent->numVirtualMethods;
	} 
	else 
	{
		virtualOfs = 0;
	}
	pTypeDef->isValueType = (U8)Type_IsValueType(pTypeDef);

	// If not primed, then work out how many methods & fields there are.
	if (!pTypeDef->isPrimed)
	{
		// Methods
		lastIdx = (pTypeDef->isLast)?
			MAKE_TABLE_INDEX(MD_TABLE_METHODDEF, pTypeDef->pMetaData->tables.numRows[MD_TABLE_METHODDEF]):
			(pTypeDef[1].methodList - 1);
		pTypeDef->numMethods = lastIdx - pTypeDef->methodList + 1;
		// Fields
		lastIdx = (pTypeDef->isLast)?
			MAKE_TABLE_INDEX(MD_TABLE_FIELDDEF, pTypeDef->pMetaData->tables.numRows[MD_TABLE_FIELDDEF]):
			(pTypeDef[1].fieldList - 1);
		pTypeDef->numFields = lastIdx - pTypeDef->fieldList + 1;
	}

	// Must create the virtual method table BEFORE any other type resolution is done
	// Note that this must not do ANY filling of types or methods.
	// This is to ensure that the parent object(s) in any type inheritance hierachy are allocated
	// their virtual method offset before derived types.
	firstIdx = pTypeDef->methodList;
	lastIdx = firstIdx + pTypeDef->numMethods - 1;
	// This only needs to be done for non-generic types, or for generic types that are not a definition
	// I.e. Fully instantiated generic types
	if (!pTypeDef->isGenericDefinition) 
	{
		for (token = firstIdx; token <= lastIdx; token++)
		{
			tMD_MethodDef *pMethodDef;

			pMethodDef = MetaData_GetMethodDefFromDefRefOrSpec(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs);

			// This is needed, so array resolution can work correctly and FindVirtualOverriddenMethod() can work.
			pMethodDef->pParentType = pTypeDef;

			if (METHOD_ISVIRTUAL(pMethodDef))
			{
				if (METHOD_ISNEWSLOT(pMethodDef) || pTypeDef->pParent == NULL) 
				{
					// Allocate a new vTable slot if method is explicitly marked as NewSlot, or
					// this is of type Object.
					pMethodDef->vTableOfs = virtualOfs++;
				} 
				else 
				{
					tMD_MethodDef *pVirtualOveriddenMethod;

					pVirtualOveriddenMethod = FindVirtualOverriddenMethod(pTypeDef->pParent, pMethodDef);
					Assert(pVirtualOveriddenMethod != NULL);
					pMethodDef->vTableOfs = pVirtualOveriddenMethod->vTableOfs;
				}
			} 
			else 
			{
				// Dummy value - make it obvious it's not valid!
				pMethodDef->vTableOfs = 0xffffffff;
			}

		}
		// Create the virtual method table
		pTypeDef->numVirtualMethods = virtualOfs;

		// Resolve fields, members, interfaces.
		// Only needs to be done if it's not a generic definition type

		// It it's not a value-type and the stack-size is not preset, then set it up now.
		// It needs to be done here as non-static fields in non-value types can point to the containing type
		if (pTypeDef->stackSize == 0 && !pTypeDef->isValueType)
		{
			pTypeDef->stackType = EVALSTACK_O;
			pTypeDef->stackSize = sizeof(void*);
		}
		// Resolve all fields - instance ONLY at this point,
		// because static fields in value-types can be of the containing type, and the size is not yet known.
		firstIdx = pTypeDef->fieldList;
		lastIdx = firstIdx + pTypeDef->numFields - 1;
		staticMemSize = 0;
		if (pTypeDef->numFields > 0) 
		{
			pTypeDef->ppFields = mallocForever(pTypeDef->numFields * sizeof(tMD_FieldDef*));
		}
		instanceMemSize = (pTypeDef->pParent == NULL)?0:pTypeDef->pParent->instanceMemSize;
		for (token = firstIdx, i=0; token <= lastIdx; token++, i++) 
		{
			tMD_FieldDef *pFieldDef;

			pFieldDef = MetaData_GetFieldDefFromDefOrRef(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs);
			if (!FIELD_ISSTATIC(pFieldDef))
			{
				// Only handle non-static fields at the moment
				if (pTypeDef->pGenericDefinition != NULL)
				{
					// If this is a generic instantiation type, then all field defs need to be copied,
					// as there will be lots of different instantiations.
					tMD_FieldDef *pFieldCopy = TMALLOCFOREVER(tMD_FieldDef);
					memcpy(pFieldCopy, pFieldDef, sizeof(tMD_FieldDef));
					pFieldDef = pFieldCopy;
				}
				if (FIELD_ISLITERAL(pFieldDef) || FIELD_HASFIELDRVA(pFieldDef))
				{
					// If it's a literal, then analyse the field, but don't include it in any memory allocation
					// If is has an RVA, then analyse the field, but don't include it in any memory allocation
					MetaData_Fill_FieldDef(pTypeDef, pFieldDef, 0, ppClassTypeArgs);
				}
				else 
				{
					MetaData_Fill_FieldDef(pTypeDef, pFieldDef, instanceMemSize, ppClassTypeArgs);
					instanceMemSize += pFieldDef->memSize;
				}
				pTypeDef->ppFields[i] = pFieldDef;
			}
		}
		if (pTypeDef->instanceMemSize == 0)
		{
			pTypeDef->instanceMemSize = instanceMemSize;
		}

		// Sort out stack type and size.
		// Note that this may already be set, as some basic types have this preset;
		// or if it's not a value-type it'll already be set
		if (pTypeDef->stackSize == 0) 
		{
			// if it gets here then it must be a value type
			pTypeDef->stackType = EVALSTACK_VALUETYPE;
			pTypeDef->stackSize = pTypeDef->instanceMemSize;
		}
		// Sort out array element size. Note that some basic types will have this preset.
		if (pTypeDef->arrayElementSize == 0) 
		{
			pTypeDef->arrayElementSize = pTypeDef->stackSize;
		}

		// Handle static fields
		for (token = firstIdx, i=0; token <= lastIdx; token++, i++)
		{
			tMD_FieldDef *pFieldDef;

			pFieldDef = MetaData_GetFieldDefFromDefOrRef(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs);
			if (FIELD_ISSTATIC(pFieldDef))
			{
				// Only handle static fields here
				if (pTypeDef->pGenericDefinition != NULL)
				{
					// If this is a generic instantiation type, then all field defs need to be copied,
					// as there will be lots of different instantiations.
					tMD_FieldDef *pFieldCopy = TMALLOCFOREVER(tMD_FieldDef);
					memcpy(pFieldCopy, pFieldDef, sizeof(tMD_FieldDef));
					pFieldDef = pFieldCopy;
				}
				if (FIELD_ISLITERAL(pFieldDef) || FIELD_HASFIELDRVA(pFieldDef))
				{
					// If it's a literal, then analyse the field, but don't include it in any memory allocation
					// If is has an RVA, then analyse the field, but don't include it in any memory allocation
					MetaData_Fill_FieldDef(pTypeDef, pFieldDef, 0, ppClassTypeArgs);
				} 
				else
				{
					MetaData_Fill_FieldDef(pTypeDef, pFieldDef, staticMemSize, ppClassTypeArgs);
					staticMemSize += pFieldDef->memSize;
				}
				pTypeDef->ppFields[i] = pFieldDef;
			}
		}
		if (staticMemSize > 0) {
			pTypeDef->pStaticFields = mallocForever(staticMemSize);
			memset(pTypeDef->pStaticFields, 0, staticMemSize);
			// Set the field addresses (->pMemory) of all static fields
			for (i = 0; i<pTypeDef->numFields; i++) {
				tMD_FieldDef *pFieldDef;

				pFieldDef = pTypeDef->ppFields[i];
				if (FIELD_ISSTATIC(pFieldDef) && pFieldDef->pMemory == NULL) {
					// Only set it if it isn't already set. It will be already set if this field has an RVA
					pFieldDef->pMemory = pTypeDef->pStaticFields + pFieldDef->memOffset;
				}
			}
			pTypeDef->staticFieldSize = staticMemSize;
		}

		// Resolve all members
		firstIdx = pTypeDef->methodList;
		lastIdx = firstIdx + pTypeDef->numMethods - 1;
		pTypeDef->ppMethods = mallocForever(pTypeDef->numMethods * sizeof(tMD_MethodDef*));
		pTypeDef->pVTable = mallocForever(pTypeDef->numVirtualMethods * sizeof(tMD_MethodDef*));
		// Copy initial vTable from parent
		if (pTypeDef->pParent != NULL) {
			memcpy(pTypeDef->pVTable, pTypeDef->pParent->pVTable, pTypeDef->pParent->numVirtualMethods * sizeof(tMD_MethodDef*));
		}
		for (token = firstIdx, i = 0; token <= lastIdx; token++, i++) {
			tMD_MethodDef *pMethodDef;

			pMethodDef = MetaData_GetMethodDefFromDefRefOrSpec(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs);
			if (pTypeDef->pGenericDefinition != NULL) {
				// If this is a generic instantiation type, then all method defs need to be copied,
				// as there will be lots of different instantiations.
				tMD_MethodDef *pMethodCopy = TMALLOCFOREVER(tMD_MethodDef);
				memcpy(pMethodCopy, pMethodDef, sizeof(tMD_MethodDef));
				pMethodDef = pMethodCopy;
			}
			if (METHOD_ISSTATIC(pMethodDef) && strcmp(pMethodDef->name, ".cctor") == 0) {
				// This is a static constructor
				pTypeDef->pStaticConstructor = pMethodDef;
			}
			if (!METHOD_ISSTATIC(pMethodDef) && pTypeDef->pParent != NULL &&
				strcmp(pMethodDef->name, "Finalize") == 0) {
				// This is a Finalizer method, but not for Object.
				// Delibrately miss out Object's Finalizer because it's empty and will cause every object
				// of any type to have a Finalizer which will be terrible for performance.
				pTypeDef->pFinalizer = pMethodDef;
			}
			if (METHOD_ISVIRTUAL(pMethodDef)) {
				// This is a virtual method, so enter it in the vTable
				pTypeDef->pVTable[pMethodDef->vTableOfs] = pMethodDef;
			}
			pTypeDef->ppMethods[i] = pMethodDef;
		}
		// Find inherited Finalizer, if this type doesn't have an explicit Finalizer, and if there is one
		if (pTypeDef->pFinalizer == NULL) {
			tMD_TypeDef *pInheritedType = pTypeDef->pParent;
			while (pInheritedType != NULL) {
				if (pInheritedType->pFinalizer != NULL) {
					pTypeDef->pFinalizer = pInheritedType->pFinalizer;
					break;
				}
				pInheritedType = pInheritedType->pParent;
			}
		}
		// Fill all method definitions for this type
		for (i=0; i<pTypeDef->numMethods; i++) {
			MetaData_Fill_MethodDef(pTypeDef, pTypeDef->ppMethods[i], ppClassTypeArgs, ppMethodTypeArgs);
		}

		// Map all interface method calls. This only needs to be done for Classes, not Interfaces
		// And is not done for generic definitions.
		if (!TYPE_ISINTERFACE(pTypeDef)) {
			firstIdx = 0;
			if (pTypeDef->pParent != NULL) {
				j = pTypeDef->numInterfaces = pTypeDef->pParent->numInterfaces;
			} else {
				j = 0;
			}
			// TODO: Better to do this once during file load (the bit in this for loop)
			for (i=1; i<=pMetaData->tables.numRows[MD_TABLE_INTERFACEIMPL]; i++) {
				tMD_InterfaceImpl *pInterfaceImpl;

				pInterfaceImpl = (tMD_InterfaceImpl*)MetaData_GetTableRow(pMetaData, MAKE_TABLE_INDEX(MD_TABLE_INTERFACEIMPL, i));
				if (pInterfaceImpl->class_ == pTypeDef->tableIndex) {
					// count how many interfaces are implemented
					pTypeDef->numInterfaces++;
					if (firstIdx == 0) {
						firstIdx = MAKE_TABLE_INDEX(MD_TABLE_INTERFACEIMPL, i);
					}
					lastIdx = MAKE_TABLE_INDEX(MD_TABLE_INTERFACEIMPL, i);
				}
			}
			if (pTypeDef->numInterfaces > 0 && !pTypeDef->isGenericDefinition) {
				U32 mapNum;

				pTypeDef->pInterfaceMaps = (tInterfaceMap*)mallocForever(pTypeDef->numInterfaces * sizeof(tInterfaceMap));
				// Copy interface maps from parent type
				if (j > 0) {
					memcpy(pTypeDef->pInterfaceMaps, pTypeDef->pParent->pInterfaceMaps, j * sizeof(tInterfaceMap));
				}
				mapNum = j;
				if (firstIdx > 0) {
					for (token=firstIdx; token<=lastIdx; token++, mapNum++) {
						tMD_InterfaceImpl *pInterfaceImpl;

						pInterfaceImpl = (tMD_InterfaceImpl*)MetaData_GetTableRow(pMetaData, token);
						if (pInterfaceImpl->class_ == pTypeDef->tableIndex) {
							tMD_TypeDef *pInterface;
							tInterfaceMap *pMap;

							// Get the interface that this type implements
							pInterface = MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, pInterfaceImpl->interface_, ppClassTypeArgs, ppMethodTypeArgs);
							MetaData_Fill_TypeDef(pInterface, NULL, NULL);
							pMap = &pTypeDef->pInterfaceMaps[mapNum];
							pMap->pInterface = pInterface;
							pMap->pVTableLookup = (U32*)mallocForever(pInterface->numVirtualMethods * sizeof(U32));
							pMap->ppMethodVLookup = NULL;
							// Discover interface mapping for each interface method
							for (i=0; i<pInterface->numVirtualMethods; i++) {
								tMD_MethodDef *pInterfaceMethod, *pOverriddenMethod;

								pInterfaceMethod = pInterface->pVTable[i];
								pOverriddenMethod = FindVirtualOverriddenMethod(pTypeDef, pInterfaceMethod);
								Assert(pOverriddenMethod != NULL);
								pMap->pVTableLookup[i] = pOverriddenMethod->vTableOfs;
							}
						} else {
							Crash("Problem with interface class");
						}
					}
				}
			}
		}

		// If this is an enum type, then pretend its stack type is its underlying type
		if (pTypeDef->pParent == types[TYPE_SYSTEM_ENUM]) {
			pTypeDef->stackType = EVALSTACK_INT32;
		}
	}

	// If this is a nested type, then find the namespace of it
	if (pTypeDef->pNestedIn != NULL) {
		tMD_TypeDef *pRootTypeDef = pTypeDef->pNestedIn;
		while (pRootTypeDef->pNestedIn != NULL) {
			pRootTypeDef = pRootTypeDef->pNestedIn;
		}
		pTypeDef->nameSpace = pRootTypeDef->nameSpace;
	}

	log_f(2, "Type:  %s.%s\n", pTypeDef->nameSpace, pTypeDef->name);
}
示例#6
0
文件: Generics.c 项目: Astaelan/SEMOS
tMD_TypeDef* Generics_GetGenericTypeFromCoreType(tMD_TypeDef *pCoreType, U32 numTypeArgs, tMD_TypeDef **ppTypeArgs) {
	tGenericInstance *pInst;
	tMD_TypeDef *pTypeDef;
	U32 i;
	unsigned char name[2048];
	tMetaData *pMetaData;

	pMetaData = pCoreType->pMetaData;
	MetaData_Fill_TypeDef(pCoreType, NULL, NULL);

	// See if we have already built an instantiation of this type with the given type args.
	pInst = pCoreType->pGenericInstances;
	while (pInst != NULL) {
		if (pInst->numTypeArgs == numTypeArgs &&
			memcmp(pInst->pTypeArgs, ppTypeArgs, numTypeArgs * sizeof(tMD_TypeDef*)) == 0) {
			return pInst->pInstanceTypeDef;
		}
		pInst = pInst->pNext;
	}

	// This has not already been instantiated, so instantiate it now.
	pInst = (tGenericInstance*)mallocForever(sizeof(tGenericInstance) + numTypeArgs * sizeof(tMD_TypeDef*));
	// Insert this into the chain of instantiations.
	pInst->pNext = pCoreType->pGenericInstances;
	pCoreType->pGenericInstances = pInst;
	// Copy the type args into the instantiation.
	pInst->numTypeArgs = numTypeArgs;
	memcpy(pInst->pTypeArgs, ppTypeArgs, numTypeArgs * sizeof(tMD_TypeDef*));

	// Create the new instantiated type
	pInst->pInstanceTypeDef = pTypeDef = TMALLOCFOREVER(tMD_TypeDef);
	memset(pTypeDef, 0, sizeof(tMD_TypeDef));
	// Make the name of the instantiation.
	strcpy(name, pCoreType->name);
	strcat(name, "[");
	for (i=0; i<numTypeArgs; i++) {
		if (i > 0) {
			strcat(name, ",");
		}
		if (ppTypeArgs[i] != NULL) {
			sprintf(strchr(name, 0), "%s.%s", ppTypeArgs[i]->nameSpace, ppTypeArgs[i]->name);
		} else {
			tMD_GenericParam *pGenericParam = FindGenericParam(pCoreType, i);
			if (pGenericParam != NULL) {
				sprintf(strchr(name, 0), pGenericParam->name);
			} else {
				sprintf(strchr(name, 0), "???");
			}
		}
	}
	strcat(name, "]");
	// Fill in the basic bits of the new type def.
	pTypeDef->pTypeDef = pTypeDef;
	pTypeDef->pMetaData = pMetaData;
	pTypeDef->flags = pCoreType->flags;
	pTypeDef->pGenericDefinition = pCoreType;
	for (i=0; i<numTypeArgs; i++) {
		if (ppTypeArgs[i] == NULL) {
			pTypeDef->isGenericDefinition = 1;
			break;
		}
	}
	pTypeDef->nameSpace = pCoreType->nameSpace;
	pTypeDef->name = (STRING)mallocForever((U32)strlen(name)+1);
	strcpy(pTypeDef->name, name);
	pTypeDef->ppClassTypeArgs = pInst->pTypeArgs;
	pTypeDef->extends = pCoreType->extends;
	pTypeDef->tableIndex = pCoreType->tableIndex;
	pTypeDef->fieldList = pCoreType->fieldList;
	pTypeDef->methodList = pCoreType->methodList;
	pTypeDef->numFields = pCoreType->numFields;
	pTypeDef->numMethods = pCoreType->numMethods;
	pTypeDef->numVirtualMethods = pCoreType->numVirtualMethods;
	pTypeDef->pNestedIn = pCoreType->pNestedIn;
	pTypeDef->isPrimed = 1;

	MetaData_Fill_TypeDef_(pTypeDef, ppTypeArgs, NULL);

	return pTypeDef;
}
示例#7
0
static void CreateNewArrayType(tMD_TypeDef *pNewArrayType, tMD_TypeDef *pElementType, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) {
	MetaData_Fill_TypeDef(types[TYPE_SYSTEM_ARRAY_NO_TYPE], NULL, NULL);

	memcpy(pNewArrayType, types[TYPE_SYSTEM_ARRAY_NO_TYPE], sizeof(tMD_TypeDef));
	pNewArrayType->pArrayElementType = pElementType;
	pNewArrayType->isFilled = 1;

	// Auto-generate the generic interfaces IEnumerable<T>, ICollection<T> and IList<T> for this array
	{
		tInterfaceMap *pInterfaceMap, *pAllIMs;
		tMD_TypeDef *pInterfaceT;
		tMD_MethodDef *pMethod;
		U32 orgNumInterfaces;

		if (genericArrayMethodsInited == 0) {
			GetMethodDefs();
		}

		orgNumInterfaces = pNewArrayType->numInterfaces;
		pNewArrayType->numInterfaces += 3;
		pAllIMs = (tInterfaceMap*)mallocForever(pNewArrayType->numInterfaces * sizeof(tInterfaceMap));
		memcpy(pAllIMs, pNewArrayType->pInterfaceMaps, orgNumInterfaces * sizeof(tInterfaceMap));
		pNewArrayType->pInterfaceMaps = pAllIMs;

		// Get the IEnumerable<T> interface
		pInterfaceMap = &pAllIMs[orgNumInterfaces + 0];
		pInterfaceT = Generics_GetGenericTypeFromCoreType(types[TYPE_SYSTEM_COLLECTIONS_GENERIC_IENUMERABLE_T], 1, &pElementType);
		pInterfaceMap->pInterface = pInterfaceT;
		pInterfaceMap->pVTableLookup = NULL;
		pInterfaceMap->ppMethodVLookup = mallocForever(pInterfaceT->numVirtualMethods * sizeof(tMD_MethodDef*));
		pMethod = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GetGenericEnumerator], pNewArrayType, 1, &pElementType);
		pInterfaceMap->ppMethodVLookup[0] = pMethod;

		// Get the ICollection<T> interface
		pInterfaceMap = &pAllIMs[orgNumInterfaces + 1];
		pInterfaceT = Generics_GetGenericTypeFromCoreType(types[TYPE_SYSTEM_COLLECTIONS_GENERIC_ICOLLECTION_T], 1, &pElementType);
		pInterfaceMap->pInterface = pInterfaceT;
		pInterfaceMap->pVTableLookup = NULL;
		pInterfaceMap->ppMethodVLookup = mallocForever(pInterfaceT->numVirtualMethods * sizeof(tMD_MethodDef*));
		pInterfaceMap->ppMethodVLookup[0] = ppGenericArrayMethods[GENERICARRAYMETHODS_get_Length];
		pInterfaceMap->ppMethodVLookup[1] = ppGenericArrayMethods[GENERICARRAYMETHODS_get_IsReadOnly];
		pInterfaceMap->ppMethodVLookup[2] = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericAdd], pNewArrayType, 1, &pElementType);
		pInterfaceMap->ppMethodVLookup[3] = ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericClear];
		pInterfaceMap->ppMethodVLookup[4] = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericContains], pNewArrayType, 1, &pElementType);
		pInterfaceMap->ppMethodVLookup[5] = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericCopyTo], pNewArrayType, 1, &pElementType);
		pInterfaceMap->ppMethodVLookup[6] = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericRemove], pNewArrayType, 1, &pElementType);

		// Get the IList<T> interface
		pInterfaceMap = &pAllIMs[orgNumInterfaces + 2];
		pInterfaceT = Generics_GetGenericTypeFromCoreType(types[TYPE_SYSTEM_COLLECTIONS_GENERIC_ILIST_T], 1, &pElementType); //, ppClassTypeArgs, ppMethodTypeArgs);
		pInterfaceMap->pInterface = pInterfaceT;
		pInterfaceMap->pVTableLookup = NULL;
		pInterfaceMap->ppMethodVLookup = mallocForever(pInterfaceT->numVirtualMethods * sizeof(tMD_MethodDef*));
		pInterfaceMap->ppMethodVLookup[0] = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericIndexOf], pNewArrayType, 1, &pElementType);
		pInterfaceMap->ppMethodVLookup[1] = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericInsert], pNewArrayType, 1, &pElementType);
		pInterfaceMap->ppMethodVLookup[2] = ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericRemoveAt];
		pInterfaceMap->ppMethodVLookup[3] = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericGetItem], pNewArrayType, 1, &pElementType);
		pInterfaceMap->ppMethodVLookup[4] = Generics_GetMethodDefFromCoreMethod(ppGenericArrayMethods[GENERICARRAYMETHODS_Internal_GenericSetItem], pNewArrayType, 1, &pElementType);
	}

	log_f(2, "Array: Array[%s.%s]\n", pElementType->nameSpace, pElementType->name);
}