Skip to content

Commit bbad484

Browse files
committed
Allow phases to give restrictions on pipeline position.
Phases can now specify which phases should it follow. Tree transforms can additionally specify which TreeTransforms should have finished their processing of compilation units entirely.
1 parent c8feb0c commit bbad484

File tree

4 files changed

+40
-1
lines changed

4 files changed

+40
-1
lines changed

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

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,24 @@ object Phases {
7474
*/
7575
private def squashPhases(phasess: List[List[Phase]]): Array[Phase] = {
7676
val squashedPhases = ListBuffer[Phase]()
77+
var prevPhases: Set[String] = Set.empty
7778
var postTyperEmmited = false
7879
var i = 0
7980
while (i < phasess.length) {
8081
if (phasess(i).length > 1) {
81-
assert(phasess(i).forall(x => x.isInstanceOf[TreeTransform]), "Only tree transforms can be squashed")
82+
val phasesInBlock: Set[String] = phasess(i).map(_.name).toSet
83+
for(phase<-phasess(i)) {
84+
phase match {
85+
case p: TreeTransform =>
8286

87+
val unmetRequirements = p.runsAfterGroupsOf &~ prevPhases
88+
assert(unmetRequirements.isEmpty,
89+
s"${phase.name} requires ${unmetRequirements.mkString(", ")} to be in different TreeTransformer")
90+
91+
case _ =>
92+
assert(false, s"Only tree transforms can be squashed, ${phase.name} can not be squashed")
93+
}
94+
}
8395
val transforms = phasess(i).asInstanceOf[List[TreeTransform]]
8496
val block =
8597
if (!postTyperEmmited) {
@@ -93,6 +105,7 @@ object Phases {
93105
override def transformations: Array[TreeTransform] = transforms.toArray
94106
}
95107
squashedPhases += block
108+
prevPhases ++= phasess(i).map(_.name)
96109
block.init(this, phasess(i).head.id, phasess(i).last.id)
97110
} else squashedPhases += phasess(i).head
98111
i += 1
@@ -106,11 +119,16 @@ object Phases {
106119
*/
107120
def usePhases(phasess: List[List[Phase]], squash: Boolean = true) = {
108121
phases = (NoPhase :: phasess.flatten ::: new TerminalPhase :: Nil).toArray
122+
var phasesAfter:Set[String] = Set.empty
109123
nextDenotTransformerId = new Array[Int](phases.length)
110124
denotTransformers = new Array[DenotTransformer](phases.length)
111125
var i = 0
112126
while (i < phases.length) {
113127
phases(i).init(this, i)
128+
val unmetPreceedeRequirements = phases(i).runsAfter -- phasesAfter
129+
assert(unmetPreceedeRequirements.isEmpty,
130+
s"phase ${phases(i)} has unmet requirement: ${unmetPreceedeRequirements.mkString(", ")} should precede this phase")
131+
phasesAfter += phases(i).name
114132
i += 1
115133
}
116134
var lastTransformerId = i
@@ -170,6 +188,9 @@ object Phases {
170188

171189
def name: String
172190

191+
/** List of names of phases that should precede this phase */
192+
def runsAfter: Set[String] = Set.empty
193+
173194
def run(implicit ctx: Context): Unit
174195

175196
def runOn(units: List[CompilationUnit])(implicit ctx: Context): Unit =

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ class Erasure extends Phase with DenotTransformer {
2525

2626
override def name: String = "erasure"
2727

28+
/** List of names of phases that should precede this phase */
29+
override def runsAfter: Set[String] = Set("typeTestsCasts", "intercepted", "splitter")
30+
2831
def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref match {
2932
case ref: SymDenotation =>
3033
assert(ctx.phase == this, s"transforming $ref at ${ctx.phase}")

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ class LazyValTranformContext {
6363

6464
override def name: String = "LazyVals"
6565

66+
/** List of names of phases that should have finished their processing of all compilation units
67+
* before this phase starts */
68+
override def runsAfterGroupsOf: Set[String] = Set("lazyValsModules")
69+
/** List of names of phases that should have finished their processing of all compilation units
70+
* before this phase starts */
71+
override def runsAfter: Set[String] = Set("lazyValsModules")
72+
73+
/** List of names of phases that should have finished processing of tree
74+
* before this phase starts processing same tree */
75+
// override def ensureAfter: Set[String] = Set("mixin")
76+
6677
def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = {
6778
ref match {
6879
case ref: SymDenotation if ref.symbol.isClass =>

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ object TreeTransforms {
5151
/** id of this treeTransform in group */
5252
var idx: Int = _
5353

54+
/** List of names of phases that should have finished their processing of all compilation units
55+
* before this phase starts */
56+
def runsAfterGroupsOf: Set[String] = Set.empty
57+
5458
def prepareForIdent(tree: Ident)(implicit ctx: Context) = this
5559
def prepareForSelect(tree: Select)(implicit ctx: Context) = this
5660
def prepareForThis(tree: This)(implicit ctx: Context) = this

0 commit comments

Comments
 (0)