[JS IR] Generate debug info for catch parameters

We will need it to generate original names for catch parameters in
sourcemaps.

Also, don't generate redundant debug info for compiler-generated
exception handling control flow operators.

See the doc comment to the MultipleCatchesLowering class

#KT-46276
This commit is contained in:
Sergej Jaskiewicz
2022-10-31 15:36:53 +01:00
committed by Space Team
parent 871d445b4e
commit ba7f5afebe
6 changed files with 44 additions and 35 deletions
@@ -7,17 +7,14 @@ package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrBranchImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCatchImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrElseBranchImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrTryImpl
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.types.IrDynamicType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
@@ -37,10 +34,19 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
* try {}
* catch ($p: dynamic) {
* when ($p) {
* ex is Ex1 -> catch1((Ex1)$p)
* ex is Ex2 -> catch2((Ex2)$p)
* ex is Ex3 -> catch3((Ex3)$p)
* else throw $p [ | catch_dynamic($p) ]
* ex1 is Ex1 -> {
* val ex1 = (Ex1)$p
* catch2(ex1)
* }
* ex1 is Ex2 -> {
* val ex2 = (Ex2)$p
* catch2(ex2)
* }
* ex1 is Ex3 -> {
* val ex3 = (Ex3)$p
* catch3(ex3)
* }
* else throw $p [ | { val exd = $p; catch_dynamic(exd) } ]
* }
* }
* finally {}
@@ -70,31 +76,32 @@ class MultipleCatchesLowering(private val context: JsIrBackendContext) : BodyLow
var isCaughtDynamic = false
for (catch in aTry.catches) {
assert(!catch.catchParameter.isVar) { "caught exception parameter has to be immutable" }
val type = catch.catchParameter.type
val catchParameter = catch.catchParameter
assert(!catchParameter.isVar) { "caught exception parameter has to be immutable" }
val type = catchParameter.type
val castedPendingException = {
if (type !is IrDynamicType)
buildImplicitCast(pendingException(), type)
else
pendingException()
}
catchParameter.initializer = if (type is IrDynamicType)
pendingException()
else
buildImplicitCast(pendingException(), type)
val catchBody = catch.result.transform(object : IrElementTransformer<IrValueSymbol> {
override fun visitGetValue(expression: IrGetValue, data: IrValueSymbol): IrExpression =
if (expression.symbol == data)
castedPendingException()
else
expression
}, catch.catchParameter.symbol)
val useOffsetsFrom = catch.result as? IrBlock ?: catch
val catchBody = IrBlockImpl(
useOffsetsFrom.startOffset,
useOffsetsFrom.endOffset,
catch.result.type,
null,
listOf(catchParameter, catch.result)
)
if (type is IrDynamicType) {
branches += IrElseBranchImpl(catch.startOffset, catch.endOffset, litTrue, catchBody)
branches += IrElseBranchImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, litTrue, catchBody)
isCaughtDynamic = true
break
} else {
val typeCheck = buildIsCheck(pendingException(), type)
branches += IrBranchImpl(catch.startOffset, catch.endOffset, typeCheck, catchBody)
branches += IrBranchImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, typeCheck, catchBody)
}
}
@@ -106,7 +113,7 @@ class MultipleCatchesLowering(private val context: JsIrBackendContext) : BodyLow
val whenStatement = JsIrBuilder.buildWhen(aTry.type, branches)
val newCatch = aTry.run {
IrCatchImpl(catches.first().startOffset, catches.last().endOffset, pendingExceptionDeclaration, whenStatement)
IrCatchImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, pendingExceptionDeclaration, whenStatement)
}
return aTry.run { IrTryImpl(startOffset, endOffset, type, tryResult, listOf(newCatch), finallyExpression) }
+2 -1
View File
@@ -33,6 +33,7 @@ fun throwIfLess(a: Int, b: Int) {
// test.kt:14 throwIfLess
// test.kt:15 throwIfLess
// test.kt:7 box
// test.kt:7 box
// test.kt:8 box
// test.kt:14 throwIfLess
// test.kt:15 throwIfLess
// test.kt:15 throwIfLess
+2 -1
View File
@@ -37,5 +37,6 @@ fun box() {
// test.kt:5 foo
// test.kt:5 foo
// test.kt:6 foo
// test.kt:6 foo
// test.kt:10 foo
// test.kt:15 box
// test.kt:15 box
+2 -2
View File
@@ -19,5 +19,5 @@ fun bar() {
}
}
// LINES(JS): 1 11 3 3 5 5 6 6 8 8 9 9 2 2 * 13 20 15 15 18 18
// LINES(JS_IR): 1 1 3 3 5 5 6 6 8 8 9 9 * 13 13 15 15 17 18 18
// LINES(JS): 1 11 3 3 5 5 6 6 8 8 9 9 2 2 * 13 20 15 15 18 18
// LINES(JS_IR): 1 1 3 3 * 5 5 5 6 6 * 8 8 8 9 9 * 13 13 15 15 17 17 17 18 18
+1 -1
View File
@@ -19,4 +19,4 @@ val o = object : I {
}
// LINES(JS): 1 2 3 2 2 2 2 2 2 2 * 11 12 12 12 15 15 15 16 18 17 17
// LINES(JS_IR): 11 11 * 11 11 * 1 1 3 3 1 1 1 1 1 1 1 1 1 5 11 11 12 12 12 16 17 17 15 15 15 * 11
// LINES(JS_IR): 11 11 * 11 11 * 1 1 3 3 1 1 1 1 1 1 1 1 1 5 11 11 12 12 12 16 17 17 15 15 15 * 1 * 11
@@ -24,5 +24,5 @@ fun baz() = "baz"
fun boo() = "boo"
// LINES(JS): 1 17 9 4 6 6 7 7 3 3 3 * 13 12 13 13 14 19 21 20 20 23 23 23 25 25 25
// LINES(JS_IR): 1 1 * 2 * 20 * 4 6 * 6 7 * 3 20 20 * 11 * 20 * 12 12 12 13 14 20 20 19 19 20 20 23 23 23 23 25 25 25 25
// LINES(JS): 1 17 9 4 6 6 7 7 3 3 3 * 13 12 13 13 14 19 21 20 20 23 23 23 25 25 25
// LINES(JS_IR): 1 1 * 2 * 20 * 4 * 6 6 7 * 3 20 20 * 11 * 20 * 12 12 12 13 14 20 20 19 19 20 20 23 23 23 23 25 25 25 25