Skip to content

Commit

Permalink
[FE 1.0] Always create return value for CallInstruction
Browse files Browse the repository at this point in the history
This fixes missing `USED_AS_EXPRESSION` recordings
^KT-47527 Fixed
  • Loading branch information
demiurg906 authored and TeamCityServer committed Jul 2, 2021
1 parent b2372ff commit ae608ea
Show file tree
Hide file tree
Showing 50 changed files with 496 additions and 204 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Expand Up @@ -17,7 +17,6 @@
package org.jetbrains.kotlin.cfg.pseudocode

import com.intellij.util.containers.Stack
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.cfg.*
import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
Expand Down Expand Up @@ -383,14 +382,13 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
receiverValues: Map<PseudoValue, ReceiverValue>,
arguments: Map<PseudoValue, ValueParameterDescriptor>
): CallInstruction {
val returnType = resolvedCall.resultingDescriptor.returnType
val instruction = CallInstruction(
valueElement,
currentScope,
resolvedCall,
receiverValues,
arguments,
if (returnType != null && KotlinBuiltIns.isNothing(returnType)) null else valueFactory
valueFactory
)
add(instruction)
return instruction
Expand Down
Expand Up @@ -52,7 +52,7 @@ L0:
mark({ if (flag) { s.add(it) } else { s.remove(it) } return true })
r({ if (flag) { s.add(it) } else { s.remove(it) } return true }) -> <v3>
mark(let { if (flag) { s.add(it) } else { s.remove(it) } return true })
call(let { if (flag) { s.add(it) } else { s.remove(it) } return true }, let|<v2>, <v3>)
call(let { if (flag) { s.add(it) } else { s.remove(it) } return true }, let|<v2>, <v3>) -> <v4>
L4 [before inlined declaration]:
inlined({ if (flag) { s.add(it) } else { s.remove(it) } return true }) NEXT:[<SINK>]
L3 [result of call]:
Expand Down
Expand Up @@ -28,8 +28,8 @@ fun test(name: String?, flag: Boolean): Boolean {
<v1>: Boolean NEW: magic[FAKE_INITIALIZER](flag: Boolean) -> <v1>
name <v2>: String NEW: r(name) -> <v2>
{ if (flag) { s.add(it) } else { s.remove(it) } return true } <v3>: {<: (String) -> Nothing} NEW: r({ if (flag) { s.add(it) } else { s.remove(it) } return true }) -> <v3>
let { if (flag) { s.add(it) } else { s.remove(it) } return true } !<v4>: *
name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true } !<v4>: * COPY
let { if (flag) { s.add(it) } else { s.remove(it) } return true } <v4>: * NEW: call(let { if (flag) { s.add(it) } else { s.remove(it) } return true }, let|<v2>, <v3>) -> <v4>
name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true } <v4>: * COPY
false <v5>: Boolean NEW: r(false) -> <v5>
return false !<v6>: *
{ name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true } return false } !<v6>: * COPY
Expand Down
Expand Up @@ -55,9 +55,9 @@ L0:
L4 [after local declaration]:
r({ if (flag) { s.add(it) } else { s.remove(it) } return true }) -> <v3> PREV:[jmp?(L4)]
mark(let { if (flag) { s.add(it) } else { s.remove(it) } return true })
call(let { if (flag) { s.add(it) } else { s.remove(it) } return true }, let|<v2>, <v3>)
call(let { if (flag) { s.add(it) } else { s.remove(it) } return true }, let|<v2>, <v3>) -> <v4>
L3 [result of call]:
jmp?(L2) NEXT:[mark({ name?.hashCode() }), r(false) -> <v5>] PREV:[jf(L3), call(let { if (flag) { s.add(it) } else { s.remove(it) } return true }, let|<v2>, <v3>)]
jmp?(L2) NEXT:[mark({ name?.hashCode() }), r(false) -> <v5>] PREV:[jf(L3), call(let { if (flag) { s.add(it) } else { s.remove(it) } return true }, let|<v2>, <v3>) -> <v4>]
r(false) -> <v5>
6 mark({ name?.hashCode() })
mark(name?.hashCode())
Expand Down
Expand Up @@ -28,8 +28,8 @@ fun test(name: String?, flag: Boolean): Boolean {
<v1>: Boolean NEW: magic[FAKE_INITIALIZER](flag: Boolean) -> <v1>
name <v2>: String NEW: r(name) -> <v2>
{ if (flag) { s.add(it) } else { s.remove(it) } return true } <v3>: {<: (String) -> Nothing} NEW: r({ if (flag) { s.add(it) } else { s.remove(it) } return true }) -> <v3>
let { if (flag) { s.add(it) } else { s.remove(it) } return true } !<v4>: *
name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true } !<v4>: * COPY
let { if (flag) { s.add(it) } else { s.remove(it) } return true } <v4>: * NEW: call(let { if (flag) { s.add(it) } else { s.remove(it) } return true }, let|<v2>, <v3>) -> <v4>
name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true } <v4>: * COPY
false <v5>: Boolean NEW: r(false) -> <v5>
return false !<v6>: *
{ name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true } return false } !<v6>: * COPY
Expand Down
22 changes: 11 additions & 11 deletions compiler/testData/cfg/deadCode/notLocalReturn_after.instructions
Expand Up @@ -103,13 +103,13 @@ L2 [after local declaration]:
mark({ return })
r({ return }) -> <v1>
mark(let { return })
call(let { return }, let|<v0>, <v1>)
call(let { return }, let|<v0>, <v1>) -> <v2>
L6 [before inlined declaration]:
inlined({ return }) NEXT:[<SINK>]
L5 [result of call]:
L7 [after inlined declaration]:
mark(f(null?.let { return })) PREV:[jf(L5)]
call(f(null?.let { return }), f|!<v2>) -> <v3>
call(f(null?.let { return }), f|<v2>) -> <v3>
mark(doSomething())
call(doSomething(), doSomething) -> <v4>
L1:
Expand Down Expand Up @@ -163,28 +163,28 @@ L0:
magic[FAKE_INITIALIZER](x: Any?) -> <v0>
w(x|<v0>)
mark(x?.let { return true })
jf(L2) NEXT:[mark(x?.let { return true } ?: false), r(x) -> <v1>]
jf(L2) NEXT:[mark(x?.let { return true } ?: false), r(x) -> <v1>]
r(x) -> <v1>
mark({ return true })
r({ return true }) -> <v2>
mark(let { return true })
call(let { return true }, let|<v1>, <v2>)
call(let { return true }, let|<v1>, <v2>) -> <v3>
L3 [before inlined declaration]:
inlined({ return true }) NEXT:[<SINK>]
inlined({ return true }) NEXT:[<SINK>]
L2 [result of call]:
L4 [after inlined declaration]:
mark(x?.let { return true } ?: false) PREV:[jf(L2)]
jt(L7|!<v3>) NEXT:[r(false) -> <v4>, merge(x?.let { return true } ?: false|!<v3>, <v4>) -> <v5>]
mark(x?.let { return true } ?: false) PREV:[jf(L2)]
jt(L7|<v3>) NEXT:[r(false) -> <v4>, merge(x?.let { return true } ?: false|<v3>, <v4>) -> <v5>]
r(false) -> <v4>
L7 [after elvis operator]:
merge(x?.let { return true } ?: false|!<v3>, <v4>) -> <v5> PREV:[jt(L7|!<v3>), r(false) -> <v4>]
merge(x?.let { return true } ?: false|<v3>, <v4>) -> <v5> PREV:[jt(L7|<v3>), r(false) -> <v4>]
ret(*|<v5>) L1
L1:
<END> NEXT:[<SINK>] PREV:[ret(*|<v0>) L1, ret(*|<v5>) L1]
<END> NEXT:[<SINK>] PREV:[ret(*|<v0>) L1, ret(*|<v5>) L1]
error:
<ERROR> PREV:[]
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>, inlined({ return true })]
<SINK> PREV:[<ERROR>, <END>, inlined({ return true })]
=====================
== inlined anonymous_2 ==
{
Expand Down
12 changes: 6 additions & 6 deletions compiler/testData/cfg/deadCode/notLocalReturn_after.values
Expand Up @@ -45,9 +45,9 @@ fun test2() {
---------------------
null <v0>: Nothing NEW: r(null) -> <v0>
{ return } <v1>: {<: (Nothing) -> Nothing} NEW: r({ return }) -> <v1>
let { return } !<v2>: *
null?.let { return } !<v2>: * COPY
f(null?.let { return }) <v3>: * NEW: call(f(null?.let { return }), f|!<v2>) -> <v3>
let { return } <v2>: * NEW: call(let { return }, let|<v0>, <v1>) -> <v2>
null?.let { return } <v2>: * COPY
f(null?.let { return }) <v3>: * NEW: call(f(null?.let { return }), f|<v2>) -> <v3>
doSomething() <v4>: * NEW: call(doSomething(), doSomething) -> <v4>
{ fun f(x: Any?) = x f(null?.let { return }) // false unreachable here doSomething() } <v4>: * COPY
=====================
Expand All @@ -72,10 +72,10 @@ fun test3(x: Any?): Boolean =
<v0>: * NEW: magic[FAKE_INITIALIZER](x: Any?) -> <v0>
x <v1>: {<: Any} NEW: r(x) -> <v1>
{ return true } <v2>: {<: (Any) -> Nothing} NEW: r({ return true }) -> <v2>
let { return true } !<v3>: *
x?.let { return true } !<v3>: * COPY
let { return true } <v3>: Boolean NEW: call(let { return true }, let|<v1>, <v2>) -> <v3>
x?.let { return true } <v3>: Boolean COPY
false <v4>: Boolean NEW: r(false) -> <v4>
x?.let { return true } ?: false <v5>: Boolean NEW: merge(x?.let { return true } ?: false|!<v3>, <v4>) -> <v5>
x?.let { return true } ?: false <v5>: Boolean NEW: merge(x?.let { return true } ?: false|<v3>, <v4>) -> <v5>
=====================
== inlined anonymous_2 ==
{
Expand Down
28 changes: 14 additions & 14 deletions compiler/testData/cfg/deadCode/notLocalReturn_before.instructions
Expand Up @@ -106,10 +106,10 @@ L2 [after local declaration]:
L6 [after local declaration]:
r({ return }) -> <v1> PREV:[jmp?(L6)]
mark(let { return })
call(let { return }, let|<v0>, <v1>)
call(let { return }, let|<v0>, <v1>) -> <v2>
L5 [result of call]:
mark(f(null?.let { return })) PREV:[jf(L5), call(let { return }, let|<v0>, <v1>)]
call(f(null?.let { return }), f|!<v2>) -> <v3>
mark(f(null?.let { return })) PREV:[jf(L5), call(let { return }, let|<v0>, <v1>) -> <v2>]
call(f(null?.let { return }), f|<v2>) -> <v3>
mark(doSomething())
call(doSomething(), doSomething) -> <v4>
L1:
Expand Down Expand Up @@ -163,28 +163,28 @@ L0:
magic[FAKE_INITIALIZER](x: Any?) -> <v0>
w(x|<v0>)
mark(x?.let { return true })
jf(L2) NEXT:[mark(x?.let { return true } ?: false), r(x) -> <v1>]
jf(L2) NEXT:[mark(x?.let { return true } ?: false), r(x) -> <v1>]
r(x) -> <v1>
mark({ return true })
jmp?(L3) NEXT:[r({ return true }) -> <v2>, d({ return true })]
d({ return true }) NEXT:[<SINK>]
jmp?(L3) NEXT:[r({ return true }) -> <v2>, d({ return true })]
d({ return true }) NEXT:[<SINK>]
L3 [after local declaration]:
r({ return true }) -> <v2> PREV:[jmp?(L3)]
r({ return true }) -> <v2> PREV:[jmp?(L3)]
mark(let { return true })
call(let { return true }, let|<v1>, <v2>)
call(let { return true }, let|<v1>, <v2>) -> <v3>
L2 [result of call]:
mark(x?.let { return true } ?: false) PREV:[jf(L2), call(let { return true }, let|<v1>, <v2>)]
jt(L6|!<v3>) NEXT:[r(false) -> <v4>, merge(x?.let { return true } ?: false|!<v3>, <v4>) -> <v5>]
mark(x?.let { return true } ?: false) PREV:[jf(L2), call(let { return true }, let|<v1>, <v2>) -> <v3>]
jt(L6|<v3>) NEXT:[r(false) -> <v4>, merge(x?.let { return true } ?: false|<v3>, <v4>) -> <v5>]
r(false) -> <v4>
L6 [after elvis operator]:
merge(x?.let { return true } ?: false|!<v3>, <v4>) -> <v5> PREV:[jt(L6|!<v3>), r(false) -> <v4>]
merge(x?.let { return true } ?: false|<v3>, <v4>) -> <v5> PREV:[jt(L6|<v3>), r(false) -> <v4>]
ret(*|<v5>) L1
L1:
<END> NEXT:[<SINK>] PREV:[ret(*|<v0>) L1, ret(*|<v5>) L1]
<END> NEXT:[<SINK>] PREV:[ret(*|<v0>) L1, ret(*|<v5>) L1]
error:
<ERROR> PREV:[]
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>, d({ return true })]
<SINK> PREV:[<ERROR>, <END>, d({ return true })]
=====================
== anonymous_2 ==
{
Expand Down
12 changes: 6 additions & 6 deletions compiler/testData/cfg/deadCode/notLocalReturn_before.values
Expand Up @@ -45,9 +45,9 @@ fun test2() {
---------------------
null <v0>: Nothing NEW: r(null) -> <v0>
{ return } <v1>: {<: (Nothing) -> Nothing} NEW: r({ return }) -> <v1>
let { return } !<v2>: *
null?.let { return } !<v2>: * COPY
f(null?.let { return }) <v3>: * NEW: call(f(null?.let { return }), f|!<v2>) -> <v3>
let { return } <v2>: * NEW: call(let { return }, let|<v0>, <v1>) -> <v2>
null?.let { return } <v2>: * COPY
f(null?.let { return }) <v3>: * NEW: call(f(null?.let { return }), f|<v2>) -> <v3>
doSomething() <v4>: * NEW: call(doSomething(), doSomething) -> <v4>
{ fun f(x: Any?) = x f(null?.let { return }) // false unreachable here doSomething() } <v4>: * COPY
=====================
Expand All @@ -72,10 +72,10 @@ fun test3(x: Any?): Boolean =
<v0>: * NEW: magic[FAKE_INITIALIZER](x: Any?) -> <v0>
x <v1>: {<: Any} NEW: r(x) -> <v1>
{ return true } <v2>: {<: (Any) -> Nothing} NEW: r({ return true }) -> <v2>
let { return true } !<v3>: *
x?.let { return true } !<v3>: * COPY
let { return true } <v3>: Boolean NEW: call(let { return true }, let|<v1>, <v2>) -> <v3>
x?.let { return true } <v3>: Boolean COPY
false <v4>: Boolean NEW: r(false) -> <v4>
x?.let { return true } ?: false <v5>: Boolean NEW: merge(x?.let { return true } ?: false|!<v3>, <v4>) -> <v5>
x?.let { return true } ?: false <v5>: Boolean NEW: merge(x?.let { return true } ?: false|<v3>, <v4>) -> <v5>
=====================
== anonymous_2 ==
{
Expand Down

0 comments on commit ae608ea

Please sign in to comment.