public override object Invoke(object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] parameters, System.Globalization.CultureInfo culture) { uint flags = 0; if (MethodAddress == null) { var mangled_name = mspec.MangleMethod(); System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosMethod.Invoke: requesting run-time address for " + mangled_name); MethodAddress = JitOperations.GetAddressOfObject(mspec.MangleMethod()); if (MethodAddress == null) { System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosMethod.Invoke: jit compiling method"); MethodAddress = JitOperations.JitCompile(this.mspec); } } if (MethodAddress == null) { throw new System.Reflection.TargetException("Method does not have a defined implementation (" + OwningType.FullName + "." + Name + "())"); } if (!IsStatic && (obj == null)) { throw new System.Reflection.TargetException("Instance method and obj is null (" + OwningType.FullName + "." + Name + "())"); } // TODO: check number and type of parameters is what the method expects // Get total number of parameters int p_length = 0; if (parameters != null) { p_length = parameters.Length; } if (!IsStatic) { p_length++; } // See InternalStrCpy for the rationale here int max_stack_alloc = p_length > 512 ? 512 : p_length; IntPtr *pstack = stackalloc IntPtr[max_stack_alloc]; IntPtr *tstack = stackalloc IntPtr[max_stack_alloc]; void **ps, ts; if (max_stack_alloc <= 512) { ps = (void **)pstack; ts = (void **)tstack; } else { ps = (void **)MemoryOperations.GcMalloc(p_length * sizeof(void *)); ts = (void **)MemoryOperations.GcMalloc(p_length * sizeof(void *)); } // Build a new params array to include obj if necessary, and a tysos type array int curptr = 0; if (!IsStatic) { ps[0] = CastOperations.ReinterpretAsPointer(obj); ts[0] = OtherOperations.GetStaticObjectAddress("_Zu1O"); curptr++; } if (parameters != null) { for (int i = 0; i < parameters.Length; i++, curptr++) { var cp = CastOperations.ReinterpretAsPointer(parameters[i]); ps[curptr] = cp; ts[curptr] = *(void **)cp; } } if (!IsStatic) { flags |= invoke_flag_instance; } if (OwningType.IsValueType) { flags |= invoke_flag_vt; } if (ReturnType != null && ReturnType.IsValueType) { flags |= invoke_flag_vt_ret; } return(CastOperations.ReinterpretAsObject(InternalInvoke(MethodAddress, p_length, ps, ts, (ReturnType != null) ? TysosType.ReinterpretAsType(ReturnType)._impl : null, flags))); }
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); } }