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

org.opalj.br.instructions.LDC_W.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 abstract class LDC_W[T] extends LoadConstantInstruction[T] with InstructionMetaInformation {

    final def opcode: Opcode = LDC_W.opcode

    final def mnemonic: String = "ldc_w"

    final def length: Int = 3

    def isIsomorphic(thisPC: PC, otherPC: PC)(implicit code: Code): Boolean = {
        val other = code.instructions(otherPC)
        (this eq other) || (
            LDC_W.opcode == other.opcode &&
            this.value == other.asInstanceOf[LDC_W[_]].value
        )
    }

}

/** A load constant instruction which never fails. */
sealed abstract class PrimitiveLDC_W[T] extends LDC_W[T]

final case class LoadInt_W(value: Int) extends PrimitiveLDC_W[Int] {
    final def computationalType = ComputationalTypeInt
}

final case class LoadFloat_W(value: Float) extends PrimitiveLDC_W[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 = {
        (this eq other) || (
            LDC_W.opcode == other.opcode && other.isInstanceOf[LoadFloat_W] && {
                val otherLoadFloat = other.asInstanceOf[LoadFloat_W]
                (this.value.isNaN && otherLoadFloat.value.isNaN) ||
                    (this.value == otherLoadFloat.value)
            }
        )
    }

    override def equals(other: Any): Boolean = {
        other match {
            case LoadFloat_W(thatValue) =>
                thatValue == this.value || (thatValue.isNaN && this.value.isNaN)
            case _ => false
        }
    }
}

final case class LoadClass_W(value: ReferenceType) extends LDC_W[ReferenceType] {
    final def computationalType: ComputationalTypeReference.type = ComputationalTypeReference
}

final case class LoadMethodHandle_W(value: MethodHandle) extends LDC_W[MethodHandle] {
    final def computationalType: ComputationalTypeReference.type = ComputationalTypeReference
}

final case class LoadMethodType_W(value: MethodDescriptor) extends LDC_W[MethodDescriptor] {
    final def computationalType: ComputationalTypeReference.type = ComputationalTypeReference
}

/**
 * @note To match [[LoadString]] and [[LoadString_W]] instructions you can use [[LDCString]].
 */
final case class LoadString_W(value: String) extends PrimitiveLDC_W[String] {
    final def computationalType = ComputationalTypeReference
}

/**
 * @note To match [[LoadDynamic]], [[LoadDynamic_W]] and [[LoadDynamic2_W]] instructions you can use
 *       [[LDCDynamic]].
 */
final case class LoadDynamic_W(
        bootstrapMethod: BootstrapMethod,
        name:            String,
        descriptor:      FieldType
) extends LDC_W[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_W extends LDC_W[Any] {

    private def error: Nothing = {
        val message = "this ldc_w 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_W instructions.
 *
 * @author Michael Eichberg
 */
object LDC_W {

    final val opcode = 19

    def apply(constantValue: ConstantValue[_]): LDC_W[_] = {
        constantValue.value match {
            case i: Int               => LoadInt_W(i)
            case f: Float             => LoadFloat_W(f)
            case r: ReferenceType     => LoadClass_W(r)
            case s: String            => LoadString_W(s)
            case mh: MethodHandle     => LoadMethodHandle_W(mh)
            case md: MethodDescriptor => LoadMethodType_W(md)
            case _                    => throw BytecodeProcessingFailedException("unsupported value: "+constantValue)
        }
    }

    def unapply[T](ldc: LDC_W[T]): Option[T] = Some(ldc.value)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy