public static bool CreateDelegate(metadata.TypeSpec ts, target.Target t, TysilaState s) { if (delegate_m_target == null) { delegate_m_target = ts.m.GetFieldDefRow("m_target", ts.m.SystemDelegate); if (delegate_m_target == null) { delegate_m_target = ts.m.GetFieldDefRow("_target", ts.m.SystemDelegate); } delegate_method_ptr = ts.m.GetFieldDefRow("method_ptr", ts.m.SystemDelegate); if (delegate_method_ptr == null) { delegate_method_ptr = ts.m.GetFieldDefRow("_methodPtr", ts.m.SystemDelegate); } } // Generate required delegate methods in IR CreateDelegateCtor(ts, t, s); CreateDelegateInvoke(ts, t, s); CreateDelegateBeginInvoke(ts, t, s); CreateDelegateEndInvoke(ts, t, s); return(true); }
public InteractiveTypeSpec(metadata.TypeSpec _ts) { ts = _ts; StringBuilder sb = new StringBuilder(); GetName(ts, sb); Name = sb.ToString(); }
static List <Reg> get_push_list(CilNode.IRNode n, Code c, metadata.MethodSpec call_ms, out metadata.TypeSpec rt, ref Reg dest, out int rct, bool want_return = true) { /* Determine which registers we need to save */ var caller_preserves = c.t.cc_caller_preserves_map[call_ms.CallingConvention]; ulong defined = 0; foreach (var si in n.stack_after) { defined |= si.reg.mask; } foreach (var si in n.stack_before) { defined |= si.reg.mask; } var rt_idx = call_ms.m.GetMethodDefSigRetTypeIndex(call_ms.msig); rt = call_ms.m.GetTypeSpec(ref rt_idx, call_ms.gtparams, call_ms.gmparams); rct = ir.Opcode.ct_unknown; if (rt != null && want_return) { defined &= ~n.stack_after.Peek().reg.mask; if (dest == null) { dest = n.stack_after.Peek().reg; } rct = ir.Opcode.GetCTFromType(rt); } var to_push = new util.Set(); to_push.Union(defined); to_push.Intersect(caller_preserves); List <Reg> push_list = new List <Reg>(); while (!to_push.Empty) { var first_set = to_push.get_first_set(); push_list.Add(c.t.regs[first_set]); to_push.unset(first_set); } return(push_list); }
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 static int GetTypeSize(metadata.TypeSpec ts, target.Target t, bool is_static = false) { switch (ts.stype) { case TypeSpec.SpecialType.None: if (ts.Equals(ts.m.SystemRuntimeTypeHandle) || ts.Equals(ts.m.SystemRuntimeMethodHandle) || ts.Equals(ts.m.SystemRuntimeFieldHandle)) { return(is_static ? 0 : (t.GetPointerSize())); } if (ts.m.classlayouts[ts.tdrow] != 0 && ts.IsGeneric == false && ts.IsGenericTemplate == false) { var size = ts.m.GetIntEntry(metadata.MetadataStream.tid_ClassLayout, ts.m.classlayouts[ts.tdrow], 1); if (size != 0) { return((int)size); } } return(GetFieldOffset(ts, (string)null, t, out var is_tls, is_static)); case TypeSpec.SpecialType.SzArray: case TypeSpec.SpecialType.Array: if (is_static) { return(0); } return(GetArrayObjectSize(t)); case TypeSpec.SpecialType.Boxed: if (is_static) { return(0); } return(GetTypeSize(ts.m.SystemObject, t) + GetTypeSize(ts.Unbox, t)); default: throw new NotImplementedException(); } }
public static int GetVTableOffset(metadata.TypeSpec ts, metadata.MethodSpec ms, Target t) { var vtbl = GetVirtualMethodDeclarations(ts); var search_meth_name = ms.m.GetIntEntry(MetadataStream.tid_MethodDef, ms.mdrow, 3); // find the requested method, match on name, signature and declaring type for (int i = 0; i < vtbl.Count; i++) { var test = vtbl[i]; var mdecl = test.unimpl_meth; if (mdecl.type.Equals(ts)) { // Check on name var mname = mdecl.m.GetIntEntry(MetadataStream.tid_MethodDef, mdecl.mdrow, 3); if (MetadataStream.CompareString(mdecl.m, mname, ms.m, search_meth_name)) { // Check on signature if (MetadataStream.CompareSignature(mdecl.m, mdecl.msig, mdecl.gtparams, mdecl.gmparams, ms.m, ms.msig, ms.gtparams, ms.gmparams)) { if (ts.IsInterface == false) { i += (6 + t.ExtraVTableFieldsPointerLength); } return(i); } } } } throw new Exception("Requested virtual method slot not found"); }
private static List <MCInst> handle_call(CilNode.IRNode n, Code c, bool is_calli, Target t, string target = null, metadata.MethodSpec call_ms = null, ir.Param[] p = null, Reg dest = null, bool want_return = true) { List <MCInst> r = new List <MCInst>(); if (call_ms == null) { call_ms = n.imm_ms; } if (target == null && is_calli == false) { target = call_ms.m.MangleMethod(call_ms); } Reg act_dest = null; metadata.TypeSpec rt; int rct; var push_list = get_push_list(n, c, call_ms, out rt, ref dest, out rct, want_return); // Store the current index, we will insert instructions // to save clobbered registers here int push_list_index = r.Count; /* Push arguments */ int push_length = 0; int vt_push_length = 0; bool vt_dest_adjust = false; if (rct == ir.Opcode.ct_vt) { if (dest is ContentsReg) { act_dest = dest; } else { throw new NotImplementedException(); } } var sig_idx = call_ms.msig; var pcount = call_ms.m.GetMethodDefSigParamCountIncludeThis(sig_idx); sig_idx = call_ms.m.GetMethodDefSigRetTypeIndex(sig_idx); var rt2 = call_ms.m.GetTypeSpec(ref sig_idx, call_ms.gtparams == null ? c.ms.gtparams : call_ms.gtparams, c.ms.gmparams); int calli_adjust = is_calli ? 1 : 0; metadata.TypeSpec[] push_tss = new metadata.TypeSpec[pcount]; for (int i = 0; i < pcount; i++) { if (i == 0 && call_ms.m.GetMethodDefSigHasNonExplicitThis(call_ms.msig)) { push_tss[i] = call_ms.type; } else { push_tss[i] = call_ms.m.GetTypeSpec(ref sig_idx, call_ms.gtparams, call_ms.gmparams); } } /* Push value type address if required */ metadata.TypeSpec hidden_loc_type = null; if (rct == ir.Opcode.ct_vt) { var act_dest_cr = act_dest as ContentsReg; if (act_dest_cr == null) { throw new NotImplementedException(); } if (vt_dest_adjust) { throw new NotImplementedException(); } //r.Add(inst(x86_lea_r32, r_eax, act_dest, n)); //r.Add(inst(x86_push_r32, r_eax, n)); hidden_loc_type = call_ms.m.SystemIntPtr; } // Build list of source and destination registers for parameters int cstack_loc = 0; var cc = t.cc_map[call_ms.CallingConvention]; var cc_class = t.cc_classmap[call_ms.CallingConvention]; int[] la_sizes; metadata.TypeSpec[] la_types; var to_locs = t.GetRegLocs(new ir.Param { m = call_ms.m, v2 = call_ms.msig, ms = call_ms }, ref cstack_loc, cc, cc_class, call_ms.CallingConvention, out la_sizes, out la_types, hidden_loc_type ); Reg calli_reg = null; if (is_calli) { calli_reg = r_r10; // Add the target register to those we want to pass Reg[] new_to_locs = new Reg[to_locs.Length + calli_adjust]; for (int i = 0; i < to_locs.Length; i++) { new_to_locs[i] = to_locs[i]; } new_to_locs[to_locs.Length] = calli_reg; to_locs = new_to_locs; } // Append the register arguments to the push list foreach (var arg in to_locs) { if (arg.type == rt_gpr || arg.type == rt_float) { if (!push_list.Contains(arg)) { push_list.Add(arg); } } } List <MCInst> r2 = new List <MCInst>(); // Insert the push instructions at the start of the stream int x = 0; foreach (var push_reg in push_list) { handle_push(push_reg, ref x, r2, n, c); } foreach (var r2inst in r2) { r.Insert(push_list_index++, r2inst); } // Get from locs ir.Param[] from_locs; int hidden_adjust = hidden_loc_type == null ? 0 : 1; if (p == null) { from_locs = new ir.Param[pcount + hidden_adjust + calli_adjust]; for (int i = 0; i < pcount; i++) { var stack_loc = pcount - i - 1; if (n.arg_list != null) { stack_loc = n.arg_list[i]; } from_locs[i + hidden_adjust] = n.stack_before.Peek(stack_loc + calli_adjust).reg; } if (is_calli) { from_locs[pcount + hidden_adjust] = n.stack_before.Peek(0).reg; } } else { from_locs = p; // adjust any rsp relative registers dependent on how many registers we have saved foreach (var l in from_locs) { if (l != null && l.t == ir.Opcode.vl_mreg && l.mreg is ContentsReg) { var l2 = l.mreg as ContentsReg; if (l2.basereg.Equals(r_sp)) { l2.disp += x; } } } } // Reserve any required stack space if (cstack_loc != 0) { push_length += cstack_loc; r.Add(inst(n, arm_sub_sp_imm, imm: cstack_loc)); } // Move from the from list to the to list such that // we never overwrite a from loc that hasn't been // transfered yet pcount += hidden_adjust; pcount += calli_adjust; var to_do = pcount; bool[] done = new bool[pcount]; if (hidden_adjust != 0) { // load up the address of the return value throw new NotImplementedException(); /* * var ret_to = to_locs[0]; * if (!(ret_to is ContentsReg)) * r.Add(inst(t.psize == 4 ? x86_lea_r32 : x86_lea_r64, ret_to, act_dest, n)); * else * { * r.Add(inst(t.psize == 4 ? x86_lea_r32 : x86_lea_r64, r_eax, act_dest, n)); * handle_move(ret_to, r_eax, r, n, c); * * } * * to_do--; * done[0] = true;*/ } while (to_do > 0) { int done_this_iter = 0; for (int to_i = 0; to_i < pcount; to_i++) { if (!done[to_i]) { var to_reg = to_locs[to_i]; if (to_reg.type == rt_stack) { to_reg = new ContentsReg { basereg = r_sp, disp = to_reg.stack_loc, size = to_reg.size }; } bool possible = true; // determine if this to register is the source of a from for (int from_i = 0; from_i < pcount; from_i++) { if (to_i == from_i) { continue; } if (!done[from_i] && from_locs[from_i].mreg != null && from_locs[from_i].mreg.Equals(to_reg)) { possible = false; break; } } if (possible) { var from_reg = from_locs[to_i]; switch (from_reg.t) { case ir.Opcode.vl_mreg: if (from_reg.want_address) { throw new NotImplementedException(); /* * Reg lea_to = to_reg; * if (to_reg is ContentsReg) * lea_to = r_eax; * r.Add(inst(t.psize == 4 ? x86_lea_r32 : x86_lea_r64, * lea_to, from_reg.mreg, n)); * handle_move(to_reg, lea_to, r, n, c); */ } else { handle_move(to_reg, from_reg.mreg, r, n, c); } break; case ir.Opcode.vl_c: case ir.Opcode.vl_c32: case ir.Opcode.vl_c64: if (from_reg.v > int.MaxValue || from_reg.v < int.MinValue) { throw new NotImplementedException(); } else { handle_const(to_reg, from_reg.v, r, n, c); } break; default: throw new NotSupportedException(); } to_do--; done_this_iter++; done[to_i] = true; } } } if (done_this_iter == 0) { // find two gprs/xmms we can swap to put them both // in the correct locations for (int i = 0; i < pcount; i++) { if (done[i]) { continue; } var from_i = from_locs[i].mreg; var to_i = to_locs[i]; if (from_i == null) { continue; } if (from_i.type != rt_gpr && from_i.type != rt_float) { continue; } if (to_i.type != rt_gpr && to_i.type != rt_float) { continue; } for (int j = 0; j < pcount; j++) { if (j == i) { continue; } if (done[j]) { continue; } var from_j = from_locs[j].mreg; if (from_j == null) { continue; } var to_j = to_locs[j]; if (from_i.Equals(to_j) && from_j.Equals(to_i)) { // we can swap these if (from_i.type == rt_gpr || from_i.type == rt_float) { handle_swap(to_i, to_j, r, n, c); } else if (from_i.type == rt_float) { throw new NotImplementedException(); } done_this_iter += 2; to_do -= 2; done[i] = true; done[j] = true; break; } } } } if (done_this_iter == 0) { // find two unassigned gprs/xmms we can swap, which // may not necessarily put them in the correct place bool shift_found = false; // try with gprs first int a = -1; int b = -1; for (int i = 0; i < pcount; i++) { if (done[i] == false && from_locs[i].mreg != null && from_locs[i].mreg.type == rt_gpr) { if (a == -1) { a = i; } else { b = i; shift_found = true; } } } if (shift_found) { handle_swap(from_locs[a].mreg, from_locs[b].mreg, r, n, c); var tmp = from_locs[a]; from_locs[a] = from_locs[b]; from_locs[b] = from_locs[a]; } else { a = -1; b = -1; for (int i = 0; i < pcount; i++) { if (done[i] == false && from_locs[i].mreg != null && from_locs[i].mreg.type == rt_float) { if (a == -1) { a = i; } else { b = i; shift_found = true; } } } if (shift_found) { handle_swap(from_locs[a].mreg, from_locs[b].mreg, r, n, c); var tmp = from_locs[a]; from_locs[a] = from_locs[b]; from_locs[b] = from_locs[a]; } } if (!shift_found) { throw new NotImplementedException(); } } } // Do the call if (is_calli) { // Thumb mode requires LSB set to 1 r.Add(inst(n, arm_orr_imm, Rd: calli_reg, Rn: calli_reg, imm: 1)); r.Add(inst(n, arm_blx, Rm: calli_reg)); } else { r.Add(inst(n, arm_bl, Rm: new ir.Param { t = ir.Opcode.vl_call_target, str = target })); } // Restore stack if (push_length != 0) { r.Add(inst(n, arm_add_sp_imm, imm: push_length)); } // Get vt return value if (rct == ir.Opcode.ct_vt && !act_dest.Equals(dest)) { handle_move(dest, act_dest, r, n, c); } // Restore saved registers for (int i = push_list.Count - 1; i >= 0; i--) { handle_pop(push_list[i], ref x, r, n, c); } // Get other return value if (rt != null && rct != ir.Opcode.ct_vt && rct != ir.Opcode.ct_unknown) { var rt_size = c.t.GetSize(rt); if (rct == ir.Opcode.ct_float) { handle_move(dest, r_s0, r, n, c); } else if (rt_size <= 4) { handle_move(dest, r_r0, r, n, c); } else if (rt_size == 8) { throw new NotImplementedException(); /* * if (t.psize == 4) * { * var drd = dest as DoubleReg; * r.Add(inst(x86_mov_rm32_r32, drd.a, r_eax, n)); * r.Add(inst(x86_mov_rm32_r32, drd.b, r_edx, n)); * } * else * { * r.Add(inst(x86_mov_rm64_r64, dest, r_eax, n)); * } */ } else { throw new NotImplementedException(); } } return(r); }
public static void OutputStaticFields(metadata.TypeSpec ts, target.Target t, binary_library.IBinaryFile of, MetadataStream base_m = null, binary_library.ISection os = null, binary_library.ISection tlsos = null) { // Don't compile if not for this architecture if (!t.IsTypeValid(ts)) { return; } int align = 1; if (ts.SimpleType == 0) { align = GetTypeAlignment(ts, t, true); } if (os == null) { os = of.GetDataSection(); } os.Align(t.GetPointerSize()); os.Align(align); ulong offset = (ulong)os.Data.Count; ulong tl_offset = 0; if (tlsos != null) { tl_offset = (ulong)tlsos.Data.Count; } int cur_offset = 0; int cur_tloffset = 0; /* is_initialized */ for (int i = 0; i < t.psize; i++) { os.Data.Add(0); } cur_offset += t.psize; /* Iterate through methods looking for requested * one */ var first_fdef = ts.m.GetIntEntry(MetadataStream.tid_TypeDef, ts.tdrow, 4); var last_fdef = ts.m.GetLastFieldDef(ts.tdrow); for (uint fdef_row = first_fdef; fdef_row < last_fdef; fdef_row++) { // Ensure field is static or not as required var flags = ts.m.GetIntEntry(MetadataStream.tid_Field, (int)fdef_row, 0); if ((flags & 0x10) == 0x10) { // Increment by type size var fsig = (int)ts.m.GetIntEntry(MetadataStream.tid_Field, (int)fdef_row, 2); var ft = ts.m.GetFieldType(ref fsig, ts.gtparams, null); var ft_size = t.GetSize(ft); ft_size = util.util.align(ft_size, align); bool is_tls = ts.m.thread_local_fields[(int)fdef_row]; ISection cur_os = os; if (is_tls) { if (tlsos == null) { throw new NotSupportedException("No thread-local section provided"); } cur_os = tlsos; } /* See if there is any data defined as an rva */ var rva = ts.m.fieldrvas[(int)fdef_row]; if (rva != 0) { var rrva = (int)ts.m.ResolveRVA(rva); for (int i = 0; i < ft_size; i++) { cur_os.Data.Add(ts.m.file.ReadByte(rrva++)); } } else { for (int i = 0; i < ft_size; i++) { cur_os.Data.Add(0); } } /* Output any additional defined symbols */ foreach (var alias in ts.m.GetFieldAliases((int)fdef_row)) { var asym = of.CreateSymbol(); asym.Name = alias; asym.Offset = offset + (ulong)cur_offset; asym.Type = binary_library.SymbolType.Global; asym.ObjectType = binary_library.SymbolObjectType.Object; cur_os.AddSymbol(asym); asym.Size = ft_size; if (base_m != null && ts.m != base_m) { asym.Type = binary_library.SymbolType.Weak; } } if (is_tls) { cur_tloffset += ft_size; } else { cur_offset += ft_size; } } } if (cur_offset > 0) { /* Add symbol */ var sym = of.CreateSymbol(); sym.Name = ts.m.MangleType(ts) + "S"; sym.Offset = offset; sym.Type = binary_library.SymbolType.Global; sym.ObjectType = binary_library.SymbolObjectType.Object; os.AddSymbol(sym); sym.Size = os.Data.Count - (int)offset; if (base_m != null && ts.m != base_m) { sym.Type = binary_library.SymbolType.Weak; } } if (cur_tloffset > 0) { /* Add thread local symbol */ var sym = of.CreateSymbol(); sym.Name = ts.m.MangleType(ts) + "ST"; sym.Offset = tl_offset; sym.Type = binary_library.SymbolType.Global; sym.ObjectType = binary_library.SymbolObjectType.Object; tlsos.AddSymbol(sym); sym.Size = tlsos.Data.Count - (int)tl_offset; if (base_m != null && ts.m != base_m) { sym.Type = binary_library.SymbolType.Weak; } } }
public static int GetTypeAlignment(metadata.TypeSpec ts, target.Target t, bool is_static) { if (ts.m.classlayouts[ts.tdrow] != 0 && ts.IsGeneric == false && ts.IsGenericTemplate == false) { // see if there is a packing specified var pack = ts.m.GetIntEntry(metadata.MetadataStream.tid_ClassLayout, ts.m.classlayouts[ts.tdrow], 0); if (pack != 0) { return((int)pack); } } if (ts.stype != TypeSpec.SpecialType.None) { return(t.psize); } // types always align on their most strictly aligned type int cur_align = 1; if (ts.SimpleType != 0) { // simple types larger than a pointer (e.g. object/string) // still aling to pointer size; var ret = GetTypeSize(ts, t, is_static); if (ret < t.psize) { return(ret); } return(t.psize); } // reference types will always have a pointer and int64 in them if (is_static == false && !ts.IsValueType) { cur_align = t.psize; cur_align = util.util.align(cur_align, t.GetCTSize(ir.Opcode.ct_int64)); } // and static will always have an 'is_initialized' else if (is_static) { cur_align = t.psize; } /* Iterate through methods looking for requested * one */ var first_fdef = ts.m.GetIntEntry(MetadataStream.tid_TypeDef, ts.tdrow, 4); var last_fdef = ts.m.GetLastFieldDef(ts.tdrow); for (uint fdef_row = first_fdef; fdef_row < last_fdef; fdef_row++) { // Ensure field is static if requested var flags = ts.m.GetIntEntry(MetadataStream.tid_Field, (int)fdef_row, 0); if (((flags & 0x10) == 0x10 && is_static == true) || ((flags & 0x10) == 0 && is_static == false)) { // Get alignment of underlying type var fsig = (int)ts.m.GetIntEntry(MetadataStream.tid_Field, (int)fdef_row, 2); var ft = ts.m.GetFieldType(ref fsig, ts.gtparams, null); int ft_align; if (ft.IsValueType) { ft_align = GetTypeAlignment(ft, t, false); } else { ft_align = t.psize; } if (ft_align > cur_align) { cur_align = ft_align; } } } return(cur_align); }
public static int GetFieldOffset(metadata.TypeSpec ts, string fname, target.Target t, out bool is_tls, bool is_static = false, List <TypeSpec> field_types = null, List <string> field_names = null, List <int> field_offsets = null) { int align = 1; is_tls = false; if (ts.SimpleType == 0) // class { align = GetTypeAlignment(ts, t, is_static); } if (ts.SimpleType == 0xe && !is_static) // string { align = t.GetPointerSize(); } if (ts.Equals(ts.m.SystemString) && !is_static) { /* System.String has a special layout in dotnet clr because the fields * length and firstchar are reversed */ if (field_names != null) { field_names.Add("__vtbl"); field_names.Add("__mutex_lock"); field_names.Add("m_stringLength"); field_names.Add("m_firstChar"); } if (field_types != null) { field_types.Add(ts.m.SystemIntPtr); field_types.Add(ts.m.SystemInt64); field_types.Add(ts.m.SystemInt32); field_types.Add(ts.m.SystemChar); } if (field_offsets != null) { field_offsets.Add(0); field_offsets.Add(GetArrayFieldOffset(ArrayField.MutexLock, t)); field_offsets.Add(GetTypeSize(ts.m.SystemObject, t)); field_offsets.Add(GetTypeSize(ts.m.SystemObject, t) + t.GetPointerSize()); } if (fname == null) { // size = sizeof(Object) + sizeof(int length), aligned to pointer size return(GetTypeSize(ts.m.SystemObject, t) + t.GetPointerSize()); } else { if (fname == "length" || fname == "m_stringLength") { return(GetTypeSize(ts.m.SystemObject, t)); } else if (fname == "start_char" || fname == "m_firstChar") { return(GetTypeSize(ts.m.SystemObject, t) + t.GetPointerSize()); } else { throw new NotSupportedException(); } } } /* Iterate through methods looking for requested * one */ var first_fdef = ts.m.GetIntEntry(MetadataStream.tid_TypeDef, ts.tdrow, 4); var last_fdef = ts.m.GetLastFieldDef(ts.tdrow); int cur_offset = 0; int cur_tl_offset = 0; if (is_static == false && !ts.IsValueType) { if (ts.GetExtends() == null) { // Add a vtable entry if (field_offsets != null) { field_offsets.Add(cur_offset); } cur_offset += t.GetCTSize(ir.Opcode.ct_object); cur_offset = util.util.align(cur_offset, align); if (field_types != null) { field_types.Add(ts.m.SystemIntPtr); } if (field_names != null) { field_names.Add("__vtbl"); } // Add a mutex lock entry if (field_offsets != null) { field_offsets.Add(cur_offset); } cur_offset += t.GetCTSize(ir.Opcode.ct_int64); cur_offset = util.util.align(cur_offset, align); if (field_types != null) { field_types.Add(ts.m.SystemInt64); } if (field_names != null) { field_names.Add("__mutex_lock"); } } else { cur_offset = GetFieldOffset(ts.GetExtends(), (string)null, t, out is_tls, is_static, field_types, field_names, field_offsets); cur_offset = util.util.align(cur_offset, align); } } else if (is_static) { // Add an is_initalized field cur_offset += t.GetCTSize(ir.Opcode.ct_intptr); cur_offset = util.util.align(cur_offset, align); } for (uint fdef_row = first_fdef; fdef_row < last_fdef; fdef_row++) { // Ensure field is static if requested var flags = ts.m.GetIntEntry(MetadataStream.tid_Field, (int)fdef_row, 0); if (((flags & 0x10) == 0x10 && is_static == true) || ((flags & 0x10) == 0 && is_static == false)) { // Check on name if we are looking for a particular field bool f_is_tls = ts.m.thread_local_fields[fdef_row]; if (fname != null) { var ffname = ts.m.GetIntEntry(MetadataStream.tid_Field, (int)fdef_row, 1); if (MetadataStream.CompareString(ts.m, ffname, fname)) { if (f_is_tls) { is_tls = true; return(cur_tl_offset); } else { is_tls = false; return(cur_offset); } } } // Increment by type size var fsig = (int)ts.m.GetIntEntry(MetadataStream.tid_Field, (int)fdef_row, 2); var ft = ts.m.GetFieldType(ref fsig, ts.gtparams, null); var ft_size = t.GetSize(ft); if (field_types != null) { field_types.Add(ft); } if (field_names != null) { var cur_fname = ts.m.GetStringEntry(MetadataStream.tid_Field, (int)fdef_row, 1); field_names.Add(cur_fname); } if (field_offsets != null) { if (f_is_tls) { field_offsets.Add(cur_tl_offset); } else { field_offsets.Add(cur_offset); } } if (f_is_tls) { cur_tl_offset += ft_size; cur_tl_offset = util.util.align(cur_tl_offset, align); } else { cur_offset += ft_size; cur_offset = util.util.align(cur_offset, align); } } } // Shouldn't get here if looking for a specific field if (fname != null) { throw new MissingFieldException(); } // Else return size of complete type return(cur_offset); }
public static int GetFieldOffset(metadata.TypeSpec ts, metadata.MethodSpec fs, target.Target t, out bool is_tls, bool is_static = false) { int align = 1; is_tls = false; if (ts.SimpleType == 0 || ts.SimpleType == 0xe) // class or string { align = GetTypeAlignment(ts, t, is_static); } /* Iterate through methods looking for requested * one */ var first_fdef = ts.m.GetIntEntry(MetadataStream.tid_TypeDef, ts.tdrow, 4); var last_fdef = ts.m.GetLastFieldDef(ts.tdrow); uint search_field_name = 0; if (fs != null) { search_field_name = fs.m.GetIntEntry(MetadataStream.tid_Field, fs.mdrow, 1); } int cur_offset = 0; int cur_tl_offset = 0; if (is_static == false && !ts.IsValueType) { if (ts.GetExtends() == null) { // Add a vtable entry cur_offset += t.GetCTSize(ir.Opcode.ct_object); cur_offset = util.util.align(cur_offset, align); // Add a mutex lock entry cur_offset += t.GetCTSize(ir.Opcode.ct_int64); cur_offset = util.util.align(cur_offset, align); } else { cur_offset = GetFieldOffset(ts.GetExtends(), (string)null, t, out is_tls); cur_offset = util.util.align(cur_offset, align); } } else if (is_static) { // Add an is_initalized field cur_offset += t.GetCTSize(ir.Opcode.ct_intptr); cur_offset = util.util.align(cur_offset, align); } for (uint fdef_row = first_fdef; fdef_row < last_fdef; fdef_row++) { // Ensure field is static if requested var flags = ts.m.GetIntEntry(MetadataStream.tid_Field, (int)fdef_row, 0); if (((flags & 0x10) == 0x10 && is_static == true) || ((flags & 0x10) == 0 && is_static == false)) { // Check on name if we are looking for a particular field bool f_is_tls = ts.m.thread_local_fields[fdef_row]; if (search_field_name != 0) { var fname = ts.m.GetIntEntry(MetadataStream.tid_Field, (int)fdef_row, 1); if (MetadataStream.CompareString(ts.m, fname, fs.m, search_field_name)) { if (f_is_tls) { is_tls = true; return(cur_tl_offset); } else { is_tls = false; return(cur_offset); } } } // Increment by type size var fsig = (int)ts.m.GetIntEntry(MetadataStream.tid_Field, (int)fdef_row, 2); var ft = ts.m.GetFieldType(ref fsig, ts.gtparams, null); var ft_size = t.GetSize(ft); if (f_is_tls) { cur_tl_offset += ft_size; cur_tl_offset = util.util.align(cur_tl_offset, align); } else { cur_offset += ft_size; cur_offset = util.util.align(cur_offset, align); } } } // Shouldn't get here if looking for a specific field if (search_field_name != 0) { throw new MissingFieldException(); } // Else return size of complete type return(cur_offset); }