[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 = {
|
op = {
|
||||||
val prefix = config.fullExportedNamePrefix.replace("-|\\.".toRegex(), "_")
|
val prefix = config.fullExportedNamePrefix.replace("-|\\.".toRegex(), "_")
|
||||||
val cAdapterTypeTranslator = CAdapterTypeTranslator(prefix, this.builtIns)
|
val cAdapterTypeTranslator = CAdapterTypeTranslator(prefix, this.builtIns)
|
||||||
this.cAdapterExportedElements = CAdapterGenerator(this, this.moduleDescriptor, cAdapterTypeTranslator)
|
this.cAdapterExportedElements = CAdapterGenerator(this, cAdapterTypeTranslator).buildExports(this.moduleDescriptor)
|
||||||
.buildExports(this.symbolTable!!)
|
|
||||||
},
|
},
|
||||||
name = "BuildCExports",
|
name = "BuildCExports",
|
||||||
description = "Build C exports",
|
description = "Build C exports",
|
||||||
|
|||||||
+18
-115
@@ -5,44 +5,31 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.konan.cexport
|
package org.jetbrains.kotlin.backend.konan.cexport
|
||||||
|
|
||||||
import kotlinx.cinterop.cValuesOf
|
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||||
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.builtins.UnsignedType
|
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
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.konan.target.Family
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
|
|
||||||
internal class CAdapterBindingsBuilder(
|
/**
|
||||||
val codegen: CodeGenerator,
|
* Third phase of C export:
|
||||||
val elements: CAdapterExportedElements,
|
* 1. Create a C++ file with runtime bindings
|
||||||
) : ContextUtils {
|
* 2. Create a header file with API
|
||||||
override val generationState = codegen.generationState
|
* 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 typeTranslator = elements.typeTranslator
|
||||||
private val builtIns = elements.typeTranslator.builtIns
|
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
|
private lateinit var outputStreamWriter: PrintWriter
|
||||||
|
|
||||||
// Primitive built-ins and unsigned types
|
// Primitive built-ins and unsigned types
|
||||||
@@ -57,92 +44,6 @@ internal class CAdapterBindingsBuilder(
|
|||||||
builtIns.builtInsModule.findClassAcrossModuleDependencies(it.classId)!!.defaultType
|
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) {
|
private fun output(string: String, indent: Int = 0) {
|
||||||
if (indent != 0) outputStreamWriter.print(" " * indent)
|
if (indent != 0) outputStreamWriter.print(" " * indent)
|
||||||
outputStreamWriter.println(string)
|
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
|
val headerFile = generationState.outputFiles.cAdapterHeader
|
||||||
outputStreamWriter = headerFile.printWriter()
|
outputStreamWriter = headerFile.printWriter()
|
||||||
|
|
||||||
@@ -285,7 +188,7 @@ internal class CAdapterBindingsBuilder(
|
|||||||
output("typedef double ${prefix}_KDouble;")
|
output("typedef double ${prefix}_KDouble;")
|
||||||
|
|
||||||
val typedef_KVector128 = "typedef float __attribute__ ((__vector_size__ (16))) ${prefix}_KVector128;"
|
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.
|
// Separate `output` for each line to ensure Windows EOL (LFCR), otherwise generated file will have inconsistent line ending.
|
||||||
output("#ifndef _MSC_VER")
|
output("#ifndef _MSC_VER")
|
||||||
output(typedef_KVector128)
|
output(typedef_KVector128)
|
||||||
@@ -476,7 +379,7 @@ internal class CAdapterBindingsBuilder(
|
|||||||
output("RUNTIME_USED ${prefix}_ExportedSymbols* $exportedSymbol(void) { return &__konan_symbols;}")
|
output("RUNTIME_USED ${prefix}_ExportedSymbols* $exportedSymbol(void) { return &__konan_symbols;}")
|
||||||
outputStreamWriter.close()
|
outputStreamWriter.close()
|
||||||
|
|
||||||
if (context.config.target.family == Family.MINGW) {
|
if (generationState.config.target.family == Family.MINGW) {
|
||||||
outputStreamWriter = generationState.outputFiles
|
outputStreamWriter = generationState.outputFiles
|
||||||
.cAdapterDef
|
.cAdapterDef
|
||||||
.printWriter()
|
.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.target.*
|
||||||
import org.jetbrains.kotlin.konan.file.*
|
import org.jetbrains.kotlin.konan.file.*
|
||||||
|
|
||||||
|
// Fourth phase of C export: compile runtime bindings to bitcode.
|
||||||
fun produceCAdapterBitcode(clang: ClangArgs, cppFileName: String, bitcodeFileName: String) {
|
fun produceCAdapterBitcode(clang: ClangArgs, cppFileName: String, bitcodeFileName: String) {
|
||||||
val clangCommand = clang.clangCXX("-std=c++17", cppFileName, "-emit-llvm", "-c", "-o", bitcodeFileName)
|
val clangCommand = clang.clangCXX("-std=c++17", cppFileName, "-emit-llvm", "-c", "-o", bitcodeFileName)
|
||||||
Command(clangCommand).execute()
|
Command(clangCommand).execute()
|
||||||
|
|||||||
+11
-26
@@ -5,26 +5,24 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.konan.cexport
|
package org.jetbrains.kotlin.backend.konan.cexport
|
||||||
|
|
||||||
import llvm.*
|
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.allParameters
|
import org.jetbrains.kotlin.backend.common.descriptors.allParameters
|
||||||
import org.jetbrains.kotlin.backend.common.pop
|
import org.jetbrains.kotlin.backend.common.pop
|
||||||
import org.jetbrains.kotlin.backend.common.push
|
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.driver.phases.PsiToIrContext
|
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.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
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.ir.util.referenceFunction
|
||||||
import org.jetbrains.kotlin.konan.target.*
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.name.isChildOf
|
import org.jetbrains.kotlin.name.isChildOf
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.annotations.*
|
import org.jetbrains.kotlin.resolve.annotations.argumentValue
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
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.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.*
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
|
|
||||||
internal enum class ScopeKind {
|
internal enum class ScopeKind {
|
||||||
TOP,
|
TOP,
|
||||||
@@ -96,11 +94,6 @@ internal class ExportedElementScope(val kind: ScopeKind, val name: String) {
|
|||||||
return "$kind: $name ${elements.joinToString(", ")} ${scopes.joinToString("\n")}"
|
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
|
// 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) {
|
fun collectInnerScopeName(innerScope: ExportedElementScope) {
|
||||||
scopeNames += innerScope.name
|
scopeNames += innerScope.name
|
||||||
@@ -396,17 +389,18 @@ private fun ModuleDescriptor.getPackageFragments(): List<PackageFragmentDescript
|
|||||||
getPackage(it).fragments.filter { it.module == this }
|
getPackage(it).fragments.filter { it.module == this }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* First phase of C export: walk given declaration descriptors and create [CAdapterExportedElements] from them.
|
||||||
|
*/
|
||||||
internal class CAdapterGenerator(
|
internal class CAdapterGenerator(
|
||||||
private val context: PsiToIrContext,
|
private val context: PsiToIrContext,
|
||||||
private val moduleDescriptor: ModuleDescriptor,
|
|
||||||
private val typeTranslator: CAdapterTypeTranslator,
|
private val typeTranslator: CAdapterTypeTranslator,
|
||||||
) : DeclarationDescriptorVisitor<Boolean, Void?> {
|
) : DeclarationDescriptorVisitor<Boolean, Void?> {
|
||||||
private val scopes = mutableListOf<ExportedElementScope>()
|
private val scopes = mutableListOf<ExportedElementScope>()
|
||||||
internal val prefix = typeTranslator.prefix
|
internal val prefix = typeTranslator.prefix
|
||||||
private val paramNamesRecorded = mutableMapOf<String, Int>()
|
private val paramNamesRecorded = mutableMapOf<String, Int>()
|
||||||
|
|
||||||
private var symbolTableOrNull: SymbolTable? = null
|
internal val symbolTable get() = context.symbolTable!!
|
||||||
internal val symbolTable get() = symbolTableOrNull!!
|
|
||||||
|
|
||||||
internal fun paramsToUniqueNames(params: List<ParameterDescriptor>): Map<ParameterDescriptor, String> {
|
internal fun paramsToUniqueNames(params: List<ParameterDescriptor>): Map<ParameterDescriptor, String> {
|
||||||
paramNamesRecorded.clear()
|
paramNamesRecorded.clear()
|
||||||
@@ -536,17 +530,7 @@ internal class CAdapterGenerator(
|
|||||||
|
|
||||||
private val moduleDescriptors = mutableSetOf<ModuleDescriptor>()
|
private val moduleDescriptors = mutableSetOf<ModuleDescriptor>()
|
||||||
|
|
||||||
fun buildExports(symbolTable: SymbolTable): CAdapterExportedElements {
|
fun buildExports(moduleDescriptor: ModuleDescriptor): CAdapterExportedElements {
|
||||||
this.symbolTableOrNull = symbolTable
|
|
||||||
try {
|
|
||||||
buildExports()
|
|
||||||
return CAdapterExportedElements(typeTranslator, scopes)
|
|
||||||
} finally {
|
|
||||||
this.symbolTableOrNull = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildExports() {
|
|
||||||
scopes.push(ExportedElementScope(ScopeKind.TOP, "kotlin"))
|
scopes.push(ExportedElementScope(ScopeKind.TOP, "kotlin"))
|
||||||
moduleDescriptors += moduleDescriptor
|
moduleDescriptors += moduleDescriptor
|
||||||
moduleDescriptors += moduleDescriptor.getExportedDependencies(context.config)
|
moduleDescriptors += moduleDescriptor.getExportedDependencies(context.config)
|
||||||
@@ -557,6 +541,7 @@ internal class CAdapterGenerator(
|
|||||||
})
|
})
|
||||||
|
|
||||||
moduleDescriptor.getPackage(FqName.ROOT).accept(this, null)
|
moduleDescriptor.getPackage(FqName.ROOT).accept(this, null)
|
||||||
|
return CAdapterExportedElements(typeTranslator, scopes)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val simpleNameMapping = mapOf(
|
private val simpleNameMapping = mapOf(
|
||||||
|
|||||||
+1
-1
@@ -15,5 +15,5 @@ internal val BuildCExports = createSimpleNamedCompilerPhase<PsiToIrContext, Fron
|
|||||||
) { context, input ->
|
) { context, input ->
|
||||||
val prefix = context.config.fullExportedNamePrefix.replace("-|\\.".toRegex(), "_")
|
val prefix = context.config.fullExportedNamePrefix.replace("-|\\.".toRegex(), "_")
|
||||||
val typeTranslator = CAdapterTypeTranslator(prefix, context.builtIns)
|
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.coroutines.getOrCreateFunctionWithContinuationStub
|
||||||
import org.jetbrains.kotlin.backend.common.lower.inline.InlinerExpressionLocationHint
|
import org.jetbrains.kotlin.backend.common.lower.inline.InlinerExpressionLocationHint
|
||||||
import org.jetbrains.kotlin.backend.konan.*
|
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.cgen.CBridgeOrigin
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
import org.jetbrains.kotlin.backend.konan.ir.*
|
||||||
@@ -327,7 +328,10 @@ internal class CodeGeneratorVisitor(val generationState: NativeGenerationState,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private fun appendCAdapters() {
|
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) {
|
private fun FunctionGenerationContext.initThreadLocalField(irField: IrField) {
|
||||||
|
|||||||
Reference in New Issue
Block a user