IR: refactor InitializersLoweringBase and descendants
This commit is contained in:
+33
-56
@@ -7,10 +7,9 @@ package org.jetbrains.kotlin.backend.common.lower
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrBlock
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrInstanceInitializerCall
|
import org.jetbrains.kotlin.ir.expressions.IrInstanceInitializerCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
|
import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
|
||||||
@@ -18,73 +17,51 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
|||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
||||||
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
|
|
||||||
object SYNTHESIZED_INIT_BLOCK : IrStatementOriginImpl("SYNTHESIZED_INIT_BLOCK")
|
object SYNTHESIZED_INIT_BLOCK : IrStatementOriginImpl("SYNTHESIZED_INIT_BLOCK")
|
||||||
|
|
||||||
open class InitializersLowering(
|
open class InitializersLowering(context: CommonBackendContext) : InitializersLoweringBase(context) {
|
||||||
context: CommonBackendContext
|
|
||||||
) : InitializersLoweringBase(context) {
|
|
||||||
override fun lower(irClass: IrClass) {
|
override fun lower(irClass: IrClass) {
|
||||||
val nonStaticDeclarations = getDeclarationsWithNonStaticInitializers(irClass)
|
val instanceInitializerStatements = extractInitializers(irClass) {
|
||||||
val instanceInitializerStatements = nonStaticDeclarations.mapNotNull { handleDeclaration(irClass, it) }
|
|
||||||
transformInstanceInitializerCallsInConstructors(irClass, instanceInitializerStatements)
|
|
||||||
|
|
||||||
val anonymousInitializers = nonStaticDeclarations.filterTo(hashSetOf()) { it is IrAnonymousInitializer }
|
|
||||||
irClass.declarations.removeAll(anonymousInitializers)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getDeclarationsWithNonStaticInitializers(irClass: IrClass): List<IrDeclaration> =
|
|
||||||
irClass.declarations.filter {
|
|
||||||
(it is IrField && !it.isStatic) || (it is IrAnonymousInitializer && !it.isStatic)
|
(it is IrField && !it.isStatic) || (it is IrAnonymousInitializer && !it.isStatic)
|
||||||
}
|
}
|
||||||
|
irClass.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
||||||
|
// Only transform constructors of current class.
|
||||||
|
override fun visitClassNew(declaration: IrClass) = declaration
|
||||||
|
|
||||||
private fun transformInstanceInitializerCallsInConstructors(irClass: IrClass, instanceInitializerStatements: List<IrStatement>) {
|
override fun visitSimpleFunction(declaration: IrSimpleFunction) = declaration
|
||||||
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
|
|
||||||
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression {
|
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression =
|
||||||
val copiedBlock =
|
IrBlockImpl(irClass.startOffset, irClass.endOffset, context.irBuiltIns.unitType, null, instanceInitializerStatements)
|
||||||
IrBlockImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.unitType, null, instanceInitializerStatements)
|
.deepCopyWithSymbols(currentScope!!.scope.getLocalDeclarationParent())
|
||||||
.copy(irClass) as IrBlock
|
|
||||||
return IrBlockImpl(irClass.startOffset, irClass.endOffset, context.irBuiltIns.unitType, null, copiedBlock.statements)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class InitializersLoweringBase(val context: CommonBackendContext) : ClassLoweringPass {
|
abstract class InitializersLoweringBase(val context: CommonBackendContext) : ClassLoweringPass {
|
||||||
protected fun handleDeclaration(irClass: IrClass, declaration: IrDeclaration): IrStatement? = when (declaration) {
|
protected fun extractInitializers(irClass: IrClass, filter: (IrDeclaration) -> Boolean) =
|
||||||
is IrField -> handleField(irClass, declaration)
|
irClass.declarations.filter(filter).mapNotNull {
|
||||||
is IrAnonymousInitializer -> handleAnonymousInitializer(declaration)
|
when (it) {
|
||||||
else -> null
|
is IrField -> handleField(irClass, it)
|
||||||
}
|
is IrAnonymousInitializer -> handleAnonymousInitializer(it)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}.also {
|
||||||
|
irClass.declarations.removeAll { it is IrAnonymousInitializer && filter(it) }
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleField(irClass: IrClass, declaration: IrField): IrStatement? {
|
private fun handleField(irClass: IrClass, declaration: IrField): IrStatement? =
|
||||||
val irFieldInitializer = declaration.initializer?.expression ?: return null
|
declaration.initializer?.run {
|
||||||
|
val receiver = if (!declaration.isStatic) // TODO isStaticField
|
||||||
|
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol)
|
||||||
|
else
|
||||||
|
null
|
||||||
|
IrSetFieldImpl(startOffset, endOffset, declaration.symbol, receiver, expression, context.irBuiltIns.unitType)
|
||||||
|
}
|
||||||
|
|
||||||
val receiver =
|
private fun handleAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement =
|
||||||
if (!declaration.isStatic) // TODO isStaticField
|
with(declaration) {
|
||||||
IrGetValueImpl(
|
IrBlockImpl(startOffset, endOffset, context.irBuiltIns.unitType, SYNTHESIZED_INIT_BLOCK, body.statements)
|
||||||
irFieldInitializer.startOffset, irFieldInitializer.endOffset,
|
}
|
||||||
irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol
|
|
||||||
)
|
|
||||||
else null
|
|
||||||
return IrSetFieldImpl(
|
|
||||||
irFieldInitializer.startOffset, irFieldInitializer.endOffset,
|
|
||||||
declaration.symbol,
|
|
||||||
receiver,
|
|
||||||
irFieldInitializer,
|
|
||||||
context.irBuiltIns.unitType,
|
|
||||||
null, null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement = IrBlockImpl(
|
|
||||||
declaration.startOffset, declaration.endOffset,
|
|
||||||
context.irBuiltIns.unitType,
|
|
||||||
SYNTHESIZED_INIT_BLOCK,
|
|
||||||
declaration.body.statements
|
|
||||||
)
|
|
||||||
|
|
||||||
protected fun IrStatement.copy(containingDeclaration: IrDeclarationParent): IrStatement = deepCopyWithSymbols(containingDeclaration)
|
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-57
@@ -6,74 +6,46 @@
|
|||||||
package org.jetbrains.kotlin.backend.jvm.lower
|
package org.jetbrains.kotlin.backend.jvm.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||||
import org.jetbrains.kotlin.backend.common.ir.SetDeclarationsParentVisitor
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower.InitializersLoweringBase
|
import org.jetbrains.kotlin.backend.common.lower.InitializersLoweringBase
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.ir.declarations.IrAnonymousInitializer
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||||
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
|
import org.jetbrains.kotlin.ir.expressions.IrSetField
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
class StaticInitializersLowering(context: CommonBackendContext) : InitializersLoweringBase(context) {
|
class StaticInitializersLowering(context: CommonBackendContext) : InitializersLoweringBase(context) {
|
||||||
override fun lower(irClass: IrClass) {
|
override fun lower(irClass: IrClass) {
|
||||||
val staticDeclarations = getDeclarationsWithStaticInitializers(irClass)
|
val staticInitializerStatements = extractInitializers(irClass) {
|
||||||
val staticInitializerStatements = staticDeclarations.mapNotNull { handleDeclaration(irClass, it) }
|
(it is IrField && it.isStatic) || (it is IrAnonymousInitializer && it.isStatic)
|
||||||
|
}.toMutableList()
|
||||||
if (staticInitializerStatements.isNotEmpty()) {
|
if (staticInitializerStatements.isNotEmpty()) {
|
||||||
createStaticInitializationMethod(irClass, staticInitializerStatements)
|
staticInitializerStatements.sortBy {
|
||||||
|
when ((it as? IrSetField)?.symbol?.owner?.origin) {
|
||||||
val anonymousInitializers = staticDeclarations.filterTo(hashSetOf()) { it is IrAnonymousInitializer }
|
IrDeclarationOrigin.FIELD_FOR_ENUM_ENTRY -> 1
|
||||||
irClass.declarations.removeAll(anonymousInitializers)
|
IrDeclarationOrigin.FIELD_FOR_ENUM_VALUES -> 2
|
||||||
|
IrDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE -> 3
|
||||||
|
else -> 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
irClass.addFunction {
|
||||||
|
startOffset = irClass.startOffset
|
||||||
|
endOffset = irClass.endOffset
|
||||||
|
name = clinitName
|
||||||
|
// TODO: mark as synthesized
|
||||||
|
origin = JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER
|
||||||
|
returnType = context.irBuiltIns.unitType
|
||||||
|
}.apply {
|
||||||
|
body = IrBlockBodyImpl(irClass.startOffset, irClass.endOffset, staticInitializerStatements)
|
||||||
|
.deepCopyWithSymbols(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getDeclarationsWithStaticInitializers(irClass: IrClass): List<IrDeclaration> =
|
|
||||||
// Hardcoded order of initializers
|
|
||||||
(irClass.declarations.filter { it is IrField && it.origin == IrDeclarationOrigin.FIELD_FOR_ENUM_ENTRY } +
|
|
||||||
irClass.declarations.filter { it is IrField && it.origin == IrDeclarationOrigin.FIELD_FOR_ENUM_VALUES } +
|
|
||||||
irClass.declarations.filter { it is IrField && it.origin == IrDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE } +
|
|
||||||
irClass.declarations.filter {
|
|
||||||
(it is IrField && it.isStatic && it.origin !in listOf(
|
|
||||||
IrDeclarationOrigin.FIELD_FOR_ENUM_ENTRY,
|
|
||||||
IrDeclarationOrigin.FIELD_FOR_ENUM_VALUES,
|
|
||||||
IrDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE
|
|
||||||
)) || (it is IrAnonymousInitializer && it.isStatic)
|
|
||||||
})
|
|
||||||
|
|
||||||
private fun createStaticInitializationMethod(irClass: IrClass, staticInitializerStatements: List<IrStatement>) {
|
|
||||||
// TODO: mark as synthesized
|
|
||||||
val staticInitializerDescriptor = WrappedSimpleFunctionDescriptor()
|
|
||||||
val staticInitializer = IrFunctionImpl(
|
|
||||||
irClass.startOffset,
|
|
||||||
irClass.endOffset,
|
|
||||||
JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER,
|
|
||||||
IrSimpleFunctionSymbolImpl(staticInitializerDescriptor),
|
|
||||||
clinitName,
|
|
||||||
Visibilities.PUBLIC,
|
|
||||||
Modality.FINAL,
|
|
||||||
returnType = context.irBuiltIns.unitType,
|
|
||||||
isInline = false,
|
|
||||||
isExternal = false,
|
|
||||||
isTailrec = false,
|
|
||||||
isSuspend = false,
|
|
||||||
isExpect = false,
|
|
||||||
isFakeOverride = false,
|
|
||||||
isOperator = false
|
|
||||||
).apply {
|
|
||||||
staticInitializerDescriptor.bind(this)
|
|
||||||
body = IrBlockBodyImpl(irClass.startOffset, irClass.endOffset,
|
|
||||||
staticInitializerStatements.map { it.copy(irClass) })
|
|
||||||
accept(SetDeclarationsParentVisitor, this)
|
|
||||||
// Should come after SetDeclarationParentVisitor, because it sets staticInitializer's own parent to itself.
|
|
||||||
parent = irClass
|
|
||||||
}
|
|
||||||
irClass.declarations.add(staticInitializer)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val clinitName = Name.special("<clinit>")
|
val clinitName = Name.special("<clinit>")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user