Merge pull request #3349 from lambdageek/handle-icalls-in-jit
[mono.git] / mcs / tools / corcompare / Util.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using Mono.Cecil;
5
6 using GuiCompare;
7
8 namespace CorCompare {
9
10         static class TypeHelper {
11
12                 public static AssemblyResolver Resolver = new AssemblyResolver ();
13
14                 internal static bool IsPublic (TypeReference typeref)
15                 {
16                         if (typeref == null)
17                                 throw new ArgumentNullException ("typeref");
18
19                         TypeDefinition td = typeref.Resolve ();
20                         if (td == null)
21                                 return false;
22
23                         return td.IsPublic;
24                 }
25
26                 internal static bool IsDelegate (TypeReference typeref)
27                 {
28                         return IsDerivedFrom (typeref, "System.MulticastDelegate");
29                 }
30
31                 internal static bool IsDerivedFrom (TypeReference type, string derivedFrom)
32                 {
33                         bool first = true;
34                         foreach (var def in WalkHierarchy (type)) {
35                                 if (first) {
36                                         first = false;
37                                         continue;
38                                 }
39                                 
40                                 if (def.FullName == derivedFrom)
41                                         return true;
42                         }
43                         
44                         return false;
45                 }
46
47                 internal static IEnumerable<TypeDefinition> WalkHierarchy (TypeReference type)
48                 {
49                         for (var def = type.Resolve (); def != null; def = GetBaseType (def))
50                                 yield return def;
51                 }
52
53                 internal static IEnumerable<TypeReference> GetInterfaces (TypeReference type)
54                 {
55                         var ifaces = new Dictionary<string, TypeReference> ();
56
57                         foreach (var def in WalkHierarchy (type))
58                                 foreach (var iface in def.Interfaces)
59                                         ifaces [iface.InterfaceType.FullName] = iface.InterfaceType;
60
61                         return ifaces.Values;
62                 }
63
64                 internal static TypeDefinition GetBaseType (TypeDefinition child)
65                 {
66                         if (child.BaseType == null)
67                                 return null;
68
69                         return child.BaseType.Resolve ();
70                 }
71
72                 internal static bool IsPublic (CustomAttribute att)
73                 {
74                         return IsPublic (att.AttributeType);
75                 }
76
77                 internal static string GetFullName (CustomAttribute att)
78                 {
79                         return att.AttributeType.FullName;
80                 }
81
82                 internal static TypeDefinition GetTypeDefinition (CustomAttribute att)
83                 {
84                         return att.AttributeType.Resolve ();
85                 }
86
87                 static bool IsOverride (MethodDefinition method)
88                 {
89                         return method.IsVirtual && !method.IsNewSlot;
90                 }
91
92                 public static MethodDefinition GetBaseMethodInTypeHierarchy (MethodDefinition method)
93                 {
94                         if (!IsOverride (method))
95                                 return method;
96
97                         var @base = GetBaseType (method.DeclaringType);
98                         while (@base != null) {
99                                 MethodDefinition base_method = TryMatchMethod (@base.Resolve (), method);
100                                 if (base_method != null)
101                                         return GetBaseMethodInTypeHierarchy (base_method) ?? base_method;
102
103                                 @base = GetBaseType (@base);
104                         }
105
106                         return method;
107                 }
108
109                 static MethodDefinition TryMatchMethod (TypeDefinition type, MethodDefinition method)
110                 {
111                         if (!type.HasMethods)
112                                 return null;
113
114                         foreach (MethodDefinition candidate in type.Methods)
115                                 if (MethodMatch (candidate, method))
116                                         return candidate;
117
118                         return null;
119                 }
120
121                 static bool MethodMatch (MethodDefinition candidate, MethodDefinition method)
122                 {
123                         if (!candidate.IsVirtual)
124                                 return false;
125
126                         if (candidate.Name != method.Name)
127                                 return false;
128
129                         if (!TypeMatch (candidate.ReturnType, method.ReturnType))
130                                 return false;
131
132                         if (candidate.Parameters.Count != method.Parameters.Count)
133                                 return false;
134
135                         for (int i = 0; i < candidate.Parameters.Count; i++)
136                                 if (!TypeMatch (candidate.Parameters [i].ParameterType, method.Parameters [i].ParameterType))
137                                         return false;
138
139                         return true;
140                 }
141
142                 public static bool TypeMatch (IModifierType a, IModifierType b)
143                 {
144                         if (!TypeMatch (a.ModifierType, b.ModifierType))
145                                 return false;
146
147                         return TypeMatch (a.ElementType, b.ElementType);
148                 }
149
150                 public static bool TypeMatch (TypeSpecification a, TypeSpecification b)
151                 {
152                         if (a is GenericInstanceType)
153                                 return TypeMatch ((GenericInstanceType) a, (GenericInstanceType) b);
154
155                         if (a is IModifierType)
156                                 return TypeMatch ((IModifierType) a, (IModifierType) b);
157
158                         return TypeMatch (a.ElementType, b.ElementType);
159                 }
160
161                 public static bool TypeMatch (GenericInstanceType a, GenericInstanceType b)
162                 {
163                         if (!TypeMatch (a.ElementType, b.ElementType))
164                                 return false;
165
166                         if (a.GenericArguments.Count != b.GenericArguments.Count)
167                                 return false;
168
169                         if (a.GenericArguments.Count == 0)
170                                 return true;
171
172                         for (int i = 0; i < a.GenericArguments.Count; i++)
173                                 if (!TypeMatch (a.GenericArguments [i], b.GenericArguments [i]))
174                                         return false;
175
176                         return true;
177                 }
178
179                 public static bool TypeMatch (TypeReference a, TypeReference b)
180                 {
181                         if (a is GenericParameter)
182                                 return true;
183
184                         if (a is TypeSpecification || b is TypeSpecification) {
185                                 if (a.GetType () != b.GetType ())
186                                         return false;
187
188                                 return TypeMatch ((TypeSpecification) a, (TypeSpecification) b);
189                         }
190
191                         return a.FullName == b.FullName;
192                 }
193         }
194 }