[FIR] Add new equalityOperatorCall node in control flow graph
This commit is contained in:
+24
-21
@@ -344,30 +344,29 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
graphBuilder.exitComparisonExpression(comparisonExpression).mergeIncomingFlow()
|
graphBuilder.exitComparisonExpression(comparisonExpression).mergeIncomingFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitOperatorCall(operatorCall: FirOperatorCall) {
|
fun exitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall) {
|
||||||
val node = graphBuilder.exitOperatorCall(operatorCall).mergeIncomingFlow()
|
val node = graphBuilder.exitEqualityOperatorCall(equalityOperatorCall).mergeIncomingFlow()
|
||||||
when (val operation = operatorCall.operation) {
|
val operation = equalityOperatorCall.operation
|
||||||
FirOperation.EQ, FirOperation.NOT_EQ, FirOperation.IDENTITY, FirOperation.NOT_IDENTITY -> {
|
val leftOperand = equalityOperatorCall.arguments[0]
|
||||||
val leftOperand = operatorCall.arguments[0]
|
val rightOperand = equalityOperatorCall.arguments[1]
|
||||||
val rightOperand = operatorCall.arguments[1]
|
|
||||||
|
|
||||||
val leftConst = leftOperand as? FirConstExpression<*>
|
val leftConst = leftOperand as? FirConstExpression<*>
|
||||||
val rightConst = rightOperand as? FirConstExpression<*>
|
val rightConst = rightOperand as? FirConstExpression<*>
|
||||||
|
|
||||||
when {
|
when {
|
||||||
leftConst != null && rightConst != null -> return
|
leftConst != null && rightConst != null -> return
|
||||||
leftConst?.kind == FirConstKind.Null -> processEqNull(node, rightOperand, operation)
|
leftConst?.kind == FirConstKind.Null -> processEqNull(node, rightOperand, operation)
|
||||||
rightConst?.kind == FirConstKind.Null -> processEqNull(node, leftOperand, operation)
|
rightConst?.kind == FirConstKind.Null -> processEqNull(node, leftOperand, operation)
|
||||||
leftConst != null -> processEqWithConst(node, rightOperand, leftConst, operation)
|
leftConst != null -> processEqWithConst(node, rightOperand, leftConst, operation)
|
||||||
rightConst != null -> processEqWithConst(node, leftOperand, rightConst, operation)
|
rightConst != null -> processEqWithConst(node, leftOperand, rightConst, operation)
|
||||||
else -> processEq(node, leftOperand, rightOperand, operation)
|
else -> processEq(node, leftOperand, rightOperand, operation)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// const != null
|
// const != null
|
||||||
private fun processEqWithConst(node: OperatorCallNode, operand: FirExpression, const: FirConstExpression<*>, operation: FirOperation) {
|
private fun processEqWithConst(
|
||||||
|
node: EqualityOperatorCallNode, operand: FirExpression, const: FirConstExpression<*>, operation: FirOperation
|
||||||
|
) {
|
||||||
val isEq = operation.isEq()
|
val isEq = operation.isEq()
|
||||||
val expressionVariable = variableStorage.createSyntheticVariable(node.fir)
|
val expressionVariable = variableStorage.createSyntheticVariable(node.fir)
|
||||||
val flow = node.flow
|
val flow = node.flow
|
||||||
@@ -402,7 +401,9 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processEq(node: OperatorCallNode, leftOperand: FirExpression, rightOperand: FirExpression, operation: FirOperation) {
|
private fun processEq(
|
||||||
|
node: EqualityOperatorCallNode, leftOperand: FirExpression, rightOperand: FirExpression, operation: FirOperation
|
||||||
|
) {
|
||||||
val leftIsNullable = leftOperand.coneType.isMarkedNullable
|
val leftIsNullable = leftOperand.coneType.isMarkedNullable
|
||||||
val rightIsNullable = rightOperand.coneType.isMarkedNullable
|
val rightIsNullable = rightOperand.coneType.isMarkedNullable
|
||||||
// left == right && right not null -> left != null
|
// left == right && right not null -> left != null
|
||||||
@@ -417,7 +418,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processEqNull(node: OperatorCallNode, operand: FirExpression, operation: FirOperation) {
|
private fun processEqNull(node: EqualityOperatorCallNode, operand: FirExpression, operation: FirOperation) {
|
||||||
val flow = node.flow
|
val flow = node.flow
|
||||||
val expressionVariable = variableStorage.createSyntheticVariable(node.fir)
|
val expressionVariable = variableStorage.createSyntheticVariable(node.fir)
|
||||||
val operandVariable = variableStorage.getOrCreateVariable(node.previousFlow, operand)
|
val operandVariable = variableStorage.getOrCreateVariable(node.previousFlow, operand)
|
||||||
@@ -448,7 +449,9 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
node.flow = flow
|
node.flow = flow
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processIdentity(node: OperatorCallNode, leftOperand: FirExpression, rightOperand: FirExpression, operation: FirOperation) {
|
private fun processIdentity(
|
||||||
|
node: EqualityOperatorCallNode, leftOperand: FirExpression, rightOperand: FirExpression, operation: FirOperation
|
||||||
|
) {
|
||||||
val flow = node.flow
|
val flow = node.flow
|
||||||
val expressionVariable = variableStorage.getOrCreateVariable(node.previousFlow, node.fir)
|
val expressionVariable = variableStorage.getOrCreateVariable(node.previousFlow, node.fir)
|
||||||
val leftOperandVariable = variableStorage.getOrCreateVariable(node.previousFlow, leftOperand)
|
val leftOperandVariable = variableStorage.getOrCreateVariable(node.previousFlow, leftOperand)
|
||||||
|
|||||||
@@ -456,18 +456,18 @@ class TypeOperatorCallNode(owner: ControlFlowGraph, override val fir: FirTypeOpe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OperatorCallNode(owner: ControlFlowGraph, override val fir: FirOperatorCall, level: Int, id: Int) : AbstractBinaryExitNode<FirOperatorCall>(owner, level, id) {
|
|
||||||
override fun <R, D> accept(visitor: ControlFlowGraphVisitor<R, D>, data: D): R {
|
|
||||||
return visitor.visitOperatorCallNode(this, data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ComparisonExpressionNode(owner: ControlFlowGraph, override val fir: FirComparisonExpression, level: Int, id: Int) : CFGNode<FirComparisonExpression>(owner, level, id) {
|
class ComparisonExpressionNode(owner: ControlFlowGraph, override val fir: FirComparisonExpression, level: Int, id: Int) : CFGNode<FirComparisonExpression>(owner, level, id) {
|
||||||
override fun <R, D> accept(visitor: ControlFlowGraphVisitor<R, D>, data: D): R {
|
override fun <R, D> accept(visitor: ControlFlowGraphVisitor<R, D>, data: D): R {
|
||||||
return visitor.visitComparisonExpressionNode(this, data)
|
return visitor.visitComparisonExpressionNode(this, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class EqualityOperatorCallNode(owner: ControlFlowGraph, override val fir: FirEqualityOperatorCall, level: Int, id: Int) : AbstractBinaryExitNode<FirEqualityOperatorCall>(owner, level, id) {
|
||||||
|
override fun <R, D> accept(visitor: ControlFlowGraphVisitor<R, D>, data: D): R {
|
||||||
|
return visitor.visitEqualityOperatorCallNode(this, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------- Jump -----------------------------------
|
// ----------------------------------- Jump -----------------------------------
|
||||||
|
|
||||||
class JumpNode(owner: ControlFlowGraph, override val fir: FirJump<*>, level: Int, id: Int) : CFGNode<FirJump<*>>(owner, level, id) {
|
class JumpNode(owner: ControlFlowGraph, override val fir: FirJump<*>, level: Int, id: Int) : CFGNode<FirJump<*>>(owner, level, id) {
|
||||||
|
|||||||
+1
-1
@@ -40,9 +40,9 @@ fun CFGNode<*>.render(): String =
|
|||||||
|
|
||||||
is QualifiedAccessNode -> "Access variable ${fir.calleeReference.render(CfgRenderMode)}"
|
is QualifiedAccessNode -> "Access variable ${fir.calleeReference.render(CfgRenderMode)}"
|
||||||
is ResolvedQualifierNode -> "Access qualifier ${fir.classId}"
|
is ResolvedQualifierNode -> "Access qualifier ${fir.classId}"
|
||||||
is OperatorCallNode -> "Operator ${fir.operation.operator}"
|
|
||||||
is ComparisonExpressionNode -> "Comparison ${fir.operation.operator}"
|
is ComparisonExpressionNode -> "Comparison ${fir.operation.operator}"
|
||||||
is TypeOperatorCallNode -> "Type operator: \"${fir.render(CfgRenderMode)}\""
|
is TypeOperatorCallNode -> "Type operator: \"${fir.render(CfgRenderMode)}\""
|
||||||
|
is EqualityOperatorCallNode -> "Equality operator ${fir.operation.operator}"
|
||||||
is JumpNode -> "Jump: ${fir.render()}"
|
is JumpNode -> "Jump: ${fir.render()}"
|
||||||
is StubNode -> "Stub"
|
is StubNode -> "Stub"
|
||||||
is CheckNotNullCallNode -> "Check not null: ${fir.render(CfgRenderMode)}"
|
is CheckNotNullCallNode -> "Check not null: ${fir.render(CfgRenderMode)}"
|
||||||
|
|||||||
+4
-4
@@ -495,14 +495,14 @@ class ControlFlowGraphBuilder {
|
|||||||
return createTypeOperatorCallNode(typeOperatorCall).also { addNewSimpleNode(it) }
|
return createTypeOperatorCallNode(typeOperatorCall).also { addNewSimpleNode(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitOperatorCall(operatorCall: FirOperatorCall): OperatorCallNode {
|
|
||||||
return createOperatorCallNode(operatorCall).also { addNewSimpleNode(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun exitComparisonExpression(comparisonExpression: FirComparisonExpression): ComparisonExpressionNode {
|
fun exitComparisonExpression(comparisonExpression: FirComparisonExpression): ComparisonExpressionNode {
|
||||||
return createComparisonExpressionNode(comparisonExpression).also { addNewSimpleNode(it) }
|
return createComparisonExpressionNode(comparisonExpression).also { addNewSimpleNode(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun exitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall): EqualityOperatorCallNode {
|
||||||
|
return createEqualityOperatorCallNode(equalityOperatorCall).also { addNewSimpleNode(it) }
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------- Jump -----------------------------------
|
// ----------------------------------- Jump -----------------------------------
|
||||||
|
|
||||||
fun exitJump(jump: FirJump<*>): JumpNode {
|
fun exitJump(jump: FirJump<*>): JumpNode {
|
||||||
|
|||||||
+2
-2
@@ -27,8 +27,8 @@ fun ControlFlowGraphBuilder.createInitBlockExitNode(fir: FirAnonymousInitializer
|
|||||||
fun ControlFlowGraphBuilder.createTypeOperatorCallNode(fir: FirTypeOperatorCall): TypeOperatorCallNode =
|
fun ControlFlowGraphBuilder.createTypeOperatorCallNode(fir: FirTypeOperatorCall): TypeOperatorCallNode =
|
||||||
TypeOperatorCallNode(currentGraph, fir, levelCounter, createId())
|
TypeOperatorCallNode(currentGraph, fir, levelCounter, createId())
|
||||||
|
|
||||||
fun ControlFlowGraphBuilder.createOperatorCallNode(fir: FirOperatorCall): OperatorCallNode =
|
fun ControlFlowGraphBuilder.createEqualityOperatorCallNode(fir: FirEqualityOperatorCall): EqualityOperatorCallNode =
|
||||||
OperatorCallNode(currentGraph, fir, levelCounter, createId())
|
EqualityOperatorCallNode(currentGraph, fir, levelCounter, createId())
|
||||||
|
|
||||||
fun ControlFlowGraphBuilder.createWhenBranchConditionExitNode(fir: FirWhenBranch): WhenBranchConditionExitNode =
|
fun ControlFlowGraphBuilder.createWhenBranchConditionExitNode(fir: FirWhenBranch): WhenBranchConditionExitNode =
|
||||||
WhenBranchConditionExitNode(currentGraph, fir, levelCounter, createId())
|
WhenBranchConditionExitNode(currentGraph, fir, levelCounter, createId())
|
||||||
|
|||||||
+2
-2
@@ -229,11 +229,11 @@ abstract class ControlFlowGraphVisitor<out R, in D> {
|
|||||||
return visitNode(node, data)
|
return visitNode(node, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun visitOperatorCallNode(node: OperatorCallNode, data: D): R {
|
open fun visitComparisonExpressionNode(node: ComparisonExpressionNode, data: D): R {
|
||||||
return visitNode(node, data)
|
return visitNode(node, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun visitComparisonExpressionNode(node: ComparisonExpressionNode, data: D): R {
|
open fun visitEqualityOperatorCallNode(node: EqualityOperatorCallNode, data: D): R {
|
||||||
return visitNode(node, data)
|
return visitNode(node, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -207,11 +207,11 @@ abstract class ControlFlowGraphVisitorVoid : ControlFlowGraphVisitor<Unit, Nothi
|
|||||||
visitNode(node)
|
visitNode(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun visitOperatorCallNode(node: OperatorCallNode) {
|
open fun visitComparisonExpressionNode(node: ComparisonExpressionNode) {
|
||||||
visitNode(node)
|
visitNode(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun visitComparisonExpressionNode(node: ComparisonExpressionNode) {
|
open fun visitEqualityOperatorCallNode(node: EqualityOperatorCallNode) {
|
||||||
visitNode(node)
|
visitNode(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,8 +496,8 @@ abstract class ControlFlowGraphVisitorVoid : ControlFlowGraphVisitor<Unit, Nothi
|
|||||||
visitTypeOperatorCallNode(node)
|
visitTypeOperatorCallNode(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
final override fun visitOperatorCallNode(node: OperatorCallNode, data: Nothing?) {
|
final override fun visitEqualityOperatorCallNode(node: EqualityOperatorCallNode, data: Nothing?) {
|
||||||
visitOperatorCallNode(node)
|
visitEqualityOperatorCallNode(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
final override fun visitComparisonExpressionNode(node: ComparisonExpressionNode, data: Nothing?) {
|
final override fun visitComparisonExpressionNode(node: ComparisonExpressionNode, data: Nothing?) {
|
||||||
|
|||||||
Reference in New Issue
Block a user