Example #1
0
        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;
        }
Example #2
0
        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;
        }
Example #3
0
        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);
        }