Rewrite IR plugin infrastructure (and serialization plugin) so it won't emit LazyIR.

LazyIR was emitted because plugin was not able to declare symbols, only to reference them.
Moreover, declarations added by frontend plugin were also unbound symbols produced by psi2ir,
and declaration stub generator was stubbing them with LazyIR – therefore access to global symbol table is not enough for plugins. IrProvider won't help here, because some functions produced by plugin have circular dependencies.

By moving compiler plugins step between psi2ir and declaration stub generator, both problems are resolved
– unbound symbols produced by psi2ir and compiler plugins are declared where they would be declared if this was a user code,
and only unbound symbols left are external dependencies, which is a correct input for lazy ir.
This commit is contained in:
Leonid Startsev
2019-11-15 18:33:46 +03:00
parent e4d0d450ab
commit 3e18350a1f
13 changed files with 187 additions and 145 deletions
@@ -5,18 +5,31 @@
package org.jetbrains.kotlin.backend.common.extensions package org.jetbrains.kotlin.backend.common.extensions
import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.builders.IrGeneratorContext
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
class IrPluginContext(
val moduleDescriptor: ModuleDescriptor,
val bindingContext: BindingContext,
val languageVersionSettings: LanguageVersionSettings,
val symbolTable: SymbolTable,
val typeTranslator: TypeTranslator,
override val irBuiltIns: IrBuiltIns
): IrGeneratorContext()
interface IrGenerationExtension { interface IrGenerationExtension {
companion object : companion object :
ProjectExtensionDescriptor<IrGenerationExtension>("org.jetbrains.kotlin.irGenerationExtension", IrGenerationExtension::class.java) ProjectExtensionDescriptor<IrGenerationExtension>("org.jetbrains.kotlin.irGenerationExtension", IrGenerationExtension::class.java)
fun generate( fun generate(
file: IrFile, moduleFragment: IrModuleFragment,
backendContext: BackendContext, pluginContext: IrPluginContext
bindingContext: BindingContext
) )
} }
@@ -39,11 +39,11 @@ import org.jetbrains.kotlin.name.Name
class IrLoweringContext(backendContext: BackendContext) : IrGeneratorContextBase(backendContext.irBuiltIns) class IrLoweringContext(backendContext: BackendContext) : IrGeneratorContextBase(backendContext.irBuiltIns)
class DeclarationIrBuilder( class DeclarationIrBuilder(
backendContext: BackendContext, generatorContext: IrGeneratorContext,
symbol: IrSymbol, symbol: IrSymbol,
startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET
) : IrBuilderWithScope( ) : IrBuilderWithScope(
IrLoweringContext(backendContext), generatorContext,
Scope(symbol), Scope(symbol),
startOffset, startOffset,
endOffset endOffset
@@ -73,7 +73,7 @@ fun BackendContext.createIrBuilder(
startOffset: Int = UNDEFINED_OFFSET, startOffset: Int = UNDEFINED_OFFSET,
endOffset: Int = UNDEFINED_OFFSET endOffset: Int = UNDEFINED_OFFSET
) = ) =
DeclarationIrBuilder(this, symbol, startOffset, endOffset) DeclarationIrBuilder(IrLoweringContext(this), symbol, startOffset, endOffset)
fun <T : IrBuilder> T.at(element: IrElement) = this.at(element.startOffset, element.endOffset) fun <T : IrBuilder> T.at(element: IrElement) = this.at(element.startOffset, element.endOffset)
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.backend.jvm package org.jetbrains.kotlin.backend.jvm
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen
import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry
@@ -31,6 +33,23 @@ object JvmBackendFacade {
val psi2ir = Psi2IrTranslator(state.languageVersionSettings) val psi2ir = Psi2IrTranslator(state.languageVersionSettings)
val psi2irContext = psi2ir.createGeneratorContext(state.module, state.bindingContext, extensions = JvmGeneratorExtensions) val psi2irContext = psi2ir.createGeneratorContext(state.module, state.bindingContext, extensions = JvmGeneratorExtensions)
val extensions = JvmStubGeneratorExtensions() val extensions = JvmStubGeneratorExtensions()
for (extension in IrGenerationExtension.getInstances(state.project)) {
psi2ir.addPostprocessingStep { module ->
extension.generate(
module,
IrPluginContext(
psi2irContext.moduleDescriptor,
psi2irContext.bindingContext,
psi2irContext.languageVersionSettings,
psi2irContext.symbolTable,
psi2irContext.typeTranslator,
psi2irContext.irBuiltIns
)
)
}
}
val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files, stubGeneratorExtensions = extensions) val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files, stubGeneratorExtensions = extensions)
doGenerateFilesInternal( doGenerateFilesInternal(
state, errorHandler, irModuleFragment, psi2irContext.symbolTable, psi2irContext.sourceManager, phaseConfig, extensions state, errorHandler, irModuleFragment, psi2irContext.symbolTable, psi2irContext.sourceManager, phaseConfig, extensions
@@ -65,12 +84,6 @@ object JvmBackendFacade {
context.classNameOverride = extensions.classNameOverride context.classNameOverride = extensions.classNameOverride
for (irFile in irModuleFragment.files) {
for (extension in IrGenerationExtension.getInstances(context.state.project)) {
extension.generate(irFile, context, context.state.bindingContext)
}
}
try { try {
JvmLower(context).lower(irModuleFragment) JvmLower(context).lower(irModuleFragment)
} catch (e: Throwable) { } catch (e: Throwable) {
@@ -31,17 +31,15 @@ import org.jetbrains.kotlin.psi2ir.transformations.insertImplicitCasts
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartList
typealias Psi2IrPostprocessingStep = (IrModuleFragment) -> Unit
class Psi2IrTranslator( class Psi2IrTranslator(
val languageVersionSettings: LanguageVersionSettings, val languageVersionSettings: LanguageVersionSettings,
val configuration: Psi2IrConfiguration = Psi2IrConfiguration() val configuration: Psi2IrConfiguration = Psi2IrConfiguration()
) { ) {
interface PostprocessingStep { private val postprocessingSteps = SmartList<Psi2IrPostprocessingStep>()
fun postprocess(context: GeneratorContext, irElement: IrElement)
}
private val postprocessingSteps = SmartList<PostprocessingStep>() fun addPostprocessingStep(step: Psi2IrPostprocessingStep) {
fun add(step: PostprocessingStep) {
postprocessingSteps.add(step) postprocessingSteps.add(step)
} }
@@ -74,20 +72,17 @@ class Psi2IrTranslator(
val moduleGenerator = ModuleGenerator(context) val moduleGenerator = ModuleGenerator(context)
val irModule = moduleGenerator.generateModuleFragment(ktFiles) val irModule = moduleGenerator.generateModuleFragment(ktFiles)
// This is required for implicit casts insertion on IrTypes (work-in-progress).
moduleGenerator.generateUnboundSymbolsAsDependencies(irModule, deserializer, irProviders, stubGeneratorExtensions)
irModule.patchDeclarationParents() irModule.patchDeclarationParents()
postprocess(context, irModule) postprocess(context, irModule)
moduleGenerator.generateUnboundSymbolsAsDependencies(irModule, deserializer, irProviders, stubGeneratorExtensions) moduleGenerator.generateUnboundSymbolsAsDependencies(irModule, deserializer, irProviders, stubGeneratorExtensions)
return irModule return irModule
} }
private fun postprocess(context: GeneratorContext, irElement: IrElement) { private fun postprocess(context: GeneratorContext, irElement: IrModuleFragment) {
insertImplicitCasts(irElement, context) insertImplicitCasts(irElement, context)
generateAnnotationsForDeclarations(context, irElement) generateAnnotationsForDeclarations(context, irElement)
postprocessingSteps.forEach { it.postprocess(context, irElement) } postprocessingSteps.forEach { it(irElement) }
irElement.patchDeclarationParents() irElement.patchDeclarationParents()
} }
@@ -177,6 +177,7 @@ fun loadIr(
} }
val moduleFragment = psi2IrContext.generateModuleFragment(files, deserializer) val moduleFragment = psi2IrContext.generateModuleFragment(files, deserializer)
// todo: add postprocessing step
return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, deserializer) return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, deserializer)
} }
@@ -5,12 +5,11 @@
package org.jetbrains.kotlinx.serialization.compiler.backend.ir package org.jetbrains.kotlinx.serialization.compiler.backend.ir
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
import org.jetbrains.kotlin.backend.common.lower.at import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl
@@ -27,7 +26,9 @@ import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.types.typeWith import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.components.isVararg
import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
@@ -37,21 +38,15 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.common.allSealedSeri
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializerOrContext import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializerOrContext
import org.jetbrains.kotlinx.serialization.compiler.backend.common.serialName import org.jetbrains.kotlinx.serialization.compiler.backend.common.serialName
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.* import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.*
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
import org.jetbrains.kotlinx.serialization.compiler.resolve.* import org.jetbrains.kotlinx.serialization.compiler.resolve.*
val BackendContext.externalSymbols: ReferenceSymbolTable get() = ir.symbols.externalSymbolTable val SerializationPluginContext.externalSymbols: SymbolTable get() = symbolTable // Todo: deprecate and remove
val SerializationPluginContext.localSymbolTable: SymbolTable get() = symbolTable // Todo: deprecate and remove
internal fun BackendContext.createTypeTranslator(moduleDescriptor: ModuleDescriptor): TypeTranslator =
TypeTranslator(externalSymbols, irBuiltIns.languageVersionSettings, moduleDescriptor.builtIns).apply {
constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable = externalSymbols)
constantValueGenerator.typeTranslator = this
}
interface IrBuilderExtension { interface IrBuilderExtension {
val compilerContext: BackendContext val compilerContext: SerializationPluginContext
val translator: TypeTranslator val translator: TypeTranslator get() = compilerContext.typeTranslator // Todo: deprecate and remove
val BackendContext.localSymbolTable: SymbolTable
private fun IrClass.declareSimpleFunctionWithExternalOverrides(descriptor: FunctionDescriptor): IrSimpleFunction { private fun IrClass.declareSimpleFunctionWithExternalOverrides(descriptor: FunctionDescriptor): IrSimpleFunction {
return compilerContext.localSymbolTable.declareSimpleFunction(startOffset, endOffset, SERIALIZABLE_PLUGIN_ORIGIN, descriptor) return compilerContext.localSymbolTable.declareSimpleFunction(startOffset, endOffset, SERIALIZABLE_PLUGIN_ORIGIN, descriptor)
@@ -64,26 +59,26 @@ interface IrBuilderExtension {
fun IrClass.contributeFunction( fun IrClass.contributeFunction(
descriptor: FunctionDescriptor, descriptor: FunctionDescriptor,
fromStubs: Boolean = false, declareNew: Boolean = true,
bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit
) { ) {
val f: IrSimpleFunction = if (!fromStubs) declareSimpleFunctionWithExternalOverrides( val f: IrSimpleFunction = if (declareNew) declareSimpleFunctionWithExternalOverrides(
descriptor descriptor
) else compilerContext.externalSymbols.referenceSimpleFunction(descriptor).owner ) else compilerContext.externalSymbols.referenceSimpleFunction(descriptor).owner
f.parent = this f.parent = this
f.returnType = descriptor.returnType!!.toIrType() f.returnType = descriptor.returnType!!.toIrType()
if (!fromStubs) f.createParameterDeclarations(this.thisReceiver!!) if (declareNew) f.createParameterDeclarations(this.thisReceiver!!)
f.body = compilerContext.createIrBuilder(f.symbol).at(this).irBlockBody(this.startOffset, this.endOffset) { bodyGen(f) } f.body = DeclarationIrBuilder(compilerContext, f.symbol, this.startOffset, this.endOffset).irBlockBody(this.startOffset, this.endOffset) { bodyGen(f) }
this.addMember(f) this.addMember(f)
} }
fun IrClass.contributeConstructor( fun IrClass.contributeConstructor(
descriptor: ClassConstructorDescriptor, descriptor: ClassConstructorDescriptor,
fromStubs: Boolean = false, declareNew: Boolean = true,
overwriteValueParameters: Boolean = false, overwriteValueParameters: Boolean = false,
bodyGen: IrBlockBodyBuilder.(IrConstructor) -> Unit bodyGen: IrBlockBodyBuilder.(IrConstructor) -> Unit
) { ) {
val c = if (!fromStubs) compilerContext.localSymbolTable.declareConstructor( val c = if (declareNew) compilerContext.localSymbolTable.declareConstructor(
this.startOffset, this.startOffset,
this.endOffset, this.endOffset,
SERIALIZABLE_PLUGIN_ORIGIN, SERIALIZABLE_PLUGIN_ORIGIN,
@@ -91,12 +86,12 @@ interface IrBuilderExtension {
) else compilerContext.externalSymbols.referenceConstructor(descriptor).owner ) else compilerContext.externalSymbols.referenceConstructor(descriptor).owner
c.parent = this c.parent = this
c.returnType = descriptor.returnType.toIrType() c.returnType = descriptor.returnType.toIrType()
if (!fromStubs || overwriteValueParameters) c.createParameterDeclarations( if (declareNew || overwriteValueParameters) c.createParameterDeclarations(
receiver = null, receiver = null,
overwriteValueParameters = overwriteValueParameters, overwriteValueParameters = overwriteValueParameters,
copyTypeParameters = false copyTypeParameters = false
) )
c.body = compilerContext.createIrBuilder(c.symbol).at(this).irBlockBody(this.startOffset, this.endOffset) { bodyGen(c) } c.body = DeclarationIrBuilder(compilerContext, c.symbol, this.startOffset, this.endOffset).irBlockBody(this.startOffset, this.endOffset) { bodyGen(c) }
this.addMember(c) this.addMember(c)
} }
@@ -106,7 +101,8 @@ interface IrBuilderExtension {
vararg args: IrExpression, vararg args: IrExpression,
typeHint: IrType? = null typeHint: IrType? = null
): IrMemberAccessExpression { ): IrMemberAccessExpression {
val call = typeHint?.let { irCall(callee, type = it) } ?: irCall(callee) val returnType = typeHint ?: callee.descriptor.returnType!!.toIrType()
val call = irCall(callee, type = returnType)
call.dispatchReceiver = dispatchReceiver call.dispatchReceiver = dispatchReceiver
args.forEachIndexed(call::putValueArgument) args.forEachIndexed(call::putValueArgument)
return call return call
@@ -126,25 +122,44 @@ interface IrBuilderExtension {
typeHint = returnTypeHint typeHint = returnTypeHint
).also { call -> typeArguments.forEachIndexed(call::putTypeArgument) } ).also { call -> typeArguments.forEachIndexed(call::putTypeArgument) }
// todo: remove copypasta
private fun SerializationPluginContext.builtInsPackage(vararg packageNameSegments: String) =
builtIns.builtInsModule.getPackage(FqName.fromSegments(listOf(*packageNameSegments))).memberScope
private fun SerializationPluginContext.getSimpleFunction(
name: Name,
vararg packageNameSegments: String = arrayOf("kotlin"),
condition: (SimpleFunctionDescriptor) -> Boolean
): IrSimpleFunctionSymbol =
symbolTable.referenceSimpleFunction(
builtInsPackage(*packageNameSegments).getContributedFunctions(name, NoLookupLocation.FROM_BACKEND)
.first(condition)
)
fun IrBuilderWithScope.createArrayOfExpression( fun IrBuilderWithScope.createArrayOfExpression(
arrayElementType: IrType, arrayElementType: IrType,
arrayElements: List<IrExpression> arrayElements: List<IrExpression>
): IrExpression { ): IrExpression {
val arrayType = compilerContext.ir.symbols.array.typeWith(arrayElementType) val arrayType = context.irBuiltIns.arrayClass.typeWith(arrayElementType)
val arg0 = IrVarargImpl(startOffset, endOffset, arrayType, arrayElementType, arrayElements) val arg0 = IrVarargImpl(startOffset, endOffset, arrayType, arrayElementType, arrayElements)
val typeArguments = listOf(arrayElementType) val typeArguments = listOf(arrayElementType)
return irCall(compilerContext.ir.symbols.arrayOf, arrayType, typeArguments = typeArguments).apply { val arrayOf = compilerContext.getSimpleFunction(Name.identifier("arrayOf")) {
it.extensionReceiverParameter == null && it.dispatchReceiverParameter == null && it.valueParameters.size == 1 &&
it.valueParameters[0].isVararg
}
return irCall(arrayOf, arrayType, typeArguments = typeArguments).apply {
putValueArgument(0, arg0) putValueArgument(0, arg0)
} }
} }
fun IrBuilderWithScope.irBinOp(name: Name, lhs: IrExpression, rhs: IrExpression): IrExpression { fun IrBuilderWithScope.irBinOp(name: Name, lhs: IrExpression, rhs: IrExpression): IrExpression {
val symbol = compilerContext.ir.symbols.getBinaryOperator( val symbol = compilerContext.symbolTable.referenceSimpleFunction(
name, lhs.type.toKotlinType().memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND)
lhs.type.toKotlinType(), .first { it.valueParameters.size == 1 && it.valueParameters[0].type == rhs.type.toKotlinType() }
rhs.type.toKotlinType()
) )
return irInvoke(lhs, symbol, rhs) return irInvoke(lhs, symbol, rhs)
} }
@@ -271,9 +286,9 @@ interface IrBuilderExtension {
descriptor: PropertyAccessorDescriptor, descriptor: PropertyAccessorDescriptor,
fieldSymbol: IrFieldSymbol fieldSymbol: IrFieldSymbol
): IrSimpleFunction { ): IrSimpleFunction {
// Declaration can also be called from user code. Since we lookup descriptor getter in externalSymbols val declaration = compilerContext.externalSymbols.declareSimpleFunctionWithOverrides(fieldSymbol.owner.startOffset,
// (see generateSave/generateLoad), seems it is correct approach to declare getter lazily there. fieldSymbol.owner.endOffset,
val declaration = compilerContext.externalSymbols.referenceSimpleFunction(descriptor).owner SERIALIZABLE_PLUGIN_ORIGIN,descriptor)
return declaration.buildWithScope { irAccessor -> return declaration.buildWithScope { irAccessor ->
irAccessor.createParameterDeclarations(receiver = null) irAccessor.createParameterDeclarations(receiver = null)
irAccessor.returnType = irAccessor.descriptor.returnType!!.toIrType() irAccessor.returnType = irAccessor.descriptor.returnType!!.toIrType()
@@ -481,7 +496,7 @@ interface IrBuilderExtension {
): IrExpression { ): IrExpression {
return if (type.isMarkedNullable) return if (type.isMarkedNullable)
irInvoke( irInvoke(
null, nullableSerializerClass.constructors.toList()[0], null, compilerContext.symbolTable.referenceConstructor(nullableSerializerClass.descriptor.constructors.toList().first()),
typeArguments = listOf(type.makeNotNullable().toIrType()), typeArguments = listOf(type.makeNotNullable().toIrType()),
valueArguments = listOf(expression), valueArguments = listOf(expression),
returnTypeHint = wrapIrTypeIntoKSerializerIrType(module, type.toIrType()) returnTypeHint = wrapIrTypeIntoKSerializerIrType(module, type.toIrType())
@@ -21,22 +21,19 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializer import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializer
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
import org.jetbrains.kotlinx.serialization.compiler.resolve.* import org.jetbrains.kotlinx.serialization.compiler.resolve.*
class SerializableCompanionIrGenerator( class SerializableCompanionIrGenerator(
val irClass: IrClass, val irClass: IrClass,
override val compilerContext: BackendContext, override val compilerContext: SerializationPluginContext,
bindingContext: BindingContext bindingContext: BindingContext
) : SerializableCompanionCodegen(irClass.descriptor, bindingContext), IrBuilderExtension { ) : SerializableCompanionCodegen(irClass.descriptor, bindingContext), IrBuilderExtension {
override val translator: TypeTranslator = compilerContext.createTypeTranslator(serializableDescriptor.module)
private val _table = SymbolTable()
override val BackendContext.localSymbolTable: SymbolTable
get() = _table
companion object { companion object {
fun generate( fun generate(
irClass: IrClass, irClass: IrClass,
context: BackendContext, context: SerializationPluginContext,
bindingContext: BindingContext bindingContext: BindingContext
) { ) {
val companionDescriptor = irClass.descriptor val companionDescriptor = irClass.descriptor
@@ -63,9 +60,9 @@ class SerializableCompanionIrGenerator(
compilerContext.externalSymbols.referenceConstructor(it) compilerContext.externalSymbols.referenceConstructor(it)
}) })
val annotationType = compilerContext.externalSymbols.referenceClass(annotationMarkerClass).owner.defaultType val annotationType = annotationMarkerClass.defaultType.toIrType()
val irSerializableClass = compilerContext.externalSymbols.referenceClass(serializableDescriptor).owner val irSerializableClass = compilerContext.externalSymbols.referenceClass(serializableDescriptor).owner
val annotationCtorCall = IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, annotationType, annotationCtor, annotationMarkerClass.declaredTypeParameters.size).apply { val annotationCtorCall = IrConstructorCallImpl.fromSymbolDescriptor(startOffset, endOffset, annotationType, annotationCtor).apply {
val serializerType = serializer.toSimpleType(false) val serializerType = serializer.toSimpleType(false)
putValueArgument( putValueArgument(
0, 0,
@@ -81,7 +78,7 @@ class SerializableCompanionIrGenerator(
} }
override fun generateSerializerGetter(methodDescriptor: FunctionDescriptor) = override fun generateSerializerGetter(methodDescriptor: FunctionDescriptor) =
irClass.contributeFunction(methodDescriptor, fromStubs = true) { getter -> irClass.contributeFunction(methodDescriptor) { getter ->
val serializer = requireNotNull( val serializer = requireNotNull(
findTypeSerializer( findTypeSerializer(
serializableDescriptor.module, serializableDescriptor.module,
@@ -28,21 +28,18 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.serializableAnnotationIsUseless import org.jetbrains.kotlinx.serialization.compiler.diagnostic.serializableAnnotationIsUseless
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
import org.jetbrains.kotlinx.serialization.compiler.resolve.* import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MISSING_FIELD_EXC import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MISSING_FIELD_EXC
class SerializableIrGenerator( class SerializableIrGenerator(
val irClass: IrClass, val irClass: IrClass,
override val compilerContext: BackendContext, override val compilerContext: SerializationPluginContext,
bindingContext: BindingContext bindingContext: BindingContext
) : SerializableCodegen(irClass.descriptor, bindingContext), IrBuilderExtension { ) : SerializableCodegen(irClass.descriptor, bindingContext), IrBuilderExtension {
override val translator: TypeTranslator = compilerContext.createTypeTranslator(serializableDescriptor.module)
private val _table = SymbolTable()
override val BackendContext.localSymbolTable: SymbolTable
get() = _table
override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) = override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) =
irClass.contributeConstructor(constructorDescriptor, fromStubs = true, overwriteValueParameters = true) { ctor -> irClass.contributeConstructor(constructorDescriptor, overwriteValueParameters = true) { ctor ->
val transformFieldInitializer = buildInitializersRemapping(irClass) val transformFieldInitializer = buildInitializersRemapping(irClass)
// Missing field exception parts // Missing field exception parts
@@ -50,7 +47,7 @@ class SerializableIrGenerator(
serializableDescriptor.getClassFromSerializationPackage(MISSING_FIELD_EXC) serializableDescriptor.getClassFromSerializationPackage(MISSING_FIELD_EXC)
.unsubstitutedPrimaryConstructor!! .unsubstitutedPrimaryConstructor!!
val exceptionCtorRef = compilerContext.externalSymbols.referenceConstructor(exceptionCtor) val exceptionCtorRef = compilerContext.externalSymbols.referenceConstructor(exceptionCtor)
val exceptionType = exceptionCtorRef.owner.returnType val exceptionType = exceptionCtor.returnType.toIrType()
val serializableProperties = properties.serializableProperties val serializableProperties = properties.serializableProperties
val seenVarsOffset = serializableProperties.bitMaskSlotCount() val seenVarsOffset = serializableProperties.bitMaskSlotCount()
@@ -166,7 +163,7 @@ class SerializableIrGenerator(
companion object { companion object {
fun generate( fun generate(
irClass: IrClass, irClass: IrClass,
context: BackendContext, context: SerializationPluginContext,
bindingContext: BindingContext bindingContext: BindingContext
) { ) {
val serializableClass = irClass.descriptor val serializableClass = irClass.descriptor
@@ -5,9 +5,9 @@
package org.jetbrains.kotlinx.serialization.compiler.backend.ir package org.jetbrains.kotlinx.serialization.compiler.backend.ir
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.declarations.IrVariable
@@ -20,9 +20,14 @@ import org.jetbrains.kotlin.ir.util.referenceFunction
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
import org.jetbrains.kotlinx.serialization.compiler.resolve.* import org.jetbrains.kotlinx.serialization.compiler.resolve.*
class SerializerForEnumsGenerator(irClass: IrClass, compilerContext: BackendContext, bindingContext: BindingContext) : class SerializerForEnumsGenerator(
irClass: IrClass,
compilerContext: SerializationPluginContext,
bindingContext: BindingContext
) :
SerializerIrGenerator(irClass, compilerContext, bindingContext) { SerializerIrGenerator(irClass, compilerContext, bindingContext) {
override fun generateSave(function: FunctionDescriptor) = irClass.contributeFunction(function) { saveFunc -> override fun generateSave(function: FunctionDescriptor) = irClass.contributeFunction(function) { saveFunc ->
@@ -53,9 +58,13 @@ class SerializerForEnumsGenerator(irClass: IrClass, compilerContext: BackendCont
val getValues = irInvoke(dispatchReceiver = null, callee = valuesF.symbol) val getValues = irInvoke(dispatchReceiver = null, callee = valuesF.symbol)
val arrayGet = val arrayGet =
compilerContext.ir.symbols.array.owner.functions.single { it.name == Name.identifier("get") }.symbol compilerContext.builtIns.array.unsubstitutedMemberScope.getContributedFunctions(
Name.identifier("get"),
NoLookupLocation.FROM_BACKEND
).single()
val arrayGetSymbol = compilerContext.externalSymbols.referenceFunction(arrayGet)
val getValueByOrdinal = val getValueByOrdinal =
irInvoke(getValues, arrayGet, irInvoke(irGet(loadFunc.valueParameters[0]), decode, serialDescGetter)) irInvoke(getValues, arrayGetSymbol, irInvoke(irGet(loadFunc.valueParameters[0]), decode, serialDescGetter))
+irReturn(getValueByOrdinal) +irReturn(getValueByOrdinal)
} }
@@ -70,7 +79,7 @@ class SerializerForEnumsGenerator(irClass: IrClass, compilerContext: BackendCont
return irInvoke( return irInvoke(
null, ctor, null, ctor,
irString(serialName), irString(serialName),
typeHint = ctor.owner.returnType typeHint = ctor.descriptor.returnType.toIrType()
) )
} }
@@ -93,7 +102,7 @@ class SerializerForEnumsGenerator(irClass: IrClass, compilerContext: BackendCont
+call +call
// serialDesc.pushAnnotation(...) // serialDesc.pushAnnotation(...)
copySerialInfoAnnotationsToDescriptor( copySerialInfoAnnotationsToDescriptor(
compilerContext.externalSymbols.referenceClass(entry).owner.annotations, entry.annotations.mapNotNull(compilerContext.typeTranslator.constantValueGenerator::generateAnnotationConstructorCall),
localDescriptor, localDescriptor,
serialDescImplClass.referenceMethod(CallingConventions.addAnnotation) serialDescImplClass.referenceMethod(CallingConventions.addAnnotation)
) )
@@ -5,9 +5,8 @@
package org.jetbrains.kotlinx.serialization.compiler.backend.ir package org.jetbrains.kotlinx.serialization.compiler.backend.ir
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irIfThen import org.jetbrains.kotlin.backend.common.lower.irIfThen
import org.jetbrains.kotlin.backend.common.lower.irThrow import org.jetbrains.kotlin.backend.common.lower.irThrow
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
@@ -25,6 +24,7 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen
import org.jetbrains.kotlinx.serialization.compiler.backend.common.getSerialTypeInfo import org.jetbrains.kotlinx.serialization.compiler.backend.common.getSerialTypeInfo
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
import org.jetbrains.kotlinx.serialization.compiler.resolve.* import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.DECODER_CLASS import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.DECODER_CLASS
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENCODER_CLASS import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENCODER_CLASS
@@ -36,14 +36,8 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.UN
// Is creating synthetic origin is a good idea or not? // Is creating synthetic origin is a good idea or not?
object SERIALIZABLE_PLUGIN_ORIGIN : IrDeclarationOriginImpl("SERIALIZER") object SERIALIZABLE_PLUGIN_ORIGIN : IrDeclarationOriginImpl("SERIALIZER")
open class SerializerIrGenerator(val irClass: IrClass, final override val compilerContext: BackendContext, bindingContext: BindingContext) : open class SerializerIrGenerator(val irClass: IrClass, final override val compilerContext: SerializationPluginContext, bindingContext: BindingContext) :
SerializerCodegen(irClass.descriptor, bindingContext), IrBuilderExtension { SerializerCodegen(irClass.descriptor, bindingContext), IrBuilderExtension {
final override val translator: TypeTranslator = compilerContext.createTypeTranslator(serializableDescriptor.module)
private val _table = SymbolTable()
final override val BackendContext.localSymbolTable: SymbolTable
get() = _table
protected val serializableIrClass = compilerContext.externalSymbols.referenceClass(serializableDescriptor).owner protected val serializableIrClass = compilerContext.externalSymbols.referenceClass(serializableDescriptor).owner
override fun generateSerialDesc() { override fun generateSerialDesc() {
@@ -75,30 +69,31 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
val ctor = irClass.declarations.filterIsInstance<IrConstructor>().find { it.isPrimary } val ctor = irClass.declarations.filterIsInstance<IrConstructor>().find { it.isPrimary }
?: throw AssertionError("Serializer must have primary constructor") ?: throw AssertionError("Serializer must have primary constructor")
compilerContext.localSymbolTable.withScope(initIrBody.descriptor) { compilerContext.localSymbolTable.withScope(initIrBody.descriptor) {
initIrBody.body = compilerContext.createIrBuilder(initIrBody.symbol).irBlockBody { initIrBody.body =
val localDesc = irTemporary( DeclarationIrBuilder(compilerContext, initIrBody.symbol, initIrBody.startOffset, initIrBody.endOffset).irBlockBody {
instantiateNewDescriptor(serialDescImplClass, irGet(thisAsReceiverParameter)), val localDesc = irTemporary(
nameHint = "serialDesc" instantiateNewDescriptor(serialDescImplClass, irGet(thisAsReceiverParameter)),
) nameHint = "serialDesc"
)
addElementsContentToDescriptor(serialDescImplClass, localDesc, addFuncS) addElementsContentToDescriptor(serialDescImplClass, localDesc, addFuncS)
// add class annotations // add class annotations
copySerialInfoAnnotationsToDescriptor( copySerialInfoAnnotationsToDescriptor(
serializableIrClass.annotations, serializableIrClass.annotations,
localDesc, localDesc,
serialDescImplClass.referenceMethod(CallingConventions.addClassAnnotation) serialDescImplClass.referenceMethod(CallingConventions.addClassAnnotation)
) )
// save local descriptor to field // save local descriptor to field
+irSetField( +irSetField(
generateReceiverExpressionForFieldAccess( generateReceiverExpressionForFieldAccess(
thisAsReceiverParameter.symbol, thisAsReceiverParameter.symbol,
generatedSerialDescPropertyDescriptor generatedSerialDescPropertyDescriptor
), ),
prop.backingField!!, prop.backingField!!,
irGet(localDesc) irGet(localDesc)
) )
} }
(ctor.body as? IrBlockBody)?.statements?.addAll(initIrBody.body.statements) (ctor.body as? IrBlockBody)?.statements?.addAll(initIrBody.body.statements)
} }
} }
@@ -113,8 +108,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
val serialClassDescImplCtor = compilerContext.externalSymbols.referenceConstructor(serialDescImplConstructor) val serialClassDescImplCtor = compilerContext.externalSymbols.referenceConstructor(serialDescImplConstructor)
return irInvoke( return irInvoke(
null, serialClassDescImplCtor, null, serialClassDescImplCtor,
irString(serialName), if (isGeneratedSerializer) correctThis else irNull(), irString(serialName), if (isGeneratedSerializer) correctThis else irNull()
typeHint = serialClassDescImplCtor.owner.returnType
) )
} }
@@ -155,7 +149,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
} }
override fun generateGenericFieldsAndConstructor(typedConstructorDescriptor: ClassConstructorDescriptor) = override fun generateGenericFieldsAndConstructor(typedConstructorDescriptor: ClassConstructorDescriptor) =
irClass.contributeConstructor(typedConstructorDescriptor, fromStubs = true) { ctor -> irClass.contributeConstructor(typedConstructorDescriptor) { ctor ->
// generate call to primary ctor to init serialClassDesc and super() // generate call to primary ctor to init serialClassDesc and super()
val primaryCtor = irClass.constructors.find { it.isPrimary } val primaryCtor = irClass.constructors.find { it.isPrimary }
?: throw AssertionError("Serializer class must have primary constructor") ?: throw AssertionError("Serializer class must have primary constructor")
@@ -183,9 +177,11 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
} }
override fun generateChildSerializersGetter(function: FunctionDescriptor) = irClass.contributeFunction(function, fromStubs = true) { irFun -> override fun generateChildSerializersGetter(function: FunctionDescriptor) = irClass.contributeFunction(function) { irFun ->
val allSerializers = serializableProperties.map { requireNotNull( val allSerializers = serializableProperties.map {
serializerTower(this@SerializerIrGenerator, irFun.dispatchReceiverParameter!!, it)) { "Property ${it.name} must have a serializer" } requireNotNull(
serializerTower(this@SerializerIrGenerator, irFun.dispatchReceiverParameter!!, it)
) { "Property ${it.name} must have a serializer" }
} }
val kSerType = ((irFun.returnType as IrSimpleType).arguments.first() as IrTypeProjection).type val kSerType = ((irFun.returnType as IrSimpleType).arguments.first() as IrTypeProjection).type
@@ -200,7 +196,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
protected fun ClassDescriptor.referenceMethod(methodName: String) = protected fun ClassDescriptor.referenceMethod(methodName: String) =
getFuncDesc(methodName).single().let { compilerContext.externalSymbols.referenceFunction(it) } getFuncDesc(methodName).single().let { compilerContext.externalSymbols.referenceFunction(it) }
override fun generateSave(function: FunctionDescriptor) = irClass.contributeFunction(function, fromStubs = true) { saveFunc -> override fun generateSave(function: FunctionDescriptor) = irClass.contributeFunction(function) { saveFunc ->
val fieldInitializer: (SerializableProperty) -> IrExpression? = val fieldInitializer: (SerializableProperty) -> IrExpression? =
buildInitializersRemapping(serializableIrClass).run { { invoke(it.irField) } } buildInitializersRemapping(serializableIrClass).run { { invoke(it.irField) } }
@@ -218,7 +214,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
// fun beginStructure(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): StructureEncoder // fun beginStructure(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): StructureEncoder
val beginFunc = kOutputSmallClass.referenceMethod(CallingConventions.begin) // todo: retrieve from actual encoder instead val beginFunc = kOutputSmallClass.referenceMethod(CallingConventions.begin) // todo: retrieve from actual encoder instead
val call = irCall(beginFunc).mapValueParametersIndexed { i, parameterDescriptor -> val call = irCall(beginFunc, type = beginFunc.descriptor.returnType!!.toIrType()).mapValueParametersIndexed { i, parameterDescriptor ->
if (i == 0) irGet(localSerialDesc) else IrVarargImpl( if (i == 0) irGet(localSerialDesc) else IrVarargImpl(
startOffset, startOffset,
endOffset, endOffset,
@@ -269,7 +265,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
property.irGet() property.irGet()
) )
} }
val typeArgs = if (writeFunc.owner.typeParameters.isNotEmpty()) listOf(property.type.toIrType()) else listOf() val typeArgs = if (writeFunc.descriptor.typeParameters.isNotEmpty()) listOf(property.type.toIrType()) else listOf()
val elementCall = irInvoke(irGet(localOutput), writeFunc, typeArguments = typeArgs, valueArguments = args) val elementCall = irInvoke(irGet(localOutput), writeFunc, typeArguments = typeArgs, valueArguments = args)
// check for call to .shouldEncodeElementDefault // check for call to .shouldEncodeElementDefault
@@ -316,7 +312,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
defaultPrimitive to kType defaultPrimitive to kType
} }
override fun generateLoad(function: FunctionDescriptor) = irClass.contributeFunction(function, fromStubs = true) { loadFunc -> override fun generateLoad(function: FunctionDescriptor) = irClass.contributeFunction(function) { loadFunc ->
if (serializableDescriptor.modality == Modality.ABSTRACT || serializableDescriptor.modality == Modality.SEALED) { if (serializableDescriptor.modality == Modality.ABSTRACT || serializableDescriptor.modality == Modality.SEALED) {
return@contributeFunction return@contributeFunction
} }
@@ -393,7 +389,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
inputClass.referenceMethod(it) inputClass.referenceMethod(it)
} }
val typeArgs = val typeArgs =
if (decodeFuncToCall.owner.typeParameters.isNotEmpty()) listOf(property.type.toIrType()) else listOf() if (decodeFuncToCall.descriptor.typeParameters.isNotEmpty()) listOf(property.type.toIrType()) else listOf()
val args = mutableListOf<IrExpression>(localSerialDesc.get(), irInt(index)) val args = mutableListOf<IrExpression>(localSerialDesc.get(), irInt(index))
if (innerSerial != null) if (innerSerial != null)
args.add(innerSerial) args.add(innerSerial)
@@ -421,8 +417,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
irInvoke( irInvoke(
null, null,
excClassRef, excClassRef,
indexVar.get(), indexVar.get()
typeHint = excClassRef.owner.returnType
) )
) )
) )
@@ -454,7 +449,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
companion object { companion object {
fun generate( fun generate(
irClass: IrClass, irClass: IrClass,
context: BackendContext, context: SerializationPluginContext,
bindingContext: BindingContext bindingContext: BindingContext
) { ) {
val serializableDesc = getSerializableClassDescriptorBySerializer(irClass.symbol.descriptor) ?: return val serializableDesc = getSerializableClassDescriptorBySerializer(irClass.symbol.descriptor) ?: return
@@ -5,18 +5,18 @@
package org.jetbrains.kotlinx.serialization.compiler.extensions package org.jetbrains.kotlinx.serialization.compiler.extensions
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.backend.common.runOnFilePostfix
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializableCompanionIrGenerator import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializableCompanionIrGenerator
import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializableIrGenerator import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializableIrGenerator
import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializerIrGenerator import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializerIrGenerator
@@ -37,24 +37,26 @@ fun ClassLoweringPass.runOnFileInOrder(irFile: IrFile) {
}) })
} }
typealias SerializationPluginContext = IrPluginContext
private class SerializerClassLowering( private class SerializerClassLowering(
val context: BackendContext, val context: SerializationPluginContext
val bindingContext: BindingContext
) : ) :
IrElementTransformerVoid(), ClassLoweringPass { IrElementTransformerVoid(), ClassLoweringPass {
override fun lower(irClass: IrClass) { override fun lower(irClass: IrClass) {
SerializableIrGenerator.generate(irClass, context, bindingContext) SerializableIrGenerator.generate(irClass, context, context.bindingContext)
SerializerIrGenerator.generate(irClass, context, bindingContext) SerializerIrGenerator.generate(irClass, context, context.bindingContext)
SerializableCompanionIrGenerator.generate(irClass, context, bindingContext) SerializableCompanionIrGenerator.generate(irClass, context, context.bindingContext)
} }
} }
open class SerializationLoweringExtension : IrGenerationExtension { open class SerializationLoweringExtension : IrGenerationExtension {
override fun generate( override fun generate(
file: IrFile, moduleFragment: IrModuleFragment,
backendContext: BackendContext, pluginContext: IrPluginContext
bindingContext: BindingContext
) { ) {
SerializerClassLowering(backendContext, bindingContext).runOnFileInOrder(file) val serializerClassLowering = SerializerClassLowering(pluginContext)
for (file in moduleFragment.files)
serializerClassLowering.runOnFileInOrder(file)
} }
} }
@@ -186,8 +186,10 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa
ALOAD (4) ALOAD (4)
ALOAD (3) ALOAD (3)
INVOKEINTERFACE (kotlinx/serialization/CompositeEncoder, endStructure, (Lkotlinx/serialization/SerialDescriptor;)V) INVOKEINTERFACE (kotlinx/serialization/CompositeEncoder, endStructure, (Lkotlinx/serialization/SerialDescriptor;)V)
RETURN
LABEL (L2) LABEL (L2)
LINENUMBER (13)
RETURN
LABEL (L3)
} }
public void serialize(kotlinx.serialization.Encoder p0, java.lang.Object p1) { public void serialize(kotlinx.serialization.Encoder p0, java.lang.Object p1) {
@@ -487,8 +489,10 @@ public final class OptionalUser$$serializer : java/lang/Object, kotlinx/serializ
ALOAD (4) ALOAD (4)
ALOAD (3) ALOAD (3)
INVOKEINTERFACE (kotlinx/serialization/CompositeEncoder, endStructure, (Lkotlinx/serialization/SerialDescriptor;)V) INVOKEINTERFACE (kotlinx/serialization/CompositeEncoder, endStructure, (Lkotlinx/serialization/SerialDescriptor;)V)
RETURN
LABEL (L7) LABEL (L7)
LINENUMBER (10)
RETURN
LABEL (L8)
} }
public void serialize(kotlinx.serialization.Encoder p0, java.lang.Object p1) { public void serialize(kotlinx.serialization.Encoder p0, java.lang.Object p1) {
@@ -829,8 +833,10 @@ public final class User$$serializer : java/lang/Object, kotlinx/serialization/in
ALOAD (4) ALOAD (4)
ALOAD (3) ALOAD (3)
INVOKEINTERFACE (kotlinx/serialization/CompositeEncoder, endStructure, (Lkotlinx/serialization/SerialDescriptor;)V) INVOKEINTERFACE (kotlinx/serialization/CompositeEncoder, endStructure, (Lkotlinx/serialization/SerialDescriptor;)V)
RETURN
LABEL (L2) LABEL (L2)
LINENUMBER (7)
RETURN
LABEL (L3)
} }
public void serialize(kotlinx.serialization.Encoder p0, java.lang.Object p1) { public void serialize(kotlinx.serialization.Encoder p0, java.lang.Object p1) {
@@ -5,14 +5,13 @@
package org.jetbrains.kotlinx.serialization.compiler.extensions package org.jetbrains.kotlinx.serialization.compiler.extensions
import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.js.translate.context.TranslationContext import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.declaration.DeclarationBodyVisitor import org.jetbrains.kotlin.js.translate.declaration.DeclarationBodyVisitor
import org.jetbrains.kotlin.psi.KtPureClassOrObject import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlinx.serialization.idea.runIfEnabledOn import org.jetbrains.kotlinx.serialization.idea.runIfEnabledOn
class SerializationIDECodegenExtension : SerializationCodegenExtension() { class SerializationIDECodegenExtension : SerializationCodegenExtension() {
@@ -32,7 +31,7 @@ class SerializationIDEJsExtension : SerializationJsExtension() {
} }
class SerializationIDEIrExtension : SerializationLoweringExtension() { class SerializationIDEIrExtension : SerializationLoweringExtension() {
override fun generate(file: IrFile, backendContext: BackendContext, bindingContext: BindingContext) { override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) {
/* No-op don't enable IR extensions in IDE */ /* No-op don't enable IR extensions in IDE */
} }
} }