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.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
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.IrInstanceInitializerCall
|
||||
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.IrSetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
object SYNTHESIZED_INIT_BLOCK : IrStatementOriginImpl("SYNTHESIZED_INIT_BLOCK")
|
||||
|
||||
open class InitializersLowering(
|
||||
context: CommonBackendContext
|
||||
) : InitializersLoweringBase(context) {
|
||||
open class InitializersLowering(context: CommonBackendContext) : InitializersLoweringBase(context) {
|
||||
override fun lower(irClass: IrClass) {
|
||||
val nonStaticDeclarations = getDeclarationsWithNonStaticInitializers(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 {
|
||||
val instanceInitializerStatements = extractInitializers(irClass) {
|
||||
(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>) {
|
||||
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression {
|
||||
val copiedBlock =
|
||||
IrBlockImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.unitType, null, instanceInitializerStatements)
|
||||
.copy(irClass) as IrBlock
|
||||
return IrBlockImpl(irClass.startOffset, irClass.endOffset, context.irBuiltIns.unitType, null, copiedBlock.statements)
|
||||
}
|
||||
override fun visitSimpleFunction(declaration: IrSimpleFunction) = declaration
|
||||
|
||||
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression =
|
||||
IrBlockImpl(irClass.startOffset, irClass.endOffset, context.irBuiltIns.unitType, null, instanceInitializerStatements)
|
||||
.deepCopyWithSymbols(currentScope!!.scope.getLocalDeclarationParent())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
abstract class InitializersLoweringBase(val context: CommonBackendContext) : ClassLoweringPass {
|
||||
protected fun handleDeclaration(irClass: IrClass, declaration: IrDeclaration): IrStatement? = when (declaration) {
|
||||
is IrField -> handleField(irClass, declaration)
|
||||
is IrAnonymousInitializer -> handleAnonymousInitializer(declaration)
|
||||
else -> null
|
||||
}
|
||||
protected fun extractInitializers(irClass: IrClass, filter: (IrDeclaration) -> Boolean) =
|
||||
irClass.declarations.filter(filter).mapNotNull {
|
||||
when (it) {
|
||||
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? {
|
||||
val irFieldInitializer = declaration.initializer?.expression ?: return null
|
||||
private fun handleField(irClass: IrClass, declaration: IrField): IrStatement? =
|
||||
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 =
|
||||
if (!declaration.isStatic) // TODO isStaticField
|
||||
IrGetValueImpl(
|
||||
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)
|
||||
private fun handleAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement =
|
||||
with(declaration) {
|
||||
IrBlockImpl(startOffset, endOffset, context.irBuiltIns.unitType, SYNTHESIZED_INIT_BLOCK, body.statements)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user