Exemple #1
0
        private void ExportClassStatics(Clarity.Rpa.HighFileBuilder fileBuilder, BinaryWriter writer, CppClass cls)
        {
            if (!cls.HaveNewStaticFields)
            {
                writer.Write((uint)0);
                return;
            }

            uint numStaticFields = 0;
            foreach (CppField field in cls.Fields)
                if (field.Field.Static && !field.Field.Literal)
                    numStaticFields++;

            writer.Write(numStaticFields);
            foreach (CppField field in cls.Fields)
            {
                if (field.Field.Static && !field.Field.Literal)
                {
                    writer.Write(fileBuilder.IndexTypeSpecTag(RpaTagFactory.CreateTypeTag(field.Type)));
                    writer.Write(fileBuilder.IndexString(field.Name));
                }
            }
        }
Exemple #2
0
        private void WriteInterfaceImplementations(Clarity.Rpa.HighFileBuilder fileBuilder, BinaryWriter writer, CppClass cls)
        {
            if (cls.TypeDef.Semantics != CLRTypeDefRow.TypeSemantics.Class)
                throw new ArgumentException();

            List<CppVtableSlot> requiredVTableSlots = new List<CppVtableSlot>();

            uint numNewInterfaces = (uint)cls.NewlyImplementedInterfaces.Count;
            uint numReimplementedInterfaces = (uint)cls.ReimplementedInterfaces.Count;

            List<KeyValuePair<CLRTypeSpec, bool>> reqBindings = new List<KeyValuePair<CLRTypeSpec, bool>>();

            foreach (CLRTypeSpec ts in cls.NewlyImplementedInterfaces)
                reqBindings.Add(new KeyValuePair<CLRTypeSpec, bool>(ts, false));
            foreach (CLRTypeSpec ts in cls.ReimplementedInterfaces)
                reqBindings.Add(new KeyValuePair<CLRTypeSpec, bool>(ts, true));

            writer.Write((uint)reqBindings.Count);

            List<BoundInterfaceMethodImpl> boundImpls = new List<BoundInterfaceMethodImpl>();

            foreach (CLRMethodImplRow methodImpl in cls.TypeDef.MethodImplementations)
            {
                CppVtableSlot decl = ResolveMethodImplReference(methodImpl.MethodDeclaration);
                CppVtableSlot body = ResolveMethodImplReference(methodImpl.MethodBody);
                CLRTypeSpec spec = m_assemblies.InternTypeDefOrRefOrSpec(methodImpl.Class);

                if (decl.Equals(body))
                {
                    // Roslyn sometimes emits redundant MethodImpls that override the vtable slot
                    // that the method already occupies via ReuseSlot.  We want to ignore these.
                    continue;
                }

                boundImpls.Add(new BoundInterfaceMethodImpl(spec, decl, body));
            }

            foreach (KeyValuePair<CLRTypeSpec, bool> convPair in reqBindings)
            {
                CLRTypeSpec conv = convPair.Key;
                bool isReimpl = convPair.Value;

                writer.Write(fileBuilder.IndexTypeSpecTag(RpaTagFactory.CreateTypeTag(conv)));

                CppClass ifcClass = this.GetCachedClass(conv);

                writer.Write((uint)ifcClass.Methods.Count);

                foreach (CppMethod method in ifcClass.Methods)
                {
                    CppVtableSlot slot = method.CreatesSlot;
                    if (slot == null)
                        throw new ArgumentException();

                    bool isExplicitlyBound = false;
                    for (int i = 0; i < boundImpls.Count; i++)
                    {
                        BoundInterfaceMethodImpl bimi = boundImpls[i];
                        if (bimi.InterfaceSlot.DisambigSpec.Equals(conv) &&
                            bimi.InterfaceSlot.Name == slot.Name && bimi.InterfaceSlot.Signature.Equals(slot.Signature))
                        {
                            isExplicitlyBound = true;

                            writer.Write(true);    // HACK - FIXME
                            WriteInterfaceBinding(fileBuilder, writer, bimi.InterfaceSlot, bimi.ClassSlot);
                            boundImpls.RemoveAt(i);
                            break;
                        }
                    }

                    if (!isExplicitlyBound)
                    {
                        // Look for a matching slot
                        // This should follow the rules of II.12.2
                        // Because Clarity does not support virtual generic methods, maintaining a
                        // per-slot implementation list is not necessary.  However, duplicate slots
                        // from generic type substitution are still allowed.
                        //
                        // We depend on visible vtable slots being in method declaration order already,
                        // so the only thing we really need to do is return the first one.
                        //
                        // .NET has some additional non-standardized behavior: If a reimplemented interface
                        // doesn't have a new match since the last time it was implemented, then the implementation
                        // has NO MATCHES.  This matters because since interface dispatch is done per-class,
                        // per-method, a variant interface that does have a match will take priority if it's
                        // higher in the class hierarchy.
                        //
                        // See TestInheritedImplementationDeprioritization for an example of this.
                        bool haveMatch = WriteSignatureMatchedBinding(fileBuilder, writer, cls, slot, conv);

                        // If there's no match, but this is a reimplementation, then use the old implementation
                        // Allows TestInheritedReimpl to pass.
                        if (!haveMatch)
                        {
                            if (!isReimpl)
                                throw new ParseFailedException("Unmatched interface method");

                            writer.Write(false);    // HACK - FIXME
                        }
                    }
                }
            }

            if (boundImpls.Count > 0)
                throw new NotSupportedException("Don't support non-interface override thunks yet");
        }
Exemple #3
0
        private void ExportClassDefinitions(Clarity.Rpa.HighFileBuilder fileBuilder, BinaryWriter writer, CppClass cls)
        {
            if (cls.IsDelegate || cls.IsEnum)
                throw new ArgumentException();

            if (cls.TypeDef.Semantics == CLRTypeDefRow.TypeSemantics.Interface)
                ExportGenericVariance(cls, writer);

            if (!cls.IsValueType && cls.TypeDef.Semantics == CLRTypeDefRow.TypeSemantics.Class)
            {
                writer.Write(cls.TypeDef.IsSealed);
                writer.Write(cls.TypeDef.IsAbstract);
                if (cls.ParentTypeSpec == null)
                    writer.Write((uint)0);
                else
                    writer.Write(1 + fileBuilder.IndexTypeSpecTag(RpaTagFactory.CreateTypeTag(cls.ParentTypeSpec)));
            }

            writer.Write((uint)cls.ExplicitInterfaces.Count);
            foreach (CLRTypeSpec typeSpec in cls.ExplicitInterfaces)
                writer.Write(fileBuilder.IndexTypeSpecTag(RpaTagFactory.CreateTypeTag(typeSpec)));

            WriteVtableThunks(fileBuilder, writer, cls);

            if (cls.TypeDef.Semantics == CLRTypeDefRow.TypeSemantics.Class)
            {
                uint numNonAbstractMethods = 0;

                foreach (CppMethod method in cls.Methods)
                {
                    if (!method.Abstract)
                        numNonAbstractMethods++;
                }

                writer.Write(numNonAbstractMethods);

                foreach (CppMethod method in cls.Methods)
                {
                    if (method.Abstract)
                        continue;

                    writer.Write(method.Static);
                    writer.Write(fileBuilder.IndexMethodSignatureTag(RpaTagFactory.CreateMethodSignature(method.MethodSignature)));
                    writer.Write(fileBuilder.IndexString(method.Name));
                    ExportMethodCode(fileBuilder, writer, cls, method);
                }

                uint numInstanceFields = 0;
                foreach (CppField field in cls.Fields)
                {
                    CLRFieldRow fieldDef = field.Field;
                    if (!fieldDef.Literal && !fieldDef.Static)
                        numInstanceFields++;
                }

                writer.Write(numInstanceFields);
                foreach (CppField field in cls.Fields)
                {
                    CLRFieldRow fieldDef = field.Field;
                    if (!fieldDef.Literal && !fieldDef.Static)
                    {
                        writer.Write(fileBuilder.IndexTypeSpecTag(RpaTagFactory.CreateTypeTag(field.Type)));
                        writer.Write(fileBuilder.IndexString(field.Name));
                    }
                }

                WriteInterfaceImplementations(fileBuilder, writer, cls);
            }
        }