PrimaryConstructorLowering

This commit is contained in:
Anton Bannykh
2019-12-25 13:23:54 +03:00
committed by Anton Bannykh
parent 76ff30b86e
commit f6d4ea469c
4 changed files with 54 additions and 21 deletions
@@ -311,6 +311,13 @@ private val primaryConstructorLoweringPhase = makeJsModulePhase(
prerequisite = setOf(enumClassConstructorLoweringPhase)
)
private val delegateToPrimaryConstructorLoweringPhase = makeJsModulePhase(
::DelegateToSyntheticPrimaryConstructor,
name = "DelegateToSyntheticPrimaryConstructor",
description = "Delegates to synthetic primary constructor",
prerequisite = setOf(primaryConstructorLoweringPhase)
)
private val annotationConstructorLowering = makeJsModulePhase(
::AnnotationConstructorLowering,
name = "AnnotationConstructorLowering",
@@ -465,6 +472,7 @@ val jsPhases = namedIrModulePhase(
innerClassConstructorCallsLoweringPhase then
propertiesLoweringPhase then
primaryConstructorLoweringPhase then
delegateToPrimaryConstructorLoweringPhase then
annotationConstructorLowering then
initializersLoweringPhase then
initializersCleanupLoweringPhase then
@@ -17,4 +17,5 @@ class JsMapping : DefaultMapping() {
val secondaryConstructorToFactory = newMapping<IrConstructor, IrSimpleFunction>()
val objectToGetInstanceFunction = newMapping<IrClass, IrSimpleFunction>()
val objectToInstanceField = newMapping<IrClass, IrField>()
val classToSyntheticPrimaryConstructor = newMapping<IrClass, IrConstructor>()
}
@@ -5,47 +5,42 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext
import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.expressions.IrInstanceInitializerCall
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
// Create primary constructor if it doesn't exist
class PrimaryConstructorLowering(context: CommonBackendContext) : ClassLoweringPass {
private val unitType = context.irBuiltIns.unitType
class PrimaryConstructorLowering(context: JsCommonBackendContext) : DeclarationTransformer {
override fun lower(irClass: IrClass) {
val constructors = irClass.declarations.filterIsInstance<IrConstructor>()
private var IrClass.syntheticPrimaryConstructor by context.mapping.classToSyntheticPrimaryConstructor
if (constructors.any { it.isPrimary }) return
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
if (declaration is IrClass) {
val constructors = declaration.declarations.filterIsInstance<IrConstructor>()
val primary = createPrimaryConstructor(irClass)
if (constructors.any { it.isPrimary }) return null
val initializeTransformer = object : IrElementTransformerVoid() {
override fun visitDeclaration(declaration: IrDeclaration) = declaration // optimize visiting
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall) = expression.run {
IrDelegatingConstructorCallImpl(startOffset, endOffset, type, primary.symbol)
}
declaration.syntheticPrimaryConstructor = createPrimaryConstructor(declaration)
}
constructors.forEach { it.transformChildrenVoid(initializeTransformer) }
return null
}
private object SYNTHETIC_PRIMARY_CONSTRUCTOR : IrDeclarationOriginImpl("SYNTHETIC_PRIMARY_CONSTRUCTOR")
private val unitType = context.irBuiltIns.unitType
private fun createPrimaryConstructor(irClass: IrClass): IrConstructor {
val declaration = irClass.addConstructor {
origin = SYNTHETIC_PRIMARY_CONSTRUCTOR
@@ -59,4 +54,25 @@ class PrimaryConstructorLowering(context: CommonBackendContext) : ClassLoweringP
return declaration
}
}
class DelegateToSyntheticPrimaryConstructor(context: JsCommonBackendContext) : BodyLoweringPass {
private var IrClass.syntheticPrimaryConstructor by context.mapping.classToSyntheticPrimaryConstructor
override fun lower(irBody: IrBody, container: IrDeclaration) {
if (container is IrConstructor && !container.isPrimary) {
container.parentAsClass.syntheticPrimaryConstructor?.let { primary ->
val initializeTransformer = object : IrElementTransformerVoid() {
override fun visitDeclaration(declaration: IrDeclaration) = declaration // optimize visiting
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall) = expression.run {
IrDelegatingConstructorCallImpl(startOffset, endOffset, type, primary.symbol)
}
}
irBody.transformChildrenVoid(initializeTransformer)
}
}
}
}
@@ -228,6 +228,13 @@ private val primaryConstructorLoweringPhase = makeWasmModulePhase(
description = "Creates primary constructor if it doesn't exist"
)
private val delegateToPrimaryConstructorLoweringPhase = makeWasmModulePhase(
::DelegateToSyntheticPrimaryConstructor,
name = "DelegateToSyntheticPrimaryConstructor",
description = "Delegates to synthetic primary constructor",
prerequisite = setOf(primaryConstructorLoweringPhase)
)
private val initializersLoweringPhase = makeWasmModulePhase(
::InitializersLowering,
name = "InitializersLowering",
@@ -372,6 +379,7 @@ val wasmPhases = namedIrModulePhase<WasmBackendContext>(
innerClassConstructorCallsLoweringPhase then
propertiesLoweringPhase then
primaryConstructorLoweringPhase then
delegateToPrimaryConstructorLoweringPhase then
initializersLoweringPhase then
initializersCleanupLoweringPhase then
// Common prefix ends