[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()
|
||||
}
|
||||
|
||||
fun exitOperatorCall(operatorCall: FirOperatorCall) {
|
||||
val node = graphBuilder.exitOperatorCall(operatorCall).mergeIncomingFlow()
|
||||
when (val operation = operatorCall.operation) {
|
||||
FirOperation.EQ, FirOperation.NOT_EQ, FirOperation.IDENTITY, FirOperation.NOT_IDENTITY -> {
|
||||
val leftOperand = operatorCall.arguments[0]
|
||||
val rightOperand = operatorCall.arguments[1]
|
||||
fun exitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall) {
|
||||
val node = graphBuilder.exitEqualityOperatorCall(equalityOperatorCall).mergeIncomingFlow()
|
||||
val operation = equalityOperatorCall.operation
|
||||
val leftOperand = equalityOperatorCall.arguments[0]
|
||||
val rightOperand = equalityOperatorCall.arguments[1]
|
||||
|
||||
val leftConst = leftOperand as? FirConstExpression<*>
|
||||
val rightConst = rightOperand as? FirConstExpression<*>
|
||||
val leftConst = leftOperand as? FirConstExpression<*>
|
||||
val rightConst = rightOperand as? FirConstExpression<*>
|
||||
|
||||
when {
|
||||
leftConst != null && rightConst != null -> return
|
||||
leftConst?.kind == FirConstKind.Null -> processEqNull(node, rightOperand, operation)
|
||||
rightConst?.kind == FirConstKind.Null -> processEqNull(node, leftOperand, operation)
|
||||
leftConst != null -> processEqWithConst(node, rightOperand, leftConst, operation)
|
||||
rightConst != null -> processEqWithConst(node, leftOperand, rightConst, operation)
|
||||
else -> processEq(node, leftOperand, rightOperand, operation)
|
||||
}
|
||||
}
|
||||
when {
|
||||
leftConst != null && rightConst != null -> return
|
||||
leftConst?.kind == FirConstKind.Null -> processEqNull(node, rightOperand, operation)
|
||||
rightConst?.kind == FirConstKind.Null -> processEqNull(node, leftOperand, operation)
|
||||
leftConst != null -> processEqWithConst(node, rightOperand, leftConst, operation)
|
||||
rightConst != null -> processEqWithConst(node, leftOperand, rightConst, operation)
|
||||
else -> processEq(node, leftOperand, rightOperand, operation)
|
||||
}
|
||||
}
|
||||
|
||||
// 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 expressionVariable = variableStorage.createSyntheticVariable(node.fir)
|
||||
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 rightIsNullable = rightOperand.coneType.isMarkedNullable
|
||||
// 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 expressionVariable = variableStorage.createSyntheticVariable(node.fir)
|
||||
val operandVariable = variableStorage.getOrCreateVariable(node.previousFlow, operand)
|
||||
@@ -448,7 +449,9 @@ abstract class FirDataFlowAnalyzer<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 expressionVariable = variableStorage.getOrCreateVariable(node.previousFlow, node.fir)
|
||||
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) {
|
||||
override fun <R, D> accept(visitor: ControlFlowGraphVisitor<R, D>, data: D): R {
|
||||
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 -----------------------------------
|
||||
|
||||
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 ResolvedQualifierNode -> "Access qualifier ${fir.classId}"
|
||||
is OperatorCallNode -> "Operator ${fir.operation.operator}"
|
||||
is ComparisonExpressionNode -> "Comparison ${fir.operation.operator}"
|
||||
is TypeOperatorCallNode -> "Type operator: \"${fir.render(CfgRenderMode)}\""
|
||||
is EqualityOperatorCallNode -> "Equality operator ${fir.operation.operator}"
|
||||
is JumpNode -> "Jump: ${fir.render()}"
|
||||
is StubNode -> "Stub"
|
||||
is CheckNotNullCallNode -> "Check not null: ${fir.render(CfgRenderMode)}"
|
||||
|
||||
+4
-4
@@ -495,14 +495,14 @@ class ControlFlowGraphBuilder {
|
||||
return createTypeOperatorCallNode(typeOperatorCall).also { addNewSimpleNode(it) }
|
||||
}
|
||||
|
||||
fun exitOperatorCall(operatorCall: FirOperatorCall): OperatorCallNode {
|
||||
return createOperatorCallNode(operatorCall).also { addNewSimpleNode(it) }
|
||||
}
|
||||
|
||||
fun exitComparisonExpression(comparisonExpression: FirComparisonExpression): ComparisonExpressionNode {
|
||||
return createComparisonExpressionNode(comparisonExpression).also { addNewSimpleNode(it) }
|
||||
}
|
||||
|
||||
fun exitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall): EqualityOperatorCallNode {
|
||||
return createEqualityOperatorCallNode(equalityOperatorCall).also { addNewSimpleNode(it) }
|
||||
}
|
||||
|
||||
// ----------------------------------- Jump -----------------------------------
|
||||
|
||||
fun exitJump(jump: FirJump<*>): JumpNode {
|
||||
|
||||
+2
-2
@@ -27,8 +27,8 @@ fun ControlFlowGraphBuilder.createInitBlockExitNode(fir: FirAnonymousInitializer
|
||||
fun ControlFlowGraphBuilder.createTypeOperatorCallNode(fir: FirTypeOperatorCall): TypeOperatorCallNode =
|
||||
TypeOperatorCallNode(currentGraph, fir, levelCounter, createId())
|
||||
|
||||
fun ControlFlowGraphBuilder.createOperatorCallNode(fir: FirOperatorCall): OperatorCallNode =
|
||||
OperatorCallNode(currentGraph, fir, levelCounter, createId())
|
||||
fun ControlFlowGraphBuilder.createEqualityOperatorCallNode(fir: FirEqualityOperatorCall): EqualityOperatorCallNode =
|
||||
EqualityOperatorCallNode(currentGraph, fir, levelCounter, createId())
|
||||
|
||||
fun ControlFlowGraphBuilder.createWhenBranchConditionExitNode(fir: FirWhenBranch): WhenBranchConditionExitNode =
|
||||
WhenBranchConditionExitNode(currentGraph, fir, levelCounter, createId())
|
||||
|
||||
+2
-2
@@ -229,11 +229,11 @@ abstract class ControlFlowGraphVisitor<out R, in D> {
|
||||
return visitNode(node, data)
|
||||
}
|
||||
|
||||
open fun visitOperatorCallNode(node: OperatorCallNode, data: D): R {
|
||||
open fun visitComparisonExpressionNode(node: ComparisonExpressionNode, data: D): R {
|
||||
return visitNode(node, data)
|
||||
}
|
||||
|
||||
open fun visitComparisonExpressionNode(node: ComparisonExpressionNode, data: D): R {
|
||||
open fun visitEqualityOperatorCallNode(node: EqualityOperatorCallNode, data: D): R {
|
||||
return visitNode(node, data)
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -207,11 +207,11 @@ abstract class ControlFlowGraphVisitorVoid : ControlFlowGraphVisitor<Unit, Nothi
|
||||
visitNode(node)
|
||||
}
|
||||
|
||||
open fun visitOperatorCallNode(node: OperatorCallNode) {
|
||||
open fun visitComparisonExpressionNode(node: ComparisonExpressionNode) {
|
||||
visitNode(node)
|
||||
}
|
||||
|
||||
open fun visitComparisonExpressionNode(node: ComparisonExpressionNode) {
|
||||
open fun visitEqualityOperatorCallNode(node: EqualityOperatorCallNode) {
|
||||
visitNode(node)
|
||||
}
|
||||
|
||||
@@ -496,8 +496,8 @@ abstract class ControlFlowGraphVisitorVoid : ControlFlowGraphVisitor<Unit, Nothi
|
||||
visitTypeOperatorCallNode(node)
|
||||
}
|
||||
|
||||
final override fun visitOperatorCallNode(node: OperatorCallNode, data: Nothing?) {
|
||||
visitOperatorCallNode(node)
|
||||
final override fun visitEqualityOperatorCallNode(node: EqualityOperatorCallNode, data: Nothing?) {
|
||||
visitEqualityOperatorCallNode(node)
|
||||
}
|
||||
|
||||
final override fun visitComparisonExpressionNode(node: ComparisonExpressionNode, data: Nothing?) {
|
||||
|
||||
Reference in New Issue
Block a user