public static int getSizeConsumed(@Nonnull AbstractInsnNode insn) {
		// Just a note about this consumed and the other produced method, ASM has a giant
		// array in MethodWriter that has the total delta, but in some cases you want to know
		// both components that combine into the final delta. It also skips entries that are
		// not constant, so we would still need some edge-case handling anyways.
		int op = insn.getOpcode();
		int type = insn.getType();
		if (type == AbstractInsnNode.MULTIANEWARRAY_INSN) {
			return ((MultiANewArrayInsnNode) insn).dims;
		} else if (type == AbstractInsnNode.METHOD_INSN) {
			MethodInsnNode min = (MethodInsnNode) insn;
			Type methodType = Type.getMethodType(min.desc);
			int count = op == INVOKESTATIC ? 0 : 1;
			for (Type argType : methodType.getArgumentTypes()) {
				count += argType.getSize();
			}
			return count;
		} else if (type == AbstractInsnNode.INVOKE_DYNAMIC_INSN) {
			Type methodType = Type.getMethodType(((InvokeDynamicInsnNode) insn).desc);
			int count = 0;
			for (Type argType : methodType.getArgumentTypes()) {
				count += argType.getSize();
			}
			return count;
		} else if (type == AbstractInsnNode.FIELD_INSN) {
			FieldInsnNode fin = (FieldInsnNode) insn;
			if (op == GETSTATIC)
				return 0;
			if (op == GETFIELD)
				return 1; // owner-value

			if (op == PUTSTATIC)
				return Type.getType(fin.desc).getSize(); // value (can be wide)
			if (op == PUTFIELD)
				return 1 + Type.getType(fin.desc).getSize(); // owner, value (can be wide)
		} else if (type == AbstractInsnNode.FRAME ||
				type == AbstractInsnNode.LABEL ||
				type == AbstractInsnNode.LINE) {
			return 0;
		}
		// noinspection EnhancedSwitchMigration
		switch (op) {
			// visitInsn
			case NOP:
			case ACONST_NULL:
			case ICONST_M1:
			case ICONST_0:
			case ICONST_1:
			case ICONST_2:
			case ICONST_3:
			case ICONST_4:
			case ICONST_5:
			case LCONST_0:
			case LCONST_1:
			case FCONST_0:
			case FCONST_1:
			case FCONST_2:
			case DCONST_0:
			case DCONST_1:
				return 0;
			// visitIntInsn
			case BIPUSH:
			case SIPUSH:
				return 0;
			// visitLdcInsn
			case LDC:
				return 0;
			// visitVarInsn
			case ILOAD:
			case LLOAD:
			case FLOAD:
			case DLOAD:
			case ALOAD:
				return 0;
			// visitInsn
			case IALOAD:
			case LALOAD:
			case FALOAD:
			case DALOAD:
			case AALOAD:
			case BALOAD:
			case CALOAD:
			case SALOAD:
				return 2; // arrayref, index
			// visitVarInsn
			case ISTORE:
			case FSTORE:
			case ASTORE:
				return 1; // value
			case DSTORE:
			case LSTORE:
				return 2; // wide-value
			// visitInsn
			case IASTORE:
			case FASTORE:
			case AASTORE:
			case BASTORE:
			case CASTORE:
			case SASTORE:
				return 3; // arrayref, index, value
			case DASTORE:
			case LASTORE:
				return 4; // arrayref, index, wide-value
			case POP:
				return 1; // value
			case POP2:
				return 2; // value x2 or wide-value
			case DUP:
			case DUP_X1:
			case DUP_X2:
			case DUP2:
			case DUP2_X1:
			case DUP2_X2:
			case SWAP:
				return 0; // Does not "consume" technically
			case IADD:
			case FADD:
			case ISUB:
			case FSUB:
			case IMUL:
			case FMUL:
			case IDIV:
			case FDIV:
			case IREM:
			case FREM:
			case ISHL:
			case ISHR:
			case IUSHR:
			case IAND:
			case IXOR:
			case IOR:
				return 2; // value1, value2
			case DREM:
			case DDIV:
			case DMUL:
			case DSUB:
			case DADD:
			case LUSHR:
			case LSHR:
			case LSHL:
			case LREM:
			case LDIV:
			case LMUL:
			case LSUB:
			case LADD:
			case LAND:
			case LOR:
			case LXOR:
				return 4; // wide-value1, wide-value2
			case INEG:
			case FNEG:
				return 1; // value
			case DNEG:
			case LNEG:
				return 2; // wide-value
			// visitIincInsn
			case IINC:
				return 0;
			// visitInsn
			case I2L:
			case I2F:
			case I2D:
			case F2I:
			case F2L:
			case F2D:
			case I2B:
			case I2C:
			case I2S:
				return 1; // value
			case D2I:
			case D2L:
			case D2F:
			case L2I:
			case L2F:
			case L2D:
				return 2; // wide-value
			case FCMPL:
			case FCMPG:
				return 2; // value1, value2
			case LCMP:
			case DCMPL:
			case DCMPG:
				return 4; // wide-value1, wide-value2
			// visitJumpInsn
			case IFEQ:
			case IFNE:
			case IFLT:
			case IFGE:
			case IFGT:
			case IFLE:
			case IFNULL:
			case IFNONNULL:
				return 1; // value
			case IF_ICMPEQ:
			case IF_ICMPNE:
			case IF_ICMPLT:
			case IF_ICMPGE:
			case IF_ICMPGT:
			case IF_ICMPLE:
			case IF_ACMPEQ:
			case IF_ACMPNE:
				return 2; // value1, value2
			case GOTO:
				return 0;
			case JSR:
				return 0;
			// visitVarInsn
			case RET:
				return 0;
			// visiTableSwitchInsn/visitLookupSwitch
			case TABLESWITCH:
			case LOOKUPSWITCH:
				return 1; // value
			// visitInsn
			case IRETURN:
			case FRETURN:
			case ARETURN:
				return 1; // value
			case LRETURN:
			case DRETURN:
				return 2; // wide-value
			case RETURN:
				return 0;
			// visitTypeInsn
			case NEW:
				return 0;
			// visitIntInsn
			case NEWARRAY:
				return 1; // count
			// visitTypeInsn
			case ANEWARRAY:
				return 1; // count
			// visitInsn
			case ARRAYLENGTH:
				return 1; // array
			case ATHROW:
				return 1; // exception, but it technically should clear the stack
			// visitTypeInsn
			case CHECKCAST:
				return 0; // instance to verify, not technically consumed but referenced
			case INSTANCEOF:
				return 1; // value
			// visitInsn
			case MONITORENTER:
			case MONITOREXIT:
				return 1; // monitor
			default:
				throw new IllegalArgumentException("Unhandled instruction: " + op);
		}
	}
Computes the size of stack items consumed for the given operation of the instruction.
This considers {@code long} and {@code double} types taking two spaces.

@param insn
		Instruction to compute for.

@return Size of stack consumed. Never negative.

@see #getSizeProduced(AbstractInsnNode)
@see <a href="https://docs.oracle.com/javase/specs/jvms/se21/html/jvms-6.html#jvms-6.5">JVMS 6.5</a>
recaf-core/src/main/java/software/coley/recaf/util/AsmInsnUtil.java