コード例 #1
0
        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;
            }
コード例 #2
0
        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;
            }
コード例 #3
0
        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;
        }
コード例 #4
0
ファイル: TypeManager.cs プロジェクト: leha-bot/il2cpp
        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;
        }