[EE-IR] Fragment Compiler Entrypoint in IR Backend
This commit introduces a new entrypoint for the IR backend, and starts the work of accomodating the evaluator in psi2ir. The evaluator expects a certain class and method structure of the compiled fragment, but PSI is only supplied for the actual fragment. So, to that end, this commit introduces a new "front end" of psi2ir that "synthesizes" the module, class and method structure around the fragment before calling into the existing psi2ir pipeline to obtain the IR for the fragment. The primary complication so far is handling the captured variables of the fragment: they are mapped to parameters of the method surrounding the fragment, and passed as arguments on evaluation. Hence, the IR translation of the fragment needs to remap captured variables to the appropriate parameter, in essentially all places they can be referred to in the fragment (and hence in psi2ir). This commit introduces a decorated symbol table that intercepts symbol look-ups and remaps as appropriate. Other cases that dispatches based on descriptor (see `CallGenerator.kt`) needs other metadata to generate correct code. It also introduces a shim in DeserializedContainerSource in the psi2ir pipeline to facilitate facade class generation for the code that is being debugged (which are generated as "external ir declarations"). Finally, in passing we resolve a small leftover from previous refactoring that left an asssertion re. allowing IR to _assign_ to parameters of methods.
This commit is contained in:
committed by
Alexander Udalov
parent
783c3d1500
commit
247cbffbac
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.SourceFile
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil.getFileClassInfoNoResolve
|
||||
import org.jetbrains.kotlin.load.kotlin.FacadeClassSource
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
|
||||
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
|
||||
// Used from CodeFragmentCompiler for IDE Debugger Plug-In
|
||||
@Suppress("unused")
|
||||
class FacadeClassSourceShimForFragmentCompilation(private val containingFile: PsiSourceFile) :
|
||||
DeserializedContainerSource, FacadeClassSource {
|
||||
|
||||
private val fileClassInfo = getFileClassInfoNoResolve(containingFile.psiFile as KtFile)
|
||||
|
||||
override val incompatibility: IncompatibleVersionErrorData<*>?
|
||||
get() = null
|
||||
override val isPreReleaseInvisible: Boolean
|
||||
get() = false
|
||||
override val abiStability: DeserializedContainerAbiStability
|
||||
get() = DeserializedContainerAbiStability.STABLE
|
||||
override val presentableString: String
|
||||
get() = "Fragment for $containingFile"
|
||||
|
||||
override fun getContainingFile(): SourceFile {
|
||||
return containingFile
|
||||
}
|
||||
|
||||
override val className: JvmClassName
|
||||
get() = JvmClassName.byFqNameWithoutInnerClasses(fileClassInfo.fileClassFqName)
|
||||
override val facadeClassName: JvmClassName?
|
||||
get() = JvmClassName.byFqNameWithoutInnerClasses(fileClassInfo.facadeClassFqName)
|
||||
}
|
||||
+8
-1
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.getParentJavaStaticClassScope
|
||||
import org.jetbrains.kotlin.load.java.sam.JavaSingleAbstractMethodUtils
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.hasEnhancedNullability
|
||||
import org.jetbrains.kotlin.load.kotlin.FacadeClassSource
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -55,10 +56,12 @@ import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmFieldAnnotation
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.isJvmRecord
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.replaceAnnotations
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
open class JvmGeneratorExtensionsImpl(
|
||||
configuration: CompilerConfiguration,
|
||||
@@ -81,6 +84,10 @@ open class JvmGeneratorExtensionsImpl(
|
||||
companion object Instance : JvmSamConversion()
|
||||
}
|
||||
|
||||
override fun getContainerSource(descriptor: DeclarationDescriptor): DeserializedContainerSource? {
|
||||
return descriptor.safeAs<DescriptorWithContainerSource>()?.containerSource
|
||||
}
|
||||
|
||||
override fun computeFieldVisibility(descriptor: PropertyDescriptor): DescriptorVisibility? =
|
||||
if (descriptor.hasJvmFieldAnnotation() || descriptor is JavaCallableMemberDescriptor)
|
||||
descriptor.visibility
|
||||
@@ -98,7 +105,7 @@ open class JvmGeneratorExtensionsImpl(
|
||||
deserializedSource: DeserializedContainerSource,
|
||||
stubGenerator: DeclarationStubGenerator
|
||||
): IrClass? {
|
||||
if (!generateFacades || deserializedSource !is JvmPackagePartSource) return null
|
||||
if (!generateFacades || deserializedSource !is FacadeClassSource) return null
|
||||
val facadeName = deserializedSource.facadeClassName ?: deserializedSource.className
|
||||
return JvmFileFacadeClass(
|
||||
if (deserializedSource.facadeClassName != null) IrDeclarationOrigin.JVM_MULTIFILE_CLASS else IrDeclarationOrigin.FILE_CLASS,
|
||||
|
||||
+24
-3
@@ -34,6 +34,8 @@ import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
|
||||
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
||||
import org.jetbrains.kotlin.psi2ir.generators.DeclarationStubGeneratorImpl
|
||||
import org.jetbrains.kotlin.psi2ir.generators.fragments.EvaluatorFragmentInfo
|
||||
import org.jetbrains.kotlin.psi2ir.generators.fragments.FragmentContext
|
||||
import org.jetbrains.kotlin.psi2ir.generators.generateTypicalIrProviderList
|
||||
import org.jetbrains.kotlin.psi2ir.preprocessing.SourceDeclarationsPreprocessor
|
||||
import org.jetbrains.kotlin.resolve.CleanableBindingContext
|
||||
@@ -44,6 +46,7 @@ open class JvmIrCodegenFactory(
|
||||
private val externalMangler: JvmDescriptorMangler? = null,
|
||||
private val externalSymbolTable: SymbolTable? = null,
|
||||
private val jvmGeneratorExtensions: JvmGeneratorExtensionsImpl = JvmGeneratorExtensionsImpl(configuration),
|
||||
private val evaluatorFragmentInfoForPsi2Ir: EvaluatorFragmentInfo? = null
|
||||
) : CodegenFactory {
|
||||
data class JvmIrBackendInput(
|
||||
val irModuleFragment: IrModuleFragment,
|
||||
@@ -65,7 +68,13 @@ open class JvmIrCodegenFactory(
|
||||
}
|
||||
val psi2ir = Psi2IrTranslator(input.languageVersionSettings, Psi2IrConfiguration(input.ignoreErrors))
|
||||
val messageLogger = input.configuration[IrMessageLogger.IR_MESSAGE_LOGGER] ?: IrMessageLogger.None
|
||||
val psi2irContext = psi2ir.createGeneratorContext(input.module, input.bindingContext, symbolTable, jvmGeneratorExtensions)
|
||||
val psi2irContext = psi2ir.createGeneratorContext(
|
||||
input.module,
|
||||
input.bindingContext,
|
||||
symbolTable,
|
||||
jvmGeneratorExtensions,
|
||||
fragmentContext = if (evaluatorFragmentInfoForPsi2Ir != null) FragmentContext() else null,
|
||||
)
|
||||
val pluginExtensions = IrGenerationExtension.getInstances(input.project)
|
||||
|
||||
val stubGenerator =
|
||||
@@ -134,10 +143,22 @@ open class JvmIrCodegenFactory(
|
||||
}
|
||||
irLinker.deserializeIrModuleHeader(it, kotlinLibrary, _moduleName = it.name.asString())
|
||||
}
|
||||
val irProviders = listOf(irLinker)
|
||||
|
||||
val irProviders = if (evaluatorFragmentInfoForPsi2Ir != null) {
|
||||
listOf(stubGenerator, irLinker)
|
||||
} else {
|
||||
listOf(irLinker)
|
||||
}
|
||||
|
||||
val irModuleFragment =
|
||||
psi2ir.generateModuleFragment(psi2irContext, input.files, irProviders, pluginExtensions, expectDescriptorToSymbol = null)
|
||||
psi2ir.generateModuleFragment(
|
||||
psi2irContext,
|
||||
input.files,
|
||||
irProviders,
|
||||
pluginExtensions,
|
||||
expectDescriptorToSymbol = null,
|
||||
fragmentInfo = evaluatorFragmentInfoForPsi2Ir)
|
||||
|
||||
irLinker.postProcess()
|
||||
|
||||
stubGenerator.unboundSymbolGeneration = true
|
||||
|
||||
Reference in New Issue
Block a user