Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/cecil.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTautvydas Žilys <tautvydas.zilys@gmail.com>2020-09-16 01:48:36 +0300
committerGitHub <noreply@github.com>2020-09-16 01:48:36 +0300
commit1e3bbed3ef66b79be7818f6c6ecf2ac639ffeb19 (patch)
treefaa9bd53158a19546066706747c9f3c739251b24 /Mono.Cecil/TypeReferenceEqualityComparer.cs
parente94d04f9196e3bdec9226bcfb89571249f62b6f3 (diff)
Unity's Windows Runtime changes (#394)
* Implemented Windows Runtime projections for implemented interface overrides. * Don't redirect Windows Runtime projected methods on interfaces. * Add additional test cases for Windows Runtime interface projection. * Fix reading interface impl attributes when using immediate reading mode. * Do not project for windows runtime during read. A type will not be fully initialized during read, so don't attempt to project for Windows runtime until after all of the metadata reading is correct. If a type reading for a module is no completed, a call to BinaryRangeSearch in MetadataSystem can fail, because some of the entries in the types array will still be null. * Fix build warnings. * Remove method that got duplicated during a cherry pick. * Fixed an issue with MethodReferenceComparer where it would incorrectly identify two method references to be the same if they had the same declaring types, the same parameter counts and were both unresolvable. * Sync up latest changes to MethodReferenceComparer and TypeReferenceEquality comparer and also add tests for them. * Fix code formatting. * Remove extra char * Style fix Co-authored-by: Ignas Ziberkas <ignas@unity3d.com> Co-authored-by: Josh Peterson <petersonjm1@gmail.com> Co-authored-by: Jb Evain <jb@evain.net>
Diffstat (limited to 'Mono.Cecil/TypeReferenceEqualityComparer.cs')
-rw-r--r--Mono.Cecil/TypeReferenceEqualityComparer.cs253
1 files changed, 253 insertions, 0 deletions
diff --git a/Mono.Cecil/TypeReferenceEqualityComparer.cs b/Mono.Cecil/TypeReferenceEqualityComparer.cs
new file mode 100644
index 0000000..29c2ee2
--- /dev/null
+++ b/Mono.Cecil/TypeReferenceEqualityComparer.cs
@@ -0,0 +1,253 @@
+using System;
+using System.Collections.Generic;
+
+namespace Mono.Cecil {
+ internal sealed class TypeReferenceEqualityComparer : EqualityComparer<TypeReference> {
+ public override bool Equals (TypeReference x, TypeReference y)
+ {
+ return AreEqual (x, y);
+ }
+
+ public override int GetHashCode (TypeReference obj)
+ {
+ return GetHashCodeFor (obj);
+ }
+
+ public static bool AreEqual (TypeReference a, TypeReference b, TypeComparisonMode comparisonMode = TypeComparisonMode.Exact)
+ {
+ if (ReferenceEquals (a, b))
+ return true;
+
+ if (a == null || b == null)
+ return false;
+
+ var aMetadataType = a.MetadataType;
+ var bMetadataType = b.MetadataType;
+
+ if (aMetadataType == MetadataType.GenericInstance || bMetadataType == MetadataType.GenericInstance) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ return AreEqual ((GenericInstanceType)a, (GenericInstanceType)b, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.Array || bMetadataType == MetadataType.Array) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ var a1 = (ArrayType)a;
+ var b1 = (ArrayType)b;
+ if (a1.Rank != b1.Rank)
+ return false;
+
+ return AreEqual (a1.ElementType, b1.ElementType, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.Var || bMetadataType == MetadataType.Var) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ return AreEqual ((GenericParameter)a, (GenericParameter)b, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.MVar || bMetadataType == MetadataType.MVar) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ return AreEqual ((GenericParameter)a, (GenericParameter)b, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.ByReference || bMetadataType == MetadataType.ByReference) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ return AreEqual (((ByReferenceType)a).ElementType, ((ByReferenceType)b).ElementType, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.Pointer || bMetadataType == MetadataType.Pointer) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ return AreEqual (((PointerType)a).ElementType, ((PointerType)b).ElementType, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.RequiredModifier || bMetadataType == MetadataType.RequiredModifier) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ var a1 = (RequiredModifierType)a;
+ var b1 = (RequiredModifierType)b;
+
+ return AreEqual (a1.ModifierType, b1.ModifierType, comparisonMode) && AreEqual (a1.ElementType, b1.ElementType, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.OptionalModifier || bMetadataType == MetadataType.OptionalModifier) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ var a1 = (OptionalModifierType)a;
+ var b1 = (OptionalModifierType)b;
+
+ return AreEqual (a1.ModifierType, b1.ModifierType, comparisonMode) && AreEqual (a1.ElementType, b1.ElementType, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.Pinned || bMetadataType == MetadataType.Pinned) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ return AreEqual (((PinnedType)a).ElementType, ((PinnedType)b).ElementType, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.Sentinel || bMetadataType == MetadataType.Sentinel) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ return AreEqual (((SentinelType)a).ElementType, ((SentinelType)b).ElementType, comparisonMode);
+ }
+
+ if (!a.Name.Equals (b.Name) || !a.Namespace.Equals (b.Namespace))
+ return false;
+
+ var xDefinition = a.Resolve ();
+ var yDefinition = b.Resolve ();
+
+ // For loose signature the types could be in different assemblies, as long as the type names match we will consider them equal
+ if (comparisonMode == TypeComparisonMode.SignatureOnlyLoose) {
+ if (xDefinition.Module.Name != yDefinition.Module.Name)
+ return false;
+
+ if (xDefinition.Module.Assembly.Name.Name != yDefinition.Module.Assembly.Name.Name)
+ return false;
+
+ return xDefinition.FullName == yDefinition.FullName;
+ }
+
+ return xDefinition == yDefinition;
+ }
+
+ static bool AreEqual (GenericParameter a, GenericParameter b, TypeComparisonMode comparisonMode = TypeComparisonMode.Exact)
+ {
+ if (ReferenceEquals (a, b))
+ return true;
+
+ if (a.Position != b.Position)
+ return false;
+
+ if (a.Type != b.Type)
+ return false;
+
+ var aOwnerType = a.Owner as TypeReference;
+ if (aOwnerType != null && AreEqual (aOwnerType, b.Owner as TypeReference, comparisonMode))
+ return true;
+
+ var aOwnerMethod = a.Owner as MethodReference;
+ if (aOwnerMethod != null && comparisonMode != TypeComparisonMode.SignatureOnlyLoose && MethodReferenceComparer.AreEqual (aOwnerMethod, b.Owner as MethodReference))
+ return true;
+
+ return comparisonMode == TypeComparisonMode.SignatureOnly || comparisonMode == TypeComparisonMode.SignatureOnlyLoose;
+ }
+
+ static bool AreEqual (GenericInstanceType a, GenericInstanceType b, TypeComparisonMode comparisonMode = TypeComparisonMode.Exact)
+ {
+ if (ReferenceEquals (a, b))
+ return true;
+
+ var aGenericArgumentsCount = a.GenericArguments.Count;
+ if (aGenericArgumentsCount != b.GenericArguments.Count)
+ return false;
+
+ if (!AreEqual (a.ElementType, b.ElementType, comparisonMode))
+ return false;
+
+ for (int i = 0; i < aGenericArgumentsCount; i++)
+ if (!AreEqual (a.GenericArguments[i], b.GenericArguments[i], comparisonMode))
+ return false;
+
+ return true;
+ }
+
+ public static int GetHashCodeFor (TypeReference obj)
+ {
+ // a very good prime number
+ const int hashCodeMultiplier = 486187739;
+ // prime numbers
+ const int genericInstanceTypeMultiplier = 31;
+ const int byReferenceMultiplier = 37;
+ const int pointerMultiplier = 41;
+ const int requiredModifierMultiplier = 43;
+ const int optionalModifierMultiplier = 47;
+ const int pinnedMultiplier = 53;
+ const int sentinelMultiplier = 59;
+
+ var metadataType = obj.MetadataType;
+
+ if (metadataType == MetadataType.GenericInstance) {
+ var genericInstanceType = (GenericInstanceType)obj;
+ var hashCode = GetHashCodeFor (genericInstanceType.ElementType) * hashCodeMultiplier + genericInstanceTypeMultiplier;
+ for (var i = 0; i < genericInstanceType.GenericArguments.Count; i++)
+ hashCode = hashCode * hashCodeMultiplier + GetHashCodeFor (genericInstanceType.GenericArguments[i]);
+ return hashCode;
+ }
+
+ if (metadataType == MetadataType.Array) {
+ var arrayType = (ArrayType)obj;
+ return GetHashCodeFor (arrayType.ElementType) * hashCodeMultiplier + arrayType.Rank.GetHashCode ();
+ }
+
+ if (metadataType == MetadataType.Var || metadataType == MetadataType.MVar) {
+ var genericParameter = (GenericParameter)obj;
+ var hashCode = genericParameter.Position.GetHashCode () * hashCodeMultiplier + ((int)metadataType).GetHashCode ();
+
+ var ownerTypeReference = genericParameter.Owner as TypeReference;
+ if (ownerTypeReference != null)
+ return hashCode * hashCodeMultiplier + GetHashCodeFor (ownerTypeReference);
+
+ var ownerMethodReference = genericParameter.Owner as MethodReference;
+ if (ownerMethodReference != null)
+ return hashCode * hashCodeMultiplier + MethodReferenceComparer.GetHashCodeFor (ownerMethodReference);
+
+ throw new InvalidOperationException ("Generic parameter encountered with invalid owner");
+ }
+
+ if (metadataType == MetadataType.ByReference) {
+ var byReferenceType = (ByReferenceType)obj;
+ return GetHashCodeFor (byReferenceType.ElementType) * hashCodeMultiplier * byReferenceMultiplier;
+ }
+
+ if (metadataType == MetadataType.Pointer) {
+ var pointerType = (PointerType)obj;
+ return GetHashCodeFor (pointerType.ElementType) * hashCodeMultiplier * pointerMultiplier;
+ }
+
+ if (metadataType == MetadataType.RequiredModifier) {
+ var requiredModifierType = (RequiredModifierType)obj;
+ var hashCode = GetHashCodeFor (requiredModifierType.ElementType) * requiredModifierMultiplier;
+ hashCode = hashCode * hashCodeMultiplier + GetHashCodeFor (requiredModifierType.ModifierType);
+ return hashCode;
+ }
+
+ if (metadataType == MetadataType.OptionalModifier) {
+ var optionalModifierType = (OptionalModifierType)obj;
+ var hashCode = GetHashCodeFor (optionalModifierType.ElementType) * optionalModifierMultiplier;
+ hashCode = hashCode * hashCodeMultiplier + GetHashCodeFor (optionalModifierType.ModifierType);
+ return hashCode;
+ }
+
+ if (metadataType == MetadataType.Pinned) {
+ var pinnedType = (PinnedType)obj;
+ return GetHashCodeFor (pinnedType.ElementType) * hashCodeMultiplier * pinnedMultiplier;
+ }
+
+ if (metadataType == MetadataType.Sentinel) {
+ var sentinelType = (SentinelType)obj;
+ return GetHashCodeFor (sentinelType.ElementType) * hashCodeMultiplier * sentinelMultiplier;
+ }
+
+ if (metadataType == MetadataType.FunctionPointer) {
+ throw new NotImplementedException ("We currently don't handle function pointer types.");
+ }
+
+ return obj.Namespace.GetHashCode () * hashCodeMultiplier + obj.FullName.GetHashCode ();
+ }
+ }
+}