
org.opalj.br.instructions.Instruction.scala Maven / Gradle / Ivy
The newest version!
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj
package br
package instructions
/**
* Common superclass of all instructions which are in their final form.
*
* @author Michael Eichberg
*/
trait Instruction extends InstructionLike {
/**
* The index of the next instruction in the (sparse) code array.
*
* @note This is primarily a convenience method that delegates to the method
* `indexOfNextInstrution(PC,Boolean)`. However, given that this is also the
* standard method called by clients, it is often meaningful to directly implement
* this. In particular since most instructions cannot be modified by wide.
*/
def indexOfNextInstruction(currentPC: Int)(implicit code: Code): Int
/**
* Returns the pcs of the instructions that may be executed next at runtime. This
* method takes potentially thrown exceptions into account. I.e., every instruction
* that may throw an exception checks if it is handled locally and
* – if so – checks if an appropriate handler exists and – if so – also returns
* the first instruction of the handler. The chain may contain duplicates, iff the state
* is potentially different when the target instruction is reached.
*
* @param regularSuccessorsOnly If `true`, only those instructions are returned
* which are not related to an exception thrown by this instruction.
* @return The absolute addresses of '''all instructions''' that may be executed next
* at runtime.
*/
def nextInstructions(
currentPC: Int,
regularSuccessorsOnly: Boolean = false
)(
implicit
code: Code,
classHierarchy: ClassHierarchy = ClassHierarchy.PreInitializedClassHierarchy
): List[Int /*PC*/ ]
/**
* Checks for structural equality of two instructions.
*
* @note Implemted by using the underlying (compiler generated) equals methods.
*/
def similar(other: Instruction): Boolean = this == other
/**
* Converts this instruction to a [[LabeledInstruction]], where relative jump targets are
* replaced by symbols using the program counters of the target instructions as
* Symbols (i.e., absolute targets).
*
* @param currentPC The pc of the current instruction.
*/
def toLabeledInstruction(currentPC: Int): LabeledInstruction
// ---------------------------------------------------------------------------------------------
//
// TYPE TEST AND TYPE CAST RELATED INSTRUCTIONS
//
// ---------------------------------------------------------------------------------------------
def isSimpleBranchInstruction: Boolean = false
def isSimpleConditionalBranchInstruction: Boolean = false
def isCompoundConditionalBranchInstruction: Boolean = false
def isGotoInstruction: Boolean = false
def isStackManagementInstruction: Boolean = false
def isLoadLocalVariableInstruction: Boolean = false
def isStoreLocalVariableInstruction: Boolean = false
def isCheckcast: Boolean = false
def isInvocationInstruction: Boolean = false
def isMethodInvocationInstruction: Boolean = false
def isInvokeStatic: Boolean = false
def isIINC: Boolean = false
def asReturnInstruction: ReturnInstruction = throw new ClassCastException();
def asATHROW: ATHROW.type = throw new ClassCastException();
def asIINC: IINC = throw new ClassCastException();
def asNEW: NEW = throw new ClassCastException();
def asCreateNewArrayInstruction: CreateNewArrayInstruction = throw new ClassCastException();
def asLoadLocalVariableInstruction: LoadLocalVariableInstruction = {
throw new ClassCastException();
}
def asStoreLocalVariableInstruction: StoreLocalVariableInstruction = {
throw new ClassCastException();
}
def asControlTransferInstruction: ControlTransferInstruction = throw new ClassCastException();
def asGotoInstruction: GotoInstruction = throw new ClassCastException();
def asSimpleBranchInstruction: SimpleBranchInstruction = throw new ClassCastException();
def asSimpleConditionalBranchInstruction: SimpleConditionalBranchInstruction[_] = {
throw new ClassCastException();
}
def asCompoundConditionalBranchInstruction: CompoundConditionalBranchInstruction = {
throw new ClassCastException();
}
def asIFICMPInstruction: IFICMPInstruction[_] = throw new ClassCastException();
def asIF0Instruction: IF0Instruction[_] = throw new ClassCastException();
def asIFACMPInstruction: IFACMPInstruction[_] = throw new ClassCastException();
def asIFXNullInstruction: IFXNullInstruction[_] = throw new ClassCastException();
def asInvocationInstruction: InvocationInstruction = throw new ClassCastException();
def asMethodInvocationInstruction: MethodInvocationInstruction = {
throw new ClassCastException();
}
def asArithmeticInstruction: ArithmeticInstruction = throw new ClassCastException();
def asTABLESWITCH: TABLESWITCH = throw new ClassCastException();
def asLOOKUPSWITCH: LOOKUPSWITCH = throw new ClassCastException();
}
/**
* Functionality common to instructions.
*
* @author Michael Eichberg
*/
object Instruction {
final val IllegalIndex: Int = 1
/**
* Facilitates the matching of [[Instruction]] objects.
*
* @return Returns the triple `Some((opcode,mnemonic,list of jvm exceptions))`.
*/
def unapply(instruction: Instruction): Some[(Int, String, List[ObjectType])] = {
Some((instruction.opcode, instruction.mnemonic, instruction.jvmExceptions))
}
/**
* Determines if the instructions with the pcs `aPC` and `bPC` are isomorphic.
*
* @see [[Instruction.isIsomorphic]] for further details.
*/
def areIsomorphic(aPC: Int, bPC: Int)(implicit code: Code): Boolean = {
assert(aPC != bPC)
code.instructions(aPC).isIsomorphic(aPC, bPC)
}
private[instructions] def nextInstructionOrExceptionHandlers(
instruction: Instruction,
currentPC: Int,
exceptions: List[ObjectType]
)(
implicit
code: Code,
classHierarchy: ClassHierarchy = ClassHierarchy.PreInitializedClassHierarchy
): List[Int /*PC*/ ] = {
var pcs = List(instruction.indexOfNextInstruction(currentPC))
exceptions foreach { exception =>
pcs = (code.handlersForException(currentPC, exception).map(_.handlerPC)) ++: pcs
}
pcs
}
private[instructions] def nextInstructionOrExceptionHandler(
instruction: Instruction,
currentPC: Int,
exception: ObjectType
)(
implicit
code: Code,
classHierarchy: ClassHierarchy = ClassHierarchy.PreInitializedClassHierarchy
): List[Int /*PC*/ ] = {
val nextInstruction = instruction.indexOfNextInstruction(currentPC)
nextInstruction :: (code.handlersForException(currentPC, exception).map(_.handlerPC))
}
final val justNullPointerException: List[org.opalj.br.ObjectType] = {
List(ObjectType.NullPointerException)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy