[FIR] Add new equalityOperatorCall node in control flow graph

This commit is contained in:
Ivan Kylchik
2020-07-15 21:43:42 +03:00
parent d23e9940ec
commit def47bdd9d
7 changed files with 43 additions and 40 deletions
@@ -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) {
@@ -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)}"
@@ -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 {
@@ -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())
@@ -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)
}
@@ -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?) {