Improve compilation to multiple LLVM modules/object files (#3334)
This commit is contained in:
committed by
GitHub
parent
a9164d858c
commit
d4a98168c0
@@ -289,13 +289,11 @@ private fun selectIncludes(
|
|||||||
outputKind: CompilerOutputKind
|
outputKind: CompilerOutputKind
|
||||||
): List<String> {
|
): List<String> {
|
||||||
val includes = arguments.includes?.toList().orEmpty()
|
val includes = arguments.includes?.toList().orEmpty()
|
||||||
val produceBinaryOrBitcode = outputKind.let { it.isNativeBinary || it == CompilerOutputKind.BITCODE }
|
|
||||||
|
|
||||||
return if (includes.isNotEmpty() && !produceBinaryOrBitcode) {
|
return if (includes.isNotEmpty() && outputKind == CompilerOutputKind.LIBRARY) {
|
||||||
configuration.report(
|
configuration.report(
|
||||||
ERROR,
|
ERROR,
|
||||||
"The $INCLUDE_ARG flag is only supported when producing native binaries or bitcode files, " +
|
"The $INCLUDE_ARG flag is not supported when producing ${outputKind.name.toLowerCase()}"
|
||||||
"but the compiler is producing ${outputKind.name.toLowerCase()}"
|
|
||||||
)
|
)
|
||||||
emptyList()
|
emptyList()
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+1
-1
@@ -150,7 +150,7 @@ internal val Context.getUnboxFunction: (IrClass) -> IrSimpleFunction by Context.
|
|||||||
* If output target is native binary then the cache is created.
|
* If output target is native binary then the cache is created.
|
||||||
*/
|
*/
|
||||||
internal fun initializeCachedBoxes(context: Context) {
|
internal fun initializeCachedBoxes(context: Context) {
|
||||||
if (context.config.produce.isNativeBinary) {
|
if (context.producedLlvmModuleContainsStdlib) {
|
||||||
BoxCache.values().forEach { cache ->
|
BoxCache.values().forEach { cache ->
|
||||||
val cacheName = "${cache.name}_CACHE"
|
val cacheName = "${cache.name}_CACHE"
|
||||||
val rangeStart = "${cache.name}_RANGE_FROM"
|
val rangeStart = "${cache.name}_RANGE_FROM"
|
||||||
|
|||||||
+24
-5
@@ -16,12 +16,28 @@ import org.jetbrains.kotlin.library.*
|
|||||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
import org.jetbrains.kotlin.konan.target.Family
|
import org.jetbrains.kotlin.konan.target.Family
|
||||||
|
|
||||||
val CompilerOutputKind.isNativeBinary: Boolean get() = when (this) {
|
/**
|
||||||
|
* Supposed to be true for a single LLVM module within final binary.
|
||||||
|
*/
|
||||||
|
val CompilerOutputKind.isFinalBinary: Boolean get() = when (this) {
|
||||||
CompilerOutputKind.PROGRAM, CompilerOutputKind.DYNAMIC,
|
CompilerOutputKind.PROGRAM, CompilerOutputKind.DYNAMIC,
|
||||||
CompilerOutputKind.STATIC, CompilerOutputKind.FRAMEWORK -> true
|
CompilerOutputKind.STATIC, CompilerOutputKind.FRAMEWORK -> true
|
||||||
CompilerOutputKind.LIBRARY, CompilerOutputKind.BITCODE -> false
|
CompilerOutputKind.LIBRARY, CompilerOutputKind.BITCODE -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val CompilerOutputKind.involvesBitcodeGeneration: Boolean
|
||||||
|
get() = this != CompilerOutputKind.LIBRARY
|
||||||
|
|
||||||
|
internal val Context.producedLlvmModuleContainsStdlib: Boolean
|
||||||
|
get() = this.llvmModuleSpecification.containsModule(this.stdlibModule)
|
||||||
|
|
||||||
|
val CompilerOutputKind.involvesLinkStage: Boolean
|
||||||
|
get() = when (this) {
|
||||||
|
CompilerOutputKind.PROGRAM, CompilerOutputKind.DYNAMIC,
|
||||||
|
CompilerOutputKind.STATIC, CompilerOutputKind.FRAMEWORK -> true
|
||||||
|
CompilerOutputKind.LIBRARY, CompilerOutputKind.BITCODE -> false
|
||||||
|
}
|
||||||
|
|
||||||
internal fun produceCStubs(context: Context) {
|
internal fun produceCStubs(context: Context) {
|
||||||
val llvmModule = context.llvmModule!!
|
val llvmModule = context.llvmModule!!
|
||||||
context.cStubsManager.compile(context.config.clang, context.messageCollector, context.inVerbosePhase)?.let {
|
context.cStubsManager.compile(context.config.clang, context.messageCollector, context.inVerbosePhase)?.let {
|
||||||
@@ -29,9 +45,12 @@ internal fun produceCStubs(context: Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun linkAllDependecies(context: Context, generatedBitcodeFiles: List<String>) {
|
private fun linkAllDependencies(context: Context, generatedBitcodeFiles: List<String>) {
|
||||||
|
val runtimeNativeLibraries = context.config.runtimeNativeLibraries
|
||||||
val nativeLibraries = context.config.nativeLibraries + context.config.defaultNativeLibraries
|
.takeIf { context.producedLlvmModuleContainsStdlib }.orEmpty()
|
||||||
|
val launcherNativeLibraries = context.config.launcherNativeLibraries
|
||||||
|
.takeIf { context.config.produce == CompilerOutputKind.PROGRAM }.orEmpty()
|
||||||
|
val nativeLibraries = context.config.nativeLibraries + runtimeNativeLibraries + launcherNativeLibraries
|
||||||
val bitcodeLibraries = context.llvm.bitcodeToLink.map { it.bitcodePaths }.flatten().filter { it.isBitcode }
|
val bitcodeLibraries = context.llvm.bitcodeToLink.map { it.bitcodePaths }.flatten().filter { it.isBitcode }
|
||||||
val additionalBitcodeFilesToLink = context.llvm.additionalProducedBitcodeFiles
|
val additionalBitcodeFilesToLink = context.llvm.additionalProducedBitcodeFiles
|
||||||
val bitcodeFiles = (nativeLibraries + generatedBitcodeFiles + additionalBitcodeFilesToLink + bitcodeLibraries).toSet()
|
val bitcodeFiles = (nativeLibraries + generatedBitcodeFiles + additionalBitcodeFilesToLink + bitcodeLibraries).toSet()
|
||||||
@@ -89,7 +108,7 @@ internal fun produceOutput(context: Context) {
|
|||||||
if (produce == CompilerOutputKind.FRAMEWORK && context.config.produceStaticFramework) {
|
if (produce == CompilerOutputKind.FRAMEWORK && context.config.produceStaticFramework) {
|
||||||
embedAppleLinkerOptionsToBitcode(context.llvm, context.config)
|
embedAppleLinkerOptionsToBitcode(context.llvm, context.config)
|
||||||
}
|
}
|
||||||
linkAllDependecies(context, generatedBitcodeFiles)
|
linkAllDependencies(context, generatedBitcodeFiles)
|
||||||
runLlvmPipeline(context)
|
runLlvmPipeline(context)
|
||||||
// Insert `_main` after pipeline so we won't worry about optimizations
|
// Insert `_main` after pipeline so we won't worry about optimizations
|
||||||
// corrupting entry point.
|
// corrupting entry point.
|
||||||
|
|||||||
+10
@@ -51,6 +51,7 @@ import org.jetbrains.kotlin.backend.common.serialization.KotlinMangler
|
|||||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager
|
import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.konan.library.KonanLibraryLayout
|
import org.jetbrains.kotlin.konan.library.KonanLibraryLayout
|
||||||
import org.jetbrains.kotlin.library.SerializedIrModule
|
import org.jetbrains.kotlin.library.SerializedIrModule
|
||||||
@@ -460,6 +461,15 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
|||||||
get() = this.builtIns.any.module
|
get() = this.builtIns.any.module
|
||||||
|
|
||||||
lateinit var compilerOutput: List<ObjectFile>
|
lateinit var compilerOutput: List<ObjectFile>
|
||||||
|
|
||||||
|
val llvmModuleSpecification: LlvmModuleSpecification = object : LlvmModuleSpecification {
|
||||||
|
// Currently all code is compiled to single LLVM module.
|
||||||
|
override fun importsKotlinDeclarationsFromOtherObjectFiles(): Boolean = false
|
||||||
|
override fun containsLibrary(library: KonanLibrary): Boolean = true
|
||||||
|
override fun containsModule(module: ModuleDescriptor): Boolean = true
|
||||||
|
override fun containsModule(module: IrModuleFragment): Boolean = true
|
||||||
|
override fun containsDeclaration(declaration: IrDeclaration): Boolean = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MemberScope.getContributedClassifier(name: String) =
|
private fun MemberScope.getContributedClassifier(name: String) =
|
||||||
|
|||||||
+5
-4
@@ -151,16 +151,17 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
|||||||
return resolvedLibraries.filterRoots { (!it.isDefault && !this.purgeUserLibs) || it.isNeededForLink }.getFullList(TopologicalLibraryOrder)
|
return resolvedLibraries.filterRoots { (!it.isDefault && !this.purgeUserLibs) || it.isNeededForLink }.getFullList(TopologicalLibraryOrder)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val defaultNativeLibraries: List<String> = mutableListOf<String>().apply {
|
internal val runtimeNativeLibraries: List<String> = mutableListOf<String>().apply {
|
||||||
add(if (debug) "debug.bc" else "release.bc")
|
add(if (debug) "debug.bc" else "release.bc")
|
||||||
add(if (memoryModel == MemoryModel.STRICT) "strict.bc" else "relaxed.bc")
|
add(if (memoryModel == MemoryModel.STRICT) "strict.bc" else "relaxed.bc")
|
||||||
if (produce == CompilerOutputKind.PROGRAM) {
|
|
||||||
addAll(distribution.launcherFiles)
|
|
||||||
}
|
|
||||||
}.map {
|
}.map {
|
||||||
File(distribution.defaultNatives(target)).child(it).absolutePath
|
File(distribution.defaultNatives(target)).child(it).absolutePath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal val launcherNativeLibraries: List<String> = distribution.launcherFiles.map {
|
||||||
|
File(distribution.defaultNatives(target)).child(it).absolutePath
|
||||||
|
}
|
||||||
|
|
||||||
internal val nativeLibraries: List<String> =
|
internal val nativeLibraries: List<String> =
|
||||||
configuration.getList(KonanConfigKeys.NATIVE_LIBRARY_FILES)
|
configuration.getList(KonanConfigKeys.NATIVE_LIBRARY_FILES)
|
||||||
|
|
||||||
|
|||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.konan
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
|
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines what LLVM module should consist of.
|
||||||
|
*/
|
||||||
|
interface LlvmModuleSpecification {
|
||||||
|
fun importsKotlinDeclarationsFromOtherObjectFiles(): Boolean
|
||||||
|
fun containsLibrary(library: KonanLibrary): Boolean
|
||||||
|
fun containsModule(module: ModuleDescriptor): Boolean
|
||||||
|
fun containsModule(module: IrModuleFragment): Boolean
|
||||||
|
fun containsDeclaration(declaration: IrDeclaration): Boolean
|
||||||
|
}
|
||||||
+1
-1
@@ -419,7 +419,7 @@ internal fun PhaseConfig.konanPhasesConfig(config: KonanConfig) {
|
|||||||
disableIf(dependenciesLowerPhase, config.produce == CompilerOutputKind.LIBRARY)
|
disableIf(dependenciesLowerPhase, config.produce == CompilerOutputKind.LIBRARY)
|
||||||
disableUnless(entryPointPhase, config.produce == CompilerOutputKind.PROGRAM)
|
disableUnless(entryPointPhase, config.produce == CompilerOutputKind.PROGRAM)
|
||||||
disableIf(bitcodePhase, config.produce == CompilerOutputKind.LIBRARY)
|
disableIf(bitcodePhase, config.produce == CompilerOutputKind.LIBRARY)
|
||||||
disableUnless(linkPhase, config.produce.isNativeBinary)
|
disableUnless(linkPhase, config.produce.involvesLinkStage)
|
||||||
disableIf(testProcessorPhase, getNotNull(KonanConfigKeys.GENERATE_TEST_RUNNER) == TestRunnerKind.NONE)
|
disableIf(testProcessorPhase, getNotNull(KonanConfigKeys.GENERATE_TEST_RUNNER) == TestRunnerKind.NONE)
|
||||||
disableUnless(buildDFGPhase, getBoolean(KonanConfigKeys.OPTIMIZATION))
|
disableUnless(buildDFGPhase, getBoolean(KonanConfigKeys.OPTIMIZATION))
|
||||||
disableUnless(devirtualizationPhase, getBoolean(KonanConfigKeys.OPTIMIZATION))
|
disableUnless(devirtualizationPhase, getBoolean(KonanConfigKeys.OPTIMIZATION))
|
||||||
|
|||||||
+3
-1
@@ -150,7 +150,7 @@ internal interface ContextUtils : RuntimeAware {
|
|||||||
* or just drop all [else] branches of corresponding conditionals.
|
* or just drop all [else] branches of corresponding conditionals.
|
||||||
*/
|
*/
|
||||||
fun isExternal(declaration: IrDeclaration): Boolean {
|
fun isExternal(declaration: IrDeclaration): Boolean {
|
||||||
return false
|
return !context.llvmModuleSpecification.containsDeclaration(declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -399,6 +399,8 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
|||||||
context.config.resolvedLibraries
|
context.config.resolvedLibraries
|
||||||
.getFullList(TopologicalLibraryOrder)
|
.getFullList(TopologicalLibraryOrder)
|
||||||
.filter { (!it.isDefault && !context.config.purgeUserLibs) || imports.bitcodeIsUsed(it) }
|
.filter { (!it.isDefault && !context.config.purgeUserLibs) || imports.bitcodeIsUsed(it) }
|
||||||
|
// TODO: the filter above is incorrect when compiling to multiple LLVM modules.
|
||||||
|
.filter { context.llvmModuleSpecification.containsLibrary(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val additionalProducedBitcodeFiles = mutableListOf<String>()
|
val additionalProducedBitcodeFiles = mutableListOf<String>()
|
||||||
|
|||||||
+10
-3
@@ -2246,7 +2246,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun appendDebugSelector() {
|
private fun appendDebugSelector() {
|
||||||
if (!context.config.produce.isNativeBinary) return
|
if (!context.producedLlvmModuleContainsStdlib) return
|
||||||
val llvmDebugSelector =
|
val llvmDebugSelector =
|
||||||
context.llvm.staticData.placeGlobal("KonanNeedDebugInfo",
|
context.llvm.staticData.placeGlobal("KonanNeedDebugInfo",
|
||||||
Int32(if (context.shouldContainDebugInfo()) 1 else 0))
|
Int32(if (context.shouldContainDebugInfo()) 1 else 0))
|
||||||
@@ -2304,7 +2304,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
LLVMSetLinkage(ctorFunction, LLVMLinkage.LLVMExternalLinkage)
|
LLVMSetLinkage(ctorFunction, LLVMLinkage.LLVMExternalLinkage)
|
||||||
|
|
||||||
val initializers = libraryToInitializers.getValue(library)
|
val initializers = libraryToInitializers.getValue(library)
|
||||||
appendStaticInitializers(ctorFunction, initializers)
|
|
||||||
|
if (library == null || context.llvmModuleSpecification.containsLibrary(library)) {
|
||||||
|
appendStaticInitializers(ctorFunction, initializers)
|
||||||
|
} else {
|
||||||
|
check(initializers.isEmpty()) {
|
||||||
|
"found initializer from ${library.libraryFile}, which is not included into compilation"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ctorFunction
|
ctorFunction
|
||||||
}
|
}
|
||||||
@@ -2342,7 +2349,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun appendGlobalCtors(ctorFunctions: List<LLVMValueRef>) {
|
private fun appendGlobalCtors(ctorFunctions: List<LLVMValueRef>) {
|
||||||
if (context.config.produce.isNativeBinary) {
|
if (context.config.produce.isFinalBinary) {
|
||||||
// Generate function calling all [ctorFunctions].
|
// Generate function calling all [ctorFunctions].
|
||||||
val globalCtorFunction = LLVMAddFunction(context.llvmModule, "_Konan_constructors", kVoidFuncType)!!
|
val globalCtorFunction = LLVMAddFunction(context.llvmModule, "_Konan_constructors", kVoidFuncType)!!
|
||||||
LLVMSetLinkage(globalCtorFunction, LLVMLinkage.LLVMPrivateLinkage)
|
LLVMSetLinkage(globalCtorFunction, LLVMLinkage.LLVMPrivateLinkage)
|
||||||
|
|||||||
+1
-1
@@ -50,7 +50,7 @@ internal class CoverageManager(val context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkRestrictions(): Boolean {
|
private fun checkRestrictions(): Boolean {
|
||||||
val isKindAllowed = with(context.config.produce) { isNativeBinary || this == CompilerOutputKind.BITCODE }
|
val isKindAllowed = context.config.produce.involvesBitcodeGeneration
|
||||||
val target = context.config.target
|
val target = context.config.target
|
||||||
val isTargetAllowed = target == KonanTarget.MACOS_X64 || target == KonanTarget.IOS_X64
|
val isTargetAllowed = target == KonanTarget.MACOS_X64 || target == KonanTarget.IOS_X64
|
||||||
return isKindAllowed && isTargetAllowed
|
return isKindAllowed && isTargetAllowed
|
||||||
|
|||||||
+16
-12
@@ -262,8 +262,8 @@ internal class ObjCExportCodeGenerator(
|
|||||||
val sortedAdaptersPointer = staticData.placeGlobalConstArray("", type, sortedAdapters)
|
val sortedAdaptersPointer = staticData.placeGlobalConstArray("", type, sortedAdapters)
|
||||||
|
|
||||||
// Note: this globals replace runtime globals with weak linkage:
|
// Note: this globals replace runtime globals with weak linkage:
|
||||||
staticData.placeGlobal(prefix, sortedAdaptersPointer, isExported = true)
|
replaceExternalWeakOrCommonGlobal(prefix, sortedAdaptersPointer)
|
||||||
staticData.placeGlobal("${prefix}Num", Int32(sortedAdapters.size), isExported = true)
|
replaceExternalWeakOrCommonGlobal("${prefix}Num", Int32(sortedAdapters.size))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,6 +381,16 @@ internal class ObjCExportCodeGenerator(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ObjCExportCodeGenerator.replaceExternalWeakOrCommonGlobal(name: String, value: ConstValue) {
|
||||||
|
val global = staticData.placeGlobal(name, value, isExported = true)
|
||||||
|
|
||||||
|
if (context.llvmModuleSpecification.importsKotlinDeclarationsFromOtherObjectFiles()) {
|
||||||
|
// Note: actually this is required only if global's weak/common definition is in other object file,
|
||||||
|
// but it is simpler to do this for all globals, considering that all usages can't be removed by DCE anyway.
|
||||||
|
context.llvm.usedGlobals += global.llvmGlobal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun ObjCExportCodeGenerator.setObjCExportTypeInfo(
|
private fun ObjCExportCodeGenerator.setObjCExportTypeInfo(
|
||||||
irClass: IrClass,
|
irClass: IrClass,
|
||||||
converter: ConstPointer? = null,
|
converter: ConstPointer? = null,
|
||||||
@@ -400,20 +410,14 @@ private fun ObjCExportCodeGenerator.setObjCExportTypeInfo(
|
|||||||
val writableTypeInfoType = runtime.writableTypeInfoType!!
|
val writableTypeInfoType = runtime.writableTypeInfoType!!
|
||||||
val writableTypeInfoValue = Struct(writableTypeInfoType, objCExportAddition)
|
val writableTypeInfoValue = Struct(writableTypeInfoType, objCExportAddition)
|
||||||
|
|
||||||
val global = if (codegen.isExternal(irClass)) {
|
if (codegen.isExternal(irClass)) {
|
||||||
// Note: this global replaces the external one with common linkage.
|
// Note: this global replaces the external one with common linkage.
|
||||||
staticData.createGlobal(
|
replaceExternalWeakOrCommonGlobal(irClass.writableTypeInfoSymbolName, writableTypeInfoValue)
|
||||||
writableTypeInfoType,
|
|
||||||
irClass.writableTypeInfoSymbolName,
|
|
||||||
isExported = true
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
context.llvmDeclarations.forClass(irClass).writableTypeInfoGlobal!!.also {
|
context.llvmDeclarations.forClass(irClass).writableTypeInfoGlobal!!.also {
|
||||||
it.setLinkage(LLVMLinkage.LLVMExternalLinkage)
|
it.setLinkage(LLVMLinkage.LLVMExternalLinkage)
|
||||||
}
|
}.setInitializer(writableTypeInfoValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
global.setInitializer(writableTypeInfoValue)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val ObjCExportCodeGenerator.kotlinToObjCFunctionType: LLVMTypeRef
|
private val ObjCExportCodeGenerator.kotlinToObjCFunctionType: LLVMTypeRef
|
||||||
@@ -480,7 +484,7 @@ private fun ObjCExportCodeGenerator.emitBlockToKotlinFunctionConverters() {
|
|||||||
).pointer.getElementPtr(0)
|
).pointer.getElementPtr(0)
|
||||||
|
|
||||||
// Note: this global replaces the weak global defined in runtime.
|
// Note: this global replaces the weak global defined in runtime.
|
||||||
staticData.placeGlobal("Kotlin_ObjCExport_blockToFunctionConverters", ptr, isExported = true)
|
replaceExternalWeakOrCommonGlobal("Kotlin_ObjCExport_blockToFunctionConverters", ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ObjCExportCodeGenerator.emitSpecialClassesConvertions() {
|
private fun ObjCExportCodeGenerator.emitSpecialClassesConvertions() {
|
||||||
|
|||||||
+6
-2
@@ -42,7 +42,11 @@ internal class ObjCExport(val context: Context, symbolTable: SymbolTable) {
|
|||||||
private fun produceInterface(): ObjCExportedInterface? {
|
private fun produceInterface(): ObjCExportedInterface? {
|
||||||
if (!target.family.isAppleFamily) return null
|
if (!target.family.isAppleFamily) return null
|
||||||
|
|
||||||
if (!context.config.produce.isNativeBinary) return null // TODO: emit RTTI to the same modules as classes belong to.
|
if (!context.config.produce.isFinalBinary) return null
|
||||||
|
|
||||||
|
// TODO: emit RTTI to the same modules as classes belong to.
|
||||||
|
// Not possible yet, since ObjCExport translates the entire "world" API at once
|
||||||
|
// and can't do this per-module, e.g. due to global name conflict resolution.
|
||||||
|
|
||||||
val produceFramework = context.config.produce == CompilerOutputKind.FRAMEWORK
|
val produceFramework = context.config.produce == CompilerOutputKind.FRAMEWORK
|
||||||
|
|
||||||
@@ -69,7 +73,7 @@ internal class ObjCExport(val context: Context, symbolTable: SymbolTable) {
|
|||||||
internal fun generate(codegen: CodeGenerator) {
|
internal fun generate(codegen: CodeGenerator) {
|
||||||
if (!target.family.isAppleFamily) return
|
if (!target.family.isAppleFamily) return
|
||||||
|
|
||||||
if (!context.config.produce.isNativeBinary) return // TODO: emit RTTI to the same modules as classes belong to.
|
if (!context.config.produce.isFinalBinary) return // TODO: emit RTTI to the same modules as classes belong to.
|
||||||
|
|
||||||
val mapper = exportedInterface?.mapper ?: ObjCExportMapper()
|
val mapper = exportedInterface?.mapper ?: ObjCExportMapper()
|
||||||
val namer = exportedInterface?.namer ?: ObjCExportNamerImpl(
|
val namer = exportedInterface?.namer ?: ObjCExportNamerImpl(
|
||||||
|
|||||||
Reference in New Issue
Block a user