Pseudocode: Generate fake values for Unit/Nothing-typed expressions

This commit is contained in:
Alexey Sedunov
2014-07-23 12:56:21 +04:00
parent 2d3ac9109b
commit 77bbf8f73b
72 changed files with 851 additions and 592 deletions
@@ -98,6 +98,8 @@ public interface JetControlFlowBuilder {
@Nullable @Nullable
PseudoValue getBoundValue(@Nullable JetElement element); PseudoValue getBoundValue(@Nullable JetElement element);
void bindValue(@NotNull PseudoValue value, @NotNull JetElement element); void bindValue(@NotNull PseudoValue value, @NotNull JetElement element);
@NotNull
PseudoValue newValue(@Nullable JetElement element);
void loadUnit(@NotNull JetExpression expression); void loadUnit(@NotNull JetExpression expression);
@@ -288,6 +288,12 @@ public abstract class JetControlFlowBuilderAdapter implements JetControlFlowBuil
getDelegateBuilder().bindValue(value, element); getDelegateBuilder().bindValue(value, element);
} }
@NotNull
@Override
public PseudoValue newValue(@Nullable JetElement element) {
return getDelegateBuilder().newValue(element);
}
@Override @Override
public void enterLexicalScope(@NotNull JetElement element) { public void enterLexicalScope(@NotNull JetElement element) {
getDelegateBuilder().enterLexicalScope(element); getDelegateBuilder().enterLexicalScope(element);
@@ -22,7 +22,6 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.SmartFMap; import com.intellij.util.SmartFMap;
import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtil;
import jet.runtime.typeinfo.JetValueParameter;
import kotlin.Function0; import kotlin.Function0;
import kotlin.Function1; import kotlin.Function1;
import kotlin.KotlinPackage; import kotlin.KotlinPackage;
@@ -235,12 +234,20 @@ public class JetControlFlowProcessor {
} }
private void copyValue(@Nullable JetElement from, @NotNull JetElement to) { private void copyValue(@Nullable JetElement from, @NotNull JetElement to) {
PseudoValue value = builder.getBoundValue(from); PseudoValue value = getBoundOrUnreachableValue(from);
if (value != null) { if (value != null) {
builder.bindValue(value, to); builder.bindValue(value, to);
} }
} }
@Nullable
private PseudoValue getBoundOrUnreachableValue(@Nullable JetElement element) {
if (element == null) return null;
PseudoValue value = builder.getBoundValue(element);
return value != null || element instanceof JetDeclaration ? value : builder.newValue(element);
}
private List<PseudoValue> elementsToValues(List<? extends JetElement> from) { private List<PseudoValue> elementsToValues(List<? extends JetElement> from) {
if (from.isEmpty()) return Collections.emptyList(); if (from.isEmpty()) return Collections.emptyList();
return KotlinPackage.filterNotNull( return KotlinPackage.filterNotNull(
@@ -249,7 +256,7 @@ public class JetControlFlowProcessor {
new Function1<JetElement, PseudoValue>() { new Function1<JetElement, PseudoValue>() {
@Override @Override
public PseudoValue invoke(JetElement element) { public PseudoValue invoke(JetElement element) {
return builder.getBoundValue(element); return getBoundOrUnreachableValue(element);
} }
} }
) )
@@ -427,7 +434,7 @@ public class JetControlFlowProcessor {
@Override @Override
public PseudoValue invoke() { public PseudoValue invoke() {
generateInstructions(expression); generateInstructions(expression);
return builder.getBoundValue(expression); return getBoundOrUnreachableValue(expression);
} }
}; };
} }
@@ -1234,7 +1241,7 @@ public class JetControlFlowProcessor {
JetExpression left = expression.getLeft(); JetExpression left = expression.getLeft();
if (operationType == JetTokens.COLON || operationType == JetTokens.AS_KEYWORD || operationType == JetTokens.AS_SAFE) { if (operationType == JetTokens.COLON || operationType == JetTokens.AS_KEYWORD || operationType == JetTokens.AS_SAFE) {
generateInstructions(left); generateInstructions(left);
if (builder.getBoundValue(left) != null) { if (getBoundOrUnreachableValue(left) != null) {
createNonSyntheticValue(expression, MagicKind.CAST, left); createNonSyntheticValue(expression, MagicKind.CAST, left);
} }
} }
@@ -1428,7 +1435,8 @@ public class JetControlFlowProcessor {
List<PseudoValue> arguments = ContainerUtil.createMaybeSingletonList(builder.getBoundValue(specifier.getDelegateExpression())); List<PseudoValue> arguments = ContainerUtil.createMaybeSingletonList(builder.getBoundValue(specifier.getDelegateExpression()));
JetType jetType = trace.get(BindingContext.TYPE, specifier.getTypeReference()); JetType jetType = trace.get(BindingContext.TYPE, specifier.getTypeReference());
TypePredicate expectedTypePredicate = jetType != null ? PseudocodePackage.getSubtypesPredicate(jetType) : AllTypes.INSTANCE$; TypePredicate expectedTypePredicate = jetType != null ? PseudocodePackage.getSubtypesPredicate(jetType) : AllTypes.INSTANCE$;
builder.magic(specifier, null, arguments, PseudocodePackage.expectedTypeFor(expectedTypePredicate, arguments), MagicKind.VALUE_CONSUMER); builder.magic(specifier, null, arguments, PseudocodePackage.expectedTypeFor(expectedTypePredicate, arguments),
MagicKind.VALUE_CONSUMER);
} }
@Override @Override
@@ -1539,7 +1547,7 @@ public class JetControlFlowProcessor {
generateInstructions(expression); generateInstructions(expression);
} }
PseudoValue receiverPseudoValue = builder.getBoundValue(expression); PseudoValue receiverPseudoValue = getBoundOrUnreachableValue(expression);
if (receiverPseudoValue != null) { if (receiverPseudoValue != null) {
receiverValues = receiverValues.plus(receiverPseudoValue, receiver); receiverValues = receiverValues.plus(receiverPseudoValue, receiver);
} }
@@ -1578,7 +1586,7 @@ public class JetControlFlowProcessor {
generateInstructions(expression); generateInstructions(expression);
} }
PseudoValue argValue = builder.getBoundValue(expression); PseudoValue argValue = getBoundOrUnreachableValue(expression);
if (argValue != null) { if (argValue != null) {
parameterValues = parameterValues.plus(argValue, parameterDescriptor); parameterValues = parameterValues.plus(argValue, parameterDescriptor);
} }
@@ -106,7 +106,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
private final PseudoValueFactory valueFactory = new PseudoValueFactoryImpl() { private final PseudoValueFactory valueFactory = new PseudoValueFactoryImpl() {
@NotNull @NotNull
@Override @Override
public PseudoValue newValue(@Nullable JetElement element, @NotNull InstructionWithValue instruction) { public PseudoValue newValue(@Nullable JetElement element, @Nullable InstructionWithValue instruction) {
PseudoValue value = super.newValue(element, instruction); PseudoValue value = super.newValue(element, instruction);
if (element != null) { if (element != null) {
bindValue(value, element); bindValue(value, element);
@@ -283,6 +283,12 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
pseudocode.bindElementToValue(element, value); pseudocode.bindElementToValue(element, value);
} }
@NotNull
@Override
public PseudoValue newValue(@Nullable JetElement element) {
return valueFactory.newValue(element, null);
}
@Override @Override
public void returnValue(@NotNull JetExpression returnExpression, @NotNull PseudoValue returnValue, @NotNull JetElement subroutine) { public void returnValue(@NotNull JetExpression returnExpression, @NotNull PseudoValue returnValue, @NotNull JetElement subroutine) {
Label exitPoint = getExitPoint(subroutine); Label exitPoint = getExitPoint(subroutine);
@@ -22,9 +22,9 @@ import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.InstructionWithVa
public trait PseudoValue { public trait PseudoValue {
public val debugName: String public val debugName: String
public val element: JetElement? public val element: JetElement?
public val createdAt: InstructionWithValue public val createdAt: InstructionWithValue?
} }
public trait PseudoValueFactory { public trait PseudoValueFactory {
public fun newValue(element: JetElement?, instruction: InstructionWithValue): PseudoValue public fun newValue(element: JetElement?, instruction: InstructionWithValue?): PseudoValue
} }
@@ -22,7 +22,7 @@ import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.InstructionWithVa
class PseudoValueImpl( class PseudoValueImpl(
override val debugName: String, override val debugName: String,
override val element: JetElement?, override val element: JetElement?,
override val createdAt: InstructionWithValue override val createdAt: InstructionWithValue?
) : PseudoValue { ) : PseudoValue {
override fun toString(): String = debugName override fun toString(): String = debugName
} }
@@ -30,7 +30,7 @@ class PseudoValueImpl(
open class PseudoValueFactoryImpl: PseudoValueFactory { open class PseudoValueFactoryImpl: PseudoValueFactory {
private var lastIndex: Int = 0 private var lastIndex: Int = 0
override fun newValue(element: JetElement?, instruction: InstructionWithValue): PseudoValue { override fun newValue(element: JetElement?, instruction: InstructionWithValue?): PseudoValue {
return PseudoValueImpl("<v${lastIndex++}>", element, instruction) return PseudoValueImpl((instruction?.let { "" } ?: "!") + "<v${lastIndex++}>", element, instruction)
} }
} }
@@ -54,7 +54,9 @@ fun getReceiverTypePredicate(resolvedCall: ResolvedCall<*>, receiverValue: Recei
} }
fun getExpectedTypePredicate(value: PseudoValue, bindingContext: BindingContext): TypePredicate { fun getExpectedTypePredicate(value: PseudoValue, bindingContext: BindingContext): TypePredicate {
val pseudocode = value.createdAt.owner val pseudocode = value.createdAt?.owner
if (pseudocode == null) return AllTypes
val typePredicates = LinkedHashSet<TypePredicate?>() val typePredicates = LinkedHashSet<TypePredicate?>()
fun addSubtypesOf(jetType: JetType?) = typePredicates.add(jetType?.getSubtypesPredicate()) fun addSubtypesOf(jetType: JetType?) = typePredicates.add(jetType?.getSubtypesPredicate())
@@ -66,7 +68,7 @@ fun getExpectedTypePredicate(value: PseudoValue, bindingContext: BindingContext)
val returnElement = it.element val returnElement = it.element
val functionDescriptor = when(returnElement) { val functionDescriptor = when(returnElement) {
is JetReturnExpression -> returnElement.getTargetFunctionDescriptor(bindingContext) is JetReturnExpression -> returnElement.getTargetFunctionDescriptor(bindingContext)
else -> bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, value.createdAt.owner.getCorrespondingElement()] else -> bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, pseudocode.getCorrespondingElement()]
} }
addSubtypesOf((functionDescriptor as? CallableDescriptor)?.getReturnType()) addSubtypesOf((functionDescriptor as? CallableDescriptor)?.getReturnType())
} }
@@ -10,31 +10,32 @@ fun foo() {
} }
--------------------- ---------------------
L0: L0:
1 <START> INIT: in: {} out: {} USE: in: {} out: {} 1 <START> INIT: in: {} out: {} USE: in: {} out: {}
2 mark({ val b: Boolean if (1 < 2) { use(b) } else { b = true } }) 2 mark({ val b: Boolean if (1 < 2) { use(b) } else { b = true } })
v(val b: Boolean) INIT: in: {} out: {b=D} v(val b: Boolean) INIT: in: {} out: {b=D}
mark(if (1 < 2) { use(b) } else { b = true }) INIT: in: {b=D} out: {b=D} mark(if (1 < 2) { use(b) } else { b = true }) INIT: in: {b=D} out: {b=D}
r(1) -> <v0> r(1) -> <v0>
r(2) -> <v1> r(2) -> <v1>
mark(1 < 2) mark(1 < 2)
call(1 < 2, compareTo|<v0>, <v1>) -> <v2> call(1 < 2, compareTo|<v0>, <v1>) -> <v2>
jf(L2|<v2>) jf(L2|<v2>)
3 mark({ use(b) }) USE: in: {b=READ} out: {b=READ} 3 mark({ use(b) }) USE: in: {b=READ} out: {b=READ}
r(b) -> <v3> USE: in: {} out: {b=READ} r(b) -> <v3> USE: in: {} out: {b=READ}
mark(use(b)) mark(use(b))
call(use(b), use|<v3>) -> <v4> call(use(b), use|<v3>) -> <v4>
2 jmp(L3) USE: in: {} out: {} 2 jmp(L3) USE: in: {} out: {}
L2: L2:
3 mark({ b = true }) 3 mark({ b = true })
r(true) -> <v5> USE: in: {b=ONLY_WRITTEN_NEVER_READ} out: {b=ONLY_WRITTEN_NEVER_READ} r(true) -> <v5> USE: in: {b=ONLY_WRITTEN_NEVER_READ} out: {b=ONLY_WRITTEN_NEVER_READ}
w(b|<v5>) INIT: in: {b=D} out: {b=ID} USE: in: {} out: {b=ONLY_WRITTEN_NEVER_READ} w(b|<v5>) INIT: in: {b=D} out: {b=ID} USE: in: {} out: {b=ONLY_WRITTEN_NEVER_READ}
L1:
L3: L3:
1 <END> INIT: in: {} out: {} 2 merge(if (1 < 2) { use(b) } else { b = true }|<v4>, !<v6>) -> <v7> INIT: in: {b=D} out: {b=D}
L1:
1 <END> INIT: in: {} out: {}
error: error:
<ERROR> <ERROR>
sink: sink:
<SINK> USE: in: {} out: {} <SINK> USE: in: {} out: {}
===================== =====================
== use == == use ==
fun use(vararg a: Any?) = a fun use(vararg a: Any?) = a
@@ -16,8 +16,10 @@ b <v3>: *
use(b) <v4>: * NEW: call(use(b), use|<v3>) -> <v4> use(b) <v4>: * NEW: call(use(b), use|<v3>) -> <v4>
{ use(b) } <v4>: * COPY { use(b) } <v4>: * COPY
true <v5>: Boolean NEW: r(true) -> <v5> true <v5>: Boolean NEW: r(true) -> <v5>
if (1 < 2) { use(b) } else { b = true } <v4>: * COPY b = true !<v6>: *
{ val b: Boolean if (1 < 2) { use(b) } else { b = true } } <v4>: * COPY { b = true } !<v6>: * COPY
if (1 < 2) { use(b) } else { b = true } <v7>: * NEW: merge(if (1 < 2) { use(b) } else { b = true }|<v4>, !<v6>) -> <v7>
{ val b: Boolean if (1 < 2) { use(b) } else { b = true } } <v7>: * COPY
===================== =====================
== use == == use ==
fun use(vararg a: Any?) = a fun use(vararg a: Any?) = a
@@ -6,6 +6,8 @@ class A {
val x: Int val x: Int
} }
--------------------- ---------------------
<v0>: A NEW: magic[IMPLICIT_RECEIVER](x) -> <v0> <v0>: A NEW: magic[IMPLICIT_RECEIVER](x) -> <v0>
1 <v1>: Int NEW: r(1) -> <v1> 1 <v1>: Int NEW: r(1) -> <v1>
x = 1 !<v2>: *
{ x = 1 } !<v2>: * COPY
===================== =====================
@@ -20,7 +20,9 @@ fun bar() {
b = 3 b = 3
} }
--------------------- ---------------------
3 <v0>: Int NEW: r(3) -> <v0> 3 <v0>: Int NEW: r(3) -> <v0>
b = 3 !<v1>: *
{ val b: Int b = 3 } !<v1>: * COPY
===================== =====================
== use == == use ==
fun use(a: Int) = a fun use(a: Int) = a
@@ -26,14 +26,15 @@ L0:
2 jmp(L3) INIT: in: {b=ID} out: {b=ID} USE: in: {b=READ} out: {b=READ} 2 jmp(L3) INIT: in: {b=ID} out: {b=ID} USE: in: {b=READ} out: {b=READ}
L2: L2:
3 mark({ b = true }) INIT: in: {b=D} out: {b=D} 3 mark({ b = true }) INIT: in: {b=D} out: {b=D}
r(true) -> <v4> USE: in: {b=WRITTEN_AFTER_READ} out: {b=WRITTEN_AFTER_READ} r(true) -> <v5> USE: in: {b=WRITTEN_AFTER_READ} out: {b=WRITTEN_AFTER_READ}
w(b|<v4>) INIT: in: {b=D} out: {b=ID} USE: in: {b=READ} out: {b=WRITTEN_AFTER_READ} w(b|<v5>) INIT: in: {b=D} out: {b=ID} USE: in: {b=READ} out: {b=WRITTEN_AFTER_READ}
L3: L3:
2 error(use(b), No resolved call) INIT: in: {b=ID} out: {b=ID} USE: in: {b=READ} out: {b=READ} 2 merge(if (1 < 2) { b = false } else { b = true }|!<v4>, !<v6>) -> <v7> INIT: in: {b=ID} out: {b=ID}
r(b) -> <v5> USE: in: {} out: {b=READ} error(use(b), No resolved call) USE: in: {b=READ} out: {b=READ}
r(b) -> <v8> USE: in: {} out: {b=READ}
error(use, No resolved call) error(use, No resolved call)
mark(use(b)) mark(use(b))
magic[UNRESOLVED_CALL](use(b)|<v5>) -> <v6> magic[UNRESOLVED_CALL](use(b)|<v8>, !<v9>) -> <v10>
L1: L1:
1 <END> INIT: in: {} out: {} 1 <END> INIT: in: {} out: {}
error: error:
@@ -14,8 +14,14 @@ fun foo() {
2 <v1>: Int NEW: r(2) -> <v1> 2 <v1>: Int NEW: r(2) -> <v1>
1 < 2 <v2>: Boolean NEW: call(1 < 2, compareTo|<v0>, <v1>) -> <v2> 1 < 2 <v2>: Boolean NEW: call(1 < 2, compareTo|<v0>, <v1>) -> <v2>
false <v3>: Boolean NEW: r(false) -> <v3> false <v3>: Boolean NEW: r(false) -> <v3>
true <v4>: Boolean NEW: r(true) -> <v4> b = false !<v4>: *
b <v5>: * NEW: r(b) -> <v5> { b = false } !<v4>: * COPY
use(b) <v6>: * NEW: magic[UNRESOLVED_CALL](use(b)|<v5>) -> <v6> true <v5>: Boolean NEW: r(true) -> <v5>
{ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) } <v6>: * COPY b = true !<v6>: *
{ b = true } !<v6>: * COPY
if (1 < 2) { b = false } else { b = true } <v7>: * NEW: merge(if (1 < 2) { b = false } else { b = true }|!<v4>, !<v6>) -> <v7>
use !<v9>: *
b <v8>: * NEW: r(b) -> <v8>
use(b) <v10>: * NEW: magic[UNRESOLVED_CALL](use(b)|<v8>, !<v9>) -> <v10>
{ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) } <v10>: * COPY
===================== =====================
@@ -42,12 +42,13 @@ L5 [body entry point]:
4 jmp(L7) INIT: in: {b=ID, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {b=READ} out: {b=READ} 4 jmp(L7) INIT: in: {b=ID, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {b=READ} out: {b=READ}
L6: L6:
5 mark({ b = true }) INIT: in: {b=D, i=ID, numbers=ID} out: {b=D, i=ID, numbers=ID} 5 mark({ b = true }) INIT: in: {b=D, i=ID, numbers=ID} out: {b=D, i=ID, numbers=ID}
r(true) -> <v7> USE: in: {b=WRITTEN_AFTER_READ} out: {b=WRITTEN_AFTER_READ} r(true) -> <v8> USE: in: {b=WRITTEN_AFTER_READ} out: {b=WRITTEN_AFTER_READ}
w(b|<v7>) INIT: in: {b=D, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {b=READ} out: {b=WRITTEN_AFTER_READ} w(b|<v8>) INIT: in: {b=D, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {b=READ} out: {b=WRITTEN_AFTER_READ}
L7: L7:
4 r(b) -> <v8> INIT: in: {b=ID, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {} out: {b=READ} 4 merge(if (1 < 2) { b = false } else { b = true }|!<v7>, !<v9>) -> <v10> INIT: in: {b=ID, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {b=READ} out: {b=READ}
r(b) -> <v11> USE: in: {} out: {b=READ}
mark(use(b)) mark(use(b))
call(use(b), use|<v8>) -> <v9> call(use(b), use|<v11>) -> <v12>
jmp(L4 [loop entry point]) USE: in: {} out: {} jmp(L4 [loop entry point]) USE: in: {} out: {}
- 3 jmp?(L4 [loop entry point]) - 3 jmp?(L4 [loop entry point])
L2: L2:
@@ -13,16 +13,25 @@ fun foo(numbers: Collection<Int>) {
} }
} }
--------------------- ---------------------
<v0>: {<: Collection<Int>} NEW: magic[FAKE_INITIALIZER](numbers: Collection<Int>) -> <v0> <v0>: {<: Collection<Int>} NEW: magic[FAKE_INITIALIZER](numbers: Collection<Int>) -> <v0>
<v2>: Int NEW: magic[LOOP_RANGE_ITERATION](numbers|<v1>) -> <v2> <v2>: Int NEW: magic[LOOP_RANGE_ITERATION](numbers|<v1>) -> <v2>
numbers <v1>: {<: Iterable<Int>} NEW: r(numbers) -> <v1> numbers <v1>: {<: Iterable<Int>} NEW: r(numbers) -> <v1>
1 <v3>: {<: Comparable<Int>} NEW: r(1) -> <v3> 1 <v3>: {<: Comparable<Int>} NEW: r(1) -> <v3>
2 <v4>: Int NEW: r(2) -> <v4> 2 <v4>: Int NEW: r(2) -> <v4>
1 < 2 <v5>: Boolean NEW: call(1 < 2, compareTo|<v3>, <v4>) -> <v5> 1 < 2 <v5>: Boolean NEW: call(1 < 2, compareTo|<v3>, <v4>) -> <v5>
false <v6>: Boolean NEW: r(false) -> <v6> false <v6>: Boolean NEW: r(false) -> <v6>
true <v7>: Boolean NEW: r(true) -> <v7> b = false !<v7>: *
b <v8>: * NEW: r(b) -> <v8> { b = false } !<v7>: * COPY
use(b) <v9>: * NEW: call(use(b), use|<v8>) -> <v9> true <v8>: Boolean NEW: r(true) -> <v8>
b = true !<v9>: *
{ b = true } !<v9>: * COPY
if (1 < 2) { b = false } else { b = true } <v10>: * NEW: merge(if (1 < 2) { b = false } else { b = true }|!<v7>, !<v9>) -> <v10>
b <v11>: * NEW: r(b) -> <v11>
use(b) <v12>: * NEW: call(use(b), use|<v11>) -> <v12>
continue !<v13>: *
{ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue } !<v13>: * COPY
for (i in numbers) { val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue } !<v14>: *
{ for (i in numbers) { val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue } } !<v14>: * COPY
===================== =====================
== use == == use ==
fun use(vararg a: Any?) = a fun use(vararg a: Any?) = a
@@ -11,7 +11,7 @@ fun foo() {
} }
--------------------- ---------------------
L0: L0:
1 <START> INIT: in: {} out: {} 1 <START> INIT: in: {} out: {}
2 mark({ "before" if (true) { val a = 1 } else { val b = 2 } "after" }) 2 mark({ "before" if (true) { val a = 1 } else { val b = 2 } "after" })
mark("before") mark("before")
r("before") -> <v0> r("before") -> <v0>
@@ -19,22 +19,23 @@ L0:
r(true) -> <v1> r(true) -> <v1>
jf(L2|<v1>) jf(L2|<v1>)
3 mark({ val a = 1 }) 3 mark({ val a = 1 })
v(val a = 1) INIT: in: {} out: {a=D} v(val a = 1) INIT: in: {} out: {a=D}
r(1) -> <v2> INIT: in: {a=D} out: {a=D} r(1) -> <v2> INIT: in: {a=D} out: {a=D}
w(a|<v2>) INIT: in: {a=D} out: {a=ID} w(a|<v2>) INIT: in: {a=D} out: {a=ID}
2 jmp(L3) INIT: in: {} out: {} 2 jmp(L3) INIT: in: {} out: {}
L2: L2:
3 mark({ val b = 2 }) 3 mark({ val b = 2 })
v(val b = 2) INIT: in: {} out: {b=D} v(val b = 2) INIT: in: {} out: {b=D}
r(2) -> <v3> INIT: in: {b=D} out: {b=D} r(2) -> <v3> INIT: in: {b=D} out: {b=D}
w(b|<v3>) INIT: in: {b=D} out: {b=ID} w(b|<v3>) INIT: in: {b=D} out: {b=ID}
L3: L3:
2 mark("after") INIT: in: {} out: {} 2 merge(if (true) { val a = 1 } else { val b = 2 }|!<v4>, !<v5>) -> <v6> INIT: in: {} out: {}
r("after") -> <v4> mark("after")
r("after") -> <v7>
L1: L1:
1 <END> 1 <END>
error: error:
<ERROR> <ERROR>
sink: sink:
<SINK> USE: in: {} out: {} <SINK> USE: in: {} out: {}
===================== =====================
@@ -13,7 +13,10 @@ fun foo() {
"before" <v0>: * NEW: r("before") -> <v0> "before" <v0>: * NEW: r("before") -> <v0>
true <v1>: Boolean NEW: r(true) -> <v1> true <v1>: Boolean NEW: r(true) -> <v1>
1 <v2>: Int NEW: r(1) -> <v2> 1 <v2>: Int NEW: r(1) -> <v2>
{ val a = 1 } !<v4>: *
2 <v3>: Int NEW: r(2) -> <v3> 2 <v3>: Int NEW: r(2) -> <v3>
"after" <v4>: * NEW: r("after") -> <v4> { val b = 2 } !<v5>: *
{ "before" if (true) { val a = 1 } else { val b = 2 } "after" } <v4>: * COPY if (true) { val a = 1 } else { val b = 2 } <v6>: * NEW: merge(if (true) { val a = 1 } else { val b = 2 }|!<v4>, !<v5>) -> <v6>
"after" <v7>: * NEW: r("after") -> <v7>
{ "before" if (true) { val a = 1 } else { val b = 2 } "after" } <v7>: * COPY
===================== =====================
@@ -17,15 +17,19 @@ get() {
return $a return $a
} }
--------------------- ---------------------
<v0>: A NEW: magic[IMPLICIT_RECEIVER]($a) -> <v0> <v0>: A NEW: magic[IMPLICIT_RECEIVER]($a) -> <v0>
$a <v1>: Int NEW: r($a|<v0>) -> <v1> $a <v1>: Int NEW: r($a|<v0>) -> <v1>
return $a !<v2>: *
{ return $a } !<v2>: * COPY
===================== =====================
== set_a == == set_a ==
set(v: Int) { set(v: Int) {
$a = v $a = v
} }
--------------------- ---------------------
<v0>: Int NEW: magic[FAKE_INITIALIZER](v: Int) -> <v0> <v0>: Int NEW: magic[FAKE_INITIALIZER](v: Int) -> <v0>
<v1>: A NEW: magic[IMPLICIT_RECEIVER]($a) -> <v1> <v1>: A NEW: magic[IMPLICIT_RECEIVER]($a) -> <v1>
v <v2>: Int NEW: r(v) -> <v2> v <v2>: Int NEW: r(v) -> <v2>
$a = v !<v3>: *
{ $a = v } !<v3>: * COPY
===================== =====================
@@ -49,8 +49,9 @@ L5 [skipFinallyToErrorBlock]:
v(val a = 1) INIT: in: {} out: {a=D} v(val a = 1) INIT: in: {} out: {a=D}
r(1) -> <v4> INIT: in: {a=D} out: {a=D} r(1) -> <v4> INIT: in: {a=D} out: {a=D}
w(a|<v4>) INIT: in: {a=D} out: {a=ID} w(a|<v4>) INIT: in: {a=D} out: {a=ID}
2 mark("after") INIT: in: {} out: {} 2 merge(try { foo() } catch (e: Exception) { val a = e } finally { val a = 1 }|<v1>, !<v5>) -> <v6> INIT: in: {} out: {}
r("after") -> <v5> mark("after")
r("after") -> <v7>
L1: L1:
1 <END> 1 <END>
error: error:
@@ -18,8 +18,9 @@ fun foo() {
foo() <v1>: * NEW: call(foo(), foo) -> <v1> foo() <v1>: * NEW: call(foo(), foo) -> <v1>
{ foo() } <v1>: * COPY { foo() } <v1>: * COPY
e <v3>: {<: Exception} NEW: r(e) -> <v3> e <v3>: {<: Exception} NEW: r(e) -> <v3>
{ val a = e } !<v5>: *
1 <v4>: Int NEW: r(1) -> <v4> 1 <v4>: Int NEW: r(1) -> <v4>
try { foo() } catch (e: Exception) { val a = e } finally { val a = 1 } <v1>: * COPY try { foo() } catch (e: Exception) { val a = e } finally { val a = 1 } <v6>: * NEW: merge(try { foo() } catch (e: Exception) { val a = e } finally { val a = 1 }|<v1>, !<v5>) -> <v6>
"after" <v5>: * NEW: r("after") -> <v5> "after" <v7>: * NEW: r("after") -> <v7>
{ "before" try { foo() } catch (e: Exception) { val a = e } finally { val a = 1 } "after" } <v5>: * COPY { "before" try { foo() } catch (e: Exception) { val a = e } finally { val a = 1 } "after" } <v7>: * COPY
===================== =====================
@@ -22,9 +22,9 @@ L4 [body entry point]:
v(val a: Int) INIT: in: {} out: {a=D} v(val a: Int) INIT: in: {} out: {a=D}
2 jmp(L2 [loop entry point]) INIT: in: {} out: {} USE: in: {} out: {} 2 jmp(L2 [loop entry point]) INIT: in: {} out: {} USE: in: {} out: {}
L3 [loop exit point]: L3 [loop exit point]:
- read (Unit) -> <v3> - read (Unit)
- mark("after") - mark("after")
- r("after") -> <v4> - r("after") -> <v3>
L1: L1:
1 <END> INIT: in: {} out: {} 1 <END> INIT: in: {} out: {}
error: error:
@@ -46,11 +46,12 @@ sink:
L7: L7:
5 <START> 5 <START>
6 mark(break) 6 mark(break)
jmp(L2) NEXT:[read (Unit)] jmp(L2) NEXT:[read (Unit)]
- 5 ret(*|!<v0>) L8 PREV:[]
L8: L8:
5 <END> NEXT:[<SINK>] PREV:[] <END> NEXT:[<SINK>] PREV:[]
error: error:
<ERROR> PREV:[] <ERROR> PREV:[]
sink: sink:
<SINK> PREV:[<ERROR>, <END>] <SINK> PREV:[<ERROR>, <END>]
===================== =====================
@@ -7,15 +7,19 @@ fun foo(c: Collection<Int>) {
} }
} }
--------------------- ---------------------
<v0>: {<: Collection<Int>} NEW: magic[FAKE_INITIALIZER](c: Collection<Int>) -> <v0> <v0>: {<: Collection<Int>} NEW: magic[FAKE_INITIALIZER](c: Collection<Int>) -> <v0>
<v2>: Int NEW: magic[LOOP_RANGE_ITERATION](c|<v1>) -> <v2> <v2>: Int NEW: magic[LOOP_RANGE_ITERATION](c|<v1>) -> <v2>
c <v1>: {<: Iterable<Int>} NEW: r(c) -> <v1> c <v1>: {<: Iterable<Int>} NEW: r(c) -> <v1>
{ break } <v3>: * NEW: r({ break }) -> <v3> { break } <v3>: * NEW: r({ break }) -> <v3>
{ { break } } <v3>: * COPY { { break } } <v3>: * COPY
for (e in c) { { break } } !<v4>: *
{ for (e in c) { { break } } } !<v4>: * COPY
===================== =====================
== anonymous_0 == == anonymous_0 ==
{ {
break break
} }
--------------------- ---------------------
break !<v0>: *
break !<v0>: * COPY
===================== =====================
@@ -143,12 +143,13 @@ L4:
jf(L6|<v2>) NEXT:[read (Unit), mark({ return@l })] jf(L6|<v2>) NEXT:[read (Unit), mark({ return@l })]
6 mark({ return@l }) 6 mark({ return@l })
ret L5 NEXT:[<END>] ret L5 NEXT:[<END>]
- 5 jmp(L7) NEXT:[<END>] PREV:[] - 5 jmp(L7) NEXT:[ret(*|!<v3>) L5] PREV:[]
L6: L6:
read (Unit) PREV:[jf(L6|<v2>)] read (Unit) PREV:[jf(L6|<v2>)]
L5:
L7: L7:
4 <END> NEXT:[<SINK>] PREV:[ret L5, read (Unit)] 4 ret(*|!<v3>) L5
L5:
<END> NEXT:[<SINK>] PREV:[ret L5, ret(*|!<v3>) L5]
error: error:
<ERROR> PREV:[] <ERROR> PREV:[]
sink: sink:
@@ -227,8 +228,9 @@ L5 [onExceptionToFinallyBlock]:
L10 [skipFinallyToErrorBlock]: L10 [skipFinallyToErrorBlock]:
7 mark({ 2 }) PREV:[jmp(L10 [skipFinallyToErrorBlock])] 7 mark({ 2 }) PREV:[jmp(L10 [skipFinallyToErrorBlock])]
r(2) -> <v4> r(2) -> <v4>
3 ret(*|!<v5>) L4
L4: L4:
3 <END> NEXT:[<SINK>] PREV:[ret L4, r(2) -> <v4>] <END> NEXT:[<SINK>] PREV:[ret L4, ret(*|!<v5>) L4]
error: error:
<ERROR> PREV:[jmp(error)] <ERROR> PREV:[jmp(error)]
sink: sink:
@@ -342,17 +344,17 @@ L8:
3 jmp(L3 [loop entry point]) NEXT:[r(true) -> <v0>] 3 jmp(L3 [loop entry point]) NEXT:[r(true) -> <v0>]
L4 [loop exit point]: L4 [loop exit point]:
read (Unit) PREV:[jmp(L4 [loop exit point])] read (Unit) PREV:[jmp(L4 [loop exit point])]
r(5) -> <v6> r(5) -> <v8>
2 jmp(L9 [skipFinallyToErrorBlock]) NEXT:[mark({ 2 })] 2 jmp(L9 [skipFinallyToErrorBlock]) NEXT:[mark({ 2 })]
L2 [onExceptionToFinallyBlock]: L2 [onExceptionToFinallyBlock]:
L10 [start finally]: L10 [start finally]:
3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])] 3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])]
r(2) -> <v7> r(2) -> <v9>
L11 [finish finally]: L11 [finish finally]:
2 jmp(error) NEXT:[<ERROR>] 2 jmp(error) NEXT:[<ERROR>]
L9 [skipFinallyToErrorBlock]: L9 [skipFinallyToErrorBlock]:
3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])] 3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])]
r(2) -> <v7> r(2) -> <v9>
L1: L1:
1 <END> NEXT:[<SINK>] 1 <END> NEXT:[<SINK>]
error: error:
@@ -408,12 +410,12 @@ L4 [loop exit point]:
L2 [onExceptionToFinallyBlock]: L2 [onExceptionToFinallyBlock]:
L10 [start finally]: L10 [start finally]:
3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])] 3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])]
r(2) -> <v6> r(2) -> <v8>
L11 [finish finally]: L11 [finish finally]:
2 jmp(error) NEXT:[<ERROR>] 2 jmp(error) NEXT:[<ERROR>]
L9 [skipFinallyToErrorBlock]: L9 [skipFinallyToErrorBlock]:
3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])] 3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])]
r(2) -> <v6> r(2) -> <v8>
L1: L1:
1 <END> NEXT:[<SINK>] 1 <END> NEXT:[<SINK>]
error: error:
@@ -547,17 +549,17 @@ L8:
4 jmp?(L5 [loop entry point]) NEXT:[magic[LOOP_RANGE_ITERATION](1..a|<v3>) -> <v4>, read (Unit)] 4 jmp?(L5 [loop entry point]) NEXT:[magic[LOOP_RANGE_ITERATION](1..a|<v3>) -> <v4>, read (Unit)]
L3: L3:
read (Unit) PREV:[jmp?(L3), jmp?(L5 [loop entry point])] read (Unit) PREV:[jmp?(L3), jmp?(L5 [loop entry point])]
3 r(5) -> <v9> 3 r(5) -> <v11>
2 jmp(L9 [skipFinallyToErrorBlock]) NEXT:[mark({ 2 })] 2 jmp(L9 [skipFinallyToErrorBlock]) NEXT:[mark({ 2 })]
L2 [onExceptionToFinallyBlock]: L2 [onExceptionToFinallyBlock]:
L10 [start finally]: L10 [start finally]:
3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])] 3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])]
r(2) -> <v10> r(2) -> <v12>
L11 [finish finally]: L11 [finish finally]:
2 jmp(error) NEXT:[<ERROR>] 2 jmp(error) NEXT:[<ERROR>]
L9 [skipFinallyToErrorBlock]: L9 [skipFinallyToErrorBlock]:
3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])] 3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])]
r(2) -> <v10> r(2) -> <v12>
L1: L1:
1 <END> NEXT:[<SINK>] 1 <END> NEXT:[<SINK>]
error: error:
@@ -622,12 +624,12 @@ L3:
L2 [onExceptionToFinallyBlock]: L2 [onExceptionToFinallyBlock]:
L10 [start finally]: L10 [start finally]:
3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])] 3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])]
r(2) -> <v9> r(2) -> <v11>
L11 [finish finally]: L11 [finish finally]:
2 jmp(error) NEXT:[<ERROR>] 2 jmp(error) NEXT:[<ERROR>]
L9 [skipFinallyToErrorBlock]: L9 [skipFinallyToErrorBlock]:
3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])] 3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])]
r(2) -> <v9> r(2) -> <v11>
L1: L1:
1 <END> NEXT:[<SINK>] 1 <END> NEXT:[<SINK>]
error: error:
@@ -735,8 +737,8 @@ L0:
1 <START> 1 <START>
2 mark({ try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) } }) 2 mark({ try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) } })
mark(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) }) mark(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) })
jmp?(L2 [onException]) NEXT:[v(e: UnsupportedOperationException), jmp?(L3 [onExceptionToFinallyBlock])] jmp?(L2 [onException]) NEXT:[v(e: UnsupportedOperationException), jmp?(L3 [onExceptionToFinallyBlock])]
jmp?(L3 [onExceptionToFinallyBlock]) NEXT:[mark({ doSmth(3) }), mark({ return 1 })] jmp?(L3 [onExceptionToFinallyBlock]) NEXT:[mark({ doSmth(3) }), mark({ return 1 })]
3 mark({ return 1 }) 3 mark({ return 1 })
r(1) -> <v0> r(1) -> <v0>
L4 [start finally]: L4 [start finally]:
@@ -745,36 +747,37 @@ L4 [start finally]:
mark(doSmth(3)) mark(doSmth(3))
call(doSmth(3), doSmth|<v1>) -> <v2> call(doSmth(3), doSmth|<v1>) -> <v2>
L5 [finish finally]: L5 [finish finally]:
3 ret(*|<v0>) L1 NEXT:[<END>] 3 ret(*|<v0>) L1 NEXT:[<END>]
- 2 jmp(L6 [afterCatches]) NEXT:[jmp(L7 [skipFinallyToErrorBlock])] PREV:[] - 2 jmp(L6 [afterCatches]) NEXT:[jmp(L7 [skipFinallyToErrorBlock])] PREV:[]
L2 [onException]: L2 [onException]:
3 v(e: UnsupportedOperationException) PREV:[jmp?(L2 [onException])] 3 v(e: UnsupportedOperationException) PREV:[jmp?(L2 [onException])]
magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v3> magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v4>
w(e|<v3>) w(e|<v4>)
4 mark({ doSmth(2) }) 4 mark({ doSmth(2) })
r(2) -> <v4> r(2) -> <v5>
mark(doSmth(2)) mark(doSmth(2))
call(doSmth(2), doSmth|<v4>) -> <v5> call(doSmth(2), doSmth|<v5>) -> <v6>
3 jmp(L6 [afterCatches]) 3 jmp(L6 [afterCatches])
L6 [afterCatches]: L6 [afterCatches]:
2 jmp(L7 [skipFinallyToErrorBlock]) NEXT:[mark({ doSmth(3) })] 2 jmp(L7 [skipFinallyToErrorBlock]) NEXT:[mark({ doSmth(3) })]
L3 [onExceptionToFinallyBlock]: L3 [onExceptionToFinallyBlock]:
4 mark({ doSmth(3) }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])] 4 mark({ doSmth(3) }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])]
r(3) -> <v1> r(3) -> <v1>
mark(doSmth(3)) mark(doSmth(3))
call(doSmth(3), doSmth|<v1>) -> <v2> call(doSmth(3), doSmth|<v1>) -> <v2>
2 jmp(error) NEXT:[<ERROR>] 2 jmp(error) NEXT:[<ERROR>]
L7 [skipFinallyToErrorBlock]: L7 [skipFinallyToErrorBlock]:
4 mark({ doSmth(3) }) PREV:[jmp(L7 [skipFinallyToErrorBlock])] 4 mark({ doSmth(3) }) PREV:[jmp(L7 [skipFinallyToErrorBlock])]
r(3) -> <v1> r(3) -> <v1>
mark(doSmth(3)) mark(doSmth(3))
call(doSmth(3), doSmth|<v1>) -> <v2> call(doSmth(3), doSmth|<v1>) -> <v2>
2 merge(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) }|!<v3>, <v6>) -> <v7>
L1: L1:
1 <END> NEXT:[<SINK>] PREV:[ret(*|<v0>) L1, call(doSmth(3), doSmth|<v1>) -> <v2>] 1 <END> NEXT:[<SINK>] PREV:[ret(*|<v0>) L1, merge(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) }|!<v3>, <v6>) -> <v7>]
error: error:
<ERROR> PREV:[jmp(error)] <ERROR> PREV:[jmp(error)]
sink: sink:
<SINK> PREV:[<ERROR>, <END>] <SINK> PREV:[<ERROR>, <END>]
===================== =====================
== t14 == == t14 ==
fun t14() : Int { fun t14() : Int {
@@ -790,27 +793,28 @@ L0:
1 <START> 1 <START>
2 mark({ try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } }) 2 mark({ try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } })
mark(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) }) mark(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) })
jmp?(L2 [onException]) NEXT:[v(e: UnsupportedOperationException), mark({ return 1 })] jmp?(L2 [onException]) NEXT:[v(e: UnsupportedOperationException), mark({ return 1 })]
3 mark({ return 1 }) 3 mark({ return 1 })
r(1) -> <v0> r(1) -> <v0>
ret(*|<v0>) L1 NEXT:[<END>] ret(*|<v0>) L1 NEXT:[<END>]
- 2 jmp(L3 [afterCatches]) NEXT:[<END>] PREV:[] - 2 jmp(L3 [afterCatches]) NEXT:[merge(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) }|!<v1>, <v4>) -> <v5>] PREV:[]
L2 [onException]: L2 [onException]:
3 v(e: UnsupportedOperationException) PREV:[jmp?(L2 [onException])] 3 v(e: UnsupportedOperationException) PREV:[jmp?(L2 [onException])]
magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v1> magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v2>
w(e|<v1>) w(e|<v2>)
4 mark({ doSmth(2) }) 4 mark({ doSmth(2) })
r(2) -> <v2> r(2) -> <v3>
mark(doSmth(2)) mark(doSmth(2))
call(doSmth(2), doSmth|<v2>) -> <v3> call(doSmth(2), doSmth|<v3>) -> <v4>
3 jmp(L3 [afterCatches]) 3 jmp(L3 [afterCatches])
L1:
L3 [afterCatches]: L3 [afterCatches]:
1 <END> NEXT:[<SINK>] PREV:[ret(*|<v0>) L1, jmp(L3 [afterCatches])] 2 merge(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) }|!<v1>, <v4>) -> <v5>
L1:
1 <END> NEXT:[<SINK>] PREV:[ret(*|<v0>) L1, merge(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) }|!<v1>, <v4>) -> <v5>]
error: error:
<ERROR> PREV:[] <ERROR> PREV:[]
sink: sink:
<SINK> PREV:[<ERROR>, <END>] <SINK> PREV:[<ERROR>, <END>]
===================== =====================
== t15 == == t15 ==
fun t15() : Int { fun t15() : Int {
@@ -829,8 +833,8 @@ L0:
1 <START> 1 <START>
2 mark({ try { return 1 } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } }) 2 mark({ try { return 1 } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } })
mark(try { return 1 } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) }) mark(try { return 1 } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) })
jmp?(L2 [onException]) NEXT:[v(e: UnsupportedOperationException), jmp?(L3 [onExceptionToFinallyBlock])] jmp?(L2 [onException]) NEXT:[v(e: UnsupportedOperationException), jmp?(L3 [onExceptionToFinallyBlock])]
jmp?(L3 [onExceptionToFinallyBlock]) NEXT:[mark({ doSmth(3) }), mark({ return 1 })] jmp?(L3 [onExceptionToFinallyBlock]) NEXT:[mark({ doSmth(3) }), mark({ return 1 })]
3 mark({ return 1 }) 3 mark({ return 1 })
r(1) -> <v0> r(1) -> <v0>
L4 [start finally]: L4 [start finally]:
@@ -839,39 +843,40 @@ L4 [start finally]:
mark(doSmth(3)) mark(doSmth(3))
call(doSmth(3), doSmth|<v1>) -> <v2> call(doSmth(3), doSmth|<v1>) -> <v2>
L5 [finish finally]: L5 [finish finally]:
3 ret(*|<v0>) L1 NEXT:[<END>] 3 ret(*|<v0>) L1 NEXT:[<END>]
- 2 jmp(L6 [afterCatches]) NEXT:[jmp(L7 [skipFinallyToErrorBlock])] PREV:[] - 2 jmp(L6 [afterCatches]) NEXT:[jmp(L7 [skipFinallyToErrorBlock])] PREV:[]
L2 [onException]: L2 [onException]:
3 v(e: UnsupportedOperationException) PREV:[jmp?(L2 [onException])] 3 v(e: UnsupportedOperationException) PREV:[jmp?(L2 [onException])]
magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v3> magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v4>
w(e|<v3>) w(e|<v4>)
4 mark({ return 2 }) 4 mark({ return 2 })
r(2) -> <v4> r(2) -> <v5>
mark({ doSmth(3) }) mark({ doSmth(3) })
r(3) -> <v1> r(3) -> <v1>
mark(doSmth(3)) mark(doSmth(3))
call(doSmth(3), doSmth|<v1>) -> <v2> call(doSmth(3), doSmth|<v1>) -> <v2>
ret(*|<v4>) L1 NEXT:[<END>] ret(*|<v5>) L1 NEXT:[<END>]
- 3 jmp(L6 [afterCatches]) PREV:[] - 3 jmp(L6 [afterCatches]) PREV:[]
L6 [afterCatches]: L6 [afterCatches]:
- 2 jmp(L7 [skipFinallyToErrorBlock]) NEXT:[mark({ doSmth(3) })] PREV:[] - 2 jmp(L7 [skipFinallyToErrorBlock]) NEXT:[mark({ doSmth(3) })] PREV:[]
L3 [onExceptionToFinallyBlock]: L3 [onExceptionToFinallyBlock]:
4 mark({ doSmth(3) }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])] 4 mark({ doSmth(3) }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])]
r(3) -> <v1> r(3) -> <v1>
mark(doSmth(3)) mark(doSmth(3))
call(doSmth(3), doSmth|<v1>) -> <v2> call(doSmth(3), doSmth|<v1>) -> <v2>
2 jmp(error) NEXT:[<ERROR>] 2 jmp(error) NEXT:[<ERROR>]
L7 [skipFinallyToErrorBlock]: L7 [skipFinallyToErrorBlock]:
- 4 mark({ doSmth(3) }) PREV:[] - 4 mark({ doSmth(3) }) PREV:[]
- r(3) -> <v1> PREV:[] - r(3) -> <v1> PREV:[]
- mark(doSmth(3)) PREV:[] - mark(doSmth(3)) PREV:[]
- call(doSmth(3), doSmth|<v1>) -> <v2> PREV:[] - call(doSmth(3), doSmth|<v1>) -> <v2> PREV:[]
- 2 merge(try { return 1 } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) }|!<v3>, !<v6>) -> <v7> PREV:[]
L1: L1:
1 <END> NEXT:[<SINK>] PREV:[ret(*|<v0>) L1, ret(*|<v4>) L1] 1 <END> NEXT:[<SINK>] PREV:[ret(*|<v0>) L1, ret(*|<v5>) L1]
error: error:
<ERROR> PREV:[jmp(error)] <ERROR> PREV:[jmp(error)]
sink: sink:
<SINK> PREV:[<ERROR>, <END>] <SINK> PREV:[<ERROR>, <END>]
===================== =====================
== t16 == == t16 ==
fun t16() : Int { fun t16() : Int {
@@ -890,15 +895,15 @@ L0:
1 <START> 1 <START>
2 mark({ try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } }) 2 mark({ try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } })
mark(try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) }) mark(try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) })
jmp?(L2 [onException]) NEXT:[v(e: UnsupportedOperationException), jmp?(L3 [onExceptionToFinallyBlock])] jmp?(L2 [onException]) NEXT:[v(e: UnsupportedOperationException), jmp?(L3 [onExceptionToFinallyBlock])]
jmp?(L3 [onExceptionToFinallyBlock]) NEXT:[mark({ doSmth(3) }), mark({ doSmth(1) })] jmp?(L3 [onExceptionToFinallyBlock]) NEXT:[mark({ doSmth(3) }), mark({ doSmth(1) })]
3 mark({ doSmth(1) }) 3 mark({ doSmth(1) })
r(1) -> <v0> r(1) -> <v0>
mark(doSmth(1)) mark(doSmth(1))
call(doSmth(1), doSmth|<v0>) -> <v1> call(doSmth(1), doSmth|<v0>) -> <v1>
2 jmp(L4 [afterCatches]) NEXT:[jmp(L7 [skipFinallyToErrorBlock])] 2 jmp(L4 [afterCatches]) NEXT:[jmp(L7 [skipFinallyToErrorBlock])]
L2 [onException]: L2 [onException]:
3 v(e: UnsupportedOperationException) PREV:[jmp?(L2 [onException])] 3 v(e: UnsupportedOperationException) PREV:[jmp?(L2 [onException])]
magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v2> magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v2>
w(e|<v2>) w(e|<v2>)
4 mark({ return 2 }) 4 mark({ return 2 })
@@ -909,27 +914,28 @@ L5 [start finally]:
mark(doSmth(3)) mark(doSmth(3))
call(doSmth(3), doSmth|<v4>) -> <v5> call(doSmth(3), doSmth|<v4>) -> <v5>
L6 [finish finally]: L6 [finish finally]:
4 ret(*|<v3>) L1 NEXT:[<END>] 4 ret(*|<v3>) L1 NEXT:[<END>]
- 3 jmp(L4 [afterCatches]) PREV:[] - 3 jmp(L4 [afterCatches]) PREV:[]
L4 [afterCatches]: L4 [afterCatches]:
2 jmp(L7 [skipFinallyToErrorBlock]) NEXT:[mark({ doSmth(3) })] PREV:[jmp(L4 [afterCatches])] 2 jmp(L7 [skipFinallyToErrorBlock]) NEXT:[mark({ doSmth(3) })] PREV:[jmp(L4 [afterCatches])]
L3 [onExceptionToFinallyBlock]: L3 [onExceptionToFinallyBlock]:
5 mark({ doSmth(3) }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])] 5 mark({ doSmth(3) }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])]
r(3) -> <v4> r(3) -> <v4>
mark(doSmth(3)) mark(doSmth(3))
call(doSmth(3), doSmth|<v4>) -> <v5> call(doSmth(3), doSmth|<v4>) -> <v5>
2 jmp(error) NEXT:[<ERROR>] 2 jmp(error) NEXT:[<ERROR>]
L7 [skipFinallyToErrorBlock]: L7 [skipFinallyToErrorBlock]:
5 mark({ doSmth(3) }) PREV:[jmp(L7 [skipFinallyToErrorBlock])] 5 mark({ doSmth(3) }) PREV:[jmp(L7 [skipFinallyToErrorBlock])]
r(3) -> <v4> r(3) -> <v4>
mark(doSmth(3)) mark(doSmth(3))
call(doSmth(3), doSmth|<v4>) -> <v5> call(doSmth(3), doSmth|<v4>) -> <v5>
2 merge(try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) }|<v1>, !<v6>) -> <v7>
L1: L1:
1 <END> NEXT:[<SINK>] PREV:[ret(*|<v3>) L1, call(doSmth(3), doSmth|<v4>) -> <v5>] 1 <END> NEXT:[<SINK>] PREV:[ret(*|<v3>) L1, merge(try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) }|<v1>, !<v6>) -> <v7>]
error: error:
<ERROR> PREV:[jmp(error)] <ERROR> PREV:[jmp(error)]
sink: sink:
<SINK> PREV:[<ERROR>, <END>] <SINK> PREV:[<ERROR>, <END>]
===================== =====================
== doSmth == == doSmth ==
fun doSmth(i: Int) { fun doSmth(i: Int) {
@@ -26,12 +26,18 @@ fun t2() {
} }
} }
--------------------- ---------------------
1 <v0>: * NEW: r(1) -> <v0> 1 <v0>: * NEW: r(1) -> <v0>
2 <v1>: {<: Comparable<Int>} NEW: r(2) -> <v1> 2 <v1>: {<: Comparable<Int>} NEW: r(2) -> <v1>
3 <v2>: Int NEW: r(3) -> <v2> 3 <v2>: Int NEW: r(3) -> <v2>
2 > 3 <v3>: Boolean NEW: call(2 > 3, compareTo|<v1>, <v2>) -> <v3> 2 > 3 <v3>: Boolean NEW: call(2 > 3, compareTo|<v1>, <v2>) -> <v3>
2 <v4>: * NEW: r(2) -> <v4> return !<v5>: *
{ 2 } <v4>: * COPY { return } !<v5>: * COPY
if (2 > 3) { return } !<v5>: * COPY
{ 1 if (2 > 3) { return } } !<v5>: * COPY
2 <v4>: * NEW: r(2) -> <v4>
{ 2 } <v4>: * COPY
try { 1 if (2 > 3) { return } } finally { 2 } !<v5>: * COPY
{ try { 1 if (2 > 3) { return } } finally { 2 } } !<v5>: * COPY
===================== =====================
== t3 == == t3 ==
fun t3() { fun t3() {
@@ -63,9 +69,13 @@ try { 1 @l{ () -> if (2 > 3) { return@l } } } finally { 2 } <v1>: * COPY
} }
} }
--------------------- ---------------------
2 <v0>: {<: Comparable<Int>} NEW: r(2) -> <v0> 2 <v0>: {<: Comparable<Int>} NEW: r(2) -> <v0>
3 <v1>: Int NEW: r(3) -> <v1> 3 <v1>: Int NEW: r(3) -> <v1>
2 > 3 <v2>: Boolean NEW: call(2 > 3, compareTo|<v0>, <v1>) -> <v2> 2 > 3 <v2>: Boolean NEW: call(2 > 3, compareTo|<v0>, <v1>) -> <v2>
return@l !<v3>: *
{ return@l } !<v3>: * COPY
if (2 > 3) { return@l } !<v3>: * COPY
if (2 > 3) { return@l } !<v3>: * COPY
===================== =====================
== t4 == == t4 ==
fun t4() { fun t4() {
@@ -97,12 +107,18 @@ fun t4() {
} }
} }
--------------------- ---------------------
1 <v0>: * NEW: r(1) -> <v0> 1 <v0>: * NEW: r(1) -> <v0>
2 <v1>: {<: Comparable<Int>} NEW: r(2) -> <v1> 2 <v1>: {<: Comparable<Int>} NEW: r(2) -> <v1>
3 <v2>: Int NEW: r(3) -> <v2> 3 <v2>: Int NEW: r(3) -> <v2>
2 > 3 <v3>: Boolean NEW: call(2 > 3, compareTo|<v1>, <v2>) -> <v3> 2 > 3 <v3>: Boolean NEW: call(2 > 3, compareTo|<v1>, <v2>) -> <v3>
2 <v4>: * NEW: r(2) -> <v4> return@l !<v5>: *
{ 2 } <v4>: * COPY { return@l } !<v5>: * COPY
if (2 > 3) { return@l } !<v5>: * COPY
{ 1 if (2 > 3) { return@l } } !<v5>: * COPY
2 <v4>: * NEW: r(2) -> <v4>
{ 2 } <v4>: * COPY
try { 1 if (2 > 3) { return@l } } finally { 2 } !<v5>: * COPY
try { 1 if (2 > 3) { return@l } } finally { 2 } !<v5>: * COPY
===================== =====================
== t5 == == t5 ==
fun t5() { fun t5() {
@@ -118,14 +134,23 @@ fun t5() {
} }
} }
--------------------- ---------------------
<v1>: * NEW: magic[VALUE_CONSUMER](true|<v0>) -> <v1> <v1>: * NEW: magic[VALUE_CONSUMER](true|<v0>) -> <v1>
true <v0>: Boolean NEW: r(true) -> <v0> true <v0>: Boolean NEW: r(true) -> <v0>
1 <v2>: * NEW: r(1) -> <v2> 1 <v2>: * NEW: r(1) -> <v2>
2 <v3>: {<: Comparable<Int>} NEW: r(2) -> <v3> 2 <v3>: {<: Comparable<Int>} NEW: r(2) -> <v3>
3 <v4>: Int NEW: r(3) -> <v4> 3 <v4>: Int NEW: r(3) -> <v4>
2 > 3 <v5>: Boolean NEW: call(2 > 3, compareTo|<v3>, <v4>) -> <v5> 2 > 3 <v5>: Boolean NEW: call(2 > 3, compareTo|<v3>, <v4>) -> <v5>
2 <v6>: * NEW: r(2) -> <v6> break @l !<v7>: *
{ 2 } <v6>: * COPY { break @l } !<v7>: * COPY
if (2 > 3) { break @l } !<v7>: * COPY
{ 1 if (2 > 3) { break @l } } !<v7>: * COPY
2 <v6>: * NEW: r(2) -> <v6>
{ 2 } <v6>: * COPY
try { 1 if (2 > 3) { break @l } } finally { 2 } !<v7>: * COPY
{ try { 1 if (2 > 3) { break @l } } finally { 2 } } !<v7>: * COPY
while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } } !<v8>: *
@l while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } } !<v8>: * COPY
{ @l while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } } } !<v8>: * COPY
===================== =====================
== t6 == == t6 ==
fun t6() { fun t6() {
@@ -148,12 +173,18 @@ true <v0>:
2 <v3>: {<: Comparable<Int>} NEW: r(2) -> <v3> 2 <v3>: {<: Comparable<Int>} NEW: r(2) -> <v3>
3 <v4>: Int NEW: r(3) -> <v4> 3 <v4>: Int NEW: r(3) -> <v4>
2 > 3 <v5>: Boolean NEW: call(2 > 3, compareTo|<v3>, <v4>) -> <v5> 2 > 3 <v5>: Boolean NEW: call(2 > 3, compareTo|<v3>, <v4>) -> <v5>
5 <v6>: * NEW: r(5) -> <v6> break @l !<v6>: *
{ @l while(true) { 1 if (2 > 3) { break @l } } 5 } <v6>: * COPY { break @l } !<v6>: * COPY
2 <v7>: * NEW: r(2) -> <v7> if (2 > 3) { break @l } !<v6>: * COPY
{ 2 } <v7>: * COPY { 1 if (2 > 3) { break @l } } !<v6>: * COPY
try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } <v6>: * COPY while(true) { 1 if (2 > 3) { break @l } } !<v7>: *
{ try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } } <v6>: * COPY @l while(true) { 1 if (2 > 3) { break @l } } !<v7>: * COPY
5 <v8>: * NEW: r(5) -> <v8>
{ @l while(true) { 1 if (2 > 3) { break @l } } 5 } <v8>: * COPY
2 <v9>: * NEW: r(2) -> <v9>
{ 2 } <v9>: * COPY
try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } <v8>: * COPY
{ try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } } <v8>: * COPY
===================== =====================
== t7 == == t7 ==
fun t7() { fun t7() {
@@ -169,14 +200,23 @@ fun t7() {
} }
} }
--------------------- ---------------------
<v1>: * NEW: magic[VALUE_CONSUMER](true|<v0>) -> <v1> <v1>: * NEW: magic[VALUE_CONSUMER](true|<v0>) -> <v1>
true <v0>: Boolean NEW: r(true) -> <v0> true <v0>: Boolean NEW: r(true) -> <v0>
1 <v2>: * NEW: r(1) -> <v2> 1 <v2>: * NEW: r(1) -> <v2>
2 <v3>: {<: Comparable<Int>} NEW: r(2) -> <v3> 2 <v3>: {<: Comparable<Int>} NEW: r(2) -> <v3>
3 <v4>: Int NEW: r(3) -> <v4> 3 <v4>: Int NEW: r(3) -> <v4>
2 > 3 <v5>: Boolean NEW: call(2 > 3, compareTo|<v3>, <v4>) -> <v5> 2 > 3 <v5>: Boolean NEW: call(2 > 3, compareTo|<v3>, <v4>) -> <v5>
2 <v6>: * NEW: r(2) -> <v6> break @l !<v6>: *
{ 2 } <v6>: * COPY { break @l } !<v6>: * COPY
if (2 > 3) { break @l } !<v6>: * COPY
{ 1 if (2 > 3) { break @l } } !<v6>: * COPY
while(true) { 1 if (2 > 3) { break @l } } !<v7>: *
@l while(true) { 1 if (2 > 3) { break @l } } !<v7>: * COPY
{ @l while(true) { 1 if (2 > 3) { break @l } } } !<v7>: * COPY
2 <v8>: * NEW: r(2) -> <v8>
{ 2 } <v8>: * COPY
try { @l while(true) { 1 if (2 > 3) { break @l } } } finally { 2 } !<v7>: * COPY
{ try { @l while(true) { 1 if (2 > 3) { break @l } } } finally { 2 } } !<v7>: * COPY
===================== =====================
== t8 == == t8 ==
fun t8(a : Int) { fun t8(a : Int) {
@@ -192,17 +232,26 @@ fun t8(a : Int) {
} }
} }
--------------------- ---------------------
<v0>: Int NEW: magic[FAKE_INITIALIZER](a : Int) -> <v0> <v0>: Int NEW: magic[FAKE_INITIALIZER](a : Int) -> <v0>
<v4>: Int NEW: magic[LOOP_RANGE_ITERATION](1..a|<v3>) -> <v4> <v4>: Int NEW: magic[LOOP_RANGE_ITERATION](1..a|<v3>) -> <v4>
1 <v1>: Int NEW: r(1) -> <v1> 1 <v1>: Int NEW: r(1) -> <v1>
a <v2>: Int NEW: r(a) -> <v2> a <v2>: Int NEW: r(a) -> <v2>
1..a <v3>: {<: Iterable<Int>} NEW: call(1..a, rangeTo|<v1>, <v2>) -> <v3> 1..a <v3>: {<: Iterable<Int>} NEW: call(1..a, rangeTo|<v1>, <v2>) -> <v3>
1 <v5>: * NEW: r(1) -> <v5> 1 <v5>: * NEW: r(1) -> <v5>
2 <v6>: {<: Comparable<Int>} NEW: r(2) -> <v6> 2 <v6>: {<: Comparable<Int>} NEW: r(2) -> <v6>
3 <v7>: Int NEW: r(3) -> <v7> 3 <v7>: Int NEW: r(3) -> <v7>
2 > 3 <v8>: Boolean NEW: call(2 > 3, compareTo|<v6>, <v7>) -> <v8> 2 > 3 <v8>: Boolean NEW: call(2 > 3, compareTo|<v6>, <v7>) -> <v8>
2 <v9>: * NEW: r(2) -> <v9> continue @l !<v10>: *
{ 2 } <v9>: * COPY { continue @l } !<v10>: * COPY
if (2 > 3) { continue @l } !<v10>: * COPY
{ 1 if (2 > 3) { continue @l } } !<v10>: * COPY
2 <v9>: * NEW: r(2) -> <v9>
{ 2 } <v9>: * COPY
try { 1 if (2 > 3) { continue @l } } finally { 2 } !<v10>: * COPY
{ try { 1 if (2 > 3) { continue @l } } finally { 2 } } !<v10>: * COPY
for (i in 1..a) { try { 1 if (2 > 3) { continue @l } } finally { 2 } } !<v11>: *
@l for (i in 1..a) { try { 1 if (2 > 3) { continue @l } } finally { 2 } } !<v11>: * COPY
{ @l for (i in 1..a) { try { 1 if (2 > 3) { continue @l } } finally { 2 } } } !<v11>: * COPY
===================== =====================
== t9 == == t9 ==
fun t9(a : Int) { fun t9(a : Int) {
@@ -228,12 +277,18 @@ a
2 <v6>: {<: Comparable<Int>} NEW: r(2) -> <v6> 2 <v6>: {<: Comparable<Int>} NEW: r(2) -> <v6>
3 <v7>: Int NEW: r(3) -> <v7> 3 <v7>: Int NEW: r(3) -> <v7>
2 > 3 <v8>: Boolean NEW: call(2 > 3, compareTo|<v6>, <v7>) -> <v8> 2 > 3 <v8>: Boolean NEW: call(2 > 3, compareTo|<v6>, <v7>) -> <v8>
5 <v9>: * NEW: r(5) -> <v9> continue @l !<v9>: *
{ @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } <v9>: * COPY { continue @l } !<v9>: * COPY
2 <v10>: * NEW: r(2) -> <v10> if (2 > 3) { continue @l } !<v9>: * COPY
{ 2 } <v10>: * COPY { 1 if (2 > 3) { continue @l } } !<v9>: * COPY
try { @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } finally { 2 } <v9>: * COPY for (i in 1..a) { 1 if (2 > 3) { continue @l } } !<v10>: *
{ try { @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } finally { 2 } } <v9>: * COPY @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } !<v10>: * COPY
5 <v11>: * NEW: r(5) -> <v11>
{ @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } <v11>: * COPY
2 <v12>: * NEW: r(2) -> <v12>
{ 2 } <v12>: * COPY
try { @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } finally { 2 } <v11>: * COPY
{ try { @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } finally { 2 } } <v11>: * COPY
===================== =====================
== t10 == == t10 ==
fun t10(a : Int) { fun t10(a : Int) {
@@ -249,17 +304,26 @@ fun t10(a : Int) {
} }
} }
--------------------- ---------------------
<v0>: Int NEW: magic[FAKE_INITIALIZER](a : Int) -> <v0> <v0>: Int NEW: magic[FAKE_INITIALIZER](a : Int) -> <v0>
<v4>: Int NEW: magic[LOOP_RANGE_ITERATION](1..a|<v3>) -> <v4> <v4>: Int NEW: magic[LOOP_RANGE_ITERATION](1..a|<v3>) -> <v4>
1 <v1>: Int NEW: r(1) -> <v1> 1 <v1>: Int NEW: r(1) -> <v1>
a <v2>: Int NEW: r(a) -> <v2> a <v2>: Int NEW: r(a) -> <v2>
1..a <v3>: {<: Iterable<Int>} NEW: call(1..a, rangeTo|<v1>, <v2>) -> <v3> 1..a <v3>: {<: Iterable<Int>} NEW: call(1..a, rangeTo|<v1>, <v2>) -> <v3>
1 <v5>: * NEW: r(1) -> <v5> 1 <v5>: * NEW: r(1) -> <v5>
2 <v6>: {<: Comparable<Int>} NEW: r(2) -> <v6> 2 <v6>: {<: Comparable<Int>} NEW: r(2) -> <v6>
3 <v7>: Int NEW: r(3) -> <v7> 3 <v7>: Int NEW: r(3) -> <v7>
2 > 3 <v8>: Boolean NEW: call(2 > 3, compareTo|<v6>, <v7>) -> <v8> 2 > 3 <v8>: Boolean NEW: call(2 > 3, compareTo|<v6>, <v7>) -> <v8>
2 <v9>: * NEW: r(2) -> <v9> continue @l !<v9>: *
{ 2 } <v9>: * COPY { continue @l } !<v9>: * COPY
if (2 > 3) { continue @l } !<v9>: * COPY
{ 1 if (2 > 3) { continue @l } } !<v9>: * COPY
for (i in 1..a) { 1 if (2 > 3) { continue @l } } !<v10>: *
@l for (i in 1..a) { 1 if (2 > 3) { continue @l } } !<v10>: * COPY
{ @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } } !<v10>: * COPY
2 <v11>: * NEW: r(2) -> <v11>
{ 2 } <v11>: * COPY
try { @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } } finally { 2 } !<v10>: * COPY
{ try { @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } } finally { 2 } } !<v10>: * COPY
===================== =====================
== t11 == == t11 ==
fun t11() { fun t11() {
@@ -271,8 +335,14 @@ fun t11() {
} }
} }
--------------------- ---------------------
1 <v0>: {<: Unit} NEW: r(1) -> <v0> 1 <v0>: Unit NEW: r(1) -> <v0>
2 <v1>: {<: Unit} NEW: r(2) -> <v1> return 1 !<v3>: *
{ return 1 } !<v3>: * COPY
2 <v1>: Unit NEW: r(2) -> <v1>
return 2 !<v2>: *
{ return 2 } !<v2>: * COPY
try { return 1 } finally { return 2 } !<v3>: * COPY
{ try { return 1 } finally { return 2 } } !<v3>: * COPY
===================== =====================
== t12 == == t12 ==
fun t12() : Int { fun t12() : Int {
@@ -284,10 +354,14 @@ fun t12() : Int {
} }
} }
--------------------- ---------------------
1 <v0>: Int NEW: r(1) -> <v0> 1 <v0>: Int NEW: r(1) -> <v0>
3 <v1>: Int NEW: r(3) -> <v1> return 1 !<v3>: *
doSmth(3) <v2>: * NEW: call(doSmth(3), doSmth|<v1>) -> <v2> { return 1 } !<v3>: * COPY
{ doSmth(3) } <v2>: * COPY 3 <v1>: Int NEW: r(3) -> <v1>
doSmth(3) <v2>: * NEW: call(doSmth(3), doSmth|<v1>) -> <v2>
{ doSmth(3) } <v2>: * COPY
try { return 1 } finally { doSmth(3) } !<v3>: * COPY
{ try { return 1 } finally { doSmth(3) } } !<v3>: * COPY
===================== =====================
== t13 == == t13 ==
fun t13() : Int { fun t13() : Int {
@@ -302,16 +376,18 @@ fun t13() : Int {
} }
} }
--------------------- ---------------------
<v3>: {<: UnsupportedOperationException} NEW: magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v3> <v4>: {<: UnsupportedOperationException} NEW: magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v4>
1 <v0>: Int NEW: r(1) -> <v0> 1 <v0>: Int NEW: r(1) -> <v0>
2 <v4>: Int NEW: r(2) -> <v4> return 1 !<v3>: *
doSmth(2) <v5>: * NEW: call(doSmth(2), doSmth|<v4>) -> <v5> { return 1 } !<v3>: * COPY
{ doSmth(2) } <v5>: * COPY 2 <v5>: Int NEW: r(2) -> <v5>
doSmth(2) <v6>: * NEW: call(doSmth(2), doSmth|<v5>) -> <v6>
{ doSmth(2) } <v6>: * COPY
3 <v1>: Int NEW: r(3) -> <v1> 3 <v1>: Int NEW: r(3) -> <v1>
doSmth(3) <v2>: * NEW: call(doSmth(3), doSmth|<v1>) -> <v2> doSmth(3) <v2>: * NEW: call(doSmth(3), doSmth|<v1>) -> <v2>
{ doSmth(3) } <v2>: * COPY { doSmth(3) } <v2>: * COPY
try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) } <v5>: * COPY try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) } <v7>: * NEW: merge(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) }|!<v3>, <v6>) -> <v7>
{ try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) } } <v5>: * COPY { try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) } } <v7>: * COPY
===================== =====================
== t14 == == t14 ==
fun t14() : Int { fun t14() : Int {
@@ -323,13 +399,15 @@ fun t14() : Int {
} }
} }
--------------------- ---------------------
<v1>: {<: UnsupportedOperationException} NEW: magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v1> <v2>: {<: UnsupportedOperationException} NEW: magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v2>
1 <v0>: Int NEW: r(1) -> <v0> 1 <v0>: Int NEW: r(1) -> <v0>
2 <v2>: Int NEW: r(2) -> <v2> return 1 !<v1>: *
doSmth(2) <v3>: * NEW: call(doSmth(2), doSmth|<v2>) -> <v3> { return 1 } !<v1>: * COPY
{ doSmth(2) } <v3>: * COPY 2 <v3>: Int NEW: r(2) -> <v3>
try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } <v3>: * COPY doSmth(2) <v4>: * NEW: call(doSmth(2), doSmth|<v3>) -> <v4>
{ try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } } <v3>: * COPY { doSmth(2) } <v4>: * COPY
try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } <v5>: * NEW: merge(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) }|!<v1>, <v4>) -> <v5>
{ try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } } <v5>: * COPY
===================== =====================
== t15 == == t15 ==
fun t15() : Int { fun t15() : Int {
@@ -344,12 +422,18 @@ fun t15() : Int {
} }
} }
--------------------- ---------------------
<v3>: {<: UnsupportedOperationException} NEW: magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v3> <v4>: {<: UnsupportedOperationException} NEW: magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v4>
1 <v0>: Int NEW: r(1) -> <v0> 1 <v0>: Int NEW: r(1) -> <v0>
2 <v4>: Int NEW: r(2) -> <v4> return 1 !<v3>: *
3 <v1>: Int NEW: r(3) -> <v1> { return 1 } !<v3>: * COPY
doSmth(3) <v2>: * NEW: call(doSmth(3), doSmth|<v1>) -> <v2> 2 <v5>: Int NEW: r(2) -> <v5>
{ doSmth(3) } <v2>: * COPY return 2 !<v6>: *
{ return 2 } !<v6>: * COPY
3 <v1>: Int NEW: r(3) -> <v1>
doSmth(3) <v2>: * NEW: call(doSmth(3), doSmth|<v1>) -> <v2>
{ doSmth(3) } <v2>: * COPY
try { return 1 } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } <v7>: * NEW: merge(try { return 1 } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) }|!<v3>, !<v6>) -> <v7>
{ try { return 1 } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } } <v7>: * COPY
===================== =====================
== t16 == == t16 ==
fun t16() : Int { fun t16() : Int {
@@ -369,11 +453,13 @@ fun t16() : Int {
doSmth(1) <v1>: * NEW: call(doSmth(1), doSmth|<v0>) -> <v1> doSmth(1) <v1>: * NEW: call(doSmth(1), doSmth|<v0>) -> <v1>
{ doSmth(1) } <v1>: * COPY { doSmth(1) } <v1>: * COPY
2 <v3>: Int NEW: r(2) -> <v3> 2 <v3>: Int NEW: r(2) -> <v3>
return 2 !<v6>: *
{ return 2 } !<v6>: * COPY
3 <v4>: Int NEW: r(3) -> <v4> 3 <v4>: Int NEW: r(3) -> <v4>
doSmth(3) <v5>: * NEW: call(doSmth(3), doSmth|<v4>) -> <v5> doSmth(3) <v5>: * NEW: call(doSmth(3), doSmth|<v4>) -> <v5>
{ doSmth(3) } <v5>: * COPY { doSmth(3) } <v5>: * COPY
try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } <v1>: * COPY try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } <v7>: * NEW: merge(try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) }|<v1>, !<v6>) -> <v7>
{ try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } } <v1>: * COPY { try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } } <v7>: * COPY
===================== =====================
== doSmth == == doSmth ==
fun doSmth(i: Int) { fun doSmth(i: Int) {
@@ -110,7 +110,7 @@ L6 [skipFinallyToErrorBlock]:
3 mark({ return 1 }) PREV:[jmp(L6 [skipFinallyToErrorBlock])] 3 mark({ return 1 }) PREV:[jmp(L6 [skipFinallyToErrorBlock])]
r(1) -> <v5> r(1) -> <v5>
ret(*|<v5>) L1 NEXT:[<END>] ret(*|<v5>) L1 NEXT:[<END>]
- 2 merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 }|<v0>, <v2>, <v4>) -> <v6> PREV:[] - 2 merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 }|<v0>, <v2>, <v4>) -> <v7> PREV:[]
L1: L1:
1 <END> NEXT:[<SINK>] PREV:[ret(*|<v5>) L1, ret(*|<v5>) L1] 1 <END> NEXT:[<SINK>] PREV:[ret(*|<v5>) L1, ret(*|<v5>) L1]
error: error:
@@ -142,30 +142,30 @@ L0:
2 mark({ while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } }) 2 mark({ while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } })
L2 [loop entry point]: L2 [loop entry point]:
L5 [condition entry point]: L5 [condition entry point]:
mark(cond()) PREV:[mark({ while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } }), jmp(L2 [loop entry point]), jmp(L2 [loop entry point])] mark(cond()) PREV:[mark({ while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } }), jmp(L2 [loop entry point]), jmp(L2 [loop entry point])]
call(cond(), cond) -> <v0> call(cond(), cond) -> <v0>
mark(while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } }) mark(while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } })
jf(L3 [loop exit point]|<v0>) NEXT:[read (Unit), mark({ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } })] jf(L3 [loop exit point]|<v0>) NEXT:[read (Unit), mark({ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } })]
L4 [body entry point]: L4 [body entry point]:
3 mark({ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } }) 3 mark({ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } })
mark(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue }) mark(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue })
jmp?(L6 [onException]) NEXT:[jmp?(L9 [catch 0]), jmp?(L7 [onExceptionToFinallyBlock])] jmp?(L6 [onException]) NEXT:[jmp?(L9 [catch 0]), jmp?(L7 [onExceptionToFinallyBlock])]
jmp?(L7 [onExceptionToFinallyBlock]) NEXT:[mark({ if (cond()) return else continue }), mark({ doSmth() })] jmp?(L7 [onExceptionToFinallyBlock]) NEXT:[mark({ if (cond()) return else continue }), mark({ doSmth() })]
4 mark({ doSmth() }) 4 mark({ doSmth() })
mark(doSmth()) mark(doSmth())
call(doSmth(), doSmth) -> <v1> call(doSmth(), doSmth) -> <v1>
3 jmp(L8 [afterCatches]) NEXT:[jmp(L10 [skipFinallyToErrorBlock])] 3 jmp(L8 [afterCatches]) NEXT:[jmp(L10 [skipFinallyToErrorBlock])]
L6 [onException]: L6 [onException]:
jmp?(L9 [catch 0]) NEXT:[v(e: Exception), v(e: NullPointerException)] PREV:[jmp?(L6 [onException])] jmp?(L9 [catch 0]) NEXT:[v(e: Exception), v(e: NullPointerException)] PREV:[jmp?(L6 [onException])]
4 v(e: NullPointerException) 4 v(e: NullPointerException)
magic[FAKE_INITIALIZER](e: NullPointerException) -> <v2> magic[FAKE_INITIALIZER](e: NullPointerException) -> <v2>
w(e|<v2>) w(e|<v2>)
5 mark({ doSmth1() }) 5 mark({ doSmth1() })
mark(doSmth1()) mark(doSmth1())
call(doSmth1(), doSmth1) -> <v3> call(doSmth1(), doSmth1) -> <v3>
4 jmp(L8 [afterCatches]) NEXT:[jmp(L10 [skipFinallyToErrorBlock])] 4 jmp(L8 [afterCatches]) NEXT:[jmp(L10 [skipFinallyToErrorBlock])]
L9 [catch 0]: L9 [catch 0]:
v(e: Exception) PREV:[jmp?(L9 [catch 0])] v(e: Exception) PREV:[jmp?(L9 [catch 0])]
magic[FAKE_INITIALIZER](e: Exception) -> <v4> magic[FAKE_INITIALIZER](e: Exception) -> <v4>
w(e|<v4>) w(e|<v4>)
5 mark({ doSmth2() }) 5 mark({ doSmth2() })
@@ -173,40 +173,42 @@ L9 [catch 0]:
call(doSmth2(), doSmth2) -> <v5> call(doSmth2(), doSmth2) -> <v5>
4 jmp(L8 [afterCatches]) 4 jmp(L8 [afterCatches])
L8 [afterCatches]: L8 [afterCatches]:
3 jmp(L10 [skipFinallyToErrorBlock]) NEXT:[mark({ if (cond()) return else continue })] PREV:[jmp(L8 [afterCatches]), jmp(L8 [afterCatches]), jmp(L8 [afterCatches])] 3 jmp(L10 [skipFinallyToErrorBlock]) NEXT:[mark({ if (cond()) return else continue })] PREV:[jmp(L8 [afterCatches]), jmp(L8 [afterCatches]), jmp(L8 [afterCatches])]
L7 [onExceptionToFinallyBlock]: L7 [onExceptionToFinallyBlock]:
L11 [start finally]: L11 [start finally]:
4 mark({ if (cond()) return else continue }) PREV:[jmp?(L7 [onExceptionToFinallyBlock])] 4 mark({ if (cond()) return else continue }) PREV:[jmp?(L7 [onExceptionToFinallyBlock])]
mark(if (cond()) return else continue) mark(if (cond()) return else continue)
mark(cond()) mark(cond())
call(cond(), cond) -> <v6> call(cond(), cond) -> <v6>
jf(L12|<v6>) NEXT:[jmp(L2 [loop entry point]), ret L1] jf(L12|<v6>) NEXT:[jmp(L2 [loop entry point]), ret L1]
ret L1 NEXT:[<END>] ret L1 NEXT:[<END>]
- jmp(L13) NEXT:[jmp(error)] PREV:[] - jmp(L13) NEXT:[merge(if (cond()) return else continue|!<v7>, !<v8>) -> <v9>] PREV:[]
L12: L12:
jmp(L2 [loop entry point]) NEXT:[mark(cond())] PREV:[jf(L12|<v6>)] jmp(L2 [loop entry point]) NEXT:[mark(cond())] PREV:[jf(L12|<v6>)]
L13: L13:
- merge(if (cond()) return else continue|!<v7>, !<v8>) -> <v9> PREV:[]
L14 [finish finally]: L14 [finish finally]:
- 3 jmp(error) NEXT:[<ERROR>] PREV:[] - 3 jmp(error) NEXT:[<ERROR>] PREV:[]
L10 [skipFinallyToErrorBlock]: L10 [skipFinallyToErrorBlock]:
4 mark({ if (cond()) return else continue }) PREV:[jmp(L10 [skipFinallyToErrorBlock])] 4 mark({ if (cond()) return else continue }) PREV:[jmp(L10 [skipFinallyToErrorBlock])]
mark(if (cond()) return else continue) mark(if (cond()) return else continue)
mark(cond()) mark(cond())
call(cond(), cond) -> <v6> call(cond(), cond) -> <v6>
jf(copy L12|<v6>) NEXT:[jmp(L2 [loop entry point]), ret L1] jf(copy L12|<v6>) NEXT:[jmp(L2 [loop entry point]), ret L1]
ret L1 NEXT:[<END>] ret L1 NEXT:[<END>]
- jmp(copy L13) NEXT:[merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue }|<v1>, <v3>, <v5>) -> <v7>] PREV:[] - jmp(copy L13) NEXT:[merge(if (cond()) return else continue|!<v7>, !<v8>) -> <v9>] PREV:[]
jmp(L2 [loop entry point]) NEXT:[mark(cond())] PREV:[jf(copy L12|<v6>)] jmp(L2 [loop entry point]) NEXT:[mark(cond())] PREV:[jf(copy L12|<v6>)]
- 3 merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue }|<v1>, <v3>, <v5>) -> <v7> PREV:[] - merge(if (cond()) return else continue|!<v7>, !<v8>) -> <v9> PREV:[]
- 2 jmp(L2 [loop entry point]) NEXT:[mark(cond())] PREV:[] - 3 merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue }|<v1>, <v3>, <v5>) -> <v10> PREV:[]
- 2 jmp(L2 [loop entry point]) NEXT:[mark(cond())] PREV:[]
L3 [loop exit point]: L3 [loop exit point]:
read (Unit) PREV:[jf(L3 [loop exit point]|<v0>)] read (Unit) PREV:[jf(L3 [loop exit point]|<v0>)]
L1: L1:
1 <END> NEXT:[<SINK>] PREV:[ret L1, ret L1, read (Unit)] 1 <END> NEXT:[<SINK>] PREV:[ret L1, ret L1, read (Unit)]
error: error:
<ERROR> PREV:[] <ERROR> PREV:[]
sink: sink:
<SINK> PREV:[<ERROR>, <END>] <SINK> PREV:[<ERROR>, <END>]
===================== =====================
== testCopy3 == == testCopy3 ==
fun testCopy3() { fun testCopy3() {
@@ -276,7 +278,7 @@ L6 [skipFinallyToErrorBlock]:
jf(copy L9 [loop exit point]|<v5>) NEXT:[read (Unit), jmp(copy L8 [loop entry point])] jf(copy L9 [loop exit point]|<v5>) NEXT:[read (Unit), jmp(copy L8 [loop entry point])]
jmp(copy L8 [loop entry point]) NEXT:[mark(cond())] jmp(copy L8 [loop entry point]) NEXT:[mark(cond())]
read (Unit) PREV:[jf(copy L9 [loop exit point]|<v5>)] read (Unit) PREV:[jf(copy L9 [loop exit point]|<v5>)]
2 merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); }|<v0>, <v2>, <v4>) -> <v6> 2 merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); }|<v0>, <v2>, <v4>) -> <v7>
L1: L1:
1 <END> NEXT:[<SINK>] 1 <END> NEXT:[<SINK>]
error: error:
@@ -39,8 +39,10 @@ doSmth1()
doSmth2() <v4>: * NEW: call(doSmth2(), doSmth2) -> <v4> doSmth2() <v4>: * NEW: call(doSmth2(), doSmth2) -> <v4>
{ doSmth2() } <v4>: * COPY { doSmth2() } <v4>: * COPY
1 <v5>: Int NEW: r(1) -> <v5> 1 <v5>: Int NEW: r(1) -> <v5>
try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 } <v6>: * NEW: merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 }|<v0>, <v2>, <v4>) -> <v6> return 1 !<v6>: *
{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 } } <v6>: * COPY { return 1 } !<v6>: * COPY
try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 } <v7>: * NEW: merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 }|<v0>, <v2>, <v4>) -> <v7>
{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 } } <v7>: * COPY
===================== =====================
== testCopy2 == == testCopy2 ==
fun testCopy2() { fun testCopy2() {
@@ -61,18 +63,24 @@ fun testCopy2() {
} }
} }
--------------------- ---------------------
<v2>: {<: NullPointerException} NEW: magic[FAKE_INITIALIZER](e: NullPointerException) -> <v2> <v2>: {<: NullPointerException} NEW: magic[FAKE_INITIALIZER](e: NullPointerException) -> <v2>
<v4>: {<: Exception} NEW: magic[FAKE_INITIALIZER](e: Exception) -> <v4> <v4>: {<: Exception} NEW: magic[FAKE_INITIALIZER](e: Exception) -> <v4>
cond() <v0>: Boolean NEW: call(cond(), cond) -> <v0> cond() <v0>: Boolean NEW: call(cond(), cond) -> <v0>
doSmth() <v1>: * NEW: call(doSmth(), doSmth) -> <v1> doSmth() <v1>: * NEW: call(doSmth(), doSmth) -> <v1>
{ doSmth() } <v1>: * COPY { doSmth() } <v1>: * COPY
doSmth1() <v3>: * NEW: call(doSmth1(), doSmth1) -> <v3> doSmth1() <v3>: * NEW: call(doSmth1(), doSmth1) -> <v3>
{ doSmth1() } <v3>: * COPY { doSmth1() } <v3>: * COPY
doSmth2() <v5>: * NEW: call(doSmth2(), doSmth2) -> <v5> doSmth2() <v5>: * NEW: call(doSmth2(), doSmth2) -> <v5>
{ doSmth2() } <v5>: * COPY { doSmth2() } <v5>: * COPY
cond() <v6>: Boolean NEW: call(cond(), cond) -> <v6> cond() <v6>: Boolean NEW: call(cond(), cond) -> <v6>
try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } <v7>: * NEW: merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue }|<v1>, <v3>, <v5>) -> <v7> return !<v7>: *
{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } <v7>: * COPY continue !<v8>: *
if (cond()) return else continue <v9>: * NEW: merge(if (cond()) return else continue|!<v7>, !<v8>) -> <v9>
{ if (cond()) return else continue } <v9>: * COPY
try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } <v10>: * NEW: merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue }|<v1>, <v3>, <v5>) -> <v10>
{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } <v10>: * COPY
while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } !<v11>: *
{ while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } } !<v11>: * COPY
===================== =====================
== testCopy3 == == testCopy3 ==
fun testCopy3() { fun testCopy3() {
@@ -99,8 +107,10 @@ doSmth1()
doSmth2() <v4>: * NEW: call(doSmth2(), doSmth2) -> <v4> doSmth2() <v4>: * NEW: call(doSmth2(), doSmth2) -> <v4>
{ doSmth2() } <v4>: * COPY { doSmth2() } <v4>: * COPY
cond() <v5>: Boolean NEW: call(cond(), cond) -> <v5> cond() <v5>: Boolean NEW: call(cond(), cond) -> <v5>
try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); } <v6>: * NEW: merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); }|<v0>, <v2>, <v4>) -> <v6> while (cond()) !<v6>: *
{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); } } <v6>: * COPY { while (cond()); } !<v6>: * COPY
try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); } <v7>: * NEW: merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); }|<v0>, <v2>, <v4>) -> <v7>
{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); } } <v7>: * COPY
===================== =====================
== doTestCopy4 == == doTestCopy4 ==
fun doTestCopy4(list: List<String>?) : Int { fun doTestCopy4(list: List<String>?) : Int {
@@ -119,6 +129,9 @@ doSmth() <v1>: *
list <v2>: * NEW: r(list) -> <v2> list <v2>: * NEW: r(list) -> <v2>
null <v3>: * NEW: r(null) -> <v3> null <v3>: * NEW: r(null) -> <v3>
list != null <v4>: Boolean NEW: call(list != null, equals|<v2>, <v3>) -> <v4> list != null <v4>: Boolean NEW: call(list != null, equals|<v2>, <v3>) -> <v4>
{ } !<v5>: *
if(list != null) { } !<v5>: * COPY
{ if(list != null) { } } !<v5>: * COPY
try { doSmth() } finally { if(list != null) { } } <v1>: * COPY try { doSmth() } finally { if(list != null) { } } <v1>: * COPY
{ try { doSmth() } finally { if(list != null) { } } } <v1>: * COPY { try { doSmth() } finally { if(list != null) { } } } <v1>: * COPY
===================== =====================
@@ -5,13 +5,15 @@ fun t1() {
} }
} }
--------------------- ---------------------
<v3>: Int NEW: magic[LOOP_RANGE_ITERATION](1..2|<v2>) -> <v3> <v3>: Int NEW: magic[LOOP_RANGE_ITERATION](1..2|<v2>) -> <v3>
1 <v0>: Int NEW: r(1) -> <v0> 1 <v0>: Int NEW: r(1) -> <v0>
2 <v1>: Int NEW: r(2) -> <v1> 2 <v1>: Int NEW: r(2) -> <v1>
1..2 <v2>: {<: Iterable<Int>} NEW: call(1..2, rangeTo|<v0>, <v1>) -> <v2> 1..2 <v2>: {<: Iterable<Int>} NEW: call(1..2, rangeTo|<v0>, <v1>) -> <v2>
i <v4>: Int NEW: r(i) -> <v4> i <v4>: Int NEW: r(i) -> <v4>
doSmth(i) <v5>: * NEW: call(doSmth(i), doSmth|<v4>) -> <v5> doSmth(i) <v5>: * NEW: call(doSmth(i), doSmth|<v4>) -> <v5>
{ doSmth(i) } <v5>: * COPY { doSmth(i) } <v5>: * COPY
for (i in 1..2) { doSmth(i) } !<v6>: *
{ for (i in 1..2) { doSmth(i) } } !<v6>: * COPY
===================== =====================
== doSmth == == doSmth ==
fun doSmth(i: Int) {} fun doSmth(i: Int) {}
@@ -30,31 +30,32 @@ L0:
mark("s") mark("s")
r("s") -> <v2> r("s") -> <v2>
w(u|<v2>) w(u|<v2>)
2 jmp(L3) NEXT:[r(u) -> <v3>] 2 jmp(L3) NEXT:[r(u) -> <v4>]
L2: L2:
read (Unit) PREV:[jf(L2|<v1>)] read (Unit) PREV:[jf(L2|<v1>)]
L3: L3:
r(u) -> <v3> PREV:[jmp(L3), read (Unit)] r(u) -> <v4> PREV:[jmp(L3), read (Unit)]
mark(doSmth(u)) mark(doSmth(u))
call(doSmth(u), doSmth|<v3>) -> <v4> call(doSmth(u), doSmth|<v4>) -> <v5>
v(var r: String) v(var r: String)
mark(if (b) { r = "s" } else { r = "t" }) mark(if (b) { r = "s" } else { r = "t" })
r(b) -> <v5> r(b) -> <v6>
jf(L4|<v5>) NEXT:[mark({ r = "t" }), mark({ r = "s" })] jf(L4|<v6>) NEXT:[mark({ r = "t" }), mark({ r = "s" })]
3 mark({ r = "s" }) 3 mark({ r = "s" })
mark("s") mark("s")
r("s") -> <v6> r("s") -> <v7>
w(r|<v6>)
2 jmp(L5) NEXT:[r(r) -> <v8>]
L4:
3 mark({ r = "t" }) PREV:[jf(L4|<v5>)]
mark("t")
r("t") -> <v7>
w(r|<v7>) w(r|<v7>)
2 jmp(L5) NEXT:[merge(if (b) { r = "s" } else { r = "t" }|!<v8>, !<v10>) -> <v11>]
L4:
3 mark({ r = "t" }) PREV:[jf(L4|<v6>)]
mark("t")
r("t") -> <v9>
w(r|<v9>)
L5: L5:
2 r(r) -> <v8> PREV:[jmp(L5), w(r|<v7>)] 2 merge(if (b) { r = "s" } else { r = "t" }|!<v8>, !<v10>) -> <v11> PREV:[jmp(L5), w(r|<v9>)]
r(r) -> <v12>
mark(doSmth(r)) mark(doSmth(r))
call(doSmth(r), doSmth|<v8>) -> <v9> call(doSmth(r), doSmth|<v12>) -> <v13>
L1: L1:
1 <END> NEXT:[<SINK>] 1 <END> NEXT:[<SINK>]
error: error:
@@ -88,23 +89,23 @@ L0:
jf(L2|<v2>) NEXT:[read (Unit), mark({ return; })] jf(L2|<v2>) NEXT:[read (Unit), mark({ return; })]
3 mark({ return; }) 3 mark({ return; })
ret L1 NEXT:[<END>] ret L1 NEXT:[<END>]
- 2 jmp(L3) NEXT:[r(i) -> <v3>] PREV:[] - 2 jmp(L3) NEXT:[r(i) -> <v4>] PREV:[]
L2: L2:
read (Unit) PREV:[jf(L2|<v2>)] read (Unit) PREV:[jf(L2|<v2>)]
L3: L3:
r(i) -> <v3> r(i) -> <v4>
mark(doSmth(i)) mark(doSmth(i))
call(doSmth(i), doSmth|<v3>) -> <v4> call(doSmth(i), doSmth|<v4>) -> <v5>
mark(if (i is Int) { return; }) mark(if (i is Int) { return; })
mark(i is Int) mark(i is Int)
r(i) -> <v5> r(i) -> <v6>
magic[IS](i is Int|<v5>) -> <v6> magic[IS](i is Int|<v6>) -> <v7>
jf(L4|<v6>) NEXT:[read (Unit), mark({ return; })] jf(L4|<v7>) NEXT:[read (Unit), mark({ return; })]
3 mark({ return; }) 3 mark({ return; })
ret L1 NEXT:[<END>] ret L1 NEXT:[<END>]
- 2 jmp(L5) NEXT:[<END>] PREV:[] - 2 jmp(L5) NEXT:[<END>] PREV:[]
L4: L4:
read (Unit) PREV:[jf(L4|<v6>)] read (Unit) PREV:[jf(L4|<v7>)]
L1: L1:
L5: L5:
1 <END> NEXT:[<SINK>] PREV:[ret L1, ret L1, read (Unit)] 1 <END> NEXT:[<SINK>] PREV:[ret L1, ret L1, read (Unit)]
@@ -19,14 +19,22 @@ fun t1(b: Boolean) {
<v0>: Boolean NEW: magic[FAKE_INITIALIZER](b: Boolean) -> <v0> <v0>: Boolean NEW: magic[FAKE_INITIALIZER](b: Boolean) -> <v0>
b <v1>: Boolean NEW: r(b) -> <v1> b <v1>: Boolean NEW: r(b) -> <v1>
"s" <v2>: String NEW: r("s") -> <v2> "s" <v2>: String NEW: r("s") -> <v2>
u <v3>: String NEW: r(u) -> <v3> u = "s" !<v3>: *
doSmth(u) <v4>: * NEW: call(doSmth(u), doSmth|<v3>) -> <v4> { u = "s" } !<v3>: * COPY
b <v5>: Boolean NEW: r(b) -> <v5> if (b) { u = "s" } !<v3>: * COPY
"s" <v6>: String NEW: r("s") -> <v6> u <v4>: String NEW: r(u) -> <v4>
"t" <v7>: String NEW: r("t") -> <v7> doSmth(u) <v5>: * NEW: call(doSmth(u), doSmth|<v4>) -> <v5>
r <v8>: String NEW: r(r) -> <v8> b <v6>: Boolean NEW: r(b) -> <v6>
doSmth(r) <v9>: * NEW: call(doSmth(r), doSmth|<v8>) -> <v9> "s" <v7>: String NEW: r("s") -> <v7>
{ var u: String if (b) { u = "s" } doSmth(u) var r: String if (b) { r = "s" } else { r = "t" } doSmth(r) } <v9>: * COPY r = "s" !<v8>: *
{ r = "s" } !<v8>: * COPY
"t" <v9>: String NEW: r("t") -> <v9>
r = "t" !<v10>: *
{ r = "t" } !<v10>: * COPY
if (b) { r = "s" } else { r = "t" } <v11>: * NEW: merge(if (b) { r = "s" } else { r = "t" }|!<v8>, !<v10>) -> <v11>
r <v12>: String NEW: r(r) -> <v12>
doSmth(r) <v13>: * NEW: call(doSmth(r), doSmth|<v12>) -> <v13>
{ var u: String if (b) { u = "s" } doSmth(u) var r: String if (b) { r = "s" } else { r = "t" } doSmth(r) } <v13>: * COPY
===================== =====================
== t2 == == t2 ==
fun t2(b: Boolean) { fun t2(b: Boolean) {
@@ -40,13 +48,20 @@ fun t2(b: Boolean) {
} }
} }
--------------------- ---------------------
<v0>: Boolean NEW: magic[FAKE_INITIALIZER](b: Boolean) -> <v0> <v0>: Boolean NEW: magic[FAKE_INITIALIZER](b: Boolean) -> <v0>
3 <v1>: Int NEW: r(3) -> <v1> 3 <v1>: Int NEW: r(3) -> <v1>
b <v2>: Boolean NEW: r(b) -> <v2> b <v2>: Boolean NEW: r(b) -> <v2>
i <v3>: String NEW: r(i) -> <v3> return !<v3>: *
doSmth(i) <v4>: * NEW: call(doSmth(i), doSmth|<v3>) -> <v4> { return; } !<v3>: * COPY
i <v5>: * NEW: r(i) -> <v5> if (b) { return; } !<v3>: * COPY
i is Int <v6>: Boolean NEW: magic[IS](i is Int|<v5>) -> <v6> i <v4>: String NEW: r(i) -> <v4>
doSmth(i) <v5>: * NEW: call(doSmth(i), doSmth|<v4>) -> <v5>
i <v6>: * NEW: r(i) -> <v6>
i is Int <v7>: Boolean NEW: magic[IS](i is Int|<v6>) -> <v7>
return !<v8>: *
{ return; } !<v8>: * COPY
if (i is Int) { return; } !<v8>: * COPY
{ val i = 3 if (b) { return; } doSmth(i) if (i is Int) { return; } } !<v8>: * COPY
===================== =====================
== doSmth == == doSmth ==
fun doSmth(s: String) {} fun doSmth(s: String) {}
@@ -44,11 +44,11 @@ L4 [body entry point]:
mark({return}) mark({return})
ret L1 NEXT:[<END>] ret L1 NEXT:[<END>]
L5 [condition entry point]: L5 [condition entry point]:
- r(0) -> <v0> PREV:[] - r(0) -> <v1> PREV:[]
- r(1) -> <v1> PREV:[] - r(1) -> <v2> PREV:[]
- mark(0 > 1) PREV:[] - mark(0 > 1) PREV:[]
- call(0 > 1, compareTo|<v0>, <v1>) -> <v2> PREV:[] - call(0 > 1, compareTo|<v1>, <v2>) -> <v3> PREV:[]
- jt(L2 [loop entry point]|<v2>) NEXT:[read (Unit), mark({return})] PREV:[] - jt(L2 [loop entry point]|<v3>) NEXT:[read (Unit), mark({return})] PREV:[]
L3 [loop exit point]: L3 [loop exit point]:
- read (Unit) PREV:[] - read (Unit) PREV:[]
L1: L1:
@@ -5,11 +5,13 @@ fun main() {
} }
} }
--------------------- ---------------------
0 <v0>: {<: Comparable<Int>} NEW: r(0) -> <v0> 0 <v0>: {<: Comparable<Int>} NEW: r(0) -> <v0>
1 <v1>: Int NEW: r(1) -> <v1> 1 <v1>: Int NEW: r(1) -> <v1>
0 > 1 <v2>: Boolean NEW: call(0 > 1, compareTo|<v0>, <v1>) -> <v2> 0 > 1 <v2>: Boolean NEW: call(0 > 1, compareTo|<v0>, <v1>) -> <v2>
2 <v3>: * NEW: r(2) -> <v3> 2 <v3>: * NEW: r(2) -> <v3>
{ 2 } <v3>: * COPY { 2 } <v3>: * COPY
while(0 > 1) { 2 } !<v4>: *
{ while(0 > 1) { 2 } } !<v4>: * COPY
===================== =====================
== dowhile == == dowhile ==
fun dowhile() { fun dowhile() {
@@ -17,7 +19,11 @@ fun dowhile() {
while(0 > 1) while(0 > 1)
} }
--------------------- ---------------------
0 <v0>: {<: Comparable<Int>} NEW: r(0) -> <v0> return !<v0>: *
1 <v1>: Int NEW: r(1) -> <v1> {return} !<v0>: * COPY
0 > 1 <v2>: Boolean NEW: call(0 > 1, compareTo|<v0>, <v1>) -> <v2> 0 <v1>: {<: Comparable<Int>} NEW: r(0) -> <v1>
1 <v2>: Int NEW: r(1) -> <v2>
0 > 1 <v3>: Boolean NEW: call(0 > 1, compareTo|<v1>, <v2>) -> <v3>
do {return} while(0 > 1) !<v4>: *
{ do {return} while(0 > 1) } !<v4>: * COPY
===================== =====================
@@ -5,8 +5,11 @@ fun illegalWhenBlock(a: Any): Any {
} }
} }
--------------------- ---------------------
<v0>: {<: Any} NEW: magic[FAKE_INITIALIZER](a: Any) -> <v0> <v0>: {<: Any} NEW: magic[FAKE_INITIALIZER](a: Any) -> <v0>
a <v1>: * NEW: r(a) -> <v1> a <v1>: * NEW: r(a) -> <v1>
is Int <v2>: * NEW: magic[IS](is Int|<v1>) -> <v2> is Int <v2>: * NEW: magic[IS](is Int|<v1>) -> <v2>
a <v3>: {<: Any} NEW: r(a) -> <v3> a <v3>: {<: Any} NEW: r(a) -> <v3>
return a !<v4>: *
when(a) { is Int -> return a } !<v4>: * COPY
{ when(a) { is Int -> return a } } !<v4>: * COPY
===================== =====================
@@ -4,9 +4,12 @@ fun foo(a: Int, b: Int) {
} }
} }
--------------------- ---------------------
<v0>: Int NEW: magic[FAKE_INITIALIZER](a: Int) -> <v0> <v0>: Int NEW: magic[FAKE_INITIALIZER](a: Int) -> <v0>
<v1>: Int NEW: magic[FAKE_INITIALIZER](b: Int) -> <v1> <v1>: Int NEW: magic[FAKE_INITIALIZER](b: Int) -> <v1>
a <v2>: OR{{<: Any}, {<: Any}} NEW: r(a) -> <v2> a <v2>: OR{{<: Any}, {<: Any}} NEW: r(a) -> <v2>
b <v3>: * NEW: r(b) -> <v3> b <v3>: * NEW: r(b) -> <v3>
a == b <v4>: Boolean NEW: call(a == b, equals|<v2>, <v3>) -> <v4> a == b <v4>: Boolean NEW: call(a == b, equals|<v2>, <v3>) -> <v4>
{ } !<v5>: *
if (a == b) { } !<v5>: * COPY
{ if (a == b) { } } !<v5>: * COPY
===================== =====================
@@ -3,9 +3,12 @@ fun neq(a: Int, b: Int) {
if (a != b) {} if (a != b) {}
} }
--------------------- ---------------------
<v0>: Int NEW: magic[FAKE_INITIALIZER](a: Int) -> <v0> <v0>: Int NEW: magic[FAKE_INITIALIZER](a: Int) -> <v0>
<v1>: Int NEW: magic[FAKE_INITIALIZER](b: Int) -> <v1> <v1>: Int NEW: magic[FAKE_INITIALIZER](b: Int) -> <v1>
a <v2>: OR{{<: Any}, {<: Any}} NEW: r(a) -> <v2> a <v2>: OR{{<: Any}, {<: Any}} NEW: r(a) -> <v2>
b <v3>: * NEW: r(b) -> <v3> b <v3>: * NEW: r(b) -> <v3>
a != b <v4>: Boolean NEW: call(a != b, equals|<v2>, <v3>) -> <v4> a != b <v4>: Boolean NEW: call(a != b, equals|<v2>, <v3>) -> <v4>
{} !<v5>: *
if (a != b) {} !<v5>: * COPY
{ if (a != b) {} } !<v5>: * COPY
===================== =====================
@@ -6,15 +6,16 @@ fun foo() {
L0: L0:
1 <START> 1 <START>
2 mark({ return ?: null }) 2 mark({ return ?: null })
ret L1 NEXT:[<END>] ret L1 NEXT:[<END>]
- mark(return ?: null) PREV:[] - mark(return ?: null) PREV:[]
- jt(L2) NEXT:[r(null) -> <v0>, <END>] PREV:[] - jt(L2) NEXT:[r(null) -> <v0>, merge(return ?: null|!<v1>, <v0>) -> <v2>] PREV:[]
- r(null) -> <v0> PREV:[] - r(null) -> <v0> PREV:[]
L1:
L2: L2:
1 <END> NEXT:[<SINK>] PREV:[ret L1] - merge(return ?: null|!<v1>, <v0>) -> <v2> PREV:[]
L1:
1 <END> NEXT:[<SINK>] PREV:[ret L1]
error: error:
<ERROR> PREV:[] <ERROR> PREV:[]
sink: sink:
<SINK> PREV:[<ERROR>, <END>] <SINK> PREV:[<ERROR>, <END>]
===================== =====================
@@ -3,7 +3,8 @@ fun foo() {
return ?: null return ?: null
} }
--------------------- ---------------------
null <v0>: * NEW: r(null) -> <v0> return !<v1>: *
return ?: null <v0>: * COPY null <v0>: * NEW: r(null) -> <v0>
{ return ?: null } <v0>: * COPY return ?: null <v2>: * NEW: merge(return ?: null|!<v1>, <v0>) -> <v2>
{ return ?: null } <v2>: * COPY
===================== =====================
@@ -10,13 +10,13 @@ L0:
mark(throw Exception()) mark(throw Exception())
mark(Exception()) mark(Exception())
call(Exception(), <init>) -> <v0> call(Exception(), <init>) -> <v0>
throw (throw Exception()|<v0>) NEXT:[<ERROR>] throw (throw Exception()|<v0>) NEXT:[<ERROR>]
- r(1) -> <v1> PREV:[] - r(1) -> <v1> PREV:[]
- magic[STRING_TEMPLATE]("${throw Exception()} ${1}"|<v1>) -> <v2> PREV:[] - magic[STRING_TEMPLATE]("${throw Exception()} ${1}"|!<v2>, <v1>) -> <v3> PREV:[]
L1: L1:
1 <END> NEXT:[<SINK>] PREV:[] 1 <END> NEXT:[<SINK>] PREV:[]
error: error:
<ERROR> PREV:[throw (throw Exception()|<v0>)] <ERROR> PREV:[throw (throw Exception()|<v0>)]
sink: sink:
<SINK> PREV:[<ERROR>, <END>] <SINK> PREV:[<ERROR>, <END>]
===================== =====================
@@ -4,7 +4,8 @@ fun test() {
} }
--------------------- ---------------------
Exception() <v0>: {<: Throwable} NEW: call(Exception(), <init>) -> <v0> Exception() <v0>: {<: Throwable} NEW: call(Exception(), <init>) -> <v0>
throw Exception() !<v2>: *
1 <v1>: * NEW: r(1) -> <v1> 1 <v1>: * NEW: r(1) -> <v1>
"${throw Exception()} ${1}" <v2>: * NEW: magic[STRING_TEMPLATE]("${throw Exception()} ${1}"|<v1>) -> <v2> "${throw Exception()} ${1}" <v3>: * NEW: magic[STRING_TEMPLATE]("${throw Exception()} ${1}"|!<v2>, <v1>) -> <v3>
{ "${throw Exception()} ${1}" } <v2>: * COPY { "${throw Exception()} ${1}" } <v3>: * COPY
===================== =====================
@@ -27,9 +27,9 @@ L0:
w($i|<v1>, <v2>) w($i|<v1>, <v2>)
1 v(val j: Int get() = 20) 1 v(val j: Int get() = 20)
2 mark({ $i = 13 }) 2 mark({ $i = 13 })
magic[IMPLICIT_RECEIVER]($i) -> <v3> magic[IMPLICIT_RECEIVER]($i) -> <v4>
r(13) -> <v4> r(13) -> <v5>
w($i|<v3>, <v4>) w($i|<v4>, <v5>)
L1: L1:
1 <END> NEXT:[<SINK>] 1 <END> NEXT:[<SINK>]
error: error:
@@ -15,9 +15,13 @@ class AnonymousInitializers() {
} }
} }
--------------------- ---------------------
<v1>: AnonymousInitializers NEW: magic[IMPLICIT_RECEIVER]($i) -> <v1> <v1>: AnonymousInitializers NEW: magic[IMPLICIT_RECEIVER]($i) -> <v1>
<v3>: AnonymousInitializers NEW: magic[IMPLICIT_RECEIVER]($i) -> <v3> <v4>: AnonymousInitializers NEW: magic[IMPLICIT_RECEIVER]($i) -> <v4>
34 <v0>: Int NEW: r(34) -> <v0> 34 <v0>: Int NEW: r(34) -> <v0>
12 <v2>: Int NEW: r(12) -> <v2> 12 <v2>: Int NEW: r(12) -> <v2>
13 <v4>: Int NEW: r(13) -> <v4> $i = 12 !<v3>: *
{ $i = 12 } !<v3>: * COPY
13 <v5>: Int NEW: r(13) -> <v5>
$i = 13 !<v6>: *
{ $i = 13 } !<v6>: * COPY
===================== =====================
@@ -3,6 +3,8 @@ fun fail() : Nothing {
throw java.lang.RuntimeException() throw java.lang.RuntimeException()
} }
--------------------- ---------------------
RuntimeException() <v0>: {<: Throwable} NEW: call(RuntimeException(), <init>) -> <v0> RuntimeException() <v0>: {<: Throwable} NEW: call(RuntimeException(), <init>) -> <v0>
java.lang.RuntimeException() <v0>: {<: Throwable} COPY java.lang.RuntimeException() <v0>: {<: Throwable} COPY
throw java.lang.RuntimeException() !<v1>: *
{ throw java.lang.RuntimeException() } !<v1>: * COPY
===================== =====================
@@ -66,8 +66,8 @@ L0:
magic[IMPLICIT_RECEIVER]($x) -> <v0> magic[IMPLICIT_RECEIVER]($x) -> <v0>
r(1) -> <v1> r(1) -> <v1>
w($x|<v0>, <v1>) w($x|<v0>, <v1>)
2 r(object { val x : Int { $x = 1 } }) -> <v2> 2 r(object { val x : Int { $x = 1 } }) -> <v3>
w(a|<v2>) w(a|<v3>)
L1: L1:
1 <END> NEXT:[<SINK>] 1 <END> NEXT:[<SINK>]
error: error:
@@ -196,11 +196,11 @@ L0:
magic[IMPLICIT_RECEIVER]($x) -> <v0> magic[IMPLICIT_RECEIVER]($x) -> <v0>
r(1) -> <v1> r(1) -> <v1>
w($x|<v0>, <v1>) w($x|<v0>, <v1>)
2 jmp?(L2) NEXT:[r(object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } }) -> <v2>, d(fun ggg() { y = 10 })] 2 jmp?(L2) NEXT:[r(object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } }) -> <v3>, d(fun ggg() { y = 10 })]
d(fun ggg() { y = 10 }) NEXT:[<SINK>] d(fun ggg() { y = 10 }) NEXT:[<SINK>]
L2: L2:
r(object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } }) -> <v2> PREV:[jmp?(L2)] r(object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } }) -> <v3> PREV:[jmp?(L2)]
w(a|<v2>) w(a|<v3>)
L1: L1:
1 <END> NEXT:[<SINK>] 1 <END> NEXT:[<SINK>]
error: error:
@@ -257,11 +257,11 @@ L0:
2 jmp?(L2) NEXT:[jmp?(L5), d(fun foo() { x = 3 })] 2 jmp?(L2) NEXT:[jmp?(L5), d(fun foo() { x = 3 })]
d(fun foo() { x = 3 }) NEXT:[<SINK>] d(fun foo() { x = 3 }) NEXT:[<SINK>]
L2: L2:
jmp?(L5) NEXT:[r(object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } }) -> <v3>, d(fun bar() { x = 4 })] PREV:[jmp?(L2)] jmp?(L5) NEXT:[r(object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } }) -> <v4>, d(fun bar() { x = 4 })] PREV:[jmp?(L2)]
d(fun bar() { x = 4 }) NEXT:[<SINK>] d(fun bar() { x = 4 }) NEXT:[<SINK>]
L5: L5:
r(object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } }) -> <v3> PREV:[jmp?(L5)] r(object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } }) -> <v4> PREV:[jmp?(L5)]
w(a|<v3>) w(a|<v4>)
L1: L1:
1 <END> NEXT:[<SINK>] 1 <END> NEXT:[<SINK>]
error: error:
@@ -36,7 +36,9 @@ fun test1() {
--------------------- ---------------------
<v0>: <no name provided> NEW: magic[IMPLICIT_RECEIVER]($x) -> <v0> <v0>: <no name provided> NEW: magic[IMPLICIT_RECEIVER]($x) -> <v0>
1 <v1>: Int NEW: r(1) -> <v1> 1 <v1>: Int NEW: r(1) -> <v1>
object { val x : Int { $x = 1 } } <v2>: <no name provided> NEW: r(object { val x : Int { $x = 1 } }) -> <v2> $x = 1 !<v2>: *
{ $x = 1 } !<v2>: * COPY
object { val x : Int { $x = 1 } } <v3>: <no name provided> NEW: r(object { val x : Int { $x = 1 } }) -> <v3>
===================== =====================
== O == == O ==
object O { object O {
@@ -46,8 +48,10 @@ object O {
} }
} }
--------------------- ---------------------
<v0>: O NEW: magic[IMPLICIT_RECEIVER]($x) -> <v0> <v0>: O NEW: magic[IMPLICIT_RECEIVER]($x) -> <v0>
1 <v1>: Int NEW: r(1) -> <v1> 1 <v1>: Int NEW: r(1) -> <v1>
$x = 1 !<v2>: *
{ $x = 1 } !<v2>: * COPY
===================== =====================
== test2 == == test2 ==
fun test2() { fun test2() {
@@ -78,8 +82,10 @@ fun inner_bar() {
y = 10 y = 10
} }
--------------------- ---------------------
<v0>: <no name provided> NEW: magic[IMPLICIT_RECEIVER](y) -> <v0> <v0>: <no name provided> NEW: magic[IMPLICIT_RECEIVER](y) -> <v0>
10 <v1>: Int NEW: r(10) -> <v1> 10 <v1>: Int NEW: r(10) -> <v1>
y = 10 !<v2>: *
{ y = 10 } !<v2>: * COPY
===================== =====================
== test4 == == test4 ==
fun test4() { fun test4() {
@@ -97,15 +103,19 @@ fun test4() {
--------------------- ---------------------
<v0>: <no name provided> NEW: magic[IMPLICIT_RECEIVER]($x) -> <v0> <v0>: <no name provided> NEW: magic[IMPLICIT_RECEIVER]($x) -> <v0>
1 <v1>: Int NEW: r(1) -> <v1> 1 <v1>: Int NEW: r(1) -> <v1>
object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } } <v2>: <no name provided> NEW: r(object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } }) -> <v2> $x = 1 !<v2>: *
{ $x = 1 } !<v2>: * COPY
object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } } <v3>: <no name provided> NEW: r(object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } }) -> <v3>
===================== =====================
== ggg == == ggg ==
fun ggg() { fun ggg() {
y = 10 y = 10
} }
--------------------- ---------------------
<v0>: <no name provided> NEW: magic[IMPLICIT_RECEIVER](y) -> <v0> <v0>: <no name provided> NEW: magic[IMPLICIT_RECEIVER](y) -> <v0>
10 <v1>: Int NEW: r(10) -> <v1> 10 <v1>: Int NEW: r(10) -> <v1>
y = 10 !<v2>: *
{ y = 10 } !<v2>: * COPY
===================== =====================
== test5 == == test5 ==
fun test5() { fun test5() {
@@ -126,21 +136,27 @@ fun test5() {
<v1>: <no name provided> NEW: magic[IMPLICIT_RECEIVER]($x) -> <v1> <v1>: <no name provided> NEW: magic[IMPLICIT_RECEIVER]($x) -> <v1>
1 <v0>: Int NEW: r(1) -> <v0> 1 <v0>: Int NEW: r(1) -> <v0>
2 <v2>: Int NEW: r(2) -> <v2> 2 <v2>: Int NEW: r(2) -> <v2>
object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } } <v3>: <no name provided> NEW: r(object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } }) -> <v3> $x = 2 !<v3>: *
{ $x = 2 } !<v3>: * COPY
object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } } <v4>: <no name provided> NEW: r(object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } }) -> <v4>
===================== =====================
== foo == == foo ==
fun foo() { fun foo() {
x = 3 x = 3
} }
--------------------- ---------------------
<v0>: <no name provided> NEW: magic[IMPLICIT_RECEIVER](x) -> <v0> <v0>: <no name provided> NEW: magic[IMPLICIT_RECEIVER](x) -> <v0>
3 <v1>: Int NEW: r(3) -> <v1> 3 <v1>: Int NEW: r(3) -> <v1>
x = 3 !<v2>: *
{ x = 3 } !<v2>: * COPY
===================== =====================
== bar == == bar ==
fun bar() { fun bar() {
x = 4 x = 4
} }
--------------------- ---------------------
<v0>: <no name provided> NEW: magic[IMPLICIT_RECEIVER](x) -> <v0> <v0>: <no name provided> NEW: magic[IMPLICIT_RECEIVER](x) -> <v0>
4 <v1>: Int NEW: r(4) -> <v1> 4 <v1>: Int NEW: r(4) -> <v1>
x = 4 !<v2>: *
{ x = 4 } !<v2>: * COPY
===================== =====================
@@ -25,11 +25,13 @@ fun foo(b: B) : Int {
return o.foo() return o.foo()
} }
--------------------- ---------------------
<v0>: B NEW: magic[FAKE_INITIALIZER](b: B) -> <v0> <v0>: B NEW: magic[FAKE_INITIALIZER](b: B) -> <v0>
<v2>: * NEW: magic[VALUE_CONSUMER](A by b|<v1>) -> <v2> <v2>: * NEW: magic[VALUE_CONSUMER](A by b|<v1>) -> <v2>
b <v1>: {<: A} NEW: r(b) -> <v1> b <v1>: {<: A} NEW: r(b) -> <v1>
object : A by b {} <v3>: <no name provided> NEW: r(object : A by b {}) -> <v3> object : A by b {} <v3>: <no name provided> NEW: r(object : A by b {}) -> <v3>
o <v4>: {<: A} NEW: r(o) -> <v4> o <v4>: {<: A} NEW: r(o) -> <v4>
foo() <v5>: Int NEW: call(foo(), foo|<v4>) -> <v5> foo() <v5>: Int NEW: call(foo(), foo|<v4>) -> <v5>
o.foo() <v5>: Int COPY o.foo() <v5>: Int COPY
return o.foo() !<v6>: *
{ val o = object : A by b {} return o.foo() } !<v6>: * COPY
===================== =====================
@@ -16,5 +16,7 @@ get() {
return b return b
} }
--------------------- ---------------------
b <v0>: Int NEW: r(b) -> <v0> b <v0>: Int NEW: r(b) -> <v0>
return b !<v1>: *
{ val b: Int return b } !<v1>: * COPY
===================== =====================
@@ -7,16 +7,16 @@ L0:
1 <START> 1 <START>
2 mark({ false || (return false) }) 2 mark({ false || (return false) })
r(false) -> <v0> r(false) -> <v0>
jt(L2|<v0>) NEXT:[mark((return false)), magic[OR](false || (return false)|<v0>) -> <v2>] jt(L2|<v0>) NEXT:[mark((return false)), magic[OR](false || (return false)|<v0>, !<v2>) -> <v3>]
mark((return false)) mark((return false))
r(false) -> <v1> r(false) -> <v1>
ret(*|<v1>) L1 NEXT:[<END>] ret(*|<v1>) L1 NEXT:[<END>]
L2: L2:
magic[OR](false || (return false)|<v0>) -> <v2> PREV:[jt(L2|<v0>)] magic[OR](false || (return false)|<v0>, !<v2>) -> <v3> PREV:[jt(L2|<v0>)]
L1: L1:
1 <END> NEXT:[<SINK>] PREV:[ret(*|<v1>) L1, magic[OR](false || (return false)|<v0>) -> <v2>] 1 <END> NEXT:[<SINK>] PREV:[ret(*|<v1>) L1, magic[OR](false || (return false)|<v0>, !<v2>) -> <v3>]
error: error:
<ERROR> PREV:[] <ERROR> PREV:[]
sink: sink:
<SINK> PREV:[<ERROR>, <END>] <SINK> PREV:[<ERROR>, <END>]
===================== =====================
@@ -5,6 +5,8 @@ fun blockAndAndMismatch() : Boolean {
--------------------- ---------------------
false <v0>: Boolean NEW: r(false) -> <v0> false <v0>: Boolean NEW: r(false) -> <v0>
false <v1>: Boolean NEW: r(false) -> <v1> false <v1>: Boolean NEW: r(false) -> <v1>
false || (return false) <v2>: * NEW: magic[OR](false || (return false)|<v0>) -> <v2> return false !<v2>: *
{ false || (return false) } <v2>: * COPY (return false) !<v2>: * COPY
false || (return false) <v3>: * NEW: magic[OR](false || (return false)|<v0>, !<v2>) -> <v3>
{ false || (return false) } <v3>: * COPY
===================== =====================
@@ -48,7 +48,7 @@ L0:
- call(bar(), bar) PREV:[] - call(bar(), bar) PREV:[]
- jmp(error) NEXT:[<ERROR>] PREV:[] - jmp(error) NEXT:[<ERROR>] PREV:[]
- mark(doSomething) PREV:[] - mark(doSomething) PREV:[]
- call(doSomething, doSomething) -> <v3> PREV:[] - call(doSomething, doSomething|!<v3>) -> <v4> PREV:[]
L1: L1:
1 <END> NEXT:[<SINK>] PREV:[] 1 <END> NEXT:[<SINK>] PREV:[]
error: error:
@@ -13,11 +13,12 @@ fun foo() {
bar().doSomething bar().doSomething
} }
--------------------- ---------------------
null <v0>: * NEW: r(null) -> <v0> null <v0>: * NEW: r(null) -> <v0>
null!! <v1>: * NEW: magic[NOT_NULL_ASSERTION](null!!|<v0>) -> <v1> null!! <v1>: * NEW: magic[NOT_NULL_ASSERTION](null!!|<v0>) -> <v1>
doSomething() <v2>: * NEW: call(doSomething(), doSomething|<v1>) -> <v2> doSomething() <v2>: * NEW: call(doSomething(), doSomething|<v1>) -> <v2>
null!!.doSomething() <v2>: * COPY null!!.doSomething() <v2>: * COPY
doSomething <v3>: * NEW: call(doSomething, doSomething) -> <v3> bar() !<v3>: *
bar().doSomething <v3>: * COPY doSomething <v4>: * NEW: call(doSomething, doSomething|!<v3>) -> <v4>
{ null!!.doSomething() bar().doSomething } <v3>: * COPY bar().doSomething <v4>: * COPY
{ null!!.doSomething() bar().doSomething } <v4>: * COPY
===================== =====================
@@ -7,11 +7,11 @@ L0:
1 <START> 1 <START>
2 mark({ this() }) 2 mark({ this() })
mark(this()) mark(this())
call(this(), invoke) -> <v0> call(this(), invoke|!<v0>) -> <v1>
L1: L1:
1 <END> NEXT:[<SINK>] 1 <END> NEXT:[<SINK>]
error: error:
<ERROR> PREV:[] <ERROR> PREV:[]
sink: sink:
<SINK> PREV:[<ERROR>, <END>] <SINK> PREV:[<ERROR>, <END>]
===================== =====================
@@ -3,6 +3,8 @@ fun Function0<Unit>.foo() {
this() this()
} }
--------------------- ---------------------
this() <v0>: * NEW: call(this(), invoke) -> <v0> this !<v0>: * COPY
{ this() } <v0>: * COPY this !<v0>: *
this() <v1>: * NEW: call(this(), invoke|!<v0>) -> <v1>
{ this() } <v1>: * COPY
===================== =====================
@@ -14,11 +14,11 @@ L0:
error(foo, No resolved call) error(foo, No resolved call)
r(a) -> <v1> r(a) -> <v1>
mark(foo()) mark(foo())
magic[UNRESOLVED_CALL](foo()|<v1>) -> <v2> magic[UNRESOLVED_CALL](foo()|!<v2>, <v1>) -> <v3>
L1: L1:
1 <END> NEXT:[<SINK>] 1 <END> NEXT:[<SINK>]
error: error:
<ERROR> PREV:[] <ERROR> PREV:[]
sink: sink:
<SINK> PREV:[<ERROR>, <END>] <SINK> PREV:[<ERROR>, <END>]
===================== =====================
@@ -5,7 +5,8 @@ fun test(a: Any) {
--------------------- ---------------------
<v0>: {<: Any} NEW: magic[FAKE_INITIALIZER](a: Any) -> <v0> <v0>: {<: Any} NEW: magic[FAKE_INITIALIZER](a: Any) -> <v0>
a <v1>: * NEW: r(a) -> <v1> a <v1>: * NEW: r(a) -> <v1>
foo() <v2>: * NEW: magic[UNRESOLVED_CALL](foo()|<v1>) -> <v2> foo !<v2>: *
a.foo() <v2>: * COPY foo() <v3>: * NEW: magic[UNRESOLVED_CALL](foo()|!<v2>, <v1>) -> <v3>
{ a.foo() } <v2>: * COPY a.foo() <v3>: * COPY
{ a.foo() } <v3>: * COPY
===================== =====================
@@ -7,6 +7,9 @@ tailRecursive fun test() : Int {
} }
} }
--------------------- ---------------------
test() <v0>: * NEW: call(test(), test) -> <v0> { // do nothing } !<v1>: *
{ test() } <v0>: * COPY test() <v0>: * NEW: call(test(), test) -> <v0>
{ test() } <v0>: * COPY
try { // do nothing } finally { test() } !<v1>: * COPY
{ try { // do nothing } finally { test() } } !<v1>: * COPY
===================== =====================
@@ -7,5 +7,10 @@ tailRecursive fun test() : Int {
} }
} }
--------------------- ---------------------
test() <v0>: Int NEW: call(test(), test) -> <v0> { // do nothing } !<v2>: *
test() <v0>: Int NEW: call(test(), test) -> <v0>
return test() !<v1>: *
{ return test() } !<v1>: * COPY
try { // do nothing } finally { return test() } !<v2>: * COPY
{ try { // do nothing } finally { return test() } } !<v2>: * COPY
===================== =====================
@@ -24,23 +24,23 @@ L0:
jf(L2|<v5>) NEXT:[read (Unit), r(sum) -> <v6>] jf(L2|<v5>) NEXT:[read (Unit), r(sum) -> <v6>]
r(sum) -> <v6> r(sum) -> <v6>
ret(*|<v6>) L1 NEXT:[<END>] ret(*|<v6>) L1 NEXT:[<END>]
- jmp(L3) NEXT:[r(x) -> <v7>] PREV:[] - jmp(L3) NEXT:[r(x) -> <v8>] PREV:[]
L2: L2:
read (Unit) PREV:[jf(L2|<v5>)] read (Unit) PREV:[jf(L2|<v5>)]
L3: L3:
r(x) -> <v7> r(x) -> <v8>
r(1) -> <v8> r(1) -> <v9>
mark(x - 1) mark(x - 1)
call(x - 1, minus|<v7>, <v8>) -> <v9> call(x - 1, minus|<v8>, <v9>) -> <v10>
r(sum) -> <v10> r(sum) -> <v11>
r(x) -> <v11> r(x) -> <v12>
mark(sum + x) mark(sum + x)
call(sum + x, plus|<v10>, <v11>) -> <v12> call(sum + x, plus|<v11>, <v12>) -> <v13>
mark(sum(x - 1, sum + x)) mark(sum(x - 1, sum + x))
call(sum(x - 1, sum + x), sum|<v9>, <v12>) -> <v13> call(sum(x - 1, sum + x), sum|<v10>, <v13>) -> <v14>
ret(*|<v13>) L1 ret(*|<v14>) L1
L1: L1:
1 <END> NEXT:[<SINK>] PREV:[ret(*|<v6>) L1, ret(*|<v13>) L1] 1 <END> NEXT:[<SINK>] PREV:[ret(*|<v6>) L1, ret(*|<v14>) L1]
error: error:
<ERROR> PREV:[] <ERROR> PREV:[]
sink: sink:
+19 -15
View File
@@ -4,19 +4,23 @@ tailRecursive fun sum(x: Long, sum: Long): Long {
return sum(x - 1, sum + x) return sum(x - 1, sum + x)
} }
--------------------- ---------------------
<v0>: Long NEW: magic[FAKE_INITIALIZER](x: Long) -> <v0> <v0>: Long NEW: magic[FAKE_INITIALIZER](x: Long) -> <v0>
<v1>: Long NEW: magic[FAKE_INITIALIZER](sum: Long) -> <v1> <v1>: Long NEW: magic[FAKE_INITIALIZER](sum: Long) -> <v1>
x <v2>: OR{{<: Any}, {<: Any}} NEW: r(x) -> <v2> x <v2>: OR{{<: Any}, {<: Any}} NEW: r(x) -> <v2>
0 <v3>: {<: Number} NEW: r(0) -> <v3> 0 <v3>: {<: Number} NEW: r(0) -> <v3>
toLong() <v4>: * NEW: call(toLong(), toLong|<v3>) -> <v4> toLong() <v4>: * NEW: call(toLong(), toLong|<v3>) -> <v4>
0.toLong() <v4>: * COPY 0.toLong() <v4>: * COPY
x == 0.toLong() <v5>: Boolean NEW: call(x == 0.toLong(), equals|<v2>, <v4>) -> <v5> x == 0.toLong() <v5>: Boolean NEW: call(x == 0.toLong(), equals|<v2>, <v4>) -> <v5>
sum <v6>: Long NEW: r(sum) -> <v6> sum <v6>: Long NEW: r(sum) -> <v6>
x <v7>: Long NEW: r(x) -> <v7> return sum !<v7>: *
1 <v8>: Int NEW: r(1) -> <v8> if (x == 0.toLong()) return sum !<v7>: * COPY
x - 1 <v9>: Long NEW: call(x - 1, minus|<v7>, <v8>) -> <v9> x <v8>: Long NEW: r(x) -> <v8>
sum <v10>: Long NEW: r(sum) -> <v10> 1 <v9>: Int NEW: r(1) -> <v9>
x <v11>: Long NEW: r(x) -> <v11> x - 1 <v10>: Long NEW: call(x - 1, minus|<v8>, <v9>) -> <v10>
sum + x <v12>: Long NEW: call(sum + x, plus|<v10>, <v11>) -> <v12> sum <v11>: Long NEW: r(sum) -> <v11>
sum(x - 1, sum + x) <v13>: Long NEW: call(sum(x - 1, sum + x), sum|<v9>, <v12>) -> <v13> x <v12>: Long NEW: r(x) -> <v12>
sum + x <v13>: Long NEW: call(sum + x, plus|<v11>, <v12>) -> <v13>
sum(x - 1, sum + x) <v14>: Long NEW: call(sum(x - 1, sum + x), sum|<v10>, <v13>) -> <v14>
return sum(x - 1, sum + x) !<v15>: *
{ if (x == 0.toLong()) return sum return sum(x - 1, sum + x) } !<v15>: * COPY
===================== =====================
@@ -11,24 +11,25 @@ L0:
1 <START> 1 <START>
2 mark({ try { return foo() } catch (e: Throwable) { } }) 2 mark({ try { return foo() } catch (e: Throwable) { } })
mark(try { return foo() } catch (e: Throwable) { }) mark(try { return foo() } catch (e: Throwable) { })
jmp?(L2 [onException]) NEXT:[v(e: Throwable), mark({ return foo() })] jmp?(L2 [onException]) NEXT:[v(e: Throwable), mark({ return foo() })]
3 mark({ return foo() }) 3 mark({ return foo() })
mark(foo()) mark(foo())
call(foo(), foo) -> <v0> call(foo(), foo) -> <v0>
ret(*|<v0>) L1 NEXT:[<END>] ret(*|<v0>) L1 NEXT:[<END>]
- 2 jmp(L3 [afterCatches]) NEXT:[<END>] PREV:[] - 2 jmp(L3 [afterCatches]) NEXT:[merge(try { return foo() } catch (e: Throwable) { }|!<v1>, !<v3>) -> <v4>] PREV:[]
L2 [onException]: L2 [onException]:
3 v(e: Throwable) PREV:[jmp?(L2 [onException])] 3 v(e: Throwable) PREV:[jmp?(L2 [onException])]
magic[FAKE_INITIALIZER](e: Throwable) -> <v1> magic[FAKE_INITIALIZER](e: Throwable) -> <v2>
w(e|<v1>) w(e|<v2>)
4 mark({ }) 4 mark({ })
read (Unit) read (Unit)
3 jmp(L3 [afterCatches]) 3 jmp(L3 [afterCatches])
L1:
L3 [afterCatches]: L3 [afterCatches]:
1 <END> NEXT:[<SINK>] PREV:[ret(*|<v0>) L1, jmp(L3 [afterCatches])] 2 merge(try { return foo() } catch (e: Throwable) { }|!<v1>, !<v3>) -> <v4>
L1:
1 <END> NEXT:[<SINK>] PREV:[ret(*|<v0>) L1, merge(try { return foo() } catch (e: Throwable) { }|!<v1>, !<v3>) -> <v4>]
error: error:
<ERROR> PREV:[] <ERROR> PREV:[]
sink: sink:
<SINK> PREV:[<ERROR>, <END>] <SINK> PREV:[<ERROR>, <END>]
===================== =====================
+7 -2
View File
@@ -7,6 +7,11 @@ tailRecursive fun foo() {
} }
} }
--------------------- ---------------------
<v1>: {<: Throwable} NEW: magic[FAKE_INITIALIZER](e: Throwable) -> <v1> <v2>: {<: Throwable} NEW: magic[FAKE_INITIALIZER](e: Throwable) -> <v2>
foo() <v0>: Unit NEW: call(foo(), foo) -> <v0> foo() <v0>: Unit NEW: call(foo(), foo) -> <v0>
return foo() !<v1>: *
{ return foo() } !<v1>: * COPY
{ } !<v3>: *
try { return foo() } catch (e: Throwable) { } <v4>: * NEW: merge(try { return foo() } catch (e: Throwable) { }|!<v1>, !<v3>) -> <v4>
{ try { return foo() } catch (e: Throwable) { } } <v4>: * COPY
===================== =====================
@@ -1,6 +1,6 @@
fun test() { fun test() {
run1 @f{(): Int -> run1 @f{(): Int ->
(return@f 1): Nothing (return@f 1)<!UNREACHABLE_CODE!>: Nothing<!>
} }
} }
@@ -54,7 +54,10 @@ public abstract class AbstractPseudoValueTest : AbstractPseudocodeTest() {
} }
fun valueDescription(element: JetElement?, value: PseudoValue): String { fun valueDescription(element: JetElement?, value: PseudoValue): String {
return if (value.element != element) "COPY" else "NEW: ${value.createdAt}" return when {
value.element != element -> "COPY"
else -> value.createdAt?.let { "NEW: $it" } ?: ""
}
} }
val elementToValues = getElementToValueMap(pseudocode) val elementToValues = getElementToValueMap(pseudocode)