private static void AddBaseType(IList <byte> d, TypeSpec ts, IBinaryFile of, ISection os, ref ulong offset, Target t, TysilaState s) { if (ts.other != null && ts.stype != TypeSpec.SpecialType.Boxed) { var bt = ts.other.Box; 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 = bt.MangleType(); ext_reloc.References = ext_sym; of.AddRelocation(ext_reloc); s.r.VTableRequestor.Request(bt); } for (int i = 0; i < t.GetPointerSize(); i++, offset++) { d.Add(0); } }
private static void OutputVirtualMethods(TypeSpec decl_ts, IBinaryFile of, ISection os, IList <byte> d, ref ulong offset, target.Target t, TysilaState s) { var vmeths = GetVirtualMethodDeclarations(decl_ts); ImplementVirtualMethods(decl_ts, vmeths); foreach (var vmeth in vmeths) { var impl_ms = vmeth.impl_meth; string impl_target = (impl_ms == null) ? "__cxa_pure_virtual" : impl_ms.MethodReferenceAlias; var impl_sym = of.CreateSymbol(); impl_sym.Name = impl_target; impl_sym.ObjectType = SymbolObjectType.Function; var impl_reloc = of.CreateRelocation(); impl_reloc.Addend = 0; impl_reloc.DefinedIn = os; impl_reloc.Offset = offset; impl_reloc.References = impl_sym; impl_reloc.Type = t.GetDataToCodeReloc(); of.AddRelocation(impl_reloc); for (int i = 0; i < t.GetPointerSize(); i++, offset++) { d.Add(0); } if (impl_ms != null) { s.r.MethodRequestor.Request(impl_ms); } } }
// TODO: Use ImplementInterface private static void OutputInterface(TypeSpec impl_ts, TypeSpec iface_ts, IBinaryFile of, ISection os, IList <byte> d, ref ulong offset, Target t, TysilaState s) { bool is_boxed = false; if (impl_ts.IsBoxed) { impl_ts = impl_ts.Unbox; is_boxed = true; /* 'boxed' versions of each method should unbox the * first parameter to a managed pointer then call * the acutal method */ } /* Iterate through methods */ var first_mdef = iface_ts.m.GetIntEntry(MetadataStream.tid_TypeDef, iface_ts.tdrow, 5); var last_mdef = iface_ts.m.GetLastMethodDef(iface_ts.tdrow); for (uint mdef_row = first_mdef; mdef_row < last_mdef; mdef_row++) { MethodSpec iface_ms; MethodSpec impl_ms = null; iface_ts.m.GetMethodDefRow(MetadataStream.tid_MethodDef, (int)mdef_row, out iface_ms, iface_ts.gtparams, null); iface_ms.type = iface_ts; // First determine if there is a relevant MethodImpl entry for (int i = 1; i <= impl_ts.m.table_rows[MetadataStream.tid_MethodImpl]; i++) { var Class = impl_ts.m.GetIntEntry(MetadataStream.tid_MethodImpl, i, 0); if (Class == impl_ts.tdrow) { int mdecl_id, mdecl_row, mbody_id, mbody_row; impl_ts.m.GetCodedIndexEntry(MetadataStream.tid_MethodImpl, i, 2, impl_ts.m.MethodDefOrRef, out mdecl_id, out mdecl_row); MethodSpec mdecl_ms; impl_ts.m.GetMethodDefRow(mdecl_id, mdecl_row, out mdecl_ms, impl_ts.gtparams); if (mdecl_ms.Equals(iface_ms)) { impl_ts.m.GetCodedIndexEntry(MetadataStream.tid_MethodImpl, i, 1, impl_ts.m.MethodDefOrRef, out mbody_id, out mbody_row); impl_ts.m.GetMethodDefRow(mbody_id, mbody_row, out impl_ms, impl_ts.gtparams); impl_ms.type = impl_ts; break; } } } // Then iterate through all base classes looking for an implementation if (impl_ms == null) { impl_ms = GetVirtualMethod(impl_ts, iface_ms, t, true); } if (iface_ms.MangleMethod().StartsWith("_ZW30System#2ECollections#2EGeneric13IEnumerable`1_G1") && impl_ts.stype == TypeSpec.SpecialType.SzArray) { // Special case this so we get the generic IEnumerator<T> rather than the standard IEnumator from System.Array.GetEnumerator // coreclr does something similar for _all_ T[] methods (see https://github.com/dotnet/coreclr/blob/release/2.0.0/src/mscorlib/src/System/Array.cs#L2577) var szarrayhelper = iface_ms.m.GetTypeSpec("System", "SZArrayHelper"); var genum_ms = iface_ms.m.GetMethodSpec(szarrayhelper, "GetEnumerator"); genum_ms.gmparams = new TypeSpec[] { impl_ts.other }; s.r.MethodRequestor.Request(genum_ms); impl_ms = genum_ms; } // Vectors implement methods which we need to provide if (impl_ms == null && impl_ts.stype == TypeSpec.SpecialType.SzArray) { // Build a new method that is based in the vector class impl_ms = iface_ms; impl_ms.type = new TypeSpec { m = impl_ts.m, tdrow = impl_ts.tdrow, stype = impl_ts.stype, other = impl_ts.other, gtparams = iface_ms.type.gtparams }; } if (impl_ms != null) { if (impl_ms.ReturnType != null && impl_ms.ReturnType.IsValueType && t.NeedsBoxRetType(impl_ms) && (iface_ms.ReturnType == null || (iface_ms.ReturnType != null && !iface_ms.ReturnType.IsValueType))) { impl_ms = impl_ms.Clone(); impl_ms.ret_type_needs_boxing = true; s.r.BoxedMethodRequestor.Request(impl_ms); } else if (is_boxed) { impl_ms.is_boxed = true; s.r.BoxedMethodRequestor.Request(impl_ms); } else { s.r.MethodRequestor.Request(impl_ms); } } // Output reference string impl_target = (impl_ms == null) ? "__cxa_pure_virtual" : impl_ms.MangleMethod(); //if(impl_ms == null) //{ // System.Diagnostics.Debugger.Break(); // var test = GetVirtualMethod(impl_ts, iface_ms, t, true); //} var impl_sym = of.CreateSymbol(); impl_sym.Name = impl_target; impl_sym.ObjectType = SymbolObjectType.Function; var impl_reloc = of.CreateRelocation(); impl_reloc.Addend = 0; impl_reloc.DefinedIn = os; impl_reloc.Offset = offset; impl_reloc.References = impl_sym; impl_reloc.Type = t.GetDataToCodeReloc(); of.AddRelocation(impl_reloc); for (int i = 0; i < t.GetPointerSize(); i++, offset++) { d.Add(0); } } }
public unsafe override bool AssembleJitStub(MethodSpec ms, Target t, IBinaryFile bf, TysilaState s) { var tsect = bf.GetTextSection(); var mname = ms.MangleMethod(); // Align to 16 byte boundary while ((tsect.Data.Count & 0xf) != 0) { tsect.Data.Add(0); } // First comes a pointer to the MethodSpec for this type, followed by a state flag (starts at 0) var ms_ptr = libsupcs.CastOperations.ReinterpretAsUlong(ms); var ms_ptr_b = BitConverter.GetBytes(ms_ptr); foreach (var bi in ms_ptr_b) { tsect.Data.Add(bi); } for (int i = 0; i < 8; i++) { tsect.Data.Add(0); } // Add symbol var sym = bf.CreateSymbol(); sym.Name = mname; sym.ObjectType = SymbolObjectType.Function; sym.Offset = (ulong)tsect.Data.Count; sym.Type = SymbolType.Weak; tsect.AddSymbol(sym); // The code here comes from libtysila5/target/x86/x86_64-jitstub.asm var b = new byte[] { 0x83, 0x3d, 0xf1, 0xff, 0xff, 0xff, 0x02, 0x74, 0x58, 0x57, 0x48, 0xc7, 0xc7, 0x01, 0x00, 0x00, 0x00, 0x31, 0xc0, 0xf0, 0x0f, 0xb1, 0x3d, 0xdd, 0xff, 0xff, 0xff, 0x83, 0xf8, 0x01, 0x7c, 0x06, 0x7f, 0x3e, 0xf3, 0x90, 0xeb, 0xeb, 0x56, 0x52, 0x51, 0x41, 0x50, 0x41, 0x51, 0x41, 0x52, 0x41, 0x53, 0x48, 0x8b, 0x3d, 0xb8, 0xff, 0xff, 0xff, 0x48, 0xb8 }; foreach (var bi in b) { tsect.Data.Add(bi); } // Next comes the 64-bit address of jit_tm var jit_tm_addr = libsupcs.CastOperations.ReinterpretAs <ulong>(libsupcs.OtherOperations.GetFunctionAddress("jit_tm")); var jit_tm_addr_b = BitConverter.GetBytes(jit_tm_addr); foreach (var bi in jit_tm_addr_b) { tsect.Data.Add(bi); } // Continue with the rest of the function b = new byte[] { 0xff, 0xd0, 0x41, 0x5b, 0x41, 0x5a, 0x41, 0x59, 0x41, 0x58, 0x59, 0x5a, 0x5e, 0x48, 0x89, 0x05, 0x9a, 0xff, 0xff, 0xff, 0xc7, 0x05, 0x98, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, 0x5f, 0xff, 0x25, 0x89, 0xff, 0xff, 0xff }; foreach (var bi in b) { tsect.Data.Add(bi); } return(true); }