All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.dmlloyd.classfile.Opcode Maven / Gradle / Ivy

There is a newer version: 24.beta3
Show newest version
/*
 * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package io.github.dmlloyd.classfile;

import java.lang.constant.ConstantDesc;
import java.lang.constant.ConstantDescs;
import io.github.dmlloyd.classfile.extras.PreviewFeature;

/**
 * Describes the opcodes of the JVM instruction set, as described in JVMS {@jvms 6.5}.
 * As well as a number of pseudo-instructions that may be encountered when
 * traversing the instructions of a method.
 *
 * @see Instruction
 * @see PseudoInstruction
 *
 * @since 22
 */
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
public enum Opcode {

    /** Do nothing */
    NOP(ClassFile.NOP, 1, Kind.NOP),

    /** Push null */
    ACONST_NULL(ClassFile.ACONST_NULL, 1, Kind.CONSTANT, TypeKind.ReferenceType, 0, ConstantDescs.NULL),

    /** Push int constant -1 */
    ICONST_M1(ClassFile.ICONST_M1, 1, Kind.CONSTANT, TypeKind.IntType, 0, -1),

    /** Push int constant 0 */
    ICONST_0(ClassFile.ICONST_0, 1, Kind.CONSTANT, TypeKind.IntType, 0, 0),

    /** Push int constant 1 */
    ICONST_1(ClassFile.ICONST_1, 1, Kind.CONSTANT, TypeKind.IntType, 0, 1),

    /** Push int constant 2 */
    ICONST_2(ClassFile.ICONST_2, 1, Kind.CONSTANT, TypeKind.IntType, 0, 2),

    /** Push int constant 3 */
    ICONST_3(ClassFile.ICONST_3, 1, Kind.CONSTANT, TypeKind.IntType, 0, 3),

    /** Push int constant 4 */
    ICONST_4(ClassFile.ICONST_4, 1, Kind.CONSTANT, TypeKind.IntType, 0, 4),

    /** Push int constant 5 */
    ICONST_5(ClassFile.ICONST_5, 1, Kind.CONSTANT, TypeKind.IntType, 0, 5),

    /** Push long constant 0 */
    LCONST_0(ClassFile.LCONST_0, 1, Kind.CONSTANT, TypeKind.LongType, 0, 0L),

    /** Push long constant  1 */
    LCONST_1(ClassFile.LCONST_1, 1, Kind.CONSTANT, TypeKind.LongType, 0, 1L),

    /** Push float constant 0 */
    FCONST_0(ClassFile.FCONST_0, 1, Kind.CONSTANT, TypeKind.FloatType, 0, 0.0f),

    /** Push float constant 1 */
    FCONST_1(ClassFile.FCONST_1, 1, Kind.CONSTANT, TypeKind.FloatType, 0, 1.0f),

    /** Push float constant 2 */
    FCONST_2(ClassFile.FCONST_2, 1, Kind.CONSTANT, TypeKind.FloatType, 0, 2.0f),

    /** Push double constant 0 */
    DCONST_0(ClassFile.DCONST_0, 1, Kind.CONSTANT, TypeKind.DoubleType, 0, 0.0d),

    /** Push double constant 1 */
    DCONST_1(ClassFile.DCONST_1, 1, Kind.CONSTANT, TypeKind.DoubleType, 0, 1.0d),

    /** Push byte */
    BIPUSH(ClassFile.BIPUSH, 2, Kind.CONSTANT, TypeKind.ByteType),

    /** Push short */
    SIPUSH(ClassFile.SIPUSH, 3, Kind.CONSTANT, TypeKind.ShortType),

    /** Push item from run-time constant pool */
    LDC(ClassFile.LDC, 2, Kind.CONSTANT),

    /** Push item from run-time constant pool (wide index) */
    LDC_W(ClassFile.LDC_W, 3, Kind.CONSTANT),

    /** Push long or double from run-time constant pool (wide index) */
    LDC2_W(ClassFile.LDC2_W, 3, Kind.CONSTANT),

    /** Load int from local variable */
    ILOAD(ClassFile.ILOAD, 2, Kind.LOAD, TypeKind.IntType, -1),

    /** Load long from local variable */
    LLOAD(ClassFile.LLOAD, 2, Kind.LOAD, TypeKind.LongType, -1),

    /** Load float from local variable */
    FLOAD(ClassFile.FLOAD, 2, Kind.LOAD, TypeKind.FloatType, -1),

    /** Load double from local variable */
    DLOAD(ClassFile.DLOAD, 2, Kind.LOAD, TypeKind.DoubleType, -1),

    /** Load reference from local variable */
    ALOAD(ClassFile.ALOAD, 2, Kind.LOAD, TypeKind.ReferenceType, -1),

    /** Load int from local variable 0 */
    ILOAD_0(ClassFile.ILOAD_0, 1, Kind.LOAD, TypeKind.IntType, 0),

    /** Load int from local variable 1 */
    ILOAD_1(ClassFile.ILOAD_1, 1, Kind.LOAD, TypeKind.IntType, 1),

    /** Load int from local variable 2 */
    ILOAD_2(ClassFile.ILOAD_2, 1, Kind.LOAD, TypeKind.IntType, 2),

    /** Load int from local variable3  */
    ILOAD_3(ClassFile.ILOAD_3, 1, Kind.LOAD, TypeKind.IntType, 3),

    /** Load long from local variable 0 */
    LLOAD_0(ClassFile.LLOAD_0, 1, Kind.LOAD, TypeKind.LongType, 0),

    /** Load long from local variable 1 */
    LLOAD_1(ClassFile.LLOAD_1, 1, Kind.LOAD, TypeKind.LongType, 1),

    /** Load long from local variable 2 */
    LLOAD_2(ClassFile.LLOAD_2, 1, Kind.LOAD, TypeKind.LongType, 2),

    /** Load long from local variable 3 */
    LLOAD_3(ClassFile.LLOAD_3, 1, Kind.LOAD, TypeKind.LongType, 3),

    /** Load float from local variable 0 */
    FLOAD_0(ClassFile.FLOAD_0, 1, Kind.LOAD, TypeKind.FloatType, 0),

    /** Load float from local variable 1 */
    FLOAD_1(ClassFile.FLOAD_1, 1, Kind.LOAD, TypeKind.FloatType, 1),

    /** Load float from local variable 2 */
    FLOAD_2(ClassFile.FLOAD_2, 1, Kind.LOAD, TypeKind.FloatType, 2),

    /** Load float from local variable 3 */
    FLOAD_3(ClassFile.FLOAD_3, 1, Kind.LOAD, TypeKind.FloatType, 3),

    /** Load double from local variable 0 */
    DLOAD_0(ClassFile.DLOAD_0, 1, Kind.LOAD, TypeKind.DoubleType, 0),

    /** Load double from local variable 1 */
    DLOAD_1(ClassFile.DLOAD_1, 1, Kind.LOAD, TypeKind.DoubleType, 1),

    /** Load double from local variable 2 */
    DLOAD_2(ClassFile.DLOAD_2, 1, Kind.LOAD, TypeKind.DoubleType, 2),

    /** Load double from local variable 3 */
    DLOAD_3(ClassFile.DLOAD_3, 1, Kind.LOAD, TypeKind.DoubleType, 3),

    /**  Load reference from local variable 0 */
    ALOAD_0(ClassFile.ALOAD_0, 1, Kind.LOAD, TypeKind.ReferenceType, 0),

    /** Load reference from local variable 1 */
    ALOAD_1(ClassFile.ALOAD_1, 1, Kind.LOAD, TypeKind.ReferenceType, 1),

    /** Load reference from local variable 2 */
    ALOAD_2(ClassFile.ALOAD_2, 1, Kind.LOAD, TypeKind.ReferenceType, 2),

    /** Load reference from local variable 3 */
    ALOAD_3(ClassFile.ALOAD_3, 1, Kind.LOAD, TypeKind.ReferenceType, 3),

    /** Load int from array */
    IALOAD(ClassFile.IALOAD, 1, Kind.ARRAY_LOAD, TypeKind.IntType),

    /** Load long from array */
    LALOAD(ClassFile.LALOAD, 1, Kind.ARRAY_LOAD, TypeKind.LongType),

    /** Load float from array */
    FALOAD(ClassFile.FALOAD, 1, Kind.ARRAY_LOAD, TypeKind.FloatType),

    /** Load double from array */
    DALOAD(ClassFile.DALOAD, 1, Kind.ARRAY_LOAD, TypeKind.DoubleType),

    /** Load reference from array */
    AALOAD(ClassFile.AALOAD, 1, Kind.ARRAY_LOAD, TypeKind.ReferenceType),

    /** Load byte from array */
    BALOAD(ClassFile.BALOAD, 1, Kind.ARRAY_LOAD, TypeKind.ByteType),

    /** Load char from array */
    CALOAD(ClassFile.CALOAD, 1, Kind.ARRAY_LOAD, TypeKind.CharType),

    /** Load short from array */
    SALOAD(ClassFile.SALOAD, 1, Kind.ARRAY_LOAD, TypeKind.ShortType),

    /** Store int into local variable */
    ISTORE(ClassFile.ISTORE, 2, Kind.STORE, TypeKind.IntType, -1),

    /** Store long into local variable */
    LSTORE(ClassFile.LSTORE, 2, Kind.STORE, TypeKind.LongType, -1),

    /** Store float into local variable */
    FSTORE(ClassFile.FSTORE, 2, Kind.STORE, TypeKind.FloatType, -1),

    /** Store double into local variable */
    DSTORE(ClassFile.DSTORE, 2, Kind.STORE, TypeKind.DoubleType, -1),

    /** Store reference into local variable */
    ASTORE(ClassFile.ASTORE, 2, Kind.STORE, TypeKind.ReferenceType, -1),

    /** Store int into local variable 0 */
    ISTORE_0(ClassFile.ISTORE_0, 1, Kind.STORE, TypeKind.IntType, 0),

    /** Store int into local variable 1 */
    ISTORE_1(ClassFile.ISTORE_1, 1, Kind.STORE, TypeKind.IntType, 1),

    /** Store int into local variable 2 */
    ISTORE_2(ClassFile.ISTORE_2, 1, Kind.STORE, TypeKind.IntType, 2),

    /** Store int into local variable 3 */
    ISTORE_3(ClassFile.ISTORE_3, 1, Kind.STORE, TypeKind.IntType, 3),

    /** Store long into local variable 0 */
    LSTORE_0(ClassFile.LSTORE_0, 1, Kind.STORE, TypeKind.LongType, 0),

    /** Store long into local variable 1 */
    LSTORE_1(ClassFile.LSTORE_1, 1, Kind.STORE, TypeKind.LongType, 1),

    /** Store long into local variable 2 */
    LSTORE_2(ClassFile.LSTORE_2, 1, Kind.STORE, TypeKind.LongType, 2),

    /** Store long into local variable 3 */
    LSTORE_3(ClassFile.LSTORE_3, 1, Kind.STORE, TypeKind.LongType, 3),

    /** Store float into local variable 0 */
    FSTORE_0(ClassFile.FSTORE_0, 1, Kind.STORE, TypeKind.FloatType, 0),

    /** Store float into local variable 1 */
    FSTORE_1(ClassFile.FSTORE_1, 1, Kind.STORE, TypeKind.FloatType, 1),

    /** Store float into local variable 2 */
    FSTORE_2(ClassFile.FSTORE_2, 1, Kind.STORE, TypeKind.FloatType, 2),

    /** Store float into local variable 3 */
    FSTORE_3(ClassFile.FSTORE_3, 1, Kind.STORE, TypeKind.FloatType, 3),

    /** Store double into local variable 0 */
    DSTORE_0(ClassFile.DSTORE_0, 1, Kind.STORE, TypeKind.DoubleType, 0),

    /** Store double into local variable 1 */
    DSTORE_1(ClassFile.DSTORE_1, 1, Kind.STORE, TypeKind.DoubleType, 1),

    /** Store double into local variable 2 */
    DSTORE_2(ClassFile.DSTORE_2, 1, Kind.STORE, TypeKind.DoubleType, 2),

    /** Store double into local variable 3 */
    DSTORE_3(ClassFile.DSTORE_3, 1, Kind.STORE, TypeKind.DoubleType, 3),

    /** Store reference into local variable 0 */
    ASTORE_0(ClassFile.ASTORE_0, 1, Kind.STORE, TypeKind.ReferenceType, 0),

    /** Store reference into local variable 1 */
    ASTORE_1(ClassFile.ASTORE_1, 1, Kind.STORE, TypeKind.ReferenceType, 1),

    /** Store reference into local variable 2 */
    ASTORE_2(ClassFile.ASTORE_2, 1, Kind.STORE, TypeKind.ReferenceType, 2),

    /** Store reference into local variable 3 */
    ASTORE_3(ClassFile.ASTORE_3, 1, Kind.STORE, TypeKind.ReferenceType, 3),

    /** Store into int array */
    IASTORE(ClassFile.IASTORE, 1, Kind.ARRAY_STORE, TypeKind.IntType),

    /** Store into long array */
    LASTORE(ClassFile.LASTORE, 1, Kind.ARRAY_STORE, TypeKind.LongType),

    /** Store into float array */
    FASTORE(ClassFile.FASTORE, 1, Kind.ARRAY_STORE, TypeKind.FloatType),

    /** Store into double array */
    DASTORE(ClassFile.DASTORE, 1, Kind.ARRAY_STORE, TypeKind.DoubleType),

    /** Store into reference array */
    AASTORE(ClassFile.AASTORE, 1, Kind.ARRAY_STORE, TypeKind.ReferenceType),

    /** Store into byte array */
    BASTORE(ClassFile.BASTORE, 1, Kind.ARRAY_STORE, TypeKind.ByteType),

    /** Store into char array */
    CASTORE(ClassFile.CASTORE, 1, Kind.ARRAY_STORE, TypeKind.CharType),

    /** Store into short array */
    SASTORE(ClassFile.SASTORE, 1, Kind.ARRAY_STORE, TypeKind.ShortType),

    /** Pop the top operand stack value */
    POP(ClassFile.POP, 1, Kind.STACK),

    /** Pop the top one or two operand stack values */
    POP2(ClassFile.POP2, 1, Kind.STACK),

    /** Duplicate the top operand stack value */
    DUP(ClassFile.DUP, 1, Kind.STACK),

    /** Duplicate the top operand stack value and insert two values down */
    DUP_X1(ClassFile.DUP_X1, 1, Kind.STACK),

    /** Duplicate the top operand stack value and insert two or three values down */
    DUP_X2(ClassFile.DUP_X2, 1, Kind.STACK),

    /** Duplicate the top one or two operand stack values */
    DUP2(ClassFile.DUP2, 1, Kind.STACK),

    /** Duplicate the top one or two operand stack values and insert two or three values down */
    DUP2_X1(ClassFile.DUP2_X1, 1, Kind.STACK),

    /** Duplicate the top one or two operand stack values and insert two, three, or four values down */
    DUP2_X2(ClassFile.DUP2_X2, 1, Kind.STACK),

    /** Swap the top two operand stack values */
    SWAP(ClassFile.SWAP, 1, Kind.STACK),

    /** Add int */
    IADD(ClassFile.IADD, 1, Kind.OPERATOR, TypeKind.IntType),

    /** Add long */
    LADD(ClassFile.LADD, 1, Kind.OPERATOR, TypeKind.LongType),

    /** Add float */
    FADD(ClassFile.FADD, 1, Kind.OPERATOR, TypeKind.FloatType),

    /** Add double */
    DADD(ClassFile.DADD, 1, Kind.OPERATOR, TypeKind.DoubleType),

    /** Subtract int */
    ISUB(ClassFile.ISUB, 1, Kind.OPERATOR, TypeKind.IntType),

    /** Subtract long */
    LSUB(ClassFile.LSUB, 1, Kind.OPERATOR, TypeKind.LongType),

    /** Subtract float */
    FSUB(ClassFile.FSUB, 1, Kind.OPERATOR, TypeKind.FloatType),

    /** Subtract double */
    DSUB(ClassFile.DSUB, 1, Kind.OPERATOR, TypeKind.DoubleType),

    /** Multiply int */
    IMUL(ClassFile.IMUL, 1, Kind.OPERATOR, TypeKind.IntType),

    /** Multiply long */
    LMUL(ClassFile.LMUL, 1, Kind.OPERATOR, TypeKind.LongType),

    /** Multiply float */
    FMUL(ClassFile.FMUL, 1, Kind.OPERATOR, TypeKind.FloatType),

    /** Multiply double */
    DMUL(ClassFile.DMUL, 1, Kind.OPERATOR, TypeKind.DoubleType),

    /** Divide int */
    IDIV(ClassFile.IDIV, 1, Kind.OPERATOR, TypeKind.IntType),

    /** Divide long */
    LDIV(ClassFile.LDIV, 1, Kind.OPERATOR, TypeKind.LongType),

    /** Divide float */
    FDIV(ClassFile.FDIV, 1, Kind.OPERATOR, TypeKind.FloatType),

    /** Divide double */
    DDIV(ClassFile.DDIV, 1, Kind.OPERATOR, TypeKind.DoubleType),

    /** Remainder int */
    IREM(ClassFile.IREM, 1, Kind.OPERATOR, TypeKind.IntType),

    /** Remainder long */
    LREM(ClassFile.LREM, 1, Kind.OPERATOR, TypeKind.LongType),

    /** Remainder float */
    FREM(ClassFile.FREM, 1, Kind.OPERATOR, TypeKind.FloatType),

    /** Remainder double */
    DREM(ClassFile.DREM, 1, Kind.OPERATOR, TypeKind.DoubleType),

    /** Negate int */
    INEG(ClassFile.INEG, 1, Kind.OPERATOR, TypeKind.IntType),

    /** Negate long */
    LNEG(ClassFile.LNEG, 1, Kind.OPERATOR, TypeKind.LongType),

    /** Negate float */
    FNEG(ClassFile.FNEG, 1, Kind.OPERATOR, TypeKind.FloatType),

    /** Negate double */
    DNEG(ClassFile.DNEG, 1, Kind.OPERATOR, TypeKind.DoubleType),

    /** Shift left int */
    ISHL(ClassFile.ISHL, 1, Kind.OPERATOR, TypeKind.IntType),

    /** Shift left long */
    LSHL(ClassFile.LSHL, 1, Kind.OPERATOR, TypeKind.LongType),

    /** Shift right int */
    ISHR(ClassFile.ISHR, 1, Kind.OPERATOR, TypeKind.IntType),

    /** Shift right long */
    LSHR(ClassFile.LSHR, 1, Kind.OPERATOR, TypeKind.LongType),

    /** Logical shift right int */
    IUSHR(ClassFile.IUSHR, 1, Kind.OPERATOR, TypeKind.IntType),

    /** Logical shift right long */
    LUSHR(ClassFile.LUSHR, 1, Kind.OPERATOR, TypeKind.LongType),

    /** Boolean AND int */
    IAND(ClassFile.IAND, 1, Kind.OPERATOR, TypeKind.IntType),

    /** Boolean AND long */
    LAND(ClassFile.LAND, 1, Kind.OPERATOR, TypeKind.LongType),

    /** Boolean OR int */
    IOR(ClassFile.IOR, 1, Kind.OPERATOR, TypeKind.IntType),

    /** Boolean OR long */
    LOR(ClassFile.LOR, 1, Kind.OPERATOR, TypeKind.LongType),

    /** Boolean XOR int */
    IXOR(ClassFile.IXOR, 1, Kind.OPERATOR, TypeKind.IntType),

    /** Boolean XOR long */
    LXOR(ClassFile.LXOR, 1, Kind.OPERATOR, TypeKind.LongType),

    /** Increment local variable by constant */
    IINC(ClassFile.IINC, 3, Kind.INCREMENT, TypeKind.IntType, -1),

    /** Convert int to long */
    I2L(ClassFile.I2L, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.LongType),

    /** Convert int to float */
    I2F(ClassFile.I2F, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.FloatType),

    /** Convert int to double */
    I2D(ClassFile.I2D, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.DoubleType),

    /** Convert long to int */
    L2I(ClassFile.L2I, 1, Kind.CONVERT, TypeKind.LongType, TypeKind.IntType),

    /** Convert long to float */
    L2F(ClassFile.L2F, 1, Kind.CONVERT, TypeKind.LongType, TypeKind.FloatType),

    /** Convert long to double */
    L2D(ClassFile.L2D, 1, Kind.CONVERT, TypeKind.LongType, TypeKind.DoubleType),

    /** Convert float to int */
    F2I(ClassFile.F2I, 1, Kind.CONVERT, TypeKind.FloatType, TypeKind.IntType),

    /** Convert float to long */
    F2L(ClassFile.F2L, 1, Kind.CONVERT, TypeKind.FloatType, TypeKind.LongType),

    /** Convert float to double */
    F2D(ClassFile.F2D, 1, Kind.CONVERT, TypeKind.FloatType, TypeKind.DoubleType),

    /** Convert double to int */
    D2I(ClassFile.D2I, 1, Kind.CONVERT, TypeKind.DoubleType, TypeKind.IntType),

    /** Convert double to long */
    D2L(ClassFile.D2L, 1, Kind.CONVERT, TypeKind.DoubleType, TypeKind.LongType),

    /** Convert double to float */
    D2F(ClassFile.D2F, 1, Kind.CONVERT, TypeKind.DoubleType, TypeKind.FloatType),

    /** Convert int to byte */
    I2B(ClassFile.I2B, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.ByteType),

    /** Convert int to char */
    I2C(ClassFile.I2C, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.CharType),

    /** Convert int to short */
    I2S(ClassFile.I2S, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.ShortType),

    /** Compare long */
    LCMP(ClassFile.LCMP, 1, Kind.OPERATOR, TypeKind.LongType),

    /** Compare float */
    FCMPL(ClassFile.FCMPL, 1, Kind.OPERATOR, TypeKind.FloatType),

    /** Compare float */
    FCMPG(ClassFile.FCMPG, 1, Kind.OPERATOR, TypeKind.FloatType),

    /** Compare double */
    DCMPL(ClassFile.DCMPL, 1, Kind.OPERATOR, TypeKind.DoubleType),

    /** Compare double */
    DCMPG(ClassFile.DCMPG, 1, Kind.OPERATOR, TypeKind.DoubleType),

    /** Branch if int comparison with zero succeeds */
    IFEQ(ClassFile.IFEQ, 3, Kind.BRANCH, TypeKind.IntType),

    /** Branch if int comparison with zero succeeds */
    IFNE(ClassFile.IFNE, 3, Kind.BRANCH, TypeKind.IntType),

    /** Branch if int comparison with zero succeeds */
    IFLT(ClassFile.IFLT, 3, Kind.BRANCH, TypeKind.IntType),

    /** Branch if int comparison with zero succeeds */
    IFGE(ClassFile.IFGE, 3, Kind.BRANCH, TypeKind.IntType),

    /** Branch if int comparison with zero succeeds */
    IFGT(ClassFile.IFGT, 3, Kind.BRANCH, TypeKind.IntType),

    /** Branch if int comparison with zero succeeds */
    IFLE(ClassFile.IFLE, 3, Kind.BRANCH, TypeKind.IntType),

    /** Branch if int comparison succeeds */
    IF_ICMPEQ(ClassFile.IF_ICMPEQ, 3, Kind.BRANCH, TypeKind.IntType),

    /** Branch if int comparison succeeds */
    IF_ICMPNE(ClassFile.IF_ICMPNE, 3, Kind.BRANCH, TypeKind.IntType),

    /** Branch if int comparison succeeds */
    IF_ICMPLT(ClassFile.IF_ICMPLT, 3, Kind.BRANCH, TypeKind.IntType),

    /** Branch if int comparison succeeds */
    IF_ICMPGE(ClassFile.IF_ICMPGE, 3, Kind.BRANCH, TypeKind.IntType),

    /** Branch if int comparison succeeds */
    IF_ICMPGT(ClassFile.IF_ICMPGT, 3, Kind.BRANCH, TypeKind.IntType),

    /** Branch if int comparison succeeds */
    IF_ICMPLE(ClassFile.IF_ICMPLE, 3, Kind.BRANCH, TypeKind.IntType),

    /** Branch if reference comparison succeeds */
    IF_ACMPEQ(ClassFile.IF_ACMPEQ, 3, Kind.BRANCH, TypeKind.ReferenceType),

    /** Branch if reference comparison succeeds */
    IF_ACMPNE(ClassFile.IF_ACMPNE, 3, Kind.BRANCH, TypeKind.ReferenceType),

    /** Branch always */
    GOTO(ClassFile.GOTO, 3, Kind.BRANCH, TypeKind.VoidType),

    /**
     * Jump subroutine is discontinued opcode
     * @see io.github.dmlloyd.classfile.instruction.DiscontinuedInstruction
     */
    JSR(ClassFile.JSR, 3, Kind.DISCONTINUED_JSR),

    /**
     * Return from subroutine is discontinued opcode
     * @see io.github.dmlloyd.classfile.instruction.DiscontinuedInstruction
     */
    RET(ClassFile.RET, 2, Kind.DISCONTINUED_RET),

    /** Access jump table by index and jump */
    TABLESWITCH(ClassFile.TABLESWITCH, -1, Kind.TABLE_SWITCH),

    /** Access jump table by key match and jump */
    LOOKUPSWITCH(ClassFile.LOOKUPSWITCH, -1, Kind.LOOKUP_SWITCH),

    /** Return int from method */
    IRETURN(ClassFile.IRETURN, 1, Kind.RETURN, TypeKind.IntType),

    /** Return long from method */
    LRETURN(ClassFile.LRETURN, 1, Kind.RETURN, TypeKind.LongType),

    /** Return float from method */
    FRETURN(ClassFile.FRETURN, 1, Kind.RETURN, TypeKind.FloatType),

    /** Return double from method */
    DRETURN(ClassFile.DRETURN, 1, Kind.RETURN, TypeKind.DoubleType),

    /** Return reference from method */
    ARETURN(ClassFile.ARETURN, 1, Kind.RETURN, TypeKind.ReferenceType),

    /** Return void from method */
    RETURN(ClassFile.RETURN, 1, Kind.RETURN, TypeKind.VoidType),

    /** Get static field from class */
    GETSTATIC(ClassFile.GETSTATIC, 3, Kind.FIELD_ACCESS),

    /** Set static field in class */
    PUTSTATIC(ClassFile.PUTSTATIC, 3, Kind.FIELD_ACCESS),

    /** Fetch field from object */
    GETFIELD(ClassFile.GETFIELD, 3, Kind.FIELD_ACCESS),

    /** Set field in object */
    PUTFIELD(ClassFile.PUTFIELD, 3, Kind.FIELD_ACCESS),

    /** Invoke instance method; dispatch based on class */
    INVOKEVIRTUAL(ClassFile.INVOKEVIRTUAL, 3, Kind.INVOKE),

    /**
     * Invoke instance method; direct invocation of instance initialization
     * methods and methods of the current class and its supertypes
     */
    INVOKESPECIAL(ClassFile.INVOKESPECIAL, 3, Kind.INVOKE),

    /** Invoke a class (static) method */
    INVOKESTATIC(ClassFile.INVOKESTATIC, 3, Kind.INVOKE),

    /** Invoke interface method */
    INVOKEINTERFACE(ClassFile.INVOKEINTERFACE, 5, Kind.INVOKE),

    /** Invoke a dynamically-computed call site */
    INVOKEDYNAMIC(ClassFile.INVOKEDYNAMIC, 5, Kind.INVOKE_DYNAMIC),

    /** Create new object */
    NEW(ClassFile.NEW, 3, Kind.NEW_OBJECT),

    /** Create new array */
    NEWARRAY(ClassFile.NEWARRAY, 2, Kind.NEW_PRIMITIVE_ARRAY),

    /** Create new array of reference */
    ANEWARRAY(ClassFile.ANEWARRAY, 3, Kind.NEW_REF_ARRAY),

    /** Get length of array */
    ARRAYLENGTH(ClassFile.ARRAYLENGTH, 1, Kind.OPERATOR, TypeKind.IntType),

    /** Throw exception or error */
    ATHROW(ClassFile.ATHROW, 1, Kind.THROW_EXCEPTION),

    /** Check whether object is of given type */
    CHECKCAST(ClassFile.CHECKCAST, 3, Kind.TYPE_CHECK),

    /** Determine if object is of given type */
    INSTANCEOF(ClassFile.INSTANCEOF, 3, Kind.TYPE_CHECK),

    /** Enter monitor for object */
    MONITORENTER(ClassFile.MONITORENTER, 1, Kind.MONITOR),

    /** Exit monitor for object */
    MONITOREXIT(ClassFile.MONITOREXIT, 1, Kind.MONITOR),

    /** Create new multidimensional array */
    MULTIANEWARRAY(ClassFile.MULTIANEWARRAY, 4, Kind.NEW_MULTI_ARRAY),

    /** Branch if reference is null */
    IFNULL(ClassFile.IFNULL, 3, Kind.BRANCH, TypeKind.ReferenceType),

    /** Branch if reference not null */
    IFNONNULL(ClassFile.IFNONNULL, 3, Kind.BRANCH, TypeKind.ReferenceType),

    /** Branch always (wide index) */
    GOTO_W(ClassFile.GOTO_W, 5, Kind.BRANCH, TypeKind.VoidType),

    /**
     * Jump subroutine (wide index) is discontinued opcode
     * @see io.github.dmlloyd.classfile.instruction.DiscontinuedInstruction
     */
    JSR_W(ClassFile.JSR_W, 5, Kind.DISCONTINUED_JSR),

    /** Load int from local variable (wide index) */
    ILOAD_W((ClassFile.WIDE << 8) | ClassFile.ILOAD, 4, Kind.LOAD, TypeKind.IntType, -1),

    /** Load long from local variable (wide index) */
    LLOAD_W((ClassFile.WIDE << 8) | ClassFile.LLOAD, 4, Kind.LOAD, TypeKind.LongType, -1),

    /** Load float from local variable (wide index) */
    FLOAD_W((ClassFile.WIDE << 8) | ClassFile.FLOAD, 4, Kind.LOAD, TypeKind.FloatType, -1),

    /** Load double from local variable (wide index) */
    DLOAD_W((ClassFile.WIDE << 8) | ClassFile.DLOAD, 4, Kind.LOAD, TypeKind.DoubleType, -1),

    /** Load reference from local variable (wide index) */
    ALOAD_W((ClassFile.WIDE << 8) | ClassFile.ALOAD, 4, Kind.LOAD, TypeKind.ReferenceType, -1),

    /** Store int into local variable (wide index) */
    ISTORE_W((ClassFile.WIDE << 8) | ClassFile.ISTORE, 4, Kind.STORE, TypeKind.IntType, -1),

    /** Store long into local variable (wide index) */
    LSTORE_W((ClassFile.WIDE << 8) | ClassFile.LSTORE, 4, Kind.STORE, TypeKind.LongType, -1),

    /** Store float into local variable (wide index) */
    FSTORE_W((ClassFile.WIDE << 8) | ClassFile.FSTORE, 4, Kind.STORE, TypeKind.FloatType, -1),

    /** Store double into local variable (wide index) */
    DSTORE_W((ClassFile.WIDE << 8) | ClassFile.DSTORE, 4, Kind.STORE, TypeKind.DoubleType, -1),

    /** Store reference into local variable (wide index) */
    ASTORE_W((ClassFile.WIDE << 8) | ClassFile.ASTORE, 4, Kind.STORE, TypeKind.ReferenceType, -1),

    /**
     * Return from subroutine (wide index) is discontinued opcode
     * @see io.github.dmlloyd.classfile.instruction.DiscontinuedInstruction
     */
    RET_W((ClassFile.WIDE << 8) | ClassFile.RET, 4, Kind.DISCONTINUED_RET),

    /** Increment local variable by constant (wide index) */
    IINC_W((ClassFile.WIDE << 8) | ClassFile.IINC, 6, Kind.INCREMENT, TypeKind.IntType, -1);

    /**
     * Kinds of opcodes.
     *
     * @since 22
     */
    @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
    public static enum Kind {

        /**
         * Load from local variable
         *
         * @see Opcode#ILOAD
         * @see Opcode#LLOAD
         * @see Opcode#FLOAD
         * @see Opcode#DLOAD
         * @see Opcode#ALOAD
         * @see Opcode#ILOAD_0
         * @see Opcode#ILOAD_1
         * @see Opcode#ILOAD_2
         * @see Opcode#ILOAD_3
         * @see Opcode#LLOAD_0
         * @see Opcode#LLOAD_1
         * @see Opcode#LLOAD_2
         * @see Opcode#LLOAD_3
         * @see Opcode#FLOAD_0
         * @see Opcode#FLOAD_1
         * @see Opcode#FLOAD_2
         * @see Opcode#FLOAD_3
         * @see Opcode#DLOAD_0
         * @see Opcode#DLOAD_1
         * @see Opcode#DLOAD_2
         * @see Opcode#DLOAD_3
         * @see Opcode#ALOAD_0
         * @see Opcode#ALOAD_1
         * @see Opcode#ALOAD_2
         * @see Opcode#ALOAD_3
         * @see Opcode#ILOAD_W
         * @see Opcode#LLOAD_W
         * @see Opcode#FLOAD_W
         * @see Opcode#DLOAD_W
         * @see Opcode#ALOAD_W
         */
        LOAD,

        /**
         * Store into local variable
         *
         * @see Opcode#ISTORE
         * @see Opcode#LSTORE
         * @see Opcode#FSTORE
         * @see Opcode#DSTORE
         * @see Opcode#ASTORE
         * @see Opcode#ISTORE_0
         * @see Opcode#ISTORE_1
         * @see Opcode#ISTORE_2
         * @see Opcode#ISTORE_3
         * @see Opcode#LSTORE_0
         * @see Opcode#LSTORE_1
         * @see Opcode#LSTORE_2
         * @see Opcode#LSTORE_3
         * @see Opcode#FSTORE_0
         * @see Opcode#FSTORE_1
         * @see Opcode#FSTORE_2
         * @see Opcode#FSTORE_3
         * @see Opcode#DSTORE_0
         * @see Opcode#DSTORE_1
         * @see Opcode#DSTORE_2
         * @see Opcode#DSTORE_3
         * @see Opcode#ASTORE_0
         * @see Opcode#ASTORE_1
         * @see Opcode#ASTORE_2
         * @see Opcode#ASTORE_3
         * @see Opcode#ISTORE_W
         * @see Opcode#LSTORE_W
         * @see Opcode#FSTORE_W
         * @see Opcode#DSTORE_W
         * @see Opcode#ASTORE_W
         */
        STORE,

        /**
         * Increment local variable
         *
         * @see Opcode#IINC
         * @see Opcode#IINC_W
         */
        INCREMENT,

        /**
         * Branch
         *
         * @see Opcode#IFEQ
         * @see Opcode#IFNE
         * @see Opcode#IFLT
         * @see Opcode#IFGE
         * @see Opcode#IFGT
         * @see Opcode#IFLE
         * @see Opcode#IF_ICMPEQ
         * @see Opcode#IF_ICMPNE
         * @see Opcode#IF_ICMPLT
         * @see Opcode#IF_ICMPGE
         * @see Opcode#IF_ICMPGT
         * @see Opcode#IF_ICMPLE
         * @see Opcode#IF_ACMPEQ
         * @see Opcode#IF_ACMPNE
         * @see Opcode#GOTO
         * @see Opcode#IFNULL
         * @see Opcode#IFNONNULL
         * @see Opcode#GOTO_W
         */
        BRANCH,

        /**
         * Access jump table by key match and jump
         *
         * @see Opcode#LOOKUPSWITCH
         */
        LOOKUP_SWITCH,

        /**
         * Access jump table by index and jump
         *
         * @see Opcode#TABLESWITCH
         */
        TABLE_SWITCH,

        /**
         * Return from method
         *
         * @see Opcode#IRETURN
         * @see Opcode#LRETURN
         * @see Opcode#FRETURN
         * @see Opcode#DRETURN
         * @see Opcode#ARETURN
         * @see Opcode#RETURN
         */
        RETURN,

        /**
         * Throw exception or error
         *
         * @see Opcode#ATHROW
         */
        THROW_EXCEPTION,

        /**
         * Access field
         *
         * @see Opcode#GETSTATIC
         * @see Opcode#PUTSTATIC
         * @see Opcode#GETFIELD
         * @see Opcode#PUTFIELD
         */
        FIELD_ACCESS,

        /**
         * Invoke method or constructor
         *
         * @see Opcode#INVOKEVIRTUAL
         * @see Opcode#INVOKESPECIAL
         * @see Opcode#INVOKESTATIC
         * @see Opcode#INVOKEINTERFACE
         */
        INVOKE,

        /**
         * Invoke a dynamically-computed call site
         *
         * @see Opcode#INVOKEDYNAMIC
         */
        INVOKE_DYNAMIC,

        /**
         * Create new object
         *
         * @see Opcode#NEW
         */
        NEW_OBJECT,

        /**
         * Create new array
         *
         * @see Opcode#NEWARRAY
         */
        NEW_PRIMITIVE_ARRAY,

        /**
         * Create new reference array
         *
         * @see Opcode#ANEWARRAY
         */
        NEW_REF_ARRAY,

        /**
         * Create new multidimensional array
         *
         * @see Opcode#MULTIANEWARRAY
         */
        NEW_MULTI_ARRAY,

        /**
         * Check whether object is of given type
         *
         * @see Opcode#CHECKCAST
         * @see Opcode#INSTANCEOF
         */
        TYPE_CHECK,

        /**
         * Load from array
         *
         * @see Opcode#IALOAD
         * @see Opcode#LALOAD
         * @see Opcode#FALOAD
         * @see Opcode#DALOAD
         * @see Opcode#AALOAD
         * @see Opcode#BALOAD
         * @see Opcode#CALOAD
         * @see Opcode#SALOAD
         */
        ARRAY_LOAD,

        /**
         * Store into array
         *
         * @see Opcode#IASTORE
         * @see Opcode#LASTORE
         * @see Opcode#FASTORE
         * @see Opcode#DASTORE
         * @see Opcode#AASTORE
         * @see Opcode#BASTORE
         * @see Opcode#CASTORE
         * @see Opcode#SASTORE
         */
        ARRAY_STORE,

        /**
         * Stack operations
         *
         * @see Opcode#POP
         * @see Opcode#POP2
         * @see Opcode#DUP
         * @see Opcode#DUP_X1
         * @see Opcode#DUP_X2
         * @see Opcode#DUP2
         * @see Opcode#DUP2_X1
         * @see Opcode#DUP2_X2
         * @see Opcode#SWAP
         */
        STACK,

        /**
         * Type conversions
         *
         * @see Opcode#I2L
         * @see Opcode#I2F
         * @see Opcode#I2D
         * @see Opcode#L2I
         * @see Opcode#L2F
         * @see Opcode#L2D
         * @see Opcode#F2I
         * @see Opcode#F2L
         * @see Opcode#F2D
         * @see Opcode#D2I
         * @see Opcode#D2L
         * @see Opcode#D2F
         * @see Opcode#I2B
         * @see Opcode#I2C
         * @see Opcode#I2S
         */
        CONVERT,

        /**
         * Operators
         *
         * @see Opcode#IADD
         * @see Opcode#LADD
         * @see Opcode#FADD
         * @see Opcode#DADD
         * @see Opcode#ISUB
         * @see Opcode#LSUB
         * @see Opcode#FSUB
         * @see Opcode#DSUB
         * @see Opcode#IMUL
         * @see Opcode#LMUL
         * @see Opcode#FMUL
         * @see Opcode#DMUL
         * @see Opcode#IDIV
         * @see Opcode#LDIV
         * @see Opcode#FDIV
         * @see Opcode#DDIV
         * @see Opcode#IREM
         * @see Opcode#LREM
         * @see Opcode#FREM
         * @see Opcode#DREM
         * @see Opcode#INEG
         * @see Opcode#LNEG
         * @see Opcode#FNEG
         * @see Opcode#DNEG
         * @see Opcode#ISHL
         * @see Opcode#LSHL
         * @see Opcode#ISHR
         * @see Opcode#LSHR
         * @see Opcode#IUSHR
         * @see Opcode#LUSHR
         * @see Opcode#IAND
         * @see Opcode#LAND
         * @see Opcode#IOR
         * @see Opcode#LOR
         * @see Opcode#IXOR
         * @see Opcode#LXOR
         * @see Opcode#LCMP
         * @see Opcode#FCMPL
         * @see Opcode#FCMPG
         * @see Opcode#DCMPL
         * @see Opcode#DCMPG
         * @see Opcode#ARRAYLENGTH
         */
        OPERATOR,

        /**
         * Constants
         *
         * @see Opcode#ACONST_NULL
         * @see Opcode#ICONST_M1
         * @see Opcode#ICONST_0
         * @see Opcode#ICONST_1
         * @see Opcode#ICONST_2
         * @see Opcode#ICONST_3
         * @see Opcode#ICONST_4
         * @see Opcode#ICONST_5
         * @see Opcode#LCONST_0
         * @see Opcode#LCONST_1
         * @see Opcode#FCONST_0
         * @see Opcode#FCONST_1
         * @see Opcode#FCONST_2
         * @see Opcode#DCONST_0
         * @see Opcode#DCONST_1
         * @see Opcode#BIPUSH
         * @see Opcode#SIPUSH
         * @see Opcode#LDC
         * @see Opcode#LDC_W
         * @see Opcode#LDC2_W
         */
        CONSTANT,

        /**
         * Monitor
         *
         * @see Opcode#MONITORENTER
         * @see Opcode#MONITOREXIT
         */
        MONITOR,

        /**
         * Do nothing
         *
         * @see Opcode#NOP
         */
        NOP,

        /**
         * Discontinued jump subroutine
         *
         * @see Opcode#JSR
         * @see Opcode#JSR_W
         * @see io.github.dmlloyd.classfile.instruction.DiscontinuedInstruction
         */
        DISCONTINUED_JSR,

        /**
         * Discontinued return from subroutine
         *
         * @see Opcode#RET
         * @see Opcode#RET_W
         * @see io.github.dmlloyd.classfile.instruction.DiscontinuedInstruction
         */
        DISCONTINUED_RET;
    }

    private final int bytecode;
    private final int sizeIfFixed;
    private final Kind kind;
    private final TypeKind primaryTypeKind;
    private final TypeKind secondaryTypeKind;
    private final int slot;
    private final ConstantDesc constantValue;

    Opcode(int bytecode, int sizeIfFixed, Kind kind) {
        this(bytecode, sizeIfFixed, kind, null, null, -1, null);
    }

    Opcode(int bytecode, int sizeIfFixed, Kind kind, TypeKind typeKind) {
        this(bytecode, sizeIfFixed, kind, typeKind, null, -1, null);
    }

    Opcode(int bytecode, int sizeIfFixed, Kind kind, TypeKind typeKind, int slot) {
        this(bytecode, sizeIfFixed, kind, typeKind, null, slot, null);
    }

    Opcode(int bytecode, int sizeIfFixed, Kind kind, TypeKind typeKind, int slot, ConstantDesc constantValue) {
        this(bytecode, sizeIfFixed, kind, typeKind, null, slot, constantValue);
    }

    Opcode(int bytecode, int sizeIfFixed, Kind kind, TypeKind primaryTypeKind, TypeKind secondaryTypeKind) {
        this(bytecode, sizeIfFixed, kind, primaryTypeKind, secondaryTypeKind, 0, null);
    }

    Opcode(int bytecode,
           int sizeIfFixed,
           Kind kind,
           TypeKind primaryTypeKind,
           TypeKind secondaryTypeKind,
           int slot,
           ConstantDesc constantValue) {
        this.bytecode = bytecode;
        this.sizeIfFixed = sizeIfFixed;
        this.kind = kind;
        this.primaryTypeKind = primaryTypeKind;
        this.secondaryTypeKind = secondaryTypeKind;
        this.slot = slot;
        this.constantValue = constantValue;
    }

    /**
     * {@return bytecode}
     */
    public int bytecode() { return bytecode; }

    /**
     * {@return true if the instruction has extended local variable index by additional bytes}
     */
    public boolean isWide() { return bytecode > 255; }

    /**
     * {@return size of the instruction if fixed, or -1 otherwise}
     */
    public int sizeIfFixed() { return sizeIfFixed; }

    /**
     * {@return instruction kind}
     */
    public Kind kind() { return kind; }

    /**
     * {@return primary type kind for instructions operating with at least one type, or null otherwise}
     */
    public TypeKind primaryTypeKind() {
        return primaryTypeKind;
    }

    /**
     * {@return secondary type kind for instructions operating with two types, or null otherwise}
     */
    public TypeKind secondaryTypeKind() {
        return secondaryTypeKind;
    }

    /**
     * {@return local variable slot for instructions operating with local variable, or -1 otherwise}
     */
    public int slot() {
        return slot;
    }

    /**
     * {@return constant value for constant instructions, or null otherwise}
     */
    public ConstantDesc constantValue() {
        return constantValue;
    }

    /**
     * {@return true if the instruction represents an unconditional branch}
     */
    public boolean isUnconditionalBranch() {
        return switch (this) {
            case GOTO, ATHROW, GOTO_W, LOOKUPSWITCH, TABLESWITCH -> true;
            default -> kind() == Kind.RETURN;
        };
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy