Compare commits

...

5 Commits

Author SHA1 Message Date
Leonid Startsev
5804979624 ~revert changes connected to generation of synthetic backing fields 2020-11-24 16:06:32 +03:00
Leonid Startsev
bf7bd8c7ad ~rebase fixup 2020-11-19 18:21:25 +03:00
Leonid Startsev
32664f0abf Correctly create IrProperty and IrField when they were not created
by SyntheticDeclarationGenerator.

Do not use symbol table because 'declare' API is not available in plugins.
2020-11-19 17:11:36 +03:00
Leonid Startsev
5d12825329 Add backing field handling to SyntheticDeclarationsGenerator
so field symbols won't be unbound.
2020-11-19 17:09:29 +03:00
Leonid Startsev
569914236b Directly search in IrClass for declarations to fill bodies with plugin
because some other compiler plugins (Compose) copy/rewrite IR declarations
completely, and in the end, functions that are present in the final IR tree
do not have bodies.
2020-11-19 17:01:45 +03:00
5 changed files with 56 additions and 70 deletions

View File

@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.util

View File

@@ -8,6 +8,7 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.common
import org.jetbrains.kotlin.backend.common.CodegenUtil.getMemberToGenerate
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationDescriptorSerializerPlugin
@@ -69,12 +70,13 @@ abstract class SerializerCodegen(
serializerDescriptor::checkSerializableClassPropertyResult
) { true }
val localSerializersFieldsDescriptors: List<PropertyDescriptor> = findLocalSerializersFieldDescriptors()
lateinit var localSerializersFieldsDescriptors: List<Pair<PropertyDescriptor, IrProperty>>
protected set
// Can be false if user specified inheritance from KSerializer explicitly
protected val isGeneratedSerializer = serializerDescriptor.typeConstructor.supertypes.any(::isGeneratedKSerializer)
private fun findLocalSerializersFieldDescriptors(): List<PropertyDescriptor> {
protected fun findLocalSerializersFieldDescriptors(): List<PropertyDescriptor> {
val count = serializableDescriptor.declaredTypeParameters.size
if (count == 0) return emptyList()
val propNames = (0 until count).map { "${SerialEntityNames.typeArgPrefix}$it" }

View File

@@ -15,8 +15,7 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
@@ -42,10 +41,12 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.*
interface IrBuilderExtension {
val compilerContext: SerializationPluginContext
private inline fun <reified T : IrDeclaration> IrClass.searchForDeclaration(descriptor: DeclarationDescriptor): T? {
return declarations.singleOrNull { it.descriptor == descriptor } as? T
}
fun IrClass.contributeFunction(descriptor: FunctionDescriptor, bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit) {
val functionSymbol = compilerContext.symbolTable.referenceSimpleFunction(descriptor)
assert(functionSymbol.isBound)
val f: IrSimpleFunction = functionSymbol.owner
val f: IrSimpleFunction = searchForDeclaration(descriptor) ?: compilerContext.symbolTable.referenceSimpleFunction(descriptor).owner
// TODO: default parameters
f.body = DeclarationIrBuilder(compilerContext, f.symbol, this.startOffset, this.endOffset).irBlockBody(
this.startOffset,
@@ -59,11 +60,7 @@ interface IrBuilderExtension {
overwriteValueParameters: Boolean = false,
bodyGen: IrBlockBodyBuilder.(IrConstructor) -> Unit
) {
val ctorSymbol = compilerContext.symbolTable.referenceConstructor(descriptor)
assert(ctorSymbol.isBound)
val c = ctorSymbol.owner
val c: IrConstructor = searchForDeclaration(descriptor) ?: compilerContext.symbolTable.referenceConstructor(descriptor).owner
c.body = DeclarationIrBuilder(compilerContext, c.symbol, this.startOffset, this.endOffset).irBlockBody(
this.startOffset,
this.endOffset
@@ -94,7 +91,7 @@ interface IrBuilderExtension {
irInvoke(
dispatchReceiver,
callee,
*valueArguments.toTypedArray(),
args = valueArguments.toTypedArray(),
typeHint = returnTypeHint
).also { call -> typeArguments.forEachIndexed(call::putTypeArgument) }
@@ -226,16 +223,12 @@ interface IrBuilderExtension {
fun generateSimplePropertyWithBackingField(
propertyDescriptor: PropertyDescriptor,
propertyParent: IrClass,
declare: Boolean,
fieldName: Name = propertyDescriptor.name,
): IrProperty {
val irPropertySymbol = compilerContext.symbolTable.referenceProperty(propertyDescriptor)
assert(irPropertySymbol.isBound || declare)
if (!irPropertySymbol.isBound) {
val irProperty = propertyParent.searchForDeclaration<IrProperty>(propertyDescriptor) ?: run {
with(propertyDescriptor) {
propertyParent.factory.createProperty(
propertyParent.startOffset, propertyParent.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, irPropertySymbol,
propertyParent.startOffset, propertyParent.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrPropertySymbolImpl(propertyDescriptor),
name, visibility, modality, isVar, isConst, isLateInit, isDelegated, isExternal
).also {
it.parent = propertyParent
@@ -243,50 +236,54 @@ interface IrBuilderExtension {
}
}
}
val irProperty = irPropertySymbol.owner
irProperty.backingField = generatePropertyBackingField(propertyDescriptor, irProperty, fieldName).apply {
parent = propertyParent
correspondingPropertySymbol = irPropertySymbol
}
propertyParent.generatePropertyBackingFieldIfNeeded(propertyDescriptor, irProperty, fieldName)
val fieldSymbol = irProperty.backingField!!.symbol
irProperty.getter = propertyDescriptor.getter?.let { generatePropertyAccessor(irProperty, it, fieldSymbol, declare) }
?.apply { parent = propertyParent }
irProperty.setter = propertyDescriptor.setter?.let { generatePropertyAccessor(irProperty, it, fieldSymbol, declare) }
?.apply { parent = propertyParent }
irProperty.getter = propertyDescriptor.getter?.let {
propertyParent.generatePropertyAccessor(propertyDescriptor, irProperty, it, fieldSymbol, isGetter = true)
}?.apply { parent = propertyParent }
irProperty.setter = propertyDescriptor.setter?.let {
propertyParent.generatePropertyAccessor(propertyDescriptor, irProperty, it, fieldSymbol, isGetter = false)
}?.apply { parent = propertyParent }
return irProperty
}
private fun generatePropertyBackingField(
descriptor: PropertyDescriptor,
private fun IrClass.generatePropertyBackingFieldIfNeeded(
propertyDescriptor: PropertyDescriptor,
originProperty: IrProperty,
name: Name,
): IrField {
val fieldSymbol = compilerContext.symbolTable.referenceField(descriptor)
if (fieldSymbol.isBound) return fieldSymbol.owner
) {
if (originProperty.backingField != null) return
return with(descriptor) {
val field = with(propertyDescriptor) {
// TODO: type parameters
originProperty.factory.createField(
originProperty.startOffset, originProperty.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, fieldSymbol, name, type.toIrType(),
originProperty.startOffset, originProperty.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrFieldSymbolImpl(propertyDescriptor), name, type.toIrType(),
visibility, !isVar, isEffectivelyExternal(), dispatchReceiverParameter == null
)
}
field.apply {
parent = this@generatePropertyBackingFieldIfNeeded
correspondingPropertySymbol = originProperty.symbol
}
originProperty.backingField = field
}
private fun generatePropertyAccessor(
private fun IrClass.generatePropertyAccessor(
propertyDescriptor: PropertyDescriptor,
property: IrProperty,
descriptor: PropertyAccessorDescriptor,
fieldSymbol: IrFieldSymbol,
declare: Boolean
isGetter: Boolean,
): IrSimpleFunction {
val symbol = compilerContext.symbolTable.referenceSimpleFunction(descriptor)
assert(symbol.isBound || declare)
if (!symbol.isBound) {
val irAccessor: IrSimpleFunction = when (isGetter) {
true -> searchForDeclaration<IrProperty>(propertyDescriptor)?.getter
false -> searchForDeclaration<IrProperty>(propertyDescriptor)?.setter
} ?: run {
with(descriptor) {
property.factory.createFunction(
fieldSymbol.owner.startOffset, fieldSymbol.owner.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, symbol,
fieldSymbol.owner.startOffset, fieldSymbol.owner.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrSimpleFunctionSymbolImpl(descriptor),
name, visibility, modality, returnType!!.toIrType(),
isInline, isExternal, isTailrec, isSuspend, isOperator, isInfix, isExpect
)
@@ -298,11 +295,9 @@ interface IrBuilderExtension {
}
}
val irAccessor = symbol.owner
irAccessor.body = when (descriptor) {
is PropertyGetterDescriptor -> generateDefaultGetterBody(descriptor, irAccessor)
is PropertySetterDescriptor -> generateDefaultSetterBody(descriptor, irAccessor)
else -> throw AssertionError("Should be getter or setter: $descriptor")
irAccessor.body = when (isGetter) {
true -> generateDefaultGetterBody(descriptor as PropertyGetterDescriptor, irAccessor)
false -> generateDefaultSetterBody(descriptor as PropertySetterDescriptor, irAccessor)
}
return irAccessor
@@ -557,8 +552,8 @@ interface IrBuilderExtension {
kType,
genericIndex
) { it, _ ->
val prop = enclosingGenerator.localSerializersFieldsDescriptors[it]
irGetField(irGet(dispatchReceiverParameter), compilerContext.symbolTable.referenceField(prop).owner)
val (prop, ir) = enclosingGenerator.localSerializersFieldsDescriptors[it]
irGetField(irGet(dispatchReceiverParameter), ir.backingField!!)
}
fun IrBuilderWithScope.serializerInstance(

View File

@@ -65,7 +65,7 @@ class SerialInfoImplJvmIrGenerator(
ctor.body = ctorBody
for (property in properties) {
generateSimplePropertyWithBackingField(property.descriptor, irClass, true, Name.identifier("_" + property.name.asString()))
generateSimplePropertyWithBackingField(property.descriptor, irClass, Name.identifier("_" + property.name.asString()))
val getter = property.getter!!
getter.origin = SERIALIZABLE_SYNTHETIC_ORIGIN

View File

@@ -65,11 +65,11 @@ open class SerializerIrGenerator(
// how to (auto)create backing field and getter/setter?
compilerContext.symbolTable.withReferenceScope(irClass.descriptor) {
prop = generateSimplePropertyWithBackingField(desc, irClass, false)
prop = generateSimplePropertyWithBackingField(desc, irClass)
// TODO: Do not use descriptors here
localSerializersFieldsDescriptors.forEach {
generateSimplePropertyWithBackingField(it, irClass, true)
localSerializersFieldsDescriptors = findLocalSerializersFieldDescriptors().map { it ->
it to generateSimplePropertyWithBackingField(it, irClass)
}
}
@@ -195,11 +195,11 @@ open class SerializerIrGenerator(
// store type arguments serializers in fields
val thisAsReceiverParameter = irClass.thisReceiver!!
ctor.valueParameters.forEachIndexed { index, param ->
val localSerial = compilerContext.symbolTable.referenceField(localSerializersFieldsDescriptors[index])
val localSerial = localSerializersFieldsDescriptors[index].second.backingField!!
+irSetField(generateReceiverExpressionForFieldAccess(
thisAsReceiverParameter.symbol,
localSerializersFieldsDescriptors[index]
), localSerial.owner, irGet(param))
localSerializersFieldsDescriptors[index].first
), localSerial, irGet(param))
}
@@ -221,7 +221,7 @@ open class SerializerIrGenerator(
val typeParams = serializableDescriptor.declaredTypeParameters.mapIndexed { idx, _ ->
irGetField(
irGet(irFun.dispatchReceiverParameter!!),
compilerContext.symbolTable.referenceField(localSerializersFieldsDescriptors[idx]).owner
localSerializersFieldsDescriptors[idx].second.backingField!!
)
}
val kSerType = ((irFun.returnType as IrSimpleType).arguments.first() as IrTypeProjection).type