Skip to content

Commit 2074edc

Browse files
Charles ZhangSpace Team
authored andcommitted
[Wasm]: Make the Wasm backend also generate NothingValueException.
In commit 00f6197, the test in compiler/testData/codegen/box/nothingValue/nothingValueException.kt was muted for the WebAssembly backend. This commit fixes the issue and re-enables the test. Merge-request: KT-MR-24551 Merged-by: Charlie Zhang <charles.zhang@jetbrains.com>
1 parent 4b23be4 commit 2074edc

File tree

12 files changed

+41
-16
lines changed

12 files changed

+41
-16
lines changed

compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/KotlinNothingValueExceptionLowering.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ open class KotlinNothingValueExceptionLowering(
4242
// Replace call 'foo' of type 'kotlin.Nothing' with a block:
4343
//
4444
// {
45-
// [ call 'foo' with type: 'kotlin.Unit' ]
45+
// [ call 'foo' with type: 'kotlin.Nothing' ]
4646
// call ThrowKotlinNothingValueException(): Nothing
4747
// }: Nothing
4848
//

compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ private val lateinitPhase = makeIrModulePhase(
9696
name = "LateinitLowering",
9797
)
9898

99+
private val kotlinNothingValueExceptionPhase = makeIrModulePhase(
100+
::KotlinNothingValueExceptionLowering,
101+
name = "KotlinNothingValueException",
102+
)
103+
99104
private val rangeContainsLoweringPhase = makeIrModulePhase(
100105
::RangeContainsLowering,
101106
name = "RangeContainsLowering",
@@ -680,6 +685,12 @@ fun getWasmLowerings(
680685
addContinuationToFunctionCallsLoweringPhase,
681686
generateMainFunctionWrappersPhase,
682687

688+
// We need to generate nothing value exceptions after suspend
689+
// functions have been lowered so that suspend functions
690+
// declared to return nothing get a chance to get lowered
691+
// without the exception being inserted.
692+
kotlinNothingValueExceptionPhase,
693+
683694
invokeOnExportedFunctionExitLowering,
684695

685696
tryCatchCanonicalization,

compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,7 @@ class WasmSymbols(
7474
val throwTypeCastWithInfoException = CallableIds.THROW_CCE_WITH_INFO.functionSymbol()
7575
override val throwIAE = CallableIds.THROW_IAE.functionSymbol()
7676
val throwNoBranchMatchedException = CallableIds.throwNoBranchMatchedException.functionSymbol()
77-
override val throwKotlinNothingValueException: IrSimpleFunctionSymbol
78-
get() = TODO()
77+
override val throwKotlinNothingValueException = CallableIds.throwKotlinNothingValueException.functionSymbol()
7978
override val stringBuilder = ClassIds.StringBuilder.classSymbol()
8079
override val getContinuation = CallableIds.getContinuation.functionSymbol()
8180
override val returnIfSuspended = CallableIds.returnIfSuspended.functionSymbol()
@@ -409,6 +408,7 @@ private object CallableIds {
409408
val THROW_CCE_WITH_INFO = "THROW_CCE_WITH_INFO".wasmCallableId
410409
val THROW_IAE = "THROW_IAE".wasmCallableId
411410
val throwNoBranchMatchedException = "throwNoBranchMatchedException".wasmCallableId
411+
val throwKotlinNothingValueException = "throwKotlinNothingValueException".wasmCallableId
412412
val getContinuation = "getContinuation".wasmCallableId
413413
val returnIfSuspended = "returnIfSuspended".wasmCallableId
414414
val enumValueOfIntrinsic = "enumValueOfIntrinsic".wasmCallableId

compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.ir.util.isNullable
2727
import org.jetbrains.kotlin.ir.util.isSubtypeOfClass
2828
import org.jetbrains.kotlin.ir.visitors.IrVisitorVoid
2929
import org.jetbrains.kotlin.ir.visitors.acceptVoid
30+
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
3031
import org.jetbrains.kotlin.wasm.config.WasmConfigurationKeys
3132
import org.jetbrains.kotlin.wasm.ir.*
3233
import org.jetbrains.kotlin.wasm.ir.source.location.SourceLocation
@@ -65,7 +66,19 @@ class BodyGenerator(
6566
internal fun generateExpression(expression: IrExpression) {
6667
expression.acceptVoid(this)
6768

68-
if (expression.type.isNothing()) {
69+
// Checks if it is safe to assume the statement doesn't return
70+
// (e.g. throws an exception or loops infinitely)
71+
//
72+
// Takes into account cases like `fun <T> foo(): T = Any() as
73+
// T`, which could be used as `foo<Nothing>()` and terminate
74+
// despite the call type `Nothing`.
75+
//
76+
// Assumes that only functions with explicit return type
77+
// `Nothing` do not return.
78+
//
79+
// Also see KotlinNothingValueExceptionLowering.kt
80+
if (expression.type.isNothing() &&
81+
!(expression is IrCall && !expression.symbol.owner.returnType.isNothing())) {
6982
// TODO Ideally, we should generate unreachable only for specific cases and preferable on declaration site.
7083
body.buildUnreachableAfterNothingType()
7184
}
@@ -74,7 +87,7 @@ class BodyGenerator(
7487
// Generates code for the given IR element but *never* leaves anything on the stack.
7588
private fun generateAsStatement(statement: IrExpression) {
7689
generateExpression(statement)
77-
if (statement.type != wasmSymbols.voidType) {
90+
if (statement.type != wasmSymbols.voidType && !statement.type.isNothing()) {
7891
body.buildDrop(SourceLocation.NoLocation("DROP"))
7992
}
8093
}

compiler/testData/codegen/box/nothingValue/nothingValueException.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
// IGNORE_BACKEND: WASM_JS, WASM_WASI
2-
// WASM_MUTE_REASON: REFLECTION
3-
41
fun <T> something(): T = Any() as T
52

63
class Context<T>

compiler/testData/codegen/box/size/add.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// TARGET_BACKEND: WASM_JS
22

33
// RUN_THIRD_PARTY_OPTIMIZER
4-
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 55_229
4+
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 55_926
55
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 5_940
66
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 76
77

compiler/testData/codegen/box/size/helloWorld.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// TARGET_BACKEND: WASM
22

33
// RUN_THIRD_PARTY_OPTIMIZER
4-
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 55_530
4+
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 56_266
55
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 5_871
66
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 3_911
77

compiler/testData/codegen/box/size/helloWorldPromise.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// TARGET_BACKEND: WASM_JS
22

33
// RUN_THIRD_PARTY_OPTIMIZER
4-
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 55_635
4+
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 56_329
55
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 6_103
66
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 4_131
77

compiler/testData/codegen/box/size/objectsOptimization.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// TARGET_BACKEND: WASM
22

33
// RUN_THIRD_PARTY_OPTIMIZER
4-
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 60_209
4+
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 60_909
55
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 5_806
66
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 4_822
77

@@ -68,4 +68,4 @@ fun box(): String {
6868
if (ClassWithCompanionWithConst.MAX != 5) return "Fail simple companion object with const val"
6969
SimpleWithDifferentMembers
7070
return "OK"
71-
}
71+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
// TARGET_BACKEND: WASM
22

33
// RUN_THIRD_PARTY_OPTIMIZER
4-
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 55_280
4+
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 55_977
55
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 5_806
66
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 3_849
77

88
// IGNORE_BACKEND: WASM_WASI
99

10-
fun box() = "OK"
10+
fun box() = "OK"

0 commit comments

Comments
 (0)