[IR] Combine value class lowerings
Signed-off-by: Evgeniy.Zhelenskiy <Evgeniy.Zhelenskiy@jetbrains.com> #KT-1179
This commit is contained in:
committed by
Space Team
parent
68fb8aa2a1
commit
86809e898a
+1
-1
@@ -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)
|
||||||
|
|||||||
+4
-5
@@ -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(),
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -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() {
|
||||||
|
|||||||
+15
-22
@@ -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
|
||||||
|
|||||||
+60
-53
@@ -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) {
|
||||||
|
|||||||
+167
-22
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
+193
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -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
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user