Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jetbrains.kotlin.backend.common.phaser.CompilerPhase.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.phaser
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import kotlin.system.measureTimeMillis
class PhaserState(
val alreadyDone: MutableSet = mutableSetOf(),
var depth: Int = 0,
var phaseCount: Int = 0,
val stickyPostconditions: MutableSet> = mutableSetOf()
)
// Copy state, forgetting the sticky postconditions (which will not be applicable to the new type)
fun PhaserState .changeType() = PhaserState(alreadyDone, depth, phaseCount, mutableSetOf())
fun PhaserState.downlevel(nlevels: Int = 1, block: () -> R): R {
depth += nlevels
val result = block()
depth -= nlevels
return result
}
interface CompilerPhase {
fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState , context: Context, input: Input): Output
fun getNamedSubphases(startDepth: Int = 0): List> = emptyList()
// In phase trees, `stickyPostconditions` is inherited along the right edge to be used in `then`.
val stickyPostconditions: Set> get() = emptySet()
}
fun CompilerPhase.invokeToplevel(
phaseConfig: PhaseConfig,
context: Context,
input: Input
): Output = invoke(phaseConfig, PhaserState(), context, input)
interface SameTypeCompilerPhase : CompilerPhase
// A failing checker should just throw an exception.
typealias Checker = (Data) -> Unit
interface NamedCompilerPhase : CompilerPhase {
val name: String
val description: String
val prerequisite: Set get() = emptySet()
val preconditions: Set>
val postconditions: Set>
val actionsBefore: Set>
val actionsAfter: Set>
}
typealias AnyNamedPhase = NamedCompilerPhase<*, *, *>
enum class BeforeOrAfter { BEFORE, AFTER }
data class ActionState(
val config: PhaseConfig,
val phase: AnyNamedPhase,
val phaseCount: Int,
val beforeOrAfter: BeforeOrAfter
)
typealias Action = (ActionState, Data, Context) -> Unit
infix operator fun Action.plus(other: Action): Action =
{ phaseState, data, context ->
this(phaseState, data, context)
other(phaseState, data, context)
}
abstract class AbstractNamedPhaseWrapper(
override val name: String,
override val description: String,
override val prerequisite: Set,
private val lower: CompilerPhase,
override val preconditions: Set> = emptySet(),
override val postconditions: Set> = emptySet(),
override val stickyPostconditions: Set> = emptySet(),
override val actionsBefore: Set> = emptySet(),
override val actionsAfter: Set> = emptySet(),
private val nlevels: Int = 0
) : NamedCompilerPhase {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState , context: Context, input: Input): Output {
if (this is SameTypeCompilerPhase<*, *> &&
this !in phaseConfig.enabled
) {
@Suppress("UNCHECKED_CAST")
return input as Output
}
assert(phaserState.alreadyDone.containsAll(prerequisite)) {
"Lowering $name: phases ${(prerequisite - phaserState.alreadyDone).map { it.name }} are required, but not satisfied"
}
context.inVerbosePhase = this in phaseConfig.verbose
runBefore(phaseConfig, phaserState, context, input)
val output = runBody(phaseConfig, phaserState, context, input)
runAfter(phaseConfig, phaserState, context, output)
phaserState.alreadyDone.add(this)
phaserState.phaseCount++
return output
}
private fun runBefore(phaseConfig: PhaseConfig, phaserState: PhaserState , context: Context, input: Input) {
val state = ActionState(phaseConfig, this, phaserState.phaseCount, BeforeOrAfter.BEFORE)
for (action in actionsBefore) action(state, input, context)
if (phaseConfig.checkConditions) {
for (pre in preconditions) pre(input)
}
}
private fun runBody(phaseConfig: PhaseConfig, phaserState: PhaserState , context: Context, input: Input): Output {
return if (phaseConfig.needProfiling) {
runAndProfile(phaseConfig, phaserState, context, input)
} else {
phaserState.downlevel(nlevels) {
lower.invoke(phaseConfig, phaserState, context, input)
}
}
}
private fun runAfter(phaseConfig: PhaseConfig, phaserState: PhaserState , context: Context, output: Output) {
val state = ActionState(phaseConfig, this, phaserState.phaseCount, BeforeOrAfter.AFTER)
for (action in actionsAfter) action(state, output, context)
if (phaseConfig.checkConditions) {
for (post in postconditions) post(output)
for (post in stickyPostconditions) post(output)
if (phaseConfig.checkStickyConditions && this is SameTypeCompilerPhase<*, *>) {
@Suppress("UNCHECKED_CAST") val phaserStateO = phaserState as PhaserState
for (post in phaserStateO.stickyPostconditions) post(output)
}
}
}
private fun runAndProfile(phaseConfig: PhaseConfig, phaserState: PhaserState , context: Context, source: Input): Output {
var result: Output? = null
val msec = measureTimeMillis {
result = phaserState.downlevel(nlevels) {
lower.invoke(phaseConfig, phaserState, context, source)
}
}
// TODO: use a proper logger
println("${"\t".repeat(phaserState.depth)}$description: $msec msec")
return result!!
}
private fun checkAndRun(set: Set, block: () -> Unit) {
if (this in set) block()
}
override fun getNamedSubphases(startDepth: Int): List>> =
listOf(startDepth to this) + lower.getNamedSubphases(startDepth + nlevels)
override fun toString() = "Compiler Phase @$name"
}
class SameTypeNamedPhaseWrapper(
name: String,
description: String,
prerequisite: Set,
lower: CompilerPhase,
preconditions: Set> = emptySet(),
postconditions: Set> = emptySet(),
stickyPostconditions: Set> = lower.stickyPostconditions,
actions: Set> = emptySet(),
nlevels: Int = 0
) : AbstractNamedPhaseWrapper(
name, description, prerequisite, lower, preconditions, postconditions, stickyPostconditions, actions, actions, nlevels
), SameTypeCompilerPhase