Implement fake vars generation for functions inlined with IR inliner
This commit is contained in:
@@ -407,6 +407,7 @@ private val jvmFilePhases = listOf(
|
|||||||
|
|
||||||
renameFieldsPhase,
|
renameFieldsPhase,
|
||||||
fakeInliningLocalVariablesLowering,
|
fakeInliningLocalVariablesLowering,
|
||||||
|
fakeInliningLocalVariablesAfterInlineLowering,
|
||||||
|
|
||||||
// makePatchParentsPhase()
|
// makePatchParentsPhase()
|
||||||
)
|
)
|
||||||
|
|||||||
+118
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.ir.*
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
|
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.ir.isInlineOnly
|
||||||
|
import org.jetbrains.kotlin.codegen.inline.INLINE_FUN_VAR_SUFFIX
|
||||||
|
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.builders.createTmpVariable
|
||||||
|
import org.jetbrains.kotlin.ir.builders.irInt
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrBlock
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrInlinedFunctionBlock
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
|
|
||||||
|
internal val fakeInliningLocalVariablesAfterInlineLowering = makeIrFilePhase(
|
||||||
|
::FakeInliningLocalVariablesAfterInlineLowering,
|
||||||
|
name = "FakeInliningLocalVariablesAfterInlineLowering",
|
||||||
|
description = """Add fake locals to identify the range of inlined functions and lambdas.
|
||||||
|
|This lowering adds fake locals into already inlined blocks.""".trimMargin()
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO extract common code with FakeInliningLocalVariablesLowering
|
||||||
|
internal class FakeInliningLocalVariablesAfterInlineLowering(val context: JvmBackendContext) : IrElementVisitor<Unit, IrDeclaration?>, FileLoweringPass {
|
||||||
|
private val inlinedStack = mutableListOf<IrInlinedFunctionBlock>()
|
||||||
|
|
||||||
|
override fun lower(irFile: IrFile) {
|
||||||
|
irFile.accept(this, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitElement(element: IrElement, data: IrDeclaration?) {
|
||||||
|
val newData = if (element is IrDeclaration && element !is IrVariable) element else data
|
||||||
|
element.acceptChildren(this, newData)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitBlock(expression: IrBlock, data: IrDeclaration?) {
|
||||||
|
when {
|
||||||
|
expression is IrInlinedFunctionBlock && expression.isFunctionInlining() -> handleInlineFunction(expression, data)
|
||||||
|
expression is IrInlinedFunctionBlock && expression.isLambdaInlining() -> handleInlineLambda(expression, data)
|
||||||
|
else -> super.visitBlock(expression, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleInlineFunction(expression: IrInlinedFunctionBlock, data: IrDeclaration?) {
|
||||||
|
val declaration = expression.inlineDeclaration
|
||||||
|
|
||||||
|
inlinedStack += expression
|
||||||
|
super.visitBlock(expression, data)
|
||||||
|
inlinedStack.removeLast()
|
||||||
|
|
||||||
|
if (declaration is IrFunction && declaration.isInline && !declaration.origin.isSynthetic && declaration.body != null && !declaration.isInlineOnly()) {
|
||||||
|
val currentFunctionName = context.defaultMethodSignatureMapper.mapFunctionName(declaration)
|
||||||
|
val localName = "${JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION}$currentFunctionName"
|
||||||
|
//declaration.addFakeLocalVariable(localName)
|
||||||
|
with(context.createIrBuilder(data!!.symbol)) {
|
||||||
|
val tmpVar =
|
||||||
|
scope.createTmpVariable(irInt(0), localName.removeSuffix(FOR_INLINE_SUFFIX), origin = IrDeclarationOrigin.DEFINED)
|
||||||
|
// TODO maybe add in front of inline block
|
||||||
|
expression.putStatementsInFrontOfInlinedFunction(listOf(tmpVar))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expression.processLocalDeclarations()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
|
private fun handleInlineLambda(expression: IrInlinedFunctionBlock, data: IrDeclaration?) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrInlinedFunctionBlock.processLocalDeclarations() {
|
||||||
|
this.getAdditionalStatementsFromInlinedBlock().forEach {
|
||||||
|
if (it is IrVariable && it.origin == IrDeclarationOrigin.IR_TEMPORARY_VARIABLE) {
|
||||||
|
val varName = it.name.asString().substringAfterLast("_")
|
||||||
|
it.name = Name.identifier((if (varName == SpecialNames.THIS.asString()) "this_" else varName) + INLINE_FUN_VAR_SUFFIX)
|
||||||
|
it.origin = IrDeclarationOrigin.DEFINED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getOriginalStatementsFromInlinedBlock().forEach {
|
||||||
|
it.acceptVoid(object : IrElementVisitorVoid {
|
||||||
|
override fun visitElement(element: IrElement) {
|
||||||
|
element.acceptChildrenVoid(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitVariable(declaration: IrVariable) {
|
||||||
|
val varName = declaration.name.asString()
|
||||||
|
declaration.name = when {
|
||||||
|
varName == SpecialNames.THIS.asString() -> {
|
||||||
|
Name.identifier("this_$INLINE_FUN_VAR_SUFFIX")
|
||||||
|
}
|
||||||
|
|
||||||
|
!varName.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION) -> {
|
||||||
|
Name.identifier(varName + INLINE_FUN_VAR_SUFFIX)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> declaration.name
|
||||||
|
}
|
||||||
|
super.visitVariable(declaration)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user