From 52b81a15e540b313d3c7300c220ce767fa26d2c2 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Thu, 19 Jan 2012 00:01:46 +0100 Subject: [PATCH] KT-998: wrong codegen for labeled continue/break --- .../jet/codegen/ExpressionCodegen.java | 45 ++++++++++++++----- .../testData/codegen/regressions/kt998.kt | 35 +++++++++++++++ .../jet/codegen/ControlStructuresTest.java | 4 ++ 3 files changed, 72 insertions(+), 12 deletions(-) create mode 100644 compiler/testData/codegen/regressions/kt998.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 3e5c4b0d6ed..dbf018ec21a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -65,10 +65,12 @@ public class ExpressionCodegen extends JetVisitor { static class LoopBlockStackElement extends BlockStackElement { final Label continueLabel; final Label breakLabel; + public JetSimpleNameExpression targetLabel; - LoopBlockStackElement(Label breakLabel, Label continueLabel) { + LoopBlockStackElement(Label breakLabel, Label continueLabel, JetSimpleNameExpression targetLabel) { this.breakLabel = breakLabel; this.continueLabel = continueLabel; + this.targetLabel = targetLabel; } } @@ -258,7 +260,7 @@ public class ExpressionCodegen extends JetVisitor { v.mark(condition); Label end = continueLabel != null ? continueLabel : new Label(); - blockStackElements.push(new LoopBlockStackElement(end, condition)); + blockStackElements.push(new LoopBlockStackElement(end, condition, targetLabel(expression))); Label savedContinueLabel = continueLabel; continueLabel = condition; @@ -278,14 +280,15 @@ public class ExpressionCodegen extends JetVisitor { return StackValue.onStack(Type.VOID_TYPE); } + @Override public StackValue visitDoWhileExpression(JetDoWhileExpression expression, StackValue receiver) { Label condition = new Label(); v.mark(condition); Label end = new Label(); - - blockStackElements.push(new LoopBlockStackElement(end, condition)); + + blockStackElements.push(new LoopBlockStackElement(end, condition, targetLabel(expression))); gen(expression.getBody(), Type.VOID_TYPE); @@ -356,7 +359,7 @@ public class ExpressionCodegen extends JetVisitor { } Label begin = new Label(); - blockStackElements.push(new LoopBlockStackElement(end, begin)); + blockStackElements.push(new LoopBlockStackElement(end, begin, targetLabel(expression))); v.mark(begin); v.load(iteratorVar, asmIterType); @@ -426,7 +429,7 @@ public class ExpressionCodegen extends JetVisitor { Label increment = new Label(); v.mark(condition); - blockStackElements.push(new LoopBlockStackElement(end, increment)); + blockStackElements.push(new LoopBlockStackElement(end, increment, targetLabel(expression))); generateCondition(asmParamType, end); @@ -607,9 +610,10 @@ public class ExpressionCodegen extends JetVisitor { } else if(stackElement instanceof LoopBlockStackElement) { LoopBlockStackElement loopBlockStackElement = (LoopBlockStackElement) stackElement; - Label label = labelElement == null ? loopBlockStackElement.breakLabel : null; // TODO: - v.goTo(label); - return StackValue.none(); + if (labelElement == null || loopBlockStackElement.targetLabel != null && labelElement.getReferencedName().equals(loopBlockStackElement.targetLabel.getReferencedName())) { + v.goTo(loopBlockStackElement.breakLabel); + return StackValue.none(); + } } else { throw new UnsupportedOperationException(); @@ -632,9 +636,10 @@ public class ExpressionCodegen extends JetVisitor { } else if(stackElement instanceof LoopBlockStackElement) { LoopBlockStackElement loopBlockStackElement = (LoopBlockStackElement) stackElement; - Label label = labelElement == null ? loopBlockStackElement.continueLabel : null; // TODO: - v.goTo(label); - return StackValue.none(); + if (labelElement == null || loopBlockStackElement.targetLabel != null && labelElement.getReferencedName().equals(loopBlockStackElement.targetLabel.getReferencedName())) { + v.goTo(loopBlockStackElement.continueLabel); + return StackValue.none(); + } } else { throw new UnsupportedOperationException(); @@ -1960,8 +1965,24 @@ public class ExpressionCodegen extends JetVisitor { v.invokevirtual("java/lang/StringBuilder", "append", appendDescriptor.getDescriptor()); } + private JetSimpleNameExpression targetLabel(JetExpression expression) { + if(expression.getParent() instanceof JetPrefixExpression) { + JetPrefixExpression parent = (JetPrefixExpression) expression.getParent(); + JetSimpleNameExpression operationSign = parent.getOperationReference(); + if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) { + return operationSign; + } + } + return null; + } + @Override public StackValue visitPrefixExpression(JetPrefixExpression expression, StackValue receiver) { + JetSimpleNameExpression operationSign = expression.getOperationReference(); + if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) { + return genQualified(receiver, expression.getBaseExpression()); + } + DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); final Callable callable = resolveToCallable(op, false); if (callable instanceof IntrinsicMethod) { diff --git a/compiler/testData/codegen/regressions/kt998.kt b/compiler/testData/codegen/regressions/kt998.kt new file mode 100644 index 00000000000..2b5d30d6fdd --- /dev/null +++ b/compiler/testData/codegen/regressions/kt998.kt @@ -0,0 +1,35 @@ +fun findPairless(a : IntArray) : Int { + @loop for (i in a.indices) { + for (j in a.indices) { + if (i != j && a[i] == a[j]) continue@loop + } + return a[i] + } + return -1 +} + +fun hasDuplicates(a : IntArray) : Boolean { + var duplicate = false + @loop for (i in a.indices) { + for (j in a.indices) { + if (i != j && a[i] == a[j]) { + duplicate = true + break@loop + } + } + return a[i] + } + return duplicate +} + +fun box() : String { + val a = IntArray(5) + a[0] = 0 + a[1] = 0 + a[2] = 1 + a[3] = 1 + a[4] = 5 + if(findPairless(a) != 5) return "fail" + return if(hasDuplicates(a)) "OK" else "fail" + +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java b/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java index 56d56d8cfba..3a6a0e61b2b 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java @@ -266,4 +266,8 @@ public class ControlStructuresTest extends CodegenTestCase { public void testKt1076() throws Exception { blackBoxFile("regressions/kt1076.kt"); } + + public void testKt998() throws Exception { + blackBoxFile("regressions/kt998.kt"); + } }