[FIR] Add VariableStorage and flow on nodes into CFG reference
This commit is contained in:
+11
-2
@@ -7,11 +7,15 @@ package org.jetbrains.kotlin.fir.resolve.dfa
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.CFGNode
|
||||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph
|
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||||
|
|
||||||
class FirControlFlowGraphReferenceImpl(val controlFlowGraph: ControlFlowGraph) : FirControlFlowGraphReference() {
|
class FirControlFlowGraphReferenceImpl(
|
||||||
|
val controlFlowGraph: ControlFlowGraph,
|
||||||
|
val dataFlowInfo: DataFlowInfo? = null
|
||||||
|
) : FirControlFlowGraphReference() {
|
||||||
override val source: FirSourceElement? get() = null
|
override val source: FirSourceElement? get() = null
|
||||||
|
|
||||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
|
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
|
||||||
@@ -21,5 +25,10 @@ class FirControlFlowGraphReferenceImpl(val controlFlowGraph: ControlFlowGraph) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DataFlowInfo(val variableStorage: VariableStorage, val flowOnNodes: Map<CFGNode<*>, Flow>)
|
||||||
|
|
||||||
val FirControlFlowGraphReference.controlFlowGraph: ControlFlowGraph?
|
val FirControlFlowGraphReference.controlFlowGraph: ControlFlowGraph?
|
||||||
get() = (this as? FirControlFlowGraphReferenceImpl)?.controlFlowGraph
|
get() = (this as? FirControlFlowGraphReferenceImpl)?.controlFlowGraph
|
||||||
|
|
||||||
|
val FirControlFlowGraphReference.dataFlowInfo: DataFlowInfo?
|
||||||
|
get() = (this as? FirControlFlowGraphReferenceImpl)?.dataFlowInfo
|
||||||
+19
-11
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.contracts.description.ConeConstantReference
|
|||||||
import org.jetbrains.kotlin.fir.contracts.description.ConeReturnsEffectDeclaration
|
import org.jetbrains.kotlin.fir.contracts.description.ConeReturnsEffectDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.PersistentImplicitReceiverStack
|
import org.jetbrains.kotlin.fir.resolve.PersistentImplicitReceiverStack
|
||||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||||
@@ -33,15 +34,21 @@ import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
|||||||
|
|
||||||
class DataFlowAnalyzerContext<FLOW : Flow>(
|
class DataFlowAnalyzerContext<FLOW : Flow>(
|
||||||
val graphBuilder: ControlFlowGraphBuilder,
|
val graphBuilder: ControlFlowGraphBuilder,
|
||||||
val variableStorage: VariableStorage,
|
variableStorage: VariableStorage,
|
||||||
val flowOnNodes: MutableMap<CFGNode<*>, FLOW>,
|
flowOnNodes: MutableMap<CFGNode<*>, FLOW>,
|
||||||
val variablesForWhenConditions: MutableMap<WhenBranchConditionExitNode, DataFlowVariable>
|
val variablesForWhenConditions: MutableMap<WhenBranchConditionExitNode, DataFlowVariable>
|
||||||
) {
|
) {
|
||||||
|
var flowOnNodes = flowOnNodes
|
||||||
|
private set
|
||||||
|
var variableStorage = variableStorage
|
||||||
|
private set
|
||||||
|
|
||||||
fun reset() {
|
fun reset() {
|
||||||
graphBuilder.reset()
|
graphBuilder.reset()
|
||||||
variableStorage.reset()
|
|
||||||
flowOnNodes.clear()
|
|
||||||
variablesForWhenConditions.clear()
|
variablesForWhenConditions.clear()
|
||||||
|
|
||||||
|
variableStorage = variableStorage.clear()
|
||||||
|
flowOnNodes = mutableMapOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -160,7 +167,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
functionEnterNode.mergeIncomingFlow(shouldForkFlow = previousNode != null)
|
functionEnterNode.mergeIncomingFlow(shouldForkFlow = previousNode != null)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitFunction(function: FirFunction<*>): ControlFlowGraph {
|
fun exitFunction(function: FirFunction<*>): FirControlFlowGraphReference {
|
||||||
if (function is FirAnonymousFunction) {
|
if (function is FirAnonymousFunction) {
|
||||||
return exitAnonymousFunction(function)
|
return exitAnonymousFunction(function)
|
||||||
}
|
}
|
||||||
@@ -171,12 +178,13 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
variableStorage.removeRealVariable(valueParameter.symbol)
|
variableStorage.removeRealVariable(valueParameter.symbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val variableStorage = variableStorage
|
||||||
|
val flowOnNodes = context.flowOnNodes
|
||||||
|
|
||||||
if (graphBuilder.isTopLevel()) {
|
if (graphBuilder.isTopLevel()) {
|
||||||
context.flowOnNodes.clear()
|
context.reset()
|
||||||
variableStorage.reset()
|
|
||||||
graphBuilder.reset()
|
|
||||||
}
|
}
|
||||||
return graph
|
return FirControlFlowGraphReferenceImpl(graph, DataFlowInfo(variableStorage, flowOnNodes))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------- Anonymous function -----------------------------------
|
// ----------------------------------- Anonymous function -----------------------------------
|
||||||
@@ -188,12 +196,12 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
functionEnterNode.mergeIncomingFlow()
|
functionEnterNode.mergeIncomingFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun exitAnonymousFunction(anonymousFunction: FirAnonymousFunction): ControlFlowGraph {
|
private fun exitAnonymousFunction(anonymousFunction: FirAnonymousFunction): FirControlFlowGraphReference {
|
||||||
val (functionExitNode, postponedLambdaExitNode, graph) = graphBuilder.exitAnonymousFunction(anonymousFunction)
|
val (functionExitNode, postponedLambdaExitNode, graph) = graphBuilder.exitAnonymousFunction(anonymousFunction)
|
||||||
// TODO: questionable
|
// TODO: questionable
|
||||||
postponedLambdaExitNode?.mergeIncomingFlow()
|
postponedLambdaExitNode?.mergeIncomingFlow()
|
||||||
functionExitNode.mergeIncomingFlow()
|
functionExitNode.mergeIncomingFlow()
|
||||||
return graph
|
return FirControlFlowGraphReferenceImpl(graph)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun visitPostponedAnonymousFunction(anonymousFunction: FirAnonymousFunction) {
|
fun visitPostponedAnonymousFunction(anonymousFunction: FirAnonymousFunction) {
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ class VariableStorage(private val session: FirSession) {
|
|||||||
private val realVariables: MutableMap<Identifier, RealVariable> = HashMap()
|
private val realVariables: MutableMap<Identifier, RealVariable> = HashMap()
|
||||||
private val syntheticVariables: MutableMap<FirElement, SyntheticVariable> = HashMap()
|
private val syntheticVariables: MutableMap<FirElement, SyntheticVariable> = HashMap()
|
||||||
|
|
||||||
|
fun clear(): VariableStorage = VariableStorage(session)
|
||||||
|
|
||||||
fun getOrCreateRealVariableWithoutUnwrappingAlias(flow: Flow, symbol: AbstractFirBasedSymbol<*>, fir: FirElement): RealVariable {
|
fun getOrCreateRealVariableWithoutUnwrappingAlias(flow: Flow, symbol: AbstractFirBasedSymbol<*>, fir: FirElement): RealVariable {
|
||||||
val realFir = fir.unwrapElement()
|
val realFir = fir.unwrapElement()
|
||||||
val identifier = getIdentifierBySymbol(flow, symbol, realFir)
|
val identifier = getIdentifierBySymbol(flow, symbol, realFir)
|
||||||
@@ -139,12 +141,6 @@ class VariableStorage(private val session: FirSession) {
|
|||||||
syntheticVariables.remove(variable.fir)
|
syntheticVariables.remove(variable.fir)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reset() {
|
|
||||||
counter = 0
|
|
||||||
realVariables.clear()
|
|
||||||
syntheticVariables.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalContracts::class)
|
@OptIn(ExperimentalContracts::class)
|
||||||
fun AbstractFirBasedSymbol<*>?.isStable(originalFir: FirElement): Boolean {
|
fun AbstractFirBasedSymbol<*>?.isStable(originalFir: FirElement): Boolean {
|
||||||
contract {
|
contract {
|
||||||
|
|||||||
+4
-4
@@ -521,8 +521,8 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
transformDeclarationContent(function, data).also {
|
transformDeclarationContent(function, data).also {
|
||||||
if (functionIsNotAnalyzed) {
|
if (functionIsNotAnalyzed) {
|
||||||
val result = it.single as FirFunction<*>
|
val result = it.single as FirFunction<*>
|
||||||
val controlFlowGraph = dataFlowAnalyzer.exitFunction(result)
|
val controlFlowGraphReference = dataFlowAnalyzer.exitFunction(result)
|
||||||
result.replaceControlFlowGraphReference(FirControlFlowGraphReferenceImpl(controlFlowGraph))
|
result.replaceControlFlowGraphReference(controlFlowGraphReference)
|
||||||
}
|
}
|
||||||
} as CompositeTransformResult<FirStatement>
|
} as CompositeTransformResult<FirStatement>
|
||||||
}
|
}
|
||||||
@@ -593,8 +593,8 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val graph = dataFlowAnalyzer.exitFunction(constructor)
|
val controlFlowGraphReference = dataFlowAnalyzer.exitFunction(constructor)
|
||||||
constructor.replaceControlFlowGraphReference(FirControlFlowGraphReferenceImpl(graph))
|
constructor.replaceControlFlowGraphReference(controlFlowGraphReference)
|
||||||
constructor.compose()
|
constructor.compose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user