public static void MethodDefNameKey( StringBuilder sb, MethodDef metDef, IGenericReplacer replacer) { if (replacer == null) { MethodNameKey( sb, metDef.Name, metDef.GenericParameters.Count, metDef.MethodSig.RetType, metDef.MethodSig.Params, metDef.MethodSig.CallingConvention); } else { TypeSig retType = Helper.ReplaceGenericSig(metDef.MethodSig.RetType, replacer); IList <TypeSig> paramTypes = Helper.ReplaceGenericSigList(metDef.MethodSig.Params, replacer); MethodNameKey( sb, metDef.Name, metDef.GenericParameters.Count, retType, paramTypes, metDef.MethodSig.CallingConvention); } }
// 替换类型中的泛型签名 public static TypeSig ReplaceGenericSig(TypeSig tySig, IGenericReplacer replacer) { if (replacer == null || !IsReplaceNeeded(tySig)) { return(tySig); } return(ReplaceGenericSigImpl(tySig, replacer)); }
private string GetReplacedNameKey(IGenericReplacer replacer) { if (HasGenArgs) { var repGenArgs = Helper.ReplaceGenericSigList(GenArgs, replacer); StringBuilder sb = new StringBuilder(); Helper.TypeNameKey(sb, Def, repGenArgs); return(sb.ToString()); } return(GetNameKey()); }
private void ExplicitOverride(MethodDef ownerMetDef, int ownerMetIdx) { IGenericReplacer replacer = null; if (HasGenArgs) { replacer = new TypeDefGenReplacer(Def, GenArgs); } foreach (var overItem in ownerMetDef.Overrides) { var target = overItem.MethodDeclaration; var impl = overItem.MethodBody; MethodTable targetTable = Context.TypeMgr.ResolveMethodTable(target.DeclaringType, replacer); MethodDef targetDef = target.ResolveMethodDef(); if (targetDef == null) { throw new TypeLoadException("Cannot find overriding signature: " + target.FullName); } if (targetDef.HasOverrides) { throw new TypeLoadException("Method already has overrides: " + targetDef.FullName); } MethodDef implDef = impl.ResolveMethodDef(); if (targetTable == this) { // 处理显式重写当前类型方法的情况 MethodReplaceMap.Add(targetDef, new Tuple <MethodTable, MethodDef>(this, implDef)); } else { string expSigName; if (implDef == ownerMetDef) { expSigName = ExpandedSigList[ownerMetIdx]; } else { throw new NotSupportedException(); } // 合并目标入口到实现方法的方法槽内 MergeSlot(expSigName, targetTable, targetDef); } } }
private void ResolveOperand(InstInfo inst, IGenericReplacer replacer) { // 重定向数组指令 switch (inst.OpCode.Code) { case Code.Newarr: { // newobj T[]::.ctor(int) TypeSig elemSig = ((ITypeDefOrRef)inst.Operand).ToTypeSig(); inst.OpCode = OpCodes.Newobj; inst.Operand = new MemberRefUser( Context.CorLibModule, ".ctor", MethodSig.CreateInstance(Context.CorLibTypes.Void, Context.CorLibTypes.Int32), new TypeSpecUser(new SZArraySig(elemSig))); break; } case Code.Ldlen: { // call int Array::get_Length() inst.OpCode = OpCodes.Call; inst.Operand = new MemberRefUser( Context.CorLibModule, "get_Length", MethodSig.CreateInstance(Context.CorLibTypes.Int32), Context.CorLibTypes.GetTypeRef("System", "Array")); break; } case Code.Ldelema: { // call T& T[]::Address(int) TypeSig elemSig = ((ITypeDefOrRef)inst.Operand).ToTypeSig(); inst.OpCode = OpCodes.Call; inst.Operand = new MemberRefUser( Context.CorLibModule, "Address", MethodSig.CreateInstance(new ByRefSig(elemSig), Context.CorLibTypes.Int32), new TypeSpecUser(new SZArraySig(elemSig))); break; } case Code.Ldelem_I1: case Code.Ldelem_U1: case Code.Ldelem_I2: case Code.Ldelem_U2: case Code.Ldelem_I4: case Code.Ldelem_U4: case Code.Ldelem_I8: case Code.Ldelem_I: case Code.Ldelem_R4: case Code.Ldelem_R8: case Code.Ldelem_Ref: case Code.Ldelem: { TypeSig elemSig = null; switch (inst.OpCode.Code) { case Code.Ldelem_I1: elemSig = Context.CorLibTypes.SByte; break; case Code.Ldelem_U1: elemSig = Context.CorLibTypes.Byte; break; case Code.Ldelem_I2: elemSig = Context.CorLibTypes.Int16; break; case Code.Ldelem_U2: elemSig = Context.CorLibTypes.UInt16; break; case Code.Ldelem_I4: elemSig = Context.CorLibTypes.Int32; break; case Code.Ldelem_U4: elemSig = Context.CorLibTypes.UInt32; break; case Code.Ldelem_I8: elemSig = Context.CorLibTypes.Int64; break; case Code.Ldelem_I: elemSig = Context.CorLibTypes.IntPtr; break; case Code.Ldelem_R4: elemSig = Context.CorLibTypes.Single; break; case Code.Ldelem_R8: elemSig = Context.CorLibTypes.Double; break; case Code.Ldelem_Ref: elemSig = Context.CorLibTypes.Object; break; case Code.Ldelem: elemSig = ((ITypeDefOrRef)inst.Operand).ToTypeSig(); break; } // call T T[]::Get(int) inst.OpCode = OpCodes.Call; inst.Operand = new MemberRefUser( Context.CorLibModule, "Get", MethodSig.CreateInstance(elemSig, Context.CorLibTypes.Int32), new TypeSpecUser(new SZArraySig(elemSig))); break; } case Code.Stelem_I1: case Code.Stelem_I2: case Code.Stelem_I4: case Code.Stelem_I8: case Code.Stelem_I: case Code.Stelem_R4: case Code.Stelem_R8: case Code.Stelem_Ref: case Code.Stelem: { TypeSig elemSig = null; switch (inst.OpCode.Code) { case Code.Stelem_I1: elemSig = Context.CorLibTypes.SByte; break; case Code.Stelem_I2: elemSig = Context.CorLibTypes.Int16; break; case Code.Stelem_I4: elemSig = Context.CorLibTypes.Int32; break; case Code.Stelem_I8: elemSig = Context.CorLibTypes.Int64; break; case Code.Stelem_I: elemSig = Context.CorLibTypes.IntPtr; break; case Code.Stelem_R4: elemSig = Context.CorLibTypes.Single; break; case Code.Stelem_R8: elemSig = Context.CorLibTypes.Double; break; case Code.Stelem_Ref: elemSig = Context.CorLibTypes.Object; break; case Code.Stelem: elemSig = ((ITypeDefOrRef)inst.Operand).ToTypeSig(); break; } // call void T[]::Set(int,T) inst.OpCode = OpCodes.Call; inst.Operand = new MemberRefUser( Context.CorLibModule, "Set", MethodSig.CreateInstance(Context.CorLibTypes.Void, Context.CorLibTypes.Int32, elemSig), new TypeSpecUser(new SZArraySig(elemSig))); break; } } switch (inst.OpCode.OperandType) { case OperandType.InlineMethod: { MethodX resMetX; switch (inst.Operand) { case MethodDef metDef: resMetX = ResolveMethodDef(metDef); break; case MemberRef memRef: resMetX = ResolveMethodRef(memRef, replacer); break; case MethodSpec metSpec: resMetX = ResolveMethodSpec(metSpec, replacer); break; default: throw new ArgumentOutOfRangeException(); } bool isReAddMethod = false; if (inst.OpCode.Code == Code.Newobj) { Debug.Assert(!resMetX.Def.IsStatic); Debug.Assert(resMetX.Def.IsConstructor); // 设置实例化标记 resMetX.DeclType.IsInstantiated = true; // 生成静态构造和终结器 GenStaticCctor(resMetX.DeclType); GenFinalizer(resMetX.DeclType); } else if (inst.OpCode.Code == Code.Callvirt || inst.OpCode.Code == Code.Ldvirtftn) { if (resMetX.IsVirtual) { AddVCallEntry(resMetX); } else { // 非虚方法重定向指令 inst.OpCode = inst.OpCode.Code == Code.Callvirt ? OpCodes.Call : OpCodes.Ldftn; } } else if (resMetX.IsVirtual && (inst.OpCode.Code == Code.Call || inst.OpCode.Code == Code.Ldftn)) { // 处理方法替换 if (resMetX.DeclType.QueryCallReplace(this, resMetX.Def, out TypeX implTyX, out var implDef)) { resMetX.IsSkipProcessing = true; Debug.Assert(implTyX != null); MethodX implMetX = MakeMethodX(implTyX, implDef, resMetX.GenArgs); resMetX = implMetX; } else { isReAddMethod = true; } } else { isReAddMethod = true; } if (isReAddMethod) { // 尝试重新加入处理队列 AddPendingMethod(resMetX); } if (resMetX.IsStatic) { // 生成静态构造 GenStaticCctor(resMetX.DeclType); } inst.Operand = resMetX; return; }
private VirtualSlot ExpandVirtualSlot(VirtualSlot vslot, MethodTable expMetTable, IGenericReplacer replacer) { VirtualSlot expVSlot = new VirtualSlot(ExpandMethodPair(vslot.NewSlotEntry, expMetTable, replacer)); foreach (var entry in vslot.Entries) { expVSlot.Entries.Add(ExpandMethodPair(entry, expMetTable, replacer)); } expVSlot.Implemented = ExpandMethodPair(vslot.Implemented, expMetTable, replacer); return(expVSlot); }
private TableMethodPair ExpandMethodPair(TableMethodPair metPair, MethodTable expMetTable, IGenericReplacer replacer) { if (metPair == null) { return(null); } MethodTable mtable = metPair.Item1; if (mtable == this) { return(new TableMethodPair(expMetTable, metPair.Item2)); } if (mtable.InstGenArgs.IsCollectionValid()) { var genArgs = Helper.ReplaceGenericSigList(mtable.InstGenArgs, replacer); mtable = TypeMgr.ResolveMethodTableSpec(mtable.Def, genArgs); Debug.Assert(mtable != this); return(new TableMethodPair(mtable, metPair.Item2)); } return(metPair); }
private static IList <TypeSig> ReplaceGenericSigListImpl(IList <TypeSig> tySigList, IGenericReplacer replacer) { return(tySigList?.Select(tySig => ReplaceGenericSigImpl(tySig, replacer)).ToList()); }
// 替换类型签名列表 public static IList <TypeSig> ReplaceGenericSigList(IList <TypeSig> tySigList, IGenericReplacer replacer) { return(tySigList?.Select(tySig => ReplaceGenericSig(tySig, replacer)).ToList()); }
private static TypeSig ReplaceGenericSigImpl(TypeSig tySig, IGenericReplacer replacer) { if (tySig == null) { return(null); } switch (tySig.ElementType) { case ElementType.Class: case ElementType.ValueType: case ElementType.TypedByRef: return(tySig); case ElementType.Ptr: return(new PtrSig(ReplaceGenericSigImpl(tySig.Next, replacer))); case ElementType.ByRef: return(new ByRefSig(ReplaceGenericSigImpl(tySig.Next, replacer))); case ElementType.Pinned: return(new PinnedSig(ReplaceGenericSigImpl(tySig.Next, replacer))); case ElementType.SZArray: return(new SZArraySig(ReplaceGenericSigImpl(tySig.Next, replacer))); case ElementType.Array: { ArraySig arySig = (ArraySig)tySig; return(new ArraySig(ReplaceGenericSigImpl(arySig.Next, replacer), arySig.Rank, arySig.Sizes, arySig.LowerBounds)); } case ElementType.CModReqd: { CModReqdSig modreqdSig = (CModReqdSig)tySig; return(new CModReqdSig(modreqdSig.Modifier, ReplaceGenericSigImpl(modreqdSig.Next, replacer))); } case ElementType.CModOpt: { CModOptSig modoptSig = (CModOptSig)tySig; return(new CModOptSig(modoptSig.Modifier, ReplaceGenericSigImpl(modoptSig.Next, replacer))); } case ElementType.GenericInst: { GenericInstSig genInstSig = (GenericInstSig)tySig; return(new GenericInstSig(genInstSig.GenericType, ReplaceGenericSigListImpl(genInstSig.GenericArguments, replacer))); } case ElementType.Var: { GenericVar genVarSig = (GenericVar)tySig; TypeSig result = replacer.Replace(genVarSig); if (result != null) { return(result); } return(genVarSig); } case ElementType.MVar: { GenericMVar genMVarSig = (GenericMVar)tySig; TypeSig result = replacer.Replace(genMVarSig); if (result != null) { return(result); } return(genMVarSig); } default: if (tySig is CorLibTypeSig) { return(tySig); } throw new NotSupportedException(); } }
private void ResolveOperand(InstInfo inst, IGenericReplacer replacer) { switch (inst.OpCode.OperandType) { case OperandType.InlineMethod: { MethodX resMetX; switch (inst.Operand) { case MethodDef metDef: resMetX = ResolveMethodDef(metDef); break; case MemberRef memRef: resMetX = ResolveMethodRef(memRef, replacer); break; case MethodSpec metSpec: resMetX = ResolveMethodSpec(metSpec, replacer); break; default: throw new ArgumentOutOfRangeException(); } bool isReAddMethod = false; if (inst.OpCode.Code == Code.Newobj) { Debug.Assert(!resMetX.Def.IsStatic); Debug.Assert(resMetX.Def.IsConstructor); // 设置实例化标记 resMetX.DeclType.IsInstantiated = true; // 生成静态构造和终结器 GenStaticCctor(resMetX.DeclType); GenFinalizer(resMetX.DeclType); // 解析虚表 resMetX.DeclType.ResolveVTable(); } else if (resMetX.IsVirtual && (inst.OpCode.Code == Code.Callvirt || inst.OpCode.Code == Code.Ldvirtftn)) { // 处理非入口虚调用重定向 if (!resMetX.Def.IsNewSlot) { if (GetNewSlotMethodChecked(resMetX.DeclType, resMetX.Def, out var slotTypeName, out var slotMetDef)) { resMetX.IsSkipProcessing = true; TypeX slotTyX = GetTypeByName(slotTypeName); Debug.Assert(slotTyX != null); MethodX slotMetX = MakeMethodX(slotTyX, slotMetDef, resMetX.GenArgs); resMetX = slotMetX; } } AddVCallEntry(resMetX); } else if (resMetX.IsVirtual && (inst.OpCode.Code == Code.Call || inst.OpCode.Code == Code.Ldftn)) { // 处理方法替换 if (resMetX.DeclType.IsMethodReplaced(resMetX.Def, out var repTypeName, out var repMetDef)) { resMetX.IsSkipProcessing = true; TypeX repTyX = GetTypeByName(repTypeName); Debug.Assert(repTyX != null); MethodX repMetX = MakeMethodX(repTyX, repMetDef, resMetX.GenArgs); resMetX = repMetX; } else { isReAddMethod = true; } } else { isReAddMethod = true; } if (isReAddMethod) { // 尝试重新加入处理队列 AddPendingMethod(resMetX); } if (resMetX.IsStatic) { // 生成静态构造 GenStaticCctor(resMetX.DeclType); } inst.Operand = resMetX; return; }
public void ResolveTable() { StringBuilder sb = new StringBuilder(); IGenericReplacer replacer = null; if (HasGenArgs) { replacer = new TypeDefGenReplacer(Def, GenArgs); } Dictionary <string, MethodDef> sameSigDefs = new Dictionary <string, MethodDef>(); // 解析不展开类型泛型的方法签名, 和展开的方法签名 uint lastRid = 0; foreach (var metDef in Def.Methods) { if (metDef.IsStatic || metDef.IsConstructor) { continue; } Debug.Assert(lastRid < metDef.Rid); lastRid = metDef.Rid; MethodDefList.Add(metDef); Helper.MethodDefNameKey(sb, metDef, replacer); string expSigName = sb.ToString(); sb.Clear(); ExpandedSigList.Add(expSigName); if (sameSigDefs.TryGetValue(expSigName, out var osameDef)) { // 遇到相同签名的方法 //if (!Def.HasGenericParameters) // throw new TypeLoadException("Conflicted method signature"); if (SameSigResolvedMap == null) { SameSigResolvedMap = new Dictionary <string, Tuple <MethodTable, MethodDef> >(); } SameSigResolvedMap.Add(expSigName, new Tuple <MethodTable, MethodDef>(this, osameDef)); } else { sameSigDefs.Add(expSigName, metDef); } } // 解析并继承基类方法表 if (Def.BaseType != null) { MethodTable baseTable = Context.TypeMgr.ResolveMethodTable(Def.BaseType, replacer); DerivedFrom(baseTable); } List <int> explicitOverrides = new List <int>(); // 处理当前类型的重写 for (int i = 0; i < MethodDefList.Count; ++i) { MethodDef metDef = MethodDefList[i]; string expSigName = ExpandedSigList[i]; if (metDef.HasOverrides) { // 记录存在显式重写的方法 explicitOverrides.Add(i); } if (Def.IsInterface) { // 特殊处理接口方法, 用于解决泛型接口内签名相同的情况 Debug.Assert(metDef.IsVirtual && metDef.IsNewSlot && metDef.IsAbstract); MergeSlot(expSigName, this, metDef); } else if (metDef.IsVirtual) { if (metDef.IsNewSlot) { NewSlot(expSigName, metDef); } else { Debug.Assert(metDef.IsReuseSlot); ReuseSlot(expSigName, metDef); } } else { NewSlot(expSigName, metDef); } } HashSet <string> absNoImplSlots = null; if (Def.IsAbstract) { absNoImplSlots = new HashSet <string>(); } // 合并接口的方法槽到当前方法槽 if (Def.HasInterfaces) { foreach (var inf in Def.Interfaces) { MethodTable infTable = Context.TypeMgr.ResolveMethodTable(inf.Interface, replacer); foreach (var kv in infTable.VSlotMap) { string expSigName = kv.Key; VirtualSlot vslot = kv.Value; foreach (var kv2 in vslot.Entries) { MethodTable entryTable = kv2.Key; foreach (MethodDef entryDef in kv2.Value) { if (NeedMergeInterface(expSigName, entryTable, entryDef)) { // 合并 var mergedVSlot = MergeSlot(expSigName, entryTable, entryDef); // 记录虚类型未实现的接口签名 if (absNoImplSlots != null && !mergedVSlot.Impl.IsValid()) { absNoImplSlots.Add(expSigName); } } } } } } } // 合并抽象基类未实现的接口 if (Helper.IsCollectionValid(AbsNoImplSlotMap)) { foreach (var kv in AbsNoImplSlotMap) { string expSigName = kv.Key; foreach (var kv2 in kv.Value) { MethodTable entryTable = kv2.Key; foreach (MethodDef entryDef in kv2.Value) { if (NeedMergeInterface(expSigName, entryTable, entryDef)) { // 合并 var mergedVSlot = MergeSlot(expSigName, entryTable, entryDef); } } } } } // 处理显式重写 foreach (int idx in explicitOverrides) { MethodDef overDef = MethodDefList[idx]; ExplicitOverride(overDef, idx); } if (!Def.IsInterface) { foreach (var kv in VSlotMap) { string expSigName = kv.Key; VirtualSlot vslot = kv.Value; if (vslot.Entries.Count > 0) { if (!Def.IsAbstract && !vslot.Impl.IsValid()) { // 遇到非抽象类且存在空的绑定实现则报错 StringBuilder sb2 = new StringBuilder(); sb2.AppendFormat("Slot has no implementation. Class: {0}, Slot: {1}, ", this, expSigName); foreach (var item in vslot.Entries) { sb2.AppendFormat("{0} -> [", item.Key); foreach (var entryDef in item.Value) { sb2.AppendFormat("{0} ", entryDef); } sb2.Append(']'); } // 检查是否存在未实现的接口 throw new TypeLoadException(sb2.ToString()); } else { // 删除存在实现的接口入口 if (absNoImplSlots != null && vslot.Impl.IsValid()) { absNoImplSlots.Remove(expSigName); if (AbsNoImplSlotMap != null) { AbsNoImplSlotMap.Remove(expSigName); } } // 展平方法槽 foreach (var kv2 in vslot.Entries) { MethodTable entryTable = kv2.Key; foreach (MethodDef entryDef in kv2.Value) { SetExpandedVSlotMap(entryTable, entryDef, ref vslot.Impl); } } } } } } if (Helper.IsCollectionValid(absNoImplSlots)) { if (AbsNoImplSlotMap == null) { AbsNoImplSlotMap = new Dictionary <string, Dictionary <MethodTable, HashSet <MethodDef> > >(); } foreach (var expSigName in absNoImplSlots) { var vslot = VSlotMap[expSigName]; Debug.Assert(!vslot.Impl.IsValid()); if (!AbsNoImplSlotMap.TryGetValue(expSigName, out var defMap)) { defMap = new Dictionary <MethodTable, HashSet <MethodDef> >(); AbsNoImplSlotMap.Add(expSigName, defMap); } foreach (var entry in vslot.Entries) { if (!defMap.TryGetValue(entry.Key, out var defSet)) { defSet = new HashSet <MethodDef>(); defMap.Add(entry.Key, defSet); } defSet.UnionWith(entry.Value); } } } }
public VirtualTable ExpandVTable(IList <TypeSig> tyGenArgs) { Debug.Assert(!HasGenArgs); Debug.Assert(tyGenArgs == null || Def.GenericParameters.Count == tyGenArgs.Count); // 展开当前类型名 StringBuilder sb = new StringBuilder(); Helper.TypeNameKey(sb, Def, tyGenArgs); string thisNameKey = sb.ToString(); sb = null; // 构建泛型替换器 IGenericReplacer replacer = null; if (Helper.IsCollectionValid(tyGenArgs)) { replacer = new TypeDefGenReplacer(Def, tyGenArgs); } // 替换类型名称 var newSlotMap = new Dictionary <string, Tuple <string, MethodDef> >(); foreach (var kv in NewSlotMap) { MethodTable slotTable = kv.Value.Item1; string slotType = slotTable == this ? thisNameKey : slotTable.GetReplacedNameKey(replacer); newSlotMap.Add(kv.Key, new Tuple <string, MethodDef>(slotType, kv.Value.Item2)); } var metReplaceMap = new Dictionary <MethodDef, Tuple <string, MethodDef> >(); foreach (var kv in MethodReplaceMap) { MethodTable repTable = kv.Value.Item1; string repType = repTable == this ? thisNameKey : repTable.GetReplacedNameKey(replacer); metReplaceMap.Add(kv.Key, new Tuple <string, MethodDef>(repType, kv.Value.Item2)); } var fallbackTable = new Dictionary <string, MethodDef>(); if (Helper.IsCollectionValid(SameSigResolvedMap)) { foreach (var kv in SameSigResolvedMap) { MethodTable resTable = kv.Value.Item1; string resType = resTable == this ? thisNameKey : resTable.GetReplacedNameKey(replacer); fallbackTable.Add(resType, kv.Value.Item2); } } VirtualTable vtable = new VirtualTable(newSlotMap, metReplaceMap, fallbackTable); // 不可实例化的类型不展开虚表 if (Def.IsAbstract || Def.IsInterface) { return(vtable); } foreach (var kv in ExpandedVSlotMap) { MethodTable entryTable = kv.Key; Debug.Assert(entryTable != null); foreach (var item in kv.Value) { MethodDef entryDef = item.Key; Debug.Assert(entryDef != null); MethodTable implTable = item.Value.ImplTable; MethodDef implDef = item.Value.ImplMethod; Debug.Assert(implTable != null); string entryTypeName = entryTable == this ? thisNameKey : entryTable.GetReplacedNameKey(replacer); string implTypeName = implTable == this ? thisNameKey : implTable.GetReplacedNameKey(replacer); vtable.Set(entryTypeName, entryDef, implTypeName, implDef); } } return(vtable); }