[JS IR] Generate correct source locations in sourcemap for inline declarations
* Keep returnable blocks. * Add a new lowering which simplifies returnable blocks by introducing temporary variable for result and changing returnable block's type to Unit. * Use information from returnable blocks in codegen to generate the right source locations in sourcemap. * Support in namer (LocalNameGenerator). * Fix some lowerings to work correctly with returnable blocks. #KT-46551 In Progress
This commit is contained in:
committed by
teamcityserver
parent
2460f5f9ae
commit
d1f5ab4b09
+3
-2
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
|
|||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.ir.transformStatement
|
import org.jetbrains.kotlin.ir.transformStatement
|
||||||
|
|
||||||
|
// TODO migrate other usages and move this file to backend.jvm
|
||||||
/**
|
/**
|
||||||
* Replaces returnable blocks and `return`'s with loops and `break`'s correspondingly.
|
* Replaces returnable blocks and `return`'s with loops and `break`'s correspondingly.
|
||||||
*
|
*
|
||||||
@@ -149,4 +150,4 @@ class ReturnableBlockTransformer(val context: CommonBackendContext, val containe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -348,9 +348,9 @@ private val callableReferenceLowering = makeBodyLoweringPhase(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private val returnableBlockLoweringPhase = makeBodyLoweringPhase(
|
private val returnableBlockLoweringPhase = makeBodyLoweringPhase(
|
||||||
::ReturnableBlockLowering,
|
::JsReturnableBlockLowering,
|
||||||
name = "ReturnableBlockLowering",
|
name = "JsReturnableBlockLowering",
|
||||||
description = "Replace returnable block with do-while loop",
|
description = "Introduce temporary variable for result and change returnable block's type to Unit",
|
||||||
prerequisite = setOf(functionInliningPhase)
|
prerequisite = setOf(functionInliningPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+95
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
||||||
|
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.at
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.irComposite
|
||||||
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps returnable blocks with returns to composite and replaces returns with assignment to temporary variable + `return Unit`,
|
||||||
|
* also, it changes type of returnable block to Unit.
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* returnable_block {
|
||||||
|
* ...
|
||||||
|
* return@returnable_block e
|
||||||
|
* ...
|
||||||
|
* }: T
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* is transformed into
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* composite {
|
||||||
|
* val result
|
||||||
|
* returnable_block {
|
||||||
|
* ...
|
||||||
|
* result = e
|
||||||
|
* return@returnable_block Unit
|
||||||
|
* ...
|
||||||
|
* }: Unit
|
||||||
|
* result
|
||||||
|
* }: T
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
class JsReturnableBlockLowering(val context: CommonBackendContext) : BodyLoweringPass {
|
||||||
|
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||||
|
container.transform(JsReturnableBlockTransformer(context), null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class JsReturnableBlockTransformer(val context: CommonBackendContext) : IrElementTransformerVoidWithContext() {
|
||||||
|
private var labelCnt = 0
|
||||||
|
private var map = mutableMapOf<IrReturnableBlockSymbol, IrVariable>()
|
||||||
|
|
||||||
|
private val unitType = context.irBuiltIns.unitType
|
||||||
|
private val unitValue get() = IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, unitType, context.irBuiltIns.unitClass)
|
||||||
|
|
||||||
|
override fun visitBlock(expression: IrBlock): IrExpression {
|
||||||
|
if (expression !is IrReturnableBlock) return super.visitBlock(expression)
|
||||||
|
|
||||||
|
expression.transformChildrenVoid()
|
||||||
|
|
||||||
|
val variable = map.remove(expression.symbol) ?: return expression
|
||||||
|
|
||||||
|
val builder = context.createIrBuilder(expression.symbol)
|
||||||
|
|
||||||
|
expression.type = context.irBuiltIns.unitType
|
||||||
|
return builder.irComposite(expression, expression.origin, variable.type) {
|
||||||
|
+variable
|
||||||
|
+expression
|
||||||
|
+irGet(variable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitReturn(expression: IrReturn): IrExpression {
|
||||||
|
expression.transformChildrenVoid()
|
||||||
|
|
||||||
|
val targetSymbol = expression.returnTargetSymbol
|
||||||
|
if (targetSymbol !is IrReturnableBlockSymbol) return expression
|
||||||
|
|
||||||
|
val variable = map.getOrPut(targetSymbol) {
|
||||||
|
currentScope!!.scope.createTmpVariable(targetSymbol.owner.type, "tmp\$ret\$${labelCnt++}", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
val builder = context.createIrBuilder(targetSymbol)
|
||||||
|
return builder.at(UNDEFINED_OFFSET, UNDEFINED_OFFSET).irComposite {
|
||||||
|
+at(expression).irSet(variable.symbol, expression.value)
|
||||||
|
+at(UNDEFINED_OFFSET, UNDEFINED_OFFSET).irReturn(unitValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
-10
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -10,8 +10,8 @@ import org.jetbrains.kotlin.backend.common.DeclarationTransformer
|
|||||||
import org.jetbrains.kotlin.backend.common.getOrPut
|
import org.jetbrains.kotlin.backend.common.getOrPut
|
||||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||||
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
|
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
|||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||||
@@ -130,25 +131,30 @@ class SecondaryConstructorLowering(val context: JsIrBackendContext) : Declaratio
|
|||||||
delegate.body = context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
|
delegate.body = context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
|
||||||
statements += (constructorBody.deepCopyWithSymbols(delegate) as IrStatementContainer).statements
|
statements += (constructorBody.deepCopyWithSymbols(delegate) as IrStatementContainer).statements
|
||||||
statements += JsIrBuilder.buildReturn(delegate.symbol, JsIrBuilder.buildGetValue(thisParam.symbol), context.irBuiltIns.nothingType)
|
statements += JsIrBuilder.buildReturn(delegate.symbol, JsIrBuilder.buildGetValue(thisParam.symbol), context.irBuiltIns.nothingType)
|
||||||
transformChildrenVoid(ThisUsageReplaceTransformer(delegate.symbol, oldValueParameters.zip(delegate.valueParameters).toMap()))
|
transformChildrenVoid(ThisUsageReplaceTransformer(constructor.symbol, delegate.symbol, oldValueParameters.zip(delegate.valueParameters).toMap()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class ThisUsageReplaceTransformer(
|
private class ThisUsageReplaceTransformer(
|
||||||
|
val constructor: IrConstructorSymbol,
|
||||||
val function: IrFunctionSymbol,
|
val function: IrFunctionSymbol,
|
||||||
val symbolMapping: Map<IrValueParameter, IrValueParameter>
|
val symbolMapping: Map<IrValueParameter, IrValueParameter>
|
||||||
) : IrElementTransformerVoid() {
|
) : IrElementTransformerVoid() {
|
||||||
|
|
||||||
val newThisSymbol = symbolMapping.values.last().symbol
|
val newThisSymbol = symbolMapping.values.last().symbol
|
||||||
|
|
||||||
override fun visitReturn(expression: IrReturn): IrExpression = IrReturnImpl(
|
override fun visitReturn(expression: IrReturn): IrExpression =
|
||||||
expression.startOffset,
|
if (expression.returnTargetSymbol != constructor)
|
||||||
expression.endOffset,
|
expression
|
||||||
expression.type,
|
else
|
||||||
function,
|
IrReturnImpl(
|
||||||
IrGetValueImpl(expression.startOffset, expression.endOffset, newThisSymbol.owner.type, newThisSymbol)
|
expression.startOffset,
|
||||||
)
|
expression.endOffset,
|
||||||
|
expression.type,
|
||||||
|
function,
|
||||||
|
IrGetValueImpl(expression.startOffset, expression.endOffset, newThisSymbol.owner.type, newThisSymbol)
|
||||||
|
)
|
||||||
|
|
||||||
override fun visitGetValue(expression: IrGetValue) = symbolMapping[expression.symbol.owner]?.let {
|
override fun visitGetValue(expression: IrGetValue) = symbolMapping[expression.symbol.owner]?.let {
|
||||||
expression.run { IrGetValueImpl(startOffset, endOffset, type, it.symbol, origin) }
|
expression.run { IrGetValueImpl(startOffset, endOffset, type, it.symbol, origin) }
|
||||||
|
|||||||
+8
-3
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -36,7 +36,12 @@ private class BlockRemover : IrElementVisitorVoid {
|
|||||||
|
|
||||||
private fun process(container: IrStatementContainer) {
|
private fun process(container: IrStatementContainer) {
|
||||||
container.statements.transformFlat { statement ->
|
container.statements.transformFlat { statement ->
|
||||||
(statement as? IrStatementContainer)?.statements
|
when (statement) {
|
||||||
|
// returnable blocks required for sourcemaps generation, so keep them
|
||||||
|
is IrReturnableBlock -> null
|
||||||
|
is IrStatementContainer -> statement.statements
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,4 +115,4 @@ private class CodeCleaner : IrElementVisitorVoid {
|
|||||||
super.visitContainerExpression(expression)
|
super.visitContainerExpression(expression)
|
||||||
expression.cleanUpStatements()
|
expression.cleanUpStatements()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-3
@@ -11,8 +11,10 @@ import org.jetbrains.kotlin.ir.backend.js.utils.emptyScope
|
|||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.isAny
|
import org.jetbrains.kotlin.ir.types.isAny
|
||||||
import org.jetbrains.kotlin.ir.util.constructedClassType
|
import org.jetbrains.kotlin.ir.util.constructedClassType
|
||||||
|
import org.jetbrains.kotlin.ir.util.file
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
|
|
||||||
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
|
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
|
||||||
@@ -28,8 +30,19 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
|||||||
return JsBlock(body.statements.map { it.accept(this, context) })
|
return JsBlock(body.statements.map { it.accept(this, context) })
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitBlock(expression: IrBlock, context: JsGenerationContext): JsBlock {
|
override fun visitBlock(expression: IrBlock, context: JsGenerationContext): JsStatement {
|
||||||
return JsBlock(expression.statements.map { it.accept(this, context) })
|
val newContext = (expression as? IrReturnableBlock)?.inlineFunctionSymbol?.let {
|
||||||
|
context.newFile(it.owner.file, context.currentFunction, context.localNames)
|
||||||
|
} ?: context
|
||||||
|
|
||||||
|
val block = JsBlock(expression.statements.map { it.accept(this, newContext) })
|
||||||
|
|
||||||
|
if (expression is IrReturnableBlock) {
|
||||||
|
val label = context.getNameForReturnableBlock(expression)
|
||||||
|
if (label != null) return JsLabel(label, block)
|
||||||
|
}
|
||||||
|
|
||||||
|
return block
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitComposite(expression: IrComposite, context: JsGenerationContext): JsStatement {
|
override fun visitComposite(expression: IrComposite, context: JsGenerationContext): JsStatement {
|
||||||
@@ -72,7 +85,16 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitReturn(expression: IrReturn, context: JsGenerationContext): JsStatement {
|
override fun visitReturn(expression: IrReturn, context: JsGenerationContext): JsStatement {
|
||||||
return expression.value.maybeOptimizeIntoSwitch(context) { JsReturn(it) }.withSource(expression, context)
|
val targetSymbol = expression.returnTargetSymbol
|
||||||
|
val lastStatementTransformer: (JsExpression) -> JsStatement =
|
||||||
|
if (targetSymbol is IrReturnableBlockSymbol) {
|
||||||
|
// TODO assert that value is Unit?
|
||||||
|
{ JsBreak(context.getNameForReturnableBlock(targetSymbol.owner)!!.makeRef()) }
|
||||||
|
} else {
|
||||||
|
{ JsReturn(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
return expression.value.maybeOptimizeIntoSwitch(context, lastStatementTransformer).withSource(expression, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitThrow(expression: IrThrow, context: JsGenerationContext): JsStatement {
|
override fun visitThrow(expression: IrThrow, context: JsGenerationContext): JsStatement {
|
||||||
|
|||||||
+5
@@ -71,6 +71,11 @@ class JsGenerationContext(
|
|||||||
return JsName(name)
|
return JsName(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getNameForReturnableBlock(block: IrReturnableBlock): JsName? {
|
||||||
|
val name = localNames!!.localReturnableBlockNames.names[block] ?: return null
|
||||||
|
return JsName(name)
|
||||||
|
}
|
||||||
|
|
||||||
private fun isCoroutineDoResume(): Boolean {
|
private fun isCoroutineDoResume(): Boolean {
|
||||||
val overriddenSymbols = (currentFunction as? IrSimpleFunction)?.overriddenSymbols ?: return false
|
val overriddenSymbols = (currentFunction as? IrSimpleFunction)?.overriddenSymbols ?: return false
|
||||||
return overriddenSymbols.any {
|
return overriddenSymbols.any {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -10,10 +10,8 @@ import org.jetbrains.kotlin.ir.IrElement
|
|||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr
|
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrBreak
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrWhen
|
|
||||||
import org.jetbrains.kotlin.ir.types.isUnit
|
import org.jetbrains.kotlin.ir.types.isUnit
|
||||||
import org.jetbrains.kotlin.ir.util.file
|
import org.jetbrains.kotlin.ir.util.file
|
||||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||||
@@ -304,6 +302,7 @@ class NameTables(
|
|||||||
class LocalNameGenerator(parentScope: NameScope) : IrElementVisitorVoid {
|
class LocalNameGenerator(parentScope: NameScope) : IrElementVisitorVoid {
|
||||||
val variableNames = NameTable<IrDeclarationWithName>(parentScope)
|
val variableNames = NameTable<IrDeclarationWithName>(parentScope)
|
||||||
val localLoopNames = NameTable<IrLoop>()
|
val localLoopNames = NameTable<IrLoop>()
|
||||||
|
val localReturnableBlockNames = NameTable<IrReturnableBlock>()
|
||||||
|
|
||||||
private val breakableDeque: Deque<IrExpression> = LinkedList()
|
private val breakableDeque: Deque<IrExpression> = LinkedList()
|
||||||
|
|
||||||
@@ -327,6 +326,15 @@ class LocalNameGenerator(parentScope: NameScope) : IrElementVisitorVoid {
|
|||||||
super.visitBreak(jump)
|
super.visitBreak(jump)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitReturn(expression: IrReturn) {
|
||||||
|
val targetSymbol = expression.returnTargetSymbol
|
||||||
|
if (targetSymbol is IrReturnableBlockSymbol) {
|
||||||
|
persistReturnableBlockName(SYNTHETIC_BLOCK_LABEL, targetSymbol.owner)
|
||||||
|
}
|
||||||
|
|
||||||
|
super.visitReturn(expression)
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitWhen(expression: IrWhen) {
|
override fun visitWhen(expression: IrWhen) {
|
||||||
breakableDeque.push(expression)
|
breakableDeque.push(expression)
|
||||||
|
|
||||||
@@ -352,6 +360,10 @@ class LocalNameGenerator(parentScope: NameScope) : IrElementVisitorVoid {
|
|||||||
private fun persistLoopName(label: String, loop: IrLoop) {
|
private fun persistLoopName(label: String, loop: IrLoop) {
|
||||||
localLoopNames.declareFreshName(loop, label)
|
localLoopNames.declareFreshName(loop, label)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun persistReturnableBlockName(label: String, loop: IrReturnableBlock) {
|
||||||
|
localReturnableBlockNames.declareFreshName(loop, label)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -373,3 +385,4 @@ fun sanitizeName(name: String): String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private const val SYNTHETIC_LOOP_LABEL = "\$l\$break"
|
private const val SYNTHETIC_LOOP_LABEL = "\$l\$break"
|
||||||
|
private const val SYNTHETIC_BLOCK_LABEL = "\$l\$block"
|
||||||
|
|||||||
Reference in New Issue
Block a user