[K/N] Enable klib IR phases in dynamic driver
Support SpecialBackendChecksPhase and CopyDefaultValuesToActualPhase
This commit is contained in:
committed by
Space Team
parent
73a52b6081
commit
39656209f0
+1
-1
@@ -83,7 +83,7 @@ internal fun makeKonanModuleOpPhase(
|
|||||||
)
|
)
|
||||||
|
|
||||||
internal val specialBackendChecksPhase = makeKonanModuleLoweringPhase(
|
internal val specialBackendChecksPhase = makeKonanModuleLoweringPhase(
|
||||||
::SpecialBackendChecksTraversal,
|
{ SpecialBackendChecksTraversal(it, it.interopBuiltIns, it.ir.symbols, it.irBuiltIns) },
|
||||||
name = "SpecialBackendChecks",
|
name = "SpecialBackendChecks",
|
||||||
description = "Special backend checks"
|
description = "Special backend checks"
|
||||||
)
|
)
|
||||||
|
|||||||
+3
-1
@@ -45,7 +45,7 @@ internal class DynamicCompilerDriver : CompilerDriver() {
|
|||||||
|
|
||||||
private fun produceKlib(engine: PhaseEngine<PhaseContext>, config: KonanConfig, environment: KotlinCoreEnvironment) {
|
private fun produceKlib(engine: PhaseEngine<PhaseContext>, config: KonanConfig, environment: KotlinCoreEnvironment) {
|
||||||
val frontendOutput = engine.useContext(FrontendContextImpl(config)) { it.runFrontend(environment) }
|
val frontendOutput = engine.useContext(FrontendContextImpl(config)) { it.runFrontend(environment) }
|
||||||
if (frontendOutput is FrontendPhaseOutput.ShouldNotGenerateCode) {
|
if (frontendOutput == FrontendPhaseOutput.ShouldNotGenerateCode) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
require(frontendOutput is FrontendPhaseOutput.Full)
|
require(frontendOutput is FrontendPhaseOutput.Full)
|
||||||
@@ -55,8 +55,10 @@ internal class DynamicCompilerDriver : CompilerDriver() {
|
|||||||
val psiToIrContext = PsiToIrContextImpl(config, frontendOutput.moduleDescriptor, frontendOutput.bindingContext)
|
val psiToIrContext = PsiToIrContextImpl(config, frontendOutput.moduleDescriptor, frontendOutput.bindingContext)
|
||||||
val psiToIrOutput = engine.useContext(psiToIrContext) { psiToIrEngine ->
|
val psiToIrOutput = engine.useContext(psiToIrContext) { psiToIrEngine ->
|
||||||
val output = psiToIrEngine.runPsiToIr(frontendOutput, isProducingLibrary = true)
|
val output = psiToIrEngine.runPsiToIr(frontendOutput, isProducingLibrary = true)
|
||||||
|
psiToIrEngine.runSpecialBackendChecks(output)
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
engine.runPhase(CopyDefaultValuesToActualPhase, psiToIrOutput.irModule)
|
||||||
psiToIrOutput
|
psiToIrOutput
|
||||||
}
|
}
|
||||||
val serializerOutput = engine.runSerializer(frontendOutput.moduleDescriptor, psiToIrOutput)
|
val serializerOutput = engine.runSerializer(frontendOutput.moduleDescriptor, psiToIrOutput)
|
||||||
|
|||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.konan.driver.phases
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower
|
||||||
|
import org.jetbrains.kotlin.backend.konan.driver.PhaseContext
|
||||||
|
import org.jetbrains.kotlin.backend.konan.driver.PhaseEngine
|
||||||
|
import org.jetbrains.kotlin.backend.konan.lower.ExpectToActualDefaultValueCopier
|
||||||
|
import org.jetbrains.kotlin.backend.konan.lower.SpecialBackendChecksTraversal
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
|
|
||||||
|
internal val SpecialBackendChecksPhase = createSimpleNamedCompilerPhase<PsiToIrContext, PsiToIrOutput>(
|
||||||
|
"SpecialBackendChecks",
|
||||||
|
"Special backend checks",
|
||||||
|
) { context, input ->
|
||||||
|
SpecialBackendChecksTraversal(context, context.interopBuiltIns, input.symbols, input.irModule.irBuiltins).lower(input.irModule)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal val CopyDefaultValuesToActualPhase = createSimpleNamedCompilerPhase<PhaseContext, IrModuleFragment>(
|
||||||
|
name = "CopyDefaultValuesToActual",
|
||||||
|
description = "Copy default values from expect to actual declarations",
|
||||||
|
) { _, input ->
|
||||||
|
ExpectToActualDefaultValueCopier(input).process()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun <T : PsiToIrContext> PhaseEngine<T>.runSpecialBackendChecks(psiToIrOutput: PsiToIrOutput) {
|
||||||
|
runPhase(SpecialBackendChecksPhase, psiToIrOutput)
|
||||||
|
}
|
||||||
+27
-13
@@ -15,11 +15,13 @@ import org.jetbrains.kotlin.backend.common.push
|
|||||||
import org.jetbrains.kotlin.backend.konan.*
|
import org.jetbrains.kotlin.backend.konan.*
|
||||||
import org.jetbrains.kotlin.backend.konan.cgen.*
|
import org.jetbrains.kotlin.backend.konan.cgen.*
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions
|
import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions
|
||||||
|
import org.jetbrains.kotlin.backend.konan.driver.PhaseContext
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
import org.jetbrains.kotlin.backend.konan.ir.*
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.getSuperClassNotAny
|
import org.jetbrains.kotlin.backend.konan.ir.getSuperClassNotAny
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.IntrinsicType
|
import org.jetbrains.kotlin.backend.konan.llvm.IntrinsicType
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.tryGetIntrinsicType
|
import org.jetbrains.kotlin.backend.konan.llvm.tryGetIntrinsicType
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
@@ -35,14 +37,26 @@ import org.jetbrains.kotlin.types.Variance
|
|||||||
import org.jetbrains.kotlin.utils.fileUtils.descendantRelativeTo
|
import org.jetbrains.kotlin.utils.fileUtils.descendantRelativeTo
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
internal class SpecialBackendChecksTraversal(val context: Context) : FileLoweringPass {
|
/**
|
||||||
override fun lower(irFile: IrFile) = irFile.acceptChildrenVoid(BackendChecker(context, irFile))
|
* Kotlin/Native-specific language checks. Most importantly, it checks C/Objective-C interop restrictions.
|
||||||
|
* TODO: Should be moved to compiler frontend after K2.
|
||||||
|
*/
|
||||||
|
internal class SpecialBackendChecksTraversal(
|
||||||
|
private val context: PhaseContext,
|
||||||
|
private val interop: InteropBuiltIns,
|
||||||
|
private val symbols: KonanSymbols,
|
||||||
|
private val irBuiltIns: IrBuiltIns,
|
||||||
|
) : FileLoweringPass {
|
||||||
|
override fun lower(irFile: IrFile) = irFile.acceptChildrenVoid(BackendChecker(context, interop, symbols, irBuiltIns, irFile))
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BackendChecker(val context: Context, val irFile: IrFile) : IrElementVisitorVoid {
|
private class BackendChecker(
|
||||||
val interop = context.interopBuiltIns
|
private val context: PhaseContext,
|
||||||
val symbols = context.ir.symbols
|
val interop: InteropBuiltIns,
|
||||||
val irBuiltIns = context.irBuiltIns
|
val symbols: KonanSymbols,
|
||||||
|
val irBuiltIns: IrBuiltIns,
|
||||||
|
private val irFile: IrFile,
|
||||||
|
) : IrElementVisitorVoid {
|
||||||
val target = context.config.target
|
val target = context.config.target
|
||||||
|
|
||||||
fun reportError(location: IrElement, message: String): Nothing =
|
fun reportError(location: IrElement, message: String): Nothing =
|
||||||
@@ -95,7 +109,7 @@ private class BackendChecker(val context: Context, val irFile: IrFile) : IrEleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun IrConstructor.isOverrideInit() =
|
private fun IrConstructor.isOverrideInit() =
|
||||||
this.annotations.hasAnnotation(context.interopBuiltIns.objCOverrideInit.fqNameSafe)
|
this.annotations.hasAnnotation(interop.objCOverrideInit.fqNameSafe)
|
||||||
|
|
||||||
private fun checkCanGenerateOverrideInit(irClass: IrClass, constructor: IrConstructor) {
|
private fun checkCanGenerateOverrideInit(irClass: IrClass, constructor: IrConstructor) {
|
||||||
val superClass = irClass.getSuperClassNotAny()!!
|
val superClass = irClass.getSuperClassNotAny()!!
|
||||||
@@ -104,7 +118,7 @@ private class BackendChecker(val context: Context, val irFile: IrFile) : IrEleme
|
|||||||
}.toList()
|
}.toList()
|
||||||
|
|
||||||
val superConstructor = superConstructors.singleOrNull() ?: run {
|
val superConstructor = superConstructors.singleOrNull() ?: run {
|
||||||
val annotation = context.interopBuiltIns.objCOverrideInit.name
|
val annotation = interop.objCOverrideInit.name
|
||||||
if (superConstructors.isEmpty())
|
if (superConstructors.isEmpty())
|
||||||
reportError(constructor,
|
reportError(constructor,
|
||||||
"""
|
"""
|
||||||
@@ -122,7 +136,7 @@ private class BackendChecker(val context: Context, val irFile: IrFile) : IrEleme
|
|||||||
// Remove fake overrides of this init method, also check for explicit overriding:
|
// Remove fake overrides of this init method, also check for explicit overriding:
|
||||||
irClass.declarations.forEach {
|
irClass.declarations.forEach {
|
||||||
if (it is IrSimpleFunction && initMethod.symbol in it.overriddenSymbols && it.isReal) {
|
if (it is IrSimpleFunction && initMethod.symbol in it.overriddenSymbols && it.isReal) {
|
||||||
val annotation = context.interopBuiltIns.objCOverrideInit.name
|
val annotation = interop.objCOverrideInit.name
|
||||||
reportError(constructor,
|
reportError(constructor,
|
||||||
"constructor with @$annotation overrides initializer that is already overridden explicitly"
|
"constructor with @$annotation overrides initializer that is already overridden explicitly"
|
||||||
)
|
)
|
||||||
@@ -138,7 +152,7 @@ private class BackendChecker(val context: Context, val irFile: IrFile) : IrEleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkCanGenerateActionImp(function: IrSimpleFunction) {
|
private fun checkCanGenerateActionImp(function: IrSimpleFunction) {
|
||||||
val action = "@${context.interopBuiltIns.objCAction.name}"
|
val action = "@${interop.objCAction.name}"
|
||||||
|
|
||||||
function.extensionReceiverParameter?.let {
|
function.extensionReceiverParameter?.let {
|
||||||
reportError(it, "$action method must not have extension receiver")
|
reportError(it, "$action method must not have extension receiver")
|
||||||
@@ -162,7 +176,7 @@ private class BackendChecker(val context: Context, val irFile: IrFile) : IrEleme
|
|||||||
private fun checkCanGenerateOutletSetterImp(property: IrProperty) {
|
private fun checkCanGenerateOutletSetterImp(property: IrProperty) {
|
||||||
val descriptor = property.descriptor
|
val descriptor = property.descriptor
|
||||||
|
|
||||||
val outlet = "@${context.interopBuiltIns.objCOutlet.name}"
|
val outlet = "@${interop.objCOutlet.name}"
|
||||||
|
|
||||||
if (!descriptor.isVar)
|
if (!descriptor.isVar)
|
||||||
reportError(property, "$outlet property must be var")
|
reportError(property, "$outlet property must be var")
|
||||||
@@ -243,7 +257,7 @@ private class BackendChecker(val context: Context, val irFile: IrFile) : IrEleme
|
|||||||
if (!hasObjCClassSupertype)
|
if (!hasObjCClassSupertype)
|
||||||
reportError(irClass, "Kotlin implementation of Objective-C protocol must have Objective-C superclass (e.g. NSObject)")
|
reportError(irClass, "Kotlin implementation of Objective-C protocol must have Objective-C superclass (e.g. NSObject)")
|
||||||
|
|
||||||
val methodsOfAny = context.ir.symbols.any.owner.declarations.filterIsInstance<IrSimpleFunction>().toSet()
|
val methodsOfAny = symbols.any.owner.declarations.filterIsInstance<IrSimpleFunction>().toSet()
|
||||||
|
|
||||||
irClass.declarations.filterIsInstance<IrSimpleFunction>().filter { it.isReal }.forEach { method ->
|
irClass.declarations.filterIsInstance<IrSimpleFunction>().filter { it.isReal }.forEach { method ->
|
||||||
val overriddenMethodOfAny = method.allOverriddenFunctions.firstOrNull {
|
val overriddenMethodOfAny = method.allOverriddenFunctions.firstOrNull {
|
||||||
@@ -318,7 +332,7 @@ private class BackendChecker(val context: Context, val irFile: IrFile) : IrEleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (callee.returnType.isNativePointed(symbols) &&
|
if (callee.returnType.isNativePointed(symbols) &&
|
||||||
!callee.hasCCallAnnotation("CppClassConstructor"))
|
!callee.hasCCallAnnotation("CppClassConstructor"))
|
||||||
reportError(expression, "Native interop types constructors must not be called directly")
|
reportError(expression, "Native interop types constructors must not be called directly")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user