diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index 9808bd84336..d56041caac0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -802,6 +802,13 @@ public class JetControlFlowProcessor { if (!conditionIsTrueConstant) { builder.jumpOnFalse(loopInfo.getExitPoint(), expression, builder.getBoundValue(condition)); } + else { + assert condition != null : "Invalid while condition: " + expression.getText(); + List values = ContainerUtil.createMaybeSingletonList(builder.getBoundValue(condition)); + Map typePredicates = + PseudocodePackage.expectedTypeFor(new SingleType(KotlinBuiltIns.getInstance().getBooleanType()), values); + builder.magic(condition, null, values, typePredicates, MagicKind.VALUE_CONSUMER); + } builder.bindLabel(loopInfo.getBodyEntryPoint()); JetExpression body = expression.getBody(); diff --git a/compiler/testData/cfg-variables/lexicalScopes/whileScope.instructions b/compiler/testData/cfg-variables/lexicalScopes/whileScope.instructions index 2dec72a8ad3..08521566d7a 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/whileScope.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/whileScope.instructions @@ -16,14 +16,15 @@ L2 [loop entry point]: L5 [condition entry point]: r(true) -> mark(while (true) { val a: Int }) + magic[VALUE_CONSUMER](true|) -> L4 [body entry point]: 3 mark({ val a: Int }) v(val a: Int) INIT: in: {} out: {a=D} 2 jmp(L2 [loop entry point]) INIT: in: {} out: {} USE: in: {} out: {} L3 [loop exit point]: -- read (Unit) +- read (Unit) -> - mark("after") -- r("after") -> +- r("after") -> L1: 1 INIT: in: {} out: {} error: diff --git a/compiler/testData/cfg-variables/lexicalScopes/whileScope.values b/compiler/testData/cfg-variables/lexicalScopes/whileScope.values index 23af85b6d26..c11056bc64a 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/whileScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/whileScope.values @@ -7,8 +7,9 @@ fun foo() { "after" } --------------------- -"before" : * NEW: r("before") -> -true : * NEW: r(true) -> -"after" : * NEW: r("after") -> -{ "before" while (true) { val a: Int } "after" } : * COPY + : * NEW: magic[VALUE_CONSUMER](true|) -> +"before" : * NEW: r("before") -> +true : Boolean NEW: r(true) -> +"after" : * NEW: r("after") -> +{ "before" while (true) { val a: Int } "after" } : * COPY ===================== diff --git a/compiler/testData/cfg/controlStructures/Finally.instructions b/compiler/testData/cfg/controlStructures/Finally.instructions index 249942ec105..d5d1797d6af 100644 --- a/compiler/testData/cfg/controlStructures/Finally.instructions +++ b/compiler/testData/cfg/controlStructures/Finally.instructions @@ -256,36 +256,37 @@ L2 [loop entry point]: L5 [condition entry point]: r(true) -> PREV:[mark(@l while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } }), jmp(L2 [loop entry point])] mark(while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } }) + magic[VALUE_CONSUMER](true|) -> L4 [body entry point]: 3 mark({ try { 1 if (2 > 3) { break @l } } finally { 2 } }) mark(try { 1 if (2 > 3) { break @l } } finally { 2 }) jmp?(L6 [onExceptionToFinallyBlock]) NEXT:[mark({ 2 }), mark({ 1 if (2 > 3) { break @l } })] 4 mark({ 1 if (2 > 3) { break @l } }) - r(1) -> + r(1) -> mark(if (2 > 3) { break @l }) - r(2) -> - r(3) -> + r(2) -> + r(3) -> mark(2 > 3) - call(2 > 3, compareTo|, ) -> - jf(L7|) NEXT:[read (Unit), mark({ break @l })] + call(2 > 3, compareTo|, ) -> + jf(L7|) NEXT:[read (Unit), mark({ break @l })] 5 mark({ break @l }) L8 [start finally]: 6 mark({ 2 }) - r(2) -> + r(2) -> L9 [finish finally]: 5 jmp(L3 [loop exit point]) NEXT:[read (Unit)] - 4 jmp(L10) NEXT:[jmp(L11 [skipFinallyToErrorBlock])] PREV:[] L7: - read (Unit) PREV:[jf(L7|)] + read (Unit) PREV:[jf(L7|)] L10: 3 jmp(L11 [skipFinallyToErrorBlock]) NEXT:[mark({ 2 })] L6 [onExceptionToFinallyBlock]: 6 mark({ 2 }) PREV:[jmp?(L6 [onExceptionToFinallyBlock])] - r(2) -> + r(2) -> 3 jmp(error) NEXT:[] L11 [skipFinallyToErrorBlock]: 6 mark({ 2 }) PREV:[jmp(L11 [skipFinallyToErrorBlock])] - r(2) -> + r(2) -> 2 jmp(L2 [loop entry point]) NEXT:[r(true) -> ] L3 [loop exit point]: read (Unit) PREV:[jmp(L3 [loop exit point])] @@ -322,35 +323,36 @@ L3 [loop entry point]: L6 [condition entry point]: r(true) -> PREV:[mark(@l while(true) { 1 if (2 > 3) { break @l } }), jmp(L3 [loop entry point])] mark(while(true) { 1 if (2 > 3) { break @l } }) + magic[VALUE_CONSUMER](true|) -> L5 [body entry point]: 4 mark({ 1 if (2 > 3) { break @l } }) - r(1) -> + r(1) -> mark(if (2 > 3) { break @l }) - r(2) -> - r(3) -> + r(2) -> + r(3) -> mark(2 > 3) - call(2 > 3, compareTo|, ) -> - jf(L7|) NEXT:[read (Unit), mark({ break @l })] + call(2 > 3, compareTo|, ) -> + jf(L7|) NEXT:[read (Unit), mark({ break @l })] 5 mark({ break @l }) jmp(L4 [loop exit point]) NEXT:[read (Unit)] - 4 jmp(L8) NEXT:[jmp(L3 [loop entry point])] PREV:[] L7: - read (Unit) PREV:[jf(L7|)] + read (Unit) PREV:[jf(L7|)] L8: 3 jmp(L3 [loop entry point]) NEXT:[r(true) -> ] L4 [loop exit point]: read (Unit) PREV:[jmp(L4 [loop exit point])] - r(5) -> + r(5) -> 2 jmp(L9 [skipFinallyToErrorBlock]) NEXT:[mark({ 2 })] L2 [onExceptionToFinallyBlock]: L10 [start finally]: 3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])] - r(2) -> + r(2) -> L11 [finish finally]: 2 jmp(error) NEXT:[] L9 [skipFinallyToErrorBlock]: 3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])] - r(2) -> + r(2) -> L1: 1 NEXT:[] error: @@ -383,20 +385,21 @@ L3 [loop entry point]: L6 [condition entry point]: r(true) -> PREV:[mark(@l while(true) { 1 if (2 > 3) { break @l } }), jmp(L3 [loop entry point])] mark(while(true) { 1 if (2 > 3) { break @l } }) + magic[VALUE_CONSUMER](true|) -> L5 [body entry point]: 4 mark({ 1 if (2 > 3) { break @l } }) - r(1) -> + r(1) -> mark(if (2 > 3) { break @l }) - r(2) -> - r(3) -> + r(2) -> + r(3) -> mark(2 > 3) - call(2 > 3, compareTo|, ) -> - jf(L7|) NEXT:[read (Unit), mark({ break @l })] + call(2 > 3, compareTo|, ) -> + jf(L7|) NEXT:[read (Unit), mark({ break @l })] 5 mark({ break @l }) jmp(L4 [loop exit point]) NEXT:[read (Unit)] - 4 jmp(L8) NEXT:[jmp(L3 [loop entry point])] PREV:[] L7: - read (Unit) PREV:[jf(L7|)] + read (Unit) PREV:[jf(L7|)] L8: 3 jmp(L3 [loop entry point]) NEXT:[r(true) -> ] L4 [loop exit point]: @@ -405,12 +408,12 @@ L4 [loop exit point]: L2 [onExceptionToFinallyBlock]: L10 [start finally]: 3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])] - r(2) -> + r(2) -> L11 [finish finally]: 2 jmp(error) NEXT:[] L9 [skipFinallyToErrorBlock]: 3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])] - r(2) -> + r(2) -> L1: 1 NEXT:[] error: diff --git a/compiler/testData/cfg/controlStructures/Finally.values b/compiler/testData/cfg/controlStructures/Finally.values index 88328671165..4fbfca31178 100644 --- a/compiler/testData/cfg/controlStructures/Finally.values +++ b/compiler/testData/cfg/controlStructures/Finally.values @@ -118,13 +118,14 @@ fun t5() { } } --------------------- -true : * NEW: r(true) -> -1 : * NEW: r(1) -> -2 : {<: Comparable} NEW: r(2) -> -3 : Int NEW: r(3) -> -2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> -2 : * NEW: r(2) -> -{ 2 } : * COPY + : * NEW: magic[VALUE_CONSUMER](true|) -> +true : Boolean NEW: r(true) -> +1 : * NEW: r(1) -> +2 : {<: Comparable} NEW: r(2) -> +3 : Int NEW: r(3) -> +2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> +2 : * NEW: r(2) -> +{ 2 } : * COPY ===================== == t6 == fun t6() { @@ -141,17 +142,18 @@ fun t6() { } } --------------------- -true : * NEW: r(true) -> -1 : * NEW: r(1) -> -2 : {<: Comparable} NEW: r(2) -> -3 : Int NEW: r(3) -> -2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> -5 : * NEW: r(5) -> -{ @l while(true) { 1 if (2 > 3) { break @l } } 5 } : * COPY -2 : * NEW: r(2) -> -{ 2 } : * COPY -try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } : * COPY -{ try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } } : * COPY + : * NEW: magic[VALUE_CONSUMER](true|) -> +true : Boolean NEW: r(true) -> +1 : * NEW: r(1) -> +2 : {<: Comparable} NEW: r(2) -> +3 : Int NEW: r(3) -> +2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> +5 : * NEW: r(5) -> +{ @l while(true) { 1 if (2 > 3) { break @l } } 5 } : * COPY +2 : * NEW: r(2) -> +{ 2 } : * COPY +try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } : * COPY +{ try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } } : * COPY ===================== == t7 == fun t7() { @@ -167,13 +169,14 @@ fun t7() { } } --------------------- -true : * NEW: r(true) -> -1 : * NEW: r(1) -> -2 : {<: Comparable} NEW: r(2) -> -3 : Int NEW: r(3) -> -2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> -2 : * NEW: r(2) -> -{ 2 } : * COPY + : * NEW: magic[VALUE_CONSUMER](true|) -> +true : Boolean NEW: r(true) -> +1 : * NEW: r(1) -> +2 : {<: Comparable} NEW: r(2) -> +3 : Int NEW: r(3) -> +2 > 3 : Boolean NEW: call(2 > 3, compareTo|, ) -> +2 : * NEW: r(2) -> +{ 2 } : * COPY ===================== == t8 == fun t8(a : Int) {