Skip to content

Commit 866f1ae

Browse files
committed
Merge pull request #9 from magarciaEPFL/b2
adding GenBCode to dotc
2 parents 25e97e1 + 051ad46 commit 866f1ae

14 files changed

+1138
-150
lines changed

src/dotty/tools/dotc/Compiler.scala

100644100755
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import reporting.ConsoleReporter
1010

1111
class Compiler {
1212

13-
def phases = List(new FrontEnd)
13+
def phases = List(new FrontEnd, new backend.jvm.GenBCode.BCodePhase)
1414

1515
def rootContext(implicit ctx: Context): Context = {
1616
ctx.definitions.init()

src/dotty/tools/dotc/backend/jvm/BCodeBodyBuilder.scala

100644100755
Lines changed: 102 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
*/
55

66

7-
package scala
8-
package tools.nsc
7+
package dotty.tools
8+
package dotc
99
package backend
1010
package jvm
1111

@@ -14,23 +14,31 @@ import scala.annotation.switch
1414

1515
import scala.tools.asm
1616

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+
1723
/*
1824
*
1925
* @author Miguel Garcia, http://lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/
2026
* @version 1.0
2127
*
2228
*/
2329
abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
24-
import global._
25-
import definitions._
30+
31+
import ast.tpd._
2632

2733
/*
2834
* Functionality to build the body of ASM MethodNode, except for `synchronized` and `try` expressions.
2935
*/
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) {
3138

3239
import icodes.TestOp
3340
import icodes.opcodes.InvokeStyle
41+
import StdNames.nme
3442

3543
/* If the selector type has a member with the right name,
3644
* it is the host class; otherwise the symbol's owner.
@@ -218,10 +226,83 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
218226
resKind
219227
}
220228

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+
221302
def genPrimitiveOp(tree: Apply, expectedType: BType): BType = {
222303
val sym = tree.symbol
223304
val Apply(fun @ Select(receiver, _), _) = tree
224-
val code = scalaPrimitives.getPrimitive(sym, receiver.tpe)
305+
val code = getPrimitive(sym, receiver.tpe)
225306

226307
import scalaPrimitives.{isArithmeticOp, isArrayOp, isLogicalOp, isComparisonOp}
227308

@@ -306,7 +387,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
306387
case app : Apply =>
307388
generatedType = genApply(app, expectedType)
308389

309-
case ApplyDynamic(qual, args) => sys.error("No invokedynamic support yet.")
390+
// case ApplyDynamic(qual, args) => sys.error("No invokedynamic support yet.")
310391

311392
case This(qual) =>
312393
val symIsModuleClass = tree.symbol.isModuleClass
@@ -359,10 +440,10 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
359440

360441
case Literal(value) =>
361442
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)
366447
}
367448

368449
case blck : Block => genBlock(blck, expectedType)
@@ -434,6 +515,9 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
434515
* Otherwise it's safe to call from multiple threads.
435516
*/
436517
def genConstant(const: Constant) {
518+
519+
import dotc.core.Constants._
520+
437521
(const.tag: @switch) match {
438522

439523
case BooleanTag => bc.boolconst(const.booleanValue)
@@ -825,7 +909,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
825909
}
826910

827911
/* 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) {
829913

830914
val aps = {
831915
val params: List[Symbol] = lblDef.params.map(_.symbol)
@@ -936,7 +1020,10 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
9361020
StringReference
9371021
}
9381022

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) {
9401027

9411028
val siteSymbol = claszSymbol
9421029
val hostSymbol = if (hostClass0 == null) method.owner else hostClass0;
@@ -1118,7 +1205,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
11181205
tree match {
11191206

11201207
case Apply(fun, args) if isPrimitive(fun.symbol) =>
1121-
import scalaPrimitives.{ ZNOT, ZAND, ZOR, EQ, getPrimitive }
1208+
import scalaPrimitives.{ ZNOT, ZAND, ZOR, EQ }
11221209

11231210
// lhs and rhs of test
11241211
lazy val Select(lhs, _) = fun
@@ -1135,7 +1222,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
11351222
genCond(rhs, success, failure)
11361223
}
11371224

1138-
getPrimitive(fun.symbol) match {
1225+
scalaPrimitives.getPrimitive(fun.symbol) match {
11391226
case ZNOT => genCond(lhs, failure, success)
11401227
case ZAND => genZandOrZor(and = true)
11411228
case ZOR => genZandOrZor(and = false)

src/dotty/tools/dotc/backend/jvm/BCodeGlue.scala

100644100755
Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,31 @@
33
* @author Martin Odersky
44
*/
55

6-
package scala
7-
package tools.nsc
6+
package dotty.tools
7+
package dotc
88
package backend.jvm
99

1010
import scala.tools.asm
1111
import scala.annotation.switch
1212
import scala.collection.{ immutable, mutable }
1313

14+
import dotc.ast.Trees.Tree
15+
import dotc.core.Types.Type
16+
import dotc.core.Symbols.{Symbol, NoSymbol}
17+
1418
/*
1519
* Immutable representations of bytecode-level types.
1620
*
1721
* @author Miguel Garcia, http://lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded
1822
* @version 1.0
1923
*
2024
*/
21-
abstract class BCodeGlue extends SubComponent {
22-
23-
import global._
25+
abstract class BCodeGlue {
2426

2527
object BType {
2628

27-
import global.chrs
29+
import core.Names
30+
import Names.chrs
2831

2932
// ------------- sorts -------------
3033

@@ -124,7 +127,7 @@ abstract class BCodeGlue extends SubComponent {
124127
* must-single-thread
125128
*/
126129
def getMethodType(methodDescriptor: String): BType = {
127-
val n = global.newTypeName(methodDescriptor)
130+
val n = Names.typeName(methodDescriptor)
128131
new BType(BType.METHOD, n.start, n.length) // TODO assert isValidMethodDescriptor
129132
}
130133

@@ -138,7 +141,7 @@ abstract class BCodeGlue extends SubComponent {
138141
* must-single-thread
139142
*/
140143
def getMethodType(returnType: BType, argumentTypes: Array[BType]): BType = {
141-
val n = global.newTypeName(getMethodDescriptor(returnType, argumentTypes))
144+
val n = Names.typeName(getMethodDescriptor(returnType, argumentTypes))
142145
new BType(BType.METHOD, n.start, n.length)
143146
}
144147

@@ -206,7 +209,7 @@ abstract class BCodeGlue extends SubComponent {
206209
* must-single-thread
207210
*/
208211
def getReturnType(methodDescriptor: String): BType = {
209-
val n = global.newTypeName(methodDescriptor)
212+
val n = Names.typeName(methodDescriptor)
210213
val delta = n.pos(')') // `delta` is relative to the Name's zero-based start position, not a valid index into chrs.
211214
assert(delta < n.length, s"not a valid method descriptor: $methodDescriptor")
212215
getType(n.start + delta + 1)
@@ -248,7 +251,7 @@ abstract class BCodeGlue extends SubComponent {
248251
*/
249252
final class BType(val sort: Int, val off: Int, val len: Int) {
250253

251-
import global.chrs
254+
import core.Names.chrs
252255

253256
/*
254257
* can-multi-thread
@@ -619,15 +622,15 @@ abstract class BCodeGlue extends SubComponent {
619622
*
620623
* must-single-thread
621624
*/
622-
def brefType(iname: String): BType = { brefType(newTypeName(iname.toCharArray(), 0, iname.length())) }
625+
def brefType(iname: String): BType = { brefType(dotc.core.Names.typeName(iname.toCharArray(), 0, iname.length())) }
623626

624627
/*
625628
* Creates a BType token for the TypeName received as argument.
626629
* This method does not add to `innerClassBufferASM`, use `internalName()` or `asmType()` or `toTypeKind()` for that.
627630
*
628631
* can-multi-thread
629632
*/
630-
def brefType(iname: TypeName): BType = { BType.getObjectType(iname.start, iname.length) }
633+
def brefType(iname: core.Names.TypeName): BType = { BType.getObjectType(iname.start, iname.length) }
631634

632635
// due to keyboard economy only
633636
val UNIT = BType.VOID_TYPE

0 commit comments

Comments
 (0)