[K/N][IR] Supported lateinit properties in per-file caches
This commit is contained in:
+3
@@ -89,6 +89,9 @@ internal class InternalAbi(private val context: Context) {
|
||||
fun getInnerClassOuterThisAccessorName(innerClass: IrClass): Name =
|
||||
getMangledNameFor("outerThis", innerClass)
|
||||
|
||||
fun getLateinitPropertyFieldAccessorName(property: IrProperty): Name =
|
||||
getMangledNameFor("${property.name}_field", property.parent)
|
||||
|
||||
/**
|
||||
* Generate name for declaration that will be a part of internal ABI.
|
||||
*/
|
||||
|
||||
+8
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.backend.konan.serialization.*
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin
|
||||
import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin
|
||||
import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib
|
||||
@@ -34,6 +35,12 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.CleanableBindingContext
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
|
||||
object KonanStubGeneratorExtensions : StubGeneratorExtensions() {
|
||||
override fun isPropertyWithPlatformField(descriptor: PropertyDescriptor): Boolean {
|
||||
return super.isPropertyWithPlatformField(descriptor) || descriptor.isLateInit
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Context.psiToIr(
|
||||
symbolTable: SymbolTable,
|
||||
isProducingLibrary: Boolean,
|
||||
@@ -61,6 +68,7 @@ internal fun Context.psiToIr(
|
||||
moduleDescriptor, symbolTable,
|
||||
generatorContext.irBuiltIns,
|
||||
DescriptorByIdSignatureFinderImpl(moduleDescriptor, KonanManglerDesc),
|
||||
KonanStubGeneratorExtensions
|
||||
)
|
||||
val irBuiltInsOverDescriptors = generatorContext.irBuiltIns as IrBuiltInsOverDescriptors
|
||||
val functionIrClassFactory: KonanIrAbstractDescriptorBasedFunctionFactory =
|
||||
|
||||
+94
-26
@@ -429,6 +429,35 @@ internal val exportInternalAbiPhase = makeKonanModuleOpPhase(
|
||||
context.internalAbi.declare(function, declaration.module)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitProperty(declaration: IrProperty) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
|
||||
if (!declaration.isLateinit || declaration.isFakeOverride
|
||||
|| DescriptorVisibilities.isPrivate(declaration.visibility) || declaration.isLocal)
|
||||
return
|
||||
|
||||
val backingField = declaration.backingField ?: error("Lateinit property ${declaration.render()} should have a backing field")
|
||||
val function = context.irFactory.buildFun {
|
||||
name = InternalAbi.getLateinitPropertyFieldAccessorName(declaration)
|
||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||
returnType = backingField.type
|
||||
}
|
||||
val ownerClass = declaration.parentClassOrNull
|
||||
if (ownerClass != null)
|
||||
function.addValueParameter {
|
||||
name = Name.identifier("owner")
|
||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||
type = ownerClass.defaultType
|
||||
}
|
||||
|
||||
context.createIrBuilder(function.symbol).apply {
|
||||
function.body = irBlockBody {
|
||||
+irReturn(irGetField(ownerClass?.let { irGet(function.valueParameters[0]) }, backingField))
|
||||
}
|
||||
}
|
||||
context.internalAbi.declare(function, declaration.module)
|
||||
}
|
||||
}
|
||||
module.acceptChildrenVoid(visitor)
|
||||
}
|
||||
@@ -441,8 +470,12 @@ internal val useInternalAbiPhase = makeKonanModuleOpPhase(
|
||||
op = { context, module ->
|
||||
val companionObjectAccessors = mutableMapOf<IrClass, IrSimpleFunction>()
|
||||
val outerThisAccessors = mutableMapOf<IrClass, IrSimpleFunction>()
|
||||
val lateinitPropertyAccessors = mutableMapOf<IrProperty, IrSimpleFunction>()
|
||||
|
||||
val transformer = object : IrElementTransformerVoid() {
|
||||
override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
val irClass = expression.symbol.owner
|
||||
if (!irClass.isCompanion || context.llvmModuleSpecification.containsDeclaration(irClass)) {
|
||||
return expression
|
||||
@@ -466,35 +499,70 @@ internal val useInternalAbiPhase = makeKonanModuleOpPhase(
|
||||
}
|
||||
|
||||
override fun visitGetField(expression: IrGetField): IrExpression {
|
||||
val field = expression.symbol.owner
|
||||
val irClass = field.parentClassOrNull ?: return expression
|
||||
if (!irClass.isInner || context.llvmModuleSpecification.containsDeclaration(irClass)
|
||||
|| context.specialDeclarationsFactory.getOuterThisField(irClass) != field
|
||||
) {
|
||||
return expression
|
||||
}
|
||||
val accessor = outerThisAccessors.getOrPut(irClass) {
|
||||
context.irFactory.buildFun {
|
||||
name = InternalAbi.getInnerClassOuterThisAccessorName(irClass)
|
||||
returnType = irClass.parentAsClass.defaultType
|
||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||
isExternal = true
|
||||
}.also { function ->
|
||||
context.internalAbi.reference(function, irClass.module)
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
function.addValueParameter {
|
||||
name = Name.identifier("innerClass")
|
||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||
type = irClass.defaultType
|
||||
val field = expression.symbol.owner
|
||||
val irClass = field.parentClassOrNull
|
||||
val property = field.correspondingPropertySymbol?.owner
|
||||
|
||||
return when {
|
||||
context.llvmModuleSpecification.containsDeclaration(field) -> expression
|
||||
|
||||
irClass?.isInner == true && context.specialDeclarationsFactory.getOuterThisField(irClass) == field -> {
|
||||
val accessor = outerThisAccessors.getOrPut(irClass) {
|
||||
context.irFactory.buildFun {
|
||||
name = InternalAbi.getInnerClassOuterThisAccessorName(irClass)
|
||||
returnType = irClass.parentAsClass.defaultType
|
||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||
isExternal = true
|
||||
}.also { function ->
|
||||
context.internalAbi.reference(function, irClass.module)
|
||||
|
||||
function.addValueParameter {
|
||||
name = Name.identifier("innerClass")
|
||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||
type = irClass.defaultType
|
||||
}
|
||||
}
|
||||
}
|
||||
return IrCallImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type, accessor.symbol,
|
||||
accessor.typeParameters.size, accessor.valueParameters.size
|
||||
).apply {
|
||||
putValueArgument(0, expression.receiver)
|
||||
}
|
||||
}
|
||||
}
|
||||
return IrCallImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type, accessor.symbol,
|
||||
accessor.typeParameters.size, accessor.valueParameters.size
|
||||
).apply {
|
||||
putValueArgument(0, expression.receiver)
|
||||
|
||||
property?.isLateinit == true -> {
|
||||
val accessor = lateinitPropertyAccessors.getOrPut(property) {
|
||||
context.irFactory.buildFun {
|
||||
name = InternalAbi.getLateinitPropertyFieldAccessorName(property)
|
||||
returnType = field.type
|
||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||
isExternal = true
|
||||
}.also { function ->
|
||||
context.internalAbi.reference(function, property.module)
|
||||
|
||||
if (irClass != null)
|
||||
function.addValueParameter {
|
||||
name = Name.identifier("owner")
|
||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||
type = irClass.defaultType
|
||||
}
|
||||
}
|
||||
}
|
||||
return IrCallImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type, accessor.symbol,
|
||||
accessor.typeParameters.size, accessor.valueParameters.size
|
||||
).apply {
|
||||
if (irClass != null)
|
||||
putValueArgument(0, expression.receiver)
|
||||
}
|
||||
}
|
||||
|
||||
else -> expression
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user