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(); } }
private static void OutputVirtualMethods(TypeSpec decl_ts, IBinaryFile of, ISection os, IList <byte> d, ref ulong offset, target.Target t, TysilaState s) { var vmeths = GetVirtualMethodDeclarations(decl_ts); ImplementVirtualMethods(decl_ts, vmeths); foreach (var vmeth in vmeths) { var impl_ms = vmeth.impl_meth; string impl_target = (impl_ms == null) ? "__cxa_pure_virtual" : impl_ms.MethodReferenceAlias; var impl_sym = of.CreateSymbol(); impl_sym.Name = impl_target; impl_sym.ObjectType = SymbolObjectType.Function; var impl_reloc = of.CreateRelocation(); impl_reloc.Addend = 0; impl_reloc.DefinedIn = os; impl_reloc.Offset = offset; impl_reloc.References = impl_sym; impl_reloc.Type = t.GetDataToCodeReloc(); of.AddRelocation(impl_reloc); for (int i = 0; i < t.GetPointerSize(); i++, offset++) { d.Add(0); } if (impl_ms != null) { s.r.MethodRequestor.Request(impl_ms); } } }
internal static target.Target.Reg DoAllocation(Code c, int ct, target.Target t, ref long alloced, ref int cur_stack) { // rationalise thread-local addresses to use the same registers as normal ones if (ct == Opcode.ct_tls_int32) { ct = Opcode.ct_int32; } else if (ct == Opcode.ct_tls_int64) { ct = Opcode.ct_int64; } else if (ct == Opcode.ct_tls_intptr) { ct = Opcode.ct_intptr; } long avail = t.ct_regs[ct] & ~alloced; if (avail != 0) { // We have a valid allocation to use int idx = 0; while ((avail & 0x1) == 0) { idx++; avail >>= 1; } var reg = t.regs[idx]; alloced |= (1L << idx); return(reg); } else { return(t.AllocateStackLocation(c, t.GetCTSize(ct), ref cur_stack)); } }
static int get_conv_pushtype(Opcode n, target.Target t) { var dt = n.uses[1].v; switch (dt) { case 1: case 2: case 4: case -1: case -2: case -4: return(ct_int32); case 8: case -8: return(ct_int64); case 14: case 18: return(ct_float); } throw new NotSupportedException("Invalid opcode: " + n.ToString()); }
static int get_call_rettype(Opcode n, target.Target t) { // Determine the return type from the method signature var cs = n.uses[0]; var ms = cs.ms; if (ms == null) { throw new NotSupportedException(); } var msig = ms.msig; var rt_idx = ms.m.GetMethodDefSigRetTypeIndex(msig); throw new NotImplementedException(); /*var ret_ts = ms.m.GetTypeSpec(ref rt_idx, * n.n.g.ms.gtparams, n.n.g.ms.gmparams); * * var ct = GetCTFromType(ret_ts); * * return ct;*/ }
/* Vtable: * * TIPtr (just to a glorified TypeSpec) * IFacePtr (to list of implemented interfaces) * Extends (to base classes for quick castclassex) * TypeSize (to allow MemberwiseClone to work without full Reflection) * Any target-specific data * Method 0 * ... * * IFaceList TODO * * */ public static void OutputVTable(TypeSpec ts, target.Target t, binary_library.IBinaryFile of, TysilaState s, MetadataStream base_m = null, ISection os = null, ISection data_sect = null) { // Don't compile if not for this architecture if (!t.IsTypeValid(ts)) { return; } /* New signature table */ s.sigt = new SignatureTable(ts.MangleType()); // If its a delegate type we also need to output its methods if (ts.IsDelegate && !ts.IsGenericTemplate) { s.r.DelegateRequestor.Request(ts); } if (os == null) { os = of.GetRDataSection(); } var d = os.Data; var ptr_size = t.GetCTSize(ir.Opcode.ct_object); os.Align(ptr_size); ulong offset = (ulong)os.Data.Count; /* Symbol */ var sym = of.CreateSymbol(); sym.Name = ts.MangleType(); sym.ObjectType = binary_library.SymbolObjectType.Object; sym.Offset = offset; sym.Type = binary_library.SymbolType.Global; os.AddSymbol(sym); if (base_m != null && ts.m != base_m) { sym.Type = SymbolType.Weak; } /* TIPtr */ var tiptr_offset = s.sigt.GetSignatureAddress(ts.Signature, t, s); var ti_reloc = of.CreateRelocation(); ti_reloc.Addend = tiptr_offset; ti_reloc.DefinedIn = os; ti_reloc.Offset = offset; ti_reloc.Type = t.GetDataToDataReloc(); ti_reloc.References = of.CreateSymbol(); ti_reloc.References.Name = s.sigt.GetStringTableName(); of.AddRelocation(ti_reloc); for (int i = 0; i < ptr_size; i++, offset++) { d.Add(0); } /* IFacePtr */ IRelocation if_reloc = null; if (!ts.IsGenericTemplate && !ts.IsInterface && ts.stype != TypeSpec.SpecialType.Ptr && ts.stype != TypeSpec.SpecialType.MPtr) { if_reloc = of.CreateRelocation(); if_reloc.DefinedIn = os; if_reloc.Offset = offset; if_reloc.Type = t.GetDataToDataReloc(); if_reloc.References = sym; of.AddRelocation(if_reloc); } for (int i = 0; i < ptr_size; i++, offset++) { d.Add(0); } /* Extends */ var ts_extends = ts.GetExtends(); if (ts_extends != null) { var ext_reloc = of.CreateRelocation(); ext_reloc.Addend = 0; ext_reloc.DefinedIn = os; ext_reloc.Offset = offset; ext_reloc.Type = t.GetDataToDataReloc(); var ext_sym = of.CreateSymbol(); ext_sym.Name = ts_extends.MangleType(); ext_reloc.References = ext_sym; of.AddRelocation(ext_reloc); s.r.VTableRequestor.Request(ts_extends); } for (int i = 0; i < ptr_size; i++, offset++) { d.Add(0); } if (ts.IsInterface || ts.IsGenericTemplate || ts.stype == TypeSpec.SpecialType.MPtr || ts.stype == TypeSpec.SpecialType.Ptr) { /* Type size is zero for somethinh we cannot * instantiate */ for (int i = 0; i < ptr_size; i++, offset++) { d.Add(0); } /* Flags */ AddFlags(d, ts, ref offset, t); /* BaseType */ AddBaseType(d, ts, of, os, ref offset, t, s); // Target-specific information t.AddExtraVTableFields(ts, d, ref offset); } else { /* Type size */ var tsize = t.IntPtrArray(BitConverter.GetBytes(GetTypeSize(ts, t))); foreach (var b in tsize) { d.Add(b); offset++; } /* Flags */ AddFlags(d, ts, ref offset, t); /* BaseType */ AddBaseType(d, ts, of, os, ref offset, t, s); // Target specific information t.AddExtraVTableFields(ts, d, ref offset); /* Virtual methods */ OutputVirtualMethods(ts, of, os, d, ref offset, t, s); /* Interface implementations */ // build list of implemented interfaces var ii = ts.ImplementedInterfaces; // first, add all interface implementations List <ulong> ii_offsets = new List <ulong>(); for (int i = 0; i < ii.Count; i++) { ii_offsets.Add(offset - sym.Offset); OutputInterface(ts, ii[i], of, os, d, ref offset, t, s); s.r.VTableRequestor.Request(ii[i]); } // point iface ptr here if_reloc.Addend = (long)offset - (long)sym.Offset; for (int i = 0; i < ii.Count; i++) { // list is pointer to interface declaration, then implementation var id_ptr_sym = of.CreateSymbol(); id_ptr_sym.Name = ii[i].MangleType(); var id_ptr_reloc = of.CreateRelocation(); id_ptr_reloc.Addend = 0; id_ptr_reloc.DefinedIn = os; id_ptr_reloc.Offset = offset; id_ptr_reloc.References = id_ptr_sym; id_ptr_reloc.Type = t.GetDataToDataReloc(); of.AddRelocation(id_ptr_reloc); for (int j = 0; j < ptr_size; j++, offset++) { d.Add(0); } // implementation var ii_ptr_reloc = of.CreateRelocation(); ii_ptr_reloc.Addend = (long)ii_offsets[i]; ii_ptr_reloc.DefinedIn = os; ii_ptr_reloc.Offset = offset; ii_ptr_reloc.References = sym; ii_ptr_reloc.Type = t.GetDataToDataReloc(); of.AddRelocation(ii_ptr_reloc); for (int j = 0; j < ptr_size; j++, offset++) { d.Add(0); } } // null terminate the list for (int j = 0; j < ptr_size; j++, offset++) { d.Add(0); } } sym.Size = (long)(offset - sym.Offset); /* Output signature table if any */ if (data_sect == null) { data_sect = of.GetDataSection(); } s.sigt.WriteToOutput(of, base_m, t, data_sect); }
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); }
public static int GetArrayObjectSize(target.Target t) { // round up to 8x intptr size so size is aligned to word size return(8 * t.GetPointerSize()); }
protected static target.Target.Reg DoAllocation(Code c, StackItem si, target.Target t, ref long alloced, ref int cur_stack) { si.reg = DoAllocation(c, si.ct, t, ref alloced, ref cur_stack); return(si.reg); }
static int get_object_pushtype(Opcode n, target.Target t) { return(ct_intptr); }
static int get_binnumop_pushtype(Opcode n, target.Target t) { var a = n.uses[0].ct; var b = n.uses[1].ct; switch (a) { case ct_int32: switch (b) { case ct_int32: return(ct_int32); case ct_intptr: return(ct_intptr); case ct_ref: if (n.oc == oc_add) { return(ct_ref); } break; } break; case ct_int64: switch (b) { case ct_int64: return(ct_int64); } break; case ct_intptr: switch (b) { case ct_int32: return(ct_intptr); case ct_intptr: return(ct_intptr); case ct_ref: if (n.oc == oc_add) { return(ct_ref); } break; } break; case ct_float: switch (b) { case ct_float: return(ct_float); } break; case ct_ref: switch (b) { case ct_int32: if (n.oc == oc_add || n.oc == oc_sub) { return(ct_ref); } break; case ct_intptr: if (n.oc == oc_add || n.oc == oc_sub) { return(ct_ref); } break; case ct_ref: if (n.oc == oc_sub) { return(ct_intptr); } break; } break; } throw new NotSupportedException("Invalid opcode:" + n.ToString()); }