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

org.opalj.br.instructions.LDC2_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 long or double from runtime constant pool.
 *
 * @author Michael Eichberg
 * @author Dominik Helm
 */
sealed abstract class LDC2_W[@specialized(Long, Double) T <: Any]
    extends LoadConstantInstruction[T]
    with InstructionMetaInformation {

    final def opcode: Opcode = LDC2_W.opcode

    final def mnemonic: String = "ldc2_w"

    final def length: Int = 3

}

final case class LoadLong(value: Long) extends LDC2_W[Long] {

    final def computationalType = ComputationalTypeLong

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

}

final case class LoadDouble(value: Double) extends LDC2_W[Double] {

    final def computationalType = ComputationalTypeDouble

    final 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) || (
            LDC2_W.opcode == other.opcode && other.isInstanceOf[LoadDouble] && {
                val otherLoadDouble = other.asInstanceOf[LoadDouble]
                (this.value.isNaN && otherLoadDouble.value.isNaN) ||
                    (this.value == otherLoadDouble.value)
            }
        )
    }

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

    // HashCode of "value.NaN" is stable and 0

}

/**
 * @note To match [[LoadDynamic]], [[LoadDynamic_W]] and [[LoadDynamic2_W]] instructions you can use
 *       [[LDCDynamic]].
 */
final case class LoadDynamic2_W(
        bootstrapMethod: BootstrapMethod,
        name:            String,
        descriptor:      FieldType
) extends LDC2_W[Nothing] {
    def value: Nothing = throw new UnsupportedOperationException("dynamic constant unknown")

    def computationalType: ComputationalType = descriptor.computationalType

    final def isIsomorphic(thisPC: PC, otherPC: PC)(implicit code: Code): Boolean = {
        val other = code.instructions(otherPC)
        (this eq other) || this == other
    }
}

case object INCOMPLETE_LDC2_W extends LDC2_W[Any] {

    private def error: Nothing = {
        val message = "this ldc2_w is incomplete"
        throw BytecodeProcessingFailedException(message)
    }

    final def computationalType = error

    final def value: Any = error

    final def isIsomorphic(thisPC: PC, otherPC: PC)(implicit code: Code): Boolean = error
}

/**
 * Defines factory and extractor methods for LDC2_W instructions.
 *
 * @author Michael Eichberg
 */
object LDC2_W {

    final val opcode = 20

    def apply(constantValue: ConstantValue[_]): LDC2_W[_] = {
        constantValue.value match {
            case v: Long   => LoadLong(v)
            case d: Double => LoadDouble(d)
            case _ =>
                throw BytecodeProcessingFailedException(
                    "unsupported LDC2_W constant value: "+constantValue
                )
        }
    }

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

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy