Ejemplo n.º 1
0
        /* Vtable:
         *
         *  TIPtr (just to a glorified TypeSpec)
         *  IFacePtr (to list of implemented interfaces)
         *  Extends (to base classes for quick castclassex)
         *  TypeSize (to allow MemberwiseClone to work without full Reflection)
         *  Any target-specific data
         *  Method 0
         *  ...
         *
         *  IFaceList TODO
         *
         *
         */

        public static void OutputVTable(TypeSpec ts,
                                        target.Target t, binary_library.IBinaryFile of,
                                        TysilaState s,
                                        MetadataStream base_m = null,
                                        ISection os           = null,
                                        ISection data_sect    = null)
        {
            // Don't compile if not for this architecture
            if (!t.IsTypeValid(ts))
            {
                return;
            }

            /* New signature table */
            s.sigt = new SignatureTable(ts.MangleType());

            // If its a delegate type we also need to output its methods
            if (ts.IsDelegate && !ts.IsGenericTemplate)
            {
                s.r.DelegateRequestor.Request(ts);
            }

            if (os == null)
            {
                os = of.GetRDataSection();
            }
            var d        = os.Data;
            var ptr_size = t.GetCTSize(ir.Opcode.ct_object);

            os.Align(ptr_size);

            ulong offset = (ulong)os.Data.Count;

            /* Symbol */
            var sym = of.CreateSymbol();

            sym.Name       = ts.MangleType();
            sym.ObjectType = binary_library.SymbolObjectType.Object;
            sym.Offset     = offset;
            sym.Type       = binary_library.SymbolType.Global;
            os.AddSymbol(sym);

            if (base_m != null && ts.m != base_m)
            {
                sym.Type = SymbolType.Weak;
            }

            /* TIPtr */
            var tiptr_offset = s.sigt.GetSignatureAddress(ts.Signature, t, s);

            var ti_reloc = of.CreateRelocation();

            ti_reloc.Addend          = tiptr_offset;
            ti_reloc.DefinedIn       = os;
            ti_reloc.Offset          = offset;
            ti_reloc.Type            = t.GetDataToDataReloc();
            ti_reloc.References      = of.CreateSymbol();
            ti_reloc.References.Name = s.sigt.GetStringTableName();
            of.AddRelocation(ti_reloc);

            for (int i = 0; i < ptr_size; i++, offset++)
            {
                d.Add(0);
            }

            /* IFacePtr */
            IRelocation if_reloc = null;

            if (!ts.IsGenericTemplate && !ts.IsInterface && ts.stype != TypeSpec.SpecialType.Ptr && ts.stype != TypeSpec.SpecialType.MPtr)
            {
                if_reloc            = of.CreateRelocation();
                if_reloc.DefinedIn  = os;
                if_reloc.Offset     = offset;
                if_reloc.Type       = t.GetDataToDataReloc();
                if_reloc.References = sym;
                of.AddRelocation(if_reloc);
            }

            for (int i = 0; i < ptr_size; i++, offset++)
            {
                d.Add(0);
            }

            /* Extends */
            var ts_extends = ts.GetExtends();

            if (ts_extends != null)
            {
                var ext_reloc = of.CreateRelocation();
                ext_reloc.Addend    = 0;
                ext_reloc.DefinedIn = os;
                ext_reloc.Offset    = offset;
                ext_reloc.Type      = t.GetDataToDataReloc();

                var ext_sym = of.CreateSymbol();
                ext_sym.Name = ts_extends.MangleType();

                ext_reloc.References = ext_sym;
                of.AddRelocation(ext_reloc);

                s.r.VTableRequestor.Request(ts_extends);
            }
            for (int i = 0; i < ptr_size; i++, offset++)
            {
                d.Add(0);
            }

            if (ts.IsInterface || ts.IsGenericTemplate || ts.stype == TypeSpec.SpecialType.MPtr || ts.stype == TypeSpec.SpecialType.Ptr)
            {
                /* Type size is zero for somethinh we cannot
                 * instantiate */
                for (int i = 0; i < ptr_size; i++, offset++)
                {
                    d.Add(0);
                }

                /* Flags */
                AddFlags(d, ts, ref offset, t);

                /* BaseType */
                AddBaseType(d, ts, of, os, ref offset, t, s);

                // Target-specific information
                t.AddExtraVTableFields(ts, d, ref offset);
            }
            else
            {
                /* Type size */
                var tsize = t.IntPtrArray(BitConverter.GetBytes(GetTypeSize(ts, t)));
                foreach (var b in tsize)
                {
                    d.Add(b);
                    offset++;
                }

                /* Flags */
                AddFlags(d, ts, ref offset, t);

                /* BaseType */
                AddBaseType(d, ts, of, os, ref offset, t, s);

                // Target specific information
                t.AddExtraVTableFields(ts, d, ref offset);

                /* Virtual methods */
                OutputVirtualMethods(ts, of, os,
                                     d, ref offset, t, s);

                /* Interface implementations */

                // build list of implemented interfaces
                var ii = ts.ImplementedInterfaces;

                // first, add all interface implementations
                List <ulong> ii_offsets = new List <ulong>();

                for (int i = 0; i < ii.Count; i++)
                {
                    ii_offsets.Add(offset - sym.Offset);
                    OutputInterface(ts, ii[i],
                                    of, os, d, ref offset, t, s);
                    s.r.VTableRequestor.Request(ii[i]);
                }

                // point iface ptr here
                if_reloc.Addend = (long)offset - (long)sym.Offset;
                for (int i = 0; i < ii.Count; i++)
                {
                    // list is pointer to interface declaration, then implementation
                    var id_ptr_sym = of.CreateSymbol();
                    id_ptr_sym.Name = ii[i].MangleType();

                    var id_ptr_reloc = of.CreateRelocation();
                    id_ptr_reloc.Addend     = 0;
                    id_ptr_reloc.DefinedIn  = os;
                    id_ptr_reloc.Offset     = offset;
                    id_ptr_reloc.References = id_ptr_sym;
                    id_ptr_reloc.Type       = t.GetDataToDataReloc();
                    of.AddRelocation(id_ptr_reloc);

                    for (int j = 0; j < ptr_size; j++, offset++)
                    {
                        d.Add(0);
                    }

                    // implementation
                    var ii_ptr_reloc = of.CreateRelocation();
                    ii_ptr_reloc.Addend     = (long)ii_offsets[i];
                    ii_ptr_reloc.DefinedIn  = os;
                    ii_ptr_reloc.Offset     = offset;
                    ii_ptr_reloc.References = sym;
                    ii_ptr_reloc.Type       = t.GetDataToDataReloc();
                    of.AddRelocation(ii_ptr_reloc);

                    for (int j = 0; j < ptr_size; j++, offset++)
                    {
                        d.Add(0);
                    }
                }

                // null terminate the list
                for (int j = 0; j < ptr_size; j++, offset++)
                {
                    d.Add(0);
                }
            }

            sym.Size = (long)(offset - sym.Offset);

            /* Output signature table if any */
            if (data_sect == null)
            {
                data_sect = of.GetDataSection();
            }
            s.sigt.WriteToOutput(of, base_m, t, data_sect);
        }