package scala.tools.nsc
package backend.jvm
import scala.collection.{ mutable, immutable }
import ch.epfl.lamp.fjbg._
trait GenJVMUtil {
self: GenJVM =>
import global._
import icodes._
import icodes.opcodes._
import definitions._
val classLiteral = immutable.Map[TypeKind, JObjectType](
UNIT -> new JObjectType("java.lang.Void"),
BOOL -> new JObjectType("java.lang.Boolean"),
BYTE -> new JObjectType("java.lang.Byte"),
SHORT -> new JObjectType("java.lang.Short"),
CHAR -> new JObjectType("java.lang.Character"),
INT -> new JObjectType("java.lang.Integer"),
LONG -> new JObjectType("java.lang.Long"),
FLOAT -> new JObjectType("java.lang.Float"),
DOUBLE -> new JObjectType("java.lang.Double")
)
private val javaNameCache = {
val map = new mutable.WeakHashMap[Symbol, String]()
map ++= List(
NothingClass -> RuntimeNothingClass.fullName('/'),
RuntimeNothingClass -> RuntimeNothingClass.fullName('/'),
NullClass -> RuntimeNullClass.fullName('/'),
RuntimeNullClass -> RuntimeNullClass.fullName('/')
)
map
}
trait BytecodeUtil {
val conds = immutable.Map[TestOp, Int](
EQ -> JExtendedCode.COND_EQ,
NE -> JExtendedCode.COND_NE,
LT -> JExtendedCode.COND_LT,
GT -> JExtendedCode.COND_GT,
LE -> JExtendedCode.COND_LE,
GE -> JExtendedCode.COND_GE
)
val negate = immutable.Map[TestOp, TestOp](
EQ -> NE,
NE -> EQ,
LT -> GE,
GT -> LE,
LE -> GT,
GE -> LT
)
def mkArray(xs: Traversable[JType]): Array[JType] = { val a = new Array[JType](xs.size); xs.copyToArray(a); a }
def mkArray(xs: Traversable[String]): Array[String] = { val a = new Array[String](xs.size); xs.copyToArray(a); a }
def javaName(sym: Symbol): String =
javaNameCache.getOrElseUpdate(sym, {
if (sym.isClass || (sym.isModule && !sym.isMethod))
sym.fullName('/') + moduleSuffix(sym)
else
sym.simpleName.toString.trim() + moduleSuffix(sym)
})
def javaType(t: TypeKind): JType = (t: @unchecked) match {
case UNIT => JType.VOID
case BOOL => JType.BOOLEAN
case BYTE => JType.BYTE
case SHORT => JType.SHORT
case CHAR => JType.CHAR
case INT => JType.INT
case LONG => JType.LONG
case FLOAT => JType.FLOAT
case DOUBLE => JType.DOUBLE
case REFERENCE(cls) => new JObjectType(javaName(cls))
case ARRAY(elem) => new JArrayType(javaType(elem))
}
def javaType(t: Type): JType = javaType(toTypeKind(t))
def javaType(s: Symbol): JType =
if (s.isMethod)
new JMethodType(
if (s.isClassConstructor) JType.VOID else javaType(s.tpe.resultType),
mkArray(s.tpe.paramTypes map javaType)
)
else
javaType(s.tpe)
protected def genConstant(jcode: JExtendedCode, const: Constant) {
const.tag match {
case UnitTag => ()
case BooleanTag => jcode emitPUSH const.booleanValue
case ByteTag => jcode emitPUSH const.byteValue
case ShortTag => jcode emitPUSH const.shortValue
case CharTag => jcode emitPUSH const.charValue
case IntTag => jcode emitPUSH const.intValue
case LongTag => jcode emitPUSH const.longValue
case FloatTag => jcode emitPUSH const.floatValue
case DoubleTag => jcode emitPUSH const.doubleValue
case StringTag => jcode emitPUSH const.stringValue
case NullTag => jcode.emitACONST_NULL()
case ClassTag =>
val kind = toTypeKind(const.typeValue)
val toPush =
if (kind.isValueType) classLiteral(kind)
else javaType(kind).asInstanceOf[JReferenceType]
jcode emitPUSH toPush
case EnumTag =>
val sym = const.symbolValue
jcode.emitGETSTATIC(javaName(sym.owner),
javaName(sym),
javaType(sym.tpe.underlying))
case _ =>
abort("Unknown constant value: " + const)
}
}
}
}