[K/N] More clear separation of CAdapterGenerator
Separated CAdapterBindingsBuilder into CAdapterCodegen and CAdapterApiExporter. It makes C export much more comprehensible and allows to split it into more clear phases.
This commit is contained in:
committed by
Space Team
parent
c33013e159
commit
287337007f
+1
-2
@@ -108,8 +108,7 @@ internal val buildCExportsPhase = konanUnitPhase(
|
||||
op = {
|
||||
val prefix = config.fullExportedNamePrefix.replace("-|\\.".toRegex(), "_")
|
||||
val cAdapterTypeTranslator = CAdapterTypeTranslator(prefix, this.builtIns)
|
||||
this.cAdapterExportedElements = CAdapterGenerator(this, this.moduleDescriptor, cAdapterTypeTranslator)
|
||||
.buildExports(this.symbolTable!!)
|
||||
this.cAdapterExportedElements = CAdapterGenerator(this, cAdapterTypeTranslator).buildExports(this.moduleDescriptor)
|
||||
},
|
||||
name = "BuildCExports",
|
||||
description = "Build C exports",
|
||||
|
||||
+18
-115
@@ -5,44 +5,31 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.cexport
|
||||
|
||||
import kotlinx.cinterop.cValuesOf
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.common.pop
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.CodeGenerator
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.ContextUtils
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.ExceptionHandler
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.Lifetime
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.addLlvmFunctionWithDefaultAttributes
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.generateFunction
|
||||
import org.jetbrains.kotlin.backend.konan.lower.getObjectClassInstanceFunction
|
||||
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrEnumEntry
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.util.isOverridable
|
||||
import org.jetbrains.kotlin.konan.target.Family
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
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
|
||||
|
||||
internal class CAdapterBindingsBuilder(
|
||||
val codegen: CodeGenerator,
|
||||
val elements: CAdapterExportedElements,
|
||||
) : ContextUtils {
|
||||
override val generationState = codegen.generationState
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
internal class CAdapterApiExporter(
|
||||
private val generationState: NativeGenerationState,
|
||||
private val elements: CAdapterExportedElements,
|
||||
) {
|
||||
private val typeTranslator = elements.typeTranslator
|
||||
private val builtIns = elements.typeTranslator.builtIns
|
||||
private val scopes = elements.scopes
|
||||
|
||||
internal val prefix = context.config.fullExportedNamePrefix.replace("-|\\.".toRegex(), "_")
|
||||
private val prefix = elements.typeTranslator.prefix
|
||||
private lateinit var outputStreamWriter: PrintWriter
|
||||
|
||||
// Primitive built-ins and unsigned types
|
||||
@@ -57,92 +44,6 @@ internal class CAdapterBindingsBuilder(
|
||||
builtIns.builtInsModule.findClassAcrossModuleDependencies(it.classId)!!.defaultType
|
||||
}
|
||||
|
||||
fun build() {
|
||||
val top = scopes.pop()
|
||||
assert(scopes.isEmpty() && top.kind == ScopeKind.TOP)
|
||||
|
||||
// Now, let's generate C world adapters for all functions.
|
||||
top.generateCAdapters(::buildCAdapter)
|
||||
|
||||
// Then generate data structure, describing generated adapters.
|
||||
makeGlobalStruct(top)
|
||||
}
|
||||
|
||||
private fun buildCAdapter(exportedElement: ExportedElement): Unit = with(exportedElement) {
|
||||
when {
|
||||
isFunction -> {
|
||||
val function = declaration as FunctionDescriptor
|
||||
val irFunction = irSymbol.owner as IrFunction
|
||||
cname = "_konan_function_${owner.nextFunctionIndex()}"
|
||||
val llvmCallable = codegen.llvmFunction(irFunction)
|
||||
// If function is virtual, we need to resolve receiver properly.
|
||||
val bridge = generateFunction(codegen, llvmCallable.functionType, cname) {
|
||||
val callee = if (!DescriptorUtils.isTopLevelDeclaration(function) &&
|
||||
irFunction.isOverridable
|
||||
) {
|
||||
val receiver = param(0)
|
||||
lookupVirtualImpl(receiver, irFunction)
|
||||
} else {
|
||||
// KT-45468: Alias insertion may not be handled by LLVM properly, in case callee is in the cache.
|
||||
// Hence, insert not an alias but a wrapper, hoping it will be optimized out later.
|
||||
llvmCallable
|
||||
}
|
||||
|
||||
val numParams = LLVMCountParams(llvmCallable.llvmValue)
|
||||
val args = (0 until numParams).map { index -> param(index) }
|
||||
callee.attributeProvider.addFunctionAttributes(this.function)
|
||||
val result = call(callee, args, exceptionHandler = ExceptionHandler.Caller, verbatim = true)
|
||||
ret(result)
|
||||
}
|
||||
LLVMSetLinkage(bridge, LLVMLinkage.LLVMExternalLinkage)
|
||||
}
|
||||
isClass -> {
|
||||
val irClass = irSymbol.owner as IrClass
|
||||
cname = "_konan_function_${owner.nextFunctionIndex()}"
|
||||
// Produce type getter.
|
||||
val getTypeFunction = addLlvmFunctionWithDefaultAttributes(
|
||||
context,
|
||||
llvm.module,
|
||||
"${cname}_type",
|
||||
kGetTypeFuncType
|
||||
)
|
||||
val builder = LLVMCreateBuilderInContext(llvm.llvmContext)!!
|
||||
val bb = LLVMAppendBasicBlockInContext(llvm.llvmContext, getTypeFunction, "")!!
|
||||
LLVMPositionBuilderAtEnd(builder, bb)
|
||||
LLVMBuildRet(builder, irClass.typeInfoPtr.llvm)
|
||||
LLVMDisposeBuilder(builder)
|
||||
// Produce instance getter if needed.
|
||||
if (isSingletonObject) {
|
||||
generateFunction(codegen, kGetObjectFuncType, "${cname}_instance") {
|
||||
val value = call(
|
||||
codegen.llvmFunction(context.getObjectClassInstanceFunction(irClass)),
|
||||
emptyList(),
|
||||
Lifetime.GLOBAL,
|
||||
ExceptionHandler.Caller,
|
||||
false,
|
||||
returnSlot
|
||||
)
|
||||
ret(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
isEnumEntry -> {
|
||||
// Produce entry getter.
|
||||
cname = "_konan_function_${owner.nextFunctionIndex()}"
|
||||
generateFunction(codegen, kGetObjectFuncType, cname) {
|
||||
val irEnumEntry = irSymbol.owner as IrEnumEntry
|
||||
val value = getEnumEntry(irEnumEntry, ExceptionHandler.Caller)
|
||||
ret(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val kGetTypeFuncType = LLVMFunctionType(codegen.kTypeInfoPtr, null, 0, 0)!!
|
||||
|
||||
// Abstraction leak for slot :(.
|
||||
private val kGetObjectFuncType = LLVMFunctionType(codegen.kObjHeaderPtr, cValuesOf(codegen.kObjHeaderPtrPtr), 1, 0)!!
|
||||
|
||||
private fun output(string: String, indent: Int = 0) {
|
||||
if (indent != 0) outputStreamWriter.print(" " * indent)
|
||||
outputStreamWriter.println(string)
|
||||
@@ -249,9 +150,11 @@ internal class CAdapterBindingsBuilder(
|
||||
}
|
||||
}
|
||||
|
||||
val exportedSymbols = mutableListOf<String>()
|
||||
private val exportedSymbols = mutableListOf<String>()
|
||||
|
||||
private fun makeGlobalStruct(top: ExportedElementScope) {
|
||||
// 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()
|
||||
|
||||
@@ -285,7 +188,7 @@ internal class CAdapterBindingsBuilder(
|
||||
output("typedef double ${prefix}_KDouble;")
|
||||
|
||||
val typedef_KVector128 = "typedef float __attribute__ ((__vector_size__ (16))) ${prefix}_KVector128;"
|
||||
if (context.config.target.family == Family.MINGW) {
|
||||
if (generationState.config.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)
|
||||
@@ -476,7 +379,7 @@ internal class CAdapterBindingsBuilder(
|
||||
output("RUNTIME_USED ${prefix}_ExportedSymbols* $exportedSymbol(void) { return &__konan_symbols;}")
|
||||
outputStreamWriter.close()
|
||||
|
||||
if (context.config.target.family == Family.MINGW) {
|
||||
if (generationState.config.target.family == Family.MINGW) {
|
||||
outputStreamWriter = generationState.outputFiles
|
||||
.cAdapterDef
|
||||
.printWriter()
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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.cexport
|
||||
|
||||
import kotlinx.cinterop.cValuesOf
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.CodeGenerator
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.ContextUtils
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.ExceptionHandler
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.Lifetime
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.addLlvmFunctionWithDefaultAttributes
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.generateFunction
|
||||
import org.jetbrains.kotlin.backend.konan.lower.getObjectClassInstanceFunction
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrEnumEntry
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.util.isOverridable
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
|
||||
/**
|
||||
* Second phase of C Export: build bitcode bridges from C wrappers to Kotlin functions.
|
||||
*/
|
||||
internal class CAdapterCodegen(
|
||||
private val codegen: CodeGenerator,
|
||||
override val generationState: NativeGenerationState,
|
||||
) : ContextUtils {
|
||||
|
||||
fun buildAllAdaptersRecursively(elements: CAdapterExportedElements) {
|
||||
val top = elements.scopes.single()
|
||||
assert(top.kind == ScopeKind.TOP)
|
||||
top.generateCAdapters(this::buildCAdapter)
|
||||
}
|
||||
|
||||
private fun ExportedElementScope.generateCAdapters(builder: (ExportedElement) -> Unit) {
|
||||
this.elements.forEach { builder(it) }
|
||||
this.scopes.forEach { it.generateCAdapters(builder) }
|
||||
}
|
||||
|
||||
private fun buildCAdapter(exportedElement: ExportedElement): Unit = with(exportedElement) {
|
||||
when {
|
||||
isFunction -> {
|
||||
val function = declaration as FunctionDescriptor
|
||||
val irFunction = irSymbol.owner as IrFunction
|
||||
cname = "_konan_function_${owner.nextFunctionIndex()}"
|
||||
val llvmCallable = codegen.llvmFunction(irFunction)
|
||||
// If function is virtual, we need to resolve receiver properly.
|
||||
val bridge = generateFunction(codegen, llvmCallable.functionType, cname) {
|
||||
val callee = if (!DescriptorUtils.isTopLevelDeclaration(function) &&
|
||||
irFunction.isOverridable
|
||||
) {
|
||||
val receiver = param(0)
|
||||
lookupVirtualImpl(receiver, irFunction)
|
||||
} else {
|
||||
// KT-45468: Alias insertion may not be handled by LLVM properly, in case callee is in the cache.
|
||||
// Hence, insert not an alias but a wrapper, hoping it will be optimized out later.
|
||||
llvmCallable
|
||||
}
|
||||
|
||||
val numParams = LLVMCountParams(llvmCallable.llvmValue)
|
||||
val args = (0 until numParams).map { index -> param(index) }
|
||||
callee.attributeProvider.addFunctionAttributes(this.function)
|
||||
val result = call(callee, args, exceptionHandler = ExceptionHandler.Caller, verbatim = true)
|
||||
ret(result)
|
||||
}
|
||||
LLVMSetLinkage(bridge, LLVMLinkage.LLVMExternalLinkage)
|
||||
}
|
||||
isClass -> {
|
||||
val irClass = irSymbol.owner as IrClass
|
||||
cname = "_konan_function_${owner.nextFunctionIndex()}"
|
||||
// Produce type getter.
|
||||
val getTypeFunction = addLlvmFunctionWithDefaultAttributes(
|
||||
context,
|
||||
llvm.module,
|
||||
"${cname}_type",
|
||||
kGetTypeFuncType
|
||||
)
|
||||
val builder = LLVMCreateBuilderInContext(llvm.llvmContext)!!
|
||||
val bb = LLVMAppendBasicBlockInContext(llvm.llvmContext, getTypeFunction, "")!!
|
||||
LLVMPositionBuilderAtEnd(builder, bb)
|
||||
LLVMBuildRet(builder, irClass.typeInfoPtr.llvm)
|
||||
LLVMDisposeBuilder(builder)
|
||||
// Produce instance getter if needed.
|
||||
if (isSingletonObject) {
|
||||
generateFunction(codegen, kGetObjectFuncType, "${cname}_instance") {
|
||||
val value = call(
|
||||
codegen.llvmFunction(context.getObjectClassInstanceFunction(irClass)),
|
||||
emptyList(),
|
||||
Lifetime.GLOBAL,
|
||||
ExceptionHandler.Caller,
|
||||
false,
|
||||
returnSlot
|
||||
)
|
||||
ret(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
isEnumEntry -> {
|
||||
// Produce entry getter.
|
||||
cname = "_konan_function_${owner.nextFunctionIndex()}"
|
||||
generateFunction(codegen, kGetObjectFuncType, cname) {
|
||||
val irEnumEntry = irSymbol.owner as IrEnumEntry
|
||||
val value = getEnumEntry(irEnumEntry, ExceptionHandler.Caller)
|
||||
ret(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val kGetTypeFuncType = LLVMFunctionType(codegen.kTypeInfoPtr, null, 0, 0)!!
|
||||
|
||||
// Abstraction leak for slot :(.
|
||||
private val kGetObjectFuncType = LLVMFunctionType(codegen.kObjHeaderPtr, cValuesOf(codegen.kObjHeaderPtrPtr), 1, 0)!!
|
||||
}
|
||||
+1
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.konan.exec.*
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
import org.jetbrains.kotlin.konan.file.*
|
||||
|
||||
// Fourth phase of C export: compile runtime bindings to bitcode.
|
||||
fun produceCAdapterBitcode(clang: ClangArgs, cppFileName: String, bitcodeFileName: String) {
|
||||
val clangCommand = clang.clangCXX("-std=c++17", cppFileName, "-emit-llvm", "-c", "-o", bitcodeFileName)
|
||||
Command(clangCommand).execute()
|
||||
|
||||
+11
-26
@@ -5,26 +5,24 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.cexport
|
||||
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.allParameters
|
||||
import org.jetbrains.kotlin.backend.common.pop
|
||||
import org.jetbrains.kotlin.backend.common.push
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.driver.phases.PsiToIrContext
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.referenceFunction
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.isChildOf
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.annotations.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||
import org.jetbrains.kotlin.resolve.annotations.argumentValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPublicApi
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
|
||||
internal enum class ScopeKind {
|
||||
TOP,
|
||||
@@ -96,11 +94,6 @@ internal class ExportedElementScope(val kind: ScopeKind, val name: String) {
|
||||
return "$kind: $name ${elements.joinToString(", ")} ${scopes.joinToString("\n")}"
|
||||
}
|
||||
|
||||
fun generateCAdapters(builder: (ExportedElement) -> Unit) {
|
||||
elements.forEach { builder(it) }
|
||||
scopes.forEach { it.generateCAdapters(builder) }
|
||||
}
|
||||
|
||||
// collects names of inner scopes to make sure function<->scope name clashes would be detected, and functions would be mangled with "_" suffix
|
||||
fun collectInnerScopeName(innerScope: ExportedElementScope) {
|
||||
scopeNames += innerScope.name
|
||||
@@ -396,17 +389,18 @@ private fun ModuleDescriptor.getPackageFragments(): List<PackageFragmentDescript
|
||||
getPackage(it).fragments.filter { it.module == this }
|
||||
}
|
||||
|
||||
/**
|
||||
* First phase of C export: walk given declaration descriptors and create [CAdapterExportedElements] from them.
|
||||
*/
|
||||
internal class CAdapterGenerator(
|
||||
private val context: PsiToIrContext,
|
||||
private val moduleDescriptor: ModuleDescriptor,
|
||||
private val typeTranslator: CAdapterTypeTranslator,
|
||||
) : DeclarationDescriptorVisitor<Boolean, Void?> {
|
||||
private val scopes = mutableListOf<ExportedElementScope>()
|
||||
internal val prefix = typeTranslator.prefix
|
||||
private val paramNamesRecorded = mutableMapOf<String, Int>()
|
||||
|
||||
private var symbolTableOrNull: SymbolTable? = null
|
||||
internal val symbolTable get() = symbolTableOrNull!!
|
||||
internal val symbolTable get() = context.symbolTable!!
|
||||
|
||||
internal fun paramsToUniqueNames(params: List<ParameterDescriptor>): Map<ParameterDescriptor, String> {
|
||||
paramNamesRecorded.clear()
|
||||
@@ -536,17 +530,7 @@ internal class CAdapterGenerator(
|
||||
|
||||
private val moduleDescriptors = mutableSetOf<ModuleDescriptor>()
|
||||
|
||||
fun buildExports(symbolTable: SymbolTable): CAdapterExportedElements {
|
||||
this.symbolTableOrNull = symbolTable
|
||||
try {
|
||||
buildExports()
|
||||
return CAdapterExportedElements(typeTranslator, scopes)
|
||||
} finally {
|
||||
this.symbolTableOrNull = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildExports() {
|
||||
fun buildExports(moduleDescriptor: ModuleDescriptor): CAdapterExportedElements {
|
||||
scopes.push(ExportedElementScope(ScopeKind.TOP, "kotlin"))
|
||||
moduleDescriptors += moduleDescriptor
|
||||
moduleDescriptors += moduleDescriptor.getExportedDependencies(context.config)
|
||||
@@ -557,6 +541,7 @@ internal class CAdapterGenerator(
|
||||
})
|
||||
|
||||
moduleDescriptor.getPackage(FqName.ROOT).accept(this, null)
|
||||
return CAdapterExportedElements(typeTranslator, scopes)
|
||||
}
|
||||
|
||||
private val simpleNameMapping = mapOf(
|
||||
|
||||
+1
-1
@@ -15,5 +15,5 @@ internal val BuildCExports = createSimpleNamedCompilerPhase<PsiToIrContext, Fron
|
||||
) { context, input ->
|
||||
val prefix = context.config.fullExportedNamePrefix.replace("-|\\.".toRegex(), "_")
|
||||
val typeTranslator = CAdapterTypeTranslator(prefix, context.builtIns)
|
||||
CAdapterGenerator(context, input.moduleDescriptor, typeTranslator).buildExports(context.symbolTable!!)
|
||||
CAdapterGenerator(context, typeTranslator).buildExports(input.moduleDescriptor)
|
||||
}
|
||||
+6
-2
@@ -10,7 +10,8 @@ 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.CAdapterBindingsBuilder
|
||||
import org.jetbrains.kotlin.backend.konan.cexport.CAdapterApiExporter
|
||||
import org.jetbrains.kotlin.backend.konan.cexport.CAdapterCodegen
|
||||
import org.jetbrains.kotlin.backend.konan.cgen.CBridgeOrigin
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
||||
@@ -327,7 +328,10 @@ internal class CodeGeneratorVisitor(val generationState: NativeGenerationState,
|
||||
}
|
||||
}
|
||||
private fun appendCAdapters() {
|
||||
CAdapterBindingsBuilder(codegen, context.cAdapterExportedElements).build()
|
||||
val elements = context.cAdapterExportedElements
|
||||
CAdapterCodegen(codegen, generationState).buildAllAdaptersRecursively(elements)
|
||||
// TODO: It is not a part of IrToBitcode. Maybe move it somewhere?
|
||||
CAdapterApiExporter(generationState, elements).makeGlobalStruct()
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.initThreadLocalField(irField: IrField) {
|
||||
|
||||
Reference in New Issue
Block a user