Jump after 'for' cycle to loop parameter change.

Not to the cycle body.
This commit is contained in:
Svetlana Isakova
2014-03-05 19:38:50 +04:00
parent e34385bbcf
commit 7d46ff951e
7 changed files with 93 additions and 52 deletions
@@ -24,7 +24,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowInstructionsGenerator;
import org.jetbrains.jet.lang.cfg.pseudocode.LocalFunctionDeclarationInstruction;
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeImpl;
import org.jetbrains.jet.lang.descriptors.*;
@@ -608,14 +607,7 @@ public class JetControlFlowProcessor {
if (loopRange != null) {
generateInstructions(loopRange, NOT_IN_CONDITION);
}
JetParameter loopParameter = expression.getLoopParameter();
if (loopParameter != null) {
generateInstructions(loopParameter, context);
}
else {
JetMultiDeclaration multiParameter = expression.getMultiParameter();
generateInstructions(multiParameter, context);
}
declareLoopParameter(expression);
// TODO : primitive cases
Label loopExitPoint = builder.createUnboundLabel();
@@ -627,6 +619,8 @@ public class JetControlFlowProcessor {
LoopInfo loopInfo = builder.enterLoop(expression, loopExitPoint, conditionEntryPoint);
builder.bindLabel(loopInfo.getBodyEntryPoint());
writeLoopParameterAssignment(expression);
JetExpression body = expression.getBody();
if (body != null) {
generateInstructions(body, NOT_IN_CONDITION);
@@ -638,6 +632,30 @@ public class JetControlFlowProcessor {
builder.exitLexicalScope(expression);
}
private void declareLoopParameter(JetForExpression expression) {
JetParameter loopParameter = expression.getLoopParameter();
JetMultiDeclaration multiDeclaration = expression.getMultiParameter();
if (loopParameter != null) {
builder.declareParameter(loopParameter);
}
else if (multiDeclaration != null) {
visitMultiDeclaration(multiDeclaration, false);
}
}
private void writeLoopParameterAssignment(JetForExpression expression) {
JetParameter loopParameter = expression.getLoopParameter();
JetMultiDeclaration multiDeclaration = expression.getMultiParameter();
if (loopParameter != null) {
builder.write(loopParameter, loopParameter);
}
else if (multiDeclaration != null) {
for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) {
builder.write(entry, entry);
}
}
}
@Override
public void visitBreakExpressionVoid(@NotNull JetBreakExpression expression, CFPContext context) {
JetElement loop = getCorrespondingLoop(expression);
@@ -832,18 +850,21 @@ public class JetControlFlowProcessor {
@Override
public void visitMultiDeclarationVoid(@NotNull JetMultiDeclaration declaration, CFPContext context) {
JetExpression initializer = declaration.getInitializer();
if (initializer != null) {
generateInstructions(initializer, NOT_IN_CONDITION);
}
List<JetMultiDeclarationEntry> entries = declaration.getEntries();
for (JetMultiDeclarationEntry entry : entries) {
visitMultiDeclaration(declaration, true);
}
private void visitMultiDeclaration(@NotNull JetMultiDeclaration declaration, boolean generateWriteForEntries) {
generateInstructions(declaration.getInitializer(), NOT_IN_CONDITION);
for (JetMultiDeclarationEntry entry : declaration.getEntries()) {
builder.declareVariable(entry);
ResolvedCall<FunctionDescriptor> resolvedCall = trace.get(BindingContext.COMPONENT_RESOLVED_CALL, entry);
if (resolvedCall != null) {
builder.call(entry, resolvedCall);
}
builder.write(entry, entry);
if (generateWriteForEntries) {
builder.write(entry, entry);
}
}
}
@@ -21,14 +21,14 @@ L0:
3 mark(for (i in numbers) { val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue }) USE: in: {numbers=READ} out: {numbers=READ}
r(numbers) USE: in: {} out: {numbers=READ}
v(i) INIT: in: {numbers=ID} out: {i=D, numbers=ID}
w(i) INIT: in: {i=D, numbers=ID} out: {i=ID, numbers=ID}
L3:
jmp?(L2) INIT: in: {i=ID, numbers=ID} out: {i=ID, numbers=ID} USE: in: {} out: {}
jmp?(L2) INIT: in: {i=D, numbers=ID} out: {i=D, numbers=ID}
L4 [loop entry point]:
L5 [body entry point]:
4 mark({ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue }) INIT: in: {b=ID, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID}
v(val b: Boolean)
mark(if (1 < 2) { b = false } else { b = true })
w(i) INIT: in: {i=D, numbers=ID} out: {i=ID, numbers=ID} USE: in: {} out: {}
4 mark({ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue }) INIT: in: {i=ID, numbers=ID} out: {i=ID, numbers=ID}
v(val b: Boolean) INIT: in: {i=ID, numbers=ID} out: {b=D, i=ID, numbers=ID}
mark(if (1 < 2) { b = false } else { b = true }) INIT: in: {b=D, i=ID, numbers=ID} out: {b=D, i=ID, numbers=ID}
mark(1 < 2)
r(1)
r(2)
@@ -36,20 +36,20 @@ L5 [body entry point]:
jf(L6)
5 mark({ b = false })
r(false) USE: in: {b=WRITTEN_AFTER_READ} out: {b=WRITTEN_AFTER_READ}
w(b) USE: in: {b=READ} out: {b=WRITTEN_AFTER_READ}
4 jmp(L7) USE: in: {b=READ} out: {b=READ}
w(b) INIT: in: {b=D, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {b=READ} out: {b=WRITTEN_AFTER_READ}
4 jmp(L7) INIT: in: {b=ID, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {b=READ} out: {b=READ}
L6:
5 mark({ b = true })
5 mark({ b = true }) INIT: in: {b=D, i=ID, numbers=ID} out: {b=D, i=ID, numbers=ID}
r(true) USE: in: {b=WRITTEN_AFTER_READ} out: {b=WRITTEN_AFTER_READ}
w(b) USE: in: {b=READ} out: {b=WRITTEN_AFTER_READ}
w(b) INIT: in: {b=D, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {b=READ} out: {b=WRITTEN_AFTER_READ}
L7:
4 mark(use(b)) USE: in: {b=READ} out: {b=READ}
r(b) USE: in: {b=WRITTEN_AFTER_READ} out: {b=READ}
4 mark(use(b)) INIT: in: {b=ID, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {b=READ} out: {b=READ}
r(b) USE: in: {} out: {b=READ}
call(use, use)
jmp(L4 [loop entry point]) USE: in: {b=WRITTEN_AFTER_READ} out: {b=WRITTEN_AFTER_READ}
jmp(L4 [loop entry point]) USE: in: {} out: {}
- 3 jmp?(L4 [loop entry point])
L2:
read (Unit) INIT: in: {i=ID, numbers=ID} out: {i=ID, numbers=ID}
read (Unit) INIT: in: {i=D, numbers=ID} out: {i=D, numbers=ID}
L1:
1 <END> INIT: in: {numbers=ID} out: {numbers=ID}
error:
@@ -18,18 +18,18 @@ L0:
r(10)
call(.., rangeTo)
v(i) INIT: in: {} out: {i=D}
w(i) INIT: in: {i=D} out: {i=ID}
L3:
jmp?(L2) INIT: in: {i=ID} out: {i=ID}
jmp?(L2) INIT: in: {i=D} out: {i=D}
L4 [loop entry point]:
L5 [body entry point]:
4 mark({ val a = i })
w(i) INIT: in: {i=D} out: {i=ID}
4 mark({ val a = i }) INIT: in: {i=ID} out: {i=ID}
v(val a = i) INIT: in: {i=ID} out: {a=D, i=ID}
r(i) INIT: in: {a=D, i=ID} out: {a=D, i=ID}
w(a) INIT: in: {a=D, i=ID} out: {a=ID, i=ID}
3 jmp?(L4 [loop entry point]) INIT: in: {i=ID} out: {i=ID} USE: in: {i=READ} out: {i=READ}
L2:
read (Unit)
read (Unit) INIT: in: {i=D} out: {i=D}
2 mark("after") INIT: in: {} out: {}
r("after")
L1:
@@ -444,12 +444,12 @@ L0:
r(a)
call(.., rangeTo)
v(i)
w(i)
L3:
jmp?(L2) NEXT:[read (Unit), mark({ try { 1 if (2 > 3) { continue @ } } finally { 2 } })]
jmp?(L2) NEXT:[read (Unit), w(i)]
L4 [loop entry point]:
L5 [body entry point]:
4 mark({ try { 1 if (2 > 3) { continue @ } } finally { 2 } }) PREV:[jmp?(L2), jmp(L4 [loop entry point]), jmp?(L4 [loop entry point])]
w(i) PREV:[jmp?(L2), jmp(L4 [loop entry point]), jmp?(L4 [loop entry point])]
4 mark({ try { 1 if (2 > 3) { continue @ } } finally { 2 } })
mark(try { 1 if (2 > 3) { continue @ } } finally { 2 })
jmp?(L6 [onExceptionToFinallyBlock]) NEXT:[mark({ 2 }), mark({ 1 if (2 > 3) { continue @ } })]
5 mark({ 1 if (2 > 3) { continue @ } })
@@ -465,7 +465,7 @@ L8 [start finally]:
7 mark({ 2 })
r(2)
L9 [finish finally]:
6 jmp(L4 [loop entry point]) NEXT:[mark({ try { 1 if (2 > 3) { continue @ } } finally { 2 } })]
6 jmp(L4 [loop entry point]) NEXT:[w(i)]
- 5 jmp(L10) NEXT:[jmp(L11 [skipFinallyToErrorBlock])] PREV:[]
L7:
read (Unit) PREV:[jf(L7)]
@@ -478,7 +478,7 @@ L6 [onExceptionToFinallyBlock]:
L11 [skipFinallyToErrorBlock]:
7 mark({ 2 }) PREV:[jmp(L11 [skipFinallyToErrorBlock])]
r(2)
3 jmp?(L4 [loop entry point]) NEXT:[mark({ try { 1 if (2 > 3) { continue @ } } finally { 2 } }), read (Unit)]
3 jmp?(L4 [loop entry point]) NEXT:[w(i), read (Unit)]
L2:
read (Unit) PREV:[jmp?(L2), jmp?(L4 [loop entry point])]
L1:
@@ -518,12 +518,12 @@ L0:
r(a)
call(.., rangeTo)
v(i)
w(i)
L4:
jmp?(L3) NEXT:[read (Unit), mark({ 1 if (2 > 3) { continue @ } })]
jmp?(L3) NEXT:[read (Unit), w(i)]
L5 [loop entry point]:
L6 [body entry point]:
5 mark({ 1 if (2 > 3) { continue @ } }) PREV:[jmp?(L3), jmp(L5 [loop entry point]), jmp?(L5 [loop entry point])]
w(i) PREV:[jmp?(L3), jmp(L5 [loop entry point]), jmp?(L5 [loop entry point])]
5 mark({ 1 if (2 > 3) { continue @ } })
r(1)
mark(if (2 > 3) { continue @ })
mark(2 > 3)
@@ -532,12 +532,12 @@ L6 [body entry point]:
call(>, compareTo)
jf(L7) NEXT:[read (Unit), mark({ continue @ })]
6 mark({ continue @ })
jmp(L5 [loop entry point]) NEXT:[mark({ 1 if (2 > 3) { continue @ } })]
jmp(L5 [loop entry point]) NEXT:[w(i)]
- 5 jmp(L8) NEXT:[jmp?(L5 [loop entry point])] PREV:[]
L7:
read (Unit) PREV:[jf(L7)]
L8:
4 jmp?(L5 [loop entry point]) NEXT:[mark({ 1 if (2 > 3) { continue @ } }), read (Unit)]
4 jmp?(L5 [loop entry point]) NEXT:[w(i), read (Unit)]
L3:
read (Unit) PREV:[jmp?(L3), jmp?(L5 [loop entry point])]
3 r(5)
@@ -587,12 +587,12 @@ L0:
r(a)
call(.., rangeTo)
v(i)
w(i)
L4:
jmp?(L3) NEXT:[read (Unit), mark({ 1 if (2 > 3) { continue @ } })]
jmp?(L3) NEXT:[read (Unit), w(i)]
L5 [loop entry point]:
L6 [body entry point]:
5 mark({ 1 if (2 > 3) { continue @ } }) PREV:[jmp?(L3), jmp(L5 [loop entry point]), jmp?(L5 [loop entry point])]
w(i) PREV:[jmp?(L3), jmp(L5 [loop entry point]), jmp?(L5 [loop entry point])]
5 mark({ 1 if (2 > 3) { continue @ } })
r(1)
mark(if (2 > 3) { continue @ })
mark(2 > 3)
@@ -601,12 +601,12 @@ L6 [body entry point]:
call(>, compareTo)
jf(L7) NEXT:[read (Unit), mark({ continue @ })]
6 mark({ continue @ })
jmp(L5 [loop entry point]) NEXT:[mark({ 1 if (2 > 3) { continue @ } })]
jmp(L5 [loop entry point]) NEXT:[w(i)]
- 5 jmp(L8) NEXT:[jmp?(L5 [loop entry point])] PREV:[]
L7:
read (Unit) PREV:[jf(L7)]
L8:
4 jmp?(L5 [loop entry point]) NEXT:[mark({ 1 if (2 > 3) { continue @ } }), read (Unit)]
4 jmp?(L5 [loop entry point]) NEXT:[w(i), read (Unit)]
L3:
read (Unit) PREV:[jmp?(L3), jmp?(L5 [loop entry point])]
2 jmp(L9 [skipFinallyToErrorBlock]) NEXT:[mark({ 2 })]
@@ -14,16 +14,16 @@ L0:
r(2)
call(.., rangeTo)
v(i)
w(i)
L3:
jmp?(L2) NEXT:[read (Unit), mark({ doSmth(i) })]
jmp?(L2) NEXT:[read (Unit), w(i)]
L4 [loop entry point]:
L5 [body entry point]:
4 mark({ doSmth(i) }) PREV:[jmp?(L2), jmp?(L4 [loop entry point])]
w(i) PREV:[jmp?(L2), jmp?(L4 [loop entry point])]
4 mark({ doSmth(i) })
mark(doSmth(i))
r(i)
call(doSmth, doSmth)
3 jmp?(L4 [loop entry point]) NEXT:[mark({ doSmth(i) }), read (Unit)]
3 jmp?(L4 [loop entry point]) NEXT:[w(i), read (Unit)]
L2:
read (Unit) PREV:[jmp?(L2), jmp?(L4 [loop entry point])]
L1:
@@ -0,0 +1,15 @@
fun foo(numbers: Collection<Int>) {
for (i in numbers) {
val b: Boolean
if (1 < 2) {
b = false
}
else {
b = true
}
use(b)
continue
}
}
fun use(vararg a: Any?) = a
@@ -1688,6 +1688,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/unreachableCode.kt");
}
@TestMetadata("varInitializationInIfInCycle.kt")
public void testVarInitializationInIfInCycle() throws Exception {
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/varInitializationInIfInCycle.kt");
}
@TestMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/definiteReturn")
public static class DefiniteReturn extends AbstractJetDiagnosticsTest {
public void testAllFilesPresentInDefiniteReturn() throws Exception {