diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/complex.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/complex.dot index 09b24ca4075..782bfdcb4b3 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/complex.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/complex.dot @@ -260,7 +260,7 @@ digraph complex_kt { 79 -> {68} [style=dotted]; 80 -> {68}; 81 -> {82}; - 82 -> {58}; + 82 -> {58} [color=green style=dashed]; 83 -> {84}; 84 -> {52}; 84 -> {85} [style=dotted]; diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/jumps.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/jumps.dot index d81bad9c3ef..dfdd5232c2d 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/jumps.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/jumps.dot @@ -191,7 +191,7 @@ digraph jumps_kt { 63 -> {64} [style=dotted]; 64 -> {65} [style=dotted]; 65 -> {66} [style=dotted]; - 66 -> {56} [style=dotted]; + 66 -> {56} [color=green style=dotted]; 67 -> {68}; 68 -> {53}; @@ -241,7 +241,8 @@ digraph jumps_kt { 80 -> {81} [style=dotted]; 81 -> {82} [style=dotted]; 82 -> {83} [style=dotted]; - 83 -> {73 72} [style=dotted]; + 83 -> {72} [style=dotted]; + 83 -> {73} [color=green style=dotted]; 84 -> {85}; 85 -> {70}; @@ -307,14 +308,14 @@ digraph jumps_kt { 99 -> {100 106}; 100 -> {101}; 101 -> {102}; - 102 -> {88}; 102 -> {103} [style=dotted]; + 102 -> {88} [color=green style=dashed]; 103 -> {104} [style=dotted]; 104 -> {105} [style=dotted]; 105 -> {96} [style=dotted]; 106 -> {96}; 107 -> {108}; - 108 -> {90}; + 108 -> {90} [color=green style=dashed]; subgraph cluster_30 { color=red @@ -346,8 +347,8 @@ digraph jumps_kt { 115 -> {116}; 116 -> {113}; 117 -> {118 119}; - 118 -> {117}; 118 -> {115} [color=green]; + 118 -> {117} [color=green style=dashed]; 119 -> {118}; 119 -> {120} [style=dotted]; 120 -> {118} [style=dotted]; diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/lambdas.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/lambdas.dot index 3a454bd7457..3c4b2c8bcca 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/lambdas.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/lambdas.dot @@ -64,8 +64,8 @@ digraph lambdas_kt { 17 -> {6}; 18 -> {6}; 19 -> {20 21}; - 20 -> {19}; 20 -> {14} [color=green]; + 20 -> {19} [color=green style=dashed]; 21 -> {22}; 22 -> {20}; @@ -166,8 +166,8 @@ digraph lambdas_kt { 52 -> {53} [style=dotted]; 53 -> {48} [style=dotted]; 54 -> {55 56}; - 55 -> {54}; 55 -> {50} [color=green]; + 55 -> {54} [color=green style=dashed]; 56 -> {57}; 57 -> {48}; 57 -> {58} [style=dotted]; @@ -203,8 +203,8 @@ digraph lambdas_kt { 64 -> {65} [style=dotted]; 65 -> {60} [style=dotted]; 66 -> {67 68}; - 67 -> {66}; 67 -> {62} [color=green]; + 67 -> {66} [color=green style=dashed]; 68 -> {69}; 69 -> {60}; 69 -> {70} [style=dotted]; diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/localClassesWithImplicit.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/localClassesWithImplicit.dot index 21ee7fbf08f..2a180cb1101 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/localClassesWithImplicit.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/localClassesWithImplicit.dot @@ -184,8 +184,8 @@ digraph localClassesWithImplicit_kt { 31 -> {32} [style=dotted]; 32 -> {27} [style=dotted]; 33 -> {34 35}; - 34 -> {33}; 34 -> {29} [color=green]; + 34 -> {33} [color=green style=dashed]; 35 -> {36}; 36 -> {37}; 37 -> {39}; @@ -217,8 +217,8 @@ digraph localClassesWithImplicit_kt { 62 -> {63} [style=dotted]; 63 -> {58} [style=dotted]; 64 -> {65 66}; - 65 -> {64}; 65 -> {60} [color=green]; + 65 -> {64} [color=green style=dashed]; 66 -> {67}; 67 -> {68}; 68 -> {69}; @@ -320,8 +320,8 @@ digraph localClassesWithImplicit_kt { 86 -> {87} [style=dotted]; 87 -> {82} [style=dotted]; 88 -> {89 90}; - 89 -> {88}; 89 -> {84} [color=green]; + 89 -> {88} [color=green style=dashed]; 90 -> {91}; 91 -> {92}; 92 -> {94}; @@ -379,8 +379,8 @@ digraph localClassesWithImplicit_kt { 117 -> {118} [style=dotted]; 118 -> {113} [style=dotted]; 119 -> {120 121}; - 120 -> {119}; 120 -> {115} [color=green]; + 120 -> {119} [color=green style=dashed]; 121 -> {122}; 122 -> {123}; 123 -> {124}; diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/loops.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/loops.dot index 0ccf8b14c58..ecdbe51176b 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/loops.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/loops.dot @@ -46,7 +46,7 @@ digraph loops_kt { 10 -> {11}; 11 -> {12}; 12 -> {13}; - 13 -> {4}; + 13 -> {4} [color=green style=dashed]; 14 -> {15}; 15 -> {1}; @@ -93,7 +93,8 @@ digraph loops_kt { 26 -> {27}; 27 -> {28}; 28 -> {29}; - 29 -> {20 19}; + 29 -> {19}; + 29 -> {20} [color=green style=dashed]; 30 -> {31}; 31 -> {17}; @@ -158,7 +159,7 @@ digraph loops_kt { 51 -> {52}; 52 -> {53}; 53 -> {54}; - 54 -> {41}; + 54 -> {41} [color=green style=dashed]; 55 -> {56}; 56 -> {33}; @@ -201,7 +202,7 @@ digraph loops_kt { 65 -> {66}; 66 -> {67}; 67 -> {68}; - 68 -> {61}; + 68 -> {61} [color=green style=dashed]; 69 -> {58} [style=dotted]; subgraph cluster_20 { @@ -275,7 +276,7 @@ digraph loops_kt { 89 -> {80} [style=dotted]; 90 -> {80}; 91 -> {92}; - 92 -> {74}; + 92 -> {74} [color=green style=dashed]; 93 -> {71}; subgraph cluster_28 { @@ -317,7 +318,7 @@ digraph loops_kt { 102 -> {103} [style=dotted]; 103 -> {104} [style=dotted]; 104 -> {105} [style=dotted]; - 105 -> {98} [style=dotted]; + 105 -> {98} [color=green style=dotted]; 106 -> {95}; subgraph cluster_33 { @@ -358,8 +359,8 @@ digraph loops_kt { 115 -> {116}; 116 -> {117}; 117 -> {118}; - 118 -> {111}; 118 -> {110} [style=dotted]; + 118 -> {111} [color=green style=dashed]; 119 -> {108} [style=dotted]; subgraph cluster_38 { @@ -432,8 +433,8 @@ digraph loops_kt { 139 -> {140}; 140 -> {141}; 141 -> {142}; - 142 -> {124}; 142 -> {123} [style=dotted]; + 142 -> {124} [color=green style=dashed]; 143 -> {121}; subgraph cluster_46 { @@ -475,7 +476,7 @@ digraph loops_kt { 153 -> {154}; 154 -> {155}; 155 -> {147}; - 155 -> {148} [style=dotted]; + 155 -> {148} [color=green style=dotted]; 156 -> {145}; } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/postponedLambdas.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/postponedLambdas.dot index dd4595892dd..29073b231c3 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/postponedLambdas.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/postponedLambdas.dot @@ -34,8 +34,8 @@ digraph postponedLambdas_kt { 7 -> {8}; 8 -> {3}; 9 -> {10 11}; - 10 -> {9}; 10 -> {6} [color=green]; + 10 -> {9} [color=green style=dashed]; 11 -> {10}; } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/propertiesAndInitBlocks.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/propertiesAndInitBlocks.dot index 1bc82dfba81..501ef0ed2d9 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/propertiesAndInitBlocks.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/propertiesAndInitBlocks.dot @@ -177,8 +177,8 @@ digraph propertiesAndInitBlocks_kt { 67 -> {64}; 20 -> {21 22}; 20 -> {26 35 38} [color=red]; - 21 -> {20}; 21 -> {66} [color=green]; + 21 -> {20} [color=green style=dashed]; 22 -> {23}; 23 -> {24}; 24 -> {64}; diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/tryCatch.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/tryCatch.dot index 711034dacca..c9da9d8f96e 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/tryCatch.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/tryCatch.dot @@ -280,8 +280,8 @@ digraph tryCatch_kt { 79 -> {80}; 80 -> {47}; 81 -> {82}; - 82 -> {39}; 82 -> {83} [style=dotted]; + 82 -> {39} [color=green style=dashed]; 83 -> {84} [style=dotted]; 84 -> {85} [style=dotted]; 85 -> {47} [style=dotted]; @@ -294,7 +294,7 @@ digraph tryCatch_kt { 91 -> {92}; 92 -> {93}; 93 -> {94}; - 94 -> {41}; + 94 -> {41} [color=green style=dashed]; 95 -> {96}; 96 -> {38}; diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.dot b/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.dot index f81deb36c77..15e92403ec7 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.dot +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.dot @@ -124,8 +124,8 @@ digraph boundSmartcastsInBranches_kt { 36 -> {37}; 37 -> {38}; 38 -> {39}; - 39 -> {17}; 39 -> {40} [style=dotted]; + 39 -> {17} [color=green style=dashed]; 40 -> {41} [style=dotted]; 41 -> {42} [style=dotted]; 42 -> {29} [style=dotted]; @@ -133,7 +133,7 @@ digraph boundSmartcastsInBranches_kt { 44 -> {45}; 45 -> {46}; 46 -> {47}; - 47 -> {19}; + 47 -> {19} [color=green style=dashed]; subgraph cluster_12 { color=red diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/loops/dataFlowInfoFromWhileCondition.dot b/compiler/fir/analysis-tests/testData/resolve/smartcasts/loops/dataFlowInfoFromWhileCondition.dot index dad20c836f2..d18d3268119 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/loops/dataFlowInfoFromWhileCondition.dot +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/loops/dataFlowInfoFromWhileCondition.dot @@ -91,6 +91,6 @@ digraph dataFlowInfoFromWhileCondition_kt { 26 -> {27}; 27 -> {28}; 28 -> {29}; - 29 -> {14}; + 29 -> {14} [color=green style=dashed]; } diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/loops/endlessLoops.dot b/compiler/fir/analysis-tests/testData/resolve/smartcasts/loops/endlessLoops.dot index 89bd96a9300..d2464d8b7b2 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/loops/endlessLoops.dot +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/loops/endlessLoops.dot @@ -93,7 +93,7 @@ digraph endlessLoops_kt { 25 -> {16} [style=dotted]; 26 -> {16}; 27 -> {28}; - 28 -> {8}; + 28 -> {8} [color=green style=dashed]; 29 -> {30}; 30 -> {5}; @@ -173,7 +173,7 @@ digraph endlessLoops_kt { 52 -> {41} [style=dotted]; 53 -> {41}; 54 -> {55}; - 55 -> {35}; + 55 -> {35} [color=green style=dashed]; 56 -> {57}; 57 -> {32}; @@ -287,7 +287,7 @@ digraph endlessLoops_kt { 91 -> {82} [style=dotted]; 92 -> {82}; 93 -> {94}; - 94 -> {62}; + 94 -> {62} [color=green style=dashed]; 95 -> {96}; 96 -> {59}; @@ -372,7 +372,7 @@ digraph endlessLoops_kt { 120 -> {121} [style=dotted]; 121 -> {122} [style=dotted]; 122 -> {123} [style=dotted]; - 123 -> {101} [style=dotted]; + 123 -> {101} [color=green style=dotted]; 124 -> {125}; 125 -> {98}; @@ -451,8 +451,8 @@ digraph endlessLoops_kt { 147 -> {148}; 148 -> {149}; 149 -> {150}; - 150 -> {130}; 150 -> {129} [style=dotted]; + 150 -> {130} [color=green style=dashed]; 151 -> {152}; 152 -> {127}; @@ -531,8 +531,8 @@ digraph endlessLoops_kt { 174 -> {175}; 175 -> {176}; 176 -> {177}; - 177 -> {157}; 177 -> {156} [style=dotted]; + 177 -> {157} [color=green style=dashed]; 178 -> {179}; 179 -> {154}; @@ -577,8 +577,8 @@ digraph endlessLoops_kt { 189 -> {190}; 190 -> {191}; 191 -> {192}; - 192 -> {184}; 192 -> {183} [style=dotted]; + 192 -> {184} [color=green style=dashed]; 193 -> {194} [style=dotted]; 194 -> {181} [style=dotted]; diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToNothing.dot b/compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToNothing.dot index b90bdf01d8d..70ef90466e8 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToNothing.dot +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToNothing.dot @@ -250,7 +250,7 @@ digraph smartcastToNothing_kt { 81 -> {70} [style=dotted]; 82 -> {70} [style=dotted]; 83 -> {84} [style=dotted]; - 84 -> {56} [style=dotted]; + 84 -> {56} [color=green style=dotted]; 85 -> {86 87}; 86 -> {88}; 87 -> {48} [style=dotted]; diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromLibrary/callsInPlace.dot b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromLibrary/callsInPlace.dot index 7ca780fcfd7..716951b7f5c 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromLibrary/callsInPlace.dot +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromLibrary/callsInPlace.dot @@ -59,8 +59,8 @@ digraph callsInPlace_kt { 17 -> {18}; 18 -> {14}; 19 -> {20 21}; - 20 -> {19}; 20 -> {17} [color=green]; + 20 -> {19} [color=green style=dashed]; 21 -> {20}; subgraph cluster_4 { @@ -85,8 +85,8 @@ digraph callsInPlace_kt { 26 -> {27}; 27 -> {23}; 28 -> {29 30}; - 29 -> {28}; 29 -> {25} [color=green]; + 29 -> {28} [color=green style=dashed]; 30 -> {29}; subgraph cluster_6 { @@ -203,12 +203,12 @@ digraph callsInPlace_kt { 68 -> {69}; 69 -> {64}; 70 -> {71 72}; - 71 -> {70}; 71 -> {66} [color=green]; + 71 -> {70} [color=green style=dashed]; 72 -> {71}; 73 -> {74 75}; - 74 -> {73}; 74 -> {68} [color=green]; + 74 -> {73} [color=green style=dashed]; 75 -> {74}; subgraph cluster_14 { @@ -242,12 +242,12 @@ digraph callsInPlace_kt { 81 -> {82}; 82 -> {77}; 83 -> {84 85}; - 84 -> {83}; 84 -> {79} [color=green]; + 84 -> {83} [color=green style=dashed]; 85 -> {84}; 86 -> {87 88}; - 87 -> {86}; 87 -> {81} [color=green]; + 87 -> {86} [color=green style=dashed]; 88 -> {87}; subgraph cluster_17 { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atLeastOnce.dot b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atLeastOnce.dot index 258d057ef48..bd57edff22d 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atLeastOnce.dot +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atLeastOnce.dot @@ -48,8 +48,8 @@ digraph atLeastOnce_kt { 12 -> {13}; 13 -> {7}; 14 -> {16}; - 15 -> {14}; 15 -> {10} [color=green]; + 15 -> {14} [color=green style=dashed]; 16 -> {17}; 17 -> {15}; @@ -80,8 +80,8 @@ digraph atLeastOnce_kt { 24 -> {25}; 25 -> {19}; 26 -> {28}; - 27 -> {26}; 27 -> {22} [color=green]; + 27 -> {26} [color=green style=dashed]; 28 -> {29}; 29 -> {27}; diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/unknown.dot b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/unknown.dot index f4f3027f6f4..e5933116ebd 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/unknown.dot +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/unknown.dot @@ -48,8 +48,8 @@ digraph unknown_kt { 12 -> {13}; 13 -> {7}; 14 -> {15 16}; - 15 -> {14}; 15 -> {10} [color=green]; + 15 -> {14} [color=green style=dashed]; 16 -> {17}; 17 -> {15}; @@ -80,8 +80,8 @@ digraph unknown_kt { 24 -> {25}; 25 -> {19}; 26 -> {27 28}; - 27 -> {26}; 27 -> {22} [color=green]; + 27 -> {26} [color=green style=dashed]; 28 -> {29}; 29 -> {27}; diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/smartcasts/tryWithLambdaInside.dot b/compiler/fir/analysis-tests/testData/resolveWithStdlib/smartcasts/tryWithLambdaInside.dot index 2b8b9d11c4b..76bb4209cd4 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/smartcasts/tryWithLambdaInside.dot +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/smartcasts/tryWithLambdaInside.dot @@ -94,8 +94,8 @@ finally { 23 -> {24} [style=dotted]; 24 -> {8} [style=dotted]; 25 -> {26 27}; - 26 -> {25}; 26 -> {16} [color=green]; + 26 -> {25} [color=green style=dashed]; 27 -> {26}; subgraph cluster_9 { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt index 211b4a7f6dc..a68e4dd8b5e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt @@ -69,9 +69,11 @@ class ControlFlowGraph(val declaration: FirDeclaration?, val name: String, val k } } -enum class EdgeKind(val usedInDfa: Boolean) { - Simple(usedInDfa = true), - Dead(usedInDfa = false), - Cfg(usedInDfa = false), - Dfg(usedInDfa = true) +enum class EdgeKind(val usedInDfa: Boolean, val isBack: Boolean) { + Simple(usedInDfa = true, isBack = false), + Dead(usedInDfa = false, isBack = false), + Cfg(usedInDfa = false, isBack = false), + Dfg(usedInDfa = true, isBack = false), + Back(usedInDfa = false, isBack = true), + DeadBack(usedInDfa = false, isBack = true) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt index d113f3fc1d2..5852db61e2e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt @@ -151,7 +151,7 @@ class ControlFlowGraphBuilder { val enterNode = functionEnterNodes.pop() @Suppress("NON_EXHAUSTIVE_WHEN") when (invocationKind) { - InvocationKind.AT_LEAST_ONCE, InvocationKind.UNKNOWN -> addEdge(exitNode, enterNode, propagateDeadness = false) + InvocationKind.AT_LEAST_ONCE, InvocationKind.UNKNOWN -> addBackEdge(exitNode, enterNode) } if (postponedExitNode != null) { CFGNode.addEdge(lastNodes.pop(), postponedExitNode, propagateDeadness = true, kind = EdgeKind.Cfg) @@ -399,7 +399,7 @@ class ControlFlowGraphBuilder { is FirBreakExpression -> loopExitNodes[jump.target.labeledElement] else -> throw IllegalArgumentException("Unknown jump type: ${jump.render()}") } - addNodeWithJump(node, nextNode) + addNodeWithJump(node, nextNode, isBack = jump is FirContinueExpression) return node } @@ -502,7 +502,7 @@ class ControlFlowGraphBuilder { if (lastNodes.isNotEmpty) { val conditionEnterNode = lastNodes.pop() require(conditionEnterNode is LoopConditionEnterNode) { loop.render() } - addEdge(loopBlockExitNode, conditionEnterNode, propagateDeadness = false) + addBackEdge(loopBlockExitNode, conditionEnterNode) } val loopExitNode = loopExitNodes.pop() loopExitNode.updateDeadStatus() @@ -543,7 +543,7 @@ class ControlFlowGraphBuilder { addEdge(lastNodes.pop(), conditionExitNode) val blockEnterNode = lastNodes.pop() require(blockEnterNode is LoopBlockEnterNode) - addEdge(conditionExitNode, blockEnterNode, propagateDeadness = false, isDead = conditionBooleanValue == false) + addBackEdge(conditionExitNode, blockEnterNode, isDead = conditionBooleanValue == false) val loopExit = loopExitNodes.pop() addEdge(conditionExitNode, loopExit, propagateDeadness = false, isDead = conditionBooleanValue == true) loopExit.updateDeadStatus() @@ -903,13 +903,17 @@ class ControlFlowGraphBuilder { * it will be replaced after correct implementation of CFG for class initialization */ val exitNode: CFGNode<*> = exitNodes.top() - addNodeWithJump(node, exitNode, preferredKind) + addNodeWithJump(node, exitNode) } - private fun addNodeWithJump(node: CFGNode<*>, targetNode: CFGNode<*>?, preferredKind: EdgeKind = EdgeKind.Simple) { + private fun addNodeWithJump(node: CFGNode<*>, targetNode: CFGNode<*>?, isBack: Boolean = false) { addEdge(lastNodes.pop(), node) if (targetNode != null) { - addEdge(node, targetNode) + if (isBack) { + addBackEdge(node, targetNode) + } else { + addEdge(node, targetNode) + } } val stub = createStubNode() addEdge(node, stub) @@ -933,12 +937,23 @@ class ControlFlowGraphBuilder { to: CFGNode<*>, propagateDeadness: Boolean = true, isDead: Boolean = false, - preferredKind: EdgeKind = EdgeKind.Simple + isBack: Boolean = false, + preferredKind: EdgeKind = EdgeKind.Simple, ) { - val kind = if (isDead || from.isDead || to.isDead) EdgeKind.Dead else preferredKind + val kind = if (isDead || from.isDead || to.isDead) { + if (isBack) EdgeKind.DeadBack else EdgeKind.Dead + } else preferredKind CFGNode.addEdge(from, to, kind, propagateDeadness) } + private fun addBackEdge( + from: CFGNode<*>, + to: CFGNode<*>, + isDead: Boolean = false + ) { + addEdge(from, to, propagateDeadness = false, isDead = isDead, isBack = true, preferredKind = EdgeKind.Back) + } + private val FirFunction<*>.invocationKind: InvocationKind? get() = (this as? FirAnonymousFunction)?.invocationKind diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphRenderer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphRenderer.kt index c92240c813e..04a05a45f13 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphRenderer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphRenderer.kt @@ -30,6 +30,8 @@ class FirControlFlowGraphRenderVisitor( EdgeKind.Dead to "[style=dotted]", EdgeKind.Cfg to "[color=green]", EdgeKind.Dfg to "[color=red]", + EdgeKind.Back to "[color=green style=dashed]", + EdgeKind.DeadBack to "[color=green style=dotted]" ) ) } diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt index afcfad2ace1..61260a50fa2 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt @@ -308,7 +308,7 @@ abstract class AbstractFirDiagnosticsTest : AbstractFirBaseDiagnosticsTest() { val toKind = to.incomingEdges.getValue(from) TestCase.assertEquals(fromKind, toKind) if (from.isDead || to.isDead) { - KtUsefulTestCase.assertContainsElements(listOf(EdgeKind.Dead, EdgeKind.Cfg), toKind) + KtUsefulTestCase.assertContainsElements(listOf(EdgeKind.Dead, EdgeKind.Cfg, EdgeKind.DeadBack, EdgeKind.Back), toKind) } } }