JVM_IR: give loops somewhat more debuggable labels

This commit is contained in:
pyos
2021-01-05 12:19:20 +01:00
committed by max-kammerer
parent ad53fc931e
commit bd3bc13e75
4 changed files with 58 additions and 58 deletions
@@ -394,7 +394,7 @@ val jvmPhases = NamedCompilerPhase(
generateMultifileFacadesPhase then
resolveInlineCallsPhase then
// should be last transformation
removeDeclarationsThatWouldBeInlined then
prepareForBytecodeInlining then
validateIrAfterLowering
)
@@ -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"}"
@@ -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)
}
}
}
@@ -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)
}
}
})
}
}