Froze enums on creation + tests

This commit is contained in:
Igor Chevdar
2018-03-19 15:48:31 +03:00
parent 1833270dbd
commit 8477f79d58
5 changed files with 72 additions and 18 deletions
@@ -251,6 +251,9 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym
val initInstance = symbolTable.referenceSimpleFunction( val initInstance = symbolTable.referenceSimpleFunction(
context.getInternalFunctions("initInstance").single()) context.getInternalFunctions("initInstance").single())
val freeze = symbolTable.referenceSimpleFunction(
builtInsPackage("konan", "worker").getContributedFunctions(Name.identifier("freeze"), NoLookupLocation.FROM_BACKEND).single())
val getContinuation = symbolTable.referenceSimpleFunction( val getContinuation = symbolTable.referenceSimpleFunction(
context.getInternalFunctions("getContinuation").single()) context.getInternalFunctions("getContinuation").single())
@@ -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.addSimpleDelegatingConstructor
import org.jetbrains.kotlin.backend.common.ir.createArrayOfExpression import org.jetbrains.kotlin.backend.common.ir.createArrayOfExpression
import org.jetbrains.kotlin.backend.common.ir.createSimpleDelegatingConstructorDescriptor 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.*
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.declarations.impl.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol 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.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid 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.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.Variance
internal class EnumSyntheticFunctionsBuilder(val context: Context) { internal class EnumSyntheticFunctionsBuilder(val context: Context) {
fun buildValuesExpression(startOffset: Int, endOffset: Int, 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 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 { private fun createValuesPropertyInitializer(enumEntries: List<IrEnumEntry>): IrAnonymousInitializerImpl {
val startOffset = irClass.startOffset val startOffset = irClass.startOffset
val endOffset = irClass.endOffset val endOffset = irClass.endOffset
val statements = enumEntries val symbol = IrAnonymousInitializerSymbolImpl(loweredEnum.implObject.descriptor)
.sortedBy { it.descriptor.name } val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
.withIndex() return IrAnonymousInitializerImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, symbol).apply {
.map { body = irBuilder.irBlockBody(irClass) {
val instances = IrGetFieldImpl(startOffset, endOffset, val instances = irTemporary(irGetField(irGet(loweredEnum.implObject.thisReceiver!!.symbol), loweredEnum.valuesField.symbol))
loweredEnum.valuesField.symbol, IrGetValueImpl(startOffset, endOffset, loweredEnum.implObject.thisReceiver!!.symbol)) enumEntries
val instance = IrCallImpl(startOffset, endOffset, arrayGetSymbol).apply { .sortedBy { it.descriptor.name }
dispatchReceiver = instances .withIndex()
putValueArgument(0, IrConstImpl(startOffset, endOffset, context.builtIns.intType, IrConstKind.Int, it.index)) .forEach {
} val instance = irCall(arrayGetSymbol).apply {
val initializer = it.value.initializerExpression!! as IrCall dispatchReceiver = irGet(instances.symbol)
IrCallImpl(startOffset, endOffset, initInstanceSymbol).apply { putValueArgument(0, irInt(it.index))
putValueArgument(0, instance) }
putValueArgument(1, initializer) 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 { private fun createSyntheticValuesMethodBody(declaration: IrFunction): IrBody {
+10
View File
@@ -704,6 +704,16 @@ task enum_nested(type: RunKonanTest) {
source = "codegen/enum/nested.kt" 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) { task mangling(type: LinkKonanTest) {
goldValue = goldValue =
"Int direct [1, 2, 3, 4]\n" + "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)
}
+15
View File
@@ -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)
}