[IR] Combine value class lowerings

Signed-off-by: Evgeniy.Zhelenskiy <Evgeniy.Zhelenskiy@jetbrains.com>

#KT-1179
This commit is contained in:
Evgeniy.Zhelenskiy
2022-10-26 06:34:01 +02:00
committed by Space Team
parent 68fb8aa2a1
commit 86809e898a
9 changed files with 444 additions and 108 deletions
@@ -30,7 +30,7 @@ open class ScopeWithIr(val scope: Scope, val irElement: IrElement)
abstract class IrElementTransformerVoidWithContext : IrElementTransformerVoid() { abstract class IrElementTransformerVoidWithContext : IrElementTransformerVoid() {
private val scopeStack = mutableListOf<ScopeWithIr>() protected open val scopeStack = mutableListOf<ScopeWithIr>()
protected open fun createScope(declaration: IrSymbolOwner): ScopeWithIr = protected open fun createScope(declaration: IrSymbolOwner): ScopeWithIr =
ScopeWithIr(Scope(declaration.symbol), declaration) ScopeWithIr(Scope(declaration.symbol), declaration)
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrReturnTargetSymbol import org.jetbrains.kotlin.ir.symbols.IrReturnTargetSymbol
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isNothing import org.jetbrains.kotlin.ir.types.isNothing
import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.ir.types.isUnit
@@ -75,14 +74,14 @@ class FinallyBlocksLowering(val context: CommonBackendContext, private val throw
val jumps = mutableMapOf<HighLevelJump, IrReturnTargetSymbol>() val jumps = mutableMapOf<HighLevelJump, IrReturnTargetSymbol>()
} }
private val scopeStack = mutableListOf<Scope>() private val otherScopeStack = mutableListOf<Scope>()
private inline fun <S: Scope, R> using(scope: S, block: (S) -> R): R { private inline fun <S: Scope, R> using(scope: S, block: (S) -> R): R {
scopeStack.push(scope) otherScopeStack.push(scope)
try { try {
return block(scope) return block(scope)
} finally { } finally {
scopeStack.pop() otherScopeStack.pop()
} }
} }
@@ -155,7 +154,7 @@ class FinallyBlocksLowering(val context: CommonBackendContext, private val throw
endOffset: Int, endOffset: Int,
value: IrExpression value: IrExpression
): IrExpression? { ): IrExpression? {
val tryScopes = scopeStack.reversed() val tryScopes = otherScopeStack.reversed()
.takeWhile { !targetScopePredicate(it) } .takeWhile { !targetScopePredicate(it) }
.filterIsInstance<TryScope>() .filterIsInstance<TryScope>()
.toList() .toList()
@@ -310,8 +310,7 @@ private val jvmFilePhases = listOf(
forLoopsPhase, forLoopsPhase,
collectionStubMethodLowering, collectionStubMethodLowering,
singleAbstractMethodPhase, singleAbstractMethodPhase,
jvmMultiFieldValueClassPhase, jvmValueClassPhase,
jvmInlineClassPhase,
tailrecPhase, tailrecPhase,
// makePatchParentsPhase(), // makePatchParentsPhase(),
@@ -113,7 +113,7 @@ internal val bridgePhase = makeIrFilePhase(
::BridgeLowering, ::BridgeLowering,
name = "Bridge", name = "Bridge",
description = "Generate bridges", description = "Generate bridges",
prerequisite = setOf(jvmInlineClassPhase, jvmMultiFieldValueClassPhase, inheritedDefaultMethodsOnClassesPhase) prerequisite = setOf(jvmValueClassPhase, inheritedDefaultMethodsOnClassesPhase)
) )
internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass, IrElementTransformerVoid() { internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass, IrElementTransformerVoid() {
@@ -5,12 +5,12 @@
package org.jetbrains.kotlin.backend.jvm.lower package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ScopeWithIr
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlockBody import org.jetbrains.kotlin.backend.common.lower.irBlockBody
import org.jetbrains.kotlin.backend.common.lower.loops.forLoopsPhase
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.* import org.jetbrains.kotlin.backend.jvm.*
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
import org.jetbrains.kotlin.backend.jvm.ir.isInlineClassType
import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
@@ -31,28 +31,19 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.JVM_INLINE_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.JVM_INLINE_ANNOTATION_FQ_NAME
val jvmInlineClassPhase = makeIrFilePhase(
::JvmInlineClassLowering,
name = "Inline Classes",
description = "Lower inline classes",
// forLoopsPhase may produce UInt and ULong which are inline classes.
// Standard library replacements are done on the unmangled names for UInt and ULong classes.
// Collection stubs may require mangling by inline class rules.
// SAM wrappers may require mangling for fun interfaces with inline class parameters
prerequisite = setOf(
forLoopsPhase, jvmBuiltInsPhase, collectionStubMethodLowering, singleAbstractMethodPhase, jvmMultiFieldValueClassPhase
),
)
/** /**
* Adds new constructors, box, and unbox functions to inline classes as well as replacement * Adds new constructors, box, and unbox functions to inline classes as well as replacement
* functions and bridges to avoid clashes between overloaded function. Changes calls with * functions and bridges to avoid clashes between overloaded function. Changes call with
* known types to call the replacement functions. * known types to call the replacement functions.
* *
* We do not unfold inline class types here. Instead, the type mapper will lower inline class * We do not unfold inline class types here. Instead, the type mapper will lower inline class
* types to the types of their underlying field. * types to the types of their underlying field.
*/ */
private class JvmInlineClassLowering(context: JvmBackendContext) : JvmValueClassAbstractLowering(context) { internal class JvmInlineClassLowering(
context: JvmBackendContext,
fileClassNewDeclarations: MutableMap<IrFile, MutableList<IrSimpleFunction>>,
scopeStack: MutableList<ScopeWithIr>,
) : JvmValueClassAbstractLowering(context, fileClassNewDeclarations, scopeStack) {
override val replacements: MemoizedValueClassAbstractReplacements override val replacements: MemoizedValueClassAbstractReplacements
get() = context.inlineClassReplacements get() = context.inlineClassReplacements
@@ -83,8 +74,10 @@ private class JvmInlineClassLowering(context: JvmBackendContext) : JvmValueClass
override val specificMangle: SpecificMangle override val specificMangle: SpecificMangle
get() = SpecificMangle.Inline get() = SpecificMangle.Inline
override val IrType.needsHandling get() = isInlineClassType()
override fun visitClassNewDeclarationsWhenParallel(declaration: IrDeclaration) = Unit
override fun visitClassNew(declaration: IrClass): IrStatement { override fun visitClassNew(declaration: IrClass): IrClass {
// The arguments to the primary constructor are in scope in the initializers of IrFields. // The arguments to the primary constructor are in scope in the initializers of IrFields.
declaration.primaryConstructor?.let { declaration.primaryConstructor?.let {
@@ -122,7 +115,7 @@ private class JvmInlineClassLowering(context: JvmBackendContext) : JvmValueClass
addJvmInlineAnnotation(declaration) addJvmInlineAnnotation(declaration)
} }
fun addJvmInlineAnnotation(valueClass: IrClass) { private fun addJvmInlineAnnotation(valueClass: IrClass) {
if (valueClass.hasAnnotation(JVM_INLINE_ANNOTATION_FQ_NAME)) return if (valueClass.hasAnnotation(JVM_INLINE_ANNOTATION_FQ_NAME)) return
val constructor = context.ir.symbols.jvmInlineAnnotation.constructors.first() val constructor = context.ir.symbols.jvmInlineAnnotation.constructors.first()
valueClass.annotations = valueClass.annotations + IrConstructorCallImpl.fromSymbolOwner( valueClass.annotations = valueClass.annotations + IrConstructorCallImpl.fromSymbolOwner(
@@ -424,7 +417,7 @@ private class JvmInlineClassLowering(context: JvmBackendContext) : JvmValueClass
return super.visitSetValue(expression) return super.visitSetValue(expression)
} }
fun buildPrimaryInlineClassConstructor(valueClass: IrClass, irConstructor: IrConstructor) { private fun buildPrimaryInlineClassConstructor(valueClass: IrClass, irConstructor: IrConstructor) {
// Add the default primary constructor // Add the default primary constructor
valueClass.addConstructor { valueClass.addConstructor {
updateFrom(irConstructor) updateFrom(irConstructor)
@@ -469,7 +462,7 @@ private class JvmInlineClassLowering(context: JvmBackendContext) : JvmValueClass
valueClass.declarations += function valueClass.declarations += function
} }
fun buildBoxFunction(valueClass: IrClass) { private fun buildBoxFunction(valueClass: IrClass) {
val function = context.inlineClassReplacements.getBoxFunction(valueClass) val function = context.inlineClassReplacements.getBoxFunction(valueClass)
with(context.createIrBuilder(function.symbol)) { with(context.createIrBuilder(function.symbol)) {
function.body = irExprBody( function.body = irExprBody(
@@ -494,7 +487,7 @@ private class JvmInlineClassLowering(context: JvmBackendContext) : JvmValueClass
irClass.declarations += function irClass.declarations += function
} }
fun buildSpecializedEqualsMethodIfNeeded(valueClass: IrClass) { private fun buildSpecializedEqualsMethodIfNeeded(valueClass: IrClass) {
val function = context.inlineClassReplacements.getSpecializedEqualsMethod(valueClass, context.irBuiltIns) val function = context.inlineClassReplacements.getSpecializedEqualsMethod(valueClass, context.irBuiltIns)
// Return if we have already built specialized equals as static replacement of typed equals // Return if we have already built specialized equals as static replacement of typed equals
if (function.body != null) return if (function.body != null) return
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ScopeWithIr import org.jetbrains.kotlin.backend.common.ScopeWithIr
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irCatch import org.jetbrains.kotlin.backend.common.lower.irCatch
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.common.pop
import org.jetbrains.kotlin.backend.common.push import org.jetbrains.kotlin.backend.common.push
import org.jetbrains.kotlin.backend.jvm.* import org.jetbrains.kotlin.backend.jvm.*
@@ -36,16 +35,14 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
val jvmMultiFieldValueClassPhase = makeIrFilePhase( internal class JvmMultiFieldValueClassLowering(
::JvmMultiFieldValueClassLowering, context: JvmBackendContext,
name = "Multi-field Value Classes", fileClassNewDeclarations: MutableMap<IrFile, MutableList<IrSimpleFunction>>,
description = "Lower multi-field value classes", scopeStack: MutableList<ScopeWithIr>,
// Collection stubs may require mangling by multi-field value class rules. ) : JvmValueClassAbstractLowering(context, fileClassNewDeclarations, scopeStack) {
// SAM wrappers may require mangling for fun interfaces with multi-field value class parameters override val IrType.needsHandling: Boolean
prerequisite = setOf(collectionStubMethodLowering, singleAbstractMethodPhase), get() = needsMfvcFlattening()
)
private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmValueClassAbstractLowering(context) {
private sealed class MfvcNodeInstanceAccessor { private sealed class MfvcNodeInstanceAccessor {
abstract val instance: MfvcNodeInstance abstract val instance: MfvcNodeInstance
abstract operator fun get(name: Name): MfvcNodeInstanceAccessor? abstract operator fun get(name: Name): MfvcNodeInstanceAccessor?
@@ -268,7 +265,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
variablesToAdd.getOrPut(variable.parent) { mutableSetOf() }.add(variable) variablesToAdd.getOrPut(variable.parent) { mutableSetOf() }.add(variable)
} }
override fun visitClassNew(declaration: IrClass): IrStatement { override fun visitClassNew(declaration: IrClass): IrClass {
if (declaration.isSpecificLoweringLogicApplicable()) { if (declaration.isSpecificLoweringLogicApplicable()) {
handleSpecificNewClass(declaration) handleSpecificNewClass(declaration)
@@ -284,25 +281,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
null null
}).also { declarations -> }).also { declarations ->
for (replacingDeclaration in declarations ?: listOf(memberDeclaration)) { for (replacingDeclaration in declarations ?: listOf(memberDeclaration)) {
when (replacingDeclaration) { postActionAfterTransformingClassDeclaration(replacingDeclaration)
is IrFunction -> replacingDeclaration.body = replacingDeclaration.body?.makeBodyWithAddedVariables(
context, variablesToAdd[replacingDeclaration] ?: emptySet(), replacingDeclaration.symbol
)?.apply {
if (replacingDeclaration in possibleExtraBoxUsageGenerated) {
removeAllExtraBoxes()
}
}
is IrAnonymousInitializer -> replacingDeclaration.body = replacingDeclaration.body.makeBodyWithAddedVariables(
context, variablesToAdd[replacingDeclaration.parent] ?: emptySet(), replacingDeclaration.symbol
).apply {
if (replacingDeclaration in possibleExtraBoxUsageGenerated) {
removeAllExtraBoxes()
}
} as IrBlockBody
else -> Unit
}
} }
} }
} }
@@ -310,6 +289,31 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
return declaration return declaration
} }
override fun visitClassNewDeclarationsWhenParallel(declaration: IrDeclaration) =
postActionAfterTransformingClassDeclaration(declaration)
private fun postActionAfterTransformingClassDeclaration(replacingDeclaration: IrDeclaration) {
when (replacingDeclaration) {
is IrFunction -> replacingDeclaration.body = replacingDeclaration.body?.makeBodyWithAddedVariables(
context, variablesToAdd[replacingDeclaration] ?: emptySet(), replacingDeclaration.symbol
)?.apply {
if (replacingDeclaration in possibleExtraBoxUsageGenerated) {
removeAllExtraBoxes()
}
}
is IrAnonymousInitializer -> replacingDeclaration.body = replacingDeclaration.body.makeBodyWithAddedVariables(
context, variablesToAdd[replacingDeclaration.parent] ?: emptySet(), replacingDeclaration.symbol
).apply {
if (replacingDeclaration in possibleExtraBoxUsageGenerated) {
removeAllExtraBoxes()
}
} as IrBlockBody
else -> Unit
}
}
private fun handleNonSpecificNewClass(irClass: IrClass) { private fun handleNonSpecificNewClass(irClass: IrClass) {
irClass.primaryConstructor?.let { irClass.primaryConstructor?.let {
replacements.getReplacementForRegularClassConstructor(it)?.let { replacement -> addBindingsFor(it, replacement) } replacements.getReplacementForRegularClassConstructor(it)?.let { replacement -> addBindingsFor(it, replacement) }
@@ -319,7 +323,8 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
val property = (propertyOrField as? IrPropertyOrIrField.Property)?.property ?: return@mapNotNull null val property = (propertyOrField as? IrPropertyOrIrField.Property)?.property ?: return@mapNotNull null
property.backingField?.let { property to it } property.backingField?.let { property to it }
}.toMap() }.toMap()
val propertiesOrFieldsReplacement = collectRegularClassMfvcPropertiesOrFieldsReplacement(propertiesOrFields) // resets backing fields val propertiesOrFieldsReplacement =
collectRegularClassMfvcPropertiesOrFieldsReplacement(propertiesOrFields) // resets backing fields
val fieldsToRemove = propertiesOrFieldsReplacement.keys.mapNotNull { val fieldsToRemove = propertiesOrFieldsReplacement.keys.mapNotNull {
when (it) { when (it) {
@@ -696,7 +701,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
} }
} }
fun RootMfvcNode.replacePrimaryMultiFieldValueClassConstructor() { private fun RootMfvcNode.replacePrimaryMultiFieldValueClassConstructor() {
val rootMfvcNode = this val rootMfvcNode = this
mfvc.declarations.removeIf { it is IrConstructor && it.isPrimary } mfvc.declarations.removeIf { it is IrConstructor && it.isPrimary }
mfvc.declarations += listOf(newPrimaryConstructor, primaryConstructorImpl) mfvc.declarations += listOf(newPrimaryConstructor, primaryConstructorImpl)
@@ -755,26 +760,28 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
} }
} }
override val fileClassNewDeclarations = mutableMapOf<IrFile, MutableList<IrSimpleFunction>>() private fun createMfvcPrimaryConstructorReferenceHelperFunction(rootNode: RootMfvcNode): IrSimpleFunction {
val currentFile = currentFile
private fun createMfvcPrimaryConstructorReferenceHelperFunction(rootNode: RootMfvcNode) = context.irFactory.buildFun { return context.irFactory.buildFun {
name = Name.identifier("mfvcConstructorReferenceHelper\$${fileClassNewDeclarations[currentFile]?.size ?: 0}") name = Name.identifier("mfvcConstructorReferenceHelper\$${fileClassNewDeclarations[currentFile]?.size ?: 0}")
origin = JvmLoweredDeclarationOrigin.MFVC_PRIMARY_CONSTRUCTOR_REFERENCE_HELPER origin = JvmLoweredDeclarationOrigin.MFVC_PRIMARY_CONSTRUCTOR_REFERENCE_HELPER
}.apply function@{ }.apply function@{
fileClassNewDeclarations.getOrPut(currentFile) { mutableListOf() }.add(this) parent = currentFile
copyParameterDeclarationsFrom(rootNode.primaryConstructorImpl) fileClassNewDeclarations.getOrPut(currentFile) { mutableListOf() }.add(this)
returnType = rootNode.type.substitute(rootNode.mfvc.typeParameters, typeParameters.map { it.defaultType }) copyParameterDeclarationsFrom(rootNode.primaryConstructorImpl)
body = context.createJvmIrBuilder(this.symbol).run { returnType = rootNode.type.substitute(rootNode.mfvc.typeParameters, typeParameters.map { it.defaultType })
irExprBody(irBlock { body = context.createJvmIrBuilder(this.symbol).run {
for (callee in listOf(rootNode.primaryConstructorImpl, rootNode.boxMethod)) { irExprBody(irBlock {
+irCall(callee).apply { for (callee in listOf(rootNode.primaryConstructorImpl, rootNode.boxMethod)) {
passTypeArgumentsFrom(this@function) +irCall(callee).apply {
for ((index, parameter) in this@function.valueParameters.withIndex()) { passTypeArgumentsFrom(this@function)
putValueArgument(index, irGet(parameter)) for ((index, parameter) in this@function.valueParameters.withIndex()) {
putValueArgument(index, irGet(parameter))
}
} }
} }
} })
}) }
} }
} }
@@ -971,7 +978,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
* val b = 3 * val b = 3
* [a, b, b + 1] * [a, b, b + 1]
*/ */
fun IrBuilderWithScope.removeExtraSetVariablesFromExpressionList( private fun IrBuilderWithScope.removeExtraSetVariablesFromExpressionList(
block: IrContainerExpression, block: IrContainerExpression,
variables: List<IrVariable> variables: List<IrVariable>
): List<IrExpression> { ): List<IrExpression> {
@@ -1114,7 +1121,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
/** /**
* Takes not transformed expression and initialized given MfvcNodeInstance with transformed version of it * Takes not transformed expression and initialized given MfvcNodeInstance with transformed version of it
*/ */
fun IrBlockBuilder.flattenExpressionTo(expression: IrExpression, instance: MfvcNodeInstance) { private fun IrBlockBuilder.flattenExpressionTo(expression: IrExpression, instance: MfvcNodeInstance) {
val rootNode = replacements.getRootMfvcNodeOrNull( val rootNode = replacements.getRootMfvcNodeOrNull(
if (expression is IrConstructorCall) expression.symbol.owner.constructedClass else expression.type.erasedUpperBound if (expression is IrConstructorCall) expression.symbol.owner.constructedClass else expression.type.erasedUpperBound
) )
@@ -1197,7 +1204,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
/** /**
* Removes boxing when the result is not used * Removes boxing when the result is not used
*/ */
fun IrBody.removeAllExtraBoxes() { private fun IrBody.removeAllExtraBoxes() {
// data is whether the expression result is used // data is whether the expression result is used
accept(object : IrElementVisitor<Unit, Boolean> { accept(object : IrElementVisitor<Unit, Boolean> {
override fun visitElement(element: IrElement, data: Boolean) { override fun visitElement(element: IrElement, data: Boolean) {
@@ -5,44 +5,37 @@
package org.jetbrains.kotlin.backend.jvm.lower package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.pop
import org.jetbrains.kotlin.backend.common.push
import org.jetbrains.kotlin.backend.jvm.* import org.jetbrains.kotlin.backend.jvm.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.irReturn import org.jetbrains.kotlin.ir.builders.irReturn
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.transformStatement import org.jetbrains.kotlin.ir.transformStatement
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceAnd import org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceAnd
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
internal abstract class JvmValueClassAbstractLowering(val context: JvmBackendContext) : FileLoweringPass, internal abstract class JvmValueClassAbstractLowering(
IrElementTransformerVoidWithContext() { val context: JvmBackendContext,
protected val fileClassNewDeclarations: MutableMap<IrFile, MutableList<IrSimpleFunction>>,
override val scopeStack: MutableList<ScopeWithIr>,
) : FileLoweringPass, IrElementTransformerVoidWithContext() {
abstract val replacements: MemoizedValueClassAbstractReplacements abstract val replacements: MemoizedValueClassAbstractReplacements
final override fun lower(irFile: IrFile) { final override fun lower(irFile: IrFile) = withinScope(irFile) {
withinScope(irFile) { irFile.transformChildrenVoid()
irFile.transformChildrenVoid() addDeclarations(context, fileClassNewDeclarations, irFile)
fileClassNewDeclarations[irFile]?.let { newDeclarations ->
val oldFileClass = irFile.declarations.filterIsInstanceAnd<IrClass> { it.isFileClass }.singleOrNull()
val allFileDeclarations = (oldFileClass?.declarations ?: listOf()) + newDeclarations
val newClass = createFileClass(context, irFile, allFileDeclarations)
oldFileClass?.let { irFile.declarations.remove(it) }
irFile.addChild(newClass)
}
}
} }
abstract fun IrClass.isSpecificLoweringLogicApplicable(): Boolean abstract fun IrClass.isSpecificLoweringLogicApplicable(): Boolean
abstract override fun visitClassNew(declaration: IrClass): IrStatement
abstract fun handleSpecificNewClass(declaration: IrClass) abstract fun handleSpecificNewClass(declaration: IrClass)
protected fun transformFunctionFlat(function: IrFunction): List<IrDeclaration>? { protected fun transformFunctionFlat(function: IrFunction): List<IrDeclaration>? {
@@ -91,7 +84,7 @@ internal abstract class JvmValueClassAbstractLowering(val context: JvmBackendCon
} }
} }
private fun transformFlattenedConstructor(function: IrConstructor, replacement: IrConstructor): List<IrDeclaration>? { private fun transformFlattenedConstructor(function: IrConstructor, replacement: IrConstructor): List<IrDeclaration> {
replacement.valueParameters.forEach { replacement.valueParameters.forEach {
visitParameter(it) visitParameter(it)
it.defaultValue?.patchDeclarationParents(replacement) it.defaultValue?.patchDeclarationParents(replacement)
@@ -155,7 +148,7 @@ internal abstract class JvmValueClassAbstractLowering(val context: JvmBackendCon
return super.visitReturn(expression) return super.visitReturn(expression)
} }
private fun visitStatementContainer(container: IrStatementContainer) { internal fun visitStatementContainer(container: IrStatementContainer) {
container.statements.transformFlat { statement -> container.statements.transformFlat { statement ->
if (statement is IrFunction) if (statement is IrFunction)
transformFunctionFlat(statement) transformFunctionFlat(statement)
@@ -248,5 +241,157 @@ internal abstract class JvmValueClassAbstractLowering(val context: JvmBackendCon
protected abstract fun createBridgeBody(source: IrSimpleFunction, target: IrSimpleFunction, original: IrFunction, inverted: Boolean) protected abstract fun createBridgeBody(source: IrSimpleFunction, target: IrSimpleFunction, original: IrFunction, inverted: Boolean)
protected open val fileClassNewDeclarations: Map<IrFile, List<IrSimpleFunction>> = emptyMap()
// Functions for common lowering dispatching
private inner class NeedsToVisit : IrElementVisitor<Boolean, Nothing?> {
override fun visitElement(element: IrElement, data: Nothing?): Boolean = false
override fun visitClass(declaration: IrClass, data: Nothing?): Boolean =
declaration.isSpecificLoweringLogicApplicable() || declaration.declarations.any { it.accept(this, null) }
override fun visitFunction(declaration: IrFunction, data: Nothing?): Boolean =
replacements.quickCheckIfFunctionIsNotApplicable(declaration)
override fun visitFunctionReference(expression: IrFunctionReference, data: Nothing?): Boolean =
visitFunction(expression.symbol.owner, data)
override fun visitFunctionAccess(expression: IrFunctionAccessExpression, data: Nothing?): Boolean =
visitFunction(expression.symbol.owner, data)
override fun visitField(declaration: IrField, data: Nothing?): Boolean = declaration.type.needsHandling
override fun visitFieldAccess(expression: IrFieldAccessExpression, data: Nothing?): Boolean =
visitField(expression.symbol.owner, data)
override fun visitVariable(declaration: IrVariable, data: Nothing?): Boolean = visitValueDeclaration(declaration)
private fun visitValueDeclaration(declaration: IrValueDeclaration) = declaration.type.needsHandling
override fun visitValueParameter(declaration: IrValueParameter, data: Nothing?): Boolean = visitValueDeclaration(declaration)
override fun visitValueAccess(expression: IrValueAccessExpression, data: Nothing?): Boolean =
visitValueDeclaration(expression.symbol.owner)
override fun visitStringConcatenation(expression: IrStringConcatenation, data: Nothing?): Boolean = false
override fun visitReturn(expression: IrReturn, data: Nothing?): Boolean = expression.returnTargetSymbol.owner.safeAs<IrFunction>()
?.let { replacements.quickCheckIfFunctionIsNotApplicable(it) } ?: false
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer, data: Nothing?): Boolean =
declaration.parent.safeAs<IrClass>()?.isSpecificLoweringLogicApplicable() == true
private fun visitStatementContainer(container: IrStatementContainer) = container.statements.any { it.accept(this, null) }
override fun visitContainerExpression(expression: IrContainerExpression, data: Nothing?): Boolean =
visitStatementContainer(expression)
override fun visitBlockBody(body: IrBlockBody, data: Nothing?): Boolean = visitStatementContainer(body)
}
internal fun needsToVisitClassNew(declaration: IrClass): Boolean = declaration.accept(NeedsToVisit(), null)
internal fun needsToVisitFunctionReference(expression: IrFunctionReference): Boolean = expression.accept(NeedsToVisit(), null)
internal fun needsToVisitFunctionAccess(expression: IrFunctionAccessExpression): Boolean = expression.accept(NeedsToVisit(), null)
internal fun needsToVisitCall(expression: IrCall): Boolean = expression.accept(NeedsToVisit(), null)
internal fun needsToVisitStringConcatenation(expression: IrStringConcatenation): Boolean = expression.accept(NeedsToVisit(), null)
internal fun needsToVisitGetField(expression: IrGetField): Boolean = expression.accept(NeedsToVisit(), null)
internal fun needsToVisitSetField(expression: IrSetField): Boolean = expression.accept(NeedsToVisit(), null)
internal fun needsToVisitGetValue(expression: IrGetValue): Boolean = expression.accept(NeedsToVisit(), null)
internal fun needsToVisitSetValue(expression: IrSetValue): Boolean = expression.accept(NeedsToVisit(), null)
internal fun needsToVisitVariable(declaration: IrVariable): Boolean = declaration.accept(NeedsToVisit(), null)
internal fun needsToVisitReturn(expression: IrReturn): Boolean = expression.accept(NeedsToVisit(), null)
internal abstract fun visitClassNewDeclarationsWhenParallel(declaration: IrDeclaration)
// forbid other overrides without modifying dispatcher file JvmValueClassLoweringDispatcher.kt
final override fun visitModuleFragment(declaration: IrModuleFragment): IrModuleFragment = super.visitModuleFragment(declaration)
final override fun visitPackageFragment(declaration: IrPackageFragment): IrPackageFragment = super.visitPackageFragment(declaration)
final override fun visitExternalPackageFragment(declaration: IrExternalPackageFragment): IrExternalPackageFragment =
super.visitExternalPackageFragment(declaration)
final override fun visitDeclaration(declaration: IrDeclarationBase): IrStatement = super.visitDeclaration(declaration)
final override fun visitSimpleFunction(declaration: IrSimpleFunction) = super.visitSimpleFunction(declaration)
final override fun visitConstructor(declaration: IrConstructor) = super.visitConstructor(declaration)
final override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty) = super.visitLocalDelegatedProperty(declaration)
final override fun visitEnumEntry(declaration: IrEnumEntry) = super.visitEnumEntry(declaration)
final override fun visitTypeParameter(declaration: IrTypeParameter) = super.visitTypeParameter(declaration)
final override fun visitTypeAlias(declaration: IrTypeAlias) = super.visitTypeAlias(declaration)
final override fun visitBody(body: IrBody): IrBody = super.visitBody(body)
final override fun visitExpressionBody(body: IrExpressionBody) = super.visitExpressionBody(body)
final override fun visitSyntheticBody(body: IrSyntheticBody) = super.visitSyntheticBody(body)
final override fun visitSuspendableExpression(expression: IrSuspendableExpression) = super.visitSuspendableExpression(expression)
final override fun visitSuspensionPoint(expression: IrSuspensionPoint) = super.visitSuspensionPoint(expression)
final override fun visitExpression(expression: IrExpression): IrExpression = super.visitExpression(expression)
final override fun visitConst(expression: IrConst<*>) = super.visitConst(expression)
final override fun visitConstantValue(expression: IrConstantValue): IrConstantValue = super.visitConstantValue(expression)
final override fun visitConstantObject(expression: IrConstantObject) = super.visitConstantObject(expression)
final override fun visitConstantPrimitive(expression: IrConstantPrimitive) = super.visitConstantPrimitive(expression)
final override fun visitConstantArray(expression: IrConstantArray) = super.visitConstantArray(expression)
final override fun visitVararg(expression: IrVararg) = super.visitVararg(expression)
final override fun visitSpreadElement(spread: IrSpreadElement): IrSpreadElement = super.visitSpreadElement(spread)
final override fun visitBlock(expression: IrBlock) = super.visitBlock(expression)
final override fun visitComposite(expression: IrComposite) = super.visitComposite(expression)
final override fun visitDeclarationReference(expression: IrDeclarationReference) = super.visitDeclarationReference(expression)
final override fun visitSingletonReference(expression: IrGetSingletonValue) = super.visitSingletonReference(expression)
final override fun visitGetObjectValue(expression: IrGetObjectValue) = super.visitGetObjectValue(expression)
final override fun visitGetEnumValue(expression: IrGetEnumValue) = super.visitGetEnumValue(expression)
final override fun visitValueAccess(expression: IrValueAccessExpression) = super.visitValueAccess(expression)
final override fun visitFieldAccess(expression: IrFieldAccessExpression) = super.visitFieldAccess(expression)
final override fun visitMemberAccess(expression: IrMemberAccessExpression<*>) = super.visitMemberAccess(expression)
final override fun visitConstructorCall(expression: IrConstructorCall) = super.visitConstructorCall(expression)
final override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) =
super.visitDelegatingConstructorCall(expression)
final override fun visitEnumConstructorCall(expression: IrEnumConstructorCall) = super.visitEnumConstructorCall(expression)
final override fun visitGetClass(expression: IrGetClass) = super.visitGetClass(expression)
final override fun visitCallableReference(expression: IrCallableReference<*>) = super.visitCallableReference(expression)
final override fun visitPropertyReference(expression: IrPropertyReference) = super.visitPropertyReference(expression)
final override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference) =
super.visitLocalDelegatedPropertyReference(expression)
final override fun visitRawFunctionReference(expression: IrRawFunctionReference) = super.visitRawFunctionReference(expression)
final override fun visitFunctionExpression(expression: IrFunctionExpression) = super.visitFunctionExpression(expression)
final override fun visitClassReference(expression: IrClassReference) = super.visitClassReference(expression)
final override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall) = super.visitInstanceInitializerCall(expression)
final override fun visitTypeOperator(expression: IrTypeOperatorCall) = super.visitTypeOperator(expression)
final override fun visitWhen(expression: IrWhen) = super.visitWhen(expression)
final override fun visitBranch(branch: IrBranch): IrBranch = super.visitBranch(branch)
final override fun visitElseBranch(branch: IrElseBranch): IrElseBranch = super.visitElseBranch(branch)
final override fun visitLoop(loop: IrLoop) = super.visitLoop(loop)
final override fun visitWhileLoop(loop: IrWhileLoop) = super.visitWhileLoop(loop)
final override fun visitDoWhileLoop(loop: IrDoWhileLoop) = super.visitDoWhileLoop(loop)
final override fun visitTry(aTry: IrTry) = super.visitTry(aTry)
final override fun visitCatch(aCatch: IrCatch): IrCatch = super.visitCatch(aCatch)
final override fun visitBreakContinue(jump: IrBreakContinue) = super.visitBreakContinue(jump)
final override fun visitBreak(jump: IrBreak) = super.visitBreak(jump)
final override fun visitContinue(jump: IrContinue) = super.visitContinue(jump)
final override fun visitThrow(expression: IrThrow) = super.visitThrow(expression)
final override fun visitDynamicExpression(expression: IrDynamicExpression) = super.visitDynamicExpression(expression)
final override fun visitDynamicOperatorExpression(expression: IrDynamicOperatorExpression) =
super.visitDynamicOperatorExpression(expression)
final override fun visitDynamicMemberExpression(expression: IrDynamicMemberExpression) = super.visitDynamicMemberExpression(expression)
final override fun visitErrorDeclaration(declaration: IrErrorDeclaration) = super.visitErrorDeclaration(declaration)
final override fun visitErrorExpression(expression: IrErrorExpression) = super.visitErrorExpression(expression)
final override fun visitErrorCallExpression(expression: IrErrorCallExpression) = super.visitErrorCallExpression(expression)
companion object {
internal fun addDeclarations(
context: JvmBackendContext, fileClassNewDeclarations: MutableMap<IrFile, MutableList<IrSimpleFunction>>, irFile: IrFile
) {
fileClassNewDeclarations[irFile]?.let { newDeclarations ->
val oldFileClass = irFile.declarations.filterIsInstanceAnd<IrClass> { it.isFileClass }.singleOrNull()
val allFileDeclarations = (oldFileClass?.declarations ?: listOf()) + newDeclarations
val newClass = createFileClass(context, irFile, allFileDeclarations)
oldFileClass?.let { irFile.declarations.remove(it) }
irFile.addChild(newClass)
}
}
}
abstract val IrType.needsHandling: Boolean
} }
@@ -0,0 +1,193 @@
/*
* Copyright 2010-2022 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.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.ScopeWithIr
import org.jetbrains.kotlin.backend.common.lower.loops.forLoopsPhase
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.transformStatement
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
val jvmValueClassPhase = makeIrFilePhase(
::JvmValueClassLoweringDispatcher,
name = "Value Classes",
description = "Lower value classes",
// forLoopsPhase may produce UInt and ULong which are inline classes.
// Standard library replacements are done on the not mangled names for UInt and ULong classes.
// Collection stubs may require mangling by value class rules.
// SAM wrappers may require mangling for fun interfaces with value class parameters
prerequisite = setOf(forLoopsPhase, jvmBuiltInsPhase, collectionStubMethodLowering, singleAbstractMethodPhase),
)
internal class JvmValueClassLoweringDispatcher(
private val context: JvmBackendContext,
private val fileClassNewDeclarations: MutableMap<IrFile, MutableList<IrSimpleFunction>> = mutableMapOf(),
override val scopeStack: MutableList<ScopeWithIr> = mutableListOf(),
private val inlineClassLowering: JvmInlineClassLowering = JvmInlineClassLowering(context, fileClassNewDeclarations, scopeStack),
private val multiFieldValueClassLowering: JvmMultiFieldValueClassLowering =
JvmMultiFieldValueClassLowering(context, fileClassNewDeclarations, scopeStack),
) : IrElementTransformerVoidWithContext(), FileLoweringPass {
override fun lower(irFile: IrFile) = withinScope(irFile) {
irFile.transformChildrenVoid()
JvmValueClassAbstractLowering.addDeclarations(context, fileClassNewDeclarations, irFile)
}
private fun IrElement.requiresAnyHandling() =
requiresHandling(multiFieldValueClassLowering) || requiresHandling(inlineClassLowering)
override fun visitClassNew(declaration: IrClass): IrClass = if (declaration.requiresAnyHandling()) {
declaration
.let(multiFieldValueClassLowering::visitClassNew)
.let(inlineClassLowering::visitClassNew)
} else {
declaration.transformChildrenVoid()
for (innerDeclaration in declaration.declarations) {
multiFieldValueClassLowering.visitClassNewDeclarationsWhenParallel(innerDeclaration)
}
for (innerDeclaration in declaration.declarations) {
inlineClassLowering.visitClassNewDeclarationsWhenParallel(innerDeclaration)
}
declaration
}
private fun transformExpressionConsequently(expression: IrExpression) = expression
.transform(multiFieldValueClassLowering, null)
.transform(inlineClassLowering, null)
private fun transformStatementConsequently(statement: IrStatement) = statement
.transformStatement(multiFieldValueClassLowering)
.transformStatement(inlineClassLowering)
private fun IrElement.requiresHandling(lowering: JvmValueClassAbstractLowering) =
accept(object : IrElementVisitor<Boolean, Nothing?> {
override fun visitElement(element: IrElement, data: Nothing?): Boolean = false
override fun visitClass(declaration: IrClass, data: Nothing?): Boolean =
lowering.needsToVisitClassNew(declaration) || super.visitClass(declaration, data)
override fun visitFunctionReference(expression: IrFunctionReference, data: Nothing?): Boolean =
lowering.needsToVisitFunctionReference(expression) || super.visitFunctionReference(expression, data)
override fun visitFunctionAccess(expression: IrFunctionAccessExpression, data: Nothing?): Boolean =
lowering.needsToVisitFunctionAccess(expression) || super.visitFunctionAccess(expression, data)
override fun visitCall(expression: IrCall, data: Nothing?): Boolean =
lowering.needsToVisitCall(expression) || super.visitCall(expression, data)
override fun visitStringConcatenation(expression: IrStringConcatenation, data: Nothing?): Boolean =
lowering.needsToVisitStringConcatenation(expression) || super.visitStringConcatenation(expression, data)
override fun visitGetField(expression: IrGetField, data: Nothing?): Boolean =
lowering.needsToVisitGetField(expression) || super.visitGetField(expression, data)
override fun visitSetField(expression: IrSetField, data: Nothing?): Boolean =
lowering.needsToVisitSetField(expression) || super.visitSetField(expression, data)
override fun visitGetValue(expression: IrGetValue, data: Nothing?): Boolean =
lowering.needsToVisitGetValue(expression) || super.visitGetValue(expression, data)
override fun visitSetValue(expression: IrSetValue, data: Nothing?): Boolean =
lowering.needsToVisitSetValue(expression) || super.visitSetValue(expression, data)
override fun visitVariable(declaration: IrVariable, data: Nothing?): Boolean =
lowering.needsToVisitVariable(declaration) || super.visitVariable(declaration, data)
override fun visitReturn(expression: IrReturn, data: Nothing?): Boolean =
lowering.needsToVisitReturn(expression) || super.visitReturn(expression, data)
}, null)
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression = if (expression.requiresAnyHandling()) {
transformExpressionConsequently(expression)
} else {
super.visitFunctionReference(expression)
}
override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression = if (expression.requiresAnyHandling()) {
transformExpressionConsequently(expression)
} else {
super.visitFunctionAccess(expression)
}
override fun visitCall(expression: IrCall): IrExpression = if (expression.requiresAnyHandling()) {
transformExpressionConsequently(expression)
} else {
super.visitCall(expression)
}
override fun visitStringConcatenation(expression: IrStringConcatenation): IrExpression = if (expression.requiresAnyHandling()) {
transformExpressionConsequently(expression)
} else {
super.visitStringConcatenation(expression)
}
override fun visitGetField(expression: IrGetField): IrExpression = if (expression.requiresAnyHandling()) {
transformExpressionConsequently(expression)
} else {
super.visitGetField(expression)
}
override fun visitSetField(expression: IrSetField): IrExpression = if (expression.requiresAnyHandling()) {
transformExpressionConsequently(expression)
} else {
super.visitSetField(expression)
}
override fun visitGetValue(expression: IrGetValue): IrExpression = if (expression.requiresAnyHandling()) {
transformExpressionConsequently(expression)
} else {
super.visitGetValue(expression)
}
override fun visitSetValue(expression: IrSetValue): IrExpression = if (expression.requiresAnyHandling()) {
transformExpressionConsequently(expression)
} else {
super.visitSetValue(expression)
}
override fun visitVariable(declaration: IrVariable): IrStatement = if (declaration.requiresAnyHandling()) {
transformStatementConsequently(declaration)
} else {
super.visitVariable(declaration)
}
override fun visitReturn(expression: IrReturn): IrExpression = if (expression.requiresAnyHandling()) {
transformExpressionConsequently(expression)
} else {
super.visitReturn(expression)
}
override fun visitAnonymousInitializerNew(declaration: IrAnonymousInitializer): IrStatement = if (declaration.requiresAnyHandling()) {
transformStatementConsequently(declaration)
} else {
super.visitAnonymousInitializerNew(declaration)
}
private fun visitStatementContainer(container: IrStatementContainer) = if (container.statements.any { it.requiresAnyHandling() }) {
multiFieldValueClassLowering.visitStatementContainer(container)
inlineClassLowering.visitStatementContainer(container)
} else {
container.statements.replaceAll { it.transformStatement(this) }
}
override fun visitContainerExpression(expression: IrContainerExpression): IrExpression {
visitStatementContainer(expression)
return expression
}
override fun visitBlockBody(body: IrBlockBody): IrBody {
visitStatementContainer(body)
return body
}
}
@@ -95,7 +95,7 @@ abstract class MemoizedValueClassAbstractReplacements(
annotations = propertySymbol.owner.annotations annotations = propertySymbol.owner.annotations
// In case this property is declared in an object in another file which is not yet lowered, its backing field will // In case this property is declared in an object in another file which is not yet lowered, its backing field will
// be made static later. We have to handle it here though, because this new property will be saved to the cache // be made static later. We have to handle it here though, because this new property will be saved to the cache
// and reused when lowering the same call in all subsequent files, which would be incorrect if it was unlowered. // and reused when lowering the same call in all subsequent files, which would be incorrect if it was not lowered.
backingField = context.cachedDeclarations.getStaticBackingField(propertySymbol.owner) backingField = context.cachedDeclarations.getStaticBackingField(propertySymbol.owner)
?: propertySymbol.owner.backingField ?: propertySymbol.owner.backingField
} }
@@ -132,5 +132,5 @@ abstract class MemoizedValueClassAbstractReplacements(
function.overriddenSymbols = replaceOverriddenSymbols(function) function.overriddenSymbols = replaceOverriddenSymbols(function)
} }
protected abstract fun quickCheckIfFunctionIsNotApplicable(function: IrFunction): Boolean abstract fun quickCheckIfFunctionIsNotApplicable(function: IrFunction): Boolean
} }