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

org.opalj.br.instructions.RET.scala Maven / Gradle / Ivy

The newest version!
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj
package br
package instructions

import org.opalj.br.cfg.CFGFactory
import org.opalj.br.cfg.CFG

/**
 * Return from subroutine.
 *
 * @note A RET instruction always returns to an instruction immediately following a JSR(_W)
 *      instruction.
 *
 * @author Michael Eichberg
 */
case class RET(
        lvIndex: Int
) extends ControlTransferInstruction
    with ConstantLengthInstruction
    with NoLabels {

    final override def opcode: Opcode = RET.opcode

    final override def mnemonic: String = "ret"

    final override def isRET: Boolean = true

    final override def length: Int = 2

    final override def nextInstructions(
        currentPC:             Int /*PC*/ ,
        regularSuccessorsOnly: Boolean
    )(
        implicit
        code:           Code,
        classHierarchy: ClassHierarchy = ClassHierarchy.PreInitializedClassHierarchy
    ): List[Int /*PC*/ ] = {
        nextInstructions(currentPC, () => CFGFactory(code, classHierarchy))
    }

    override def jumpTargets(
        currentPC: Int
    )(
        implicit
        code:           Code,
        classHierarchy: ClassHierarchy = ClassHierarchy.PreInitializedClassHierarchy
    ): Iterator[PC] = {
        nextInstructions(currentPC, false /*irrelevant*/ ).iterator
    }

    final def nextInstructions(
        currentPC: Int, cfg: () => CFG[Instruction, Code]
    )(
        implicit
        code: Code
    ): List[Int /*PC*/ ] = {

        // If we have just one subroutine it is sufficient to collect the
        // successor instructions of all JSR instructions.
        var jumpTargetPCs: List[Int] = List.empty
        code.iterate { (pc, instruction) =>
            if (pc != currentPC) { // filter this ret!
                instruction.opcode match {

                    case JSR.opcode | JSR_W.opcode =>
                        jumpTargetPCs ::= (instruction.indexOfNextInstruction(pc))

                    case RET.opcode =>
                        // we have found another RET ... hence, we have at least two subroutines
                        return cfg().successors(currentPC).toList;

                    case _ =>
                    // we don't care
                }
            }
        }
        jumpTargetPCs
    }

    final override def numberOfPoppedOperands(ctg: Int => ComputationalTypeCategory): Int = 0

    final override def numberOfPushedOperands(ctg: Int => ComputationalTypeCategory): Int = 0

    final override def stackSlotsChange: Int = 0

    final override def isIsomorphic(thisPC: Int, otherPC: Int)(implicit code: Code): Boolean = {
        this == code.instructions(otherPC)
    }

    final override def readsLocal: Boolean = true

    final override def indexOfReadLocal: Int = lvIndex

    final override def writesLocal: Boolean = false

    final override def indexOfWrittenLocal: Int = throw new UnsupportedOperationException()

    final override def toString(currentPC: Int): String = toString()
}
object RET extends InstructionMetaInformation {

    final val opcode = 169

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy