[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 =
|
fun getInnerClassOuterThisAccessorName(innerClass: IrClass): Name =
|
||||||
getMangledNameFor("outerThis", innerClass)
|
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.
|
* 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.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
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.DeserializedKlibModuleOrigin
|
||||||
import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin
|
import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin
|
||||||
import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib
|
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.resolve.CleanableBindingContext
|
||||||
import org.jetbrains.kotlin.utils.DFS
|
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(
|
internal fun Context.psiToIr(
|
||||||
symbolTable: SymbolTable,
|
symbolTable: SymbolTable,
|
||||||
isProducingLibrary: Boolean,
|
isProducingLibrary: Boolean,
|
||||||
@@ -61,6 +68,7 @@ internal fun Context.psiToIr(
|
|||||||
moduleDescriptor, symbolTable,
|
moduleDescriptor, symbolTable,
|
||||||
generatorContext.irBuiltIns,
|
generatorContext.irBuiltIns,
|
||||||
DescriptorByIdSignatureFinderImpl(moduleDescriptor, KonanManglerDesc),
|
DescriptorByIdSignatureFinderImpl(moduleDescriptor, KonanManglerDesc),
|
||||||
|
KonanStubGeneratorExtensions
|
||||||
)
|
)
|
||||||
val irBuiltInsOverDescriptors = generatorContext.irBuiltIns as IrBuiltInsOverDescriptors
|
val irBuiltInsOverDescriptors = generatorContext.irBuiltIns as IrBuiltInsOverDescriptors
|
||||||
val functionIrClassFactory: KonanIrAbstractDescriptorBasedFunctionFactory =
|
val functionIrClassFactory: KonanIrAbstractDescriptorBasedFunctionFactory =
|
||||||
|
|||||||
+94
-26
@@ -429,6 +429,35 @@ internal val exportInternalAbiPhase = makeKonanModuleOpPhase(
|
|||||||
context.internalAbi.declare(function, declaration.module)
|
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)
|
module.acceptChildrenVoid(visitor)
|
||||||
}
|
}
|
||||||
@@ -441,8 +470,12 @@ internal val useInternalAbiPhase = makeKonanModuleOpPhase(
|
|||||||
op = { context, module ->
|
op = { context, module ->
|
||||||
val companionObjectAccessors = mutableMapOf<IrClass, IrSimpleFunction>()
|
val companionObjectAccessors = mutableMapOf<IrClass, IrSimpleFunction>()
|
||||||
val outerThisAccessors = mutableMapOf<IrClass, IrSimpleFunction>()
|
val outerThisAccessors = mutableMapOf<IrClass, IrSimpleFunction>()
|
||||||
|
val lateinitPropertyAccessors = mutableMapOf<IrProperty, IrSimpleFunction>()
|
||||||
|
|
||||||
val transformer = object : IrElementTransformerVoid() {
|
val transformer = object : IrElementTransformerVoid() {
|
||||||
override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression {
|
override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression {
|
||||||
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
val irClass = expression.symbol.owner
|
val irClass = expression.symbol.owner
|
||||||
if (!irClass.isCompanion || context.llvmModuleSpecification.containsDeclaration(irClass)) {
|
if (!irClass.isCompanion || context.llvmModuleSpecification.containsDeclaration(irClass)) {
|
||||||
return expression
|
return expression
|
||||||
@@ -466,35 +499,70 @@ internal val useInternalAbiPhase = makeKonanModuleOpPhase(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitGetField(expression: IrGetField): IrExpression {
|
override fun visitGetField(expression: IrGetField): IrExpression {
|
||||||
val field = expression.symbol.owner
|
expression.transformChildrenVoid(this)
|
||||||
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)
|
|
||||||
|
|
||||||
function.addValueParameter {
|
val field = expression.symbol.owner
|
||||||
name = Name.identifier("innerClass")
|
val irClass = field.parentClassOrNull
|
||||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
val property = field.correspondingPropertySymbol?.owner
|
||||||
type = irClass.defaultType
|
|
||||||
|
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(
|
property?.isLateinit == true -> {
|
||||||
expression.startOffset, expression.endOffset,
|
val accessor = lateinitPropertyAccessors.getOrPut(property) {
|
||||||
expression.type, accessor.symbol,
|
context.irFactory.buildFun {
|
||||||
accessor.typeParameters.size, accessor.valueParameters.size
|
name = InternalAbi.getLateinitPropertyFieldAccessorName(property)
|
||||||
).apply {
|
returnType = field.type
|
||||||
putValueArgument(0, expression.receiver)
|
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