package scala.tools.nsc
package backend
import scala.tools.nsc.backend.icode._
import scala.collection.{ mutable, immutable }
abstract class ScalaPrimitives {
val global: Global
import global._
import definitions._
import global.icodes._
final val POS = 1
final val NEG = 2
final val NOT = 3
final val ADD = 10
final val SUB = 11
final val MUL = 12
final val DIV = 13
final val MOD = 14
final val OR = 20
final val XOR = 21
final val AND = 22
final val LSL = 30
final val LSR = 31
final val ASR = 32
final val ID = 40
final val NI = 41
final val EQ = 42
final val NE = 43
final val LT = 44
final val LE = 45
final val GE = 46
final val GT = 47
final val ZNOT = 50
final val ZOR = 60
final val ZAND = 61
final val LENGTH = 70
final val APPLY = 71
final val UPDATE = 72
final val IS = 80
final val AS = 81
final val HASH = 87
final val SYNCHRONIZED = 90
final val CONCAT = 100
final val COERCE = 101
final val BOX = 110
final val UNBOX = 111
final val NEW_ZARRAY = 112
final val NEW_BARRAY = 113
final val NEW_SARRAY = 114
final val NEW_CARRAY = 115
final val NEW_IARRAY = 116
final val NEW_LARRAY = 117
final val NEW_FARRAY = 118
final val NEW_DARRAY = 119
final val NEW_OARRAY = 120
final val ZARRAY_LENGTH = 131
final val BARRAY_LENGTH = 132
final val SARRAY_LENGTH = 133
final val CARRAY_LENGTH = 134
final val IARRAY_LENGTH = 135
final val LARRAY_LENGTH = 136
final val FARRAY_LENGTH = 137
final val DARRAY_LENGTH = 138
final val OARRAY_LENGTH = 139
final val ZARRAY_GET = 140
final val BARRAY_GET = 141
final val SARRAY_GET = 142
final val CARRAY_GET = 143
final val IARRAY_GET = 144
final val LARRAY_GET = 145
final val FARRAY_GET = 146
final val DARRAY_GET = 147
final val OARRAY_GET = 148
final val ZARRAY_SET = 150
final val BARRAY_SET = 151
final val SARRAY_SET = 152
final val CARRAY_SET = 153
final val IARRAY_SET = 154
final val LARRAY_SET = 155
final val FARRAY_SET = 156
final val DARRAY_SET = 157
final val OARRAY_SET = 158
final val B2B = 200
final val B2S = 201
final val B2C = 202
final val B2I = 203
final val B2L = 204
final val B2F = 205
final val B2D = 206
final val S2B = 210
final val S2S = 211
final val S2C = 212
final val S2I = 213
final val S2L = 214
final val S2F = 215
final val S2D = 216
final val C2B = 220
final val C2S = 221
final val C2C = 222
final val C2I = 223
final val C2L = 224
final val C2F = 225
final val C2D = 226
final val I2B = 230
final val I2S = 231
final val I2C = 232
final val I2I = 233
final val I2L = 234
final val I2F = 235
final val I2D = 236
final val L2B = 240
final val L2S = 241
final val L2C = 242
final val L2I = 243
final val L2L = 244
final val L2F = 245
final val L2D = 246
final val F2B = 250
final val F2S = 251
final val F2C = 252
final val F2I = 253
final val F2L = 254
final val F2F = 255
final val F2D = 256
final val D2B = 260
final val D2S = 261
final val D2C = 262
final val D2I = 263
final val D2L = 264
final val D2F = 265
final val D2D = 266
private val primitives: mutable.Map[Symbol, Int] = new mutable.HashMap()
def init() {
primitives.clear()
addPrimitive(Any_==, EQ)
addPrimitive(Any_!=, NE)
addPrimitive(Any_isInstanceOf, IS)
addPrimitive(Any_asInstanceOf, AS)
addPrimitive(Any_##, HASH)
addPrimitive(Object_eq, ID)
addPrimitive(Object_ne, NI)
addPrimitive(Object_==, EQ)
addPrimitive(Object_!=, NE)
addPrimitive(Object_synchronized, SYNCHRONIZED)
addPrimitive(Object_isInstanceOf, IS)
addPrimitive(Object_asInstanceOf, AS)
addPrimitive(String_+, CONCAT)
addPrimitives(ArrayClass, nme.length, LENGTH)
addPrimitives(ArrayClass, nme.apply, APPLY)
addPrimitives(ArrayClass, nme.update, UPDATE)
addPrimitives(BooleanClass, nme.EQ, EQ)
addPrimitives(BooleanClass, nme.NE, NE)
addPrimitives(BooleanClass, nme.UNARY_!, ZNOT)
addPrimitives(BooleanClass, nme.ZOR, ZOR)
addPrimitives(BooleanClass, nme.ZAND, ZAND)
addPrimitives(BooleanClass, nme.OR, OR)
addPrimitives(BooleanClass, nme.AND, AND)
addPrimitives(BooleanClass, nme.XOR, XOR)
addPrimitives(ByteClass, nme.EQ, EQ)
addPrimitives(ByteClass, nme.NE, NE)
addPrimitives(ByteClass, nme.ADD, ADD)
addPrimitives(ByteClass, nme.SUB, SUB)
addPrimitives(ByteClass, nme.MUL, MUL)
addPrimitives(ByteClass, nme.DIV, DIV)
addPrimitives(ByteClass, nme.MOD, MOD)
addPrimitives(ByteClass, nme.LT, LT)
addPrimitives(ByteClass, nme.LE, LE)
addPrimitives(ByteClass, nme.GT, GT)
addPrimitives(ByteClass, nme.GE, GE)
addPrimitives(ByteClass, nme.XOR, XOR)
addPrimitives(ByteClass, nme.OR, OR)
addPrimitives(ByteClass, nme.AND, AND)
addPrimitives(ByteClass, nme.LSL, LSL)
addPrimitives(ByteClass, nme.LSR, LSR)
addPrimitives(ByteClass, nme.ASR, ASR)
addPrimitives(ByteClass, nme.toByte, B2B)
addPrimitives(ByteClass, nme.toShort, B2S)
addPrimitives(ByteClass, nme.toChar, B2C)
addPrimitives(ByteClass, nme.toInt, B2I)
addPrimitives(ByteClass, nme.toLong, B2L)
addPrimitives(ByteClass, nme.UNARY_+, POS)
addPrimitives(ByteClass, nme.UNARY_-, NEG)
addPrimitives(ByteClass, nme.UNARY_~, NOT)
addPrimitives(ByteClass, nme.toFloat, B2F)
addPrimitives(ByteClass, nme.toDouble, B2D)
addPrimitives(ShortClass, nme.EQ, EQ)
addPrimitives(ShortClass, nme.NE, NE)
addPrimitives(ShortClass, nme.ADD, ADD)
addPrimitives(ShortClass, nme.SUB, SUB)
addPrimitives(ShortClass, nme.MUL, MUL)
addPrimitives(ShortClass, nme.DIV, DIV)
addPrimitives(ShortClass, nme.MOD, MOD)
addPrimitives(ShortClass, nme.LT, LT)
addPrimitives(ShortClass, nme.LE, LE)
addPrimitives(ShortClass, nme.GT, GT)
addPrimitives(ShortClass, nme.GE, GE)
addPrimitives(ShortClass, nme.XOR, XOR)
addPrimitives(ShortClass, nme.OR, OR)
addPrimitives(ShortClass, nme.AND, AND)
addPrimitives(ShortClass, nme.LSL, LSL)
addPrimitives(ShortClass, nme.LSR, LSR)
addPrimitives(ShortClass, nme.ASR, ASR)
addPrimitives(ShortClass, nme.toByte, S2B)
addPrimitives(ShortClass, nme.toShort, S2S)
addPrimitives(ShortClass, nme.toChar, S2C)
addPrimitives(ShortClass, nme.toInt, S2I)
addPrimitives(ShortClass, nme.toLong, S2L)
addPrimitives(ShortClass, nme.UNARY_+, POS)
addPrimitives(ShortClass, nme.UNARY_-, NEG)
addPrimitives(ShortClass, nme.UNARY_~, NOT)
addPrimitives(ShortClass, nme.toFloat, S2F)
addPrimitives(ShortClass, nme.toDouble, S2D)
addPrimitives(CharClass, nme.EQ, EQ)
addPrimitives(CharClass, nme.NE, NE)
addPrimitives(CharClass, nme.ADD, ADD)
addPrimitives(CharClass, nme.SUB, SUB)
addPrimitives(CharClass, nme.MUL, MUL)
addPrimitives(CharClass, nme.DIV, DIV)
addPrimitives(CharClass, nme.MOD, MOD)
addPrimitives(CharClass, nme.LT, LT)
addPrimitives(CharClass, nme.LE, LE)
addPrimitives(CharClass, nme.GT, GT)
addPrimitives(CharClass, nme.GE, GE)
addPrimitives(CharClass, nme.XOR, XOR)
addPrimitives(CharClass, nme.OR, OR)
addPrimitives(CharClass, nme.AND, AND)
addPrimitives(CharClass, nme.LSL, LSL)
addPrimitives(CharClass, nme.LSR, LSR)
addPrimitives(CharClass, nme.ASR, ASR)
addPrimitives(CharClass, nme.toByte, C2B)
addPrimitives(CharClass, nme.toShort, C2S)
addPrimitives(CharClass, nme.toChar, C2C)
addPrimitives(CharClass, nme.toInt, C2I)
addPrimitives(CharClass, nme.toLong, C2L)
addPrimitives(CharClass, nme.UNARY_+, POS)
addPrimitives(CharClass, nme.UNARY_-, NEG)
addPrimitives(CharClass, nme.UNARY_~, NOT)
addPrimitives(CharClass, nme.toFloat, C2F)
addPrimitives(CharClass, nme.toDouble, C2D)
addPrimitives(IntClass, nme.EQ, EQ)
addPrimitives(IntClass, nme.NE, NE)
addPrimitives(IntClass, nme.ADD, ADD)
addPrimitives(IntClass, nme.SUB, SUB)
addPrimitives(IntClass, nme.MUL, MUL)
addPrimitives(IntClass, nme.DIV, DIV)
addPrimitives(IntClass, nme.MOD, MOD)
addPrimitives(IntClass, nme.LT, LT)
addPrimitives(IntClass, nme.LE, LE)
addPrimitives(IntClass, nme.GT, GT)
addPrimitives(IntClass, nme.GE, GE)
addPrimitives(IntClass, nme.XOR, XOR)
addPrimitives(IntClass, nme.OR, OR)
addPrimitives(IntClass, nme.AND, AND)
addPrimitives(IntClass, nme.LSL, LSL)
addPrimitives(IntClass, nme.LSR, LSR)
addPrimitives(IntClass, nme.ASR, ASR)
addPrimitives(IntClass, nme.toByte, I2B)
addPrimitives(IntClass, nme.toShort, I2S)
addPrimitives(IntClass, nme.toChar, I2C)
addPrimitives(IntClass, nme.toInt, I2I)
addPrimitives(IntClass, nme.toLong, I2L)
addPrimitives(IntClass, nme.UNARY_+, POS)
addPrimitives(IntClass, nme.UNARY_-, NEG)
addPrimitives(IntClass, nme.UNARY_~, NOT)
addPrimitives(IntClass, nme.toFloat, I2F)
addPrimitives(IntClass, nme.toDouble, I2D)
addPrimitives(LongClass, nme.EQ, EQ)
addPrimitives(LongClass, nme.NE, NE)
addPrimitives(LongClass, nme.ADD, ADD)
addPrimitives(LongClass, nme.SUB, SUB)
addPrimitives(LongClass, nme.MUL, MUL)
addPrimitives(LongClass, nme.DIV, DIV)
addPrimitives(LongClass, nme.MOD, MOD)
addPrimitives(LongClass, nme.LT, LT)
addPrimitives(LongClass, nme.LE, LE)
addPrimitives(LongClass, nme.GT, GT)
addPrimitives(LongClass, nme.GE, GE)
addPrimitives(LongClass, nme.XOR, XOR)
addPrimitives(LongClass, nme.OR, OR)
addPrimitives(LongClass, nme.AND, AND)
addPrimitives(LongClass, nme.LSL, LSL)
addPrimitives(LongClass, nme.LSR, LSR)
addPrimitives(LongClass, nme.ASR, ASR)
addPrimitives(LongClass, nme.toByte, L2B)
addPrimitives(LongClass, nme.toShort, L2S)
addPrimitives(LongClass, nme.toChar, L2C)
addPrimitives(LongClass, nme.toInt, L2I)
addPrimitives(LongClass, nme.toLong, L2L)
addPrimitives(LongClass, nme.UNARY_+, POS)
addPrimitives(LongClass, nme.UNARY_-, NEG)
addPrimitives(LongClass, nme.UNARY_~, NOT)
addPrimitives(LongClass, nme.toFloat, L2F)
addPrimitives(LongClass, nme.toDouble, L2D)
addPrimitives(FloatClass, nme.EQ, EQ)
addPrimitives(FloatClass, nme.NE, NE)
addPrimitives(FloatClass, nme.ADD, ADD)
addPrimitives(FloatClass, nme.SUB, SUB)
addPrimitives(FloatClass, nme.MUL, MUL)
addPrimitives(FloatClass, nme.DIV, DIV)
addPrimitives(FloatClass, nme.MOD, MOD)
addPrimitives(FloatClass, nme.LT, LT)
addPrimitives(FloatClass, nme.LE, LE)
addPrimitives(FloatClass, nme.GT, GT)
addPrimitives(FloatClass, nme.GE, GE)
addPrimitives(FloatClass, nme.toByte, F2B)
addPrimitives(FloatClass, nme.toShort, F2S)
addPrimitives(FloatClass, nme.toChar, F2C)
addPrimitives(FloatClass, nme.toInt, F2I)
addPrimitives(FloatClass, nme.toLong, F2L)
addPrimitives(FloatClass, nme.toFloat, F2F)
addPrimitives(FloatClass, nme.toDouble, F2D)
addPrimitives(FloatClass, nme.UNARY_+, POS)
addPrimitives(FloatClass, nme.UNARY_-, NEG)
addPrimitives(DoubleClass, nme.EQ, EQ)
addPrimitives(DoubleClass, nme.NE, NE)
addPrimitives(DoubleClass, nme.ADD, ADD)
addPrimitives(DoubleClass, nme.SUB, SUB)
addPrimitives(DoubleClass, nme.MUL, MUL)
addPrimitives(DoubleClass, nme.DIV, DIV)
addPrimitives(DoubleClass, nme.MOD, MOD)
addPrimitives(DoubleClass, nme.LT, LT)
addPrimitives(DoubleClass, nme.LE, LE)
addPrimitives(DoubleClass, nme.GT, GT)
addPrimitives(DoubleClass, nme.GE, GE)
addPrimitives(DoubleClass, nme.toByte, D2B)
addPrimitives(DoubleClass, nme.toShort, D2S)
addPrimitives(DoubleClass, nme.toChar, D2C)
addPrimitives(DoubleClass, nme.toInt, D2I)
addPrimitives(DoubleClass, nme.toLong, D2L)
addPrimitives(DoubleClass, nme.toFloat, D2F)
addPrimitives(DoubleClass, nme.toDouble, D2D)
addPrimitives(DoubleClass, nme.UNARY_+, POS)
addPrimitives(DoubleClass, nme.UNARY_-, NEG)
}
def addPrimitive(s: Symbol, code: Int) {
assert(!(primitives contains s), "Duplicate primitive " + s)
primitives(s) = code
}
def addPrimitives(cls: Symbol, method: Name, code: Int) {
val tpe = cls.info
val sym = tpe.member(method)
if (sym == NoSymbol)
inform("Unknown primitive method " + cls + "." + method)
for (s <- sym.alternatives)
addPrimitive(
s,
if (code == ADD && s.info.paramTypes.head == definitions.StringClass.tpe) CONCAT
else code)
}
def isCoercion(code: Int): Boolean = (code >= B2B) && (code <= D2D)
final val typeOfArrayOp: Map[Int, TypeKind] = Map(
(List(ZARRAY_LENGTH, ZARRAY_GET, ZARRAY_SET) map (_ -> BOOL)) ++
(List(BARRAY_LENGTH, BARRAY_GET, BARRAY_SET) map (_ -> BYTE)) ++
(List(SARRAY_LENGTH, SARRAY_GET, SARRAY_SET) map (_ -> SHORT)) ++
(List(CARRAY_LENGTH, CARRAY_GET, CARRAY_SET) map (_ -> CHAR)) ++
(List(IARRAY_LENGTH, IARRAY_GET, IARRAY_SET) map (_ -> INT)) ++
(List(LARRAY_LENGTH, LARRAY_GET, LARRAY_SET) map (_ -> LONG)) ++
(List(FARRAY_LENGTH, FARRAY_GET, FARRAY_SET) map (_ -> FLOAT)) ++
(List(DARRAY_LENGTH, DARRAY_GET, DARRAY_SET) map (_ -> DOUBLE)) ++
(List(OARRAY_LENGTH, OARRAY_GET, OARRAY_SET) map (_ -> REFERENCE(AnyRefClass))) : _*
)
def isArrayOp(code: Int): Boolean =
isArrayNew(code) | isArrayLength(code) | isArrayGet(code) | isArraySet(code)
def isArrayNew(code: Int): Boolean = code match {
case NEW_ZARRAY | NEW_BARRAY | NEW_SARRAY | NEW_CARRAY |
NEW_IARRAY | NEW_LARRAY | NEW_FARRAY | NEW_DARRAY |
NEW_OARRAY => true
case _ => false
}
def isArrayLength(code: Int): Boolean = code match {
case ZARRAY_LENGTH | BARRAY_LENGTH | SARRAY_LENGTH | CARRAY_LENGTH |
IARRAY_LENGTH | LARRAY_LENGTH | FARRAY_LENGTH | DARRAY_LENGTH |
OARRAY_LENGTH | LENGTH => true
case _ => false
}
def isArrayGet(code: Int): Boolean = code match {
case ZARRAY_GET | BARRAY_GET | SARRAY_GET | CARRAY_GET |
IARRAY_GET | LARRAY_GET | FARRAY_GET | DARRAY_GET |
OARRAY_GET | APPLY => true
case _ => false
}
def isArraySet(code: Int): Boolean = code match {
case ZARRAY_SET | BARRAY_SET | SARRAY_SET | CARRAY_SET |
IARRAY_SET | LARRAY_SET | FARRAY_SET | DARRAY_SET |
OARRAY_SET | UPDATE => true;
case _ => false;
}
def isComparisonOp(code: Int): Boolean = code match {
case ID | NI | EQ | NE |
LT | LE | GT | GE => true
case _ => false
}
def isUniversalEqualityOp(code: Int): Boolean = (code == EQ) || (code == NE)
def isReferenceEqualityOp(code: Int): Boolean = (code == ID) || (code == NI)
def isArithmeticOp(code: Int): Boolean = code match {
case POS | NEG | NOT => true;
case ADD | SUB | MUL |
DIV | MOD => true;
case OR | XOR | AND |
LSL | LSR | ASR => true;
case _ => false;
}
def isLogicalOp(code: Int): Boolean = code match {
case ZNOT | ZAND | ZOR => true
case _ => false
}
def isShiftOp(code: Int): Boolean = code match {
case LSL | LSR | ASR => true
case _ => false
}
def isBitwiseOp(code: Int): Boolean = code match {
case OR | XOR | AND => true
case _ => false
}
def generatedKind(code: Int): TypeKind = code match {
case B2B | C2B | S2B | I2B | L2B | F2B | D2B => BYTE
case B2C | C2C | S2C | I2C | L2C | F2C | D2C => CHAR
case B2S | C2S | S2S | I2S | L2S | F2S | D2S => SHORT
case B2I | C2I | S2I | I2I | L2I | F2I | D2I => INT
case B2L | C2L | S2L | I2L | L2L | F2L | D2L => LONG
case B2F | C2F | S2F | I2F | L2F | F2F | D2F => FLOAT
case B2D | C2D | S2D | I2D | L2D | F2D | D2D => DOUBLE
}
def isPrimitive(sym: Symbol): Boolean = primitives contains sym
def getPrimitive(sym: Symbol): Int = {
assert(isPrimitive(sym), "Unknown primitive " + sym)
primitives(sym)
}
def getPrimitive(fun: Symbol, tpe: Type): Int = {
import definitions._
val code = getPrimitive(fun)
def elementType = atPhase(currentRun.typerPhase) {
val arrayParent = tpe :: tpe.parents collectFirst {
case TypeRef(_, ArrayClass, elem :: Nil) => elem
}
arrayParent getOrElse sys.error(fun.fullName + " : " + (tpe :: tpe.baseTypeSeq.toList).mkString(", "))
}
code match {
case APPLY =>
toTypeKind(elementType) match {
case BOOL => ZARRAY_GET
case BYTE => BARRAY_GET
case SHORT => SARRAY_GET
case CHAR => CARRAY_GET
case INT => IARRAY_GET
case LONG => LARRAY_GET
case FLOAT => FARRAY_GET
case DOUBLE => DARRAY_GET
case REFERENCE(_) | ARRAY(_) => OARRAY_GET
case _ =>
abort("Unexpected array element type: " + elementType)
}
case UPDATE =>
toTypeKind(elementType) match {
case BOOL => ZARRAY_SET
case BYTE => BARRAY_SET
case SHORT => SARRAY_SET
case CHAR => CARRAY_SET
case INT => IARRAY_SET
case LONG => LARRAY_SET
case FLOAT => FARRAY_SET
case DOUBLE => DARRAY_SET
case REFERENCE(_) | ARRAY(_) => OARRAY_SET
case _ =>
abort("Unexpected array element type: " + elementType)
}
case LENGTH =>
toTypeKind(elementType) match {
case BOOL => ZARRAY_LENGTH
case BYTE => BARRAY_LENGTH
case SHORT => SARRAY_LENGTH
case CHAR => CARRAY_LENGTH
case INT => IARRAY_LENGTH
case LONG => LARRAY_LENGTH
case FLOAT => FARRAY_LENGTH
case DOUBLE => DARRAY_LENGTH
case REFERENCE(_) | ARRAY(_) => OARRAY_LENGTH
case _ =>
abort("Unexpected array element type: " + elementType)
}
case _ =>
code
}
}
}