Froze enums on creation + tests
This commit is contained in:
+3
@@ -251,6 +251,9 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym
|
||||
val initInstance = symbolTable.referenceSimpleFunction(
|
||||
context.getInternalFunctions("initInstance").single())
|
||||
|
||||
val freeze = symbolTable.referenceSimpleFunction(
|
||||
builtInsPackage("konan", "worker").getContributedFunctions(Name.identifier("freeze"), NoLookupLocation.FROM_BACKEND).single())
|
||||
|
||||
val getContinuation = symbolTable.referenceSimpleFunction(
|
||||
context.getInternalFunctions("getContinuation").single())
|
||||
|
||||
|
||||
+31
-18
@@ -27,15 +27,19 @@ import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.common.ir.addSimpleDelegatingConstructor
|
||||
import org.jetbrains.kotlin.backend.common.ir.createArrayOfExpression
|
||||
import org.jetbrains.kotlin.backend.common.ir.createSimpleDelegatingConstructorDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
@@ -44,6 +48,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
internal class EnumSyntheticFunctionsBuilder(val context: Context) {
|
||||
fun buildValuesExpression(startOffset: Int, endOffset: Int,
|
||||
@@ -367,29 +372,37 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
private val arrayGetSymbol = context.ir.symbols.array.functions.single { it.descriptor.name == Name.identifier("get") }
|
||||
|
||||
private val genericFreezeSymbol = context.ir.symbols.freeze
|
||||
private val arrayType = context.builtIns.getArrayType(Variance.INVARIANT, irClass.defaultType)
|
||||
|
||||
private fun createValuesPropertyInitializer(enumEntries: List<IrEnumEntry>): IrAnonymousInitializerImpl {
|
||||
val startOffset = irClass.startOffset
|
||||
val endOffset = irClass.endOffset
|
||||
|
||||
val statements = enumEntries
|
||||
.sortedBy { it.descriptor.name }
|
||||
.withIndex()
|
||||
.map {
|
||||
val instances = IrGetFieldImpl(startOffset, endOffset,
|
||||
loweredEnum.valuesField.symbol, IrGetValueImpl(startOffset, endOffset, loweredEnum.implObject.thisReceiver!!.symbol))
|
||||
val instance = IrCallImpl(startOffset, endOffset, arrayGetSymbol).apply {
|
||||
dispatchReceiver = instances
|
||||
putValueArgument(0, IrConstImpl(startOffset, endOffset, context.builtIns.intType, IrConstKind.Int, it.index))
|
||||
}
|
||||
val initializer = it.value.initializerExpression!! as IrCall
|
||||
IrCallImpl(startOffset, endOffset, initInstanceSymbol).apply {
|
||||
putValueArgument(0, instance)
|
||||
putValueArgument(1, initializer)
|
||||
}
|
||||
val symbol = IrAnonymousInitializerSymbolImpl(loweredEnum.implObject.descriptor)
|
||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||
return IrAnonymousInitializerImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, symbol).apply {
|
||||
body = irBuilder.irBlockBody(irClass) {
|
||||
val instances = irTemporary(irGetField(irGet(loweredEnum.implObject.thisReceiver!!.symbol), loweredEnum.valuesField.symbol))
|
||||
enumEntries
|
||||
.sortedBy { it.descriptor.name }
|
||||
.withIndex()
|
||||
.forEach {
|
||||
val instance = irCall(arrayGetSymbol).apply {
|
||||
dispatchReceiver = irGet(instances.symbol)
|
||||
putValueArgument(0, irInt(it.index))
|
||||
}
|
||||
val initializer = it.value.initializerExpression!! as IrCall
|
||||
+irCall(initInstanceSymbol).apply {
|
||||
putValueArgument(0, instance)
|
||||
putValueArgument(1, initializer)
|
||||
}
|
||||
}
|
||||
+irCall(genericFreezeSymbol, listOf(arrayType)).apply {
|
||||
extensionReceiver = irGet(instances.symbol)
|
||||
}
|
||||
return IrAnonymousInitializerImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM,
|
||||
loweredEnum.implObject.descriptor, IrBlockBodyImpl(startOffset, endOffset, statements)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createSyntheticValuesMethodBody(declaration: IrFunction): IrBody {
|
||||
|
||||
@@ -704,6 +704,16 @@ task enum_nested(type: RunKonanTest) {
|
||||
source = "codegen/enum/nested.kt"
|
||||
}
|
||||
|
||||
task enum_isFrozen(type: RunKonanTest) {
|
||||
goldValue = "true\n"
|
||||
source = "codegen/enum/isFrozen.kt"
|
||||
}
|
||||
|
||||
task enum_loop(type: RunKonanTest) {
|
||||
goldValue = "Z\nZ\n"
|
||||
source = "codegen/enum/loop.kt"
|
||||
}
|
||||
|
||||
task mangling(type: LinkKonanTest) {
|
||||
goldValue =
|
||||
"Int direct [1, 2, 3, 4]\n" +
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package codegen.enum.isFrozen
|
||||
|
||||
import kotlin.test.*
|
||||
import konan.worker.*
|
||||
|
||||
enum class Zzz(val zzz: String) {
|
||||
Z1("z1"),
|
||||
Z2("z2")
|
||||
}
|
||||
|
||||
@Test fun runTest() {
|
||||
println(Zzz.Z1.isFrozen)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package codegen.enum.loop
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
enum class Zzz {
|
||||
Z {
|
||||
init {
|
||||
println(Z.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun runTest() {
|
||||
println(Zzz.Z)
|
||||
}
|
||||
Reference in New Issue
Block a user