
org.opalj.br.instructions.LDC.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.bytecode.BytecodeProcessingFailedException
/**
* Push item from runtime constant pool.
*
* @author Michael Eichberg
* @author Dominik Helm
*/
sealed trait LDC[@specialized(Int, Float) T]
extends LoadConstantInstruction[T]
with InstructionMetaInformation {
final def opcode: Opcode = LDC.opcode
final def mnemonic: String = "ldc"
final def length: Int = 2
def isIsomorphic(thisPC: PC, otherPC: PC)(implicit code: Code): Boolean = {
val other = code.instructions(otherPC)
(this eq other) || (
this.opcode == other.opcode &&
this.value == other.asInstanceOf[LDC[_]].value
)
}
}
/** A load constant instruction which never fails. */
sealed abstract class PrimitiveLDC[@specialized(Int, Float) T] extends LDC[T]
/**
* @note To match [[LoadInt]] and [[LoadInt_W]] instructions you can use [[LDCInt]].
*/
final case class LoadInt(value: Int) extends PrimitiveLDC[Int] {
final def computationalType = ComputationalTypeInt
}
/**
* @note To match [[LoadFloat]] and [[LoadFloat_W]] instructions you can use [[LDCFloat]].
*/
final case class LoadFloat(value: Float) extends PrimitiveLDC[Float] {
final def computationalType = ComputationalTypeFloat
override def isIsomorphic(thisPC: PC, otherPC: PC)(implicit code: Code): Boolean = {
val other = code.instructions(otherPC)
this.similar(other)
}
override def similar(other: Instruction): Boolean = {
LDC.opcode == other.opcode && other.isInstanceOf[LoadFloat] && {
val otherLoadFloat = other.asInstanceOf[LoadFloat]
(this.value.isNaN && otherLoadFloat.value.isNaN) ||
(this.value == otherLoadFloat.value)
}
}
override def equals(other: Any): Boolean = {
other match {
case LoadFloat(thatValue) =>
thatValue == this.value || (thatValue.isNaN && this.value.isNaN)
case _ => false
}
}
// HashCode of "value.NaN" is stable and 0
}
/**
* @note To match [[LoadClass]] and [[LoadClass_W]] instructions you can use [[LDCClass]].
*/
final case class LoadClass(value: ReferenceType) extends LDC[ReferenceType] {
final def computationalType = ComputationalTypeReference
}
/**
* @note To match [[LoadMethodHandle]] and [[LoadMethodHandle_W]] instructions you
* can use [[LDCMethodHandle]].
*/
final case class LoadMethodHandle(value: MethodHandle) extends LDC[MethodHandle] {
final def computationalType = ComputationalTypeReference
}
/**
* @note To match [[LoadMethodType]] and [[LoadMethodType_W]] instructions you can use
* [[LDCMethodType]].
*/
final case class LoadMethodType(value: MethodDescriptor) extends LDC[MethodDescriptor] {
final def computationalType = ComputationalTypeReference
}
/**
* @note To match [[LoadString]] and [[LoadString_W]] instructions you can use [[LDCString]].
*/
final case class LoadString(value: String) extends PrimitiveLDC[String] {
final def computationalType = ComputationalTypeReference
override def toString: String = "LoadString(\""+value+"\")"
}
/**
* @note To match [[LoadDynamic]], [[LoadDynamic_W]] and [[LoadDynamic2_W]] instructions you can use
* [[LDCDynamic]].
*/
final case class LoadDynamic(
bootstrapMethod: BootstrapMethod,
name: String,
descriptor: FieldType
) extends LDC[Nothing] {
def value: Nothing = throw new UnsupportedOperationException("dynamic constant unknown")
def computationalType: ComputationalType = descriptor.computationalType
final override def isIsomorphic(thisPC: PC, otherPC: PC)(implicit code: Code): Boolean = {
val other = code.instructions(otherPC)
(this eq other) || this == other
}
}
case object INCOMPLETE_LDC extends LDC[Any] {
private def error: Nothing = {
val message = "this ldc is incomplete"
throw BytecodeProcessingFailedException(message)
}
final def computationalType = error
final def value: Any = error
final override def isIsomorphic(thisPC: PC, otherPC: PC)(implicit code: Code): Boolean = error
}
/**
* Defines factory and extractor methods for LDC instructions.
*
* @author Michael Eichberg
*/
object LDC {
def apply(constantValue: ConstantValue[_]): LDC[_] = {
constantValue.value match {
case i: Int => LoadInt(i)
case f: Float => LoadFloat(f)
case r: ReferenceType => LoadClass(r)
case s: String => LoadString(s)
case mh: MethodHandle => LoadMethodHandle(mh)
case md: MethodDescriptor => LoadMethodType(md)
case _ =>
throw BytecodeProcessingFailedException(
"unsupported constant value: "+constantValue
)
}
}
def unapply[T](ldc: LDC[T]): Option[T] = Some(ldc.value)
final val opcode = 18
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy