Пример #1
0
        /// <summary>
        /// Gets the number of items popped from the stack by an instruction of the given opcode
        /// with the given operands.
        /// </summary>
        ///
        /// <returns>The number of items popped from the stack.</returns>
        ///
        /// <param name="opcode">The instruction opcode.</param>
        /// <param name="multinameKind">The type of the multiname operand for the instruction.
        /// If <paramref name="opcode"/> uses a multiname operand, this must be a valid multiname
        /// kind; otherwise, this argument is ignored.</param>
        /// <param name="argCount">The argument count for a call-like instruction. If
        /// <paramref name="opcode"/> does not use an argument count, this argument is ignored.</param>
        ///
        /// <exception cref="AVM2Exception">ArgumentError #10061: <paramref name="argCount"/> is negative,
        /// <paramref name="opcode"/> is not the opcode of a valid instruction, or <paramref name="opcode"/>
        /// represents an instruction with a multiname argument and <paramref name="multinameKind"/> is not
        /// a valid multiname kind.</exception>
        public static int getStackPopCount(ABCOp opcode, ABCConstKind multinameKind = 0, int argCount = 0)
        {
            if (argCount < 0)
            {
                throw ErrorHelper.createError(ErrorCode.MARIANA__ARGUMENT_OUT_OF_RANGE, nameof(argCount));
            }

            ABCOpInfo opInfo = s_opinfo[(byte)opcode];

            if (!opInfo.isValid)
            {
                throw ErrorHelper.createError(ErrorCode.MARIANA__ARGUMENT_OUT_OF_RANGE, nameof(opcode));
            }

            (int popCount, bool hasMultiname) = opcode switch {
                ABCOp.newarray => (argCount, false),
                ABCOp.newobject => (checked (argCount * 2), false),
                ABCOp.call => (argCount + 2, false),

                ABCOp.construct or ABCOp.callmethod or ABCOp.callstatic
                or ABCOp.constructsuper or ABCOp.applytype =>
                (argCount + 1, false),

                ABCOp.callproperty or ABCOp.callproplex or ABCOp.callpropvoid
                or ABCOp.callsuper or ABCOp.callsupervoid or ABCOp.constructprop =>
                (argCount + 1, true),

                ABCOp.finddef or ABCOp.findproperty or ABCOp.findpropstrict => (0, true),
                ABCOp.deleteproperty or ABCOp.getdescendants or ABCOp.getproperty or ABCOp.getsuper => (1, true),
                ABCOp.setproperty or ABCOp.setsuper or ABCOp.initproperty => (2, true),

                _ => (opInfo.stackPopCount, false)
            };

            if (!hasMultiname)
            {
                return(popCount);
            }

            return(multinameKind switch {
                ABCConstKind.QName or ABCConstKind.QNameA or ABCConstKind.Multiname or ABCConstKind.MultinameA => popCount,
                ABCConstKind.RTQName or ABCConstKind.RTQNameA or ABCConstKind.MultinameL or ABCConstKind.MultinameLA => popCount + 1,
                ABCConstKind.RTQNameL or ABCConstKind.RTQNameLA => popCount + 2,
                _ => throw ErrorHelper.createError(ErrorCode.MARIANA__ARGUMENT_OUT_OF_RANGE, nameof(multinameKind)),
            });
Пример #2
0
 /// <summary>
 /// Gets the name of the given opcode as a string.
 /// </summary>
 /// <returns>The name of the opcode. If the opcode is not valid, returns null.</returns>
 /// <param name="opcode">The opcode.</param>
 public static string getName(ABCOp opcode) => s_names[(byte)opcode];
Пример #3
0
 /// <summary>
 /// Gets the <see cref="ABCOpInfo"/> instance for the given opcode.
 /// </summary>
 /// <returns>An <see cref="ABCOpInfo"/> instance.</returns>
 /// <param name="opcode">The opcode.</param>
 public static ABCOpInfo getInfo(ABCOp opcode) => s_opinfo[(byte)opcode];