Skip to content

Commit c5c400c

Browse files
committed
Merge pull request #124 from DarkDimius/backend-backport2
Backend backport2
2 parents bf9ae99 + 2001062 commit c5c400c

File tree

10 files changed

+220
-21
lines changed

10 files changed

+220
-21
lines changed

src/dotty/tools/dotc/Compiler.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class Compiler {
2121
List(
2222
List(new FrontEnd),
2323
List(new LazyValsCreateCompanionObjects,
24+
/* new Constructors, */
2425
new TailRec), //force separataion between lazyVals and LVCreateCO
2526
List(new PatternMatcher,
2627
new LazyValTranformContext().transformer,
@@ -29,7 +30,7 @@ class Compiler {
2930
new TypeTestsCasts,
3031
new InterceptedMethods),
3132
List(new Erasure),
32-
List(new UncurryTreeTransform)
33+
List(new UncurryTreeTransform, new CollectEntryPoints)
3334
)
3435

3536
var runId = 1

src/dotty/tools/dotc/config/JavaPlatform.scala

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ package config
55
import io.{AbstractFile,ClassPath,JavaClassPath,MergedClassPath,DeltaClassPath}
66
import ClassPath.{ JavaContext, DefaultJavaContext }
77
import core.Contexts._
8-
import core.SymDenotations._, core.Symbols._, core.{SymbolLoader, ClassfileLoader}
8+
import core.SymDenotations._, core.Symbols._, dotty.tools.dotc.core._
9+
import Types._, Contexts._, Symbols._, Denotations._, SymDenotations._, StdNames._, Names._
10+
import Flags._, Scopes._, Decorators._, NameOps._, util.Positions._
911

1012
class JavaPlatform extends Platform {
1113

@@ -17,6 +19,22 @@ class JavaPlatform extends Platform {
1719
currentClassPath.get
1820
}
1921

22+
// The given symbol is a method with the right name and signature to be a runnable java program.
23+
def isJavaMainMethod(sym: SymDenotation)(implicit ctx: Context) = {
24+
val dn = defn
25+
(sym.name == nme.main) && (sym.info match {
26+
case t@MethodType(_, dn.ArrayType(el) :: Nil) => el =:= defn.StringType && (t.resultType isRef defn.UnitClass)
27+
case _ => false
28+
})
29+
}
30+
31+
// The given class has a main method.
32+
def hasJavaMainMethod(sym: Symbol)(implicit ctx: Context): Boolean =
33+
(sym.info member nme.main).hasAltWith {
34+
case x: SymDenotation => isJavaMainMethod(x)
35+
case _ => false
36+
}
37+
2038
/** Update classpath with a substituted subentry */
2139
def updateClassPath(subst: Map[ClassPath, ClassPath]) =
2240
currentClassPath = Some(new DeltaClassPath(currentClassPath.get, subst))

src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ class Definitions {
156156

157157
lazy val ScalaPredefModule = ctx.requiredModule("scala.Predef")
158158
lazy val ScalaRuntimeModule = ctx.requiredModule("scala.runtime.ScalaRunTime")
159+
lazy val BoxesRunTimeModule = ctx.requiredModule("scala.runtime.BoxesRunTime")
160+
lazy val BoxesRunTimeClass = BoxesRunTimeModule.moduleClass
159161
lazy val DottyPredefModule = ctx.requiredModule("dotty.DottyPredef")
160162
lazy val NilModule = ctx.requiredModule("scala.collection.immutable.Nil")
161163

@@ -168,6 +170,10 @@ class Definitions {
168170
List(AnyClass.typeRef), EmptyScope)
169171
lazy val SeqClass: ClassSymbol = ctx.requiredClass("scala.collection.Seq")
170172
lazy val ArrayClass: ClassSymbol = ctx.requiredClass("scala.Array")
173+
lazy val Array_apply = ctx.requiredMethod(ArrayClass, nme.apply)
174+
lazy val Array_update = ctx.requiredMethod(ArrayClass, nme.update)
175+
lazy val Array_length = ctx.requiredMethod(ArrayClass, nme.length)
176+
lazy val Array_clone = ctx.requiredMethod(ArrayClass, nme.clone_)
171177
lazy val uncheckedStableClass: ClassSymbol = ctx.requiredClass("scala.annotation.unchecked.uncheckedStable")
172178

173179
lazy val UnitClass = valueClassSymbol("scala.Unit", BoxedUnitClass, java.lang.Void.TYPE, UnitEnc)
@@ -211,8 +217,20 @@ class Definitions {
211217

212218
// fundamental classes
213219
lazy val StringClass = ctx.requiredClass("java.lang.String")
220+
lazy val StringModule = StringClass.moduleClass
214221

215222
lazy val String_+ = newMethod(StringClass, nme.raw.PLUS, methOfAny(StringType), Final)
223+
lazy val String_valueOf_Object = StringModule.info.member(nme.valueOf).suchThat(_.info.firstParamTypes match {
224+
case List(pt) => pt isRef ObjectClass
225+
case _ => false
226+
}).symbol
227+
228+
// in scalac modified to have Any as parrent
229+
230+
lazy val SerializableClass = ctx.requiredClass("scala.Serializable")
231+
lazy val JavaCloneableClass = ctx.requiredClass("java.lang.Cloneable")
232+
lazy val StringBuilderClass = ctx.requiredClass("scala.collection.mutable.StringBuilder")
233+
lazy val NullPointerExceptionClass = ctx.requiredClass(jnme.NPException)
216234

217235
lazy val StringAddClass = ctx.requiredClass("scala.runtime.StringAdd")
218236

@@ -238,6 +256,11 @@ class Definitions {
238256
lazy val ClassfileAnnotationClass = ctx.requiredClass("scala.annotation.ClassfileAnnotation")
239257
lazy val StaticAnnotationClass = ctx.requiredClass("scala.annotation.StaticAnnotation")
240258
lazy val TailrecAnnotationClass = ctx.requiredClass("scala.annotation.tailrec")
259+
lazy val RemoteAnnot = ctx.requiredClass("scala.remote")
260+
lazy val SerialVersionUIDAnnot = ctx.requiredClass("scala.SerialVersionUID")
261+
lazy val TransientAnnot = ctx.requiredClass("scala.transient")
262+
lazy val NativeAnnot = ctx.requiredClass("scala.native")
263+
lazy val ScalaStrictFPAnnot = ctx.requiredClass("scala.annotation.strictfp")
241264

242265
// Annotation classes
243266
lazy val AliasAnnot = ctx.requiredClass("dotty.annotation.internal.Alias")

src/dotty/tools/dotc/core/Types.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ object Types {
427427
Set()
428428
}
429429

430-
private def memberDenots(keepOnly: NameFilter, f: (Name, mutable.Buffer[SingleDenotation]) => Unit)(implicit ctx: Context): Seq[SingleDenotation] = {
430+
def memberDenots(keepOnly: NameFilter, f: (Name, mutable.Buffer[SingleDenotation]) => Unit)(implicit ctx: Context): Seq[SingleDenotation] = {
431431
val buf = mutable.ArrayBuffer[SingleDenotation]()
432432
for (name <- memberNames(keepOnly)) f(name, buf)
433433
buf
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package dotty.tools.dotc.transform
2+
3+
import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, TreeTransform, TreeTransformer}
4+
import dotty.tools.dotc.ast.tpd
5+
import dotty.tools.dotc.core.Contexts.Context
6+
import scala.collection.mutable.ListBuffer
7+
import dotty.tools.dotc.core.{Scopes, Flags}
8+
import dotty.tools.dotc.core.Symbols.NoSymbol
9+
import scala.annotation.tailrec
10+
import dotty.tools.dotc.core._
11+
import Symbols._
12+
import scala.Some
13+
import dotty.tools.dotc.transform.TreeTransforms.{NXTransformations, TransformerInfo, TreeTransform, TreeTransformer}
14+
import dotty.tools.dotc.ast.tpd
15+
import dotty.tools.dotc.core.Contexts.Context
16+
import scala.collection.mutable
17+
import dotty.tools.dotc.core.Names.Name
18+
import NameOps._
19+
import Types._
20+
import scala.collection.SortedSet
21+
import Decorators._
22+
import StdNames._
23+
import dotty.tools.dotc.util.Positions.Position
24+
import dotty.tools.dotc.config.JavaPlatform
25+
26+
class CollectEntryPoints extends TreeTransform {
27+
28+
/** perform context-dependant initialization */
29+
override def init(implicit ctx: Context, info: TransformerInfo): Unit = {
30+
entryPoints = collection.immutable.TreeSet.empty[Symbol](new SymbolOrdering())
31+
assert(ctx.platform.isInstanceOf[JavaPlatform], "Java platform specific phase")
32+
}
33+
34+
private var entryPoints: Set[Symbol] = _
35+
36+
def getEntryPoints = entryPoints.toList
37+
38+
override def name: String = "collectEntryPoints"
39+
override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = {
40+
if (tree.symbol.owner.isClass && isJavaEntryPoint(tree.symbol)) {
41+
// collecting symbols for entry points here (as opposed to GenBCode where they are used)
42+
// has the advantage of saving an additional pass over all ClassDefs.
43+
entryPoints += tree.symbol
44+
}
45+
tree
46+
}
47+
48+
def isJavaEntryPoint(sym: Symbol)(implicit ctx: Context): Boolean = {
49+
def fail(msg: String, pos: Position = sym.pos) = {
50+
ctx.warning(sym.name +
51+
s" has a main method with parameter type Array[String], but ${sym.fullName} will not be a runnable program.\n Reason: $msg",
52+
sourcePos(sym.pos)
53+
// TODO: make this next claim true, if possible
54+
// by generating valid main methods as static in module classes
55+
// not sure what the jvm allows here
56+
// + " You can still run the program by calling it as " + javaName(sym) + " instead."
57+
)
58+
false
59+
}
60+
def failNoForwarder(msg: String) = {
61+
fail(s"$msg, which means no static forwarder can be generated.\n")
62+
}
63+
val possibles = if (sym.flags is Flags.Module) (sym.info nonPrivateMember nme.main).alternatives else Nil
64+
val hasApproximate = possibles exists {
65+
m =>
66+
m.info match {
67+
case MethodType(_, p :: Nil) =>
68+
p.typeSymbol == defn.ArrayClass
69+
case _ => false
70+
}
71+
}
72+
def precise(implicit ctx: Context) = {
73+
val companion = sym.companionClass //sym.asClass.linkedClassOfClass
74+
val javaPlatform = ctx.platform.asInstanceOf[JavaPlatform]
75+
if (javaPlatform.hasJavaMainMethod(companion))
76+
failNoForwarder("companion contains its own main method")
77+
else if (companion != NoSymbol && companion.info.member(nme.main) != NoSymbol)
78+
// this is only because forwarders aren't smart enough yet
79+
failNoForwarder("companion contains its own main method (implementation restriction: no main is allowed, regardless of signature)")
80+
else if (companion.flags is Flags.Trait)
81+
failNoForwarder("companion is a trait")
82+
// Now either succeeed, or issue some additional warnings for things which look like
83+
// attempts to be java main methods.
84+
else (possibles exists (x => javaPlatform.isJavaMainMethod(x.symbol))) || {
85+
possibles exists {
86+
m =>
87+
m.symbol.info match {
88+
case t: PolyType =>
89+
fail("main methods cannot be generic.")
90+
case t@MethodType(paramNames, paramTypes) =>
91+
if (t.resultType :: paramTypes exists (_.typeSymbol.isAbstractType))
92+
fail("main methods cannot refer to type parameters or abstract types.", m.symbol.pos)
93+
else
94+
javaPlatform.isJavaMainMethod(m.symbol) || fail("main method must have exact signature (Array[String])Unit", m.symbol.pos)
95+
case tp =>
96+
fail(s"don't know what this is: $tp", m.symbol.pos)
97+
}
98+
}
99+
}
100+
}
101+
102+
// At this point it's a module with a main-looking method, so either succeed or warn that it isn't.
103+
hasApproximate && precise(ctx.withPhase(ctx.erasurePhase))
104+
// Before erasure so we can identify generic mains.
105+
106+
107+
}
108+
109+
}
110+
111+
class SymbolOrdering(implicit ctx: Context) extends Ordering[Symbol] {
112+
override def compare(x: Symbol, y: Symbol): Int = {
113+
x.fullName.toString.compareTo(y.fullName.toString)
114+
}
115+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package dotty.tools.dotc.transform
2+
3+
import TreeTransforms._
4+
import dotty.tools.dotc.ast.tpd._
5+
import dotty.tools.dotc.core.Contexts.Context
6+
import dotty.tools.dotc.core.StdNames._
7+
8+
/** This transform moves initializers from body to constructor.
9+
* Right now it's a dummy.
10+
* Awaiting for real implemetation
11+
*/
12+
class Constructors extends TreeTransform {
13+
14+
override def name: String = "constructors"
15+
override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
16+
if(tree.symbol.isClassConstructor) {
17+
val claz = tree.symbol.enclosingClass.asClass
18+
val zuper = claz.info.parents.head.typeSymbol
19+
cpy.DefDef(tree, tree.mods, tree.name, tree.tparams, tree.vparamss, tree.tpt, rhs = {
20+
val parentCall = Apply(Select(Super(This(claz), tpnme.EMPTY, true), zuper.primaryConstructor), Nil)
21+
if(tree.rhs.isEmpty) parentCall
22+
else Block(List(parentCall), tree.rhs)
23+
24+
})
25+
} else tree
26+
}
27+
}

src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ object Erasure {
205205
else recur(cast(qual, erasedPre))
206206

207207
def recur(qual: Tree): Tree = {
208-
val qualIsPrimitive = isPrimitiveValueType(qual.tpe)
208+
val qualIsPrimitive = isPrimitiveValueType(qual.tpe.widen)
209209
val symIsPrimitive = sym.owner.isPrimitiveValueClass
210210
if ((sym.owner eq defn.AnyClass) || (sym.owner eq defn.AnyValClass))
211211
select(qual, defn.ObjectClass.info.decl(sym.name).symbol)

src/dotty/tools/dotc/transform/LazyVals.scala

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class LazyValTranformContext {
4545

4646
def transformer = new LazyValsTransform
4747

48+
val containerFlags = Flags.Synthetic | Flags.Mutable
49+
4850
/** this map contains mutable state of transformation: OffsetDefs to be appended to companion object definitions,
4951
* and number of bits currently used */
5052
class OffsetInfo(var defs: List[Tree], var ord:Int)
@@ -140,9 +142,12 @@ class LazyValTranformContext {
140142

141143
val holderImpl = ctx.requiredClass("dotty.runtime." + holderType)
142144

143-
val holderSymbol = ctx.newSymbol(x.symbol.owner, holderName, Flags.Synthetic, holderImpl.typeRef, coord = x.symbol.coord)
145+
val holderSymbol = ctx.newSymbol(x.symbol.owner, holderName, containerFlags, holderImpl.typeRef, coord = x.symbol.coord)
144146
val holderTree = ValDef(holderSymbol, New(holderImpl.typeRef, List(valueInitter)))
145-
val methodTree = DefDef(x.symbol.asTerm, Select(Ident(holderSymbol.termRef), "value".toTermName))
147+
val methodBody =
148+
if(holderType != "LazyRef") Select(Ident(holderSymbol.termRef), "value".toTermName)
149+
else TypeApply(Select(Select(Ident(holderSymbol.termRef), "value".toTermName), defn.Any_asInstanceOf), List(TypeTree(tpe)))
150+
val methodTree = DefDef(x.symbol.asTerm, methodBody)
146151
ctx.debuglog(s"found a lazy val ${x.show},\n rewrote with ${holderTree.show}")
147152
Thicket(holderTree, methodTree)
148153
}
@@ -201,7 +206,7 @@ class LazyValTranformContext {
201206
val tpe = x.tpe.widen
202207
assert(!(mods is Flags.Mutable))
203208
val containerName = ctx.freshName(name.toString + StdNames.nme.LAZY_LOCAL).toTermName
204-
val containerSymbol = ctx.newSymbol(claz, containerName, (mods &~ Flags.Lazy & Flags.Synthetic).flags, tpe, coord = x.symbol.coord)
209+
val containerSymbol = ctx.newSymbol(claz, containerName, (mods &~ Flags.Lazy | containerFlags).flags, tpe, coord = x.symbol.coord)
205210
addSym(claz, containerSymbol)
206211

207212
val containerTree = ValDef(containerSymbol, Literal(initValue(tpe)))
@@ -211,7 +216,7 @@ class LazyValTranformContext {
211216
}
212217
else {
213218
val flagName = ctx.freshName(name.toString + StdNames.nme.BITMAP_PREFIX).toTermName
214-
val flagSymbol = ctx.newSymbol(x.symbol.owner, flagName, Flags.Synthetic, defn.BooleanType)
219+
val flagSymbol = ctx.newSymbol(x.symbol.owner, flagName, containerFlags, defn.BooleanType)
215220
val flag = ValDef(flagSymbol, Literal(Constants.Constant(false)))
216221
val slowPath = DefDef(x.symbol.asTerm, mkNonThreadSafeDef(containerSymbol, flagSymbol, rhs))
217222
Thicket(List(containerTree, flag, slowPath))
@@ -256,15 +261,15 @@ class LazyValTranformContext {
256261
val computeState = Literal(Constants.Constant(1))
257262
val notifyState = Literal(Constants.Constant(2))
258263
val computedState = Literal(Constants.Constant(3))
259-
val flagSymbol = ctx.newSymbol(methodSymbol, "flag".toTermName, Flags.Mutable & Flags.Synthetic, defn.LongType)
264+
val flagSymbol = ctx.newSymbol(methodSymbol, "flag".toTermName, containerFlags, defn.LongType)
260265
val flagDef = ValDef(flagSymbol, Literal(Constant(0L)))
261266

262267
val thiz = This(claz)(ctx.fresh.setOwner(claz))
263268

264-
val resultSymbol = ctx.newSymbol(methodSymbol, "result".toTermName, Flags.Mutable & Flags.Synthetic, tp)
269+
val resultSymbol = ctx.newSymbol(methodSymbol, "result".toTermName, containerFlags, tp)
265270
val resultDef = ValDef(resultSymbol, Literal(initValue(tp.widen)))
266271

267-
val retrySymbol = ctx.newSymbol(methodSymbol, "retry".toTermName, Flags.Mutable & Flags.Synthetic, defn.BooleanType)
272+
val retrySymbol = ctx.newSymbol(methodSymbol, "retry".toTermName, containerFlags, defn.BooleanType)
268273
val retryDef = ValDef(retrySymbol, Literal(Constants.Constant(true)))
269274

270275
val whileCond = Ident(retrySymbol.termRef)
@@ -345,7 +350,7 @@ class LazyValTranformContext {
345350
} else { // need to create a new flag
346351
offsetSymbol = ctx.newSymbol(companion.moduleClass, (StdNames.nme.LAZY_FIELD_OFFSET + id.toString).toTermName, Flags.Synthetic, defn.LongType).entered
347352
val flagName = (StdNames.nme.BITMAP_PREFIX + id.toString).toTermName
348-
val flagSymbol = ctx.newSymbol(claz, flagName, Flags.Synthetic, defn.LongType)
353+
val flagSymbol = ctx.newSymbol(claz, flagName, containerFlags, defn.LongType)
349354
addSym(claz, flagSymbol)
350355
flag = ValDef(flagSymbol, Literal(Constants.Constant(0L)))
351356
val offsetTree = ValDef(offsetSymbol, Apply(getOffset, List(thiz, Literal(Constant(flagName.toString)))))
@@ -355,15 +360,15 @@ class LazyValTranformContext {
355360
case None =>
356361
offsetSymbol = ctx.newSymbol(companion.moduleClass, (StdNames.nme.LAZY_FIELD_OFFSET + "0").toTermName, Flags.Synthetic, defn.LongType).entered
357362
val flagName = (StdNames.nme.BITMAP_PREFIX + "0").toTermName
358-
val flagSymbol = ctx.newSymbol(claz, flagName, Flags.Synthetic, defn.LongType)
363+
val flagSymbol = ctx.newSymbol(claz, flagName, containerFlags, defn.LongType)
359364
addSym(claz, flagSymbol)
360365
flag = ValDef(flagSymbol, Literal(Constants.Constant(0L)))
361366
val offsetTree = ValDef(offsetSymbol, Apply(getOffset, List(thiz, Literal(Constant(flagName.toString)))))
362367
appendOffsetDefs += (companion.name.moduleClassName -> new OffsetInfo(List(offsetTree), ord))
363368
}
364369

365370
val containerName = ctx.freshName(name.toString + StdNames.nme.LAZY_LOCAL).toTermName
366-
val containerSymbol = ctx.newSymbol(claz, containerName, (mods &~ Flags.Lazy & Flags.Synthetic).flags, tpe, coord = x.symbol.coord)
371+
val containerSymbol = ctx.newSymbol(claz, containerName, (mods &~ Flags.Lazy | containerFlags).flags, tpe, coord = x.symbol.coord)
367372
addSym(claz, containerSymbol)
368373
val containerTree = ValDef(containerSymbol, Literal(initValue(tpe)))
369374

0 commit comments

Comments
 (0)