static libtysila5.TysilaState InitTysilaState() { var s = new libtysila5.TysilaState(); s.bf = new JitBinary(bness); s.bf.Init(); s.bf.Architecture = t.name; s.text_section = s.bf.GetTextSection(); var r = new JitRequestor(); s.r = r; /* thread-safe generate new symbol name */ while (true) { int cur_st_id = next_st_id; if (System.Threading.Interlocked.CompareExchange(ref next_st_id, cur_st_id + 2, cur_st_id) == cur_st_id) { s.st = new libtysila5.StringTable("jit" + cur_st_id.ToString(), libsupcs.Metadata.BAL, t); s.sigt = new libtysila5.SignatureTable("jit" + (cur_st_id + 1).ToString()); break; } } return(s); }
public static void ProcessRequestedItems(libtysila5.TysilaState s, SymbolTable stab) { while (!s.r.Empty) { /* TODO: * check each member and process accordingly. * * First need to check it has not already been done or is in progress (need flag member of each type to do this, as well as check symbol table) * - If not in progress/done, remove from requestor, set as in process and do it, then set done * - If in progress, return it to the requestor * - If done, do nothing (already removed) * * Members of MethodRequestor just need a JIT stub creating (TODO) * Members of FullMethodRequestor actually need creating */ while (!s.r.BoxedMethodRequestor.Empty) { var ne = s.r.BoxedMethodRequestor.GetNext(); // Try and set flags to INPROG var f = System.Threading.Interlocked.CompareExchange(ref ne.JitFlags, JF_INPROG, JF_NOTDONE); if (f == JF_DONE) { continue; // Already done } if (f == JF_INPROG) { // return, and skip any more processing of this group (as may just pick this one back up again) s.r.BoxedMethodRequestor.Request(ne); break; } // f was NOTDONE, and has been set to INPROG. TODO: check not in stab (do we need this step?) libtysila5.libtysila.AssembleBoxedMethod(ne.ms, s.bf, Jit.t, s); // set to DONE ne.JitFlags = JF_DONE; } while (!s.r.DelegateRequestor.Empty) { var ne = s.r.DelegateRequestor.GetNext(); // Try and set flags to INPROG var f = System.Threading.Interlocked.CompareExchange(ref ne.JitFlags, JF_INPROG, JF_NOTDONE); if (f == JF_DONE) { continue; // Already done } if (f == JF_INPROG) { // return, and skip any more processing of this group (as may just pick this one back up again) s.r.DelegateRequestor.Request(ne); break; } // f was NOTDONE, and has been set to INPROG. TODO: check not in stab (do we need this step?) libtysila5.ir.ConvertToIR.CreateDelegate(ne, Jit.t, s); // set to DONE ne.JitFlags = JF_DONE; } while (!s.r.EHRequestor.Empty) { var ne = s.r.EHRequestor.GetNext(); // Try and set flags to INPROG var f = System.Threading.Interlocked.CompareExchange(ref ne.JitFlags, JF_INPROG, JF_NOTDONE); if (f == JF_DONE) { continue; // Already done } if (f == JF_INPROG) { // return, and skip any more processing of this group (as may just pick this one back up again) s.r.EHRequestor.Request(ne); break; } // f was NOTDONE, and has been set to INPROG. TODO: check not in stab (do we need this step?) libtysila5.layout.Layout.OutputEHdr(ne, Jit.t, s.bf, s); // set to DONE ne.JitFlags = JF_DONE; } while (!s.r.MethodRequestor.Empty) { var ne = s.r.MethodRequestor.GetNext(); // Try and set flags to INPROG var f = System.Threading.Interlocked.CompareExchange(ref ne.JitFlags, JF_INPROG, JF_NOTDONE); if (f == JF_DONE) { continue; // Already done } if (f == JF_INPROG) { // return, and skip any more processing of this group (as may just pick this one back up again) s.r.MethodRequestor.Request(ne); break; } // f was NOTDONE, and has been set to INPROG. Check not in stab if (stab.GetAddress(ne.ms.MangleMethod()) == 0) { // We need to build a JIT stub here Jit.jsa.AssembleJitStub(ne.ms, Jit.t, s.bf, s); } // set to DONE ne.JitFlags = JF_DONE; } while (!s.r.StaticFieldRequestor.Empty) { var ne = s.r.StaticFieldRequestor.GetNext(); // Try and set flags to INPROG var f = System.Threading.Interlocked.CompareExchange(ref ne.JitFlags, JF_INPROG, JF_NOTDONE); if (f == JF_DONE) { continue; // Already done } if (f == JF_INPROG) { // return, and skip any more processing of this group (as may just pick this one back up again) s.r.StaticFieldRequestor.Request(ne); break; } // f was NOTDONE, and has been set to INPROG. Check not in stab if (stab.GetAddress(ne.MangleType() + "S") == 0) { libtysila5.layout.Layout.OutputStaticFields(ne, Jit.t, s.bf); } // set to DONE ne.JitFlags = JF_DONE; } while (!s.r.VTableRequestor.Empty) { var ne = s.r.VTableRequestor.GetNext(); // Try and set flags to INPROG var f = System.Threading.Interlocked.CompareExchange(ref ne.JitFlags, JF_INPROG, JF_NOTDONE); if (f == JF_DONE) { continue; // Already done } if (f == JF_INPROG) { // return, and skip any more processing of this group (as may just pick this one back up again) s.r.VTableRequestor.Request(ne); break; } // f was NOTDONE, and has been set to INPROG. Check not in stab if (stab.GetAddress(ne.MangleType()) == 0) { libtysila5.layout.Layout.OutputVTable(ne, Jit.t, s.bf, s); } // set to DONE ne.JitFlags = JF_DONE; } while (!((JitRequestor)s.r).FullMethodRequestor.Empty) { var ne = ((JitRequestor)s.r).FullMethodRequestor.GetNext(); // Try and set flags to INPROG var f = System.Threading.Interlocked.CompareExchange(ref ne.JitFlags, JF_INPROG, JF_NOTDONE); if (f == JF_DONE) { continue; // Already done } if (f == JF_INPROG) { // return, and skip any more processing of this group (as may just pick this one back up again) ((JitRequestor)s.r).FullMethodRequestor.Request(ne); break; } // f was NOTDONE, and has been set to INPROG. Check not in stab (and if so, not a stub) var faddr = stab.GetAddress(ne.ms.MangleMethod()); if (faddr == 0 || stab.IsStub(faddr)) { System.Diagnostics.Debugger.Log(0, "jit", "JIT compiling " + ne.ms.MangleMethod()); libtysila5.libtysila.AssembleMethod(ne.ms, s.bf, Jit.t, s); } else { System.Diagnostics.Debugger.Log(0, "jit", "Request to JIT compile " + ne.ms.MangleMethod() + " however already present at " + stab.GetAddress(ne.ms.MangleMethod()).ToString("X16")); } // set to DONE ne.JitFlags = JF_DONE; } } }
static int Main(string[] args) { /* Parse args */ var argc = args.Length; char c; var go = new XGetoptCS.XGetopt(); var arg_str = "t:L:o:"; while ((c = go.Getopt(argc, args, arg_str)) != '\0') { switch (c) { case 't': arch = go.Optarg; break; case 'L': new_search_dirs.Add(go.Optarg); break; case 'o': output_name = go.Optarg; break; case '?': dump_opts(); return(-1); } } tysila4.Program.search_dirs.InsertRange(0, new_search_dirs); var curopt = go.Optind; while (curopt < argc) { input_files.Add(args[curopt++]); } if (input_files.Count == 0) { System.Console.WriteLine("No input files specified"); dump_opts(); return(-1); } /* Load up each input file in turn */ var ifiles = new List <binary_library.IBinaryFile>(); foreach (var ifname in input_files) { var ifinfo = new System.IO.FileInfo(ifname); if (!ifinfo.Exists) { throw new System.IO.FileNotFoundException("Cannot find: " + ifname); } /* Determine file type from extension */ binary_library.IBinaryFile ifobj = null; if (ifinfo.Extension == ".o" || ifinfo.Extension == ".obj") { ifobj = new binary_library.elf.ElfFile(); } if (ifobj == null) { ifobj = binary_library.BinaryFile.CreateBinaryFile(ifinfo.Extension); } if (ifobj == null) { throw new Exception("Unsupported file type: " + ifinfo.FullName); } /* Load up the particular file */ ifobj.Filename = ifinfo.FullName; ifobj.Read(); ifiles.Add(ifobj); } /* Get a list of all defined symbols */ var def_syms = new Dictionary <string, binary_library.ISymbol>(); foreach (var file in ifiles) { var sym_count = file.GetSymbolCount(); for (int i = 0; i < sym_count; i++) { var sym = file.GetSymbol(i); if (sym.DefinedIn != null && sym.Type != binary_library.SymbolType.Undefined) { def_syms[sym.Name] = sym; } } } /* Get a list of those relocations which are missing */ var missing = new Dictionary <string, binary_library.ISymbol>(); foreach (var file in ifiles) { var reloc_count = file.GetRelocationCount(); for (int i = 0; i < reloc_count; i++) { var reloc = file.GetRelocation(i); if (reloc.References != null && !def_syms.ContainsKey(reloc.References.Name)) { if (reloc.References.Name == "_Zu1O_7#2Ector_Rv_P1u1t") { System.Diagnostics.Debugger.Break(); } missing[reloc.References.Name] = reloc.References; } } } /* Generate an output object */ var o = new binary_library.elf.ElfFile(ifiles[0].Bitness); o.Init(); o.Architecture = arch; o.Filename = output_name; /* Generate dummy module */ var ofi = new System.IO.FileInfo(output_name); var ms = new metadata.MetadataStream(ofi.Name.Substring(0, ofi.Name.Length - ofi.Extension.Length)); ms.al = new libtysila5.libtysila.AssemblyLoader(new tysila4.FileSystemFileLoader()); ms.LoadBuiltinTypes(); /* Load up assembler target */ var t = libtysila5.target.Target.targets[arch]; var fsi = new System.IO.FileInfo(output_name); var s = new libtysila5.TysilaState(); s.st = new libtysila5.StringTable(fsi.Name.Substring(0, fsi.Name.Length - fsi.Extension.Length), ms.al, t); /* Generate signature of missing_function(string) to call */ var special_c = new libtysila5.Code { ms = new metadata.MethodSpec { m = ms } }; var special = special_c.special_meths; var missing_msig = special.CreateMethodSignature(null, new metadata.TypeSpec[] { ms.SystemString }); /* Generate stub functions for missing methods */ var m = missing.Keys; var missing_types = new List <string>(); var other_missing = new List <string>(); foreach (var str in m) { try { if (ms.IsMangledMethod(str)) { GenerateMissingMethod(str, ms, t, missing_msig, o, s); } else { ms.IsMangledMethod(str); missing_types.Add(str); } } catch (ArgumentException) { other_missing.Add(str); } } /* Write out */ s.st.WriteToOutput(o, ms, t); o.Write(); /* Dump missing types */ if (missing_types.Count > 0) { Console.WriteLine("Warning: the following missing types were also found:"); foreach (var mt in missing_types) { Console.WriteLine(" " + mt); } } return(0); }
private static void GenerateMissingMethod(string str, metadata.MetadataStream m, libtysila5.target.Target t, int missing_msig, ElfFile o, libtysila5.TysilaState s) { /* Generate new method spec */ var ms = new metadata.MethodSpec { m = m, mangle_override = str }; /* Generate stub code */ libtysila5.Code c = new libtysila5.Code(); c.t = t; c.ms = ms; var ir = new List <libtysila5.cil.CilNode.IRNode>(); var stack = new libtysila5.util.Stack <libtysila5.ir.StackItem>(); var cilnode = new libtysila5.cil.CilNode(ms, 0); cilnode.irnodes = ir; c.ir = ir; c.starts = new List <libtysila5.cil.CilNode> { cilnode }; c.s = s; stack = libtysila5.ir.ConvertToIR.ldstr(cilnode, c, stack, str); stack = libtysila5.ir.ConvertToIR.call(cilnode, c, stack, false, "missing_function", c.special_meths, missing_msig); /* Assemble */ libtysila5.libtysila.AssembleMethod(ms, o, t, s, null, null, c); }
static void Main(string[] args) { var argc = args.Length; char c; var go = new XGetoptCS.XGetopt(); var arg_str = "t:L:f:e:o:d:qDC:H:m:i"; string target = "x86"; string debug_file = null; string output_file = null; string epoint = null; string cfile = null; string hfile = null; bool quiet = false; bool require_metadata_version_match = true; bool interactive = false; string act_epoint = null; Dictionary <string, object> opts = new Dictionary <string, object>(); while ((c = go.Getopt(argc, args, arg_str)) != '\0') { switch (c) { case 't': target = go.Optarg; break; case 'L': new_search_dirs.Add(go.Optarg); break; case 'd': debug_file = go.Optarg; break; case 'o': output_file = go.Optarg; break; case 'e': epoint = go.Optarg; break; case 'q': quiet = true; break; case 'D': require_metadata_version_match = false; break; case 'C': cfile = go.Optarg; break; case 'H': hfile = go.Optarg; break; case 'f': parse_f_option(go); break; case 'i': interactive = true; break; case 'g': do_dwarf = true; break; case 'm': { var opt = go.Optarg; object optval = true; if (opt.Contains("=")) { var optvals = opt.Substring(opt.IndexOf("=") + 1); opt = opt.Substring(0, opt.IndexOf("=")); int intval; if (optvals.ToLower() == "false" || optvals.ToLower() == "off" || optvals.ToLower() == "no") { optval = false; } else if (optvals.ToLower() == "true" || optvals.ToLower() == "on" || optvals.ToLower() == "yes") { optval = true; } else if (int.TryParse(optvals, out intval)) { optval = intval; } else { optval = optvals; } } else if (opt.StartsWith("no-")) { opt = opt.Substring(3); optval = false; } opts[opt] = optval; } break; } } var fname = go.Optarg; if (fname == String.Empty) { Console.WriteLine("No input file specified"); return; } // Insert library directories specified on the command line before the defaults search_dirs.InsertRange(0, new_search_dirs); if (cfile != null && hfile == null) { Console.WriteLine("-H must be used if -C is used"); return; } libtysila5.libtysila.AssemblyLoader al = new libtysila5.libtysila.AssemblyLoader( new FileSystemFileLoader()); /* Load up type forwarders */ foreach (var libdir in search_dirs) { try { var di = new DirectoryInfo(libdir); if (di.Exists) { foreach (var tfw_file in di.GetFiles("*.tfw")) { var tfr = new StreamReader(tfw_file.OpenRead()); while (!tfr.EndOfStream) { var tfr_line = tfr.ReadLine(); var tfr_lsplit = tfr_line.Split('='); al.TypeForwarders[tfr_lsplit[0]] = tfr_lsplit[1]; } tfr.Close(); } } } catch (Exception) { } } //search_dirs.Add(@"..\mono\corlib"); al.RequireVersionMatch = require_metadata_version_match; // add containing directory of input to search dirs var ifi = new FileInfo(fname); search_dirs.Add(ifi.DirectoryName); var m = al.GetAssembly(fname); if (m == null) { Console.WriteLine("Input file " + fname + " not found"); throw new Exception(fname + " not found"); } t = libtysila5.target.Target.targets[target]; // try and set target options foreach (var kvp in opts) { if (!t.Options.TrySet(kvp.Key, kvp.Value)) { Console.WriteLine("Unable to set target option " + kvp.Key + " to " + kvp.Value.ToString()); return; } } if (interactive) { if (new Interactive(m, t).DoInteractive() == false) { return; } } libtysila5.dwarf.DwarfCU dwarf = null; if (do_dwarf) { dwarf = new libtysila5.dwarf.DwarfCU(t, m); } libtysila5.TysilaState s = new libtysila5.TysilaState(); if (output_file != null) { var bf = new binary_library.elf.ElfFile(binary_library.Bitness.Bits32); s.bf = bf; bf.Init(); bf.Architecture = target; var st = new libtysila5.StringTable( m.GetStringEntry(metadata.MetadataStream.tid_Module, 1, 1), al, t); s.st = st; s.r = new libtysila5.CachingRequestor(m); t.InitIntcalls(); /* for now, just assemble all public and protected * non-generic methods in public types, plus the * entry point */ StringBuilder debug = new StringBuilder(); for (int i = 1; i <= m.table_rows[metadata.MetadataStream.tid_MethodDef]; i++) { metadata.MethodSpec ms = new metadata.MethodSpec { m = m, mdrow = i, msig = 0 }; ms.type = new metadata.TypeSpec { m = m, tdrow = m.methoddef_owners[ms.mdrow] }; var mflags = m.GetIntEntry(metadata.MetadataStream.tid_MethodDef, i, 2); var tflags = m.GetIntEntry(metadata.MetadataStream.tid_TypeDef, ms.type.tdrow, 0); mflags &= 0x7; tflags &= 0x7; ms.msig = (int)m.GetIntEntry(metadata.MetadataStream.tid_MethodDef, i, 4); /* See if this is the entry point */ int tid, row; m.InterpretToken(m.entry_point_token, out tid, out row); if (tid == metadata.MetadataStream.tid_MethodDef) { if (row == i) { if (epoint != null) { ms.aliases = new List <string> { epoint } } ; mflags = 6; tflags = 1; ms.AlwaysCompile = true; act_epoint = ms.MangleMethod(); } } /* See if we have an always compile attribute */ if (ms.HasCustomAttribute("_ZN14libsupcs#2Edll8libsupcs22AlwaysCompileAttribute_7#2Ector_Rv_P1u1t") || ms.type.HasCustomAttribute("_ZN14libsupcs#2Edll8libsupcs22AlwaysCompileAttribute_7#2Ector_Rv_P1u1t")) { mflags = 6; tflags = 1; ms.AlwaysCompile = true; } if (ms.type.IsGenericTemplate == false && ms.IsGenericTemplate == false && (mflags == 0x4 || mflags == 0x5 || mflags == 0x6) && tflags != 0) { s.r.MethodRequestor.Request(ms); } } /* Also assemble all public non-generic type infos */ for (int i = 1; i <= m.table_rows[metadata.MetadataStream.tid_TypeDef]; i++) { var flags = (int)m.GetIntEntry(metadata.MetadataStream.tid_TypeDef, i, 0); if (((flags & 0x7) != 0x1) && ((flags & 0x7) != 0x2)) { continue; } var ts = new metadata.TypeSpec { m = m, tdrow = i }; if (ts.IsGeneric) { continue; } s.r.StaticFieldRequestor.Request(ts); s.r.VTableRequestor.Request(ts.Box); } /* If corlib, add in the default equality comparers so we don't have to jit these * commonly used classes */ if (m.is_corlib) { s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemByte }), ".ctor")); s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemInt8 }), ".ctor")); s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemInt16 }), ".ctor")); s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemUInt16 }), ".ctor")); s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemInt32 }), ".ctor")); s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemUInt32 }), ".ctor")); s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemInt64 }), ".ctor")); s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemUInt64 }), ".ctor")); s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemString }), ".ctor")); s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemObject }), ".ctor")); s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemByte })); s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemInt8 })); s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemInt16 })); s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemUInt16 })); s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemInt32 })); s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemUInt32 })); s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemInt64 })); s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemUInt64 })); s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemString })); s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemObject })); } /* Generate a thread-local data section. We may not use it. */ var tlsos = bf.CreateContentsSection(); tlsos.Name = ".tdata"; tlsos.IsAlloc = true; tlsos.IsExecutable = false; tlsos.IsWriteable = true; tlsos.IsThreadLocal = true; while (!s.r.Empty) { if (!s.r.MethodRequestor.Empty) { var ms = s.r.MethodRequestor.GetNext(); ISection tsect = null; ISection datasect = null; if (func_sects && !ms.ms.AlwaysCompile) { tsect = get_decorated_section(bf, bf.GetTextSection(), "." + ms.ms.MangleMethod()); datasect = get_decorated_section(bf, bf.GetDataSection(), "." + ms.ms.MangleMethod() + "_SignatureTable"); } else if (class_sects && !ms.ms.AlwaysCompile) { tsect = get_decorated_section(bf, bf.GetTextSection(), "." + ms.ms.type.MangleType()); datasect = get_decorated_section(bf, bf.GetDataSection(), "." + ms.ms.type.MangleType() + "_SignatureTable"); } libtysila5.libtysila.AssembleMethod(ms.ms, bf, t, s, debug, m, ms.c, tsect, datasect, dwarf); if (!quiet) { Console.WriteLine(ms.ms.m.MangleMethod(ms.ms)); } } else if (!s.r.StaticFieldRequestor.Empty) { var sf = s.r.StaticFieldRequestor.GetNext(); ISection tsect = null; if (data_sects && !sf.AlwaysCompile) { tsect = get_decorated_section(bf, bf.GetDataSection(), "." + sf.MangleType() + "S"); } else if (class_sects && !sf.AlwaysCompile) { tsect = get_decorated_section(bf, bf.GetDataSection(), "." + sf.MangleType() + "S"); } libtysila5.layout.Layout.OutputStaticFields(sf, t, bf, m, tsect, tlsos); if (!quiet) { Console.WriteLine(sf.MangleType() + "S"); } } else if (!s.r.EHRequestor.Empty) { var eh = s.r.EHRequestor.GetNext(); ISection tsect = null; if (func_sects && !eh.ms.AlwaysCompile) { tsect = get_decorated_section(bf, bf.GetRDataSection(), "." + eh.ms.MangleMethod() + "EH"); } else if (class_sects && !eh.ms.AlwaysCompile) { tsect = get_decorated_section(bf, bf.GetRDataSection(), "." + eh.ms.type.MangleType() + "EH"); } libtysila5.layout.Layout.OutputEHdr(eh, t, bf, s, m, tsect); if (!quiet) { Console.WriteLine(eh.ms.MangleMethod() + "EH"); } } else if (!s.r.VTableRequestor.Empty) { var vt = s.r.VTableRequestor.GetNext(); ISection tsect = null; ISection data_sect = null; if (data_sects && !vt.AlwaysCompile) { tsect = get_decorated_section(bf, bf.GetRDataSection(), "." + vt.MangleType()); data_sect = get_decorated_section(bf, bf.GetDataSection(), "." + vt.MangleType() + "_SignatureTable"); } else if (class_sects && !vt.AlwaysCompile) { tsect = get_decorated_section(bf, bf.GetTextSection(), "." + vt.MangleType()); data_sect = get_decorated_section(bf, bf.GetDataSection(), "." + vt.MangleType() + "_SignatureTable"); } libtysila5.layout.Layout.OutputVTable(vt, t, bf, s, m, tsect, data_sect); if (!quiet) { Console.WriteLine(vt.MangleType()); } } else if (!s.r.DelegateRequestor.Empty) { var d = s.r.DelegateRequestor.GetNext(); libtysila5.ir.ConvertToIR.CreateDelegate(d, t, s); if (!quiet) { Console.WriteLine(d.MangleType() + "D"); } } else if (!s.r.BoxedMethodRequestor.Empty) { var bm = s.r.BoxedMethodRequestor.GetNext(); ISection tsect = null; if (func_sects && !bm.ms.AlwaysCompile) { tsect = get_decorated_section(bf, bf.GetTextSection(), "." + bm.ms.MangleMethod()); } else if (class_sects && !bm.ms.AlwaysCompile) { tsect = get_decorated_section(bf, bf.GetTextSection(), "." + bm.ms.type.MangleType()); } libtysila5.libtysila.AssembleBoxedMethod(bm.ms, bf, t, s, debug, tsect); if (!quiet) { Console.WriteLine(bm.ms.MangleMethod()); } } } if (debug_file != null) { string d = debug.ToString(); StreamWriter sw = new StreamWriter(debug_file); sw.Write(d); sw.Close(); } if (tlsos.Length > 0) { bf.AddSection(tlsos); } /* String table */ st.WriteToOutput(bf, m, t); /* Include original metadata */ var rdata = bf.GetRDataSection(); rdata.Align(t.GetPointerSize()); var mdsym = bf.CreateSymbol(); mdsym.Name = m.AssemblyName; mdsym.ObjectType = binary_library.SymbolObjectType.Object; mdsym.Offset = (ulong)rdata.Data.Count; mdsym.Type = binary_library.SymbolType.Global; var len = m.file.GetLength(); mdsym.Size = len; rdata.AddSymbol(mdsym); for (int i = 0; i < len; i++) { rdata.Data.Add(m.file.ReadByte(i)); } var mdsymend = bf.CreateSymbol(); mdsymend.Name = m.AssemblyName + "_end"; mdsymend.ObjectType = binary_library.SymbolObjectType.Object; mdsymend.Offset = (ulong)rdata.Data.Count; mdsymend.Type = binary_library.SymbolType.Global; mdsymend.Size = 0; rdata.AddSymbol(mdsymend); /* Add resource symbol if present */ if (m.GetPEFile().ResourcesSize != 0) { var rsym = bf.CreateSymbol(); rsym.Name = m.AssemblyName + "_resources"; rsym.ObjectType = SymbolObjectType.Object; rsym.Offset = (ulong)m.GetPEFile().ResourcesOffset + mdsym.Offset; rsym.Type = SymbolType.Global; rsym.Size = m.GetPEFile().ResourcesSize; rdata.AddSymbol(rsym); } /* Add comment */ var csect = bf.CreateContentsSection(); csect.IsAlloc = false; csect.IsExecutable = false; csect.IsWriteable = false; csect.Name = ".comment"; var cbytes = Encoding.ASCII.GetBytes(comment); foreach (var cbyte in cbytes) { csect.Data.Add(cbyte); } csect.Data.Add(0); if (act_epoint != null) { var epbytes = Encoding.ASCII.GetBytes("entry: " + act_epoint); foreach (var epbyte in epbytes) { csect.Data.Add(epbyte); } csect.Data.Add(0); } bf.AddSection(csect); /* Add debugger sections */ if (dwarf != null) { var dwarf_sects = new libtysila5.dwarf.DwarfSections(bf); dwarf.WriteToOutput(dwarf_sects); } /* Write output file */ bf.Filename = output_file; bf.Write(); } if (hfile != null) { COutput.WriteHeader(m, t, hfile, cfile); } }
private unsafe static void *CopyToOutput(libtysila5.TysilaState s, int sect_id) { // copy from the JitBinary file to final location, process symbols and relocations var bf = s.bf; var tsect = bf.GetTextSection(); var rsect = bf.GetRDataSection(); var dsect = bf.GetDataSection(); // TODO: ensure these are not garbage collected var rout = (byte *)(void *)gc.gc.Alloc((ulong)rsect.Length); var dout = (byte *)(void *)gc.gc.Alloc((ulong)dsect.Length); var tout = (byte *)(void *)gc.gc.Alloc((ulong)tsect.Length); System.Diagnostics.Debugger.Log(0, "jittest", "rout @ " + ((ulong)rout).ToString("X") + ", length " + rsect.Length.ToString()); System.Diagnostics.Debugger.Log(0, "jittest", "dout @ " + ((ulong)dout).ToString("X") + ", length " + dsect.Length.ToString()); System.Diagnostics.Debugger.Log(0, "jittest", "tout @ " + ((ulong)tout).ToString("X") + ", length " + tsect.Length.ToString()); for (var i = 0; i < rsect.Length; i++) { rout[i] = rsect.Data[i]; } for (var i = 0; i < dsect.Length; i++) { dout[i] = dsect.Data[i]; } for (var i = 0; i < tsect.Length; i++) { tout[i] = tsect.Data[i]; } // Add symbols for (var i = 0; i < bf.GetSymbolCount(); i++) { var cur_sym = bf.GetSymbol(i); if (cur_sym.DefinedIn != null) { byte *addr = null; if (cur_sym.DefinedIn == dsect) { addr = cur_sym.Offset + dout; Program.stab.Add(cur_sym.Name, (ulong)addr, (ulong)cur_sym.Size); } else if (cur_sym.DefinedIn == rsect) { addr = cur_sym.Offset + rout; Program.stab.Add(cur_sym.Name, (ulong)addr, (ulong)cur_sym.Size); } else if (cur_sym.DefinedIn == tsect) { addr = cur_sym.Offset + tout; // JIT Stubs are marked as weak Program.stab.Add(cur_sym.Name, (ulong)addr, (ulong)cur_sym.Size, cur_sym.Type == binary_library.SymbolType.Weak); } if (addr != null) { System.Diagnostics.Debugger.Log(0, "jittest", "Created symbol " + cur_sym.Name + " at " + ((ulong)addr).ToString("X") + "" + " (offset " + cur_sym.Offset.ToString("X") + ")"); } } } var reloc_count = bf.GetRelocationCount(); System.Diagnostics.Debugger.Log(0, "jittest", "Found " + reloc_count.ToString() + " relocs"); for (var i = 0; i < bf.GetRelocationCount(); i++) { var cur_reloc = bf.GetRelocation(i); if (cur_reloc.DefinedIn != null) { byte *addr = null; if (cur_reloc.DefinedIn == dsect) { addr = cur_reloc.Offset + dout; } else if (cur_reloc.DefinedIn == rsect) { addr = cur_reloc.Offset + rout; } else if (cur_reloc.DefinedIn == tsect) { addr = cur_reloc.Offset + tout; } if (addr != null) { var target = cur_reloc.References.Name; var taddr = Program.GetAddressOfObject(target); if (taddr == IntPtr.Zero) { System.Diagnostics.Debugger.Log(0, "test_vtable", "Unable to find target reloc " + target); } else { if (cur_reloc.Type.Type == binary_library.elf.ElfFile.R_X86_64_64) { *((byte **)addr) = (byte *)(taddr) + cur_reloc.Addend; } else { System.Diagnostics.Debugger.Log(0, "test_vtable", "Unsupported reloc type " + cur_reloc.Type.Name); } } } } } switch (sect_id) { case TextSection: return(tout); case RDataSection: return(rout); case DataSection: return(dout); default: return(null); } }
public abstract bool AssembleJitStub(metadata.MethodSpec ms, libtysila5.target.Target t, binary_library.IBinaryFile bf, libtysila5.TysilaState s);