[K/N][IR] Made the compiler pipeline to do per file lowerings
This commit is contained in:
+9
-1
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.ir.KonanIr
|
||||
import org.jetbrains.kotlin.library.SerializedMetadata
|
||||
@@ -47,6 +48,7 @@ import org.jetbrains.kotlin.backend.konan.serialization.KonanIrLinker
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.SerializedClassFields
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.SerializedInlineFunctionReference
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -57,7 +59,7 @@ import org.jetbrains.kotlin.konan.util.disposeNativeMemoryAllocator
|
||||
import org.jetbrains.kotlin.library.SerializedIrModule
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
||||
|
||||
internal class InlineFunctionOriginInfo(val irFile: IrFile, val startOffset: Int, val endOffset: Int)
|
||||
internal class InlineFunctionOriginInfo(val irFunction: IrFunction, val irFile: IrFile, val startOffset: Int, val endOffset: Int)
|
||||
|
||||
/**
|
||||
* Offset for synthetic elements created by lowerings and not attributable to other places in the source code.
|
||||
@@ -73,7 +75,13 @@ internal class SpecialDeclarationsFactory(val context: Context) {
|
||||
|
||||
private val bridges = mutableMapOf<BridgeKey, IrSimpleFunction>()
|
||||
|
||||
private val notLoweredInlineFunctions = mutableMapOf<IrFunctionSymbol, IrFunction>()
|
||||
val loweredInlineFunctions = mutableMapOf<IrFunction, InlineFunctionOriginInfo>()
|
||||
fun getNonLoweredInlineFunction(function: IrFunction): IrFunction {
|
||||
return notLoweredInlineFunctions.getOrPut(function.symbol) {
|
||||
function.deepCopyWithVariables().also { it.patchDeclarationParents(function.parent) }
|
||||
}
|
||||
}
|
||||
|
||||
object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS :
|
||||
IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS")
|
||||
|
||||
+57
-57
@@ -22,8 +22,12 @@ import org.jetbrains.kotlin.backend.konan.lower.*
|
||||
import org.jetbrains.kotlin.backend.konan.lower.FinallyBlocksLowering
|
||||
import org.jetbrains.kotlin.backend.konan.lower.InitializersLowering
|
||||
import org.jetbrains.kotlin.backend.konan.optimizations.KonanBCEForLoopBodyTransformer
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
|
||||
private val validateAll = false
|
||||
|
||||
@@ -89,13 +93,21 @@ internal val specialBackendChecksPhase = konanUnitPhase(
|
||||
description = "Special backend checks"
|
||||
)
|
||||
|
||||
internal val removeExpectDeclarationsPhase = makeKonanModuleLoweringPhase(
|
||||
internal val propertyAccessorInlinePhase = makeKonanModuleLoweringPhase(
|
||||
::PropertyAccessorInlineLowering,
|
||||
name = "PropertyAccessorInline",
|
||||
description = "Property accessor inline lowering"
|
||||
)
|
||||
|
||||
/* IrFile phases */
|
||||
|
||||
internal val removeExpectDeclarationsPhase = makeKonanFileLoweringPhase(
|
||||
::ExpectDeclarationsRemoving,
|
||||
name = "RemoveExpectDeclarations",
|
||||
description = "Expect declarations removing"
|
||||
)
|
||||
|
||||
internal val stripTypeAliasDeclarationsPhase = makeKonanModuleLoweringPhase(
|
||||
internal val stripTypeAliasDeclarationsPhase = makeKonanFileLoweringPhase(
|
||||
{ StripTypeAliasDeclarationsLowering() },
|
||||
name = "StripTypeAliasDeclarations",
|
||||
description = "Strip typealias declarations"
|
||||
@@ -107,102 +119,90 @@ internal val annotationImplementationPhase = makeKonanFileLoweringPhase(
|
||||
description = "Create synthetic annotations implementations and use them in annotations constructor calls"
|
||||
)
|
||||
|
||||
internal val lowerBeforeInlinePhase = makeKonanModuleLoweringPhase(
|
||||
internal val lowerBeforeInlinePhase = makeKonanFileLoweringPhase(
|
||||
::PreInlineLowering,
|
||||
name = "LowerBeforeInline",
|
||||
description = "Special operations processing before inlining"
|
||||
)
|
||||
|
||||
internal val arrayConstructorPhase = makeKonanModuleLoweringPhase(
|
||||
internal val arrayConstructorPhase = makeKonanFileLoweringPhase(
|
||||
::ArrayConstructorLowering,
|
||||
name = "ArrayConstructor",
|
||||
description = "Transform `Array(size) { index -> value }` into a loop"
|
||||
)
|
||||
|
||||
internal val lateinitPhase = makeKonanModuleOpPhase(
|
||||
{ context, irModule ->
|
||||
NullableFieldsForLateinitCreationLowering(context).lower(irModule)
|
||||
NullableFieldsDeclarationLowering(context).lower(irModule)
|
||||
LateinitUsageLowering(context).lower(irModule)
|
||||
internal val lateinitPhase = makeKonanFileOpPhase(
|
||||
{ context, irFile ->
|
||||
NullableFieldsForLateinitCreationLowering(context).lower(irFile)
|
||||
NullableFieldsDeclarationLowering(context).lower(irFile)
|
||||
LateinitUsageLowering(context).lower(irFile)
|
||||
},
|
||||
name = "Lateinit",
|
||||
description = "Lateinit properties lowering"
|
||||
)
|
||||
|
||||
internal val propertyAccessorInlinePhase = makeKonanModuleLoweringPhase(
|
||||
::PropertyAccessorInlineLowering,
|
||||
name = "PropertyAccessorInline",
|
||||
description = "Property accessor inline lowering"
|
||||
)
|
||||
|
||||
internal val sharedVariablesPhase = makeKonanModuleLoweringPhase(
|
||||
internal val sharedVariablesPhase = makeKonanFileLoweringPhase(
|
||||
::SharedVariablesLowering,
|
||||
name = "SharedVariables",
|
||||
description = "Shared variable lowering",
|
||||
prerequisite = setOf(lateinitPhase)
|
||||
)
|
||||
|
||||
internal val inventNamesForLocalClasses = makeKonanModuleLoweringPhase(
|
||||
::NativeInventNamesForLocalClasses,
|
||||
internal val inventNamesForLocalClasses = makeKonanFileLoweringPhase(
|
||||
{ NativeInventNamesForLocalClasses(it) },
|
||||
name = "InventNamesForLocalClasses",
|
||||
description = "Invent names for local classes and anonymous objects"
|
||||
)
|
||||
|
||||
internal val extractLocalClassesFromInlineBodies = NamedCompilerPhase(
|
||||
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<IrModuleFragment>, context: Context, input: IrModuleFragment): IrModuleFragment {
|
||||
LocalClassesInInlineLambdasLowering(context).run {
|
||||
input.files.forEach { lower(it) }
|
||||
}
|
||||
LocalClassesInInlineFunctionsLowering(context).run {
|
||||
input.files.forEach { lower(it) }
|
||||
}
|
||||
LocalClassesExtractionFromInlineFunctionsLowering(context).run {
|
||||
input.files.forEach { lower(it) }
|
||||
}
|
||||
return input
|
||||
}
|
||||
internal val extractLocalClassesFromInlineBodies = makeKonanFileOpPhase(
|
||||
{ context, irFile ->
|
||||
LocalClassesInInlineLambdasLowering(context).lower(irFile)
|
||||
LocalClassesInInlineFunctionsLowering(context).lower(irFile)
|
||||
LocalClassesExtractionFromInlineFunctionsLowering(context).lower(irFile)
|
||||
},
|
||||
name = "ExtractLocalClassesFromInlineBodies",
|
||||
description = "Extraction of local classes from inline bodies",
|
||||
prerequisite = setOf(sharedVariablesPhase), // TODO: add "soft" dependency on inventNamesForLocalClasses
|
||||
nlevels = 0,
|
||||
actions = modulePhaseActions
|
||||
)
|
||||
|
||||
internal val inlinePhase = NamedCompilerPhase(
|
||||
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<IrModuleFragment>, context: Context, input: IrModuleFragment): IrModuleFragment {
|
||||
FunctionInlining(context, NativeInlineFunctionResolver(context)).run {
|
||||
input.files.forEach { lower(it) }
|
||||
internal val inlinePhase = makeKonanFileOpPhase(
|
||||
{ context, irFile ->
|
||||
irFile.acceptChildrenVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
return input
|
||||
}
|
||||
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
if (declaration.isInline)
|
||||
context.specialDeclarationsFactory.getNonLoweredInlineFunction(declaration)
|
||||
declaration.acceptChildrenVoid(this)
|
||||
}
|
||||
})
|
||||
|
||||
FunctionInlining(context, NativeInlineFunctionResolver(context)).lower(irFile)
|
||||
},
|
||||
name = "Inline",
|
||||
description = "Functions inlining",
|
||||
prerequisite = setOf(lowerBeforeInlinePhase, arrayConstructorPhase, extractLocalClassesFromInlineBodies),
|
||||
nlevels = 0,
|
||||
actions = modulePhaseActions
|
||||
prerequisite = setOf(lowerBeforeInlinePhase, arrayConstructorPhase, extractLocalClassesFromInlineBodies)
|
||||
)
|
||||
|
||||
internal val lowerAfterInlinePhase = makeKonanModuleOpPhase(
|
||||
{ context, irModule ->
|
||||
irModule.files.forEach(PostInlineLowering(context)::lower)
|
||||
// TODO: Seems like this should be deleted in PsiToIR.
|
||||
irModule.files.forEach(ContractsDslRemover(context)::lower)
|
||||
},
|
||||
name = "LowerAfterInline",
|
||||
description = "Special operations processing after inlining"
|
||||
internal val postInlinePhase = makeKonanFileLoweringPhase(
|
||||
{ PostInlineLowering(it) },
|
||||
name = "PostInline",
|
||||
description = "Post-processing after inlining"
|
||||
)
|
||||
|
||||
/* IrFile phases */
|
||||
internal val contractsDslRemovePhase = makeKonanFileLoweringPhase(
|
||||
{ ContractsDslRemover(it) },
|
||||
name = "RemoveContractsDsl",
|
||||
description = "Contracts dsl removing"
|
||||
)
|
||||
|
||||
// TODO make all lambda-related stuff work with IrFunctionExpression and drop this phase (see kotlin: dd3f8ecaacd)
|
||||
internal val provisionalFunctionExpressionPhase = makeKonanModuleLoweringPhase(
|
||||
{ ProvisionalFunctionExpressionLowering() },
|
||||
name = "FunctionExpression-before-inliner",
|
||||
description = "Transform IrFunctionExpression to a local function reference"
|
||||
internal val provisionalFunctionExpressionPhase = makeKonanFileLoweringPhase(
|
||||
{ ProvisionalFunctionExpressionLowering() },
|
||||
name = "FunctionExpression",
|
||||
description = "Transform IrFunctionExpression to a local function reference"
|
||||
)
|
||||
|
||||
internal val flattenStringConcatenationPhase = makeKonanFileLoweringPhase(
|
||||
|
||||
+51
-50
@@ -256,56 +256,57 @@ internal val allLoweringsPhase = NamedCompilerPhase(
|
||||
name = "IrLowering",
|
||||
description = "IR Lowering",
|
||||
// TODO: The lowerings before inlinePhase should be aligned with [NativeInlineFunctionResolver.kt]
|
||||
lower = removeExpectDeclarationsPhase then
|
||||
stripTypeAliasDeclarationsPhase then
|
||||
lowerBeforeInlinePhase then
|
||||
arrayConstructorPhase then
|
||||
lateinitPhase then
|
||||
sharedVariablesPhase then
|
||||
inventNamesForLocalClasses then
|
||||
extractLocalClassesFromInlineBodies then
|
||||
inlinePhase then
|
||||
provisionalFunctionExpressionPhase then
|
||||
lowerAfterInlinePhase then
|
||||
performByIrFile(
|
||||
name = "IrLowerByFile",
|
||||
description = "IR Lowering by file",
|
||||
lower = listOf(
|
||||
annotationImplementationPhase,
|
||||
rangeContainsLoweringPhase,
|
||||
forLoopsPhase,
|
||||
flattenStringConcatenationPhase,
|
||||
foldConstantLoweringPhase,
|
||||
computeStringTrimPhase,
|
||||
stringConcatenationPhase,
|
||||
enumConstructorsPhase,
|
||||
initializersPhase,
|
||||
localFunctionsPhase,
|
||||
tailrecPhase,
|
||||
defaultParameterExtentPhase,
|
||||
innerClassPhase,
|
||||
dataClassesPhase,
|
||||
ifNullExpressionsFusionPhase,
|
||||
testProcessorPhase,
|
||||
delegationPhase,
|
||||
functionReferencePhase,
|
||||
singleAbstractMethodPhase,
|
||||
enumWhenPhase,
|
||||
builtinOperatorPhase,
|
||||
finallyBlocksPhase,
|
||||
enumClassPhase,
|
||||
enumUsagePhase,
|
||||
interopPhase,
|
||||
varargPhase,
|
||||
kotlinNothingValueExceptionPhase,
|
||||
coroutinesPhase,
|
||||
typeOperatorPhase,
|
||||
expressionBodyTransformPhase,
|
||||
fileInitializersPhase,
|
||||
bridgesPhase,
|
||||
autoboxPhase,
|
||||
)
|
||||
),
|
||||
lower = performByIrFile(
|
||||
name = "IrLowerByFile",
|
||||
description = "IR Lowering by file",
|
||||
lower = listOf(
|
||||
removeExpectDeclarationsPhase,
|
||||
stripTypeAliasDeclarationsPhase,
|
||||
lowerBeforeInlinePhase,
|
||||
arrayConstructorPhase,
|
||||
lateinitPhase,
|
||||
sharedVariablesPhase,
|
||||
inventNamesForLocalClasses,
|
||||
extractLocalClassesFromInlineBodies,
|
||||
inlinePhase,
|
||||
provisionalFunctionExpressionPhase,
|
||||
postInlinePhase,
|
||||
contractsDslRemovePhase,
|
||||
annotationImplementationPhase,
|
||||
rangeContainsLoweringPhase,
|
||||
forLoopsPhase,
|
||||
flattenStringConcatenationPhase,
|
||||
foldConstantLoweringPhase,
|
||||
computeStringTrimPhase,
|
||||
stringConcatenationPhase,
|
||||
enumConstructorsPhase,
|
||||
initializersPhase,
|
||||
localFunctionsPhase,
|
||||
tailrecPhase,
|
||||
defaultParameterExtentPhase,
|
||||
innerClassPhase,
|
||||
dataClassesPhase,
|
||||
ifNullExpressionsFusionPhase,
|
||||
testProcessorPhase,
|
||||
delegationPhase,
|
||||
functionReferencePhase,
|
||||
singleAbstractMethodPhase,
|
||||
enumWhenPhase,
|
||||
builtinOperatorPhase,
|
||||
finallyBlocksPhase,
|
||||
enumClassPhase,
|
||||
enumUsagePhase,
|
||||
interopPhase,
|
||||
varargPhase,
|
||||
kotlinNothingValueExceptionPhase,
|
||||
coroutinesPhase,
|
||||
typeOperatorPhase,
|
||||
expressionBodyTransformPhase,
|
||||
fileInitializersPhase,
|
||||
bridgesPhase,
|
||||
autoboxPhase,
|
||||
)
|
||||
),
|
||||
actions = setOf(defaultDumper, ::moduleValidationCallback)
|
||||
)
|
||||
|
||||
|
||||
+19
-17
@@ -26,44 +26,46 @@ internal class NativeInlineFunctionResolver(override val context: Context) : Def
|
||||
override fun getFunctionDeclaration(symbol: IrFunctionSymbol): IrFunction {
|
||||
val function = super.getFunctionDeclaration(symbol)
|
||||
|
||||
if (function in context.specialDeclarationsFactory.loweredInlineFunctions)
|
||||
return function
|
||||
context.specialDeclarationsFactory.loweredInlineFunctions[function]?.let { return it.irFunction }
|
||||
|
||||
val packageFragment = function.findPackage()
|
||||
if (packageFragment !is IrExternalPackageFragment) {
|
||||
context.specialDeclarationsFactory.loweredInlineFunctions[function] =
|
||||
InlineFunctionOriginInfo(function.file, function.startOffset, function.endOffset)
|
||||
val notLoweredFunction = if (packageFragment !is IrExternalPackageFragment) {
|
||||
context.specialDeclarationsFactory.getNonLoweredInlineFunction(function).also {
|
||||
context.specialDeclarationsFactory.loweredInlineFunctions[function] =
|
||||
InlineFunctionOriginInfo(it, function.file, function.startOffset, function.endOffset)
|
||||
}
|
||||
} else {
|
||||
// The function is from Lazy IR, get its body from the IR linker.
|
||||
val moduleDescriptor = packageFragment.packageFragmentDescriptor.containingDeclaration
|
||||
val moduleDeserializer = context.irLinker.cachedLibraryModuleDeserializers[moduleDescriptor]
|
||||
?: error("No module deserializer for ${function.render()}")
|
||||
context.specialDeclarationsFactory.loweredInlineFunctions[function] = moduleDeserializer.deserializeInlineFunction(function)
|
||||
function
|
||||
}
|
||||
|
||||
val body = function.body ?: return function
|
||||
val body = notLoweredFunction.body ?: return notLoweredFunction
|
||||
|
||||
PreInlineLowering(context).lower(body, function, context.specialDeclarationsFactory.loweredInlineFunctions[function]!!.irFile)
|
||||
PreInlineLowering(context).lower(body, notLoweredFunction, context.specialDeclarationsFactory.loweredInlineFunctions[function]!!.irFile)
|
||||
|
||||
ArrayConstructorLowering(context).lower(body, function)
|
||||
ArrayConstructorLowering(context).lower(body, notLoweredFunction)
|
||||
|
||||
NullableFieldsForLateinitCreationLowering(context).lowerWithLocalDeclarations(function)
|
||||
NullableFieldsDeclarationLowering(context).lowerWithLocalDeclarations(function)
|
||||
LateinitUsageLowering(context).lower(body, function)
|
||||
NullableFieldsForLateinitCreationLowering(context).lowerWithLocalDeclarations(notLoweredFunction)
|
||||
NullableFieldsDeclarationLowering(context).lowerWithLocalDeclarations(notLoweredFunction)
|
||||
LateinitUsageLowering(context).lower(body, notLoweredFunction)
|
||||
|
||||
SharedVariablesLowering(context).lower(body, function)
|
||||
SharedVariablesLowering(context).lower(body, notLoweredFunction)
|
||||
|
||||
OuterThisLowering(context).lower(function)
|
||||
OuterThisLowering(context).lower(notLoweredFunction)
|
||||
|
||||
LocalClassesInInlineLambdasLowering(context).lower(body, function)
|
||||
LocalClassesInInlineLambdasLowering(context).lower(body, notLoweredFunction)
|
||||
|
||||
if (context.llvmModuleSpecification.containsPackageFragment(packageFragment)) {
|
||||
// Do not extract local classes off of inline functions from cached libraries.
|
||||
LocalClassesInInlineFunctionsLowering(context).lower(body, function)
|
||||
LocalClassesExtractionFromInlineFunctionsLowering(context).lower(body, function)
|
||||
LocalClassesInInlineFunctionsLowering(context).lower(body, notLoweredFunction)
|
||||
LocalClassesExtractionFromInlineFunctionsLowering(context).lower(body, notLoweredFunction)
|
||||
}
|
||||
|
||||
return function
|
||||
return notLoweredFunction
|
||||
}
|
||||
|
||||
private fun DeclarationTransformer.lowerWithLocalDeclarations(function: IrFunction) {
|
||||
|
||||
+2
-1
@@ -711,6 +711,7 @@ internal class KonanIrLinker(
|
||||
if (function.parents.any { (it as? IrFunction)?.isInline == true}) {
|
||||
// Already deserialized by the top-most inline function.
|
||||
return InlineFunctionOriginInfo(
|
||||
function,
|
||||
inlineFunctionFiles[packageFragment]
|
||||
?: error("${function.render()} should've been deserialized along with its parent"),
|
||||
function.startOffset, function.endOffset
|
||||
@@ -777,7 +778,7 @@ internal class KonanIrLinker(
|
||||
}
|
||||
inlineFunctionFiles[packageFragment] = fileDeserializationInfo.file
|
||||
|
||||
return InlineFunctionOriginInfo(fileDeserializationInfo.file, inlineFunctionReference.startOffset, inlineFunctionReference.endOffset)
|
||||
return InlineFunctionOriginInfo(function, fileDeserializationInfo.file, inlineFunctionReference.startOffset, inlineFunctionReference.endOffset)
|
||||
}
|
||||
|
||||
private val classesFields by lazy {
|
||||
|
||||
Reference in New Issue
Block a user