From 5a9c23e8de0eab6ca3fb229d0e52d6749cdaf3e2 Mon Sep 17 00:00:00 2001 From: svtk Date: Tue, 18 Oct 2011 16:52:16 +0400 Subject: [PATCH] Added edges check to control flow graph test --- .../jet/lang/cfg/JetControlFlowProcessor.java | 84 ---- .../jet/lang/cfg/pseudocode/Instruction.java | 1 + .../lang/cfg/pseudocode/InstructionImpl.java | 1 + .../NondeterministicJumpInstruction.java | 2 +- .../jet/lang/cfg/pseudocode/Pseudocode.java | 182 +------ idea/testData/cfg/ArrayAccess.instructions | 46 +- idea/testData/cfg/Assignments.instructions | 68 +-- idea/testData/cfg/Basic.instructions | 116 ++--- idea/testData/cfg/EmptyFunction.instructions | 8 +- idea/testData/cfg/FailFunction.instructions | 20 +- idea/testData/cfg/Finally.instructions | 456 +++++++++--------- idea/testData/cfg/LazyBooleans.instructions | 74 +-- idea/testData/cfg/Nonlocals.instructions | 86 ++-- .../cfg/OnlyWhileInFunctionBody.instructions | 42 +- .../cfg/ReturnFromExpression.instructions | 16 +- idea/testData/cfg/ShortFunction.instructions | 8 +- .../full/infos/Autocasts.jet | 8 +- .../full/regression/OverrideResolution.jet | 4 +- .../jetbrains/jet/cfg/JetControlFlowTest.java | 238 ++++++++- 19 files changed, 729 insertions(+), 731 deletions(-) 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 07337a81a63..3d7f2a9d25a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -22,8 +22,6 @@ import static org.jetbrains.jet.lang.diagnostics.Errors.*; */ public class JetControlFlowProcessor { -// private final Map> labeledElements = new HashMap>(); - private final JetControlFlowBuilder builder; private final BindingTrace trace; @@ -37,10 +35,6 @@ public class JetControlFlowProcessor { } public void generateSubroutineControlFlow(@NotNull JetElement subroutineElement, @NotNull List body) { -// if (subroutineElement instanceof JetNamedDeclaration) { -// JetNamedDeclaration namedDeclaration = (JetNamedDeclaration) subroutineElement; -// enterLabeledElement(JetPsiUtil.safeName(namedDeclaration.getName()), namedDeclaration); -// } boolean functionLiteral = subroutineElement instanceof JetFunctionLiteralExpression; builder.enterSubroutine(subroutineElement, functionLiteral); for (JetElement statement : body) { @@ -49,51 +43,6 @@ public class JetControlFlowProcessor { builder.exitSubroutine(subroutineElement, functionLiteral); } -// private void enterLabeledElement(@NotNull String labelName, @NotNull JetElement labeledElement) { -// Stack stack = labeledElements.get(labelName); -// if (stack == null) { -// stack = new Stack(); -// labeledElements.put(labelName, stack); -// } -// stack.push(labeledElement); -// } -// -// private void exitElement(JetElement element) { -// // TODO : really suboptimal -// for (Iterator>> mapIter = labeledElements.entrySet().iterator(); mapIter.hasNext(); ) { -// Map.Entry> entry = mapIter.next(); -// Stack stack = entry.getValue(); -// for (Iterator stackIter = stack.iterator(); stackIter.hasNext(); ) { -// JetElement recorded = stackIter.next(); -// if (recorded == element) { -// stackIter.remove(); -// } -// } -// if (stack.isEmpty()) { -// mapIter.remove(); -// } -// } -// } - -// @Nullable -// private JetElement resolveLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression, boolean reportUnresolved) { -// Stack stack = labeledElements.get(labelName); -// if (stack == null || stack.isEmpty()) { -// if (reportUnresolved) { -//// trace.report(UNRESOLVED_REFERENCE.on(labelExpression)); -// } -// return null; -// } -// else if (stack.size() > 1) { -//// trace.getErrorHandler().genericWarning(labelExpression.getNode(), "There is more than one label with such a name in this scope"); -//// trace.report(LABEL_NAME_CLASH.on(labelExpression)); -// } -// -// JetElement result = stack.peek(); -//// trace.record(BindingContext.LABEL_TARGET, labelExpression, result); -// return result; -// } - private class CFPVisitor extends JetVisitorVoid { private final boolean inCondition; @@ -111,7 +60,6 @@ public class JetControlFlowProcessor { visitor = new CFPVisitor(inCondition); } element.accept(visitor); -// exitElement(element); } @Override @@ -124,12 +72,6 @@ public class JetControlFlowProcessor { @Override public void visitThisExpression(JetThisExpression expression) { -// JetSimpleNameExpression targetLabel = expression.getTargetLabel(); -// if (targetLabel != null) { -// String labelName = expression.getLabelName(); -// assert labelName != null; -// resolveLabel(labelName, targetLabel, false); -// } builder.read(expression); } @@ -161,7 +103,6 @@ public class JetControlFlowProcessor { private void visitLabeledExpression(@NotNull String labelName, @NotNull JetExpression labeledExpression) { JetExpression deparenthesized = JetPsiUtil.deparenthesize(labeledExpression); if (deparenthesized != null) { -// enterLabeledElement(labelName, deparenthesized); value(labeledExpression, inCondition); } } @@ -453,29 +394,16 @@ public class JetControlFlowProcessor { trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.getText())); loop = null; } -// loop = resolveLabel(labelName, targetLabel, true); -// if (!isLoop(loop)) { -//// trace.getErrorHandler().genericError(expression.getNode(), "The label '" + targetLabel.getText() + "' does not denote a loop"); -// trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.getText())); -// loop = null; -// } } else { loop = builder.getCurrentLoop(); if (loop == null) { -// trace.getErrorHandler().genericError(expression.getNode(), "'break' and 'continue' are only allowed inside a loop"); trace.report(BREAK_OR_CONTINUE_OUTSIDE_A_LOOP.on(expression)); } } return loop; } -// private boolean isLoop(JetElement loop) { -// return loop instanceof JetWhileExpression || -// loop instanceof JetDoWhileExpression || -// loop instanceof JetForExpression; -// } - @Override public void visitReturnExpression(JetReturnExpression expression) { JetExpression returnedExpression = expression.getReturnedExpression(); @@ -495,7 +423,6 @@ public class JetControlFlowProcessor { else { subroutine = null; } - //subroutine = resolveLabel(labelName, labelElement, true); } else { subroutine = builder.getCurrentSubroutine(); @@ -672,7 +599,6 @@ public class JetControlFlowProcessor { if (whenEntry.isElse()) { if (iterator.hasNext()) { -// trace.getErrorHandler().genericError(whenEntry.getNode(), "'else' entry must be the last one in a when-expression"); trace.report(ELSE_MISPLACED_IN_WHEN.on(whenEntry)); } } @@ -769,16 +695,6 @@ public class JetControlFlowProcessor { @Override public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) { -// List delegationSpecifiers = expression.getObjectDeclaration().getDelegationSpecifiers(); -// for (JetDelegationSpecifier delegationSpecifier : delegationSpecifiers) { -// if (delegationSpecifier instanceof JetDelegatorByExpressionSpecifier) { -// JetDelegatorByExpressionSpecifier specifier = (JetDelegatorByExpressionSpecifier) delegationSpecifier; -// JetExpression delegateExpression = specifier.getDelegateExpression(); -// if (delegateExpression != null) { -// value(delegateExpression, false, false); -// } -// } -// } value(expression.getObjectDeclaration(), inCondition); builder.read(expression); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Instruction.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Instruction.java index 156f35debc2..4a2cf3832e6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Instruction.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Instruction.java @@ -13,6 +13,7 @@ public interface Instruction { void setOwner(@NotNull Pseudocode owner); + @NotNull Collection getPreviousInstructions(); @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/InstructionImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/InstructionImpl.java index bcdbd850dcf..65fadb3b5a3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/InstructionImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/InstructionImpl.java @@ -28,6 +28,7 @@ public abstract class InstructionImpl implements Instruction { this.owner = owner; } + @NotNull @Override public Collection getPreviousInstructions() { return previousInstructions; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/NondeterministicJumpInstruction.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/NondeterministicJumpInstruction.java index 20a34886dde..d5e63335ef0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/NondeterministicJumpInstruction.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/NondeterministicJumpInstruction.java @@ -27,7 +27,7 @@ public class NondeterministicJumpInstruction extends AbstractJumpInstruction { } public void setNext(Instruction next) { - this.next = next; + this.next = outgoingEdgeTo(next); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java index 93aa1264354..211abbc4575 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java @@ -75,9 +75,13 @@ public class Pseudocode { } @NotNull - public Collection getInstructions() { + public List getInstructions() { return instructions; } + + public List getLabels() { + return labels; + } public void addExitInstruction(SubroutineExitInstruction exitInstruction) { addInstruction(exitInstruction); @@ -163,170 +167,30 @@ public class Pseudocode { @NotNull private Instruction getJumpTarget(@NotNull Label targetLabel) { - return getTargetInstruction(((PseudocodeLabel) targetLabel).resolve()); + return ((PseudocodeLabel)targetLabel).resolveToInstruction(); + //return getTargetInstruction(((PseudocodeLabel) targetLabel).resolve()); } - @NotNull - private Instruction getTargetInstruction(@NotNull List instructions) { - while (true) { - assert instructions != null; - Instruction targetInstruction = instructions.get(0); - - if (false == targetInstruction instanceof UnconditionalJumpInstruction) { - return targetInstruction; - } - - Label label = ((UnconditionalJumpInstruction) targetInstruction).getTargetLabel(); - instructions = ((PseudocodeLabel)label).resolve(); - } - } +// @NotNull +// private Instruction getTargetInstruction(@NotNull List instructions) { +// while (true) { +// assert instructions != null; +// Instruction targetInstruction = instructions.get(0); +// +// //if (false == targetInstruction instanceof UnconditionalJumpInstruction) { +// return targetInstruction; +// //} +// +//// Label label = ((UnconditionalJumpInstruction) targetInstruction).getTargetLabel(); +//// instructions = ((PseudocodeLabel)label).resolve(); +// } +// } @NotNull private Instruction getNextPosition(int currentPosition) { int targetPosition = currentPosition + 1; assert targetPosition < instructions.size() : currentPosition; - return getTargetInstruction(instructions.subList(targetPosition, instructions.size())); + return instructions.get(targetPosition); + //return getTargetInstruction(instructions.subList(targetPosition, instructions.size())); } - - public void dfsDump(StringBuilder nodes, StringBuilder edges, Map nodeNames) { - dfsDump(nodes, edges, instructions.get(0), nodeNames); - } - - private void dfsDump(StringBuilder nodes, StringBuilder edges, Instruction instruction, Map nodeNames) { - if (nodeNames.containsKey(instruction)) return; - String name = "n" + nodeNames.size(); - nodeNames.put(instruction, name); - nodes.append(name).append(" := ").append(renderName(instruction)); - - } - - private String renderName(Instruction instruction) { - throw new UnsupportedOperationException(); // TODO - } - - public void dumpInstructions(@NotNull StringBuilder out) { - List locals = new ArrayList(); - for (int i = 0, instructionsSize = instructions.size(); i < instructionsSize; i++) { - Instruction instruction = instructions.get(i); - if (instruction instanceof FunctionLiteralValueInstruction) { - FunctionLiteralValueInstruction functionLiteralValueInstruction = (FunctionLiteralValueInstruction) instruction; - locals.add(functionLiteralValueInstruction.getBody()); - } - for (PseudocodeLabel label: labels) { - if (label.getTargetInstructionIndex() == i) { - out.append(label.getName()).append(":\n"); - } - } - out.append(" ").append(instruction).append("\n"); - } - for (Pseudocode local : locals) { - local.dumpInstructions(out); - } - } - - public void dumpEdges(final PrintStream out, final int[] count, final Map nodeToName) { - for (final Instruction fromInst : instructions) { - fromInst.accept(new InstructionVisitor() { - @Override - public void visitFunctionLiteralValue(FunctionLiteralValueInstruction instruction) { - int index = count[0]; -// instruction.getBody().dumpSubgraph(out, "subgraph cluster_" + index, count, "color=blue;\nlabel = \"f" + index + "\";", nodeToName); - printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getBody().instructions.get(0)), null); - visitInstructionWithNext(instruction); - } - - @Override - public void visitUnconditionalJump(UnconditionalJumpInstruction instruction) { - // Nothing - } - - @Override - public void visitJump(AbstractJumpInstruction instruction) { - printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getResolvedTarget()), null); - } - - @Override - public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) { - visitJump(instruction); - printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getNext()), null); - } - - @Override - public void visitReturnValue(ReturnValueInstruction instruction) { - super.visitReturnValue(instruction); - } - - @Override - public void visitReturnNoValue(ReturnNoValueInstruction instruction) { - super.visitReturnNoValue(instruction); - } - - @Override - public void visitConditionalJump(ConditionalJumpInstruction instruction) { - String from = nodeToName.get(instruction); - printEdge(out, from, nodeToName.get(instruction.getNextOnFalse()), "no"); - printEdge(out, from, nodeToName.get(instruction.getNextOnTrue()), "yes"); - } - - @Override - public void visitInstructionWithNext(InstructionWithNext instruction) { - printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getNext()), null); - } - - @Override - public void visitSubroutineExit(SubroutineExitInstruction instruction) { - // Nothing - } - - @Override - public void visitInstruction(Instruction instruction) { - throw new UnsupportedOperationException(instruction.toString()); - } - }); - } - } - - public void dumpNodes(PrintStream out, int[] count, Map nodeToName) { - for (Instruction node : instructions) { - if (node instanceof UnconditionalJumpInstruction) { - continue; - } - String name = "n" + count[0]++; - nodeToName.put(node, name); - String text = node.toString(); - int newline = text.indexOf("\n"); - if (newline >= 0) { - text = text.substring(0, newline); - } - String shape = "box"; - if (node instanceof ConditionalJumpInstruction) { - shape = "diamond"; - } - else if (node instanceof NondeterministicJumpInstruction) { - shape = "Mdiamond"; - } - else if (node instanceof UnsupportedElementInstruction) { - shape = "box, fillcolor=red, style=filled"; - } - else if (node instanceof FunctionLiteralValueInstruction) { - shape = "Mcircle"; - } - else if (node instanceof SubroutineEnterInstruction || node instanceof SubroutineExitInstruction) { - shape = "roundrect, style=rounded"; - } - out.println(name + "[label=\"" + text + "\", shape=" + shape + "];"); - } - } - - private void printEdge(PrintStream out, String from, String to, String label) { - if (label != null) { - label = "[label=\"" + label + "\"]"; - } - else { - label = ""; - } - out.println(from + " -> " + to + label + ";"); - } - - } diff --git a/idea/testData/cfg/ArrayAccess.instructions b/idea/testData/cfg/ArrayAccess.instructions index b2d18a45e79..877a122fb43 100644 --- a/idea/testData/cfg/ArrayAccess.instructions +++ b/idea/testData/cfg/ArrayAccess.instructions @@ -10,29 +10,29 @@ fun foo() { } --------------------- l0: - - r(Array) - r(Array) - w(a) - r(3) - r(4) - r(10) - r(a) - r(=) - w(a[10]) - r(2) - r(10) - r(a) - r(a[10]) - r(100) - r(10) - r(a) - r(a[10]) - r(1) - r(+=) - w(a[10]) + NEXT:[r(Array)] PREV:[] + r(Array) NEXT:[r(Array)] PREV:[] + r(Array) NEXT:[w(a)] PREV:[r(Array)] + w(a) NEXT:[r(3)] PREV:[r(Array)] + r(3) NEXT:[r(4)] PREV:[w(a)] + r(4) NEXT:[r(10)] PREV:[r(3)] + r(10) NEXT:[r(a)] PREV:[r(4)] + r(a) NEXT:[r(=)] PREV:[r(10)] + r(=) NEXT:[w(a[10])] PREV:[r(a)] + w(a[10]) NEXT:[r(2)] PREV:[r(=)] + r(2) NEXT:[r(10)] PREV:[w(a[10])] + r(10) NEXT:[r(a)] PREV:[r(2)] + r(a) NEXT:[r(a[10])] PREV:[r(10)] + r(a[10]) NEXT:[r(100)] PREV:[r(a)] + r(100) NEXT:[r(10)] PREV:[r(a[10])] + r(10) NEXT:[r(a)] PREV:[r(100)] + r(a) NEXT:[r(a[10])] PREV:[r(10)] + r(a[10]) NEXT:[r(1)] PREV:[r(a)] + r(1) NEXT:[r(+=)] PREV:[r(a[10])] + r(+=) NEXT:[w(a[10])] PREV:[r(1)] + w(a[10]) NEXT:[] PREV:[r(+=)] l1: - + NEXT:[] PREV:[w(a[10])] error: - + NEXT:[] PREV:[] ===================== diff --git a/idea/testData/cfg/Assignments.instructions b/idea/testData/cfg/Assignments.instructions index 07ceb36d2c8..671c6729d14 100644 --- a/idea/testData/cfg/Assignments.instructions +++ b/idea/testData/cfg/Assignments.instructions @@ -14,44 +14,44 @@ fun assignments() : Unit { } --------------------- l0: - - r(1) - w(x) - r(2) - w(x) - r(x) - r(2) - r(+=) - w(x) - r(true) - jf(l2) - r(1) - jmp(l3) + NEXT:[r(1)] PREV:[] + r(1) NEXT:[w(x)] PREV:[] + w(x) NEXT:[r(2)] PREV:[r(1)] + r(2) NEXT:[w(x)] PREV:[w(x)] + w(x) NEXT:[r(x)] PREV:[r(2)] + r(x) NEXT:[r(2)] PREV:[w(x)] + r(2) NEXT:[r(+=)] PREV:[r(x)] + r(+=) NEXT:[w(x)] PREV:[r(2)] + w(x) NEXT:[r(true)] PREV:[r(+=)] + r(true) NEXT:[jf(l2)] PREV:[w(x)] + jf(l2) NEXT:[r(2), r(1)] PREV:[r(true)] + r(1) NEXT:[jmp(l3)] PREV:[jf(l2)] + jmp(l3) NEXT:[w(x)] PREV:[r(1)] l2: - r(2) + r(2) NEXT:[w(x)] PREV:[jf(l2)] l3: - w(x) - r(true) - jf(l4) - r(false) + w(x) NEXT:[r(true)] PREV:[jmp(l3), r(2)] + r(true) NEXT:[jf(l4)] PREV:[w(x)] + jf(l4) NEXT:[r(true && false), r(false)] PREV:[r(true)] + r(false) NEXT:[r(true && false)] PREV:[jf(l4)] l4: - r(true && false) - w(y) - r(false) - jf(l5) - r(true) + r(true && false) NEXT:[w(y)] PREV:[jf(l4), r(false)] + w(y) NEXT:[r(false)] PREV:[r(true && false)] + r(false) NEXT:[jf(l5)] PREV:[w(y)] + jf(l5) NEXT:[r(false && true), r(true)] PREV:[r(false)] + r(true) NEXT:[r(false && true)] PREV:[jf(l5)] l5: - r(false && true) - w(z) - r(Test) - r(Test()) - w(t) - r(1) - r(t) - r(=) - w(t.x) + r(false && true) NEXT:[w(z)] PREV:[jf(l5), r(true)] + w(z) NEXT:[r(Test)] PREV:[r(false && true)] + r(Test) NEXT:[r(Test())] PREV:[w(z)] + r(Test()) NEXT:[w(t)] PREV:[r(Test)] + w(t) NEXT:[r(1)] PREV:[r(Test())] + r(1) NEXT:[r(t)] PREV:[w(t)] + r(t) NEXT:[r(=)] PREV:[r(1)] + r(=) NEXT:[w(t.x)] PREV:[r(t)] + w(t.x) NEXT:[] PREV:[r(=)] l1: - + NEXT:[] PREV:[w(t.x)] error: - + NEXT:[] PREV:[] ===================== diff --git a/idea/testData/cfg/Basic.instructions b/idea/testData/cfg/Basic.instructions index 43e9c080245..f8f34d1dc84 100644 --- a/idea/testData/cfg/Basic.instructions +++ b/idea/testData/cfg/Basic.instructions @@ -2,12 +2,12 @@ {1} --------------------- l2: - - r(1) + NEXT:[r(1)] PREV:[] + r(1) NEXT:[] PREV:[] l3: - + NEXT:[] PREV:[r(1)] error: - + NEXT:[] PREV:[] ===================== == f == fun f(a : Boolean) : Unit { @@ -29,86 +29,86 @@ fun f(a : Boolean) : Unit { } --------------------- l0: - - r(1) - r(a) - r(2) - r(lng) - r(2.lng) - r(a) - r(3) - r(foo) - r(foo(a, 3)) - r(genfun) - r(genfun()) - rf({1}) - r(flfun) - r(flfun {1}) - r(3) - r(4) - r(equals) - r(equals(4)) - r(3.equals(4)) - r(3) - r(4) - r(equals) - r(3 equals 4) - r(1) - r(2) - r(+) - r(1 + 2) - r(a) - jf(l4) - r(true) + NEXT:[r(1)] PREV:[] + r(1) NEXT:[r(a)] PREV:[] + r(a) NEXT:[r(2)] PREV:[r(1)] + r(2) NEXT:[r(lng)] PREV:[r(a)] + r(lng) NEXT:[r(2.lng)] PREV:[r(2)] + r(2.lng) NEXT:[r(a)] PREV:[r(lng)] + r(a) NEXT:[r(3)] PREV:[r(2.lng)] + r(3) NEXT:[r(foo)] PREV:[r(a)] + r(foo) NEXT:[r(foo(a, 3))] PREV:[r(3)] + r(foo(a, 3)) NEXT:[r(genfun)] PREV:[r(foo)] + r(genfun) NEXT:[r(genfun())] PREV:[r(foo(a, 3))] + r(genfun()) NEXT:[rf({1})] PREV:[r(genfun)] + rf({1}) NEXT:[r(flfun)] PREV:[r(genfun())] + r(flfun) NEXT:[r(flfun {1})] PREV:[rf({1})] + r(flfun {1}) NEXT:[r(3)] PREV:[r(flfun)] + r(3) NEXT:[r(4)] PREV:[r(flfun {1})] + r(4) NEXT:[r(equals)] PREV:[r(3)] + r(equals) NEXT:[r(equals(4))] PREV:[r(4)] + r(equals(4)) NEXT:[r(3.equals(4))] PREV:[r(equals)] + r(3.equals(4)) NEXT:[r(3)] PREV:[r(equals(4))] + r(3) NEXT:[r(4)] PREV:[r(3.equals(4))] + r(4) NEXT:[r(equals)] PREV:[r(3)] + r(equals) NEXT:[r(3 equals 4)] PREV:[r(4)] + r(3 equals 4) NEXT:[r(1)] PREV:[r(equals)] + r(1) NEXT:[r(2)] PREV:[r(3 equals 4)] + r(2) NEXT:[r(+)] PREV:[r(1)] + r(+) NEXT:[r(1 + 2)] PREV:[r(2)] + r(1 + 2) NEXT:[r(a)] PREV:[r(+)] + r(a) NEXT:[jf(l4)] PREV:[r(1 + 2)] + jf(l4) NEXT:[r(a && true), r(true)] PREV:[r(a)] + r(true) NEXT:[r(a && true)] PREV:[jf(l4)] l4: - r(a && true) - r(a) - jt(l5) - r(false) + r(a && true) NEXT:[r(a)] PREV:[jf(l4), r(true)] + r(a) NEXT:[jt(l5)] PREV:[r(a && true)] + jt(l5) NEXT:[r(false), r(a || false)] PREV:[r(a)] + r(false) NEXT:[r(a || false)] PREV:[jt(l5)] l5: - r(a || false) + r(a || false) NEXT:[] PREV:[jt(l5), r(false)] l1: - + NEXT:[] PREV:[r(a || false)] error: - + NEXT:[] PREV:[] l2: - - r(1) + NEXT:[r(1)] PREV:[] + r(1) NEXT:[] PREV:[] l3: - + NEXT:[] PREV:[r(1)] error: - + NEXT:[] PREV:[] ===================== == foo == fun foo(a : Boolean, b : Int) : Unit {} --------------------- l0: - - read (Unit) + NEXT:[read (Unit)] PREV:[] + read (Unit) NEXT:[] PREV:[] l1: - + NEXT:[] PREV:[read (Unit)] error: - + NEXT:[] PREV:[] ===================== == genfun == fun genfun() : Unit {} --------------------- l0: - - read (Unit) + NEXT:[read (Unit)] PREV:[] + read (Unit) NEXT:[] PREV:[] l1: - + NEXT:[] PREV:[read (Unit)] error: - + NEXT:[] PREV:[] ===================== == flfun == fun flfun(f : fun () : Any) : Unit {} --------------------- l0: - - read (Unit) + NEXT:[read (Unit)] PREV:[] + read (Unit) NEXT:[] PREV:[] l1: - + NEXT:[] PREV:[read (Unit)] error: - + NEXT:[] PREV:[] ===================== diff --git a/idea/testData/cfg/EmptyFunction.instructions b/idea/testData/cfg/EmptyFunction.instructions index 04fbe42e40a..36b5c7f0fc2 100644 --- a/idea/testData/cfg/EmptyFunction.instructions +++ b/idea/testData/cfg/EmptyFunction.instructions @@ -2,10 +2,10 @@ fun empty() {} --------------------- l0: - - read (Unit) + NEXT:[read (Unit)] PREV:[] + read (Unit) NEXT:[] PREV:[] l1: - + NEXT:[] PREV:[read (Unit)] error: - + NEXT:[] PREV:[] ===================== diff --git a/idea/testData/cfg/FailFunction.instructions b/idea/testData/cfg/FailFunction.instructions index 716bd2a6536..be079a574d4 100644 --- a/idea/testData/cfg/FailFunction.instructions +++ b/idea/testData/cfg/FailFunction.instructions @@ -4,16 +4,16 @@ fun fail() : Nothing { } --------------------- l0: - - r(java) - r(lang) - r(java.lang) - r(RuntimeException) - r(RuntimeException()) - r(java.lang.RuntimeException()) - jmp(error) + NEXT:[r(java)] PREV:[] + r(java) NEXT:[r(lang)] PREV:[] + r(lang) NEXT:[r(java.lang)] PREV:[r(java)] + r(java.lang) NEXT:[r(RuntimeException)] PREV:[r(lang)] + r(RuntimeException) NEXT:[r(RuntimeException())] PREV:[r(java.lang)] + r(RuntimeException()) NEXT:[r(java.lang.RuntimeException())] PREV:[r(RuntimeException)] + r(java.lang.RuntimeException()) NEXT:[jmp(error)] PREV:[r(RuntimeException())] + jmp(error) NEXT:[] PREV:[r(java.lang.RuntimeException())] l1: - + NEXT:[] PREV:[] error: - + NEXT:[] PREV:[jmp(error)] ===================== diff --git a/idea/testData/cfg/Finally.instructions b/idea/testData/cfg/Finally.instructions index a5c381bc864..527b5f23b14 100644 --- a/idea/testData/cfg/Finally.instructions +++ b/idea/testData/cfg/Finally.instructions @@ -8,15 +8,15 @@ fun t3() { } --------------------- l0: - - jmp?(l2) - r(1) + NEXT:[jmp?(l2)] PREV:[] + jmp?(l2) NEXT:[r(2), r(1)] PREV:[] + r(1) NEXT:[r(2)] PREV:[jmp?(l2)] l2: - r(2) + r(2) NEXT:[] PREV:[jmp?(l2), r(1)] l1: - + NEXT:[] PREV:[r(2)] error: - + NEXT:[] PREV:[] ===================== == t3 == fun t3() { @@ -31,26 +31,26 @@ fun t3() { } --------------------- l0: - - jmp?(l2) - r(1) - r(2) - r(3) - r(>) - r(2 > 3) - jf(l3) - r(2) - ret l1 - jmp(l4) + NEXT:[jmp?(l2)] PREV:[] + jmp?(l2) NEXT:[r(2), r(1)] PREV:[] + r(1) NEXT:[r(2)] PREV:[jmp?(l2)] + r(2) NEXT:[r(3)] PREV:[r(1)] + r(3) NEXT:[r(>)] PREV:[r(2)] + r(>) NEXT:[r(2 > 3)] PREV:[r(3)] + r(2 > 3) NEXT:[jf(l3)] PREV:[r(>)] + jf(l3) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)] + r(2) NEXT:[ret l1] PREV:[jf(l3)] + ret l1 NEXT:[] PREV:[r(2)] + jmp(l4) NEXT:[r(2)] PREV:[] l3: - read (Unit) + read (Unit) NEXT:[r(2)] PREV:[jf(l3)] l2: l4: - r(2) + r(2) NEXT:[] PREV:[jmp?(l2), jmp(l4), read (Unit)] l1: - + NEXT:[] PREV:[ret l1, r(2)] error: - + NEXT:[] PREV:[] ===================== == anonymous_0 == { () => @@ -60,21 +60,21 @@ error: } --------------------- l3: - - r(2) - r(3) - r(>) - r(2 > 3) - jf(l5) - ret l4 - jmp(l6) + NEXT:[r(2)] PREV:[] + r(2) NEXT:[r(3)] PREV:[] + r(3) NEXT:[r(>)] PREV:[r(2)] + r(>) NEXT:[r(2 > 3)] PREV:[r(3)] + r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)] + jf(l5) NEXT:[read (Unit), ret l4] PREV:[r(2 > 3)] + ret l4 NEXT:[] PREV:[jf(l5)] + jmp(l6) NEXT:[] PREV:[] l5: - read (Unit) + read (Unit) NEXT:[] PREV:[jf(l5)] l4: l6: - + NEXT:[] PREV:[ret l4, jmp(l6), read (Unit)] error: - + NEXT:[] PREV:[] ===================== == t3 == fun t3() { @@ -91,36 +91,36 @@ fun t3() { } --------------------- l0: - - jmp?(l2) - r(1) - rf({ () => - if (2 > 3) { - return@ - } - }) + NEXT:[jmp?(l2)] PREV:[] + jmp?(l2) NEXT:[r(2), r(1)] PREV:[] + r(1) NEXT:[rf({ () => if (2 > 3) { retu..)] PREV:[jmp?(l2)] + rf({ () => + if (2 > 3) { + return@ + } + }) NEXT:[r(2)] PREV:[r(1)] l2: - r(2) + r(2) NEXT:[] PREV:[jmp?(l2), rf({ () => if (2 > 3) { retu..)] l1: - + NEXT:[] PREV:[r(2)] error: - + NEXT:[] PREV:[] l3: - - r(2) - r(3) - r(>) - r(2 > 3) - jf(l5) - ret l4 - jmp(l6) + NEXT:[r(2)] PREV:[] + r(2) NEXT:[r(3)] PREV:[] + r(3) NEXT:[r(>)] PREV:[r(2)] + r(>) NEXT:[r(2 > 3)] PREV:[r(3)] + r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)] + jf(l5) NEXT:[read (Unit), ret l4] PREV:[r(2 > 3)] + ret l4 NEXT:[] PREV:[jf(l5)] + jmp(l6) NEXT:[] PREV:[] l5: - read (Unit) + read (Unit) NEXT:[] PREV:[jf(l5)] l4: l6: - + NEXT:[] PREV:[ret l4, jmp(l6), read (Unit)] error: - + NEXT:[] PREV:[] ===================== == anonymous_1 == { () => @@ -135,26 +135,26 @@ error: } --------------------- l2: - - jmp?(l4) - r(1) - r(2) - r(3) - r(>) - r(2 > 3) - jf(l5) - r(2) - ret l3 - jmp(l6) + NEXT:[jmp?(l4)] PREV:[] + jmp?(l4) NEXT:[r(2), r(1)] PREV:[] + r(1) NEXT:[r(2)] PREV:[jmp?(l4)] + r(2) NEXT:[r(3)] PREV:[r(1)] + r(3) NEXT:[r(>)] PREV:[r(2)] + r(>) NEXT:[r(2 > 3)] PREV:[r(3)] + r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)] + jf(l5) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)] + r(2) NEXT:[ret l3] PREV:[jf(l5)] + ret l3 NEXT:[] PREV:[r(2)] + jmp(l6) NEXT:[r(2)] PREV:[] l5: - read (Unit) + read (Unit) NEXT:[r(2)] PREV:[jf(l5)] l4: l6: - r(2) + r(2) NEXT:[] PREV:[jmp?(l4), jmp(l6), read (Unit)] l3: - + NEXT:[] PREV:[ret l3, r(2)] error: - + NEXT:[] PREV:[] ===================== == t3 == fun t3() { @@ -171,42 +171,42 @@ fun t3() { } --------------------- l0: - - rf({ () => - try { - 1 - if (2 > 3) { - return@ - } - } finally { - 2 - } - }) + NEXT:[rf({ () => try { 1 if (2 > 3..)] PREV:[] + rf({ () => + try { + 1 + if (2 > 3) { + return@ + } + } finally { + 2 + } + }) NEXT:[] PREV:[] l1: - + NEXT:[] PREV:[rf({ () => try { 1 if (2 > 3..)] error: - + NEXT:[] PREV:[] l2: - - jmp?(l4) - r(1) - r(2) - r(3) - r(>) - r(2 > 3) - jf(l5) - r(2) - ret l3 - jmp(l6) + NEXT:[jmp?(l4)] PREV:[] + jmp?(l4) NEXT:[r(2), r(1)] PREV:[] + r(1) NEXT:[r(2)] PREV:[jmp?(l4)] + r(2) NEXT:[r(3)] PREV:[r(1)] + r(3) NEXT:[r(>)] PREV:[r(2)] + r(>) NEXT:[r(2 > 3)] PREV:[r(3)] + r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)] + jf(l5) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)] + r(2) NEXT:[ret l3] PREV:[jf(l5)] + ret l3 NEXT:[] PREV:[r(2)] + jmp(l6) NEXT:[r(2)] PREV:[] l5: - read (Unit) + read (Unit) NEXT:[r(2)] PREV:[jf(l5)] l4: l6: - r(2) + r(2) NEXT:[] PREV:[jmp?(l4), jmp(l6), read (Unit)] l3: - + NEXT:[] PREV:[ret l3, r(2)] error: - + NEXT:[] PREV:[] ===================== == t3 == fun t3() { @@ -223,34 +223,34 @@ fun t3() { } --------------------- l0: - + NEXT:[r(true)] PREV:[] l2: l5: - r(true) - jf(l3) + r(true) NEXT:[jf(l3)] PREV:[, jmp(l2)] + jf(l3) NEXT:[read (Unit), jmp?(l6)] PREV:[r(true)] l4: - jmp?(l6) - r(1) - r(2) - r(3) - r(>) - r(2 > 3) - jf(l7) - r(2) - jmp(l3) - jmp(l8) + jmp?(l6) NEXT:[r(2), r(1)] PREV:[jf(l3)] + r(1) NEXT:[r(2)] PREV:[jmp?(l6)] + r(2) NEXT:[r(3)] PREV:[r(1)] + r(3) NEXT:[r(>)] PREV:[r(2)] + r(>) NEXT:[r(2 > 3)] PREV:[r(3)] + r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)] + jf(l7) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)] + r(2) NEXT:[jmp(l3)] PREV:[jf(l7)] + jmp(l3) NEXT:[read (Unit)] PREV:[r(2)] + jmp(l8) NEXT:[r(2)] PREV:[] l7: - read (Unit) + read (Unit) NEXT:[r(2)] PREV:[jf(l7)] l6: l8: - r(2) - jmp(l2) + r(2) NEXT:[jmp(l2)] PREV:[jmp?(l6), jmp(l8), read (Unit)] + jmp(l2) NEXT:[r(true)] PREV:[r(2)] l3: - read (Unit) + read (Unit) NEXT:[] PREV:[jf(l3), jmp(l3)] l1: - + NEXT:[] PREV:[read (Unit)] error: - + NEXT:[] PREV:[] ===================== == t3 == fun t3() { @@ -268,34 +268,34 @@ fun t3() { } --------------------- l0: - - jmp?(l2) + NEXT:[jmp?(l2)] PREV:[] + jmp?(l2) NEXT:[r(2), r(true)] PREV:[] l3: l6: - r(true) - jf(l4) + r(true) NEXT:[jf(l4)] PREV:[jmp?(l2), jmp(l3)] + jf(l4) NEXT:[read (Unit), r(1)] PREV:[r(true)] l5: - r(1) - r(2) - r(3) - r(>) - r(2 > 3) - jf(l7) - jmp(l4) - jmp(l8) + r(1) NEXT:[r(2)] PREV:[jf(l4)] + r(2) NEXT:[r(3)] PREV:[r(1)] + r(3) NEXT:[r(>)] PREV:[r(2)] + r(>) NEXT:[r(2 > 3)] PREV:[r(3)] + r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)] + jf(l7) NEXT:[read (Unit), jmp(l4)] PREV:[r(2 > 3)] + jmp(l4) NEXT:[read (Unit)] PREV:[jf(l7)] + jmp(l8) NEXT:[jmp(l3)] PREV:[] l7: - read (Unit) + read (Unit) NEXT:[jmp(l3)] PREV:[jf(l7)] l8: - jmp(l3) + jmp(l3) NEXT:[r(true)] PREV:[jmp(l8), read (Unit)] l4: - read (Unit) - r(5) + read (Unit) NEXT:[r(5)] PREV:[jf(l4), jmp(l4)] + r(5) NEXT:[r(2)] PREV:[read (Unit)] l2: - r(2) + r(2) NEXT:[] PREV:[jmp?(l2), r(5)] l1: - + NEXT:[] PREV:[r(2)] error: - + NEXT:[] PREV:[] ===================== == t3 == fun t3() { @@ -312,33 +312,33 @@ fun t3() { } --------------------- l0: - - jmp?(l2) + NEXT:[jmp?(l2)] PREV:[] + jmp?(l2) NEXT:[r(2), r(true)] PREV:[] l3: l6: - r(true) - jf(l4) + r(true) NEXT:[jf(l4)] PREV:[jmp?(l2), jmp(l3)] + jf(l4) NEXT:[read (Unit), r(1)] PREV:[r(true)] l5: - r(1) - r(2) - r(3) - r(>) - r(2 > 3) - jf(l7) - jmp(l4) - jmp(l8) + r(1) NEXT:[r(2)] PREV:[jf(l4)] + r(2) NEXT:[r(3)] PREV:[r(1)] + r(3) NEXT:[r(>)] PREV:[r(2)] + r(>) NEXT:[r(2 > 3)] PREV:[r(3)] + r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)] + jf(l7) NEXT:[read (Unit), jmp(l4)] PREV:[r(2 > 3)] + jmp(l4) NEXT:[read (Unit)] PREV:[jf(l7)] + jmp(l8) NEXT:[jmp(l3)] PREV:[] l7: - read (Unit) + read (Unit) NEXT:[jmp(l3)] PREV:[jf(l7)] l8: - jmp(l3) + jmp(l3) NEXT:[r(true)] PREV:[jmp(l8), read (Unit)] l4: - read (Unit) + read (Unit) NEXT:[r(2)] PREV:[jf(l4), jmp(l4)] l2: - r(2) + r(2) NEXT:[] PREV:[jmp?(l2), read (Unit)] l1: - + NEXT:[] PREV:[r(2)] error: - + NEXT:[] PREV:[] ===================== == t3 == fun t3(a : Int) { @@ -355,37 +355,37 @@ fun t3(a : Int) { } --------------------- l0: - - r(1) - r(a) - r(..) - r(1..a) + NEXT:[r(1)] PREV:[] + r(1) NEXT:[r(a)] PREV:[] + r(a) NEXT:[r(..)] PREV:[r(1)] + r(..) NEXT:[r(1..a)] PREV:[r(a)] + r(1..a) NEXT:[jmp?(l2)] PREV:[r(..)] l3: - jmp?(l2) + jmp?(l2) NEXT:[read (Unit), jmp?(l6)] PREV:[r(1..a)] l4: l5: - jmp?(l6) - r(1) - r(2) - r(3) - r(>) - r(2 > 3) - jf(l7) - r(2) - jmp(l4) - jmp(l8) + jmp?(l6) NEXT:[r(2), r(1)] PREV:[jmp?(l2), jmp(l4), jmp?(l4)] + r(1) NEXT:[r(2)] PREV:[jmp?(l6)] + r(2) NEXT:[r(3)] PREV:[r(1)] + r(3) NEXT:[r(>)] PREV:[r(2)] + r(>) NEXT:[r(2 > 3)] PREV:[r(3)] + r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)] + jf(l7) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)] + r(2) NEXT:[jmp(l4)] PREV:[jf(l7)] + jmp(l4) NEXT:[jmp?(l6)] PREV:[r(2)] + jmp(l8) NEXT:[r(2)] PREV:[] l7: - read (Unit) + read (Unit) NEXT:[r(2)] PREV:[jf(l7)] l6: l8: - r(2) - jmp?(l4) + r(2) NEXT:[jmp?(l4)] PREV:[jmp?(l6), jmp(l8), read (Unit)] + jmp?(l4) NEXT:[jmp?(l6), read (Unit)] PREV:[r(2)] l2: - read (Unit) + read (Unit) NEXT:[] PREV:[jmp?(l2), jmp?(l4)] l1: - + NEXT:[] PREV:[read (Unit)] error: - + NEXT:[] PREV:[] ===================== == t3 == fun t3(a : Int) { @@ -403,37 +403,37 @@ fun t3(a : Int) { } --------------------- l0: - - jmp?(l2) - r(1) - r(a) - r(..) - r(1..a) + NEXT:[jmp?(l2)] PREV:[] + jmp?(l2) NEXT:[r(2), r(1)] PREV:[] + r(1) NEXT:[r(a)] PREV:[jmp?(l2)] + r(a) NEXT:[r(..)] PREV:[r(1)] + r(..) NEXT:[r(1..a)] PREV:[r(a)] + r(1..a) NEXT:[jmp?(l3)] PREV:[r(..)] l4: - jmp?(l3) + jmp?(l3) NEXT:[read (Unit), r(1)] PREV:[r(1..a)] l5: l6: - r(1) - r(2) - r(3) - r(>) - r(2 > 3) - jf(l7) - jmp(l5) - jmp(l8) + r(1) NEXT:[r(2)] PREV:[jmp?(l3), jmp(l5), jmp?(l5)] + r(2) NEXT:[r(3)] PREV:[r(1)] + r(3) NEXT:[r(>)] PREV:[r(2)] + r(>) NEXT:[r(2 > 3)] PREV:[r(3)] + r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)] + jf(l7) NEXT:[read (Unit), jmp(l5)] PREV:[r(2 > 3)] + jmp(l5) NEXT:[r(1)] PREV:[jf(l7)] + jmp(l8) NEXT:[jmp?(l5)] PREV:[] l7: - read (Unit) + read (Unit) NEXT:[jmp?(l5)] PREV:[jf(l7)] l8: - jmp?(l5) + jmp?(l5) NEXT:[r(1), read (Unit)] PREV:[jmp(l8), read (Unit)] l3: - read (Unit) - r(5) + read (Unit) NEXT:[r(5)] PREV:[jmp?(l3), jmp?(l5)] + r(5) NEXT:[r(2)] PREV:[read (Unit)] l2: - r(2) + r(2) NEXT:[] PREV:[jmp?(l2), r(5)] l1: - + NEXT:[] PREV:[r(2)] error: - + NEXT:[] PREV:[] ===================== == t3 == fun t3(a : Int) { @@ -450,36 +450,36 @@ fun t3(a : Int) { } --------------------- l0: - - jmp?(l2) - r(1) - r(a) - r(..) - r(1..a) + NEXT:[jmp?(l2)] PREV:[] + jmp?(l2) NEXT:[r(2), r(1)] PREV:[] + r(1) NEXT:[r(a)] PREV:[jmp?(l2)] + r(a) NEXT:[r(..)] PREV:[r(1)] + r(..) NEXT:[r(1..a)] PREV:[r(a)] + r(1..a) NEXT:[jmp?(l3)] PREV:[r(..)] l4: - jmp?(l3) + jmp?(l3) NEXT:[read (Unit), r(1)] PREV:[r(1..a)] l5: l6: - r(1) - r(2) - r(3) - r(>) - r(2 > 3) - jf(l7) - jmp(l5) - jmp(l8) + r(1) NEXT:[r(2)] PREV:[jmp?(l3), jmp(l5), jmp?(l5)] + r(2) NEXT:[r(3)] PREV:[r(1)] + r(3) NEXT:[r(>)] PREV:[r(2)] + r(>) NEXT:[r(2 > 3)] PREV:[r(3)] + r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)] + jf(l7) NEXT:[read (Unit), jmp(l5)] PREV:[r(2 > 3)] + jmp(l5) NEXT:[r(1)] PREV:[jf(l7)] + jmp(l8) NEXT:[jmp?(l5)] PREV:[] l7: - read (Unit) + read (Unit) NEXT:[jmp?(l5)] PREV:[jf(l7)] l8: - jmp?(l5) + jmp?(l5) NEXT:[r(1), read (Unit)] PREV:[jmp(l8), read (Unit)] l3: - read (Unit) + read (Unit) NEXT:[r(2)] PREV:[jmp?(l3), jmp?(l5)] l2: - r(2) + r(2) NEXT:[] PREV:[jmp?(l2), read (Unit)] l1: - + NEXT:[] PREV:[r(2)] error: - + NEXT:[] PREV:[] ===================== == tf == fun tf() { @@ -492,17 +492,17 @@ fun tf() { } --------------------- l0: - - jmp?(l2) - r(1) - r(2) - ret(*) l1 - ret(*) l1 + NEXT:[jmp?(l2)] PREV:[] + jmp?(l2) NEXT:[r(2), r(1)] PREV:[] + r(1) NEXT:[r(2)] PREV:[jmp?(l2)] + r(2) NEXT:[ret(*) l1] PREV:[r(1)] + ret(*) l1 NEXT:[] PREV:[r(2)] + ret(*) l1 NEXT:[] PREV:[] l2: - r(2) - ret(*) l1 + r(2) NEXT:[ret(*) l1] PREV:[jmp?(l2)] + ret(*) l1 NEXT:[] PREV:[r(2)] l1: - + NEXT:[] PREV:[ret(*) l1, ret(*) l1, ret(*) l1] error: - + NEXT:[] PREV:[] ===================== diff --git a/idea/testData/cfg/LazyBooleans.instructions b/idea/testData/cfg/LazyBooleans.instructions index d5aaf8eed74..8c477e17313 100644 --- a/idea/testData/cfg/LazyBooleans.instructions +++ b/idea/testData/cfg/LazyBooleans.instructions @@ -18,55 +18,55 @@ fun lazyBooleans(a : Boolean, b : Boolean) : Unit { } --------------------- l0: - - r(a) - jf(l2) - r(1) - jmp(l3) + NEXT:[r(a)] PREV:[] + r(a) NEXT:[jf(l2)] PREV:[] + jf(l2) NEXT:[r(2), r(1)] PREV:[r(a)] + r(1) NEXT:[jmp(l3)] PREV:[jf(l2)] + jmp(l3) NEXT:[r(3)] PREV:[r(1)] l2: - r(2) + r(2) NEXT:[r(3)] PREV:[jf(l2)] l3: - r(3) - r(a) - jf(l4) - r(b) + r(3) NEXT:[r(a)] PREV:[jmp(l3), r(2)] + r(a) NEXT:[jf(l4)] PREV:[r(3)] + jf(l4) NEXT:[jf(l5), r(b)] PREV:[r(a)] + r(b) NEXT:[jf(l5)] PREV:[jf(l4)] l4: - jf(l5) - r(5) - jmp(l6) + jf(l5) NEXT:[r(6), r(5)] PREV:[jf(l4), r(b)] + r(5) NEXT:[jmp(l6)] PREV:[jf(l5)] + jmp(l6) NEXT:[r(7)] PREV:[r(5)] l5: - r(6) + r(6) NEXT:[r(7)] PREV:[jf(l5)] l6: - r(7) - r(a) - jt(l7) - r(b) + r(7) NEXT:[r(a)] PREV:[jmp(l6), r(6)] + r(a) NEXT:[jt(l7)] PREV:[r(7)] + jt(l7) NEXT:[r(b), jf(l8)] PREV:[r(a)] + r(b) NEXT:[jf(l8)] PREV:[jt(l7)] l7: - jf(l8) - r(8) - jmp(l9) + jf(l8) NEXT:[r(9), r(8)] PREV:[jt(l7), r(b)] + r(8) NEXT:[jmp(l9)] PREV:[jf(l8)] + jmp(l9) NEXT:[r(10)] PREV:[r(8)] l8: - r(9) + r(9) NEXT:[r(10)] PREV:[jf(l8)] l9: - r(10) - r(a) - jf(l10) - r(11) - jmp(l11) + r(10) NEXT:[r(a)] PREV:[jmp(l9), r(9)] + r(a) NEXT:[jf(l10)] PREV:[r(10)] + jf(l10) NEXT:[read (Unit), r(11)] PREV:[r(a)] + r(11) NEXT:[jmp(l11)] PREV:[jf(l10)] + jmp(l11) NEXT:[r(12)] PREV:[r(11)] l10: - read (Unit) + read (Unit) NEXT:[r(12)] PREV:[jf(l10)] l11: - r(12) - r(a) - jf(l12) - read (Unit) - jmp(l13) + r(12) NEXT:[r(a)] PREV:[jmp(l11), read (Unit)] + r(a) NEXT:[jf(l12)] PREV:[r(12)] + jf(l12) NEXT:[r(13), read (Unit)] PREV:[r(a)] + read (Unit) NEXT:[jmp(l13)] PREV:[jf(l12)] + jmp(l13) NEXT:[r(14)] PREV:[read (Unit)] l12: - r(13) + r(13) NEXT:[r(14)] PREV:[jf(l12)] l13: - r(14) + r(14) NEXT:[] PREV:[jmp(l13), r(13)] l1: - + NEXT:[] PREV:[r(14)] error: - + NEXT:[] PREV:[] ===================== diff --git a/idea/testData/cfg/Nonlocals.instructions b/idea/testData/cfg/Nonlocals.instructions index ba6a27c536e..080be40b5af 100644 --- a/idea/testData/cfg/Nonlocals.instructions +++ b/idea/testData/cfg/Nonlocals.instructions @@ -5,19 +5,19 @@ fun foo() { } --------------------- l6: - - r(b) - jf(l8) - r(1) - ret(*) l5 - jmp(l9) + NEXT:[r(b)] PREV:[] + r(b) NEXT:[jf(l8)] PREV:[] + jf(l8) NEXT:[read (Unit), r(1)] PREV:[r(b)] + r(1) NEXT:[ret(*) l5] PREV:[jf(l8)] + ret(*) l5 NEXT:[] PREV:[r(1)] + jmp(l9) NEXT:[] PREV:[] l8: - read (Unit) + read (Unit) NEXT:[] PREV:[jf(l8)] l7: l9: - + NEXT:[] PREV:[jmp(l9), read (Unit)] error: - + NEXT:[] PREV:[] ===================== == anonymous_0 == {a => @@ -31,14 +31,14 @@ error: } --------------------- l4: - - r(2) - r(5) - ret(*) l5 + NEXT:[r(2)] PREV:[] + r(2) NEXT:[r(5)] PREV:[] + r(5) NEXT:[ret(*) l5] PREV:[r(2)] + ret(*) l5 NEXT:[] PREV:[r(5)] l5: - + NEXT:[] PREV:[ret(*) l5, ret(*) l5] error: - + NEXT:[] PREV:[] ===================== == nonlocals1 == fun nonlocals1(a : Boolean, b : Boolean) : Any? { @@ -60,39 +60,39 @@ fun nonlocals1(a : Boolean, b : Boolean) : Any? { } --------------------- l0: - - r(a) - jf(l2) - r(1) - ret(*) l1 - jmp(l3) + NEXT:[r(a)] PREV:[] + r(a) NEXT:[jf(l2)] PREV:[] + jf(l2) NEXT:[read (Unit), r(1)] PREV:[r(a)] + r(1) NEXT:[ret(*) l1] PREV:[jf(l2)] + ret(*) l1 NEXT:[] PREV:[r(1)] + jmp(l3) NEXT:[r(1)] PREV:[] l2: - read (Unit) + read (Unit) NEXT:[r(1)] PREV:[jf(l2)] l3: - r(1) - rf({a => - 2 - fun foo() { - if (b) - return@a 1 - } - - return@a 5; - }) - r(1) - r(lng) - r(1.lng) + r(1) NEXT:[rf({a => 2 fun foo() { if (b..)] PREV:[jmp(l3), read (Unit)] + rf({a => + 2 + fun foo() { + if (b) + return@a 1 + } + + return@a 5; + }) NEXT:[r(1)] PREV:[r(1)] + r(1) NEXT:[r(lng)] PREV:[rf({a => 2 fun foo() { if (b..)] + r(lng) NEXT:[r(1.lng)] PREV:[r(1)] + r(1.lng) NEXT:[] PREV:[r(lng)] l1: - + NEXT:[] PREV:[ret(*) l1, r(1.lng)] error: - + NEXT:[] PREV:[] l4: - - r(2) - r(5) - ret(*) l5 + NEXT:[r(2)] PREV:[] + r(2) NEXT:[r(5)] PREV:[] + r(5) NEXT:[ret(*) l5] PREV:[r(2)] + ret(*) l5 NEXT:[] PREV:[r(5)] l5: - + NEXT:[] PREV:[ret(*) l5, ret(*) l5] error: - + NEXT:[] PREV:[] ===================== diff --git a/idea/testData/cfg/OnlyWhileInFunctionBody.instructions b/idea/testData/cfg/OnlyWhileInFunctionBody.instructions index 4da6384a0b2..c0e4641ad03 100644 --- a/idea/testData/cfg/OnlyWhileInFunctionBody.instructions +++ b/idea/testData/cfg/OnlyWhileInFunctionBody.instructions @@ -6,23 +6,23 @@ fun main() { } --------------------- l0: - + NEXT:[r(1)] PREV:[] l2: l5: - r(1) - r(0) - r(>) - r(1 > 0) - jf(l3) + r(1) NEXT:[r(0)] PREV:[, jmp(l2)] + r(0) NEXT:[r(>)] PREV:[r(1)] + r(>) NEXT:[r(1 > 0)] PREV:[r(0)] + r(1 > 0) NEXT:[jf(l3)] PREV:[r(>)] + jf(l3) NEXT:[read (Unit), r(2)] PREV:[r(1 > 0)] l4: - r(2) - jmp(l2) + r(2) NEXT:[jmp(l2)] PREV:[jf(l3)] + jmp(l2) NEXT:[r(1)] PREV:[r(2)] l3: - read (Unit) + read (Unit) NEXT:[] PREV:[jf(l3)] l1: - + NEXT:[] PREV:[read (Unit)] error: - + NEXT:[] PREV:[] ===================== == dowhile == fun dowhile() { @@ -31,20 +31,20 @@ fun dowhile() { } --------------------- l0: - + NEXT:[ret l1] PREV:[] l2: l4: - ret l1 + ret l1 NEXT:[] PREV:[, jt(l2)] l5: - r(1) - r(0) - r(>) - r(1 > 0) - jt(l2) + r(1) NEXT:[r(0)] PREV:[] + r(0) NEXT:[r(>)] PREV:[r(1)] + r(>) NEXT:[r(1 > 0)] PREV:[r(0)] + r(1 > 0) NEXT:[jt(l2)] PREV:[r(>)] + jt(l2) NEXT:[read (Unit), ret l1] PREV:[r(1 > 0)] l3: - read (Unit) + read (Unit) NEXT:[] PREV:[jt(l2)] l1: - + NEXT:[] PREV:[ret l1, read (Unit)] error: - + NEXT:[] PREV:[] ===================== diff --git a/idea/testData/cfg/ReturnFromExpression.instructions b/idea/testData/cfg/ReturnFromExpression.instructions index fb3a770b768..c097530ba85 100644 --- a/idea/testData/cfg/ReturnFromExpression.instructions +++ b/idea/testData/cfg/ReturnFromExpression.instructions @@ -4,15 +4,15 @@ fun blockAndAndMismatch() : Boolean { } --------------------- l0: - - r(false) - jt(l2) - r(false) - ret(*) l1 + NEXT:[r(false)] PREV:[] + r(false) NEXT:[jt(l2)] PREV:[] + jt(l2) NEXT:[r(false), r(false || (return false))] PREV:[r(false)] + r(false) NEXT:[ret(*) l1] PREV:[jt(l2)] + ret(*) l1 NEXT:[] PREV:[r(false)] l2: - r(false || (return false)) + r(false || (return false)) NEXT:[] PREV:[jt(l2)] l1: - + NEXT:[] PREV:[ret(*) l1, r(false || (return false))] error: - + NEXT:[] PREV:[] ===================== diff --git a/idea/testData/cfg/ShortFunction.instructions b/idea/testData/cfg/ShortFunction.instructions index c3bdcaf3778..e0e2b89781b 100644 --- a/idea/testData/cfg/ShortFunction.instructions +++ b/idea/testData/cfg/ShortFunction.instructions @@ -2,10 +2,10 @@ fun short() = 1 --------------------- l0: - - r(1) + NEXT:[r(1)] PREV:[] + r(1) NEXT:[] PREV:[] l1: - + NEXT:[] PREV:[r(1)] error: - + NEXT:[] PREV:[] ===================== diff --git a/idea/testData/checkerWithErrorTypes/full/infos/Autocasts.jet b/idea/testData/checkerWithErrorTypes/full/infos/Autocasts.jet index a3cf2976f1f..0960ee88808 100644 --- a/idea/testData/checkerWithErrorTypes/full/infos/Autocasts.jet +++ b/idea/testData/checkerWithErrorTypes/full/infos/Autocasts.jet @@ -6,8 +6,8 @@ class B() : A() { fun bar() {} } -fun f9() { - val a : A? +fun f9(init : A?) { + val a : A? = init a?.foo() a?.bar() if (a is B) { @@ -30,8 +30,8 @@ fun f9() { a.foo() } -fun f10() { - val a : A? +fun f10(init : A?) { + val a : A? = init if (!(a is B)) { return; } diff --git a/idea/testData/checkerWithErrorTypes/full/regression/OverrideResolution.jet b/idea/testData/checkerWithErrorTypes/full/regression/OverrideResolution.jet index b58ac616160..e4af018eda2 100644 --- a/idea/testData/checkerWithErrorTypes/full/regression/OverrideResolution.jet +++ b/idea/testData/checkerWithErrorTypes/full/regression/OverrideResolution.jet @@ -1,5 +1,5 @@ -fun box() { - val a : C +fun box(c : C) { + val a : C = c a.foo() } diff --git a/idea/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java b/idea/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java index 0399c97acf3..60c867aadeb 100644 --- a/idea/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java +++ b/idea/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java @@ -10,10 +10,7 @@ import junit.framework.TestSuite; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetTestCaseBase; import org.jetbrains.jet.lang.cfg.LoopInfo; -import org.jetbrains.jet.lang.cfg.pseudocode.Instruction; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; -import org.jetbrains.jet.lang.cfg.pseudocode.JetPseudocodeTrace; -import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode; +import org.jetbrains.jet.lang.cfg.pseudocode.*; import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetFile; @@ -24,10 +21,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintStream; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.*; public class JetControlFlowTest extends JetTestCaseBase { static { @@ -109,8 +103,19 @@ public class JetControlFlowTest extends JetTestCaseBase { instructionDump.append(correspondingElement.getText()); instructionDump.append("\n---------------------\n"); - pseudocode.dumpInstructions(instructionDump); + dumpInstructions(pseudocode, instructionDump); instructionDump.append("=====================\n"); + + //check edges directions + Collection instructions = pseudocode.getInstructions(); + for (Instruction instruction : instructions) { + for (Instruction nextInstruction : instruction.getNextInstructions()) { + assertTrue("instruction: " + instruction + " next: " + nextInstruction, nextInstruction.getPreviousInstructions().contains(instruction)); + } + for (Instruction prevInstruction : instruction.getPreviousInstructions()) { + assertTrue("instruction: " + instruction + " prev: " + prevInstruction, prevInstruction.getNextInstructions().contains(instruction)); + } + } } String expectedInstructionsFileName = getTestDataPath() + "/" + getTestFilePath().replace(".jet", ".instructions"); @@ -129,6 +134,217 @@ public class JetControlFlowTest extends JetTestCaseBase { // } } + public void dfsDump(Pseudocode pseudocode, StringBuilder nodes, StringBuilder edges, Map nodeNames) { + dfsDump(nodes, edges, pseudocode.getInstructions().get(0), nodeNames); + } + + private void dfsDump(StringBuilder nodes, StringBuilder edges, Instruction instruction, Map nodeNames) { + if (nodeNames.containsKey(instruction)) return; + String name = "n" + nodeNames.size(); + nodeNames.put(instruction, name); + nodes.append(name).append(" := ").append(renderName(instruction)); + + } + + private String renderName(Instruction instruction) { + throw new UnsupportedOperationException(); // TODO + } + + private static String formatInstruction(Instruction instruction, int maxLength) { + String[] parts = instruction.toString().split("\n"); + if (parts.length == 1) { + return " " + String.format("%1$-" + maxLength + "s", instruction); + } + StringBuilder sb = new StringBuilder(); + for (int i = 0, partsLength = parts.length; i < partsLength; i++) { + String part = parts[i]; + sb.append(" ").append(String.format("%1$-" + maxLength + "s", part)); + if (i < partsLength - 1) sb.append("\n"); + } + return sb.toString(); + } + + private static String formatInstructionList(Collection instructions) { + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (Iterator iterator = instructions.iterator(); iterator.hasNext(); ) { + Instruction instruction = iterator.next(); + String instructionText = instruction.toString(); + String[] parts = instructionText.split("\n"); + if (parts.length > 1) { + StringBuilder instructionSb = new StringBuilder(); + for (String part : parts) { + instructionSb.append(part.trim()).append(' '); + } + if (instructionSb.toString().length() > 30) { + sb.append(instructionSb.substring(0, 28)).append("..)"); + } + else { + sb.append(instructionSb); + } + } + else { + sb.append(instruction); + } + if (iterator.hasNext()) { + sb.append(", "); + } + } + sb.append(']'); + return sb.toString(); + } + + public void dumpInstructions(Pseudocode pseudocode, @NotNull StringBuilder out) { + List instructions = pseudocode.getInstructions(); + List labels = pseudocode.getLabels(); + List locals = new ArrayList(); + int maxLength = 0; + int maxNextLength = 0; + for (Instruction instruction : instructions) { + String instuctionText = instruction.toString(); + if (instuctionText.length() > maxLength) { + String[] parts = instuctionText.split("\n"); + if (parts.length > 1) { + for (String part : parts) { + if (part.length() > maxLength) { + maxLength = part.length(); + } + } + } + else { + maxLength = instuctionText.length(); + } + } + String instructionListText = formatInstructionList(instruction.getNextInstructions()); + if (instructionListText.length() > maxNextLength) { + maxNextLength = instructionListText.length(); + } + } + for (int i = 0, instructionsSize = instructions.size(); i < instructionsSize; i++) { + Instruction instruction = instructions.get(i); + if (instruction instanceof FunctionLiteralValueInstruction) { + FunctionLiteralValueInstruction functionLiteralValueInstruction = (FunctionLiteralValueInstruction) instruction; + locals.add(functionLiteralValueInstruction.getBody()); + } + for (Pseudocode.PseudocodeLabel label: labels) { + if (label.getTargetInstructionIndex() == i) { + out.append(label.getName()).append(":\n"); + } + } + + out.append(formatInstruction(instruction, maxLength)). + append(" NEXT:").append(String.format("%1$-" + maxNextLength + "s", formatInstructionList(instruction.getNextInstructions()))). + append(" PREV:").append(formatInstructionList(instruction.getPreviousInstructions())).append("\n"); + } + for (Pseudocode local : locals) { + dumpInstructions(local, out); + } + } + + public void dumpEdges(List instructions, final PrintStream out, final int[] count, final Map nodeToName) { + for (final Instruction fromInst : instructions) { + fromInst.accept(new InstructionVisitor() { + @Override + public void visitFunctionLiteralValue(FunctionLiteralValueInstruction instruction) { + int index = count[0]; +// instruction.getBody().dumpSubgraph(out, "subgraph cluster_" + index, count, "color=blue;\nlabel = \"f" + index + "\";", nodeToName); + printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getBody().getInstructions().get(0)), null); + visitInstructionWithNext(instruction); + } + + @Override + public void visitUnconditionalJump(UnconditionalJumpInstruction instruction) { + // Nothing + } + + @Override + public void visitJump(AbstractJumpInstruction instruction) { + printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getResolvedTarget()), null); + } + + @Override + public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) { + visitJump(instruction); + printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getNext()), null); + } + + @Override + public void visitReturnValue(ReturnValueInstruction instruction) { + super.visitReturnValue(instruction); + } + + @Override + public void visitReturnNoValue(ReturnNoValueInstruction instruction) { + super.visitReturnNoValue(instruction); + } + + @Override + public void visitConditionalJump(ConditionalJumpInstruction instruction) { + String from = nodeToName.get(instruction); + printEdge(out, from, nodeToName.get(instruction.getNextOnFalse()), "no"); + printEdge(out, from, nodeToName.get(instruction.getNextOnTrue()), "yes"); + } + + @Override + public void visitInstructionWithNext(InstructionWithNext instruction) { + printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getNext()), null); + } + + @Override + public void visitSubroutineExit(SubroutineExitInstruction instruction) { + // Nothing + } + + @Override + public void visitInstruction(Instruction instruction) { + throw new UnsupportedOperationException(instruction.toString()); + } + }); + } + } + + public void dumpNodes(List instructions, PrintStream out, int[] count, Map nodeToName) { + for (Instruction node : instructions) { + if (node instanceof UnconditionalJumpInstruction) { + continue; + } + String name = "n" + count[0]++; + nodeToName.put(node, name); + String text = node.toString(); + int newline = text.indexOf("\n"); + if (newline >= 0) { + text = text.substring(0, newline); + } + String shape = "box"; + if (node instanceof ConditionalJumpInstruction) { + shape = "diamond"; + } + else if (node instanceof NondeterministicJumpInstruction) { + shape = "Mdiamond"; + } + else if (node instanceof UnsupportedElementInstruction) { + shape = "box, fillcolor=red, style=filled"; + } + else if (node instanceof FunctionLiteralValueInstruction) { + shape = "Mcircle"; + } + else if (node instanceof SubroutineEnterInstruction || node instanceof SubroutineExitInstruction) { + shape = "roundrect, style=rounded"; + } + out.println(name + "[label=\"" + text + "\", shape=" + shape + "];"); + } + } + + private void printEdge(PrintStream out, String from, String to, String label) { + if (label != null) { + label = "[label=\"" + label + "\"]"; + } + else { + label = ""; + } + out.println(from + " -> " + to + label + ";"); + } + private void dumpDot(String name, Collection pseudocodes) throws FileNotFoundException { String graphFileName = getTestDataPath() + "/" + getTestFilePath().replace(".jet", ".dot"); File target = new File(graphFileName); @@ -139,7 +355,7 @@ public class JetControlFlowTest extends JetTestCaseBase { int[] count = new int[1]; Map nodeToName = new HashMap(); for (Pseudocode pseudocode : pseudocodes) { - pseudocode.dumpNodes(out, count, nodeToName); + dumpNodes(pseudocode.getInstructions(), out, count, nodeToName); } int i = 0; for (Pseudocode pseudocode : pseudocodes) { @@ -155,7 +371,7 @@ public class JetControlFlowTest extends JetTestCaseBase { out.println("subgraph cluster_" + i + " {\n" + "label=\"" + label + "\";\n" + "color=blue;\n"); - pseudocode.dumpEdges(out, count, nodeToName); + dumpEdges(pseudocode.getInstructions(), out, count, nodeToName); out.println("}"); i++; }