Refactor CAdapterGenerator to avoid using SymbolTable during codegen

This commit is contained in:
Svyatoslav Scherbina
2019-04-11 14:15:47 +03:00
committed by SvyatoslavScherbina
parent 1ec5a188f7
commit 50c4fcb3db
4 changed files with 66 additions and 12 deletions
@@ -18,6 +18,11 @@ import org.jetbrains.kotlin.backend.konan.llvm.*
import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.descriptors.*
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.name.isChildOf
import org.jetbrains.kotlin.name.FqName
@@ -204,8 +209,9 @@ private class ExportedElement(val kind: ElementKind,
when {
isFunction -> {
val function = declaration as FunctionDescriptor
val irFunction = irSymbol.owner as IrFunction
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.
val bridge = if (!DescriptorUtils.isTopLevelDeclaration(function) && !function.isExtension &&
function.isOverridable) {
@@ -214,7 +220,7 @@ private class ExportedElement(val kind: ElementKind,
val receiver = param(0)
val numParams = LLVMCountParams(llvmFunction)
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)
ret(result)
}
@@ -224,19 +230,19 @@ private class ExportedElement(val kind: ElementKind,
LLVMSetLinkage(bridge, LLVMLinkage.LLVMExternalLinkage)
}
isClass -> {
val classDescriptor = declaration as ClassDescriptor
val irClass = irSymbol.owner as IrClass
cname = "_konan_function_${owner.nextFunctionIndex()}"
// Produce type getter.
val getTypeFunction = LLVMAddFunction(context.llvmModule, "${cname}_type", owner.kGetTypeFuncType)!!
val builder = LLVMCreateBuilder()!!
val bb = LLVMAppendBasicBlock(getTypeFunction, "")!!
LLVMPositionBuilderAtEnd(builder, bb)
LLVMBuildRet(builder, context.ir.getFromCurrentModule(classDescriptor).typeInfoPtr.llvm)
LLVMBuildRet(builder, irClass.typeInfoPtr.llvm)
LLVMDisposeBuilder(builder)
// Produce instance getter if needed.
if (isSingletonObject) {
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)
}
}
@@ -245,7 +251,7 @@ private class ExportedElement(val kind: ElementKind,
// Produce entry getter.
cname = "_konan_function_${owner.nextFunctionIndex()}"
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)
ret(value)
}
@@ -269,6 +275,13 @@ private class ExportedElement(val kind: ElementKind,
val isEnumEntry = declaration is ClassDescriptor && declaration.kind == ClassKind.ENUM_ENTRY
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 makeCFunctionSignature(shortName: Boolean): List<Pair<String, ClassDescriptor>> {
@@ -493,14 +506,19 @@ private fun ModuleDescriptor.getPackageFragments(): List<PackageFragmentDescript
getPackage(it).fragments.filter { it.module == this }
}
internal class CAdapterGenerator(
val context: Context, internal val codegen: CodeGenerator) : DeclarationDescriptorVisitor<Boolean, Void?> {
internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVisitor<Boolean, Void?> {
private val scopes = mutableListOf<ExportedElementScope>()
internal val prefix = context.config.moduleId
private lateinit var outputStreamWriter: PrintWriter
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> {
paramNamesRecorded.clear()
return params.associate {
@@ -641,7 +659,25 @@ internal class CAdapterGenerator(
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"))
moduleDescriptors += context.moduleDescriptor
moduleDescriptors += context.getExportedDependencies()
@@ -660,7 +696,9 @@ internal class CAdapterGenerator(
).forEach {
TypeUtils.getClassDescriptor(it)!!.accept(this@CAdapterGenerator, null)
}
}
private fun generateBindings() {
val top = scopes.pop()
assert(scopes.isEmpty() && top.kind == ScopeKind.TOP)
@@ -1012,9 +1050,9 @@ internal class CAdapterGenerator(
private var functionIndex = 0
fun nextFunctionIndex() = functionIndex++
internal val kGetTypeFuncType =
internal val kGetTypeFuncType get() =
LLVMFunctionType(codegen.kTypeInfoPtr, null, 0, 0)!!
// Abstraction leak for slot :(.
internal val kGetObjectFuncType =
internal val kGetObjectFuncType get() =
LLVMFunctionType(codegen.kObjHeaderPtr, cValuesOf(codegen.kObjHeaderPtrPtr), 1, 0)!!
}
@@ -203,6 +203,8 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
lateinit var objCExport: ObjCExport
lateinit var cAdapterGenerator: CAdapterGenerator
override val builtIns: KonanBuiltIns by lazy(PUBLICATION) {
moduleDescriptor.builtIns as KonanBuiltIns
}
@@ -72,6 +72,19 @@ internal val objCExportPhase = konanUnitPhase(
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(
op = {
// Translate AST to high level IR.
@@ -303,6 +316,7 @@ val toplevelPhase: CompilerPhase<*, Unit, Unit> = namedUnitPhase(
lower = frontendPhase then
createSymbolTablePhase then
objCExportPhase then
buildCExportsPhase then
psiToIrPhase then
destroySymbolTablePhase then
irGeneratorPluginsPhase then
@@ -295,7 +295,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
}
private fun appendCAdapters() {
CAdapterGenerator(context, codegen).generateBindings()
context.cAdapterGenerator.generateBindings(codegen)
}
//-------------------------------------------------------------------------//