private static MethodSpec GetVirtualMethod(TypeSpec impl_ts, MethodSpec decl_ms, target.Target t, bool allow_non_virtual = false) { /* Iterate through methods looking for virtual ones */ var first_mdef = impl_ts.m.GetIntEntry(MetadataStream.tid_TypeDef, impl_ts.tdrow, 5); var last_mdef = impl_ts.m.GetLastMethodDef(impl_ts.tdrow); for (uint mdef_row = first_mdef; mdef_row < last_mdef; mdef_row++) { var flags = impl_ts.m.GetIntEntry(MetadataStream.tid_MethodDef, (int)mdef_row, 2); if (allow_non_virtual || (flags & 0x40) == 0x40) { MethodSpec impl_ms; impl_ts.m.GetMethodDefRow(MetadataStream.tid_MethodDef, (int)mdef_row, out impl_ms, impl_ts.gtparams, null); impl_ms.type = impl_ts; if ((flags & 0x400) != 0x400) { // Not marked abstract if (MetadataStream.CompareString(impl_ms.m, impl_ms.m.GetIntEntry(MetadataStream.tid_MethodDef, (int)mdef_row, 3), decl_ms.m, decl_ms.m.GetIntEntry(MetadataStream.tid_MethodDef, (int)decl_ms.mdrow, 3))) { if (MetadataStream.CompareSignature(impl_ms.m, impl_ms.msig, impl_ts.gtparams, null, decl_ms.m, decl_ms.msig, impl_ts.gtparams, null)) { // this is the correct one return(impl_ms); } if (MetadataStream.CompareSignature(impl_ms.m, impl_ms.msig, impl_ts.gtparams, null, decl_ms.m, decl_ms.msig, decl_ms.gtparams, null)) { // this is the correct one return(impl_ms); } } } } } // if not found, look to base classes var bc = impl_ts.GetExtends(); if (bc != null) { return(GetVirtualMethod(bc, decl_ms, t, allow_non_virtual)); } else { return(null); } }
private static int GetVTableIndex(MethodSpec ms, List <VTableItem> list) { for (int idx = 0; idx < list.Count; idx++) { var i = list[idx]; if (MetadataStream.CompareString(ms.m, ms.m.GetIntEntry(MetadataStream.tid_MethodDef, ms.mdrow, 3), i.unimpl_meth.m, i.unimpl_meth.m.GetIntEntry(MetadataStream.tid_MethodDef, i.unimpl_meth.mdrow, 3))) { if (MetadataStream.CompareSignature(ms, i.unimpl_meth)) { return(idx); } } } return(-1); }
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"); }
public static void ImplementVirtualMethods(TypeSpec ts, List <VTableItem> list) { // We implement those methods in the most derived class first and work back foreach (var i in list) { // skip if already done if (i.impl_meth != null) { continue; } // if we've gone back far enough to the max_implementor class // we can start looking for implementations from here if (i.max_implementor != null && i.max_implementor.Equals(ts)) { i.max_implementor = null; } // if we haven't, skip this method for this class (it will be // implemented in a base class) if (i.max_implementor != null) { continue; } // Now, search for a matching method in this particular class /* Iterate through methods looking for virtual ones */ var first_mdef = ts.m.GetIntEntry(MetadataStream.tid_TypeDef, ts.tdrow, 5); var last_mdef = ts.m.GetLastMethodDef(ts.tdrow); var search_meth_name = i.unimpl_meth.m.GetIntEntry(MetadataStream.tid_MethodDef, i.unimpl_meth.mdrow, 3); for (uint mdef_row = first_mdef; mdef_row < last_mdef; mdef_row++) { var flags = ts.m.GetIntEntry(MetadataStream.tid_MethodDef, (int)mdef_row, 2); if ((flags & 0x40) == 0x40) { // its a virtual method MethodSpec impl_ms; ts.m.GetMethodDefRow(MetadataStream.tid_MethodDef, (int)mdef_row, out impl_ms, ts.gtparams, null); impl_ms.type = ts; // compare on name if (MetadataStream.CompareString(i.unimpl_meth.m, search_meth_name, ts.m, ts.m.GetIntEntry(MetadataStream.tid_MethodDef, (int)mdef_row, 3))) { // and on signature if (MetadataStream.CompareSignature(i.unimpl_meth, impl_ms)) { // If its marked abstract, we dont implement it if ((flags & 0x400) == 0x400) { i.impl_meth = null; } else { // we have found a valid implementing method i.impl_meth = impl_ms; } } } } } } // now implement on base classes var extends = ts.GetExtends(); if (extends != null) { ImplementVirtualMethods(extends, list); } }