/* 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); }