KT-58 Allow finally around definite returns
This commit is contained in:
@@ -18,6 +18,7 @@ public interface JetControlFlowBuilder {
|
||||
Label createUnboundLabel();
|
||||
|
||||
void bindLabel(@NotNull Label label);
|
||||
void allowDead();
|
||||
|
||||
// Jumps
|
||||
void jump(@NotNull Label label);
|
||||
|
||||
@@ -37,6 +37,12 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
|
||||
builder.bindLabel(label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void allowDead() {
|
||||
assert builder != null;
|
||||
builder.allowDead();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jump(@NotNull Label label) {
|
||||
assert builder != null;
|
||||
|
||||
@@ -5,18 +5,19 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
|
||||
@@ -356,18 +357,35 @@ public class JetControlFlowProcessor {
|
||||
});
|
||||
}
|
||||
|
||||
Label onException = builder.createUnboundLabel();
|
||||
builder.nondeterministicJump(onException);
|
||||
List<JetCatchClause> catchClauses = expression.getCatchClauses();
|
||||
final boolean hasCatches = !catchClauses.isEmpty();
|
||||
Label onException = null;
|
||||
if (hasCatches) {
|
||||
onException = builder.createUnboundLabel();
|
||||
builder.nondeterministicJump(onException);
|
||||
}
|
||||
value(expression.getTryBlock(), inCondition);
|
||||
|
||||
List<JetCatchClause> catchClauses = expression.getCatchClauses();
|
||||
if (!catchClauses.isEmpty()) {
|
||||
if (hasCatches) {
|
||||
builder.allowDead();
|
||||
Label afterCatches = builder.createUnboundLabel();
|
||||
builder.jump(afterCatches);
|
||||
|
||||
builder.bindLabel(onException);
|
||||
for (Iterator<JetCatchClause> iterator = catchClauses.iterator(); iterator.hasNext(); ) {
|
||||
JetCatchClause catchClause = iterator.next();
|
||||
LinkedList<Label> catchLabels = Lists.newLinkedList();
|
||||
int catchClausesSize = catchClauses.size();
|
||||
for (int i = 0; i < catchClausesSize - 1; i++) {
|
||||
catchLabels.add(builder.createUnboundLabel());
|
||||
}
|
||||
builder.nondeterministicJump(catchLabels);
|
||||
boolean isFirst = true;
|
||||
for (JetCatchClause catchClause : catchClauses) {
|
||||
if (!isFirst) {
|
||||
builder.bindLabel(catchLabels.remove());
|
||||
}
|
||||
else {
|
||||
isFirst = false;
|
||||
}
|
||||
JetParameter catchParameter = catchClause.getCatchParameter();
|
||||
if (catchParameter != null) {
|
||||
builder.write(catchParameter, catchParameter);
|
||||
@@ -376,14 +394,14 @@ public class JetControlFlowProcessor {
|
||||
if (catchBody != null) {
|
||||
value(catchBody, false);
|
||||
}
|
||||
if (iterator.hasNext()) {
|
||||
builder.nondeterministicJump(afterCatches);
|
||||
}
|
||||
builder.allowDead();
|
||||
builder.jump(afterCatches);
|
||||
}
|
||||
|
||||
builder.bindLabel(afterCatches);
|
||||
} else {
|
||||
builder.bindLabel(onException);
|
||||
}
|
||||
else {
|
||||
builder.allowDead();
|
||||
}
|
||||
|
||||
if (finallyBlock != null) {
|
||||
|
||||
+7
@@ -243,6 +243,13 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
pseudocode.bindLabel(label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void allowDead() {
|
||||
Label allowedDeadLabel = createUnboundLabel();
|
||||
bindLabel(allowedDeadLabel);
|
||||
pseudocode.allowDead(allowedDeadLabel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nondeterministicJump(Label label) {
|
||||
handleJumpInsideTryFinally(label);
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ public class NondeterministicJumpInstruction extends InstructionImpl{
|
||||
private final Map<Label, Instruction> resolvedTargets;
|
||||
|
||||
public NondeterministicJumpInstruction(List<Label> targetLabels) {
|
||||
this.targetLabels = targetLabels;
|
||||
this.targetLabels = Lists.newArrayList(targetLabels);
|
||||
resolvedTargets = Maps.newLinkedHashMap();
|
||||
}
|
||||
|
||||
|
||||
@@ -44,18 +44,20 @@ public class Pseudocode {
|
||||
@Nullable
|
||||
private List<Instruction> resolve() {
|
||||
assert targetInstructionIndex != null;
|
||||
return instructions.subList(getTargetInstructionIndex(), instructions.size());
|
||||
return mutableInstructionList.subList(getTargetInstructionIndex(), mutableInstructionList.size());
|
||||
}
|
||||
|
||||
public Instruction resolveToInstruction() {
|
||||
assert targetInstructionIndex != null;
|
||||
return instructions.get(targetInstructionIndex);
|
||||
return mutableInstructionList.get(targetInstructionIndex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final List<Instruction> mutableInstructionList = new ArrayList<Instruction>();
|
||||
private final List<Instruction> instructions = new ArrayList<Instruction>();
|
||||
private final List<PseudocodeLabel> labels = new ArrayList<PseudocodeLabel>();
|
||||
private final List<PseudocodeLabel> allowedDeadLabels = new ArrayList<PseudocodeLabel>();
|
||||
|
||||
private final JetElement correspondingElement;
|
||||
private SubroutineExitInstruction exitInstruction;
|
||||
@@ -75,11 +77,21 @@ public class Pseudocode {
|
||||
labels.add(label);
|
||||
return label;
|
||||
}
|
||||
|
||||
public void allowDead(Label label) {
|
||||
allowedDeadLabels.add((PseudocodeLabel) label);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<Instruction> getInstructions() {
|
||||
return instructions;
|
||||
}
|
||||
|
||||
@Deprecated //for tests only
|
||||
@NotNull
|
||||
public List<Instruction> getMutableInstructionList() {
|
||||
return mutableInstructionList;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<Instruction> getDeadInstructions() {
|
||||
@@ -93,6 +105,7 @@ public class Pseudocode {
|
||||
}
|
||||
|
||||
@Deprecated //for tests only
|
||||
@NotNull
|
||||
public List<PseudocodeLabel> getLabels() {
|
||||
return labels;
|
||||
}
|
||||
@@ -110,7 +123,7 @@ public class Pseudocode {
|
||||
}
|
||||
|
||||
public void addInstruction(Instruction instruction) {
|
||||
instructions.add(instruction);
|
||||
mutableInstructionList.add(instruction);
|
||||
instruction.setOwner(this);
|
||||
}
|
||||
|
||||
@@ -127,18 +140,18 @@ public class Pseudocode {
|
||||
|
||||
@NotNull
|
||||
public SubroutineEnterInstruction getEnterInstruction() {
|
||||
return (SubroutineEnterInstruction) instructions.get(0);
|
||||
return (SubroutineEnterInstruction) mutableInstructionList.get(0);
|
||||
}
|
||||
|
||||
public void bindLabel(Label label) {
|
||||
((PseudocodeLabel) label).setTargetInstructionIndex(instructions.size());
|
||||
((PseudocodeLabel) label).setTargetInstructionIndex(mutableInstructionList.size());
|
||||
}
|
||||
|
||||
public void postProcess() {
|
||||
if (postPrecessed) return;
|
||||
postPrecessed = true;
|
||||
for (int i = 0, instructionsSize = instructions.size(); i < instructionsSize; i++) {
|
||||
Instruction instruction = instructions.get(i);
|
||||
for (int i = 0, instructionsSize = mutableInstructionList.size(); i < instructionsSize; i++) {
|
||||
Instruction instruction = mutableInstructionList.get(i);
|
||||
final int currentPosition = i;
|
||||
instruction.accept(new InstructionVisitor() {
|
||||
@Override
|
||||
@@ -198,15 +211,20 @@ public class Pseudocode {
|
||||
});
|
||||
}
|
||||
getExitInstruction().setSink(getSinkInstruction());
|
||||
removeDeadInstructions();
|
||||
Set<Instruction> allowedDeadStartInstructions = prepareAllowedDeadInstructions();
|
||||
markDeadInstructions();
|
||||
Collection<Instruction> allowedDeadInstructions = collectAllowedDeadInstructions(allowedDeadStartInstructions);
|
||||
instructions.addAll(mutableInstructionList);
|
||||
instructions.removeAll(allowedDeadInstructions);
|
||||
|
||||
}
|
||||
|
||||
private void removeDeadInstructions() {
|
||||
private void markDeadInstructions() {
|
||||
boolean hasRemovedInstruction = true;
|
||||
Collection<Instruction> processedInstructions = Sets.newHashSet();
|
||||
while (hasRemovedInstruction) {
|
||||
hasRemovedInstruction = false;
|
||||
for (Instruction instruction : instructions) {
|
||||
for (Instruction instruction : mutableInstructionList) {
|
||||
if (!(instruction instanceof SubroutineEnterInstruction || instruction instanceof SubroutineExitInstruction || instruction instanceof SubroutineSinkInstruction) &&
|
||||
instruction.getPreviousInstructions().isEmpty() && !processedInstructions.contains(instruction)) {
|
||||
hasRemovedInstruction = true;
|
||||
@@ -220,6 +238,36 @@ public class Pseudocode {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Set<Instruction> prepareAllowedDeadInstructions() {
|
||||
Set<Instruction> allowedDeadStartInstructions = Sets.newHashSet();
|
||||
for (PseudocodeLabel allowedDeadLabel : allowedDeadLabels) {
|
||||
Instruction allowedDeadInstruction = getJumpTarget(allowedDeadLabel);
|
||||
if (allowedDeadInstruction.getPreviousInstructions().isEmpty()) {
|
||||
allowedDeadStartInstructions.add(allowedDeadInstruction);
|
||||
}
|
||||
}
|
||||
return allowedDeadStartInstructions;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Collection<Instruction> collectAllowedDeadInstructions(@NotNull Set<Instruction> allowedDeadStartInstructions) {
|
||||
Set<Instruction> allowedDeadInstructions = Sets.newHashSet();
|
||||
for (Instruction allowedDeadStartInstruction : allowedDeadStartInstructions) {
|
||||
collectAllowedDeadInstructions(allowedDeadStartInstruction, allowedDeadInstructions);
|
||||
}
|
||||
return allowedDeadInstructions;
|
||||
}
|
||||
|
||||
private void collectAllowedDeadInstructions(Instruction allowedDeadInstruction, Set<Instruction> instructionSet) {
|
||||
if (allowedDeadInstruction.isDead()) {
|
||||
instructionSet.add(allowedDeadInstruction);
|
||||
for (Instruction instruction : allowedDeadInstruction.getNextInstructions()) {
|
||||
collectAllowedDeadInstructions(instruction, instructionSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Instruction getJumpTarget(@NotNull Label targetLabel) {
|
||||
return ((PseudocodeLabel)targetLabel).resolveToInstruction();
|
||||
@@ -228,7 +276,7 @@ public class Pseudocode {
|
||||
@NotNull
|
||||
private Instruction getNextPosition(int currentPosition) {
|
||||
int targetPosition = currentPosition + 1;
|
||||
assert targetPosition < instructions.size() : currentPosition;
|
||||
return instructions.get(targetPosition);
|
||||
assert targetPosition < mutableInstructionList.size() : currentPosition;
|
||||
return mutableInstructionList.get(targetPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,17 +8,16 @@ fun t1() {
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
||||
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
|
||||
r(1) NEXT:[r(2)] PREV:[jmp?(l2)]
|
||||
<START> NEXT:[r(1)] PREV:[]
|
||||
r(1) NEXT:[r(2)] PREV:[<START>]
|
||||
l2:
|
||||
r(2) NEXT:[<END>] PREV:[jmp?(l2), r(1)]
|
||||
r(2) NEXT:[<END>] PREV:[r(1)]
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
=====================
|
||||
== t2 ==
|
||||
fun t2() {
|
||||
@@ -33,22 +32,21 @@ fun t2() {
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
||||
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
|
||||
r(1) NEXT:[r(2)] PREV:[jmp?(l2)]
|
||||
<START> NEXT:[r(1)] PREV:[]
|
||||
r(1) NEXT:[r(2)] PREV:[<START>]
|
||||
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)]
|
||||
r(2 > 3) NEXT:[jf(l2)] PREV:[r(>)]
|
||||
jf(l2) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
||||
r(2) NEXT:[ret l1] PREV:[jf(l2)]
|
||||
ret l1 NEXT:[<END>] PREV:[r(2)]
|
||||
* jmp(l4) NEXT:[r(2)] PREV:[]
|
||||
l3:
|
||||
read (Unit) NEXT:[r(2)] PREV:[jf(l3)]
|
||||
* jmp(l3) NEXT:[r(2)] PREV:[]
|
||||
l2:
|
||||
read (Unit) NEXT:[r(2)] PREV:[jf(l2)]
|
||||
l3:
|
||||
l4:
|
||||
r(2) NEXT:[<END>] PREV:[jmp?(l2), read (Unit)]
|
||||
r(2) NEXT:[<END>] PREV:[read (Unit)]
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[ret l1, r(2)]
|
||||
error:
|
||||
@@ -63,20 +61,20 @@ sink:
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
l4:
|
||||
l3:
|
||||
<START> NEXT:[r(2)] PREV:[]
|
||||
r(2) NEXT:[r(3)] PREV:[<START>]
|
||||
r(3) NEXT:[r(>)] PREV:[r(2)]
|
||||
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
||||
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
||||
jf(l6) NEXT:[read (Unit), ret l5] PREV:[r(2 > 3)]
|
||||
ret l5 NEXT:[<END>] PREV:[jf(l6)]
|
||||
* jmp(l7) NEXT:[<END>] PREV:[]
|
||||
l6:
|
||||
read (Unit) NEXT:[<END>] PREV:[jf(l6)]
|
||||
r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)]
|
||||
jf(l5) NEXT:[read (Unit), ret l4] PREV:[r(2 > 3)]
|
||||
ret l4 NEXT:[<END>] PREV:[jf(l5)]
|
||||
* jmp(l6) NEXT:[<END>] PREV:[]
|
||||
l5:
|
||||
l7:
|
||||
<END> NEXT:[<SINK>] PREV:[ret l5, read (Unit)]
|
||||
read (Unit) NEXT:[<END>] PREV:[jf(l5)]
|
||||
l4:
|
||||
l6:
|
||||
<END> NEXT:[<SINK>] PREV:[ret l4, read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
sink:
|
||||
@@ -97,43 +95,42 @@ fun t3() {
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
||||
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
|
||||
r(1) NEXT:[jmp?(l3)] PREV:[jmp?(l2)]
|
||||
jmp?(l3) NEXT:[r({ () => if (2 > 3) { retur..), d({ () => if (2 > 3) { retur..)] PREV:[r(1)]
|
||||
<START> NEXT:[r(1)] PREV:[]
|
||||
r(1) NEXT:[jmp?(l2)] PREV:[<START>]
|
||||
jmp?(l2) NEXT:[r({ () => if (2 > 3) { retur..), d({ () => if (2 > 3) { retur..)] PREV:[r(1)]
|
||||
d({ () =>
|
||||
if (2 > 3) {
|
||||
return@
|
||||
}
|
||||
}) NEXT:[<SINK>] PREV:[jmp?(l3)]
|
||||
l3:
|
||||
}) NEXT:[<SINK>] PREV:[jmp?(l2)]
|
||||
l2:
|
||||
r({ () =>
|
||||
if (2 > 3) {
|
||||
return@
|
||||
}
|
||||
}) NEXT:[r(2)] PREV:[jmp?(l3)]
|
||||
l2:
|
||||
r(2) NEXT:[<END>] PREV:[jmp?(l2), r({ () => if (2 > 3) { retur..)]
|
||||
}) NEXT:[r(2)] PREV:[jmp?(l2)]
|
||||
l7:
|
||||
r(2) NEXT:[<END>] PREV:[r({ () => if (2 > 3) { retur..)]
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[d({ () => if (2 > 3) { retur..), <END>]
|
||||
l4:
|
||||
l3:
|
||||
<START> NEXT:[r(2)] PREV:[]
|
||||
r(2) NEXT:[r(3)] PREV:[<START>]
|
||||
r(3) NEXT:[r(>)] PREV:[r(2)]
|
||||
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
||||
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
||||
jf(l6) NEXT:[read (Unit), ret l5] PREV:[r(2 > 3)]
|
||||
ret l5 NEXT:[<END>] PREV:[jf(l6)]
|
||||
* jmp(l7) NEXT:[<END>] PREV:[]
|
||||
l6:
|
||||
read (Unit) NEXT:[<END>] PREV:[jf(l6)]
|
||||
r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)]
|
||||
jf(l5) NEXT:[read (Unit), ret l4] PREV:[r(2 > 3)]
|
||||
ret l4 NEXT:[<END>] PREV:[jf(l5)]
|
||||
* jmp(l6) NEXT:[<END>] PREV:[]
|
||||
l5:
|
||||
l7:
|
||||
<END> NEXT:[<SINK>] PREV:[ret l5, read (Unit)]
|
||||
read (Unit) NEXT:[<END>] PREV:[jf(l5)]
|
||||
l4:
|
||||
l6:
|
||||
<END> NEXT:[<SINK>] PREV:[ret l4, read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
sink:
|
||||
@@ -152,22 +149,21 @@ sink:
|
||||
}
|
||||
---------------------
|
||||
l3:
|
||||
<START> NEXT:[jmp?(l5)] PREV:[]
|
||||
jmp?(l5) NEXT:[r(2), r(1)] PREV:[<START>]
|
||||
r(1) NEXT:[r(2)] PREV:[jmp?(l5)]
|
||||
<START> NEXT:[r(1)] PREV:[]
|
||||
r(1) NEXT:[r(2)] PREV:[<START>]
|
||||
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(l6)] PREV:[r(>)]
|
||||
jf(l6) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
||||
r(2) NEXT:[ret l4] PREV:[jf(l6)]
|
||||
r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)]
|
||||
jf(l5) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
||||
r(2) NEXT:[ret l4] PREV:[jf(l5)]
|
||||
ret l4 NEXT:[<END>] PREV:[r(2)]
|
||||
* jmp(l7) NEXT:[r(2)] PREV:[]
|
||||
l6:
|
||||
read (Unit) NEXT:[r(2)] PREV:[jf(l6)]
|
||||
* jmp(l6) NEXT:[r(2)] PREV:[]
|
||||
l5:
|
||||
read (Unit) NEXT:[r(2)] PREV:[jf(l5)]
|
||||
l6:
|
||||
l7:
|
||||
r(2) NEXT:[<END>] PREV:[jmp?(l5), read (Unit)]
|
||||
r(2) NEXT:[<END>] PREV:[read (Unit)]
|
||||
l4:
|
||||
<END> NEXT:[<SINK>] PREV:[ret l4, r(2)]
|
||||
error:
|
||||
@@ -220,22 +216,21 @@ error:
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[d({ () => try { 1 if (2 > 3)..), <END>]
|
||||
l3:
|
||||
<START> NEXT:[jmp?(l5)] PREV:[]
|
||||
jmp?(l5) NEXT:[r(2), r(1)] PREV:[<START>]
|
||||
r(1) NEXT:[r(2)] PREV:[jmp?(l5)]
|
||||
<START> NEXT:[r(1)] PREV:[]
|
||||
r(1) NEXT:[r(2)] PREV:[<START>]
|
||||
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(l6)] PREV:[r(>)]
|
||||
jf(l6) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
||||
r(2) NEXT:[ret l4] PREV:[jf(l6)]
|
||||
r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)]
|
||||
jf(l5) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
||||
r(2) NEXT:[ret l4] PREV:[jf(l5)]
|
||||
ret l4 NEXT:[<END>] PREV:[r(2)]
|
||||
* jmp(l7) NEXT:[r(2)] PREV:[]
|
||||
l6:
|
||||
read (Unit) NEXT:[r(2)] PREV:[jf(l6)]
|
||||
* jmp(l6) NEXT:[r(2)] PREV:[]
|
||||
l5:
|
||||
read (Unit) NEXT:[r(2)] PREV:[jf(l5)]
|
||||
l6:
|
||||
l7:
|
||||
r(2) NEXT:[<END>] PREV:[jmp?(l5), read (Unit)]
|
||||
r(2) NEXT:[<END>] PREV:[read (Unit)]
|
||||
l4:
|
||||
<END> NEXT:[<SINK>] PREV:[ret l4, r(2)]
|
||||
error:
|
||||
@@ -258,36 +253,35 @@ fun t5() {
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[r(true)] PREV:[]
|
||||
<START> NEXT:[r(true)] PREV:[]
|
||||
l2:
|
||||
l5:
|
||||
r(true) NEXT:[jf(l3)] PREV:[<START>, jmp(l2)]
|
||||
jf(l3) NEXT:[read (Unit), jmp?(l6)] PREV:[r(true)]
|
||||
r(true) NEXT:[jf(l3)] PREV:[<START>, jmp(l2)]
|
||||
jf(l3) NEXT:[read (Unit), r(1)] PREV:[r(true)]
|
||||
l4:
|
||||
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) NEXT:[r(2)] PREV:[jf(l7)]
|
||||
r(1) NEXT:[r(2)] PREV:[jf(l3)]
|
||||
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(l6)] PREV:[r(>)]
|
||||
jf(l6) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
||||
r(2) NEXT:[jmp(l3)] PREV:[jf(l6)]
|
||||
jmp(l3) NEXT:[read (Unit)] PREV:[r(2)]
|
||||
* jmp(l7) NEXT:[r(2)] PREV:[]
|
||||
l6:
|
||||
read (Unit) NEXT:[r(2)] PREV:[jf(l6)]
|
||||
l7:
|
||||
l8:
|
||||
r(2) NEXT:[jmp(l2)] PREV:[jmp?(l6), read (Unit)]
|
||||
jmp(l2) NEXT:[r(true)] PREV:[r(2)]
|
||||
r(2) NEXT:[jmp(l2)] PREV:[read (Unit)]
|
||||
jmp(l2) NEXT:[r(true)] PREV:[r(2)]
|
||||
l3:
|
||||
read (Unit) NEXT:[<END>] PREV:[jf(l3), jmp(l3)]
|
||||
read (Unit) NEXT:[<END>] PREV:[jf(l3), jmp(l3)]
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
=====================
|
||||
== t6 ==
|
||||
fun t6() {
|
||||
@@ -305,30 +299,29 @@ fun t6() {
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
||||
jmp?(l2) NEXT:[r(2), r(true)] PREV:[<START>]
|
||||
l3:
|
||||
l6:
|
||||
r(true) NEXT:[jf(l4)] PREV:[jmp?(l2), jmp(l3)]
|
||||
jf(l4) NEXT:[read (Unit), r(1)] PREV:[r(true)]
|
||||
<START> NEXT:[r(true)] PREV:[]
|
||||
l2:
|
||||
l5:
|
||||
r(1) NEXT:[r(2)] PREV:[jf(l4)]
|
||||
r(true) NEXT:[jf(l3)] PREV:[<START>, jmp(l2)]
|
||||
jf(l3) NEXT:[read (Unit), r(1)] PREV:[r(true)]
|
||||
l4:
|
||||
r(1) NEXT:[r(2)] PREV:[jf(l3)]
|
||||
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:[]
|
||||
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
||||
jf(l6) NEXT:[read (Unit), jmp(l3)] PREV:[r(2 > 3)]
|
||||
jmp(l3) NEXT:[read (Unit)] PREV:[jf(l6)]
|
||||
* jmp(l7) NEXT:[jmp(l2)] PREV:[]
|
||||
l6:
|
||||
read (Unit) NEXT:[jmp(l2)] PREV:[jf(l6)]
|
||||
l7:
|
||||
read (Unit) NEXT:[jmp(l3)] PREV:[jf(l7)]
|
||||
l8:
|
||||
jmp(l3) NEXT:[r(true)] PREV:[read (Unit)]
|
||||
l4:
|
||||
read (Unit) NEXT:[r(5)] PREV:[jf(l4), jmp(l4)]
|
||||
jmp(l2) NEXT:[r(true)] PREV:[read (Unit)]
|
||||
l3:
|
||||
read (Unit) NEXT:[r(5)] PREV:[jf(l3), jmp(l3)]
|
||||
r(5) NEXT:[r(2)] PREV:[read (Unit)]
|
||||
l2:
|
||||
r(2) NEXT:[<END>] PREV:[jmp?(l2), r(5)]
|
||||
l8:
|
||||
r(2) NEXT:[<END>] PREV:[r(5)]
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||
error:
|
||||
@@ -351,29 +344,28 @@ fun t7() {
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
||||
jmp?(l2) NEXT:[r(2), r(true)] PREV:[<START>]
|
||||
l3:
|
||||
l6:
|
||||
r(true) NEXT:[jf(l4)] PREV:[jmp?(l2), jmp(l3)]
|
||||
jf(l4) NEXT:[read (Unit), r(1)] PREV:[r(true)]
|
||||
<START> NEXT:[r(true)] PREV:[]
|
||||
l2:
|
||||
l5:
|
||||
r(1) NEXT:[r(2)] PREV:[jf(l4)]
|
||||
r(true) NEXT:[jf(l3)] PREV:[<START>, jmp(l2)]
|
||||
jf(l3) NEXT:[read (Unit), r(1)] PREV:[r(true)]
|
||||
l4:
|
||||
r(1) NEXT:[r(2)] PREV:[jf(l3)]
|
||||
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:[]
|
||||
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
||||
jf(l6) NEXT:[read (Unit), jmp(l3)] PREV:[r(2 > 3)]
|
||||
jmp(l3) NEXT:[read (Unit)] PREV:[jf(l6)]
|
||||
* jmp(l7) NEXT:[jmp(l2)] PREV:[]
|
||||
l6:
|
||||
read (Unit) NEXT:[jmp(l2)] PREV:[jf(l6)]
|
||||
l7:
|
||||
read (Unit) NEXT:[jmp(l3)] PREV:[jf(l7)]
|
||||
jmp(l2) NEXT:[r(true)] PREV:[read (Unit)]
|
||||
l3:
|
||||
read (Unit) NEXT:[r(2)] PREV:[jf(l3), jmp(l3)]
|
||||
l8:
|
||||
jmp(l3) NEXT:[r(true)] PREV:[read (Unit)]
|
||||
l4:
|
||||
read (Unit) NEXT:[r(2)] PREV:[jf(l4), jmp(l4)]
|
||||
l2:
|
||||
r(2) NEXT:[<END>] PREV:[jmp?(l2), read (Unit)]
|
||||
r(2) NEXT:[<END>] PREV:[read (Unit)]
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||
error:
|
||||
@@ -396,40 +388,39 @@ fun t8(a : Int) {
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[r(1)] PREV:[]
|
||||
r(1) NEXT:[r(a)] PREV:[<START>]
|
||||
r(a) NEXT:[r(..)] PREV:[r(1)]
|
||||
r(..) NEXT:[r(1..a)] PREV:[r(a)]
|
||||
r(1..a) NEXT:[w(i)] PREV:[r(..)]
|
||||
w(i) NEXT:[jmp?(l2)] PREV:[r(1..a)]
|
||||
<START> NEXT:[r(1)] PREV:[]
|
||||
r(1) NEXT:[r(a)] PREV:[<START>]
|
||||
r(a) NEXT:[r(..)] PREV:[r(1)]
|
||||
r(..) NEXT:[r(1..a)] PREV:[r(a)]
|
||||
r(1..a) NEXT:[w(i)] PREV:[r(..)]
|
||||
w(i) NEXT:[jmp?(l2)] PREV:[r(1..a)]
|
||||
l3:
|
||||
jmp?(l2) NEXT:[read (Unit), jmp?(l6)] PREV:[w(i)]
|
||||
jmp?(l2) NEXT:[read (Unit), r(1)] PREV:[w(i)]
|
||||
l4:
|
||||
l5:
|
||||
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) NEXT:[r(2)] PREV:[jf(l7)]
|
||||
r(1) NEXT:[r(2)] PREV:[jmp?(l2), jmp(l4), 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(l6)] PREV:[r(>)]
|
||||
jf(l6) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
||||
r(2) NEXT:[jmp(l4)] PREV:[jf(l6)]
|
||||
jmp(l4) NEXT:[r(1)] PREV:[r(2)]
|
||||
* jmp(l7) NEXT:[r(2)] PREV:[]
|
||||
l6:
|
||||
read (Unit) NEXT:[r(2)] PREV:[jf(l6)]
|
||||
l7:
|
||||
l8:
|
||||
r(2) NEXT:[jmp?(l4)] PREV:[jmp?(l6), read (Unit)]
|
||||
jmp?(l4) NEXT:[jmp?(l6), read (Unit)] PREV:[r(2)]
|
||||
r(2) NEXT:[jmp?(l4)] PREV:[read (Unit)]
|
||||
jmp?(l4) NEXT:[r(1), read (Unit)] PREV:[r(2)]
|
||||
l2:
|
||||
read (Unit) NEXT:[<END>] PREV:[jmp?(l2), jmp?(l4)]
|
||||
read (Unit) NEXT:[<END>] PREV:[jmp?(l2), jmp?(l4)]
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
=====================
|
||||
== t9 ==
|
||||
fun t9(a : Int) {
|
||||
@@ -447,34 +438,33 @@ fun t9(a : Int) {
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
||||
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
|
||||
r(1) NEXT:[r(a)] PREV:[jmp?(l2)]
|
||||
<START> NEXT:[r(1)] PREV:[]
|
||||
r(1) NEXT:[r(a)] PREV:[<START>]
|
||||
r(a) NEXT:[r(..)] PREV:[r(1)]
|
||||
r(..) NEXT:[r(1..a)] PREV:[r(a)]
|
||||
r(1..a) NEXT:[w(i)] PREV:[r(..)]
|
||||
w(i) NEXT:[jmp?(l3)] PREV:[r(1..a)]
|
||||
w(i) NEXT:[jmp?(l2)] PREV:[r(1..a)]
|
||||
l3:
|
||||
jmp?(l2) NEXT:[read (Unit), r(1)] PREV:[w(i)]
|
||||
l4:
|
||||
jmp?(l3) NEXT:[read (Unit), r(1)] PREV:[w(i)]
|
||||
l5:
|
||||
l6:
|
||||
r(1) NEXT:[r(2)] PREV:[jmp?(l3), jmp(l5), jmp?(l5)]
|
||||
r(1) NEXT:[r(2)] PREV:[jmp?(l2), jmp(l4), 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(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:[]
|
||||
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
||||
jf(l6) NEXT:[read (Unit), jmp(l4)] PREV:[r(2 > 3)]
|
||||
jmp(l4) NEXT:[r(1)] PREV:[jf(l6)]
|
||||
* jmp(l7) NEXT:[jmp?(l4)] PREV:[]
|
||||
l6:
|
||||
read (Unit) NEXT:[jmp?(l4)] PREV:[jf(l6)]
|
||||
l7:
|
||||
read (Unit) NEXT:[jmp?(l5)] PREV:[jf(l7)]
|
||||
l8:
|
||||
jmp?(l5) NEXT:[r(1), read (Unit)] PREV:[read (Unit)]
|
||||
l3:
|
||||
read (Unit) NEXT:[r(5)] PREV:[jmp?(l3), jmp?(l5)]
|
||||
r(5) NEXT:[r(2)] PREV:[read (Unit)]
|
||||
jmp?(l4) NEXT:[r(1), read (Unit)] PREV:[read (Unit)]
|
||||
l2:
|
||||
r(2) NEXT:[<END>] PREV:[jmp?(l2), r(5)]
|
||||
read (Unit) NEXT:[r(5)] PREV:[jmp?(l2), jmp?(l4)]
|
||||
r(5) NEXT:[r(2)] PREV:[read (Unit)]
|
||||
l8:
|
||||
r(2) NEXT:[<END>] PREV:[r(5)]
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||
error:
|
||||
@@ -497,33 +487,32 @@ fun t10(a : Int) {
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
||||
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
|
||||
r(1) NEXT:[r(a)] PREV:[jmp?(l2)]
|
||||
<START> NEXT:[r(1)] PREV:[]
|
||||
r(1) NEXT:[r(a)] PREV:[<START>]
|
||||
r(a) NEXT:[r(..)] PREV:[r(1)]
|
||||
r(..) NEXT:[r(1..a)] PREV:[r(a)]
|
||||
r(1..a) NEXT:[w(i)] PREV:[r(..)]
|
||||
w(i) NEXT:[jmp?(l3)] PREV:[r(1..a)]
|
||||
w(i) NEXT:[jmp?(l2)] PREV:[r(1..a)]
|
||||
l3:
|
||||
jmp?(l2) NEXT:[read (Unit), r(1)] PREV:[w(i)]
|
||||
l4:
|
||||
jmp?(l3) NEXT:[read (Unit), r(1)] PREV:[w(i)]
|
||||
l5:
|
||||
l6:
|
||||
r(1) NEXT:[r(2)] PREV:[jmp?(l3), jmp(l5), jmp?(l5)]
|
||||
r(1) NEXT:[r(2)] PREV:[jmp?(l2), jmp(l4), 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(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:[]
|
||||
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
||||
jf(l6) NEXT:[read (Unit), jmp(l4)] PREV:[r(2 > 3)]
|
||||
jmp(l4) NEXT:[r(1)] PREV:[jf(l6)]
|
||||
* jmp(l7) NEXT:[jmp?(l4)] PREV:[]
|
||||
l6:
|
||||
read (Unit) NEXT:[jmp?(l4)] PREV:[jf(l6)]
|
||||
l7:
|
||||
read (Unit) NEXT:[jmp?(l5)] PREV:[jf(l7)]
|
||||
l8:
|
||||
jmp?(l5) NEXT:[r(1), read (Unit)] PREV:[read (Unit)]
|
||||
l3:
|
||||
read (Unit) NEXT:[r(2)] PREV:[jmp?(l3), jmp?(l5)]
|
||||
jmp?(l4) NEXT:[r(1), read (Unit)] PREV:[read (Unit)]
|
||||
l2:
|
||||
r(2) NEXT:[<END>] PREV:[jmp?(l2), read (Unit)]
|
||||
read (Unit) NEXT:[r(2)] PREV:[jmp?(l2), jmp?(l4)]
|
||||
l8:
|
||||
r(2) NEXT:[<END>] PREV:[read (Unit)]
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||
error:
|
||||
@@ -542,19 +531,221 @@ fun t11() {
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
||||
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
|
||||
r(1) NEXT:[r(2)] PREV:[jmp?(l2)]
|
||||
r(2) NEXT:[ret(*) l1] PREV:[r(1)]
|
||||
ret(*) l1 NEXT:[<END>] PREV:[r(2)]
|
||||
* ret(*) l1 NEXT:[<END>] PREV:[]
|
||||
<START> NEXT:[r(1)] PREV:[]
|
||||
r(1) NEXT:[r(2)] PREV:[<START>]
|
||||
r(2) NEXT:[ret(*) l1] PREV:[r(1)]
|
||||
ret(*) l1 NEXT:[<END>] PREV:[r(2)]
|
||||
* ret(*) l1 NEXT:[<END>] PREV:[]
|
||||
l2:
|
||||
r(2) NEXT:[ret(*) l1] PREV:[jmp?(l2)]
|
||||
ret(*) l1 NEXT:[<END>] PREV:[r(2)]
|
||||
R r(2) NEXT:[ret(*) l1] PREV:[]
|
||||
R ret(*) l1 NEXT:[<END>] PREV:[]
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[ret(*) l1, ret(*) l1]
|
||||
<END> NEXT:[<SINK>] PREV:[ret(*) l1]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
=====================
|
||||
== t12 ==
|
||||
fun t12() : Int {
|
||||
try {
|
||||
return 1
|
||||
}
|
||||
finally {
|
||||
doSmth(3)
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[r(1)] PREV:[]
|
||||
r(1) NEXT:[r(3)] PREV:[<START>]
|
||||
r(3) NEXT:[r(doSmth)] PREV:[r(1)]
|
||||
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
|
||||
r(doSmth(3)) NEXT:[ret(*) l1] PREV:[r(doSmth)]
|
||||
ret(*) l1 NEXT:[<END>] PREV:[r(doSmth(3))]
|
||||
l2:
|
||||
R r(3) NEXT:[r(doSmth)] PREV:[]
|
||||
R r(doSmth) NEXT:[r(doSmth(3))] PREV:[]
|
||||
R r(doSmth(3)) NEXT:[<END>] PREV:[]
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[ret(*) l1]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
=====================
|
||||
== t13 ==
|
||||
fun t13() : Int {
|
||||
try {
|
||||
return 1
|
||||
}
|
||||
catch (e: UnsupportedOperationException) {
|
||||
doSmth(2)
|
||||
}
|
||||
finally {
|
||||
doSmth(3)
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
||||
jmp?(l2) NEXT:[jmp?(), r(1)] PREV:[<START>]
|
||||
r(1) NEXT:[r(3)] PREV:[jmp?(l2)]
|
||||
r(3) NEXT:[r(doSmth)] PREV:[r(1)]
|
||||
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
|
||||
r(doSmth(3)) NEXT:[ret(*) l1] PREV:[r(doSmth)]
|
||||
ret(*) l1 NEXT:[<END>] PREV:[r(doSmth(3))]
|
||||
l3:
|
||||
R jmp(l4) NEXT:[r(3)] PREV:[]
|
||||
l2:
|
||||
jmp?() NEXT:[w(e)] PREV:[jmp?(l2)]
|
||||
w(e) NEXT:[r(2)] PREV:[jmp?()]
|
||||
r(2) NEXT:[r(doSmth)] PREV:[w(e)]
|
||||
r(doSmth) NEXT:[r(doSmth(2))] PREV:[r(2)]
|
||||
r(doSmth(2)) NEXT:[jmp(l4)] PREV:[r(doSmth)]
|
||||
l5:
|
||||
jmp(l4) NEXT:[r(3)] PREV:[r(doSmth(2))]
|
||||
l4:
|
||||
r(3) NEXT:[r(doSmth)] PREV:[jmp(l4)]
|
||||
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
|
||||
r(doSmth(3)) NEXT:[<END>] PREV:[r(doSmth)]
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[ret(*) l1, r(doSmth(3))]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
=====================
|
||||
== t14 ==
|
||||
fun t14() : Int {
|
||||
try {
|
||||
return 1
|
||||
}
|
||||
catch (e: UnsupportedOperationException) {
|
||||
doSmth(2)
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
||||
jmp?(l2) NEXT:[jmp?(), r(1)] PREV:[<START>]
|
||||
r(1) NEXT:[ret(*) l1] PREV:[jmp?(l2)]
|
||||
ret(*) l1 NEXT:[<END>] PREV:[r(1)]
|
||||
l3:
|
||||
R jmp(l4) NEXT:[<END>] PREV:[]
|
||||
l2:
|
||||
jmp?() NEXT:[w(e)] PREV:[jmp?(l2)]
|
||||
w(e) NEXT:[r(2)] PREV:[jmp?()]
|
||||
r(2) NEXT:[r(doSmth)] PREV:[w(e)]
|
||||
r(doSmth) NEXT:[r(doSmth(2))] PREV:[r(2)]
|
||||
r(doSmth(2)) NEXT:[jmp(l4)] PREV:[r(doSmth)]
|
||||
l5:
|
||||
jmp(l4) NEXT:[<END>] PREV:[r(doSmth(2))]
|
||||
l1:
|
||||
l4:
|
||||
<END> NEXT:[<SINK>] PREV:[ret(*) l1, jmp(l4)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
=====================
|
||||
== t15 ==
|
||||
fun t15() : Int {
|
||||
try {
|
||||
return 1
|
||||
}
|
||||
catch (e: UnsupportedOperationException) {
|
||||
return 2
|
||||
}
|
||||
finally {
|
||||
doSmth(3)
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
||||
jmp?(l2) NEXT:[jmp?(), r(1)] PREV:[<START>]
|
||||
r(1) NEXT:[r(3)] PREV:[jmp?(l2)]
|
||||
r(3) NEXT:[r(doSmth)] PREV:[r(1)]
|
||||
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
|
||||
r(doSmth(3)) NEXT:[ret(*) l1] PREV:[r(doSmth)]
|
||||
ret(*) l1 NEXT:[<END>] PREV:[r(doSmth(3))]
|
||||
l3:
|
||||
R jmp(l4) NEXT:[r(3)] PREV:[]
|
||||
l2:
|
||||
jmp?() NEXT:[w(e)] PREV:[jmp?(l2)]
|
||||
w(e) NEXT:[r(2)] PREV:[jmp?()]
|
||||
r(2) NEXT:[r(3)] PREV:[w(e)]
|
||||
r(3) NEXT:[r(doSmth)] PREV:[r(2)]
|
||||
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
|
||||
r(doSmth(3)) NEXT:[ret(*) l1] PREV:[r(doSmth)]
|
||||
ret(*) l1 NEXT:[<END>] PREV:[r(doSmth(3))]
|
||||
l5:
|
||||
R jmp(l4) NEXT:[r(3)] PREV:[]
|
||||
l4:
|
||||
R r(3) NEXT:[r(doSmth)] PREV:[]
|
||||
R r(doSmth) NEXT:[r(doSmth(3))] PREV:[]
|
||||
R r(doSmth(3)) NEXT:[<END>] PREV:[]
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[ret(*) l1, ret(*) l1]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
=====================
|
||||
== t16 ==
|
||||
fun t16() : Int {
|
||||
try {
|
||||
doSmth(1)
|
||||
}
|
||||
catch (e: UnsupportedOperationException) {
|
||||
return 2
|
||||
}
|
||||
finally {
|
||||
doSmth(3)
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
||||
jmp?(l2) NEXT:[jmp?(), r(1)] PREV:[<START>]
|
||||
r(1) NEXT:[r(doSmth)] PREV:[jmp?(l2)]
|
||||
r(doSmth) NEXT:[r(doSmth(1))] PREV:[r(1)]
|
||||
r(doSmth(1)) NEXT:[jmp(l4)] PREV:[r(doSmth)]
|
||||
l3:
|
||||
jmp(l4) NEXT:[r(3)] PREV:[r(doSmth(1))]
|
||||
l2:
|
||||
jmp?() NEXT:[w(e)] PREV:[jmp?(l2)]
|
||||
w(e) NEXT:[r(2)] PREV:[jmp?()]
|
||||
r(2) NEXT:[r(3)] PREV:[w(e)]
|
||||
r(3) NEXT:[r(doSmth)] PREV:[r(2)]
|
||||
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
|
||||
r(doSmth(3)) NEXT:[ret(*) l1] PREV:[r(doSmth)]
|
||||
ret(*) l1 NEXT:[<END>] PREV:[r(doSmth(3))]
|
||||
l5:
|
||||
R jmp(l4) NEXT:[r(3)] PREV:[]
|
||||
l4:
|
||||
r(3) NEXT:[r(doSmth)] PREV:[jmp(l4)]
|
||||
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
|
||||
r(doSmth(3)) NEXT:[<END>] PREV:[r(doSmth)]
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[ret(*) l1, r(doSmth(3))]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
=====================
|
||||
== doSmth ==
|
||||
fun doSmth(i: Int) {
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[read (Unit)] PREV:[]
|
||||
read (Unit) NEXT:[<END>] PREV:[<START>]
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
=====================
|
||||
|
||||
@@ -130,4 +130,62 @@ fun t11() {
|
||||
finally {
|
||||
return 2
|
||||
}
|
||||
}
|
||||
|
||||
fun t12() : Int {
|
||||
try {
|
||||
return 1
|
||||
}
|
||||
finally {
|
||||
doSmth(3)
|
||||
}
|
||||
}
|
||||
|
||||
fun t13() : Int {
|
||||
try {
|
||||
return 1
|
||||
}
|
||||
catch (e: UnsupportedOperationException) {
|
||||
doSmth(2)
|
||||
}
|
||||
finally {
|
||||
doSmth(3)
|
||||
}
|
||||
}
|
||||
|
||||
fun t14() : Int {
|
||||
try {
|
||||
return 1
|
||||
}
|
||||
catch (e: UnsupportedOperationException) {
|
||||
doSmth(2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun t15() : Int {
|
||||
try {
|
||||
return 1
|
||||
}
|
||||
catch (e: UnsupportedOperationException) {
|
||||
return 2
|
||||
}
|
||||
finally {
|
||||
doSmth(3)
|
||||
}
|
||||
}
|
||||
|
||||
fun t16() : Int {
|
||||
try {
|
||||
doSmth(1)
|
||||
}
|
||||
catch (e: UnsupportedOperationException) {
|
||||
return 2
|
||||
}
|
||||
finally {
|
||||
doSmth(3)
|
||||
}
|
||||
}
|
||||
|
||||
fun doSmth(i: Int) {
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
//KT-58 Allow finally around definite returns
|
||||
|
||||
namespace kt58
|
||||
|
||||
import java.util.concurrent.locks.Lock
|
||||
|
||||
fun lock<T>(lock : Lock, body : fun () : T) : T {
|
||||
lock.lock()
|
||||
try {
|
||||
return body()
|
||||
}
|
||||
finally {
|
||||
lock.unlock(); // we report an error, but we chouldn't
|
||||
}
|
||||
}
|
||||
|
||||
//more tests
|
||||
fun t1() : Int {
|
||||
try {
|
||||
<!UNREACHABLE_CODE!>return 1<!>
|
||||
}
|
||||
finally {
|
||||
return 2
|
||||
}
|
||||
}
|
||||
|
||||
fun t2() : Int {
|
||||
try {
|
||||
return 1
|
||||
}
|
||||
finally {
|
||||
doSmth(3)
|
||||
}
|
||||
}
|
||||
|
||||
fun t3() : Int {
|
||||
try {
|
||||
return 1
|
||||
}
|
||||
catch (e: UnsupportedOperationException) {
|
||||
doSmth(2)
|
||||
}
|
||||
finally {
|
||||
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>doSmth(3)<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun t4() : Int {
|
||||
try {
|
||||
return 1
|
||||
}
|
||||
catch (e: UnsupportedOperationException) {
|
||||
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>doSmth(2)<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun t5() : Int {
|
||||
try {
|
||||
return 1
|
||||
}
|
||||
catch (e: UnsupportedOperationException) {
|
||||
return 2
|
||||
}
|
||||
}
|
||||
|
||||
fun t6() : Int {
|
||||
try {
|
||||
return 1
|
||||
}
|
||||
catch (e: UnsupportedOperationException) {
|
||||
return 2
|
||||
}
|
||||
finally {
|
||||
doSmth(3)
|
||||
}
|
||||
}
|
||||
|
||||
fun t7() : Int {
|
||||
try {
|
||||
doSmth(1)
|
||||
}
|
||||
catch (e: UnsupportedOperationException) {
|
||||
return 2
|
||||
}
|
||||
finally {
|
||||
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>doSmth(3)<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun doSmth(i: Int) {
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
package org.jetbrains.jet.cfg;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import junit.framework.Test;
|
||||
@@ -125,7 +126,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
||||
instructionDump.append("=====================\n");
|
||||
|
||||
//check edges directions
|
||||
Collection<Instruction> instructions = pseudocode.getInstructions();
|
||||
Collection<Instruction> instructions = pseudocode.getMutableInstructionList();
|
||||
for (Instruction instruction : instructions) {
|
||||
if (!instruction.isDead()) {
|
||||
for (Instruction nextInstruction : instruction.getNextInstructions()) {
|
||||
@@ -157,7 +158,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
||||
}
|
||||
|
||||
public void dfsDump(Pseudocode pseudocode, StringBuilder nodes, StringBuilder edges, Map<Instruction, String> nodeNames) {
|
||||
dfsDump(nodes, edges, pseudocode.getInstructions().get(0), nodeNames);
|
||||
dfsDump(nodes, edges, pseudocode.getMutableInstructionList().get(0), nodeNames);
|
||||
}
|
||||
|
||||
private void dfsDump(StringBuilder nodes, StringBuilder edges, Instruction instruction, Map<Instruction, String> nodeNames) {
|
||||
@@ -172,9 +173,10 @@ public class JetControlFlowTest extends JetLiteFixture {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
private static String formatInstruction(Instruction instruction, int maxLength) {
|
||||
private static String formatInstruction(Instruction instruction, int maxLength, Set<Instruction> remainedAfterPostProcessInstructions) {
|
||||
String[] parts = instruction.toString().split("\n");
|
||||
String prefix = instruction.isDead() ? "* " : " ";
|
||||
boolean isRemovedThroughPostProcess = !remainedAfterPostProcessInstructions.contains(instruction);
|
||||
String prefix = isRemovedThroughPostProcess ? "R " : instruction.isDead() ? "* " : " ";
|
||||
if (parts.length == 1) {
|
||||
return prefix + String.format("%1$-" + maxLength + "s", instruction);
|
||||
}
|
||||
@@ -218,7 +220,8 @@ public class JetControlFlowTest extends JetLiteFixture {
|
||||
}
|
||||
|
||||
public void dumpInstructions(Pseudocode pseudocode, @NotNull StringBuilder out) {
|
||||
List<Instruction> instructions = pseudocode.getInstructions();
|
||||
List<Instruction> instructions = pseudocode.getMutableInstructionList();
|
||||
Set<Instruction> remainedAfterPostProcessInstructions = Sets.newHashSet(pseudocode.getInstructions());
|
||||
List<Pseudocode.PseudocodeLabel> labels = pseudocode.getLabels();
|
||||
List<Pseudocode> locals = new ArrayList<Pseudocode>();
|
||||
int maxLength = 0;
|
||||
@@ -257,7 +260,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
||||
}
|
||||
}
|
||||
|
||||
out.append(formatInstruction(instruction, maxLength)).
|
||||
out.append(formatInstruction(instruction, maxLength, remainedAfterPostProcessInstructions)).
|
||||
append(" NEXT:").append(String.format("%1$-" + maxNextLength + "s", formatInstructionList(instruction.getNextInstructions()))).
|
||||
append(" PREV:").append(formatInstructionList(instruction.getPreviousInstructions())).append("\n");
|
||||
}
|
||||
@@ -273,7 +276,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
||||
public void visitLocalDeclarationInstruction(LocalDeclarationInstruction 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);
|
||||
printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getBody().getMutableInstructionList().get(0)), null);
|
||||
visitInstructionWithNext(instruction);
|
||||
}
|
||||
|
||||
@@ -336,7 +339,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
||||
}
|
||||
}
|
||||
|
||||
public void dumpNodes(List<Instruction> instructions, PrintStream out, int[] count, Map<Instruction, String> nodeToName) {
|
||||
public void dumpNodes(List<Instruction> instructions, PrintStream out, int[] count, Map<Instruction, String> nodeToName, Set<Instruction> remainedAfterPostProcessInstructions) {
|
||||
for (Instruction node : instructions) {
|
||||
String name = "n" + count[0]++;
|
||||
nodeToName.put(node, name);
|
||||
@@ -361,6 +364,9 @@ public class JetControlFlowTest extends JetLiteFixture {
|
||||
else if (node instanceof SubroutineEnterInstruction || node instanceof SubroutineExitInstruction) {
|
||||
shape = "roundrect, style=rounded";
|
||||
}
|
||||
if (!remainedAfterPostProcessInstructions.contains(node)) {
|
||||
shape += "box, fillcolor=grey, style=filled";
|
||||
}
|
||||
out.println(name + "[label=\"" + text + "\", shape=" + shape + "];");
|
||||
}
|
||||
}
|
||||
@@ -385,7 +391,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
||||
int[] count = new int[1];
|
||||
Map<Instruction, String> nodeToName = new HashMap<Instruction, String>();
|
||||
for (Pseudocode pseudocode : pseudocodes) {
|
||||
dumpNodes(pseudocode.getInstructions(), out, count, nodeToName);
|
||||
dumpNodes(pseudocode.getMutableInstructionList(), out, count, nodeToName, Sets.newHashSet(pseudocode.getInstructions()));
|
||||
}
|
||||
int i = 0;
|
||||
for (Pseudocode pseudocode : pseudocodes) {
|
||||
@@ -401,7 +407,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
||||
out.println("subgraph cluster_" + i + " {\n" +
|
||||
"label=\"" + label + "\";\n" +
|
||||
"color=blue;\n");
|
||||
dumpEdges(pseudocode.getInstructions(), out, count, nodeToName);
|
||||
dumpEdges(pseudocode.getMutableInstructionList(), out, count, nodeToName);
|
||||
out.println("}");
|
||||
i++;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user