diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrGenerationExtension.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrGenerationExtension.kt index 3a811ff2e1d..23a99acc201 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrGenerationExtension.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrGenerationExtension.kt @@ -5,18 +5,31 @@ 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.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 +class IrPluginContext( + val moduleDescriptor: ModuleDescriptor, + val bindingContext: BindingContext, + val languageVersionSettings: LanguageVersionSettings, + val symbolTable: SymbolTable, + val typeTranslator: TypeTranslator, + override val irBuiltIns: IrBuiltIns +): IrGeneratorContext() + interface IrGenerationExtension { companion object : ProjectExtensionDescriptor("org.jetbrains.kotlin.irGenerationExtension", IrGenerationExtension::class.java) fun generate( - file: IrFile, - backendContext: BackendContext, - bindingContext: BindingContext + moduleFragment: IrModuleFragment, + pluginContext: IrPluginContext ) } \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt index 93d57bb4e7a..960c141469b 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt @@ -39,11 +39,11 @@ import org.jetbrains.kotlin.name.Name class IrLoweringContext(backendContext: BackendContext) : IrGeneratorContextBase(backendContext.irBuiltIns) class DeclarationIrBuilder( - backendContext: BackendContext, + generatorContext: IrGeneratorContext, symbol: IrSymbol, startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET ) : IrBuilderWithScope( - IrLoweringContext(backendContext), + generatorContext, Scope(symbol), startOffset, endOffset @@ -73,7 +73,7 @@ fun BackendContext.createIrBuilder( startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET ) = - DeclarationIrBuilder(this, symbol, startOffset, endOffset) + DeclarationIrBuilder(IrLoweringContext(this), symbol, startOffset, endOffset) fun T.at(element: IrElement) = this.at(element.startOffset, element.endOffset) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt index a6a6f04ed43..1ac93357a56 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt @@ -6,6 +6,8 @@ package org.jetbrains.kotlin.backend.jvm 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.jvm.codegen.ClassCodegen import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry @@ -31,6 +33,23 @@ object JvmBackendFacade { val psi2ir = Psi2IrTranslator(state.languageVersionSettings) val psi2irContext = psi2ir.createGeneratorContext(state.module, state.bindingContext, extensions = JvmGeneratorExtensions) 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) doGenerateFilesInternal( state, errorHandler, irModuleFragment, psi2irContext.symbolTable, psi2irContext.sourceManager, phaseConfig, extensions @@ -65,12 +84,6 @@ object JvmBackendFacade { 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 { JvmLower(context).lower(irModuleFragment) } catch (e: Throwable) { diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt index 8cb1c52860b..f18917826e3 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt @@ -31,17 +31,15 @@ import org.jetbrains.kotlin.psi2ir.transformations.insertImplicitCasts import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.utils.SmartList +typealias Psi2IrPostprocessingStep = (IrModuleFragment) -> Unit + class Psi2IrTranslator( val languageVersionSettings: LanguageVersionSettings, val configuration: Psi2IrConfiguration = Psi2IrConfiguration() ) { - interface PostprocessingStep { - fun postprocess(context: GeneratorContext, irElement: IrElement) - } + private val postprocessingSteps = SmartList() - private val postprocessingSteps = SmartList() - - fun add(step: PostprocessingStep) { + fun addPostprocessingStep(step: Psi2IrPostprocessingStep) { postprocessingSteps.add(step) } @@ -74,20 +72,17 @@ class Psi2IrTranslator( val moduleGenerator = ModuleGenerator(context) 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() - postprocess(context, irModule) moduleGenerator.generateUnboundSymbolsAsDependencies(irModule, deserializer, irProviders, stubGeneratorExtensions) return irModule } - private fun postprocess(context: GeneratorContext, irElement: IrElement) { + private fun postprocess(context: GeneratorContext, irElement: IrModuleFragment) { insertImplicitCasts(irElement, context) generateAnnotationsForDeclarations(context, irElement) - postprocessingSteps.forEach { it.postprocess(context, irElement) } + postprocessingSteps.forEach { it(irElement) } irElement.patchDeclarationParents() } diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt index 5eaeb7ee6f2..7b11ddd7f47 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt @@ -177,6 +177,7 @@ fun loadIr( } val moduleFragment = psi2IrContext.generateModuleFragment(files, deserializer) + // todo: add postprocessing step return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, deserializer) } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt index 90cc85109eb..ce8b5b50e8d 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt @@ -5,12 +5,11 @@ 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.lower.at -import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder import org.jetbrains.kotlin.descriptors.* 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.declarations.* 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.util.* import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi +import org.jetbrains.kotlin.name.FqName 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.types.* 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.serialName import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.* +import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext import org.jetbrains.kotlinx.serialization.compiler.resolve.* -val BackendContext.externalSymbols: ReferenceSymbolTable get() = ir.symbols.externalSymbolTable - -internal fun BackendContext.createTypeTranslator(moduleDescriptor: ModuleDescriptor): TypeTranslator = - TypeTranslator(externalSymbols, irBuiltIns.languageVersionSettings, moduleDescriptor.builtIns).apply { - constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable = externalSymbols) - constantValueGenerator.typeTranslator = this - } +val SerializationPluginContext.externalSymbols: SymbolTable get() = symbolTable // Todo: deprecate and remove +val SerializationPluginContext.localSymbolTable: SymbolTable get() = symbolTable // Todo: deprecate and remove interface IrBuilderExtension { - val compilerContext: BackendContext - val translator: TypeTranslator - - val BackendContext.localSymbolTable: SymbolTable + val compilerContext: SerializationPluginContext + val translator: TypeTranslator get() = compilerContext.typeTranslator // Todo: deprecate and remove private fun IrClass.declareSimpleFunctionWithExternalOverrides(descriptor: FunctionDescriptor): IrSimpleFunction { return compilerContext.localSymbolTable.declareSimpleFunction(startOffset, endOffset, SERIALIZABLE_PLUGIN_ORIGIN, descriptor) @@ -64,26 +59,26 @@ interface IrBuilderExtension { fun IrClass.contributeFunction( descriptor: FunctionDescriptor, - fromStubs: Boolean = false, + declareNew: Boolean = true, bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit ) { - val f: IrSimpleFunction = if (!fromStubs) declareSimpleFunctionWithExternalOverrides( + val f: IrSimpleFunction = if (declareNew) declareSimpleFunctionWithExternalOverrides( descriptor ) else compilerContext.externalSymbols.referenceSimpleFunction(descriptor).owner f.parent = this f.returnType = descriptor.returnType!!.toIrType() - if (!fromStubs) f.createParameterDeclarations(this.thisReceiver!!) - f.body = compilerContext.createIrBuilder(f.symbol).at(this).irBlockBody(this.startOffset, this.endOffset) { bodyGen(f) } + if (declareNew) f.createParameterDeclarations(this.thisReceiver!!) + f.body = DeclarationIrBuilder(compilerContext, f.symbol, this.startOffset, this.endOffset).irBlockBody(this.startOffset, this.endOffset) { bodyGen(f) } this.addMember(f) } fun IrClass.contributeConstructor( descriptor: ClassConstructorDescriptor, - fromStubs: Boolean = false, + declareNew: Boolean = true, overwriteValueParameters: Boolean = false, bodyGen: IrBlockBodyBuilder.(IrConstructor) -> Unit ) { - val c = if (!fromStubs) compilerContext.localSymbolTable.declareConstructor( + val c = if (declareNew) compilerContext.localSymbolTable.declareConstructor( this.startOffset, this.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, @@ -91,12 +86,12 @@ interface IrBuilderExtension { ) else compilerContext.externalSymbols.referenceConstructor(descriptor).owner c.parent = this c.returnType = descriptor.returnType.toIrType() - if (!fromStubs || overwriteValueParameters) c.createParameterDeclarations( + if (declareNew || overwriteValueParameters) c.createParameterDeclarations( receiver = null, overwriteValueParameters = overwriteValueParameters, 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) } @@ -106,7 +101,8 @@ interface IrBuilderExtension { vararg args: IrExpression, typeHint: IrType? = null ): 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 args.forEachIndexed(call::putValueArgument) return call @@ -126,25 +122,44 @@ interface IrBuilderExtension { typeHint = returnTypeHint ).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( arrayElementType: IrType, arrayElements: List ): 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 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) } } fun IrBuilderWithScope.irBinOp(name: Name, lhs: IrExpression, rhs: IrExpression): IrExpression { - val symbol = compilerContext.ir.symbols.getBinaryOperator( - name, - lhs.type.toKotlinType(), - rhs.type.toKotlinType() + val symbol = compilerContext.symbolTable.referenceSimpleFunction( + lhs.type.toKotlinType().memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) + .first { it.valueParameters.size == 1 && it.valueParameters[0].type == rhs.type.toKotlinType() } ) return irInvoke(lhs, symbol, rhs) } @@ -271,9 +286,9 @@ interface IrBuilderExtension { descriptor: PropertyAccessorDescriptor, fieldSymbol: IrFieldSymbol ): IrSimpleFunction { - // Declaration can also be called from user code. Since we lookup descriptor getter in externalSymbols - // (see generateSave/generateLoad), seems it is correct approach to declare getter lazily there. - val declaration = compilerContext.externalSymbols.referenceSimpleFunction(descriptor).owner + val declaration = compilerContext.externalSymbols.declareSimpleFunctionWithOverrides(fieldSymbol.owner.startOffset, + fieldSymbol.owner.endOffset, + SERIALIZABLE_PLUGIN_ORIGIN,descriptor) return declaration.buildWithScope { irAccessor -> irAccessor.createParameterDeclarations(receiver = null) irAccessor.returnType = irAccessor.descriptor.returnType!!.toIrType() @@ -481,7 +496,7 @@ interface IrBuilderExtension { ): IrExpression { return if (type.isMarkedNullable) irInvoke( - null, nullableSerializerClass.constructors.toList()[0], + null, compilerContext.symbolTable.referenceConstructor(nullableSerializerClass.descriptor.constructors.toList().first()), typeArguments = listOf(type.makeNotNullable().toIrType()), valueArguments = listOf(expression), returnTypeHint = wrapIrTypeIntoKSerializerIrType(module, type.toIrType()) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt index 3d249e26cd6..af69f3ce4e6 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt @@ -21,22 +21,19 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializer +import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext import org.jetbrains.kotlinx.serialization.compiler.resolve.* class SerializableCompanionIrGenerator( val irClass: IrClass, - override val compilerContext: BackendContext, + override val compilerContext: SerializationPluginContext, bindingContext: BindingContext ) : 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 { fun generate( irClass: IrClass, - context: BackendContext, + context: SerializationPluginContext, bindingContext: BindingContext ) { val companionDescriptor = irClass.descriptor @@ -63,9 +60,9 @@ class SerializableCompanionIrGenerator( 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 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) putValueArgument( 0, @@ -81,7 +78,7 @@ class SerializableCompanionIrGenerator( } override fun generateSerializerGetter(methodDescriptor: FunctionDescriptor) = - irClass.contributeFunction(methodDescriptor, fromStubs = true) { getter -> + irClass.contributeFunction(methodDescriptor) { getter -> val serializer = requireNotNull( findTypeSerializer( serializableDescriptor.module, diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt index 37066c3f5ca..5ae986c727a 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt @@ -28,21 +28,18 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen 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.SerialEntityNames.MISSING_FIELD_EXC class SerializableIrGenerator( val irClass: IrClass, - override val compilerContext: BackendContext, + override val compilerContext: SerializationPluginContext, bindingContext: BindingContext ) : 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) = - irClass.contributeConstructor(constructorDescriptor, fromStubs = true, overwriteValueParameters = true) { ctor -> + irClass.contributeConstructor(constructorDescriptor, overwriteValueParameters = true) { ctor -> val transformFieldInitializer = buildInitializersRemapping(irClass) // Missing field exception parts @@ -50,7 +47,7 @@ class SerializableIrGenerator( serializableDescriptor.getClassFromSerializationPackage(MISSING_FIELD_EXC) .unsubstitutedPrimaryConstructor!! val exceptionCtorRef = compilerContext.externalSymbols.referenceConstructor(exceptionCtor) - val exceptionType = exceptionCtorRef.owner.returnType + val exceptionType = exceptionCtor.returnType.toIrType() val serializableProperties = properties.serializableProperties val seenVarsOffset = serializableProperties.bitMaskSlotCount() @@ -166,7 +163,7 @@ class SerializableIrGenerator( companion object { fun generate( irClass: IrClass, - context: BackendContext, + context: SerializationPluginContext, bindingContext: BindingContext ) { val serializableClass = irClass.descriptor diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerForEnumsGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerForEnumsGenerator.kt index ac70d49fc6b..5b169750f9e 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerForEnumsGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerForEnumsGenerator.kt @@ -5,9 +5,9 @@ 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.FunctionDescriptor +import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.IrClass 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.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext 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) { 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 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 = - irInvoke(getValues, arrayGet, irInvoke(irGet(loadFunc.valueParameters[0]), decode, serialDescGetter)) + irInvoke(getValues, arrayGetSymbol, irInvoke(irGet(loadFunc.valueParameters[0]), decode, serialDescGetter)) +irReturn(getValueByOrdinal) } @@ -70,7 +79,7 @@ class SerializerForEnumsGenerator(irClass: IrClass, compilerContext: BackendCont return irInvoke( null, ctor, irString(serialName), - typeHint = ctor.owner.returnType + typeHint = ctor.descriptor.returnType.toIrType() ) } @@ -93,7 +102,7 @@ class SerializerForEnumsGenerator(irClass: IrClass, compilerContext: BackendCont +call // serialDesc.pushAnnotation(...) copySerialInfoAnnotationsToDescriptor( - compilerContext.externalSymbols.referenceClass(entry).owner.annotations, + entry.annotations.mapNotNull(compilerContext.typeTranslator.constantValueGenerator::generateAnnotationConstructorCall), localDescriptor, serialDescImplClass.referenceMethod(CallingConventions.addAnnotation) ) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt index 4c637d0a415..e0d23d54fdb 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt @@ -5,9 +5,8 @@ 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.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.irThrow import org.jetbrains.kotlin.descriptors.* @@ -25,6 +24,7 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen 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.SerialEntityNames.DECODER_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? 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 { - - 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 override fun generateSerialDesc() { @@ -75,30 +69,31 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil val ctor = irClass.declarations.filterIsInstance().find { it.isPrimary } ?: throw AssertionError("Serializer must have primary constructor") compilerContext.localSymbolTable.withScope(initIrBody.descriptor) { - initIrBody.body = compilerContext.createIrBuilder(initIrBody.symbol).irBlockBody { - val localDesc = irTemporary( - instantiateNewDescriptor(serialDescImplClass, irGet(thisAsReceiverParameter)), - nameHint = "serialDesc" - ) + initIrBody.body = + DeclarationIrBuilder(compilerContext, initIrBody.symbol, initIrBody.startOffset, initIrBody.endOffset).irBlockBody { + val localDesc = irTemporary( + instantiateNewDescriptor(serialDescImplClass, irGet(thisAsReceiverParameter)), + nameHint = "serialDesc" + ) - addElementsContentToDescriptor(serialDescImplClass, localDesc, addFuncS) - // add class annotations - copySerialInfoAnnotationsToDescriptor( - serializableIrClass.annotations, - localDesc, - serialDescImplClass.referenceMethod(CallingConventions.addClassAnnotation) - ) + addElementsContentToDescriptor(serialDescImplClass, localDesc, addFuncS) + // add class annotations + copySerialInfoAnnotationsToDescriptor( + serializableIrClass.annotations, + localDesc, + serialDescImplClass.referenceMethod(CallingConventions.addClassAnnotation) + ) - // save local descriptor to field - +irSetField( - generateReceiverExpressionForFieldAccess( - thisAsReceiverParameter.symbol, - generatedSerialDescPropertyDescriptor - ), - prop.backingField!!, - irGet(localDesc) - ) - } + // save local descriptor to field + +irSetField( + generateReceiverExpressionForFieldAccess( + thisAsReceiverParameter.symbol, + generatedSerialDescPropertyDescriptor + ), + prop.backingField!!, + irGet(localDesc) + ) + } (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) return irInvoke( null, serialClassDescImplCtor, - irString(serialName), if (isGeneratedSerializer) correctThis else irNull(), - typeHint = serialClassDescImplCtor.owner.returnType + irString(serialName), if (isGeneratedSerializer) correctThis else irNull() ) } @@ -155,7 +149,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil } 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() val primaryCtor = irClass.constructors.find { it.isPrimary } ?: 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 -> - val allSerializers = serializableProperties.map { requireNotNull( - serializerTower(this@SerializerIrGenerator, irFun.dispatchReceiverParameter!!, it)) { "Property ${it.name} must have a serializer" } + override fun generateChildSerializersGetter(function: FunctionDescriptor) = irClass.contributeFunction(function) { irFun -> + val allSerializers = serializableProperties.map { + 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 @@ -200,7 +196,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil protected fun ClassDescriptor.referenceMethod(methodName: String) = 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? = 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 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( startOffset, endOffset, @@ -269,7 +265,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil 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) // check for call to .shouldEncodeElementDefault @@ -316,7 +312,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil 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) { return@contributeFunction } @@ -393,7 +389,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil inputClass.referenceMethod(it) } 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(localSerialDesc.get(), irInt(index)) if (innerSerial != null) args.add(innerSerial) @@ -421,8 +417,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil irInvoke( null, excClassRef, - indexVar.get(), - typeHint = excClassRef.owner.returnType + indexVar.get() ) ) ) @@ -454,7 +449,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil companion object { fun generate( irClass: IrClass, - context: BackendContext, + context: SerializationPluginContext, bindingContext: BindingContext ) { val serializableDesc = getSerializableClassDescriptorBySerializer(irClass.symbol.descriptor) ?: return diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt index 67762af8a26..3234d0d81b1 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt @@ -5,18 +5,18 @@ 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.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrClass 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.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid 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.SerializableIrGenerator import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializerIrGenerator @@ -37,24 +37,26 @@ fun ClassLoweringPass.runOnFileInOrder(irFile: IrFile) { }) } +typealias SerializationPluginContext = IrPluginContext + private class SerializerClassLowering( - val context: BackendContext, - val bindingContext: BindingContext + val context: SerializationPluginContext ) : IrElementTransformerVoid(), ClassLoweringPass { override fun lower(irClass: IrClass) { - SerializableIrGenerator.generate(irClass, context, bindingContext) - SerializerIrGenerator.generate(irClass, context, bindingContext) - SerializableCompanionIrGenerator.generate(irClass, context, bindingContext) + SerializableIrGenerator.generate(irClass, context, context.bindingContext) + SerializerIrGenerator.generate(irClass, context, context.bindingContext) + SerializableCompanionIrGenerator.generate(irClass, context, context.bindingContext) } } open class SerializationLoweringExtension : IrGenerationExtension { override fun generate( - file: IrFile, - backendContext: BackendContext, - bindingContext: BindingContext + moduleFragment: IrModuleFragment, + pluginContext: IrPluginContext ) { - SerializerClassLowering(backendContext, bindingContext).runOnFileInOrder(file) + val serializerClassLowering = SerializerClassLowering(pluginContext) + for (file in moduleFragment.files) + serializerClassLowering.runOnFileInOrder(file) } } \ No newline at end of file diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen/Basic.ir.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen/Basic.ir.txt index 5934b23bc41..1749899ee82 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen/Basic.ir.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen/Basic.ir.txt @@ -186,8 +186,10 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa ALOAD (4) ALOAD (3) INVOKEINTERFACE (kotlinx/serialization/CompositeEncoder, endStructure, (Lkotlinx/serialization/SerialDescriptor;)V) - RETURN LABEL (L2) + LINENUMBER (13) + RETURN + LABEL (L3) } 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 (3) INVOKEINTERFACE (kotlinx/serialization/CompositeEncoder, endStructure, (Lkotlinx/serialization/SerialDescriptor;)V) - RETURN LABEL (L7) + LINENUMBER (10) + RETURN + LABEL (L8) } 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 (3) INVOKEINTERFACE (kotlinx/serialization/CompositeEncoder, endStructure, (Lkotlinx/serialization/SerialDescriptor;)V) - RETURN LABEL (L2) + LINENUMBER (7) + RETURN + LABEL (L3) } public void serialize(kotlinx.serialization.Encoder p0, java.lang.Object p1) { @@ -957,4 +963,4 @@ public final class User : java/lang/Object { public final java.lang.String getFirstName() public final java.lang.String getLastName() -} +} \ No newline at end of file diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationIDECodegenExtensions.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationIDECodegenExtensions.kt index f56b83420d5..8467edf5a4d 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationIDECodegenExtensions.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationIDECodegenExtensions.kt @@ -5,14 +5,13 @@ 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.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.declaration.DeclarationBodyVisitor import org.jetbrains.kotlin.psi.KtPureClassOrObject -import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlinx.serialization.idea.runIfEnabledOn class SerializationIDECodegenExtension : SerializationCodegenExtension() { @@ -32,7 +31,7 @@ class SerializationIDEJsExtension : SerializationJsExtension() { } 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 newline at end of file