From ba7f5afebe53e3f8d5eadc7df2e879b2f341a71d Mon Sep 17 00:00:00 2001 From: Sergej Jaskiewicz Date: Mon, 31 Oct 2022 15:36:53 +0100 Subject: [PATCH] [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 --- .../js/lower/MultipleCatchesLowering.kt | 63 ++++++++++--------- .../testData/debug/stepping/throwException.kt | 3 +- compiler/testData/debug/stepping/tryCatch.kt | 3 +- .../testData/lineNumbers/catch.kt | 4 +- .../testData/lineNumbers/delegation.kt | 2 +- .../lastExpressionInInlineLambda.kt | 4 +- 6 files changed, 44 insertions(+), 35 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MultipleCatchesLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MultipleCatchesLowering.kt index bdce3f4c724..2f737d98949 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MultipleCatchesLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MultipleCatchesLowering.kt @@ -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 { - 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) } diff --git a/compiler/testData/debug/stepping/throwException.kt b/compiler/testData/debug/stepping/throwException.kt index de63e180f49..8c01a89366f 100644 --- a/compiler/testData/debug/stepping/throwException.kt +++ b/compiler/testData/debug/stepping/throwException.kt @@ -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 \ No newline at end of file +// test.kt:15 throwIfLess diff --git a/compiler/testData/debug/stepping/tryCatch.kt b/compiler/testData/debug/stepping/tryCatch.kt index 6c22d36337a..661d04ddd6b 100644 --- a/compiler/testData/debug/stepping/tryCatch.kt +++ b/compiler/testData/debug/stepping/tryCatch.kt @@ -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 \ No newline at end of file +// test.kt:15 box diff --git a/js/js.translator/testData/lineNumbers/catch.kt b/js/js.translator/testData/lineNumbers/catch.kt index 1cd127cc74b..aa8d367f972 100644 --- a/js/js.translator/testData/lineNumbers/catch.kt +++ b/js/js.translator/testData/lineNumbers/catch.kt @@ -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 diff --git a/js/js.translator/testData/lineNumbers/delegation.kt b/js/js.translator/testData/lineNumbers/delegation.kt index b0fa583d90d..0dd62f08991 100644 --- a/js/js.translator/testData/lineNumbers/delegation.kt +++ b/js/js.translator/testData/lineNumbers/delegation.kt @@ -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 diff --git a/js/js.translator/testData/lineNumbers/lastExpressionInInlineLambda.kt b/js/js.translator/testData/lineNumbers/lastExpressionInInlineLambda.kt index ed2218a7b39..ff9b09ba9de 100644 --- a/js/js.translator/testData/lineNumbers/lastExpressionInInlineLambda.kt +++ b/js/js.translator/testData/lineNumbers/lastExpressionInInlineLambda.kt @@ -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