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 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; }
private void BuildInstructions(MethodX metX) { Debug.Assert(metX.InstList == null); if (!metX.Def.HasBody || !metX.Def.Body.HasInstructions) { return; } IGenericReplacer replacer = new GenericReplacer(metX.DeclType, metX); var defInstList = metX.Def.Body.Instructions; int numInsts = defInstList.Count; InstInfo[] instList = new InstInfo[numInsts]; Dictionary <uint, int> offsetMap = new Dictionary <uint, int>(); List <InstInfo> branchInsts = new List <InstInfo>(); // 构建指令列表 for (int ip = 0; ip < numInsts; ++ip) { var defInst = defInstList[ip]; var inst = instList[ip] = new InstInfo(); inst.OpCode = defInst.OpCode; inst.Operand = defInst.Operand; inst.Offset = ip; offsetMap.Add(defInst.Offset, ip); switch (inst.OpCode.OperandType) { case OperandType.InlineBrTarget: case OperandType.ShortInlineBrTarget: case OperandType.InlineSwitch: branchInsts.Add(inst); break; default: ResolveOperand(inst, replacer); break; } } // 重定向跳转位置 foreach (var inst in branchInsts) { if (inst.Operand is Instruction defInst) { int target; inst.Operand = target = offsetMap[defInst.Offset]; instList[target].IsBrTarget = true; } else if (inst.Operand is Instruction[] defInsts) { int[] insts = new int[defInsts.Length]; for (int i = 0; i < defInsts.Length; ++i) { int target; insts[i] = target = offsetMap[defInsts[i].Offset]; instList[target].IsBrTarget = true; } inst.Operand = insts; } } metX.InstList = instList; }
private void BuildInstructions(MethodX metX) { Debug.Assert(metX.InstList == null); if (!metX.Def.HasBody || !metX.Def.Body.HasInstructions) { return; } IGenericReplacer replacer = new GenericReplacer(metX.DeclType, metX); var defInstList = metX.Def.Body.Instructions; int numInsts = defInstList.Count; InstInfo[] instList = new InstInfo[numInsts]; Dictionary <uint, int> offsetMap = new Dictionary <uint, int>(); List <InstInfo> branchInsts = new List <InstInfo>(); // 构建指令列表 for (int ip = 0; ip < numInsts; ++ip) { var defInst = defInstList[ip]; var inst = instList[ip] = new InstInfo(); inst.OpCode = defInst.OpCode; inst.Operand = defInst.Operand; inst.Offset = ip; offsetMap.Add(defInst.Offset, ip); switch (inst.OpCode.OperandType) { case OperandType.InlineBrTarget: case OperandType.ShortInlineBrTarget: case OperandType.InlineSwitch: branchInsts.Add(inst); break; default: ResolveOperand(inst, replacer); break; } } // 重定向跳转位置 foreach (var inst in branchInsts) { if (inst.Operand is Instruction defInst) { int target; inst.Operand = target = offsetMap[defInst.Offset]; instList[target].IsBrTarget = true; } else if (inst.Operand is Instruction[] defInsts) { int[] insts = new int[defInsts.Length]; for (int i = 0; i < defInsts.Length; ++i) { int target; insts[i] = target = offsetMap[defInsts[i].Offset]; instList[target].IsBrTarget = true; } inst.Operand = insts; } } // 展开异常处理信息 if (metX.Def.Body.HasExceptionHandlers) { List <Tuple <int, ExHandlerInfo> > sortedHandlers = new List <Tuple <int, ExHandlerInfo> >(); int idx = 0; foreach (var eh in metX.Def.Body.ExceptionHandlers) { ExHandlerInfo info = new ExHandlerInfo(); info.TryStart = offsetMap[eh.TryStart.Offset]; info.TryEnd = offsetMap[eh.TryEnd.Offset]; if (eh.FilterStart != null) { info.FilterStart = offsetMap[eh.FilterStart.Offset]; } else { info.FilterStart = -1; } info.HandlerStart = offsetMap[eh.HandlerStart.Offset]; if (eh.HandlerEnd != null) { info.HandlerEnd = offsetMap[eh.HandlerEnd.Offset]; } else { info.HandlerEnd = instList.Length; } if (eh.CatchType != null) { info.CatchType = ResolveTypeDefOrRef(eh.CatchType, replacer); } info.HandlerType = eh.HandlerType; sortedHandlers.Add(new Tuple <int, ExHandlerInfo>(idx++, info)); } // 根据 try 位置排序, 如果相同则根据定义顺序排序 sortedHandlers.Sort((lhs, rhs) => { int cmp = lhs.Item2.TryStart.CompareTo(rhs.Item2.TryStart); if (cmp == 0) { cmp = rhs.Item2.TryEnd.CompareTo(lhs.Item2.TryEnd); if (cmp == 0) { return(lhs.Item1.CompareTo(rhs.Item1)); } } return(cmp); }); // 合并同范围的异常处理器 List <ExHandlerInfo> handlers = new List <ExHandlerInfo>(); ExHandlerInfo headInfo = null; int count = sortedHandlers.Count; for (int i = 0; i < count; ++i) { ExHandlerInfo currInfo = sortedHandlers[i].Item2; if (headInfo != null && headInfo.NeedCombine(currInfo)) { headInfo.CombinedHandlers.Add(currInfo); } else { headInfo = currInfo; Debug.Assert(headInfo.CombinedHandlers.Count == 0); headInfo.CombinedHandlers.Add(headInfo); handlers.Add(headInfo); } instList[currInfo.HandlerOrFilterStart].IsBrTarget = true; } metX.ExHandlerList = handlers; } metX.InstList = instList; }