Split ObjCExport header and code generation phases
This commit is contained in:
committed by
SvyatoslavScherbina
parent
2b8dcfc533
commit
91ba661f46
+3
@@ -56,6 +56,7 @@ import java.lang.System.out
|
||||
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
||||
import kotlin.reflect.KProperty
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
||||
|
||||
/**
|
||||
@@ -207,6 +208,8 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||
|
||||
lateinit var moduleDescriptor: ModuleDescriptor
|
||||
|
||||
lateinit var objCExport: ObjCExport
|
||||
|
||||
override val builtIns: KonanBuiltIns by lazy(PUBLICATION) {
|
||||
moduleDescriptor.builtIns as KonanBuiltIns
|
||||
}
|
||||
|
||||
+10
@@ -8,6 +8,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
|
||||
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.lower.ExpectToActualDefaultValueCopier
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.*
|
||||
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
@@ -47,6 +48,14 @@ internal val frontendPhase = konanUnitPhase(
|
||||
description = "Frontend builds AST"
|
||||
)
|
||||
|
||||
internal val objCExportPhase = konanUnitPhase(
|
||||
op = {
|
||||
objCExport = ObjCExport(this)
|
||||
},
|
||||
name = "ObjCExport",
|
||||
description = "Objective-C header generation"
|
||||
)
|
||||
|
||||
internal val psiToIrPhase = konanUnitPhase(
|
||||
op = {
|
||||
// Translate AST to high level IR.
|
||||
@@ -273,6 +282,7 @@ internal val toplevelPhase = namedUnitPhase(
|
||||
name = "Compiler",
|
||||
description = "The whole compilation process",
|
||||
lower = frontendPhase then
|
||||
objCExportPhase then
|
||||
psiToIrPhase then
|
||||
irGeneratorPluginsPhase then
|
||||
copyDefaultValuesToActualPhase then
|
||||
|
||||
+1
-1
@@ -314,7 +314,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
declaration.acceptChildrenVoid(this)
|
||||
|
||||
// Note: it is here because it also generates some bitcode.
|
||||
ObjCExport(codegen).produce()
|
||||
context.objCExport.generate(codegen)
|
||||
|
||||
codegen.objCDataGenerator?.finishModule()
|
||||
|
||||
|
||||
+51
-20
@@ -5,12 +5,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.objcexport
|
||||
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.getPackageFragments
|
||||
import org.jetbrains.kotlin.backend.konan.getExportedDependencies
|
||||
import org.jetbrains.kotlin.backend.konan.isNativeBinary
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.CodeGenerator
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.objcexport.ObjCExportCodeGenerator
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SourceFile
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
@@ -20,23 +24,53 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.isSubpackageOf
|
||||
|
||||
internal class ObjCExport(val codegen: CodeGenerator) {
|
||||
val context get() = codegen.context
|
||||
internal class ObjCExportedInterface(
|
||||
val generatedClasses: Set<ClassDescriptor>,
|
||||
val categoryMembers: Map<ClassDescriptor, List<CallableMemberDescriptor>>,
|
||||
val topLevel: Map<SourceFile, List<CallableMemberDescriptor>>,
|
||||
val headerLines: List<String>,
|
||||
val namer: ObjCExportNamer,
|
||||
val mapper: ObjCExportMapper
|
||||
)
|
||||
|
||||
internal class ObjCExport(val context: Context) {
|
||||
private val target get() = context.config.target
|
||||
|
||||
internal fun produce() {
|
||||
private val exportedInterface = produceInterface()
|
||||
|
||||
private fun produceInterface(): ObjCExportedInterface? {
|
||||
if (target.family != Family.IOS && target.family != Family.OSX) return null
|
||||
|
||||
if (!context.config.produce.isNativeBinary) return null // TODO: emit RTTI to the same modules as classes belong to.
|
||||
|
||||
val produceFramework = context.config.produce == CompilerOutputKind.FRAMEWORK
|
||||
|
||||
return if (produceFramework) {
|
||||
val mapper = ObjCExportMapper()
|
||||
val moduleDescriptors = listOf(context.moduleDescriptor) + context.getExportedDependencies()
|
||||
val namer = ObjCExportNamerImpl(
|
||||
moduleDescriptors.toSet(),
|
||||
context.moduleDescriptor.builtIns,
|
||||
mapper,
|
||||
context.moduleDescriptor.namePrefix,
|
||||
local = false
|
||||
)
|
||||
val headerGenerator = ObjCExportHeaderGeneratorImpl(context, moduleDescriptors, mapper, namer)
|
||||
headerGenerator.translateModule()
|
||||
headerGenerator.buildInterface()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
internal fun generate(codegen: CodeGenerator) {
|
||||
if (target.family != Family.IOS && target.family != Family.OSX) return
|
||||
|
||||
if (!context.config.produce.isNativeBinary) return // TODO: emit RTTI to the same modules as classes belong to.
|
||||
|
||||
val produceFramework = context.config.produce == CompilerOutputKind.FRAMEWORK
|
||||
|
||||
val mapper = ObjCExportMapper()
|
||||
val exportedDependencies = if (produceFramework) context.getExportedDependencies() else emptyList()
|
||||
val moduleDescriptors = listOf(context.moduleDescriptor) + exportedDependencies
|
||||
val namer = ObjCExportNamerImpl(
|
||||
moduleDescriptors.toSet(),
|
||||
val mapper = exportedInterface?.mapper ?: ObjCExportMapper()
|
||||
val namer = exportedInterface?.namer ?: ObjCExportNamerImpl(
|
||||
setOf(codegen.context.moduleDescriptor),
|
||||
context.moduleDescriptor.builtIns,
|
||||
mapper,
|
||||
context.moduleDescriptor.namePrefix,
|
||||
@@ -45,23 +79,20 @@ internal class ObjCExport(val codegen: CodeGenerator) {
|
||||
|
||||
val objCCodeGenerator = ObjCExportCodeGenerator(codegen, namer, mapper)
|
||||
|
||||
if (produceFramework) {
|
||||
val headerGenerator = ObjCExportHeaderGeneratorImpl(context, moduleDescriptors, mapper, namer)
|
||||
produceFrameworkSpecific(headerGenerator)
|
||||
if (exportedInterface != null) {
|
||||
produceFrameworkSpecific(exportedInterface.headerLines)
|
||||
|
||||
objCCodeGenerator.generate(
|
||||
generatedClasses = headerGenerator.generatedClasses,
|
||||
categoryMembers = headerGenerator.extensions,
|
||||
topLevel = headerGenerator.topLevel
|
||||
generatedClasses = exportedInterface.generatedClasses,
|
||||
categoryMembers = exportedInterface.categoryMembers,
|
||||
topLevel = exportedInterface.topLevel
|
||||
)
|
||||
}
|
||||
|
||||
objCCodeGenerator.emitRtti()
|
||||
}
|
||||
|
||||
private fun produceFrameworkSpecific(headerGenerator: ObjCExportHeaderGenerator) {
|
||||
headerGenerator.translateModule()
|
||||
|
||||
private fun produceFrameworkSpecific(headerLines: List<String>) {
|
||||
val framework = File(context.config.outputFile)
|
||||
val frameworkContents = when(target.family) {
|
||||
Family.IOS -> framework
|
||||
@@ -75,7 +106,7 @@ internal class ObjCExport(val codegen: CodeGenerator) {
|
||||
val headerName = frameworkName + ".h"
|
||||
val header = headers.child(headerName)
|
||||
headers.mkdirs()
|
||||
header.writeLines(headerGenerator.build())
|
||||
header.writeLines(headerLines)
|
||||
|
||||
val modules = frameworkContents.child("Modules")
|
||||
modules.mkdirs()
|
||||
|
||||
+8
-3
@@ -703,9 +703,9 @@ abstract class ObjCExportHeaderGenerator internal constructor(
|
||||
this@ObjCExportHeaderGenerator.reportWarning(method, text)
|
||||
})
|
||||
|
||||
internal val generatedClasses = mutableSetOf<ClassDescriptor>()
|
||||
internal val extensions = mutableMapOf<ClassDescriptor, MutableList<CallableMemberDescriptor>>()
|
||||
internal val topLevel = mutableMapOf<SourceFile, MutableList<CallableMemberDescriptor>>()
|
||||
private val generatedClasses = mutableSetOf<ClassDescriptor>()
|
||||
private val extensions = mutableMapOf<ClassDescriptor, MutableList<CallableMemberDescriptor>>()
|
||||
private val topLevel = mutableMapOf<SourceFile, MutableList<CallableMemberDescriptor>>()
|
||||
|
||||
fun build(): List<String> = mutableListOf<String>().apply {
|
||||
add("#import <Foundation/Foundation.h>")
|
||||
@@ -732,6 +732,11 @@ abstract class ObjCExportHeaderGenerator internal constructor(
|
||||
add("NS_ASSUME_NONNULL_END")
|
||||
}
|
||||
|
||||
internal fun buildInterface(): ObjCExportedInterface {
|
||||
val headerLines = build()
|
||||
return ObjCExportedInterface(generatedClasses, extensions, topLevel, headerLines, namer, mapper)
|
||||
}
|
||||
|
||||
protected abstract fun reportWarning(text: String)
|
||||
|
||||
protected abstract fun reportWarning(method: FunctionDescriptor, text: String)
|
||||
|
||||
Reference in New Issue
Block a user