From bb1feabb793f76f859e8cf9d6fab3eecb3521d95 Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov Date: Wed, 25 Jan 2023 12:05:37 +0200 Subject: [PATCH] [K/N] Untie C header generation from NativeGenerationState --- .../konan/cexport/CAdapterApiExporter.kt | 25 +++++++++++-------- .../backend/konan/driver/phases/CExport.kt | 22 +++++++++++++--- .../konan/driver/phases/TopLevelPhases.kt | 9 ++++++- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 1 - 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cexport/CAdapterApiExporter.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cexport/CAdapterApiExporter.kt index ddd467ee51f..11058352f84 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cexport/CAdapterApiExporter.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cexport/CAdapterApiExporter.kt @@ -5,26 +5,34 @@ package org.jetbrains.kotlin.backend.konan.cexport -import org.jetbrains.kotlin.backend.konan.NativeGenerationState import org.jetbrains.kotlin.builtins.UnsignedType import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies import org.jetbrains.kotlin.konan.target.Family +import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.isNothing import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.types.typeUtil.makeNullable import java.io.PrintWriter +import java.io.File /** * Third phase of C export: * 1. Create a C++ file with runtime bindings * 2. Create a header file with API * 3. (MinGW only) create EXPORTS def file. + * + * @param headerFile C header file that will be populated with the exported C API. + * @param defFile DLL module definition file + * @param cppAdapterFile C++ source that will be populated with glue code between K/N runtime and exported API. */ internal class CAdapterApiExporter( - private val generationState: NativeGenerationState, private val elements: CAdapterExportedElements, + private val headerFile: File, + private val defFile: File?, + private val cppAdapterFile: File, + private val target: KonanTarget, ) { private val typeTranslator = elements.typeTranslator private val builtIns = elements.typeTranslator.builtIns @@ -155,7 +163,6 @@ internal class CAdapterApiExporter( // TODO: Pass temp and output files explicitly and untie from `NativeGenerationState`. fun makeGlobalStruct() { val top = elements.scopes.first() - val headerFile = generationState.outputFiles.cAdapterHeader outputStreamWriter = headerFile.printWriter() val exportedSymbol = "${prefix}_symbols" @@ -188,7 +195,7 @@ internal class CAdapterApiExporter( output("typedef double ${prefix}_KDouble;") val typedef_KVector128 = "typedef float __attribute__ ((__vector_size__ (16))) ${prefix}_KVector128;" - if (generationState.config.target.family == Family.MINGW) { + if (target.family == Family.MINGW) { // Separate `output` for each line to ensure Windows EOL (LFCR), otherwise generated file will have inconsistent line ending. output("#ifndef _MSC_VER") output(typedef_KVector128) @@ -240,9 +247,7 @@ internal class CAdapterApiExporter( outputStreamWriter.close() println("Produced library API in ${prefix}_api.h") - outputStreamWriter = generationState.tempFiles - .cAdapterCpp - .printWriter() + outputStreamWriter = cppAdapterFile.printWriter() // Include header into C++ source. headerFile.forEachLine { it -> output(it) } @@ -379,10 +384,8 @@ internal class CAdapterApiExporter( output("RUNTIME_USED ${prefix}_ExportedSymbols* $exportedSymbol(void) { return &__konan_symbols;}") outputStreamWriter.close() - if (generationState.config.target.family == Family.MINGW) { - outputStreamWriter = generationState.outputFiles - .cAdapterDef - .printWriter() + if (defFile != null) { + outputStreamWriter = defFile.printWriter() output("EXPORTS") exportedSymbols.forEach { output(it) } outputStreamWriter.close() diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/CExport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/CExport.kt index a72398646b7..9c050d17d7f 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/CExport.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/CExport.kt @@ -5,11 +5,12 @@ package org.jetbrains.kotlin.backend.konan.driver.phases -import org.jetbrains.kotlin.backend.konan.NativeGenerationState import org.jetbrains.kotlin.backend.konan.cexport.CAdapterApiExporter import org.jetbrains.kotlin.backend.konan.cexport.CAdapterExportedElements import org.jetbrains.kotlin.backend.konan.cexport.CAdapterGenerator import org.jetbrains.kotlin.backend.konan.cexport.CAdapterTypeTranslator +import org.jetbrains.kotlin.backend.konan.driver.PhaseContext +import java.io.File internal val BuildCExports = createSimpleNamedCompilerPhase( "BuildCExports", "Build C exports", @@ -20,9 +21,22 @@ internal val BuildCExports = createSimpleNamedCompilerPhase( +internal data class CExportGenerateApiInput( + val elements: CAdapterExportedElements, + val headerFile: File, + val defFile: File?, + val cppAdapterFile: File, +) + +internal val CExportGenerateApiPhase = createSimpleNamedCompilerPhase( name = "CExportGenerateApi", description = "Create C header for the exported API", -) { context, _ -> - CAdapterApiExporter(context, context.context.cAdapterExportedElements!!).makeGlobalStruct() +) { context, input -> + CAdapterApiExporter( + elements = input.elements, + headerFile = input.headerFile, + defFile = input.defFile, + cppAdapterFile = input.cppAdapterFile, + target = context.config.target, + ).makeGlobalStruct() } \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt index edcc90a0acb..7f4c0f15c87 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.ir.declarations.path import org.jetbrains.kotlin.ir.util.hasAnnotation import org.jetbrains.kotlin.konan.TempFiles import org.jetbrains.kotlin.konan.target.CompilerOutputKind +import org.jetbrains.kotlin.konan.target.Family import org.jetbrains.kotlin.library.impl.javaFile internal fun PhaseEngine.runFrontend(config: KonanConfig, environment: KotlinCoreEnvironment): FrontendPhaseOutput.Full? { @@ -174,7 +175,13 @@ internal fun PhaseEngine.runBackendCodegen(module: IrModu mergeDependencies(module, dependenciesToCompile) runCodegen(module) if (context.config.produce.isNativeLibrary) { - runPhase(CExportGenerateApiPhase) + val input = CExportGenerateApiInput( + context.context.cAdapterExportedElements!!, + headerFile = context.outputFiles.cAdapterHeader.javaFile(), + defFile = if (context.config.target.family == Family.MINGW) context.outputFiles.cAdapterDef.javaFile() else null, + cppAdapterFile = context.tempFiles.cAdapterCpp.javaFile() + ) + runPhase(CExportGenerateApiPhase, input) } runPhase(CStubsPhase) // TODO: Consider extracting llvmModule and friends from nativeGenerationState and pass them explicitly. diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 3f2db22ecbb..8bdc7523d10 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -10,7 +10,6 @@ import llvm.* import org.jetbrains.kotlin.backend.common.lower.coroutines.getOrCreateFunctionWithContinuationStub import org.jetbrains.kotlin.backend.common.lower.inline.InlinerExpressionLocationHint import org.jetbrains.kotlin.backend.konan.* -import org.jetbrains.kotlin.backend.konan.cexport.CAdapterApiExporter import org.jetbrains.kotlin.backend.konan.cexport.CAdapterCodegen import org.jetbrains.kotlin.backend.konan.cexport.CAdapterExportedElements import org.jetbrains.kotlin.backend.konan.cgen.CBridgeOrigin