JVM IR: run FileClass & ExpectDeclarationsRemoving phases on whole module

Since we now generate file classes even for IR loaded from dependencies
(see 3a9b94235f) to simplify code in certain lowerings, it makes sense
to do that for all source files together before any meaningful
lowerings. The easiest way to do so is to make FileClassLowering a
module-wide phase.

ExpectDeclarationsRemoveLowering is now also a module-wide phase because
it needs to be run before FileClassLowering (to avoid producing empty
facades for files that only contain `expect` declarations)
This commit is contained in:
Alexander Udalov
2019-07-17 16:55:32 +02:00
parent e867830eab
commit 5341de253f
3 changed files with 88 additions and 84 deletions
@@ -73,20 +73,18 @@ object JvmBackendFacade {
facadeClassGenerator = ::facadeClassGenerator facadeClassGenerator = ::facadeClassGenerator
).generateUnboundSymbolsAsDependencies() ).generateUnboundSymbolsAsDependencies()
val lower = JvmLower(context)
for (irFile in irModuleFragment.files) { for (irFile in irModuleFragment.files) {
try { for (extension in IrGenerationExtension.getInstances(context.state.project)) {
for (extension in IrGenerationExtension.getInstances(context.state.project)) { extension.generate(irFile, context, context.state.bindingContext)
extension.generate(irFile, context, context.state.bindingContext)
}
lower.lower(irFile)
} catch (e: Throwable) {
errorHandler.reportException(e, null) // TODO ktFile.virtualFile.url
} }
} }
try {
JvmLower(context).lower(irModuleFragment)
} catch (e: Throwable) {
errorHandler.reportException(e, null)
}
for (irFile in irModuleFragment.files) { for (irFile in irModuleFragment.files) {
try { try {
for (loweredClass in irFile.declarations) { for (loweredClass in irFile.declarations) {
@@ -98,7 +96,7 @@ object JvmBackendFacade {
} }
state.afterIndependentPart() state.afterIndependentPart()
} catch (e: Throwable) { } catch (e: Throwable) {
errorHandler.reportException(e, null) errorHandler.reportException(e, null) // TODO ktFile.virtualFile.url
} }
} }
} }
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.jvm.lower.*
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
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.util.PatchDeclarationParentsVisitor import org.jetbrains.kotlin.ir.util.PatchDeclarationParentsVisitor
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
@@ -41,7 +42,7 @@ private val arrayConstructorPhase = makeIrFilePhase(
description = "Transform `Array(size) { index -> value }` into a loop" description = "Transform `Array(size) { index -> value }` into a loop"
) )
private val expectDeclarationsRemovingPhase = makeIrFilePhase( private val expectDeclarationsRemovingPhase = makeIrModulePhase(
::ExpectDeclarationsRemoveLowering, ::ExpectDeclarationsRemoveLowering,
name = "ExpectDeclarationsRemoving", name = "ExpectDeclarationsRemoving",
description = "Remove expect declaration from module fragment" description = "Remove expect declaration from module fragment"
@@ -90,81 +91,84 @@ private val innerClassesPhase = makeIrFilePhase(
prerequisite = setOf(localDeclarationsPhase) prerequisite = setOf(localDeclarationsPhase)
) )
val jvmPhases = namedIrFilePhase<JvmBackendContext>( private val jvmFilePhases = inventNamesForLocalClassesPhase then
kCallableNamePropertyPhase then
arrayConstructorPhase then
lateinitPhase then
moveOrCopyCompanionObjectFieldsPhase then
inlineCallableReferenceToLambdaPhase then
propertyReferencePhase then
constPhase then
propertiesToFieldsPhase then
propertiesPhase then
renameFieldsPhase then
annotationPhase then
tailrecPhase then
jvmInlineClassPhase then
sharedVariablesPhase then
makePatchParentsPhase(1) then
enumWhenPhase then
singletonReferencesPhase then
localDeclarationsPhase then
defaultArgumentStubPhase then
interfacePhase then
interfaceDelegationPhase then
interfaceSuperCallsPhase then
singleAbstractMethodPhase then
addContinuationPhase then
callableReferencePhase then
functionNVarargInvokePhase then
innerClassesPhase then
innerClassConstructorCallsPhase then
forLoopsPhase then
makePatchParentsPhase(2) then
enumClassPhase then
objectClassPhase then
makeInitializersPhase(JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, true) then
syntheticAccessorPhase then
collectionStubMethodLowering then
bridgePhase then
jvmOverloadsAnnotationPhase then
jvmDefaultConstructorPhase then
jvmStaticAnnotationPhase then
staticDefaultFunctionPhase then
toArrayPhase then
flattenStringConcatenationPhase then
foldConstantLoweringPhase then
computeStringTrimPhase then
jvmBuiltinOptimizationLoweringPhase then
additionalClassAnnotationPhase then
recordNamesForKotlinTypeMapperPhase then
// should be last transformation
removeDeclarationsThatWouldBeInlined then
makePatchParentsPhase(3)
val jvmPhases = namedIrModulePhase(
name = "IrLowering", name = "IrLowering",
description = "IR lowering", description = "IR lowering",
lower = expectDeclarationsRemovingPhase then lower = expectDeclarationsRemovingPhase then
fileClassPhase then fileClassPhase then
inventNamesForLocalClassesPhase then performByIrFile(lower = jvmFilePhases)
kCallableNamePropertyPhase then
arrayConstructorPhase then
lateinitPhase then
moveOrCopyCompanionObjectFieldsPhase then
inlineCallableReferenceToLambdaPhase then
propertyReferencePhase then
constPhase then
propertiesToFieldsPhase then
propertiesPhase then
renameFieldsPhase then
annotationPhase then
tailrecPhase then
jvmInlineClassPhase then
sharedVariablesPhase then
makePatchParentsPhase(1) then
enumWhenPhase then
singletonReferencesPhase then
localDeclarationsPhase then
defaultArgumentStubPhase then
interfacePhase then
interfaceDelegationPhase then
interfaceSuperCallsPhase then
singleAbstractMethodPhase then
addContinuationPhase then
callableReferencePhase then
functionNVarargInvokePhase then
innerClassesPhase then
innerClassConstructorCallsPhase then
forLoopsPhase then
makePatchParentsPhase(2) then
enumClassPhase then
objectClassPhase then
makeInitializersPhase(JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, true) then
syntheticAccessorPhase then
collectionStubMethodLowering then
bridgePhase then
jvmOverloadsAnnotationPhase then
jvmDefaultConstructorPhase then
jvmStaticAnnotationPhase then
staticDefaultFunctionPhase then
toArrayPhase then
flattenStringConcatenationPhase then
foldConstantLoweringPhase then
computeStringTrimPhase then
jvmBuiltinOptimizationLoweringPhase then
additionalClassAnnotationPhase then
recordNamesForKotlinTypeMapperPhase then
// should be last transformation
removeDeclarationsThatWouldBeInlined then
makePatchParentsPhase(3)
) )
class JvmLower(val context: JvmBackendContext) { class JvmLower(val context: JvmBackendContext) {
fun lower(irFile: IrFile) { fun lower(irModuleFragment: IrModuleFragment) {
// TODO run lowering passes as callbacks in bottom-up visitor // TODO run lowering passes as callbacks in bottom-up visitor
jvmPhases.invokeToplevel(context.phaseConfig, context, irFile) jvmPhases.invokeToplevel(context.phaseConfig, context, irModuleFragment)
} }
} }
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassDescriptor
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.phaser.makeIrModulePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
@@ -33,15 +33,17 @@ import org.jetbrains.kotlin.psi2ir.PsiSourceManager
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import java.util.* import java.util.*
internal val fileClassPhase = makeIrFilePhase( internal val fileClassPhase = makeIrModulePhase(
::FileClassLowering, ::FileClassLowering,
name = "FileClass", name = "FileClass",
description = "Put file level function and property declaration into a class", description = "Put file level function and property declaration into a class",
stickyPostconditions = setOf(::checkAllFileLevelDeclarationsAreClasses) stickyPostconditions = setOf(::checkAllFileLevelDeclarationsAreClasses)
) )
private fun checkAllFileLevelDeclarationsAreClasses(irFile: IrFile) { private fun checkAllFileLevelDeclarationsAreClasses(irModuleFragment: IrModuleFragment) {
assert(irFile.declarations.all { it is IrClass }) assert(irModuleFragment.files.all { irFile ->
irFile.declarations.all { it is IrClass }
})
} }
private class FileClassLowering(val context: JvmBackendContext) : FileLoweringPass { private class FileClassLowering(val context: JvmBackendContext) : FileLoweringPass {