From f6d4ea469c530cf105165ee6c729241a5f64dc1d Mon Sep 17 00:00:00 2001 From: Anton Bannykh Date: Wed, 25 Dec 2019 13:23:54 +0300 Subject: [PATCH] PrimaryConstructorLowering --- .../kotlin/ir/backend/js/JsLoweringPhases.kt | 8 +++ .../kotlin/ir/backend/js/JsMapping.kt | 1 + .../js/lower/PrimaryConstructorLowering.kt | 58 ++++++++++++------- .../kotlin/backend/wasm/WasmLoweringPhases.kt | 8 +++ 4 files changed, 54 insertions(+), 21 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt index ecaa5b9215b..ed0cbf9e693 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt @@ -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 diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsMapping.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsMapping.kt index 9b38a24316f..55c80833b9f 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsMapping.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsMapping.kt @@ -17,4 +17,5 @@ class JsMapping : DefaultMapping() { val secondaryConstructorToFactory = newMapping() val objectToGetInstanceFunction = newMapping() val objectToInstanceField = newMapping() + val classToSyntheticPrimaryConstructor = newMapping() } \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/PrimaryConstructorLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/PrimaryConstructorLowering.kt index aea662b9122..be46d0bbd64 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/PrimaryConstructorLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/PrimaryConstructorLowering.kt @@ -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() + private var IrClass.syntheticPrimaryConstructor by context.mapping.classToSyntheticPrimaryConstructor - if (constructors.any { it.isPrimary }) return + override fun transformFlat(declaration: IrDeclaration): List? { + if (declaration is IrClass) { + val constructors = declaration.declarations.filterIsInstance() - 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) + } + } + } } \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt index e4672aaff10..10fbf975875 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt @@ -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( innerClassConstructorCallsLoweringPhase then propertiesLoweringPhase then primaryConstructorLoweringPhase then + delegateToPrimaryConstructorLoweringPhase then initializersLoweringPhase then initializersCleanupLoweringPhase then // Common prefix ends