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:
+18
-5
@@ -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
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+3
-3
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
+48
-33
@@ -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())
|
||||||
|
|||||||
+6
-9
@@ -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,
|
||||||
|
|||||||
+5
-8
@@ -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
|
||||||
|
|||||||
+15
-6
@@ -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)
|
||||||
)
|
)
|
||||||
|
|||||||
+40
-45
@@ -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
|
||||||
|
|||||||
+13
-11
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+9
-3
@@ -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) {
|
||||||
|
|||||||
+3
-4
@@ -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 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user