Example #1
0
        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);
        }
Example #2
0
        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;
                }
            }
        }
Example #3
0
        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);
        }
Example #4
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);
        }
Example #5
0
        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);
            }
        }
Example #6
0
        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);
            }
        }
Example #7
0
 public abstract bool AssembleJitStub(metadata.MethodSpec ms, libtysila5.target.Target t,
                                      binary_library.IBinaryFile bf, libtysila5.TysilaState s);