JVM_IR: give loops somewhat more debuggable labels
This commit is contained in:
@@ -394,7 +394,7 @@ val jvmPhases = NamedCompilerPhase(
|
|||||||
generateMultifileFacadesPhase then
|
generateMultifileFacadesPhase then
|
||||||
resolveInlineCallsPhase then
|
resolveInlineCallsPhase then
|
||||||
// should be last transformation
|
// should be last transformation
|
||||||
removeDeclarationsThatWouldBeInlined then
|
prepareForBytecodeInlining then
|
||||||
validateIrAfterLowering
|
validateIrAfterLowering
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -167,5 +167,4 @@ private tailrec fun IrDeclaration.isInlineOrInsideInline(): Boolean {
|
|||||||
return parent.isInlineOrInsideInline()
|
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 = "${label!!}\$${if (forBreak) "break" else "continue"}"
|
||||||
internal fun IrLoop.nonLocalReturnLabel(forBreak: Boolean): String = "$this\$${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