Get rid of TypesByMethodSpecClassIndex.

classIndexIndex only indexes the genericInstance, not the actual generic
instance type. Therefore, for example, A<Int32,Int32> and B<Int32,Int32>
have the same classIndexIndex because the generic parameters are the
same, despite being otherwise unrelated.

Instead of TypesByMethodSpecClassIndex, we simply call MakeGenericType
each time, relying on genericTypeInstances to dedup the resulting
instances. This patch thus also adds all of the types from
genericTypeInstances to the Il2CppModel.Types listing.
This commit is contained in:
Robert Xiao
2020-04-11 17:00:33 -07:00
committed by Katy
parent a9f6e7b4e0
commit 193cdcdc4a
2 changed files with 19 additions and 16 deletions

View File

@@ -22,9 +22,6 @@ namespace Il2CppInspector.Reflection
// List of all types from TypeRefs ordered by instanceIndex
public TypeInfo[] TypesByReferenceIndex { get; }
// List of all types from MethodSpecs (closed generic types that can be instantiated)
public Dictionary<int, TypeInfo> TypesByMethodSpecClassIndex { get; } = new Dictionary<int, TypeInfo>();
// List of all methods from MethodSpecs (closed generic methods that can be called; does not need to be in a generic class)
public Dictionary<Il2CppMethodSpec, MethodBase> GenericMethods { get; } = new Dictionary<Il2CppMethodSpec, MethodBase>();
@@ -32,8 +29,13 @@ namespace Il2CppInspector.Reflection
public Dictionary<string, TypeInfo> TypesByFullName { get; } = new Dictionary<string, TypeInfo>();
// Every type
public IEnumerable<TypeInfo> Types => new IEnumerable<TypeInfo>[] {TypesByDefinitionIndex, TypesByReferenceIndex, TypesByMethodSpecClassIndex.Values}
.SelectMany(t => t).Distinct();
public IEnumerable<TypeInfo> Types {
get {
var result = new IEnumerable<TypeInfo>[] { TypesByDefinitionIndex, TypesByReferenceIndex }.SelectMany(t => t);
result = result.Concat(result.SelectMany(t => t.CachedGeneratedTypes));
return result.Distinct();
}
}
// List of all methods ordered by their MethodDefinitionIndex
public MethodBase[] MethodsByDefinitionIndex { get; }
@@ -91,14 +93,10 @@ namespace Il2CppInspector.Reflection
// Concrete instance of a generic class
// If the class index is not specified, we will later create a generic method in a non-generic class
if (spec.classIndexIndex != -1) {
if (!TypesByMethodSpecClassIndex.ContainsKey(spec.classIndexIndex)) {
var genericTypeDefinition = MethodsByDefinitionIndex[spec.methodDefinitionIndex].DeclaringType;
var genericInstance = Package.GenericInstances[spec.classIndexIndex];
var genericArguments = ResolveGenericArguments(genericInstance);
TypesByMethodSpecClassIndex.Add(spec.classIndexIndex, genericTypeDefinition.MakeGenericType(genericArguments));
}
declaringType = TypesByMethodSpecClassIndex[spec.classIndexIndex];
var genericTypeDefinition = MethodsByDefinitionIndex[spec.methodDefinitionIndex].DeclaringType;
var genericInstance = Package.GenericInstances[spec.classIndexIndex];
var genericArguments = ResolveGenericArguments(genericInstance);
declaringType = genericTypeDefinition.MakeGenericType(genericArguments);
}
else
declaringType = MethodsByDefinitionIndex[spec.methodDefinitionIndex].DeclaringType;
@@ -216,9 +214,7 @@ namespace Il2CppInspector.Reflection
MetadataUsageType.TypeInfo => TypesByReferenceIndex[usage.SourceIndex],
MetadataUsageType.MethodDef => GetMetadataUsageMethod(usage).DeclaringType,
MetadataUsageType.FieldInfo => TypesByReferenceIndex[Package.FieldRefs[usage.SourceIndex].typeIndex],
MetadataUsageType.MethodRef => Package.MethodSpecs[usage.SourceIndex].classIndexIndex != -1?
TypesByMethodSpecClassIndex[Package.MethodSpecs[usage.SourceIndex].classIndexIndex] :
GetMetadataUsageMethod(usage).DeclaringType,
MetadataUsageType.MethodRef => GetMetadataUsageMethod(usage).DeclaringType,
_ => throw new InvalidOperationException("Incorrect metadata usage type to retrieve referenced type")
};

View File

@@ -33,6 +33,13 @@ namespace Il2CppInspector.Reflection {
}
// This property exposes all types which have been generated directly from this one.
public IEnumerable<TypeInfo> CachedGeneratedTypes {
get {
return genericTypeInstances?.Values ?? Enumerable.Empty<TypeInfo>();
}
}
// Information/flags about the type
// Undefined if the Type represents a generic type parameter
public TypeAttributes Attributes { get; }