Insert correct offsets in a lot of places in IR
Use correct type arguments when invoking a generic functions Fix missing parent in initializer
This commit is contained in:
+52
-35
@@ -6,10 +6,10 @@
|
||||
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||
import org.jetbrains.kotlin.backend.common.lower.at
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl
|
||||
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.types.KotlinTypeFactory
|
||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializerOrContext
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.contextSerializerId
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId
|
||||
@@ -68,32 +69,25 @@ interface IrBuilderExtension {
|
||||
f.parent = this
|
||||
f.returnType = descriptor.returnType!!.toIrType()
|
||||
if (!fromStubs) f.createParameterDeclarations(this.thisReceiver)
|
||||
f.body = compilerContext.createIrBuilder(f.symbol).irBlockBody { bodyGen(f) }
|
||||
f.body = compilerContext.createIrBuilder(f.symbol).at(this).irBlockBody(this.startOffset, this.endOffset) { bodyGen(f) }
|
||||
this.addMember(f)
|
||||
}
|
||||
|
||||
fun IrClass.contributeCtor(descriptor: ClassConstructorDescriptor, bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit) {
|
||||
val c = compilerContext.externalSymbols.referenceConstructor(descriptor).owner
|
||||
c.parent = this
|
||||
c.returnType = descriptor.returnType.toIrType()
|
||||
c.body = compilerContext.createIrBuilder(c.symbol).irBlockBody { bodyGen(c) }
|
||||
this.addMember(c)
|
||||
}
|
||||
|
||||
fun IrClass.contributeConstructor(
|
||||
descriptor: ClassConstructorDescriptor,
|
||||
fromStubs: Boolean = false,
|
||||
bodyGen: IrBlockBodyBuilder.(IrConstructor) -> Unit
|
||||
) {
|
||||
val c = compilerContext.localSymbolTable.declareConstructor(
|
||||
val c = if (!fromStubs) compilerContext.localSymbolTable.declareConstructor(
|
||||
this.startOffset,
|
||||
this.endOffset,
|
||||
SERIALIZABLE_PLUGIN_ORIGIN,
|
||||
descriptor
|
||||
)
|
||||
) else compilerContext.externalSymbols.referenceConstructor(descriptor).owner
|
||||
c.parent = this
|
||||
c.returnType = descriptor.returnType.toIrType()
|
||||
c.createParameterDeclarations()
|
||||
c.body = compilerContext.createIrBuilder(c.symbol).irBlockBody { bodyGen(c) }
|
||||
if (!fromStubs) c.createParameterDeclarations()
|
||||
c.body = compilerContext.createIrBuilder(c.symbol).at(this).irBlockBody(this.startOffset, this.endOffset) { bodyGen(c) }
|
||||
this.addMember(c)
|
||||
}
|
||||
|
||||
@@ -109,6 +103,19 @@ interface IrBuilderExtension {
|
||||
return call
|
||||
}
|
||||
|
||||
fun IrBuilderWithScope.irInvoke(
|
||||
dispatchReceiver: IrExpression? = null,
|
||||
callee: IrFunctionSymbol,
|
||||
typeArguments: List<IrType?>,
|
||||
valueArguments: List<IrExpression>,
|
||||
returnTypeHint: IrType? = null
|
||||
): IrCall = irInvoke(
|
||||
dispatchReceiver,
|
||||
callee,
|
||||
args = *valueArguments.toTypedArray(),
|
||||
typeHint = returnTypeHint
|
||||
).also { call -> typeArguments.forEachIndexed(call::putTypeArgument) }
|
||||
|
||||
fun IrBuilderWithScope.createArrayOfExpression(
|
||||
arrayElementType: IrType,
|
||||
arrayElements: List<IrExpression>
|
||||
@@ -221,12 +228,13 @@ interface IrBuilderExtension {
|
||||
propertyParent: IrClass
|
||||
): IrProperty {
|
||||
val irProperty = IrPropertyImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
propertyParent.startOffset, propertyParent.endOffset,
|
||||
SERIALIZABLE_PLUGIN_ORIGIN, false,
|
||||
propertyDescriptor
|
||||
)
|
||||
irProperty.parent = propertyParent
|
||||
irProperty.backingField = generatePropertyBackingField(propertyDescriptor).apply { parent = propertyParent }
|
||||
irProperty.backingField =
|
||||
generatePropertyBackingField(propertyDescriptor, irProperty).apply { parent = propertyParent }
|
||||
val fieldSymbol = irProperty.backingField!!.symbol
|
||||
irProperty.getter = propertyDescriptor.getter?.let { generatePropertyAccessor(it, fieldSymbol, ownerSymbol) }
|
||||
?.apply { parent = propertyParent }
|
||||
@@ -235,10 +243,13 @@ interface IrBuilderExtension {
|
||||
return irProperty
|
||||
}
|
||||
|
||||
fun generatePropertyBackingField(propertyDescriptor: PropertyDescriptor): IrField {
|
||||
private fun generatePropertyBackingField(
|
||||
propertyDescriptor: PropertyDescriptor,
|
||||
originProperty: IrProperty
|
||||
): IrField {
|
||||
return compilerContext.localSymbolTable.declareField(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
originProperty.startOffset,
|
||||
originProperty.endOffset,
|
||||
SERIALIZABLE_PLUGIN_ORIGIN,
|
||||
propertyDescriptor,
|
||||
propertyDescriptor.type.toIrType()
|
||||
@@ -271,16 +282,18 @@ interface IrBuilderExtension {
|
||||
): IrBlockBody {
|
||||
val property = getter.correspondingProperty
|
||||
|
||||
val irBody = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
|
||||
val startOffset = irAccessor.startOffset
|
||||
val endOffset = irAccessor.endOffset
|
||||
val irBody = IrBlockBodyImpl(startOffset, endOffset)
|
||||
|
||||
val receiver = generateReceiverExpressionForFieldAccess(ownerSymbol, property)
|
||||
|
||||
irBody.statements.add(
|
||||
IrReturnImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, compilerContext.irBuiltIns.nothingType,
|
||||
startOffset, endOffset, compilerContext.irBuiltIns.nothingType,
|
||||
irAccessor.symbol,
|
||||
IrGetFieldImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
startOffset, endOffset,
|
||||
compilerContext.localSymbolTable.referenceField(property),
|
||||
property.type.toIrType(),
|
||||
receiver
|
||||
@@ -297,8 +310,8 @@ interface IrBuilderExtension {
|
||||
): IrBlockBody {
|
||||
val property = setter.correspondingProperty
|
||||
|
||||
val startOffset = UNDEFINED_OFFSET
|
||||
val endOffset = UNDEFINED_OFFSET
|
||||
val startOffset = irAccessor.startOffset
|
||||
val endOffset = irAccessor.endOffset
|
||||
val irBody = IrBlockBodyImpl(startOffset, endOffset)
|
||||
|
||||
val receiver = generateReceiverExpressionForFieldAccess(ownerSymbol, property)
|
||||
@@ -306,7 +319,7 @@ interface IrBuilderExtension {
|
||||
val irValueParameter = irAccessor.valueParameters.single()
|
||||
irBody.statements.add(
|
||||
IrSetFieldImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
startOffset, endOffset,
|
||||
compilerContext.localSymbolTable.referenceField(property),
|
||||
receiver,
|
||||
IrGetValueImpl(startOffset, endOffset, irValueParameter.type, irValueParameter.symbol),
|
||||
@@ -324,7 +337,7 @@ interface IrBuilderExtension {
|
||||
return when (containingDeclaration) {
|
||||
is ClassDescriptor ->
|
||||
IrGetValueImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
ownerSymbol.owner.startOffset, ownerSymbol.owner.endOffset,
|
||||
// symbolTable.referenceValue(containingDeclaration.thisAsReceiverParameter)
|
||||
ownerSymbol
|
||||
)
|
||||
@@ -335,7 +348,7 @@ interface IrBuilderExtension {
|
||||
// todo: delet zis
|
||||
fun IrFunction.createParameterDeclarations(receiver: IrValueParameter? = null) {
|
||||
fun ParameterDescriptor.irValueParameter() = IrValueParameterImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
this@createParameterDeclarations.startOffset, this@createParameterDeclarations.endOffset,
|
||||
SERIALIZABLE_PLUGIN_ORIGIN,
|
||||
this,
|
||||
type.toIrType(),
|
||||
@@ -353,7 +366,7 @@ interface IrBuilderExtension {
|
||||
assert(typeParameters.isEmpty())
|
||||
descriptor.typeParameters.mapTo(typeParameters) {
|
||||
IrTypeParameterImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
startOffset, endOffset,
|
||||
SERIALIZABLE_PLUGIN_ORIGIN,
|
||||
it
|
||||
).also { typeParameter ->
|
||||
@@ -422,7 +435,14 @@ interface IrBuilderExtension {
|
||||
property.descriptor.findPsi()
|
||||
) else null
|
||||
return serializerInstance(generator, generator.serializableDescriptor, serializer, property.module, property.type, property.genericIndex)
|
||||
?.let { expr -> if (property.type.isMarkedNullable) irInvoke(null, nullableSerClass.constructors.toList()[0], expr) else expr }
|
||||
?.let { expr -> wrapWithNullableSerializerIfNeeded(property.type, expr, nullableSerClass) }
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.wrapWithNullableSerializerIfNeeded(type: KotlinType, expression: IrExpression, nullableSerializerClass: IrClassSymbol): IrExpression {
|
||||
return if (type.isMarkedNullable)
|
||||
irInvoke(null, nullableSerializerClass.constructors.toList()[0], listOf(type.makeNotNullable().toIrType()), listOf(expression))
|
||||
else
|
||||
expression
|
||||
}
|
||||
|
||||
fun IrBuilderWithScope.serializerInstance(
|
||||
@@ -464,12 +484,13 @@ interface IrBuilderExtension {
|
||||
val argSer = enclosingGenerator.findTypeSerializerOrContext(module, it.type, sourceElement = serializerClassOriginal.findPsi())
|
||||
val expr = serializerInstance(enclosingGenerator, serializableDescriptor, argSer, module, it.type, it.type.genericIndex)
|
||||
?: return null
|
||||
if (it.type.isMarkedNullable) irInvoke(null, nullableSerClass.constructors.toList()[0], expr) else expr
|
||||
wrapWithNullableSerializerIfNeeded(it.type, expr, nullableSerClass)
|
||||
}
|
||||
}
|
||||
if (serializerClassOriginal.classId == referenceArraySerializerId)
|
||||
args = listOf(classReference(kType.arguments[0].type)) + args
|
||||
|
||||
val typeArgs = kType.arguments.map { it.type.toIrType() }
|
||||
val serializable = getSerializableClassDescriptorBySerializer(serializerClass)
|
||||
val ctor = if (serializable?.declaredTypeParameters?.isNotEmpty() == true) {
|
||||
requireNotNull(
|
||||
@@ -479,11 +500,7 @@ interface IrBuilderExtension {
|
||||
} else {
|
||||
compilerContext.externalSymbols.referenceConstructor(serializerClass.unsubstitutedPrimaryConstructor!!)
|
||||
}
|
||||
return irInvoke(
|
||||
null,
|
||||
ctor,
|
||||
*args.toTypedArray()
|
||||
)
|
||||
return irInvoke(null, ctor, typeArgs, args)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+41
-27
@@ -76,6 +76,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
|
||||
compilerContext.localSymbolTable.declareAnonymousInitializer(
|
||||
irClass.startOffset, irClass.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, irClass.descriptor
|
||||
).buildWithScope { initIrBody ->
|
||||
initIrBody.parent = irClass
|
||||
val ctor = irClass.declarations.filterIsInstance<IrConstructor>().find { it.isPrimary }
|
||||
?: throw AssertionError("Serializer must have primary constructor")
|
||||
val serialClassDescImplCtor = compilerContext.externalSymbols.referenceConstructor(serialDescImplConstructor)
|
||||
@@ -139,16 +140,15 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
|
||||
}
|
||||
|
||||
override fun generateGenericFieldsAndConstructor(typedConstructorDescriptor: ClassConstructorDescriptor) =
|
||||
irClass.contributeCtor(typedConstructorDescriptor) { ctor ->
|
||||
irClass.contributeConstructor(typedConstructorDescriptor, fromStubs = true) { ctor ->
|
||||
// generate call to primary ctor to init serialClassDesc and super()
|
||||
val primaryCtor = irClass.descriptor.unsubstitutedPrimaryConstructor
|
||||
val primaryCtor = irClass.constructors.find { it.isPrimary }
|
||||
?: throw AssertionError("Serializer class must have primary constructor")
|
||||
+IrDelegatingConstructorCallImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
compilerContext.irBuiltIns.unitType,
|
||||
compilerContext.localSymbolTable.referenceConstructor(primaryCtor),
|
||||
primaryCtor
|
||||
primaryCtor.symbol
|
||||
)
|
||||
|
||||
// store type arguments serializers in fields
|
||||
@@ -241,7 +241,8 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
|
||||
property.irGet()
|
||||
)
|
||||
}
|
||||
val elementCall = irInvoke(irGet(localOutput), writeFunc, *args.toTypedArray())
|
||||
val typeArgs = if (writeFunc.owner.typeParameters.isNotEmpty()) listOf(property.type.toIrType()) else listOf()
|
||||
val elementCall = irInvoke(irGet(localOutput), writeFunc, typeArguments = typeArgs, valueArguments = args)
|
||||
|
||||
// check for call to .shouldEncodeElementDefault
|
||||
if (!property.optional) {
|
||||
@@ -341,29 +342,42 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
|
||||
// if index == -1 (READ_DONE) break loop
|
||||
+IrBranchImpl(irEquals(indexVar.get(), irInt(-1)), irSetVar(flagVar.symbol, irBoolean(false)))
|
||||
|
||||
val branchBodies: List<Pair<Int, IrExpression>> = serializableProperties.mapIndexed { index, property ->
|
||||
val body = irBlock {
|
||||
val sti = getSerialTypeInfo(property)
|
||||
val innerSerial = serializerInstance(this@SerializerIrGenerator, serializableDescriptor, sti.serializer, property.module, property.type, property.genericIndex)
|
||||
// todo: update
|
||||
val decodeFuncToCall =
|
||||
(if (innerSerial != null) "${CallingConventions.decode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}"
|
||||
else "${CallingConventions.decode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}")
|
||||
.let {
|
||||
inputClass.referenceMethod(it)
|
||||
}
|
||||
val args = mutableListOf<IrExpression>(localSerialDesc.get(), irInt(index))
|
||||
if (innerSerial != null)
|
||||
args.add(innerSerial)
|
||||
// local$i = localInput.decode...(...)
|
||||
+irSetVar(localProps[index].symbol, irInvoke(localInput.get(), decodeFuncToCall, *args.toTypedArray()))
|
||||
// bitMask[i] |= 1 << x
|
||||
val bitPos = 1 shl (index % 32)
|
||||
val or = irBinOp(OperatorNameConventions.OR, bitMasks[index / 32].get(), irInt(bitPos))
|
||||
+irSetVar(bitMasks[index / 32].symbol, or)
|
||||
val branchBodies: List<Pair<Int, IrExpression>> =
|
||||
serializableProperties.mapIndexed { index, property ->
|
||||
val body = irBlock {
|
||||
val sti = getSerialTypeInfo(property)
|
||||
val innerSerial = serializerInstance(
|
||||
this@SerializerIrGenerator,
|
||||
serializableDescriptor,
|
||||
sti.serializer,
|
||||
property.module,
|
||||
property.type,
|
||||
property.genericIndex
|
||||
)
|
||||
// todo: update
|
||||
val decodeFuncToCall =
|
||||
(if (innerSerial != null) "${CallingConventions.decode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}"
|
||||
else "${CallingConventions.decode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}")
|
||||
.let {
|
||||
inputClass.referenceMethod(it)
|
||||
}
|
||||
val typeArgs =
|
||||
if (decodeFuncToCall.owner.typeParameters.isNotEmpty()) listOf(property.type.toIrType()) else listOf()
|
||||
val args = mutableListOf(localSerialDesc.get(), irInt(index))
|
||||
if (innerSerial != null)
|
||||
args.add(innerSerial)
|
||||
// local$i = localInput.decode...(...)
|
||||
+irSetVar(
|
||||
localProps[index].symbol,
|
||||
irInvoke(localInput.get(), decodeFuncToCall, typeArgs, args)
|
||||
)
|
||||
// bitMask[i] |= 1 << x
|
||||
val bitPos = 1 shl (index % 32)
|
||||
val or = irBinOp(OperatorNameConventions.OR, bitMasks[index / 32].get(), irInt(bitPos))
|
||||
+irSetVar(bitMasks[index / 32].symbol, or)
|
||||
}
|
||||
index to body
|
||||
}
|
||||
index to body
|
||||
}
|
||||
branchBodies.forEach { (i, e) -> +IrBranchImpl(irEquals(indexVar.get(), irInt(i)), e) }
|
||||
|
||||
// throw exception on unknown field
|
||||
|
||||
Reference in New Issue
Block a user