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,18 +73,16 @@ 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) {
@@ -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,12 +91,8 @@ private val innerClassesPhase = makeIrFilePhase(
prerequisite = setOf(localDeclarationsPhase) prerequisite = setOf(localDeclarationsPhase)
) )
val jvmPhases = namedIrFilePhase<JvmBackendContext>( private val jvmFilePhases = inventNamesForLocalClassesPhase then
name = "IrLowering",
description = "IR lowering",
lower = expectDeclarationsRemovingPhase then
fileClassPhase then
inventNamesForLocalClassesPhase then
kCallableNamePropertyPhase then kCallableNamePropertyPhase then
arrayConstructorPhase then arrayConstructorPhase then
@@ -160,11 +157,18 @@ val jvmPhases = namedIrFilePhase<JvmBackendContext>(
// should be last transformation // should be last transformation
removeDeclarationsThatWouldBeInlined then removeDeclarationsThatWouldBeInlined then
makePatchParentsPhase(3) makePatchParentsPhase(3)
val jvmPhases = namedIrModulePhase(
name = "IrLowering",
description = "IR lowering",
lower = expectDeclarationsRemovingPhase then
fileClassPhase then
performByIrFile(lower = jvmFilePhases)
) )
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 {