/// <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)), });
/// <summary> /// Resolves a constant value in the ABC file. /// </summary> /// <returns>The constant value, boxed into an <see cref="ASAny"/> instance.</returns> /// <param name="kind">The type of the constant.</param> /// <param name="index">The index of the constant in the ABC file, in the constant pool /// determined by <paramref name="kind"/>.</param> /// <exception cref="AVM2Exception"> /// <list type="bullet"> /// <item><description>VerifyError #1032: <paramref name="index"/> is negative /// or outside the range of the constant pool for the type specified by /// <paramref name="kind"/>.</description></item> /// <item><description>ArgumentError #10061: <paramref name="kind"/> is not /// a valid constant kind.</description></item> /// </list> /// </exception> public ASAny resolveConstant(ABCConstKind kind, int index) { return(kind switch { ABCConstKind.Int => resolveInt(index), ABCConstKind.UInt => resolveUint(index), ABCConstKind.Double => resolveDouble(index), ABCConstKind.Utf8 => resolveString(index), ABCConstKind.True => true, ABCConstKind.False => false, ABCConstKind.Null => ASAny.@null, ABCConstKind.Undefined => ASAny.undefined, ABCConstKind.Namespace or ABCConstKind.PackageNamespace or ABCConstKind.PackageInternalNs or ABCConstKind.ProtectedNamespace or ABCConstKind.StaticProtectedNs or ABCConstKind.ExplicitNamespace or ABCConstKind.PrivateNs => new ASNamespace(resolveNamespace(index).uri !), _ => throw ErrorHelper.createError(ErrorCode.MARIANA__ARGUMENT_OUT_OF_RANGE, nameof(kind)), });
internal ABCMultiname(ABCConstKind kind, int index1, int index2) { m_kind = kind; m_index1 = index1; m_index2 = index2; }