コード例 #1
0
        /// <summary>
        /// return the first emitted instruction
        /// </summary>
        private Instruction TryCatchEmitTargetInstruction(FinallyTarget target, ref int insIdx, FinallyBlockState outerFinallyBlock)
        {
            bool emitReturn = outerFinallyBlock == null && target.IsReturn;

            bool chainToOuterBlock = outerFinallyBlock != null && target.IsReturn;

            if (target.IsLeave && outerFinallyBlock != null)
            {
                // check if the leave leaves the outer finally block as well.
                if (target.Destination.Index < outerFinallyBlock.FirstInstruction.Index ||
                    target.Destination.Index > outerFinallyBlock.LastInstruction.Index)
                {
                    chainToOuterBlock = true;
                }
            }

            if (emitReturn)
            {
                Instruction ret;
                if (currentMethod.ReturnsVoid)
                {
                    ret = new Instruction(RCode.Return_void);
                }
                else
                {
                    var retCode = currentMethod.ReturnsDexWide
                        ? RCode.Return_wide
                        : currentMethod.ReturnsDexValue
                            ? RCode.Return
                            : RCode.Return_object;
                    ret = new Instruction(retCode, finallyState.ReturnValueRegister);
                }
                instructions.Insert(insIdx++, ret);
                return(ret);
            }
            else if (chainToOuterBlock)
            {
                Debug.Assert(outerFinallyBlock != null);
                int id = target.SetTarget.Code == RCode.Nop ? 0 : (int)target.SetTarget.Operand;

                RLRange range;
                if (target.IsReturn)
                {
                    range = outerFinallyBlock.BranchToFinally_Ret(ref insIdx);
                }
                else // IsLeave
                {
                    range = outerFinallyBlock.BranchToFinally_Leave(target.Destination, ref insIdx);
                }

                // This is a little bit hackish. We need to set the operand in the setTarget instruction.
                if (id == 0)
                {
                    range.First.ConvertToNop();
                }
                else
                {
                    range.First.Operand = id;
                }

                return(range.First);
            }
            else
            {
                // goto
                var insGoto = new Instruction(RCode.Goto, target.Destination);
                instructions.Insert(insIdx++, insGoto);
                return(insGoto);
            }
        }
コード例 #2
0
        /// <summary>
        /// return the first emitted instruction
        /// </summary>
        private Instruction TryCatchEmitTargetInstruction(FinallyTarget target, ref int insIdx, FinallyBlockState outerFinallyBlock)
        {
            bool emitReturn = outerFinallyBlock == null && target.IsReturn;

            bool chainToOuterBlock = outerFinallyBlock != null && target.IsReturn;

            if (target.IsLeave && outerFinallyBlock != null)
            {
                // check if the leave leaves the outer finally block as well.
                if (target.Destination.Index < outerFinallyBlock.FirstInstruction.Index
                 || target.Destination.Index > outerFinallyBlock.LastInstruction.Index)
                {
                    chainToOuterBlock = true;
                }
            }

            if (emitReturn)
            {
                Instruction ret;
                if (currentMethod.ReturnsVoid)
                {
                    ret = new Instruction(RCode.Return_void);
                }
                else
                {
                    var retCode = currentMethod.ReturnsDexWide
                        ? RCode.Return_wide
                        : currentMethod.ReturnsDexValue
                            ? RCode.Return
                            : RCode.Return_object;
                    ret = new Instruction(retCode, finallyState.ReturnValueRegister);
                }
                instructions.Insert(insIdx++, ret);
                return ret;
            }
            else if (chainToOuterBlock)
            {
                Debug.Assert(outerFinallyBlock != null);
                int id = target.SetTarget.Code == RCode.Nop ? 0 : (int)target.SetTarget.Operand;

                RLRange range;
                if (target.IsReturn)
                    range = outerFinallyBlock.BranchToFinally_Ret(ref insIdx);
                else // IsLeave
                    range = outerFinallyBlock.BranchToFinally_Leave(target.Destination, ref insIdx);

                // This is a little bit hackish. We need to set the operand in the setTarget instruction.
                if (id == 0) range.First.ConvertToNop();
                else range.First.Operand = id;

                return range.First;
            }
            else
            {
                // goto
                var insGoto = new Instruction(RCode.Goto, target.Destination);
                instructions.Insert(insIdx++, insGoto);
                return insGoto;
            }
        }