[JS IR BE] Commonize JS lowerings

This commit is contained in:
Svyatoslav Kuzmich
2019-08-07 14:16:48 +03:00
parent 7bc739359b
commit 1891fa1bf1
9 changed files with 52 additions and 29 deletions
@@ -340,7 +340,7 @@ private val autoboxingTransformerPhase = makeJsModulePhase(
private val blockDecomposerLoweringPhase = makeCustomJsModulePhase( private val blockDecomposerLoweringPhase = makeCustomJsModulePhase(
{ context, module -> { context, module ->
BlockDecomposerLowering(context).lower(module) JsBlockDecomposerLowering(context).lower(module)
module.patchDeclarationParents() module.patchDeclarationParents()
}, },
name = "BlockDecomposerLowering", name = "BlockDecomposerLowering",
@@ -384,14 +384,14 @@ private val staticMembersLoweringPhase = makeJsModulePhase(
description = "Move static member declarations to top-level" description = "Move static member declarations to top-level"
) )
private val objectDeclarationLoweringPhase = makeJsModulePhase( private val objectDeclarationLoweringPhase = makeCustomJsModulePhase(
::ObjectDeclarationLowering, { context, module -> ObjectDeclarationLowering(context, context.objectToGetInstanceFunction).lower(module) },
name = "ObjectDeclarationLowering", name = "ObjectDeclarationLowering",
description = "Create lazy object instance generator functions" description = "Create lazy object instance generator functions"
) )
private val objectUsageLoweringPhase = makeJsModulePhase( private val objectUsageLoweringPhase = makeCustomJsModulePhase(
::ObjectUsageLowering, { context, module -> ObjectUsageLowering(context, context.objectToGetInstanceFunction).lower(module) },
name = "ObjectUsageLowering", name = "ObjectUsageLowering",
description = "Transform IrGetObjectValue into instance generator call" description = "Transform IrGetObjectValue into instance generator call"
) )
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
class JsSharedVariablesManager(val builtIns: IrBuiltIns, val implicitDeclarationsFile: IrFile) : SharedVariablesManager { class JsSharedVariablesManager(val builtIns: IrBuiltIns, val implicitDeclarationsFile: IrPackageFragment) : SharedVariablesManager {
override fun declareSharedVariable(originalDeclaration: IrVariable): IrVariable { override fun declareSharedVariable(originalDeclaration: IrVariable): IrVariable {
val valueType = originalDeclaration.type val valueType = originalDeclaration.type
@@ -85,7 +85,7 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag
if (actualType.isUnit() && !expectedType.isUnit()) { if (actualType.isUnit() && !expectedType.isUnit()) {
// Don't materialize Unit if value is known to be proper Unit on runtime // Don't materialize Unit if value is known to be proper Unit on runtime
if (!this.isGetUnit()) { if (!this.isGetUnit()) {
val unitValue = JsIrBuilder.buildGetObjectValue(actualType, context.symbolTable.referenceClass(context.builtIns.unit)) val unitValue = JsIrBuilder.buildGetObjectValue(actualType, context.irBuiltIns.unitClass)
return JsIrBuilder.buildComposite(actualType, listOf(this, unitValue)) return JsIrBuilder.buildComposite(actualType, listOf(this, unitValue))
} }
} }
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
import org.jetbrains.kotlin.backend.common.ir.isElseBranch import org.jetbrains.kotlin.backend.common.ir.isElseBranch
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
@@ -21,9 +22,17 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
class BlockDecomposerLowering(context: JsIrBackendContext) : DeclarationContainerLoweringPass { class JsBlockDecomposerLowering(val context: JsIrBackendContext) : AbstractBlockDecomposerLowering(context) {
override fun unreachableExpression(): IrExpression =
JsIrBuilder.buildCall(context.intrinsics.unreachable.symbol, context.irBuiltIns.nothingType)
}
private val decomposerTransformer = BlockDecomposerTransformer(context) abstract class AbstractBlockDecomposerLowering(context: CommonBackendContext) : DeclarationContainerLoweringPass {
// Expression with Nothing type to be inserted in places of unreachable expression
abstract fun unreachableExpression(): IrExpression
private val decomposerTransformer = BlockDecomposerTransformer(context, ::unreachableExpression)
private val nothingType = context.irBuiltIns.nothingType private val nothingType = context.irBuiltIns.nothingType
override fun lower(irDeclarationContainer: IrDeclarationContainer) { override fun lower(irDeclarationContainer: IrDeclarationContainer) {
@@ -80,7 +89,10 @@ class BlockDecomposerLowering(context: JsIrBackendContext) : DeclarationContaine
} }
} }
class BlockDecomposerTransformer(private val context: JsIrBackendContext) : IrElementTransformerVoid() { class BlockDecomposerTransformer(
private val context: CommonBackendContext,
private val unreachableExpression: () -> IrExpression
) : IrElementTransformerVoid() {
private lateinit var function: IrFunction private lateinit var function: IrFunction
private var tmpVarCounter: Int = 0 private var tmpVarCounter: Int = 0
@@ -92,9 +104,8 @@ class BlockDecomposerTransformer(private val context: JsIrBackendContext) : IrEl
private val nothingType = context.irBuiltIns.nothingNType private val nothingType = context.irBuiltIns.nothingNType
private val unitType = context.irBuiltIns.unitType private val unitType = context.irBuiltIns.unitType
private val unitValue get() = JsIrBuilder.buildGetObjectValue(unitType, context.symbolTable.referenceClass(context.builtIns.unit)) private val unitValue get() = JsIrBuilder.buildGetObjectValue(unitType, context.irBuiltIns.unitClass)
private val unreachableFunction = context.intrinsics.unreachable
private val booleanNotSymbol = context.irBuiltIns.booleanNotSymbol private val booleanNotSymbol = context.irBuiltIns.booleanNotSymbol
override fun visitFunction(declaration: IrFunction): IrStatement { override fun visitFunction(declaration: IrFunction): IrStatement {
@@ -429,13 +440,13 @@ class BlockDecomposerTransformer(private val context: JsIrBackendContext) : IrEl
override fun visitSetField(expression: IrSetField) = expression.asExpression(unitValue) override fun visitSetField(expression: IrSetField) = expression.asExpression(unitValue)
override fun visitBreakContinue(jump: IrBreakContinue) = override fun visitBreakContinue(jump: IrBreakContinue) =
jump.asExpression(JsIrBuilder.buildCall(unreachableFunction.symbol, nothingType)) jump.asExpression(unreachableExpression())
override fun visitThrow(expression: IrThrow) = override fun visitThrow(expression: IrThrow) =
expression.asExpression(JsIrBuilder.buildCall(unreachableFunction.symbol, nothingType)) expression.asExpression(unreachableExpression())
override fun visitReturn(expression: IrReturn) = override fun visitReturn(expression: IrReturn) =
expression.asExpression(JsIrBuilder.buildCall(unreachableFunction.symbol, nothingType)) expression.asExpression(unreachableExpression())
override fun visitVariable(declaration: IrVariable) = declaration.asExpression(unitValue) override fun visitVariable(declaration: IrVariable) = declaration.asExpression(unitValue)
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower package org.jetbrains.kotlin.ir.backend.js.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.bridges.FunctionHandle import org.jetbrains.kotlin.backend.common.bridges.FunctionHandle
import org.jetbrains.kotlin.backend.common.bridges.generateBridges import org.jetbrains.kotlin.backend.common.bridges.generateBridges
import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.copyTo
@@ -49,7 +50,7 @@ import org.jetbrains.kotlin.ir.util.*
// fun foo(t: Any?) = foo(t as Int) // Constructed bridge // fun foo(t: Any?) = foo(t as Int) // Constructed bridge
// } // }
// //
class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass { class BridgesConstruction(val context: CommonBackendContext) : ClassLoweringPass {
private val specialBridgeMethods = SpecialBridgeMethods(context) private val specialBridgeMethods = SpecialBridgeMethods(context)
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor
@@ -101,7 +102,7 @@ private fun createEntryAccessorName(enumName: String, enumEntry: IrEnumEntry) =
private fun IrEnumEntry.getType(irClass: IrClass) = (correspondingClass ?: irClass).defaultType private fun IrEnumEntry.getType(irClass: IrClass) = (correspondingClass ?: irClass).defaultType
class EnumClassConstructorLowering(val context: JsIrBackendContext) : DeclarationContainerLoweringPass { class EnumClassConstructorLowering(val context: CommonBackendContext) : DeclarationContainerLoweringPass {
override fun lower(irDeclarationContainer: IrDeclarationContainer) { override fun lower(irDeclarationContainer: IrDeclarationContainer) {
irDeclarationContainer.transformDeclarationsFlat { declaration -> irDeclarationContainer.transformDeclarationsFlat { declaration ->
if (declaration is IrClass && declaration.isEnumClass && if (declaration is IrClass && declaration.isEnumClass &&
@@ -113,7 +114,7 @@ class EnumClassConstructorLowering(val context: JsIrBackendContext) : Declaratio
} }
} }
class EnumClassConstructorTransformer(val context: JsIrBackendContext, private val irClass: IrClass) { class EnumClassConstructorTransformer(val context: CommonBackendContext, private val irClass: IrClass) {
private val builder = context.createIrBuilder(irClass.symbol) private val builder = context.createIrBuilder(irClass.symbol)
private val enumEntries = irClass.declarations.filterIsInstance<IrEnumEntry>() private val enumEntries = irClass.declarations.filterIsInstance<IrEnumEntry>()
private val loweredEnumConstructors = HashMap<IrConstructorSymbol, IrConstructor>() private val loweredEnumConstructors = HashMap<IrConstructorSymbol, IrConstructor>()
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
@@ -19,9 +20,11 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrBlockBody import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetObjectValue import org.jetbrains.kotlin.ir.expressions.IrGetObjectValue
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.types.makeNullable import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
@@ -31,13 +34,16 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
class ObjectDeclarationLowering(val context: JsIrBackendContext) : DeclarationContainerLoweringPass { class ObjectDeclarationLowering(
val context: CommonBackendContext,
val objectToGetInstanceFunction: MutableMap<IrClassSymbol, IrSimpleFunction>
) : DeclarationContainerLoweringPass {
override fun lower(irDeclarationContainer: IrDeclarationContainer) { override fun lower(irDeclarationContainer: IrDeclarationContainer) {
irDeclarationContainer.transformDeclarationsFlat { declaration -> irDeclarationContainer.transformDeclarationsFlat { declaration ->
if (declaration !is IrClass || declaration.kind != ClassKind.OBJECT || declaration.isEffectivelyExternal()) if (declaration !is IrClass || declaration.kind != ClassKind.OBJECT || declaration.isEffectivelyExternal())
return@transformDeclarationsFlat null return@transformDeclarationsFlat null
val getInstanceFun = getOrCreateGetInstanceFunction(context, declaration) val getInstanceFun = getOrCreateGetInstanceFunction(objectToGetInstanceFunction, declaration)
val instanceField = buildField { val instanceField = buildField {
name = Name.identifier(declaration.name.asString() + "_instance") name = Name.identifier(declaration.name.asString() + "_instance")
@@ -70,20 +76,23 @@ class ObjectDeclarationLowering(val context: JsIrBackendContext) : DeclarationCo
} }
} }
class ObjectUsageLowering(val context: JsIrBackendContext) : FileLoweringPass { class ObjectUsageLowering(
val context: CommonBackendContext,
val objectToGetInstanceFunction: MutableMap<IrClassSymbol, IrSimpleFunction>
) : FileLoweringPass {
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid(object : IrElementTransformerVoid() { irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression { override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression {
val obj: IrClass = expression.symbol.owner val obj: IrClass = expression.symbol.owner
if (obj.isEffectivelyExternal()) return expression if (obj.isEffectivelyExternal()) return expression
return JsIrBuilder.buildCall(getOrCreateGetInstanceFunction(context, obj).symbol) return JsIrBuilder.buildCall(getOrCreateGetInstanceFunction(objectToGetInstanceFunction, obj).symbol)
} }
}) })
} }
} }
fun getOrCreateGetInstanceFunction(context: JsIrBackendContext, obj: IrClass) = fun getOrCreateGetInstanceFunction(objectToGetInstanceFunction: MutableMap<IrClassSymbol, IrSimpleFunction>, obj: IrClass) =
context.objectToGetInstanceFunction.getOrPut(obj.symbol) { objectToGetInstanceFunction.getOrPut(obj.symbol) {
JsIrBuilder.buildFunction( JsIrBuilder.buildFunction(
obj.name.asString() + "_getInstance", obj.name.asString() + "_getInstance",
returnType = obj.defaultType, returnType = obj.defaultType,
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.ir.addChild import org.jetbrains.kotlin.backend.common.ir.addChild
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
@@ -17,7 +18,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
// Move static member declarations from classes to top level // Move static member declarations from classes to top level
class StaticMembersLowering(val context: JsIrBackendContext) : FileLoweringPass { class StaticMembersLowering(val context: CommonBackendContext) : FileLoweringPass {
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
val staticDeclarationsInClasses = mutableListOf<IrDeclaration>() val staticDeclarationsInClasses = mutableListOf<IrDeclaration>()
@@ -5,9 +5,9 @@
package org.jetbrains.kotlin.ir.backend.js.lower.inline package org.jetbrains.kotlin.ir.backend.js.lower.inline
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
@@ -69,7 +69,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
* } * }
* *
*/ */
class ReturnableBlockLowering(val context: JsIrBackendContext) : FileLoweringPass { class ReturnableBlockLowering(val context: CommonBackendContext) : FileLoweringPass {
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
irFile.transform(ReturnableBlockTransformer(context), ReturnableBlockLoweringContext(irFile)) irFile.transform(ReturnableBlockTransformer(context), ReturnableBlockLoweringContext(irFile))
} }
@@ -81,7 +81,7 @@ private class ReturnableBlockLoweringContext(val containingDeclaration: IrDeclar
} }
private class ReturnableBlockTransformer( private class ReturnableBlockTransformer(
val context: JsIrBackendContext val context: CommonBackendContext
) : IrElementTransformer<ReturnableBlockLoweringContext> { ) : IrElementTransformer<ReturnableBlockLoweringContext> {
override fun visitReturn(expression: IrReturn, data: ReturnableBlockLoweringContext): IrExpression { override fun visitReturn(expression: IrReturn, data: ReturnableBlockLoweringContext): IrExpression {