Ejemplo n.º 1
0
            private void Inherits(VTable baseVTbl)
            {
                foreach (VTableSlot slot in baseVTbl.Slots)
                {
                    _allSlots.Add(slot);
                    // It's possible to have same signature in multiple slots,
                    // when a derived type shadow the base type using newslot.
                    // In this case, use the derived type's slot in SlotsMap.

                    // The derived type's slots are always at a later position
                    // than the base type, so it would naturally 'override'
                    // their position in SlotsMap.
                    _slotsMap[slot.Signature] = slot;
                }

                // This is the step 1 of 12.2 algorithm -- copy the base interface implementation.
                foreach (var iface in baseVTbl.InterfaceSlots)
                {
                    Debug.Assert(!_interfaceSlots.ContainsKey(iface.Key));
                    _interfaceSlots.Add(iface.Key,
                                        iface.Value.ToDictionary(slot => ((VTableSlot)slot).Signature, slot => (VTableSlot)slot));
                }
            }
Ejemplo n.º 2
0
 static VTable ResolveGenericArgument(TypeDef openType, GenericInstSig genInst, VTable vTable)
 {
     Debug.Assert(new SigComparer().Equals(openType, vTable.Type));
     return(new VTable(genInst,
                       vTable.Slots.Select(slot => ResolveSlot(openType, (VTableSlot)slot, genInst.GenericArguments))
                       .ToList(),
                       vTable.InterfaceSlots.ToDictionary(
                           iface => GenericArgumentResolver.Resolve(iface.Key, genInst.GenericArguments),
                           iface => (IReadOnlyList <IVTableSlot>)iface.Value
                           .Select(slot => ResolveSlot(openType, (VTableSlot)slot, genInst.GenericArguments)).ToList())
                       ));
 }
Ejemplo n.º 3
0
            public VTable Build()
            {
                // Inherits base type's slots
                var baseVTbl = (VTable)_storage.GetVTable(_typeDef.GetBaseTypeThrow());

                if (baseVTbl != null)
                {
                    Inherits(baseVTbl);
                }

                var virtualMethods = _typeDef.Methods
                                     .Where(method => method.IsVirtual)
                                     .ToDictionary(
                    VTableSignature.FromMethod,
                    method => method
                    );

                if (_typeDef.FullName.Contains("SubjectBase"))
                {
                }

                // Explicit interface implementation
                foreach (var iface in _typeDef.Interfaces)
                {
                    var ifaceVTbl = (VTable)_storage.GetVTable(iface.Interface);
                    if (ifaceVTbl != null)
                    {
                        Implements(virtualMethods, ifaceVTbl, iface.Interface.ToTypeSig());
                    }
                }

                // Normal interface implementation
                if (!_typeDef.IsInterface)
                {
                    // Interface methods cannot implements base interface methods.
                    foreach (var iface in _interfaceSlots.Values)
                    {
                        foreach (var entry in iface.ToList())
                        {
                            if (!entry.Value.MethodDef.DeclaringType.IsInterface)
                            {
                                continue;
                            }
                            // This is the step 1 of 12.2 algorithm -- find implementation for still empty slots.
                            // Note that it seems we should include newslot methods as well, despite what the standard said.
                            if (virtualMethods.TryGetValue(entry.Key, out var impl))
                            {
                                iface[entry.Key] = OverridenBy(entry.Value, impl);
                            }
                            else if (_slotsMap.TryGetValue(entry.Key, out var implSlot))
                            {
                                iface[entry.Key] = OverridenBy(entry.Value, implSlot.MethodDef);
                            }
                        }
                    }
                }

                // Normal overrides
                foreach (var method in virtualMethods)
                {
                    VTableSlot slot;
                    if (method.Value.IsNewSlot)
                    {
                        slot = new VTableSlot(method.Value, _typeDef.ToTypeSig(), method.Key);
                    }
                    else if (_slotsMap.TryGetValue(method.Key, out slot))
                    {
                        Debug.Assert(!slot.MethodDef.IsFinal);
                        slot = OverridenBy(slot, method.Value);
                    }
                    else
                    {
                        slot = new VTableSlot(method.Value, _typeDef.ToTypeSig(), method.Key);
                    }

                    _slotsMap[method.Key] = slot;
                    _allSlots.Add(slot);
                }

                // MethodImpls
                foreach (var method in virtualMethods)
                {
                    foreach (var impl in method.Value.Overrides)
                    {
                        Debug.Assert(impl.MethodBody == method.Value);

                        var targetMethod = impl.MethodDeclaration.ResolveMethodDefThrow();
                        if (targetMethod.DeclaringType.IsInterface)
                        {
                            var iface     = impl.MethodDeclaration.DeclaringType.ToTypeSig();
                            var ifaceVTbl = _interfaceSlots[iface];

                            var signature  = VTableSignature.FromMethod(impl.MethodDeclaration);
                            var targetSlot = ifaceVTbl[signature];

                            // The Overrides of interface slots should directly points to the root interface slot
                            while (targetSlot.Parent != null)
                            {
                                targetSlot = (VTableSlot)targetSlot.Parent;
                            }
                            Debug.Assert(targetSlot.MethodDef.DeclaringType.IsInterface);
                            ifaceVTbl[targetSlot.Signature] = OverridenBy(targetSlot, method.Value);
                        }
                        else
                        {
                            var targetSlot = _allSlots.Single(slot => slot.MethodDef == targetMethod);
                            targetSlot = _slotsMap[targetSlot.Signature]; // Use the most derived slot
                            // Maybe implemented by above processes --- this process should take priority
                            while (targetSlot.MethodDef.DeclaringType == _typeDef)
                            {
                                targetSlot = (VTableSlot)targetSlot.Parent;
                            }
                            _slotsMap[targetSlot.Signature] = OverridenBy(targetSlot, method.Value);
                        }
                    }
                }

                var ret = new VTable(_typeDef.ToTypeSig(), _allSlots, _interfaceSlots.ToDictionary(
                                         kvp => kvp.Key, kvp => (IReadOnlyList <IVTableSlot>)kvp.Value.Values.ToList()));

                return(ret);
            }
Ejemplo n.º 4
0
            private void Implements(Dictionary <VTableSignature, MethodDef> virtualMethods, VTable ifaceVTbl,
                                    TypeSig iface)
            {
                // This is the step 2 of 12.2 algorithm -- use virtual newslot methods for explicit implementation.

                VTableSlot ImplLookup(IVTableSlot slot)
                {
                    if (virtualMethods.TryGetValue(((VTableSlot)slot).Signature, out var impl) && impl.IsNewSlot &&
                        !impl.DeclaringType.IsInterface)
                    {
                        // Interface methods cannot implements base interface methods.
                        // The Overrides of interface slots should directly points to the root interface slot
                        var targetSlot = slot;
                        while (targetSlot.Parent != null && !targetSlot.MethodDef.DeclaringType.IsInterface)
                        {
                            targetSlot = (VTableSlot)targetSlot.Parent;
                        }
                        Debug.Assert(targetSlot.MethodDef.DeclaringType.IsInterface);
                        return(OverridenBy((VTableSlot)targetSlot, impl));
                    }

                    return((VTableSlot)slot);
                }

                if (_interfaceSlots.ContainsKey(iface))
                {
                    _interfaceSlots[iface] =
                        _interfaceSlots[iface].Values.ToDictionary(slot => slot.Signature, ImplLookup);
                }
                else
                {
                    _interfaceSlots.Add(iface,
                                        ifaceVTbl.Slots.ToDictionary(slot => ((VTableSlot)slot).Signature, ImplLookup));
                }

                foreach (var baseIface in ifaceVTbl.InterfaceSlots)
                {
                    if (_interfaceSlots.ContainsKey(baseIface.Key))
                    {
                        _interfaceSlots[baseIface.Key] = _interfaceSlots[baseIface.Key].Values.ToDictionary(
                            slot => slot.Signature, ImplLookup);
                    }
                    else
                    {
                        _interfaceSlots.Add(baseIface.Key, baseIface.Value.ToDictionary(
                                                slot => ((VTableSlot)slot).Signature, ImplLookup));
                    }
                }
            }