JVM_IR: give loops somewhat more debuggable labels
This commit is contained in:
@@ -394,7 +394,7 @@ val jvmPhases = NamedCompilerPhase(
|
||||
generateMultifileFacadesPhase then
|
||||
resolveInlineCallsPhase then
|
||||
// should be last transformation
|
||||
removeDeclarationsThatWouldBeInlined then
|
||||
prepareForBytecodeInlining then
|
||||
validateIrAfterLowering
|
||||
)
|
||||
|
||||
|
||||
+1
-2
@@ -167,5 +167,4 @@ private tailrec fun IrDeclaration.isInlineOrInsideInline(): Boolean {
|
||||
return parent.isInlineOrInsideInline()
|
||||
}
|
||||
|
||||
// TODO generate better labels; this is unique (includes the object's address), but not very descriptive
|
||||
internal fun IrLoop.nonLocalReturnLabel(forBreak: Boolean): String = "$this\$${if (forBreak) "break" else "continue"}"
|
||||
internal fun IrLoop.nonLocalReturnLabel(forBreak: Boolean): String = "${label!!}\$${if (forBreak) "break" else "continue"}"
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrModulePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
|
||||
internal val prepareForBytecodeInlining = makeIrModulePhase(
|
||||
::BytecodeInliningPreparationLowering,
|
||||
name = "BytecodeInliningPreparation",
|
||||
description = "Remove inline lambda declarations and label all loops"
|
||||
)
|
||||
|
||||
private class BytecodeInliningPreparationLowering(val context: JvmBackendContext) : FileLoweringPass {
|
||||
override fun lower(irFile: IrFile) {
|
||||
val loweredLambdasToDelete = mutableSetOf<IrFunction>()
|
||||
irFile.accept(object : IrElementVisitor<Unit, String> {
|
||||
// This counter is intentionally not local to every declaration because their names might clash.
|
||||
private var counter = 0
|
||||
|
||||
override fun visitElement(element: IrElement, data: String) =
|
||||
element.acceptChildren(this, if (element is IrDeclarationWithName) "$data${element.name}$" else data)
|
||||
|
||||
override fun visitLoop(loop: IrLoop, data: String) {
|
||||
// Give all loops unique labels so that we can generate unambiguous instructions for non-local
|
||||
// `break`/`continue` statements.
|
||||
loop.label = "$data${++counter}"
|
||||
super.visitLoop(loop, data)
|
||||
}
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference, data: String) {
|
||||
// Remove inline lambdas from their declaration parents. They should not appear in the output
|
||||
// bytecode in non-inlined form.
|
||||
if (expression.origin.isInlineIrExpression()) {
|
||||
loweredLambdasToDelete.add(expression.symbol.owner)
|
||||
}
|
||||
super.visitFunctionReference(expression, data)
|
||||
}
|
||||
}, "")
|
||||
|
||||
for (irClass in loweredLambdasToDelete.mapTo(mutableSetOf()) { it.parentAsClass }) {
|
||||
irClass.declarations.removeAll(loweredLambdasToDelete)
|
||||
}
|
||||
}
|
||||
}
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrModulePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
|
||||
internal val removeDeclarationsThatWouldBeInlined = makeIrModulePhase(
|
||||
::RemoveDeclarationsThatWouldBeInlinedLowering,
|
||||
name = "RemoveInlinedDeclarations",
|
||||
description = "Rename declaration that should be inlined"
|
||||
)
|
||||
|
||||
// Removes all functions which are only used as arguments to inline functions. It's
|
||||
// important that this phase runs right before codegen, since we need the bodies of lambdas to
|
||||
// be lowered for inline codegen. Conversely, since this phase runs right before codegen we can
|
||||
// assume that all remaining function references are only used as arguments to inline functions -
|
||||
// otherwise they would have been lowered.
|
||||
private class RemoveDeclarationsThatWouldBeInlinedLowering(val context: JvmBackendContext) : FileLoweringPass {
|
||||
override fun lower(irFile: IrFile) {
|
||||
val loweredLambdasToDelete = mutableSetOf<IrFunction>()
|
||||
|
||||
irFile.acceptVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) = element.acceptChildrenVoid(this)
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference) {
|
||||
if (expression.origin.isInlineIrExpression()) {
|
||||
loweredLambdasToDelete.add(expression.symbol.owner)
|
||||
}
|
||||
|
||||
expression.acceptChildrenVoid(this)
|
||||
}
|
||||
})
|
||||
|
||||
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
return super.visitClass(declaration).also {
|
||||
declaration.declarations.removeAll(loweredLambdasToDelete)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user