IR: remove IrElementVisitorVoidWithContext
It was only used as a superclass in IrInlineReferenceLocator and LocalDeclarationsLowering. In both cases it's clearer and more optimal to pass the necessary data via the visitor 'data' variable.
This commit is contained in:
+4
-97
@@ -21,9 +21,11 @@ import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.builders.Scope
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
|
||||
open class ScopeWithIr(val scope: Scope, val irElement: IrElement)
|
||||
|
||||
@@ -139,98 +141,3 @@ abstract class IrElementTransformerVoidWithContext : IrElementTransformerVoid()
|
||||
return super.visitScript(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
abstract class IrElementVisitorVoidWithContext : IrElementVisitorVoid {
|
||||
|
||||
private val scopeStack = mutableListOf<ScopeWithIr>()
|
||||
|
||||
protected open fun createScope(declaration: IrSymbolOwner): ScopeWithIr =
|
||||
ScopeWithIr(Scope(declaration.symbol), declaration)
|
||||
|
||||
final override fun visitFile(declaration: IrFile) {
|
||||
scopeStack.push(createScope(declaration))
|
||||
visitFileNew(declaration)
|
||||
scopeStack.pop()
|
||||
}
|
||||
|
||||
final override fun visitClass(declaration: IrClass) {
|
||||
scopeStack.push(createScope(declaration))
|
||||
visitClassNew(declaration)
|
||||
scopeStack.pop()
|
||||
}
|
||||
|
||||
final override fun visitProperty(declaration: IrProperty) {
|
||||
scopeStack.push(createScope(declaration))
|
||||
visitPropertyNew(declaration)
|
||||
scopeStack.pop()
|
||||
}
|
||||
|
||||
final override fun visitField(declaration: IrField) {
|
||||
val isDelegated = declaration.descriptor.isDelegated
|
||||
if (isDelegated) scopeStack.push(createScope(declaration))
|
||||
visitFieldNew(declaration)
|
||||
if (isDelegated) scopeStack.pop()
|
||||
}
|
||||
|
||||
final override fun visitFunction(declaration: IrFunction) {
|
||||
scopeStack.push(createScope(declaration))
|
||||
visitFunctionNew(declaration)
|
||||
scopeStack.pop()
|
||||
}
|
||||
|
||||
final override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer) {
|
||||
scopeStack.push(createScope(declaration))
|
||||
visitAnonymousInitializerNew(declaration)
|
||||
scopeStack.pop()
|
||||
}
|
||||
|
||||
final override fun visitValueParameter(declaration: IrValueParameter) {
|
||||
scopeStack.push(createScope(declaration))
|
||||
visitValueParameterNew(declaration)
|
||||
scopeStack.pop()
|
||||
}
|
||||
|
||||
protected val currentFile get() = scopeStack.lastOrNull { it.scope.scopeOwnerSymbol is IrFileSymbol }
|
||||
protected val currentClass get() = scopeStack.lastOrNull { it.scope.scopeOwnerSymbol is IrClassSymbol }
|
||||
protected val currentFunction get() = scopeStack.lastOrNull { it.scope.scopeOwnerSymbol is IrFunctionSymbol }
|
||||
protected val currentProperty get() = scopeStack.lastOrNull { it.scope.scopeOwnerSymbol is IrPropertySymbol }
|
||||
protected val currentAnonymousInitializer get() = scopeStack.lastOrNull { it.scope.scopeOwnerSymbol is IrAnonymousInitializer }
|
||||
protected val currentValueParameter get() = scopeStack.lastOrNull { it.scope.scopeOwnerSymbol is IrValueParameter }
|
||||
protected val currentScope get() = scopeStack.peek()
|
||||
protected val parentScope get() = if (scopeStack.size < 2) null else scopeStack[scopeStack.size - 2]
|
||||
protected val allScopes get() = scopeStack
|
||||
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
fun printScopeStack() {
|
||||
scopeStack.forEach { println(it.scope.scopeOwner) }
|
||||
}
|
||||
|
||||
open fun visitFileNew(declaration: IrFile) {
|
||||
super.visitFile(declaration)
|
||||
}
|
||||
|
||||
open fun visitClassNew(declaration: IrClass) {
|
||||
super.visitClass(declaration)
|
||||
}
|
||||
|
||||
open fun visitFunctionNew(declaration: IrFunction) {
|
||||
super.visitFunction(declaration)
|
||||
}
|
||||
|
||||
open fun visitPropertyNew(declaration: IrProperty) {
|
||||
super.visitProperty(declaration)
|
||||
}
|
||||
|
||||
open fun visitFieldNew(declaration: IrField) {
|
||||
super.visitField(declaration)
|
||||
}
|
||||
|
||||
open fun visitAnonymousInitializerNew(declaration: IrAnonymousInitializer) {
|
||||
super.visitAnonymousInitializer(declaration)
|
||||
}
|
||||
|
||||
open fun visitValueParameterNew(declaration: IrValueParameter) {
|
||||
super.visitValueParameter(declaration)
|
||||
}
|
||||
}
|
||||
+38
-34
@@ -5,15 +5,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedString
|
||||
import org.jetbrains.kotlin.backend.common.ir.*
|
||||
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.ir.*
|
||||
import org.jetbrains.kotlin.ir.builders.Scope
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildField
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||
@@ -33,8 +34,7 @@ import org.jetbrains.kotlin.ir.util.file
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
@@ -109,7 +109,7 @@ class LocalDeclarationsLowering(
|
||||
LocalDeclarationsTransformer(irElement, container, classesToLower).lowerLocalDeclarations()
|
||||
}
|
||||
|
||||
internal class ScopeWithCounter(scope: Scope, irElement: IrElement) : ScopeWithIr(scope, irElement) {
|
||||
internal class ScopeWithCounter(val irElement: IrElement) {
|
||||
// Continuous numbering across all declarations in the container.
|
||||
var counter: Int = 0
|
||||
val usedLocalFunctionNames: MutableSet<Name> = hashSetOf()
|
||||
@@ -122,7 +122,7 @@ class LocalDeclarationsLowering(
|
||||
// Need to keep LocalFunctionContext.index
|
||||
private val IrSymbolOwner.scopeWithCounter: ScopeWithCounter
|
||||
get() = context.ir.localScopeWithCounterMap.scopeMap.getOrPut(this) {
|
||||
ScopeWithCounter(Scope(symbol), this)
|
||||
ScopeWithCounter(this)
|
||||
}
|
||||
|
||||
private abstract class LocalContext {
|
||||
@@ -857,66 +857,70 @@ class LocalDeclarationsLowering(
|
||||
currentParent as? IrClass
|
||||
}
|
||||
|
||||
irElement.acceptVoid(object : IrElementVisitorVoidWithContext() {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
class Data(val currentClass: ScopeWithCounter?, val isInInlineFunction: Boolean) {
|
||||
fun withCurrentClass(currentClass: IrClass): Data =
|
||||
// Don't cache local declarations
|
||||
Data(ScopeWithCounter(currentClass), isInInlineFunction)
|
||||
|
||||
fun withInline(isInline: Boolean): Data =
|
||||
if (isInline && !isInInlineFunction) Data(currentClass, true) else this
|
||||
}
|
||||
|
||||
irElement.accept(object : IrElementVisitor<Unit, Data> {
|
||||
override fun visitElement(element: IrElement, data: Data) {
|
||||
element.acceptChildren(this, data)
|
||||
}
|
||||
|
||||
override fun createScope(declaration: IrSymbolOwner): ScopeWithIr {
|
||||
return ScopeWithCounter(Scope(declaration.symbol), declaration) // Don't cache local declarations
|
||||
}
|
||||
|
||||
override fun visitFunctionExpression(expression: IrFunctionExpression) {
|
||||
override fun visitFunctionExpression(expression: IrFunctionExpression, data: Data) {
|
||||
// TODO: For now IrFunctionExpression can only be encountered here if this was called from the inliner,
|
||||
// then all IrFunctionExpression will be replaced by IrFunctionReferenceExpression.
|
||||
// Don't forget to fix this when that replacement has been dropped.
|
||||
// Also, a note: even if a lambda is not an inline one, there still cannot be a reference to it
|
||||
// from an outside declaration, so it is safe to skip them here and correctly handle later, after the above conversion.
|
||||
expression.function.acceptChildrenVoid(this)
|
||||
expression.function.acceptChildren(this, data)
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
|
||||
super.visitSimpleFunction(declaration)
|
||||
override fun visitSimpleFunction(declaration: IrSimpleFunction, data: Data) {
|
||||
super.visitSimpleFunction(declaration, data.withInline(declaration.isInline))
|
||||
|
||||
if (declaration.visibility == Visibilities.LOCAL) {
|
||||
val enclosingScope =
|
||||
val enclosingScope = data.currentClass
|
||||
?: enclosingClass?.scopeWithCounter
|
||||
// File is required for K/N because file declarations are not split by classes.
|
||||
currentClass ?: enclosingClass?.scopeWithCounter ?: enclosingFile.scopeWithCounter
|
||||
?: enclosingFile.scopeWithCounter
|
||||
val index =
|
||||
if (enclosingScope is ScopeWithCounter &&
|
||||
(declaration.name.isSpecial || declaration.name in enclosingScope.usedLocalFunctionNames)
|
||||
) enclosingScope.counter++ else -1
|
||||
if (declaration.name.isSpecial || declaration.name in enclosingScope.usedLocalFunctionNames)
|
||||
enclosingScope.counter++
|
||||
else -1
|
||||
localFunctions[declaration] =
|
||||
LocalFunctionContext(declaration, index, enclosingScope.irElement as IrDeclarationContainer)
|
||||
(enclosingScope as? ScopeWithCounter)?.usedLocalFunctionNames?.add(declaration.name)
|
||||
enclosingScope.usedLocalFunctionNames.add(declaration.name)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor) {
|
||||
super.visitConstructor(declaration)
|
||||
override fun visitConstructor(declaration: IrConstructor, data: Data) {
|
||||
super.visitConstructor(declaration, data)
|
||||
|
||||
if (!declaration.constructedClass.isLocalNotInner()) return
|
||||
|
||||
localClassConstructors[declaration] = LocalClassConstructorContext(declaration, inInlineFunctionScope)
|
||||
localClassConstructors[declaration] = LocalClassConstructorContext(declaration, data.inInlineFunctionScope)
|
||||
}
|
||||
|
||||
override fun visitClassNew(declaration: IrClass) {
|
||||
override fun visitClass(declaration: IrClass, data: Data) {
|
||||
if (classesToLower?.contains(declaration) == false) return
|
||||
super.visitClassNew(declaration)
|
||||
super.visitClass(declaration, data.withCurrentClass(declaration))
|
||||
|
||||
if (!declaration.isLocalNotInner()) return
|
||||
|
||||
val localClassContext = LocalClassContext(declaration, inInlineFunctionScope)
|
||||
localClasses[declaration] = localClassContext
|
||||
localClasses[declaration] = LocalClassContext(declaration, data.inInlineFunctionScope)
|
||||
}
|
||||
|
||||
private val inInlineFunctionScope: Boolean
|
||||
get() = allScopes.any { scope -> (scope.irElement as? IrFunction)?.isInline ?: false } ||
|
||||
private val Data.inInlineFunctionScope: Boolean
|
||||
get() = isInInlineFunction ||
|
||||
generateSequence(container) { it.parent as? IrDeclaration }.any { it is IrFunction && it.isInline }
|
||||
})
|
||||
}, Data(null, false))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Local inner classes capture anything through outer
|
||||
|
||||
+13
-7
@@ -5,25 +5,31 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.IrElementVisitorVoidWithContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineFunctionCall
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression
|
||||
import org.jetbrains.kotlin.ir.util.isLambda
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBlock
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCallableReference
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
|
||||
internal open class IrInlineReferenceLocator(private val context: JvmBackendContext) : IrElementVisitorVoidWithContext() {
|
||||
override fun visitElement(element: IrElement) = element.acceptChildrenVoid(this)
|
||||
internal open class IrInlineReferenceLocator(private val context: JvmBackendContext) : IrElementVisitor<Unit, IrDeclaration?> {
|
||||
override fun visitElement(element: IrElement, data: IrDeclaration?) {
|
||||
element.acceptChildren(this, data)
|
||||
}
|
||||
|
||||
override fun visitFunctionAccess(expression: IrFunctionAccessExpression) {
|
||||
override fun visitDeclaration(declaration: IrDeclarationBase, data: IrDeclaration?) {
|
||||
declaration.acceptChildren(this, declaration)
|
||||
}
|
||||
|
||||
override fun visitFunctionAccess(expression: IrFunctionAccessExpression, data: IrDeclaration?) {
|
||||
val function = expression.symbol.owner
|
||||
if (function.isInlineFunctionCall(context)) {
|
||||
for (parameter in function.valueParameters) {
|
||||
@@ -36,13 +42,13 @@ internal open class IrInlineReferenceLocator(private val context: JvmBackendCont
|
||||
|
||||
if (valueArgument is IrBlock && valueArgument.origin.isLambda) {
|
||||
val reference = valueArgument.statements.last() as IrFunctionReference
|
||||
visitInlineLambda(reference, function, parameter, currentScope!!.irElement as IrDeclaration)
|
||||
visitInlineLambda(reference, function, parameter, data!!)
|
||||
} else if (valueArgument is IrCallableReference<*>) {
|
||||
visitInlineReference(valueArgument)
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.visitFunctionAccess(expression)
|
||||
return super.visitFunctionAccess(expression, data)
|
||||
}
|
||||
|
||||
open fun visitInlineReference(argument: IrCallableReference<*>) {}
|
||||
|
||||
+4
-5
@@ -41,7 +41,6 @@ import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -96,13 +95,13 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
private fun transformSuspendLambdasIntoContinuations(irFile: IrFile) {
|
||||
val inlineReferences = mutableSetOf<IrCallableReference<*>>()
|
||||
val suspendLambdas = mutableMapOf<IrFunctionReference, SuspendLambdaInfo>()
|
||||
irFile.acceptChildrenVoid(object : IrInlineReferenceLocator(context) {
|
||||
irFile.acceptChildren(object : IrInlineReferenceLocator(context) {
|
||||
override fun visitInlineReference(argument: IrCallableReference<*>) {
|
||||
inlineReferences.add(argument)
|
||||
}
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference) {
|
||||
expression.acceptChildrenVoid(this)
|
||||
override fun visitFunctionReference(expression: IrFunctionReference, data: IrDeclaration?) {
|
||||
expression.acceptChildren(this, data)
|
||||
if (expression.isSuspend && expression.shouldBeTreatedAsSuspendLambda() && expression !in inlineReferences) {
|
||||
val isRestricted = expression.symbol.owner.extensionReceiverParameter?.type?.classOrNull?.owner?.annotations?.any {
|
||||
it.type.classOrNull?.signature == IdSignature.PublicSignature("kotlin.coroutines", "RestrictsSuspension", null, 0)
|
||||
@@ -115,7 +114,7 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
origin == IrStatementOrigin.LAMBDA ||
|
||||
origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE ||
|
||||
origin == IrStatementOrigin.SUSPEND_CONVERSION
|
||||
})
|
||||
}, null)
|
||||
|
||||
for (lambda in suspendLambdas.values) {
|
||||
(lambda.function.parent as IrDeclarationContainer).declarations.remove(lambda.function)
|
||||
|
||||
+3
-5
@@ -19,8 +19,6 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
|
||||
internal val fakeInliningLocalVariablesLowering = makeIrFilePhase(
|
||||
@@ -31,11 +29,11 @@ internal val fakeInliningLocalVariablesLowering = makeIrFilePhase(
|
||||
|
||||
internal class FakeInliningLocalVariablesLowering(val context: JvmBackendContext) : IrInlineReferenceLocator(context), FileLoweringPass {
|
||||
override fun lower(irFile: IrFile) {
|
||||
irFile.acceptVoid(this)
|
||||
irFile.accept(this, null)
|
||||
}
|
||||
|
||||
override fun visitFunctionNew(declaration: IrFunction) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
override fun visitFunction(declaration: IrFunction, data: IrDeclaration?) {
|
||||
super.visitFunction(declaration, data)
|
||||
if (declaration.isInline && !declaration.origin.isSynthetic && declaration.body != null) {
|
||||
declaration.addFakeInliningLocalVariables()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user