Refactor CAdapterGenerator to avoid using SymbolTable during codegen
This commit is contained in:
committed by
SvyatoslavScherbina
parent
1ec5a188f7
commit
50c4fcb3db
+49
-11
@@ -18,6 +18,11 @@ import org.jetbrains.kotlin.backend.konan.llvm.*
|
|||||||
import org.jetbrains.kotlin.builtins.UnsignedType
|
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||||
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.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrEnumEntry
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
|
import org.jetbrains.kotlin.ir.util.referenceFunction
|
||||||
import org.jetbrains.kotlin.konan.target.*
|
import org.jetbrains.kotlin.konan.target.*
|
||||||
import org.jetbrains.kotlin.name.isChildOf
|
import org.jetbrains.kotlin.name.isChildOf
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -204,8 +209,9 @@ private class ExportedElement(val kind: ElementKind,
|
|||||||
when {
|
when {
|
||||||
isFunction -> {
|
isFunction -> {
|
||||||
val function = declaration as FunctionDescriptor
|
val function = declaration as FunctionDescriptor
|
||||||
|
val irFunction = irSymbol.owner as IrFunction
|
||||||
cname = "_konan_function_${owner.nextFunctionIndex()}"
|
cname = "_konan_function_${owner.nextFunctionIndex()}"
|
||||||
val llvmFunction = owner.codegen.llvmFunction(context.ir.getFromCurrentModule(function))
|
val llvmFunction = owner.codegen.llvmFunction(irFunction)
|
||||||
// If function is virtual, we need to resolve receiver properly.
|
// If function is virtual, we need to resolve receiver properly.
|
||||||
val bridge = if (!DescriptorUtils.isTopLevelDeclaration(function) && !function.isExtension &&
|
val bridge = if (!DescriptorUtils.isTopLevelDeclaration(function) && !function.isExtension &&
|
||||||
function.isOverridable) {
|
function.isOverridable) {
|
||||||
@@ -214,7 +220,7 @@ private class ExportedElement(val kind: ElementKind,
|
|||||||
val receiver = param(0)
|
val receiver = param(0)
|
||||||
val numParams = LLVMCountParams(llvmFunction)
|
val numParams = LLVMCountParams(llvmFunction)
|
||||||
val args = (0..numParams - 1).map { index -> param(index) }
|
val args = (0..numParams - 1).map { index -> param(index) }
|
||||||
val callee = lookupVirtualImpl(receiver, context.ir.getFromCurrentModule(function))
|
val callee = lookupVirtualImpl(receiver, irFunction)
|
||||||
val result = call(callee, args, exceptionHandler = ExceptionHandler.Caller, verbatim = true)
|
val result = call(callee, args, exceptionHandler = ExceptionHandler.Caller, verbatim = true)
|
||||||
ret(result)
|
ret(result)
|
||||||
}
|
}
|
||||||
@@ -224,19 +230,19 @@ private class ExportedElement(val kind: ElementKind,
|
|||||||
LLVMSetLinkage(bridge, LLVMLinkage.LLVMExternalLinkage)
|
LLVMSetLinkage(bridge, LLVMLinkage.LLVMExternalLinkage)
|
||||||
}
|
}
|
||||||
isClass -> {
|
isClass -> {
|
||||||
val classDescriptor = declaration as ClassDescriptor
|
val irClass = irSymbol.owner as IrClass
|
||||||
cname = "_konan_function_${owner.nextFunctionIndex()}"
|
cname = "_konan_function_${owner.nextFunctionIndex()}"
|
||||||
// Produce type getter.
|
// Produce type getter.
|
||||||
val getTypeFunction = LLVMAddFunction(context.llvmModule, "${cname}_type", owner.kGetTypeFuncType)!!
|
val getTypeFunction = LLVMAddFunction(context.llvmModule, "${cname}_type", owner.kGetTypeFuncType)!!
|
||||||
val builder = LLVMCreateBuilder()!!
|
val builder = LLVMCreateBuilder()!!
|
||||||
val bb = LLVMAppendBasicBlock(getTypeFunction, "")!!
|
val bb = LLVMAppendBasicBlock(getTypeFunction, "")!!
|
||||||
LLVMPositionBuilderAtEnd(builder, bb)
|
LLVMPositionBuilderAtEnd(builder, bb)
|
||||||
LLVMBuildRet(builder, context.ir.getFromCurrentModule(classDescriptor).typeInfoPtr.llvm)
|
LLVMBuildRet(builder, irClass.typeInfoPtr.llvm)
|
||||||
LLVMDisposeBuilder(builder)
|
LLVMDisposeBuilder(builder)
|
||||||
// Produce instance getter if needed.
|
// Produce instance getter if needed.
|
||||||
if (isSingletonObject) {
|
if (isSingletonObject) {
|
||||||
generateFunction(owner.codegen, owner.kGetObjectFuncType, "${cname}_instance") {
|
generateFunction(owner.codegen, owner.kGetObjectFuncType, "${cname}_instance") {
|
||||||
val value = getObjectValue(context.ir.get(classDescriptor), ExceptionHandler.Caller, null)
|
val value = getObjectValue(irClass, ExceptionHandler.Caller, null)
|
||||||
ret(value)
|
ret(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -245,7 +251,7 @@ private class ExportedElement(val kind: ElementKind,
|
|||||||
// Produce entry getter.
|
// Produce entry getter.
|
||||||
cname = "_konan_function_${owner.nextFunctionIndex()}"
|
cname = "_konan_function_${owner.nextFunctionIndex()}"
|
||||||
generateFunction(owner.codegen, owner.kGetObjectFuncType, cname) {
|
generateFunction(owner.codegen, owner.kGetObjectFuncType, cname) {
|
||||||
val irEnumEntry = context.ir.getEnumEntryFromCurrentModule(declaration as ClassDescriptor)
|
val irEnumEntry = irSymbol.owner as IrEnumEntry
|
||||||
val value = getEnumEntry(irEnumEntry, ExceptionHandler.Caller)
|
val value = getEnumEntry(irEnumEntry, ExceptionHandler.Caller)
|
||||||
ret(value)
|
ret(value)
|
||||||
}
|
}
|
||||||
@@ -269,6 +275,13 @@ private class ExportedElement(val kind: ElementKind,
|
|||||||
val isEnumEntry = declaration is ClassDescriptor && declaration.kind == ClassKind.ENUM_ENTRY
|
val isEnumEntry = declaration is ClassDescriptor && declaration.kind == ClassKind.ENUM_ENTRY
|
||||||
val isSingletonObject = declaration is ClassDescriptor && DescriptorUtils.isObject(declaration)
|
val isSingletonObject = declaration is ClassDescriptor && DescriptorUtils.isObject(declaration)
|
||||||
|
|
||||||
|
private val irSymbol = when {
|
||||||
|
isFunction -> owner.symbolTable.referenceFunction(declaration as FunctionDescriptor)
|
||||||
|
isClass -> owner.symbolTable.referenceClass(declaration as ClassDescriptor)
|
||||||
|
isEnumEntry -> owner.symbolTable.referenceEnumEntry(declaration as ClassDescriptor)
|
||||||
|
else -> error("unexpected $kind element: $declaration")
|
||||||
|
}
|
||||||
|
|
||||||
fun KotlinType.includeToSignature() = !this.isUnit()
|
fun KotlinType.includeToSignature() = !this.isUnit()
|
||||||
|
|
||||||
fun makeCFunctionSignature(shortName: Boolean): List<Pair<String, ClassDescriptor>> {
|
fun makeCFunctionSignature(shortName: Boolean): List<Pair<String, ClassDescriptor>> {
|
||||||
@@ -493,14 +506,19 @@ private fun ModuleDescriptor.getPackageFragments(): List<PackageFragmentDescript
|
|||||||
getPackage(it).fragments.filter { it.module == this }
|
getPackage(it).fragments.filter { it.module == this }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class CAdapterGenerator(
|
internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVisitor<Boolean, Void?> {
|
||||||
val context: Context, internal val codegen: CodeGenerator) : DeclarationDescriptorVisitor<Boolean, Void?> {
|
|
||||||
|
|
||||||
private val scopes = mutableListOf<ExportedElementScope>()
|
private val scopes = mutableListOf<ExportedElementScope>()
|
||||||
internal val prefix = context.config.moduleId
|
internal val prefix = context.config.moduleId
|
||||||
private lateinit var outputStreamWriter: PrintWriter
|
private lateinit var outputStreamWriter: PrintWriter
|
||||||
private val paramNamesRecorded = mutableMapOf<String, Int>()
|
private val paramNamesRecorded = mutableMapOf<String, Int>()
|
||||||
|
|
||||||
|
private var codegenOrNull: CodeGenerator? = null
|
||||||
|
internal val codegen get() = codegenOrNull!!
|
||||||
|
|
||||||
|
private var symbolTableOrNull: SymbolTable? = null
|
||||||
|
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()
|
||||||
return params.associate {
|
return params.associate {
|
||||||
@@ -641,7 +659,25 @@ internal class CAdapterGenerator(
|
|||||||
|
|
||||||
private val moduleDescriptors = mutableSetOf<ModuleDescriptor>()
|
private val moduleDescriptors = mutableSetOf<ModuleDescriptor>()
|
||||||
|
|
||||||
fun generateBindings() {
|
fun buildExports(symbolTable: SymbolTable) {
|
||||||
|
this.symbolTableOrNull = symbolTable
|
||||||
|
try {
|
||||||
|
buildExports()
|
||||||
|
} finally {
|
||||||
|
this.symbolTableOrNull = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateBindings(codegen: CodeGenerator) {
|
||||||
|
this.codegenOrNull = codegen
|
||||||
|
try {
|
||||||
|
generateBindings()
|
||||||
|
} finally {
|
||||||
|
this.codegenOrNull = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildExports() {
|
||||||
scopes.push(ExportedElementScope(ScopeKind.TOP, "kotlin"))
|
scopes.push(ExportedElementScope(ScopeKind.TOP, "kotlin"))
|
||||||
moduleDescriptors += context.moduleDescriptor
|
moduleDescriptors += context.moduleDescriptor
|
||||||
moduleDescriptors += context.getExportedDependencies()
|
moduleDescriptors += context.getExportedDependencies()
|
||||||
@@ -660,7 +696,9 @@ internal class CAdapterGenerator(
|
|||||||
).forEach {
|
).forEach {
|
||||||
TypeUtils.getClassDescriptor(it)!!.accept(this@CAdapterGenerator, null)
|
TypeUtils.getClassDescriptor(it)!!.accept(this@CAdapterGenerator, null)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateBindings() {
|
||||||
val top = scopes.pop()
|
val top = scopes.pop()
|
||||||
assert(scopes.isEmpty() && top.kind == ScopeKind.TOP)
|
assert(scopes.isEmpty() && top.kind == ScopeKind.TOP)
|
||||||
|
|
||||||
@@ -1012,9 +1050,9 @@ internal class CAdapterGenerator(
|
|||||||
private var functionIndex = 0
|
private var functionIndex = 0
|
||||||
fun nextFunctionIndex() = functionIndex++
|
fun nextFunctionIndex() = functionIndex++
|
||||||
|
|
||||||
internal val kGetTypeFuncType =
|
internal val kGetTypeFuncType get() =
|
||||||
LLVMFunctionType(codegen.kTypeInfoPtr, null, 0, 0)!!
|
LLVMFunctionType(codegen.kTypeInfoPtr, null, 0, 0)!!
|
||||||
// Abstraction leak for slot :(.
|
// Abstraction leak for slot :(.
|
||||||
internal val kGetObjectFuncType =
|
internal val kGetObjectFuncType get() =
|
||||||
LLVMFunctionType(codegen.kObjHeaderPtr, cValuesOf(codegen.kObjHeaderPtrPtr), 1, 0)!!
|
LLVMFunctionType(codegen.kObjHeaderPtr, cValuesOf(codegen.kObjHeaderPtrPtr), 1, 0)!!
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -203,6 +203,8 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
|||||||
|
|
||||||
lateinit var objCExport: ObjCExport
|
lateinit var objCExport: ObjCExport
|
||||||
|
|
||||||
|
lateinit var cAdapterGenerator: CAdapterGenerator
|
||||||
|
|
||||||
override val builtIns: KonanBuiltIns by lazy(PUBLICATION) {
|
override val builtIns: KonanBuiltIns by lazy(PUBLICATION) {
|
||||||
moduleDescriptor.builtIns as KonanBuiltIns
|
moduleDescriptor.builtIns as KonanBuiltIns
|
||||||
}
|
}
|
||||||
|
|||||||
+14
@@ -72,6 +72,19 @@ internal val objCExportPhase = konanUnitPhase(
|
|||||||
description = "Objective-C header generation"
|
description = "Objective-C header generation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
internal val buildCExportsPhase = konanUnitPhase(
|
||||||
|
op = {
|
||||||
|
if (this.isNativeLibrary) {
|
||||||
|
this.cAdapterGenerator = CAdapterGenerator(this).also {
|
||||||
|
it.buildExports(this.symbolTable!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name = "BuildCExports",
|
||||||
|
description = "Build C exports",
|
||||||
|
prerequisite = setOf(createSymbolTablePhase)
|
||||||
|
)
|
||||||
|
|
||||||
internal val psiToIrPhase = konanUnitPhase(
|
internal val psiToIrPhase = konanUnitPhase(
|
||||||
op = {
|
op = {
|
||||||
// Translate AST to high level IR.
|
// Translate AST to high level IR.
|
||||||
@@ -303,6 +316,7 @@ val toplevelPhase: CompilerPhase<*, Unit, Unit> = namedUnitPhase(
|
|||||||
lower = frontendPhase then
|
lower = frontendPhase then
|
||||||
createSymbolTablePhase then
|
createSymbolTablePhase then
|
||||||
objCExportPhase then
|
objCExportPhase then
|
||||||
|
buildCExportsPhase then
|
||||||
psiToIrPhase then
|
psiToIrPhase then
|
||||||
destroySymbolTablePhase then
|
destroySymbolTablePhase then
|
||||||
irGeneratorPluginsPhase then
|
irGeneratorPluginsPhase then
|
||||||
|
|||||||
+1
-1
@@ -295,7 +295,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun appendCAdapters() {
|
private fun appendCAdapters() {
|
||||||
CAdapterGenerator(context, codegen).generateBindings()
|
context.cAdapterGenerator.generateBindings(codegen)
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|||||||
Reference in New Issue
Block a user