[FIR] Add different states for CFG and some assertions for graph modification

This commit is contained in:
Dmitriy Novozhilov
2020-06-04 15:27:23 +03:00
parent 1261f62afb
commit 5b64c0cfe2
3 changed files with 27 additions and 6 deletions
@@ -3,6 +3,8 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@file:Suppress("Reformat")
package org.jetbrains.kotlin.fir.resolve.dfa.cfg package org.jetbrains.kotlin.fir.resolve.dfa.cfg
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
@@ -3,8 +3,6 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@file:Suppress("Reformat")
package org.jetbrains.kotlin.fir.resolve.dfa.cfg package org.jetbrains.kotlin.fir.resolve.dfa.cfg
import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirDeclaration
@@ -15,20 +13,29 @@ class ControlFlowGraph(val declaration: FirDeclaration?, val name: String, val k
val nodes: List<CFGNode<*>> get() = _nodes val nodes: List<CFGNode<*>> get() = _nodes
internal fun addNode(node: CFGNode<*>) { internal fun addNode(node: CFGNode<*>) {
assertState(State.Building)
_nodes += node _nodes += node
} }
lateinit var enterNode: CFGNode<*> lateinit var enterNode: CFGNode<*>
internal set internal set
lateinit var exitNode: CFGNode<*> lateinit var exitNode: CFGNode<*>
internal set internal set
var owner: ControlFlowGraph? = null var owner: ControlFlowGraph? = null
private set private set
var state: State = State.Building
private set
private val _subGraphs: MutableList<ControlFlowGraph> = mutableListOf() private val _subGraphs: MutableList<ControlFlowGraph> = mutableListOf()
val subGraphs: List<ControlFlowGraph> get() = _subGraphs val subGraphs: List<ControlFlowGraph> get() = _subGraphs
internal fun complete() {
assertState(State.Building)
state = State.Completed
}
internal fun addSubGraph(graph: ControlFlowGraph) { internal fun addSubGraph(graph: ControlFlowGraph) {
assert(graph.owner == null) { assert(graph.owner == null) {
"SubGraph already has owner" "SubGraph already has owner"
@@ -46,6 +53,17 @@ class ControlFlowGraph(val declaration: FirDeclaration?, val name: String, val k
CFGNode.removeAllOutgoingEdges(graph.exitNode) CFGNode.removeAllOutgoingEdges(graph.exitNode)
} }
private fun assertState(state: State) {
assert(this.state == state) {
"This action can not be performed at $this state"
}
}
enum class State {
Building,
Completed;
}
enum class Kind { enum class Kind {
Function, ClassInitializer, TopLevel Function, ClassInitializer, TopLevel
} }
@@ -173,6 +173,7 @@ class ControlFlowGraphBuilder {
exitNode.updateDeadStatus() exitNode.updateDeadStatus()
val graph = graphs.pop().also { graph -> val graph = graphs.pop().also { graph ->
exitsFromCompletedPostponedAnonymousFunctions.removeAll { it.owner == graph } exitsFromCompletedPostponedAnonymousFunctions.removeAll { it.owner == graph }
graph.complete()
} }
val previousGraph = parentGraphForAnonymousFunctions.remove(function.symbol) ?: graphs.top() val previousGraph = parentGraphForAnonymousFunctions.remove(function.symbol) ?: graphs.top()
if (previousGraph.kind == ControlFlowGraph.Kind.Function) { if (previousGraph.kind == ControlFlowGraph.Kind.Function) {
@@ -252,7 +253,7 @@ class ControlFlowGraphBuilder {
} }
val exitNode = createClassExitNode(klass) val exitNode = createClassExitNode(klass)
addEdge(node, exitNode, preferredKind = EdgeKind.Cfg) addEdge(node, exitNode, preferredKind = EdgeKind.Cfg)
return graphs.pop() return graphs.pop().also { it.complete() }
} }
fun prepareForLocalClassMembers(members: Collection<FirSymbolOwner<*>>) { fun prepareForLocalClassMembers(members: Collection<FirSymbolOwner<*>>) {
@@ -361,7 +362,7 @@ class ControlFlowGraphBuilder {
levelCounter-- levelCounter--
exitNodes.pop() exitNodes.pop()
lexicalScopes.pop() lexicalScopes.pop()
return topLevelVariableExitNode to graphs.pop() return topLevelVariableExitNode to graphs.pop().also { it.complete() }
} }
// ----------------------------------- Delegate ----------------------------------- // ----------------------------------- Delegate -----------------------------------
@@ -854,7 +855,7 @@ class ControlFlowGraphBuilder {
} }
lexicalScopes.pop() lexicalScopes.pop()
exitNodes.pop() exitNodes.pop()
val graph = graphs.pop() val graph = graphs.pop().also { it.complete() }
return exitNode to graph return exitNode to graph
} }