public int GetStringAddress(string s, target.Target t) { if (str_addrs.ContainsKey(s)) { return(str_addrs[s]); } else { var ptr_size = t.GetCTSize(ir.Opcode.ct_object); while (str_tab.Count % ptr_size != 0) { str_tab.Add(0); } int ret = str_tab.Count; str_addrs.Add(s, ret); //int string_obj_len = layout.Layout.GetTypeSize(StringObject, // t, false); //int string_type_offset = int i = 0; for (; i < length_offset; i++) { str_tab.Add(0); } int len = s.Length; str_tab.Add((byte)(len & 0xff)); str_tab.Add((byte)((len >> 8) & 0xff)); str_tab.Add((byte)((len >> 16) & 0xff)); str_tab.Add((byte)((len >> 24) & 0xff)); i += 4; for (; i < string_obj_len; i++) { str_tab.Add(0); } foreach (char c in s) { str_tab.Add((byte)(c & 0xff)); str_tab.Add((byte)((c >> 8) & 0xff)); } // null-terminate and align up to ensure coreclr String.EqualsHelper works str_tab.Add(0); str_tab.Add(0); while ((str_tab.Count % t.GetPointerSize()) != 0) { str_tab.Add(0); } return(ret); } }
public void WriteToOutput(binary_library.IBinaryFile of, metadata.MetadataStream ms, target.Target t, binary_library.ISection rd = null) { if (str_tab.Count == 0) { return; } if (rd == null) { rd = of.GetRDataSection(); } rd.Align(t.GetCTSize(ir.Opcode.ct_object)); var stab_lab = of.CreateSymbol(); stab_lab.Name = Label; stab_lab.ObjectType = binary_library.SymbolObjectType.Object; stab_lab.Offset = (ulong)rd.Data.Count; stab_lab.Type = binary_library.SymbolType.Weak; rd.AddSymbol(stab_lab); int stab_base = rd.Data.Count; foreach (byte b in str_tab) { rd.Data.Add(b); } foreach (var kvp in sig_metadata_addrs) { var reloc = of.CreateRelocation(); reloc.DefinedIn = rd; reloc.Type = t.GetDataToDataReloc(); reloc.Addend = 0; if (sig_metadata_addends.ContainsKey(kvp.Key)) { reloc.Addend = sig_metadata_addends[kvp.Key]; } var md_lab = of.CreateSymbol(); md_lab.Name = kvp.Value; md_lab.ObjectType = binary_library.SymbolObjectType.Object; reloc.References = md_lab; reloc.Offset = (ulong)(kvp.Key + stab_base); of.AddRelocation(reloc); } stab_lab.Size = rd.Data.Count - (int)stab_lab.Offset; }
private void AddFieldSpecFields(MethodSpec fs, List <byte> str_tab, target.Target t, TysilaState s) { /* Field specs have two special fields: * * IntPtr field_size * IntPtr field_data * * where field_data may be null if no .data member is specified for the field */ // read field signature to get the type of the field var sig_idx = fs.msig; sig_idx = fs.m.GetFieldSigTypeIndex(sig_idx); var ts = fs.m.GetTypeSpec(ref sig_idx, fs.gtparams, null); var fsize = t.GetSize(ts); str_tab.AddRange(t.IntPtrArray(BitConverter.GetBytes(fsize))); // now determine if the field has an rva associated with it int rva_id = 0; for (int i = 1; i <= fs.m.table_rows[MetadataStream.tid_FieldRVA]; i++) { var field_idx = fs.m.GetIntEntry(MetadataStream.tid_FieldRVA, i, 1); if (field_idx == fs.mdrow) { rva_id = i; break; } } // rva id if (rva_id != 0) { // TODO checks in CIL II 22.18 var rva = fs.m.GetIntEntry(MetadataStream.tid_FieldRVA, rva_id, 0); var offset = fs.m.ResolveRVA(rva); sig_metadata_addrs[str_tab.Count] = fs.m.AssemblyName; sig_metadata_addends[str_tab.Count] = offset; } for (int i = 0; i < t.psize; i++) { str_tab.Add(0); } }
public StringTable(string mod_name, metadata.AssemblyLoader al, target.Target t) { Label = mod_name + "_StringTable"; var corlib = al.GetAssembly("mscorlib"); StringObject = corlib.GetTypeSpec("System", "String"); var fs_len = corlib.GetFieldDefRow("m_stringLength", StringObject); length_offset = layout.Layout.GetFieldOffset(StringObject, fs_len, t, out var is_tls); var fs_start = corlib.GetFieldDefRow("m_firstChar", StringObject); string_obj_len = layout.Layout.GetFieldOffset(StringObject, fs_start, t, out is_tls); }
public int GetSignatureAddress(metadata.TypeSpec.FullySpecSignature sig, target.Target t, TysilaState s) { var ptr_size = t.GetCTSize(ir.Opcode.ct_object); while (str_tab.Count % ptr_size != 0) { str_tab.Add(0); } int ret = str_tab.Count; // first is type of signature str_tab.AddRange(t.IntPtrArray(BitConverter.GetBytes((int)sig.Type))); // then any extra data if necessary switch (sig.Type) { case metadata.Spec.FullySpecSignature.FSSType.Field: // For fields with static data we insert it here AddFieldSpecFields(sig.OriginalSpec as MethodSpec, str_tab, t, s); break; case Spec.FullySpecSignature.FSSType.Type: AddTypeSpecFields(sig.OriginalSpec as TypeSpec, str_tab, t, s); break; } // then is length of module references str_tab.AddRange(t.IntPtrArray(BitConverter.GetBytes(sig.Modules.Count))); // then module references foreach (var mod in sig.Modules) { sig_metadata_addrs[str_tab.Count] = mod.AssemblyName; for (int i = 0; i < ptr_size; i++) { str_tab.Add(0); } } // then signature str_tab.AddRange(sig.Signature); return(ret); }
public int GetSignatureAddress(IEnumerable <byte> sig, target.Target t, TysilaState s) { var ptr_size = t.GetCTSize(ir.Opcode.ct_object); while (str_tab.Count % ptr_size != 0) { str_tab.Add(0); } int ret = str_tab.Count; foreach (byte b in sig) { str_tab.Add(b); } return(ret); }
public void WriteToOutput(binary_library.IBinaryFile of, metadata.MetadataStream ms, target.Target t) { var rd = of.GetRDataSection(); rd.Align(t.GetCTSize(ir.Opcode.ct_object)); var stab_lab = GetStringTableSymbol(of); stab_lab.Name = Label; stab_lab.ObjectType = binary_library.SymbolObjectType.Object; stab_lab.Offset = (ulong)rd.Data.Count; stab_lab.Type = binary_library.SymbolType.Global; rd.AddSymbol(stab_lab); int stab_base = rd.Data.Count; foreach (byte b in str_tab) { rd.Data.Add(b); } var str_lab = of.CreateSymbol(); str_lab.Name = StringObject.m.MangleType(StringObject); str_lab.ObjectType = binary_library.SymbolObjectType.Object; foreach (var str_addr in str_addrs.Values) { var reloc = of.CreateRelocation(); reloc.DefinedIn = rd; reloc.Type = t.GetDataToDataReloc(); reloc.Addend = 0; reloc.References = str_lab; reloc.Offset = (ulong)(str_addr + stab_base); of.AddRelocation(reloc); } stab_lab.Size = rd.Data.Count - (int)stab_lab.Offset; }
public static bool AssembleBoxedMethod(metadata.MethodSpec ms, binary_library.IBinaryFile bf, target.Target t, TysilaState s, StringBuilder debug_passes = null, binary_library.ISection ts = null) { if (ts == null) { ts = bf.GetTextSection(); } s.bf = bf; s.text_section = ts; // Symbol List <binary_library.ISymbol> meth_syms = new List <binary_library.ISymbol>(); var mangled_name = ms.MangleMethod(); var meth_sym = bf.CreateSymbol(); meth_sym.Name = mangled_name; meth_sym.ObjectType = binary_library.SymbolObjectType.Function; meth_sym.Offset = (ulong)ts.Data.Count; meth_sym.Type = binary_library.SymbolType.Weak; ts.AddSymbol(meth_sym); meth_syms.Add(meth_sym); Code c = ms.ret_type_needs_boxing ? t.AssembleBoxRetTypeMethod(ms, s) : t.AssembleBoxedMethod(ms, s); c.t = t; t.AssemblePass(c); foreach (var sym in meth_syms) { sym.Size = ts.Data.Count - (int)sym.Offset; } DumpDebug(debug_passes, meth_syms, c); return(true); }
public static bool AssembleMethod(metadata.MethodSpec ms, binary_library.IBinaryFile bf, target.Target t, TysilaState s, StringBuilder debug_passes = null, MetadataStream base_m = null, Code code_override = null, binary_library.ISection ts = null, binary_library.ISection data_sect = null, dwarf.DwarfCU dcu = null) { if (ms.ret_type_needs_boxing) { throw new Exception("AssembleMethod called for box rettype stub - use AssembleBoxedMethod instead"); } if (ms.is_boxed) { throw new Exception("AssembleMethod called for boxed method - use AssembleBoxedMethod instead"); } if (ts == null) { ts = bf.GetTextSection(); } s.bf = bf; s.text_section = ts; binary_library.SymbolType sym_st = binary_library.SymbolType.Global; var csite = ms.msig; var mdef = ms.mdrow; var m = ms.m; /* Don't compile if not for this architecture */ if (!t.IsMethodValid(ms)) { return(false); } // Get method RVA, don't compile if no body var rva = m.GetIntEntry(metadata.MetadataStream.tid_MethodDef, mdef, 0); // New signature table s.sigt = new SignatureTable(ms.MangleMethod()); /* Is this an array method? */ if (rva == 0 && ms.type != null && ms.type.stype == TypeSpec.SpecialType.Array && code_override == null) { if (ms.name_override == "Get") { code_override = ir.ConvertToIR.CreateArrayGet(ms, t, s); } else if (ms.name_override == ".ctor") { // there are two constructors, choose the correct one var pcount = ms.m.GetMethodDefSigParamCount(ms.msig); if (pcount == ms.type.arr_rank) { code_override = ir.ConvertToIR.CreateArrayCtor1(ms, t, s); } else if (pcount == 2 * ms.type.arr_rank) { code_override = ir.ConvertToIR.CreateArrayCtor2(ms, t, s); } else { throw new NotSupportedException("Invalid number of parameters to " + ms.MangleMethod() + " for array of rank " + ms.type.arr_rank.ToString()); } } else if (ms.name_override == "Set") { code_override = ir.ConvertToIR.CreateArraySet(ms, t, s); } else if (ms.name_override == "Address") { code_override = ir.ConvertToIR.CreateArrayAddress(ms, t, s); } else { throw new NotImplementedException(ms.name_override); } sym_st = binary_library.SymbolType.Weak; } /* Is this a vector method? */ if (rva == 0 && ms.type != null && ms.type.stype == TypeSpec.SpecialType.SzArray && code_override == null) { if (ms.Name == "IndexOf") { code_override = ir.ConvertToIR.CreateVectorIndexOf(ms, t, s); } else if (ms.Name == "Insert") { code_override = ir.ConvertToIR.CreateVectorInsert(ms, t, s); } else if (ms.Name == "RemoveAt") { code_override = ir.ConvertToIR.CreateVectorRemoveAt(ms, t, s); } else if (ms.Name == "get_Item") { code_override = ir.ConvertToIR.CreateVectorget_Item(ms, t, s); } else if (ms.Name == "set_Item") { code_override = ir.ConvertToIR.CreateVectorset_Item(ms, t, s); } else if (ms.Name == "get_Count") { code_override = ir.ConvertToIR.CreateVectorget_Count(ms, t, s); } else if (ms.Name == "CopyTo") { code_override = ir.ConvertToIR.CreateVectorCopyTo(ms, t, s); } /*else if (ms.Name == "GetEnumerator") * code_override = ir.ConvertToIR.CreateVectorGetEnumerator(ms, t);*/ else if (ms.Name == "Add" || ms.Name == "Clear" || ms.Name == "Contains" || ms.Name == "Remove" || ms.Name == "get_IsReadOnly" || ms.Name == "get_IsSynchronized" || ms.Name == "get_SyncRoot" || ms.Name == "get_IsFixedSize" || ms.Name == "Clone" || ms.Name == "CompareTo" || ms.Name == "GetHashCode" || ms.Name == "Equals") { code_override = ir.ConvertToIR.CreateVectorUnimplemented(ms, t, s); } else { return(false); } sym_st = binary_library.SymbolType.Weak; } if (rva == 0 && code_override == null) { return(false); } // Get mangled name for defining a symbol List <binary_library.ISymbol> meth_syms = new List <binary_library.ISymbol>(); var mangled_name = m.MangleMethod(ms); var meth_sym = bf.CreateSymbol(); meth_sym.Name = mangled_name; meth_sym.ObjectType = binary_library.SymbolObjectType.Function; meth_sym.Offset = (ulong)ts.Data.Count; meth_sym.Type = binary_library.SymbolType.Global; ts.AddSymbol(meth_sym); meth_syms.Add(meth_sym); foreach (var alias in ms.MethodAliases) { var alias_sym = bf.CreateSymbol(); alias_sym.Name = alias; alias_sym.ObjectType = binary_library.SymbolObjectType.Function; alias_sym.Offset = (ulong)ts.Data.Count; alias_sym.Type = binary_library.SymbolType.Global; ts.AddSymbol(alias_sym); meth_syms.Add(alias_sym); } if (ms.HasCustomAttribute("_ZN14libsupcs#2Edll8libsupcs20WeakLinkageAttribute_7#2Ector_Rv_P1u1t")) { sym_st = binary_library.SymbolType.Weak; } if (base_m != null && ms.m != base_m) { sym_st = binary_library.SymbolType.Weak; } foreach (var sym in meth_syms) { sym.Type = sym_st; } // Get signature if not specified if (csite == 0) { csite = (int)m.GetIntEntry(metadata.MetadataStream.tid_MethodDef, mdef, 4); } Code cil; if (code_override == null) { var meth = m.GetRVA(rva); var flags = meth.ReadByte(0); int max_stack = 0; long code_size = 0; long lvar_sig_tok = 0; int boffset = 0; List <metadata.ExceptionHeader> ehdrs = null; bool has_exceptions = false; if ((flags & 0x3) == 0x2) { // Tiny header code_size = flags >> 2; max_stack = 8; boffset = 1; } else if ((flags & 0x3) == 0x3) { // Fat header uint fat_flags = meth.ReadUShort(0) & 0xfffU; int fat_hdr_len = (meth.ReadUShort(0) >> 12) * 4; max_stack = meth.ReadUShort(2); code_size = meth.ReadUInt(4); lvar_sig_tok = meth.ReadUInt(8); boffset = fat_hdr_len; if ((flags & 0x8) == 0x8) { has_exceptions = true; ehdrs = new List <metadata.ExceptionHeader>(); int ehdr_offset = boffset + (int)code_size; ehdr_offset = util.util.align(ehdr_offset, 4); while (true) { int kind = meth.ReadByte(ehdr_offset); if ((kind & 0x1) != 0x1) { throw new Exception("Invalid exception header"); } bool is_fat = false; if ((kind & 0x40) == 0x40) { is_fat = true; } int data_size = meth.ReadInt(ehdr_offset); data_size >>= 8; if (is_fat) { data_size &= 0xffffff; } else { data_size &= 0xff; } int clause_count; if (is_fat) { clause_count = (data_size - 4) / 24; } else { clause_count = (data_size - 4) / 12; } ehdr_offset += 4; for (int i = 0; i < clause_count; i++) { var ehdr = ParseExceptionHeader(meth, ref ehdr_offset, is_fat, ms); ehdr.EhdrIdx = i; ehdrs.Add(ehdr); } if ((kind & 0x80) != 0x80) { break; } } } } else { throw new Exception("Invalid method header flags"); } /* Parse CIL code */ cil = libtysila5.cil.CilParser.ParseCIL(meth, ms, boffset, (int)code_size, lvar_sig_tok, has_exceptions, ehdrs); cil.s = s; /* Allocate local vars and args */ t.AllocateLocalVarsArgs(cil); /* Convert to IR */ cil.t = t; ir.ConvertToIR.DoConversion(cil); } else { cil = code_override; } /* Allocate registers */ ir.AllocRegs.DoAllocation(cil); /* Choose instructions */ target.ChooseInstructions.DoChoosing(cil); t.AssemblePass(cil); //((target.x86.x86_Assembler)cil.t).AssemblePass(cil); foreach (var sym in meth_syms) { sym.Size = ts.Data.Count - (int)sym.Offset; } foreach (var extra_sym in cil.extra_labels) { var esym = bf.CreateSymbol(); esym.Name = extra_sym.Name; esym.ObjectType = binary_library.SymbolObjectType.Function; esym.Offset = (ulong)extra_sym.Offset; esym.Type = sym_st; ts.AddSymbol(esym); } /* Dump debug */ DumpDebug(debug_passes, meth_syms, cil); /* Signature table */ if (data_sect == null) { data_sect = bf.GetDataSection(); } s.sigt.WriteToOutput(bf, ms.m, t, data_sect); /* DWARF output */ if (dcu != null) { var ddie = dcu.GetMethodDie(ms); ddie.sym = meth_syms[0]; ddie.cil = cil; var ddts = dcu.GetTypeDie(ms.type) as dwarf.DwarfParentDIE; ddts.Children.Add(ddie); if (ms.ReturnType != null) { dcu.GetTypeDie(ms.ReturnType); if (ms.ReturnType.stype == TypeSpec.SpecialType.None && !ms.ReturnType.IsValueType) { dcu.GetTypeDie(ms.ReturnType.Pointer); } } foreach (var la in cil.la_types) { dcu.GetTypeDie(la); if (la.stype == TypeSpec.SpecialType.None && !la.IsValueType) { dcu.GetTypeDie(la.Pointer); } } foreach (var lv in cil.lv_types) { dcu.GetTypeDie(lv); if (lv.stype == TypeSpec.SpecialType.None && !lv.IsValueType) { dcu.GetTypeDie(lv.Pointer); } } if (!ms.IsStatic) { dcu.GetTypeDie(ms.type.Pointer); } // do we have source lines? if (ms.m.pdb != null && ms.mdrow > 0) { var sps = ms.m.pdb.DebugGetSeqPtForMDRow(ms.mdrow); if (sps != null && cil.cil != null && cil.cil.Count > 0) { /* Start building a Line Number Program * * We follow the example in DWARF4 D.5 (p251), with a few changes * * header - defined per CU * - add this/these source files to it if necessary * * DW_LNE_set_address - psize 0s, reloc to mangled name * DW_LNS_advance_pc - mc_offset of first cil instruction * DW_LNS_set_prologue_end * DW_LNS_set_file - source file * SPECIAL(0,0) - add first opcode * SPECIAL(x,y) - add rest of opcodes * DW_LNE_end_sequence * */ string cur_file = null; int cur_line = 1; int cur_mc = 0; int cur_col = 0; var lnp = dcu.lnp; // DW_LNE_set_address lnp.AddRange(new byte[] { 0x00, (byte)(t.psize + 1), 0x02 }); dcu.lnp_relocs.Add(lnp.Count, meth_syms[0]); for (int i = 0; i < t.psize; i++) { lnp.Add(0); } // DW_LNS_advance_pc lnp.Add(0x02); dwarf.DwarfDIE.w(lnp, (uint)cil.cil[0].mc_offset); cur_mc = cil.cil[0].mc_offset; // DW_LNS_set_prologue_end lnp.Add(0x0a); foreach (var cn in cil.cil) { var mc_advance = cn.mc_offset - cur_mc; // get current line number MetadataStream.SeqPt csp = null; foreach (var sp in sps) { if (sp.IlOffset == cn.il_offset & !sp.IsHidden) { csp = sp; break; } } if (csp != null) { var line_advance = csp.StartLine - cur_line; if (ddie.StartLine == 0) { ddie.StartLine = csp.StartLine; } if (ddie.StartColumn == 0) { ddie.StartColumn = csp.StartCol; } if (csp.DocName != cur_file) { // DW_LNS_set_file lnp.Add(0x04); uint file_no; if (!dcu.lnp_files.TryGetValue(csp.DocName, out file_no)) { file_no = (uint)(dcu.lnp_files.Count + 1); dcu.lnp_files[csp.DocName] = file_no; dcu.lnp_fnames.Add(csp.DocName); } if (ddie.SourceFileId == 0) { ddie.SourceFileId = (int)file_no; } dwarf.DwarfDIE.w(lnp, file_no); cur_file = csp.DocName; } if (csp.StartCol != cur_col) { // DW_LNS_set_column lnp.Add(0x05); dwarf.DwarfDIE.w(lnp, (uint)csp.StartCol); cur_col = csp.StartCol; } /* SPECIAL if possible * Use example on DWARF4 p132: * opcode_base = 13, line_base = -3, line_range = 12 * * Gives a line advance range of [-3,8] and op_advance [0,19] */ if ((line_advance >= dcu.line_base && line_advance < (dcu.line_base + dcu.line_range)) && (mc_advance >= 0 && mc_advance < dcu.mc_advance_max)) { var spec_opcode = (line_advance - dcu.line_base) + (dcu.line_range * mc_advance) + dcu.opcode_base; lnp.Add((byte)spec_opcode); } else { // DW_LNS_advance_pc lnp.Add(0x02); dwarf.DwarfDIE.w(lnp, (uint)mc_advance); // DW_LNS_advance_line lnp.Add(0x03); dwarf.DwarfDIE.w(lnp, line_advance); // SPECIAL(0,0) var spec_opcode = (0 - dcu.line_base) + dcu.opcode_base; lnp.Add((byte)spec_opcode); } cur_line += line_advance; cur_mc += mc_advance; } } // Advance to end var to_advance = (int)meth_syms[0].Size - cur_mc; lnp.Add(0x02); dwarf.DwarfDIE.w(lnp, to_advance); // DW_LNE_end_sequence lnp.Add(0x00); lnp.Add(0x01); lnp.Add(0x01); } } } return(true); }