tMD_MethodDef* MetaData_GetMethodDefFromDefRefOrSpec(tMetaData *pMetaData, IDX_TABLE token, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) { void *pTableEntry; pTableEntry = MetaData_GetTableRow(pMetaData, token); if (((tMDC_ToMethodDef*)pTableEntry)->pMethodDef != NULL) { return ((tMDC_ToMethodDef*)pTableEntry)->pMethodDef; } switch (TABLE_ID(token)) { case MD_TABLE_METHODDEF: ((tMDC_ToMethodDef*)pTableEntry)->pMethodDef = (tMD_MethodDef*)pTableEntry; return (tMD_MethodDef*)pTableEntry; case MD_TABLE_MEMBERREF: { tMD_MemberRef *pMemberRef; pMemberRef = (tMD_MemberRef*)pTableEntry; switch (TABLE_ID(pMemberRef->class_)) { case MD_TABLE_TYPEREF: case MD_TABLE_TYPESPEC: { tMD_TypeDef *pTypeDef; tMD_MethodDef *pMethodDef; pTypeDef = MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, pMemberRef->class_, ppClassTypeArgs, ppMethodTypeArgs); MetaData_Fill_TypeDef(pTypeDef, NULL, NULL); pMethodDef = FindMethodInType(pTypeDef, pMemberRef->name, pMetaData, pMemberRef->signature, pTypeDef->ppClassTypeArgs, ppMethodTypeArgs); //pMethodDef->pMethodDef = pMethodDef; return pMethodDef; } default: Crash("MetaData_GetMethodDefFromMethodDefOrRef(): Cannot handle pMemberRef->class_=0x%08x", pMemberRef->class_); } } case MD_TABLE_METHODSPEC: { tMD_MethodSpec *pMethodSpec; tMD_MethodDef *pMethodDef; pMethodSpec = (tMD_MethodSpec*)pTableEntry; pMethodDef = Generics_GetMethodDefFromSpec(pMethodSpec, ppClassTypeArgs, ppMethodTypeArgs); // Note: Cannot cache the MethodDef from the MethodSpec, as class generic arguments // may be different. return pMethodDef; } } Crash("MetaData_GetMethodDefFromMethodDefOrRef(): Cannot handle token: 0x%08x", token); FAKE_RETURN; }
tMD_FieldDef* MetaData_GetFieldDefFromDefOrRef(tMetaData *pMetaData, IDX_TABLE token, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) { void *pTableEntry; pTableEntry = MetaData_GetTableRow(pMetaData, token); if (((tMDC_ToFieldDef*)pTableEntry)->pFieldDef != NULL) { return ((tMDC_ToFieldDef*)pTableEntry)->pFieldDef; } switch (TABLE_ID(token)) { case MD_TABLE_FIELDDEF: ((tMDC_ToFieldDef*)pTableEntry)->pFieldDef = (tMD_FieldDef*)pTableEntry; return (tMD_FieldDef*)pTableEntry; case MD_TABLE_MEMBERREF: { tMD_MemberRef *pMemberRef; pMemberRef = (tMD_MemberRef*)pTableEntry; switch (TABLE_ID(pMemberRef->class_)) { case MD_TABLE_TYPEREF: case MD_TABLE_TYPESPEC: { tMD_TypeDef *pTypeDef; tMD_FieldDef *pFieldDef; pTypeDef = MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, pMemberRef->class_, ppClassTypeArgs, ppMethodTypeArgs); pFieldDef = FindFieldInType(pTypeDef, pMemberRef->name); if (TABLE_ID(pMemberRef->class_) == MD_TABLE_TYPEREF) { // Can't do this for TypeSpec because the resulting TypeDef will change // depending on what the class type arguments are. ((tMDC_ToFieldDef*)pTableEntry)->pFieldDef = pFieldDef; } return pFieldDef; } default: Crash("MetaData_GetMethodDefFromMethodDefOrRef(): Cannot handle pMemberRef->class_=0x%08x", pMemberRef->class_); } } } Crash("MetaData_GetFieldDefFromDefOrRef(): Cannot handle token: 0x%08x", token); FAKE_RETURN; }
U32 Type_IsValueType(tMD_TypeDef *pTypeDef) { // If this type is an interface, then return 0 if (TYPE_ISINTERFACE(pTypeDef)) { return 0; } // If this type is Object or ValueType then return an answer if (strcmp(pTypeDef->nameSpace, "System") == 0) { if (strcmp(pTypeDef->name, "ValueType") == 0) { return 1; } if (strcmp(pTypeDef->name, "Object") == 0) { return 0; } } // Return the isValueType determined by parent type pTypeDef = MetaData_GetTypeDefFromDefRefOrSpec(pTypeDef->pMetaData, pTypeDef->extends, NULL, NULL); MetaData_Fill_TypeDef(pTypeDef, NULL, NULL); return pTypeDef->isValueType; }
tMetaData* MetaData_GetResolutionScopeMetaData(tMetaData *pMetaData, IDX_TABLE resolutionScopeToken, tMD_TypeDef **ppInNestedType) { switch (TABLE_ID(resolutionScopeToken)) { case MD_TABLE_ASSEMBLYREF: { tMD_AssemblyRef *pAssemblyRef; pAssemblyRef = (tMD_AssemblyRef*)MetaData_GetTableRow(pMetaData, resolutionScopeToken); *ppInNestedType = NULL; return CLIFile_GetMetaDataForAssembly(pAssemblyRef->name); } case MD_TABLE_TYPEREF: { tMD_TypeDef *pTypeDef; pTypeDef = MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, resolutionScopeToken, NULL, NULL); *ppInNestedType = pTypeDef; return pTypeDef->pMetaData; } default: Crash("MetaData_GetResolutionScopeMetaData(): Cannot resolve token: 0x%08x", resolutionScopeToken); FAKE_RETURN; } }
// Return pointer to the relevant Def structure. // pObjectType returns: // 0 - tMD_TypeDef // 1 - tMD_MethodDef // 2 - tMD_FieldDef // (These link up with the JIT_LOADTOKEN_* opcodes) PTR MetaData_GetTypeMethodField(tMetaData *pMetaData, IDX_TABLE token, U32 *pObjectType, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) { switch (TABLE_ID(token)) { case MD_TABLE_TYPEDEF: case MD_TABLE_TYPEREF: case MD_TABLE_TYPESPEC: { tMD_TypeDef *pTypeDef; pTypeDef = MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs); MetaData_Fill_TypeDef(pTypeDef, NULL, NULL); *pObjectType = 0; return (PTR)pTypeDef; } case MD_TABLE_METHODDEF: method: { tMD_MethodDef *pMethodDef; pMethodDef = MetaData_GetMethodDefFromDefRefOrSpec(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs); if (pMethodDef->isFilled == 0) { tMD_TypeDef *pTypeDef; pTypeDef = MetaData_GetTypeDefFromMethodDef(pMethodDef); MetaData_Fill_TypeDef(pTypeDef, NULL, NULL); } *pObjectType = 1; return (PTR)pMethodDef; } case MD_TABLE_FIELDDEF: field: { tMD_FieldDef *pFieldDef; pFieldDef = MetaData_GetFieldDefFromDefOrRef(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs); if (pFieldDef->pParentType == NULL) { tMD_TypeDef *pTypeDef; pTypeDef = MetaData_GetTypeDefFromFieldDef(pFieldDef); MetaData_Fill_TypeDef(pTypeDef, NULL, NULL); } *pObjectType = 2; return (PTR)pFieldDef; } case MD_TABLE_MEMBERREF: { tMD_MemberRef *pMemberRef; SIG sig; pMemberRef = (tMD_MemberRef*)MetaData_GetTableRow(pMetaData, token); sig = MetaData_GetBlob(pMemberRef->signature, NULL); if (*(U8*)sig == 0x06) { // Field goto field; } else { // Method goto method; } } } Crash("MetaData_GetTypeMethodField(): Cannot handle token: 0x%08x", token); FAKE_RETURN; }
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); }
// Get the TypeDef from the type signature // Also get the size of a field from the signature // This is needed to avoid recursive sizing of types like System.Boolean, // that has a field of type System.Boolean tMD_TypeDef* Type_GetTypeFromSig(tMetaData *pMetaData, SIG *pSig, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) { U32 entry; entry = MetaData_DecodeSigEntry(pSig); switch (entry) { case ELEMENT_TYPE_VOID: return NULL; case ELEMENT_TYPE_BOOLEAN: return types[TYPE_SYSTEM_BOOLEAN]; case ELEMENT_TYPE_CHAR: return types[TYPE_SYSTEM_CHAR]; case ELEMENT_TYPE_I1: return types[TYPE_SYSTEM_SBYTE]; case ELEMENT_TYPE_U1: return types[TYPE_SYSTEM_BYTE]; case ELEMENT_TYPE_I2: return types[TYPE_SYSTEM_INT16]; case ELEMENT_TYPE_U2: return types[TYPE_SYSTEM_UINT16]; case ELEMENT_TYPE_I4: return types[TYPE_SYSTEM_INT32]; case ELEMENT_TYPE_I8: return types[TYPE_SYSTEM_INT64]; case ELEMENT_TYPE_U8: return types[TYPE_SYSTEM_UINT64]; case ELEMENT_TYPE_U4: return types[TYPE_SYSTEM_UINT32]; case ELEMENT_TYPE_R4: return types[TYPE_SYSTEM_SINGLE]; case ELEMENT_TYPE_R8: return types[TYPE_SYSTEM_DOUBLE]; case ELEMENT_TYPE_STRING: return types[TYPE_SYSTEM_STRING]; case ELEMENT_TYPE_PTR: return types[TYPE_SYSTEM_UINTPTR]; case ELEMENT_TYPE_BYREF: { tMD_TypeDef *pByRefType; // type of the by-ref parameter, don't care pByRefType = Type_GetTypeFromSig(pMetaData, pSig, ppClassTypeArgs, ppMethodTypeArgs); } // fall-through case ELEMENT_TYPE_INTPTR: return types[TYPE_SYSTEM_INTPTR]; case ELEMENT_TYPE_VALUETYPE: case ELEMENT_TYPE_CLASS: entry = MetaData_DecodeSigEntryToken(pSig); return MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, entry, ppClassTypeArgs, ppMethodTypeArgs); case ELEMENT_TYPE_VAR: entry = MetaData_DecodeSigEntry(pSig); // This is the argument number if (ppClassTypeArgs == NULL) { // Return null here as we don't yet know what the type really is. // The generic instantiation code figures this out later. return NULL; } else { return ppClassTypeArgs[entry]; } case ELEMENT_TYPE_GENERICINST: { tMD_TypeDef *pType; pType = Generics_GetGenericTypeFromSig(pMetaData, pSig, ppClassTypeArgs, ppMethodTypeArgs); return pType; } //case ELEMENT_TYPE_INTPTR: // return types[TYPE_SYSTEM_INTPTR]; case ELEMENT_TYPE_UINTPTR: return types[TYPE_SYSTEM_UINTPTR]; case ELEMENT_TYPE_OBJECT: return types[TYPE_SYSTEM_OBJECT]; case ELEMENT_TYPE_SZARRAY: { tMD_TypeDef *pElementType; pElementType = Type_GetTypeFromSig(pMetaData, pSig, ppClassTypeArgs, ppMethodTypeArgs); return Type_GetArrayTypeDef(pElementType, ppClassTypeArgs, ppMethodTypeArgs); } case ELEMENT_TYPE_MVAR: entry = MetaData_DecodeSigEntry(pSig); // This is the argument number if (ppMethodTypeArgs == NULL) { // Can't do anything sensible, as we don't have any type args return NULL; } else { return ppMethodTypeArgs[entry]; } default: Crash("Type_GetTypeFromSig(): Cannot handle signature element type: 0x%02x", entry); FAKE_RETURN; } }