[JS IR BE] Use static fields instead of variables in enum lowering
This commit is contained in:
+25
-18
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
|||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
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.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
|
import org.jetbrains.kotlin.ir.builders.declarations.buildField
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||||
@@ -36,6 +37,7 @@ import org.jetbrains.kotlin.ir.util.*
|
|||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class EnumUsageLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
class EnumUsageLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
||||||
@@ -412,17 +414,20 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createEnumEntryInstanceVariables() = enumEntries.map { enumEntry ->
|
private fun createEnumEntryInstanceVariables() = enumEntries.map { enumEntry ->
|
||||||
val type = enumEntry.getType(irClass).makeNullable()
|
val result = buildField {
|
||||||
val name = "${enumName}_${enumEntry.name.identifier}_instance"
|
name = Name.identifier("${enumName}_${enumEntry.name.identifier}_instance")
|
||||||
val result = builder.run {
|
type = enumEntry.getType(irClass).makeNullable()
|
||||||
scope.createTmpVariable(irImplicitCast(irNull(), type), name)
|
isStatic = true
|
||||||
|
}.apply {
|
||||||
|
parent = irClass
|
||||||
|
initializer = builder.run { irExprBody(irImplicitCast(irNull(), type)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
enumEntry.correspondingClass?.constructors?.forEach {
|
enumEntry.correspondingClass?.constructors?.forEach {
|
||||||
// Initialize entry instance at the beginning of constructor so it can be used inside constructor body
|
// Initialize entry instance at the beginning of constructor so it can be used inside constructor body
|
||||||
(it.body as? IrBlockBody)?.apply {
|
(it.body as? IrBlockBody)?.apply {
|
||||||
statements.add(0, context.createIrBuilder(it.symbol).run {
|
statements.add(0, context.createIrBuilder(it.symbol).run {
|
||||||
irSetVar(result.symbol, irGet(enumEntry.correspondingClass!!.thisReceiver!!))
|
irSetField(null, result, irGet(enumEntry.correspondingClass!!.thisReceiver!!))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -449,37 +454,39 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
|
|||||||
|
|
||||||
private fun createGetEntryInstanceFuns(
|
private fun createGetEntryInstanceFuns(
|
||||||
initEntryInstancesFun: IrSimpleFunction,
|
initEntryInstancesFun: IrSimpleFunction,
|
||||||
entryInstances: List<IrVariable>
|
entryInstances: List<IrField>
|
||||||
) = enumEntries.mapIndexed { index, enumEntry ->
|
) = enumEntries.mapIndexed { index, enumEntry ->
|
||||||
context.enumEntryToGetInstanceFunction.getOrPut(enumEntry.symbol) {
|
context.enumEntryToGetInstanceFunction.getOrPut(enumEntry.symbol) {
|
||||||
buildFunction(createEntryAccessorName(enumName, enumEntry), enumEntry.getType(irClass))
|
buildFunction(createEntryAccessorName(enumName, enumEntry), enumEntry.getType(irClass))
|
||||||
}.apply {
|
}.apply {
|
||||||
body = context.createIrBuilder(symbol).irBlockBody(this) {
|
body = context.createIrBuilder(symbol).irBlockBody(this) {
|
||||||
+irCall(initEntryInstancesFun)
|
+irCall(initEntryInstancesFun)
|
||||||
+irReturn(irGet(entryInstances[index]))
|
+irReturn(irGetField(null, entryInstances[index]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createInitEntryInstancesFun(
|
private fun createInitEntryInstancesFun(
|
||||||
entryInstancesInitializedVar: IrVariable,
|
entryInstancesInitializedField: IrField,
|
||||||
entryInstances: List<IrVariable>
|
entryInstances: List<IrField>
|
||||||
) = buildFunction("${enumName}_initEntries") {
|
) = buildFunction("${enumName}_initEntries") {
|
||||||
+irIfThen(irGet(entryInstancesInitializedVar), irReturnUnit())
|
+irIfThen(irGetField(null, entryInstancesInitializedField), irReturnUnit())
|
||||||
+irSetVar(entryInstancesInitializedVar.symbol, irBoolean(true))
|
+irSetField(null, entryInstancesInitializedField, irBoolean(true))
|
||||||
for ((entry, instanceVar) in enumEntries.zip(entryInstances)) {
|
for ((entry, instanceField) in enumEntries.zip(entryInstances)) {
|
||||||
+irSetVar(instanceVar.symbol, entry.initializerExpression!!)
|
+irSetField(null, instanceField, entry.initializerExpression!!)
|
||||||
}
|
}
|
||||||
}.also {
|
}.also {
|
||||||
// entry.initializerExpression can have local declarations
|
// entry.initializerExpression can have local declarations
|
||||||
it.acceptVoid(PatchDeclarationParentsVisitor(irClass))
|
it.acceptVoid(PatchDeclarationParentsVisitor(irClass))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createEntryInstancesInitializedVar(): IrVariable {
|
private fun createEntryInstancesInitializedVar(): IrField = buildField {
|
||||||
return builder.scope.createTemporaryVariable(
|
name = Name.identifier("${enumName}_entriesInitialized")
|
||||||
builder.irBoolean(false),
|
type = context.irBuiltIns.booleanType
|
||||||
"${enumName}_entriesInitialized"
|
isStatic = true
|
||||||
)
|
}.apply {
|
||||||
|
parent = irClass
|
||||||
|
initializer = builder.run { irExprBody(irBoolean(false)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-4
@@ -38,11 +38,10 @@ class StaticMembersLowering(val context: JsIrBackendContext) : FileLoweringPass
|
|||||||
super.visitSimpleFunction(declaration)
|
super.visitSimpleFunction(declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitVariable(declaration: IrVariable) {
|
override fun visitField(declaration: IrField) {
|
||||||
// TODO: Don't generate variables inside classes
|
if (declaration.parent is IrClass && declaration.isStatic)
|
||||||
if (declaration.parent is IrClass)
|
|
||||||
staticDeclarationsInClasses.add(declaration)
|
staticDeclarationsInClasses.add(declaration)
|
||||||
super.visitVariable(declaration)
|
super.visitField(declaration)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ fun IrBuilderWithScope.irGetField(receiver: IrExpression?, field: IrField) =
|
|||||||
IrGetFieldImpl(startOffset, endOffset, field.symbol, field.type, receiver)
|
IrGetFieldImpl(startOffset, endOffset, field.symbol, field.type, receiver)
|
||||||
|
|
||||||
fun IrBuilderWithScope.irSetField(receiver: IrExpression?, field: IrField, value: IrExpression) =
|
fun IrBuilderWithScope.irSetField(receiver: IrExpression?, field: IrField, value: IrExpression) =
|
||||||
IrSetFieldImpl(startOffset, endOffset, field.symbol, receiver, value, field.type)
|
IrSetFieldImpl(startOffset, endOffset, field.symbol, receiver, value, context.irBuiltIns.unitType)
|
||||||
|
|
||||||
fun IrBuilderWithScope.irGetObjectValue(type: IrType, classSymbol: IrClassSymbol) =
|
fun IrBuilderWithScope.irGetObjectValue(type: IrType, classSymbol: IrClassSymbol) =
|
||||||
IrGetObjectValueImpl(startOffset, endOffset, type, classSymbol)
|
IrGetObjectValueImpl(startOffset, endOffset, type, classSymbol)
|
||||||
|
|||||||
Reference in New Issue
Block a user