4
4
*/
5
5
6
6
7
- package scala
8
- package tools . nsc
7
+ package dotty . tools
8
+ package dotc
9
9
package backend
10
10
package jvm
11
11
@@ -14,23 +14,31 @@ import scala.annotation.switch
14
14
15
15
import scala .tools .asm
16
16
17
+ import dotc .ast .Trees ._
18
+ import core .Types .Type
19
+ import core .StdNames
20
+ import core .Symbols .{Symbol , NoSymbol }
21
+ import core .Constants .Constant
22
+
17
23
/*
18
24
*
19
25
* @author Miguel Garcia, http://lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/
20
26
* @version 1.0
21
27
*
22
28
*/
23
29
abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
24
- import global . _
25
- import definitions ._
30
+
31
+ import ast . tpd ._
26
32
27
33
/*
28
34
* Functionality to build the body of ASM MethodNode, except for `synchronized` and `try` expressions.
29
35
*/
30
- abstract class PlainBodyBuilder (cunit : CompilationUnit ) extends PlainSkelBuilder (cunit) {
36
+ abstract class PlainBodyBuilder (cunit : CompilationUnit ,
37
+ implicit val ctx : dotc.core.Contexts .Context ) extends PlainSkelBuilder (cunit) {
31
38
32
39
import icodes .TestOp
33
40
import icodes .opcodes .InvokeStyle
41
+ import StdNames .nme
34
42
35
43
/* If the selector type has a member with the right name,
36
44
* it is the host class; otherwise the symbol's owner.
@@ -218,10 +226,83 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
218
226
resKind
219
227
}
220
228
229
+ /**
230
+ * Return the primitive code of the given operation. If the
231
+ * operation is an array get/set, we inspect the type of the receiver
232
+ * to demux the operation.
233
+ *
234
+ * @param fun The method symbol
235
+ * @param tpe The type of the receiver object. It is used only for array
236
+ * operations
237
+ */
238
+ def getPrimitive (fun : Symbol , tpe : Type ): Int = {
239
+ val code = scalaPrimitives.getPrimitive(fun)
240
+
241
+ def elementType = enteringTyper {
242
+ val arrayParent = tpe :: tpe.parents collectFirst {
243
+ case dotc.core.Types .TypeRef (_, ArrayClass , elem :: Nil ) => elem
244
+ }
245
+ arrayParent getOrElse sys.error(fun.fullName + " : " + (tpe :: tpe.baseTypeSeq.toList).mkString(" , " ))
246
+ }
247
+
248
+ import scalaPrimitives ._
249
+
250
+ code match {
251
+
252
+ case APPLY =>
253
+ toTypeKind(elementType) match {
254
+ case BType .BOOLEAN_TYPE => ZARRAY_GET
255
+ case BType .BYTE_TYPE => BARRAY_GET
256
+ case BType .SHORT_TYPE => SARRAY_GET
257
+ case BType .CHAR_TYPE => CARRAY_GET
258
+ case BType .INT_TYPE => IARRAY_GET
259
+ case BType .LONG_TYPE => LARRAY_GET
260
+ case BType .FLOAT_TYPE => FARRAY_GET
261
+ case BType .DOUBLE_TYPE => DARRAY_GET
262
+ case r =>
263
+ assert(r.isRefOrArrayType)
264
+ OARRAY_GET
265
+ }
266
+
267
+ case UPDATE =>
268
+ toTypeKind(elementType) match {
269
+ case BType .BOOLEAN_TYPE => ZARRAY_SET
270
+ case BType .BYTE_TYPE => BARRAY_SET
271
+ case BType .SHORT_TYPE => SARRAY_SET
272
+ case BType .CHAR_TYPE => CARRAY_SET
273
+ case BType .INT_TYPE => IARRAY_SET
274
+ case BType .LONG_TYPE => LARRAY_SET
275
+ case BType .FLOAT_TYPE => FARRAY_SET
276
+ case BType .DOUBLE_TYPE => DARRAY_SET
277
+ case r =>
278
+ assert(r.isRefOrArrayType)
279
+ OARRAY_SET
280
+ }
281
+
282
+ case LENGTH =>
283
+ toTypeKind(elementType) match {
284
+ case BType .BOOLEAN_TYPE => ZARRAY_LENGTH
285
+ case BType .BYTE_TYPE => BARRAY_LENGTH
286
+ case BType .SHORT_TYPE => SARRAY_LENGTH
287
+ case BType .CHAR_TYPE => CARRAY_LENGTH
288
+ case BType .INT_TYPE => IARRAY_LENGTH
289
+ case BType .LONG_TYPE => LARRAY_LENGTH
290
+ case BType .FLOAT_TYPE => FARRAY_LENGTH
291
+ case BType .DOUBLE_TYPE => DARRAY_LENGTH
292
+ case r =>
293
+ assert(r.isRefOrArrayType)
294
+ OARRAY_LENGTH
295
+ }
296
+
297
+ case _ =>
298
+ code
299
+ }
300
+ }
301
+
221
302
def genPrimitiveOp (tree : Apply , expectedType : BType ): BType = {
222
303
val sym = tree.symbol
223
304
val Apply (fun @ Select (receiver, _), _) = tree
224
- val code = scalaPrimitives. getPrimitive(sym, receiver.tpe)
305
+ val code = getPrimitive(sym, receiver.tpe)
225
306
226
307
import scalaPrimitives .{isArithmeticOp , isArrayOp , isLogicalOp , isComparisonOp }
227
308
@@ -306,7 +387,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
306
387
case app : Apply =>
307
388
generatedType = genApply(app, expectedType)
308
389
309
- case ApplyDynamic (qual, args) => sys.error(" No invokedynamic support yet." )
390
+ // case ApplyDynamic(qual, args) => sys.error("No invokedynamic support yet.")
310
391
311
392
case This (qual) =>
312
393
val symIsModuleClass = tree.symbol.isModuleClass
@@ -359,10 +440,10 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
359
440
360
441
case Literal (value) =>
361
442
if (value.tag != UnitTag ) (value.tag, expectedType) match {
362
- case (IntTag , LONG ) => bc.lconst(value.longValue); generatedType = LONG
363
- case (FloatTag , DOUBLE ) => bc.dconst(value.doubleValue); generatedType = DOUBLE
364
- case (NullTag , _ ) => bc.emit(asm.Opcodes .ACONST_NULL ); generatedType = RT_NULL
365
- case _ => genConstant(value); generatedType = tpeTK(tree)
443
+ case (dotc.core. Constants . IntTag , LONG ) => bc.lconst(value.longValue); generatedType = LONG
444
+ case (dotc.core. Constants . FloatTag , DOUBLE ) => bc.dconst(value.doubleValue); generatedType = DOUBLE
445
+ case (dotc.core. Constants . NullTag , _ ) => bc.emit(asm.Opcodes .ACONST_NULL ); generatedType = RT_NULL
446
+ case _ => genConstant(value); generatedType = tpeTK(tree)
366
447
}
367
448
368
449
case blck : Block => genBlock(blck, expectedType)
@@ -434,6 +515,9 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
434
515
* Otherwise it's safe to call from multiple threads.
435
516
*/
436
517
def genConstant (const : Constant ) {
518
+
519
+ import dotc .core .Constants ._
520
+
437
521
(const.tag: @ switch) match {
438
522
439
523
case BooleanTag => bc.boolconst(const.booleanValue)
@@ -825,7 +909,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
825
909
}
826
910
827
911
/* Generate code that loads args into label parameters. */
828
- def genLoadLabelArguments (args : List [Tree ], lblDef : LabelDef , gotoPos : Position ) {
912
+ def genLoadLabelArguments (args : List [Tree ], lblDef : LabelDef , gotoPos : dotc.util. Positions . Position ) {
829
913
830
914
val aps = {
831
915
val params : List [Symbol ] = lblDef.params.map(_.symbol)
@@ -936,7 +1020,10 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
936
1020
StringReference
937
1021
}
938
1022
939
- def genCallMethod (method : Symbol , style : InvokeStyle , hostClass0 : Symbol = null , pos : Position = NoPosition ) {
1023
+ def genCallMethod (method : Symbol ,
1024
+ style : InvokeStyle ,
1025
+ hostClass0 : Symbol = null ,
1026
+ pos : dotc.util.Positions .Position = dotc.util.Positions .NoPosition ) {
940
1027
941
1028
val siteSymbol = claszSymbol
942
1029
val hostSymbol = if (hostClass0 == null ) method.owner else hostClass0;
@@ -1118,7 +1205,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
1118
1205
tree match {
1119
1206
1120
1207
case Apply (fun, args) if isPrimitive(fun.symbol) =>
1121
- import scalaPrimitives .{ ZNOT , ZAND , ZOR , EQ , getPrimitive }
1208
+ import scalaPrimitives .{ ZNOT , ZAND , ZOR , EQ }
1122
1209
1123
1210
// lhs and rhs of test
1124
1211
lazy val Select (lhs, _) = fun
@@ -1135,7 +1222,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
1135
1222
genCond(rhs, success, failure)
1136
1223
}
1137
1224
1138
- getPrimitive(fun.symbol) match {
1225
+ scalaPrimitives. getPrimitive(fun.symbol) match {
1139
1226
case ZNOT => genCond(lhs, failure, success)
1140
1227
case ZAND => genZandOrZor(and = true )
1141
1228
case ZOR => genZandOrZor(and = false )
0 commit comments