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:
Leonid Startsev
2019-02-14 14:22:13 +03:00
parent 66272bfa74
commit 8b16801f0d
2 changed files with 93 additions and 62 deletions
@@ -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)
}
}
@@ -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