public static VTable ConstructVTable(TypeDef typeDef, VTableStorage storage) { var ret = new VTable(typeDef); var slotDict = new Dictionary<VTableSignature, List<VTableSlot>>(); // Partition II 12.2 // Interfaces foreach (InterfaceImpl iface in typeDef.Interfaces) { VTable ifaceVTbl = storage.GetVTable(iface.Interface); if (ifaceVTbl != null) ret.Inherit(ifaceVTbl, slotDict); } // Base type VTable baseVTbl = storage.GetVTable(typeDef.GetBaseTypeThrow()); if (baseVTbl != null) ret.Inherit(baseVTbl, slotDict); List<MethodDef> virtualMethods = typeDef.Methods.Where(method => method.IsVirtual).ToList(); var methodsProcessed = new HashSet<MethodDef>(); // MethodImpls (Partition II 22.27) foreach (MethodDef method in virtualMethods) foreach (MethodOverride impl in method.Overrides) { Debug.Assert(impl.MethodBody == method); MethodDef targetMethod = impl.MethodDeclaration.ResolveThrow(); VTableSignature sig = VTableSignature.FromMethod(impl.MethodDeclaration); Debug.Assert(slotDict.ContainsKey(sig)); var methodSlot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), VTableSignature.FromMethod(method)); ret.Override(slotDict, sig, methodSlot, targetMethod); methodsProcessed.Add(method); } // Normal override foreach (MethodDef method in virtualMethods) { VTableSignature sig = VTableSignature.FromMethod(method); var methodSlot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), sig); if (slotDict.ContainsKey(sig) && slotDict[sig].Count > 0) { ret.Override(slotDict, sig, methodSlot); methodsProcessed.Add(method); } } // Remaining methods foreach (MethodDef method in typeDef.Methods.Where(method => method.IsVirtual).Except(methodsProcessed)) { var slot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), VTableSignature.FromMethod(method)); if (method.IsFinal) ret.Finals.Add(slot); else { Debug.Assert(!ret.Slots.Any(s => s.MethodDef == method)); ret.Slots.Add(slot); } } return ret; }
public static VTable ConstructVTable(TypeDef typeDef, VTableStorage storage) { var ret = new VTable(typeDef); var slotDict = new Dictionary<VTableSignature, List<VTableSlot>>(); // Partition II 12.2 // Interfaces foreach (InterfaceImpl iface in typeDef.Interfaces) { VTable ifaceVTbl = storage.GetVTable(iface.Interface); if (ifaceVTbl != null) ret.Inherit(ifaceVTbl, slotDict); } // Base type VTable baseVTbl = storage.GetVTable(typeDef.GetBaseTypeThrow()); if (baseVTbl != null) ret.Inherit(baseVTbl, slotDict); List<MethodDef> virtualMethods = typeDef.Methods.Where(method => method.IsVirtual).ToList(); var methodsProcessed = new HashSet<MethodDef>(); // MethodImpls (Partition II 22.27) foreach (MethodDef method in virtualMethods) foreach (MethodOverride impl in method.Overrides) { Debug.Assert(impl.MethodBody == method); MethodDef targetMethod = impl.MethodDeclaration.ResolveThrow(); VTableSignature sig = VTableSignature.FromMethod(impl.MethodDeclaration); Debug.Assert(slotDict.ContainsKey(sig)); var methodSlot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), VTableSignature.FromMethod(method)); if (slotDict.ContainsKey(sig) && slotDict[sig].Count > 0) { ret.Override(slotDict, sig, methodSlot, targetMethod); methodsProcessed.Add(method); } } // Normal override foreach (MethodDef method in virtualMethods) { VTableSignature sig = VTableSignature.FromMethod(method); var methodSlot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), sig); if (slotDict.ContainsKey(sig) && slotDict[sig].Count > 0) { ret.Override(slotDict, sig, methodSlot); methodsProcessed.Add(method); } } // Remaining methods foreach (MethodDef method in typeDef.Methods.Where(method => method.IsVirtual).Except(methodsProcessed)) { foreach (var remainingSlot in slotDict.Keys.Where(key => key.InterfaceType != null)) { // If there is a remaining slot for an interface method which has the same name and signature as an unprocessed method, // allow the method to override the slot. // This is necessary because public methods which implement interface methods do not have an InterfaceType in their signature, // but the keys of "slotDict" which were added for interface methods *do* have InterfaceType in their signature. Therefore, // these slots are not filled by the "Normal override" loop above. if (new SigComparer().Equals(remainingSlot.MethodSig, method.MethodSig) && remainingSlot.Name.Equals(method.Name, StringComparison.Ordinal)) { var methodSlot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), remainingSlot); ret.Override(slotDict, remainingSlot, methodSlot); methodsProcessed.Add(method); goto next; } } var slot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), VTableSignature.FromMethod(method)); if (method.IsFinal) ret.Finals.Add(slot); else { Debug.Assert(!ret.Slots.Any(s => s.MethodDef == method)); ret.Slots.Add(slot); } next: continue; } return ret; }
public static VTable ConstructVTable(TypeDef typeDef, VTableStorage storage) { var ret = new VTable(typeDef); var slotDict = new Dictionary <VTableSignature, List <VTableSlot> >(); // Partition II 12.2 // Interfaces foreach (InterfaceImpl iface in typeDef.Interfaces) { VTable ifaceVTbl = storage.GetVTable(iface.Interface); if (ifaceVTbl != null) { ret.Inherit(ifaceVTbl, slotDict); } } // Base type VTable baseVTbl = storage.GetVTable(typeDef.GetBaseTypeThrow()); if (baseVTbl != null) { ret.Inherit(baseVTbl, slotDict); } List <MethodDef> virtualMethods = typeDef.Methods.Where(method => method.IsVirtual).ToList(); var methodsProcessed = new HashSet <MethodDef>(); // MethodImpls (Partition II 22.27) foreach (MethodDef method in virtualMethods) { foreach (MethodOverride impl in method.Overrides) { Debug.Assert(impl.MethodBody == method); MethodDef targetMethod = impl.MethodDeclaration.ResolveThrow(); VTableSignature sig = VTableSignature.FromMethod(impl.MethodDeclaration); Debug.Assert(slotDict.ContainsKey(sig)); var methodSlot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), VTableSignature.FromMethod(method)); if (slotDict.ContainsKey(sig) && slotDict[sig].Count > 0) { ret.Override(slotDict, sig, methodSlot, targetMethod); methodsProcessed.Add(method); } } } // Normal override foreach (MethodDef method in virtualMethods) { VTableSignature sig = VTableSignature.FromMethod(method); var methodSlot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), sig); if (slotDict.ContainsKey(sig) && slotDict[sig].Count > 0) { ret.Override(slotDict, sig, methodSlot); methodsProcessed.Add(method); } } // Remaining methods foreach (MethodDef method in typeDef.Methods.Where(method => method.IsVirtual).Except(methodsProcessed)) { foreach (var remainingSlot in slotDict.Keys.Where(key => key.InterfaceType != null)) { // If there is a remaining slot for an interface method which has the same name and signature as an unprocessed method, // allow the method to override the slot. // This is necessary because public methods which implement interface methods do not have an InterfaceType in their signature, // but the keys of "slotDict" which were added for interface methods *do* have InterfaceType in their signature. Therefore, // these slots are not filled by the "Normal override" loop above. if (new SigComparer().Equals(remainingSlot.MethodSig, method.MethodSig) && remainingSlot.Name.Equals(method.Name, StringComparison.Ordinal)) { var methodSlot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), remainingSlot); ret.Override(slotDict, remainingSlot, methodSlot); methodsProcessed.Add(method); goto next; } } var slot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), VTableSignature.FromMethod(method)); if (method.IsFinal) { ret.Finals.Add(slot); } else { Debug.Assert(!ret.Slots.Any(s => s.MethodDef == method)); ret.Slots.Add(slot); } next: continue; } return(ret); }