[K/N][codegen] Split CAdapterGenerator on two parts
This commit is contained in:
+198
-208
@@ -162,13 +162,9 @@ private 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() {
|
fun generateCAdapters(builder: (ExportedElement) -> Unit) {
|
||||||
elements.forEach {
|
elements.forEach { builder(it) }
|
||||||
it.generateCAdapter()
|
scopes.forEach { it.generateCAdapters(builder) }
|
||||||
}
|
|
||||||
scopes.forEach {
|
|
||||||
it.generateCAdapters()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
@@ -197,7 +193,7 @@ private class ExportedElementScope(val kind: ScopeKind, val name: String) {
|
|||||||
private class ExportedElement(val kind: ElementKind,
|
private class ExportedElement(val kind: ElementKind,
|
||||||
val scope: ExportedElementScope,
|
val scope: ExportedElementScope,
|
||||||
val declaration: DeclarationDescriptor,
|
val declaration: DeclarationDescriptor,
|
||||||
val owner: CAdapterGenerator) : ContextUtils {
|
val owner: CAdapterGenerator) {
|
||||||
init {
|
init {
|
||||||
scope.elements.add(this)
|
scope.elements.add(this)
|
||||||
}
|
}
|
||||||
@@ -211,76 +207,6 @@ private class ExportedElement(val kind: ElementKind,
|
|||||||
return "$kind: $name (aliased to ${if (::cname.isInitialized) cname.toString() else "<unknown>"})"
|
return "$kind: $name (aliased to ${if (::cname.isInitialized) cname.toString() else "<unknown>"})"
|
||||||
}
|
}
|
||||||
|
|
||||||
override val context = owner.context
|
|
||||||
|
|
||||||
fun generateCAdapter() {
|
|
||||||
when {
|
|
||||||
isFunction -> {
|
|
||||||
val function = declaration as FunctionDescriptor
|
|
||||||
val irFunction = irSymbol.owner as IrFunction
|
|
||||||
cname = "_konan_function_${owner.nextFunctionIndex()}"
|
|
||||||
val llvmCallable = owner.codegen.llvmFunction(irFunction)
|
|
||||||
// If function is virtual, we need to resolve receiver properly.
|
|
||||||
val bridge = generateFunction(owner.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..numParams - 1).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",
|
|
||||||
owner.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(owner.codegen, owner.kGetObjectFuncType, "${cname}_instance") {
|
|
||||||
val value = call(
|
|
||||||
owner.codegen.llvmFunction(context.getObjectClassInstanceFunction(irClass)),
|
|
||||||
emptyList(),
|
|
||||||
Lifetime.GLOBAL,
|
|
||||||
ExceptionHandler.Caller,
|
|
||||||
false,
|
|
||||||
returnSlot)
|
|
||||||
ret(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
isEnumEntry -> {
|
|
||||||
// Produce entry getter.
|
|
||||||
cname = "_konan_function_${owner.nextFunctionIndex()}"
|
|
||||||
generateFunction(owner.codegen, owner.kGetObjectFuncType, cname) {
|
|
||||||
val irEnumEntry = irSymbol.owner as IrEnumEntry
|
|
||||||
val value = getEnumEntry(irEnumEntry, ExceptionHandler.Caller)
|
|
||||||
ret(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun uniqueName(descriptor: DeclarationDescriptor, shortName: Boolean) =
|
fun uniqueName(descriptor: DeclarationDescriptor, shortName: Boolean) =
|
||||||
scope.scopeUniqueName(descriptor, shortName)
|
scope.scopeUniqueName(descriptor, shortName)
|
||||||
|
|
||||||
@@ -298,7 +224,7 @@ 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 {
|
val irSymbol = when {
|
||||||
isFunction -> owner.symbolTable.referenceFunction(declaration as FunctionDescriptor)
|
isFunction -> owner.symbolTable.referenceFunction(declaration as FunctionDescriptor)
|
||||||
isClass -> owner.symbolTable.referenceClass(declaration as ClassDescriptor)
|
isClass -> owner.symbolTable.referenceClass(declaration as ClassDescriptor)
|
||||||
isEnumEntry -> owner.symbolTable.referenceEnumEntry(declaration as ClassDescriptor)
|
isEnumEntry -> owner.symbolTable.referenceEnumEntry(declaration as ClassDescriptor)
|
||||||
@@ -534,30 +460,15 @@ private fun ModuleDescriptor.getPackageFragments(): List<PackageFragmentDescript
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVisitor<Boolean, Void?> {
|
internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVisitor<Boolean, Void?> {
|
||||||
|
private val builtIns = context.builtIns
|
||||||
|
|
||||||
private val scopes = mutableListOf<ExportedElementScope>()
|
private val scopes = mutableListOf<ExportedElementScope>()
|
||||||
internal val prefix = context.config.fullExportedNamePrefix.replace("-|\\.".toRegex(), "_")
|
internal val prefix = context.config.fullExportedNamePrefix.replace("-|\\.".toRegex(), "_")
|
||||||
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
|
private var symbolTableOrNull: SymbolTable? = null
|
||||||
internal val symbolTable get() = symbolTableOrNull!!
|
internal val symbolTable get() = symbolTableOrNull!!
|
||||||
|
|
||||||
// Primitive built-ins and unsigned types
|
|
||||||
private val predefinedTypes = listOf(
|
|
||||||
context.builtIns.byteType, context.builtIns.shortType,
|
|
||||||
context.builtIns.intType, context.builtIns.longType,
|
|
||||||
context.builtIns.floatType, context.builtIns.doubleType,
|
|
||||||
context.builtIns.charType, context.builtIns.booleanType,
|
|
||||||
context.builtIns.unitType
|
|
||||||
) + UnsignedType.values().map {
|
|
||||||
// Unfortunately, `context.ir` and `context.irBuiltins` are not initialized, so `context.ir.symbols.ubyte`, etc, are unreachable.
|
|
||||||
context.builtIns.builtInsModule.findClassAcrossModuleDependencies(it.classId)!!.defaultType
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
||||||
@@ -695,15 +606,6 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateBindings(codegen: CodeGenerator) {
|
|
||||||
this.codegenOrNull = codegen
|
|
||||||
try {
|
|
||||||
generateBindings()
|
|
||||||
} finally {
|
|
||||||
this.codegenOrNull = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildExports() {
|
private fun buildExports() {
|
||||||
scopes.push(ExportedElementScope(ScopeKind.TOP, "kotlin"))
|
scopes.push(ExportedElementScope(ScopeKind.TOP, "kotlin"))
|
||||||
moduleDescriptors += context.moduleDescriptor
|
moduleDescriptors += context.moduleDescriptor
|
||||||
@@ -717,17 +619,207 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
|||||||
context.moduleDescriptor.getPackage(FqName.ROOT).accept(this, null)
|
context.moduleDescriptor.getPackage(FqName.ROOT).accept(this, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateBindings() {
|
private val simpleNameMapping = mapOf(
|
||||||
|
"<this>" to "thiz",
|
||||||
|
"<set-?>" to "set"
|
||||||
|
)
|
||||||
|
|
||||||
|
private val primitiveTypeMapping = KonanPrimitiveType.values().associate {
|
||||||
|
it to when (it) {
|
||||||
|
KonanPrimitiveType.BOOLEAN -> "${prefix}_KBoolean"
|
||||||
|
KonanPrimitiveType.CHAR -> "${prefix}_KChar"
|
||||||
|
KonanPrimitiveType.BYTE -> "${prefix}_KByte"
|
||||||
|
KonanPrimitiveType.SHORT -> "${prefix}_KShort"
|
||||||
|
KonanPrimitiveType.INT -> "${prefix}_KInt"
|
||||||
|
KonanPrimitiveType.LONG -> "${prefix}_KLong"
|
||||||
|
KonanPrimitiveType.FLOAT -> "${prefix}_KFloat"
|
||||||
|
KonanPrimitiveType.DOUBLE -> "${prefix}_KDouble"
|
||||||
|
KonanPrimitiveType.NON_NULL_NATIVE_PTR -> "void*"
|
||||||
|
KonanPrimitiveType.VECTOR128 -> "${prefix}_KVector128"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val unsignedTypeMapping = UnsignedType.values().associate {
|
||||||
|
it.classId to when (it) {
|
||||||
|
UnsignedType.UBYTE -> "${prefix}_KUByte"
|
||||||
|
UnsignedType.USHORT -> "${prefix}_KUShort"
|
||||||
|
UnsignedType.UINT -> "${prefix}_KUInt"
|
||||||
|
UnsignedType.ULONG -> "${prefix}_KULong"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun isMappedToString(type: KotlinType): Boolean =
|
||||||
|
isMappedToString(type.computeBinaryType())
|
||||||
|
|
||||||
|
private fun isMappedToString(binaryType: BinaryType<ClassDescriptor>): Boolean =
|
||||||
|
when (binaryType) {
|
||||||
|
is BinaryType.Primitive -> false
|
||||||
|
is BinaryType.Reference -> binaryType.types.first() == builtIns.string
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun isMappedToReference(type: KotlinType) =
|
||||||
|
!isMappedToVoid(type) && !isMappedToString(type) &&
|
||||||
|
type.binaryTypeIsReference()
|
||||||
|
|
||||||
|
internal fun isMappedToVoid(type: KotlinType): Boolean {
|
||||||
|
return type.isUnit() || type.isNothing()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun translateName(name: Name): String {
|
||||||
|
val nameString = name.asString()
|
||||||
|
return when {
|
||||||
|
simpleNameMapping.contains(nameString) -> simpleNameMapping[nameString]!!
|
||||||
|
cKeywords.contains(nameString) -> "${nameString}_"
|
||||||
|
name.isSpecial -> nameString.replace("[<> ]".toRegex(), "_")
|
||||||
|
else -> nameString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun translateTypeFull(type: KotlinType): Pair<String, String> =
|
||||||
|
if (isMappedToVoid(type)) {
|
||||||
|
"void" to "void"
|
||||||
|
} else {
|
||||||
|
translateNonVoidTypeFull(type)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun translateNonVoidTypeFull(type: KotlinType): Pair<String, String> = type.unwrapToPrimitiveOrReference(
|
||||||
|
eachInlinedClass = { inlinedClass, _ ->
|
||||||
|
unsignedTypeMapping[inlinedClass.classId]?.let {
|
||||||
|
return it to it
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ifPrimitive = { primitiveType, _ ->
|
||||||
|
primitiveTypeMapping[primitiveType]!!.let { it to it }
|
||||||
|
},
|
||||||
|
ifReference = {
|
||||||
|
val clazz = (it.computeBinaryType() as BinaryType.Reference).types.first()
|
||||||
|
if (clazz == builtIns.string) {
|
||||||
|
"const char*" to "KObjHeader*"
|
||||||
|
} else {
|
||||||
|
"${prefix}_kref_${translateTypeFqName(clazz.fqNameSafe.asString())}" to "KObjHeader*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
fun translateType(element: SignatureElement): String =
|
||||||
|
translateTypeFull(element.type).first
|
||||||
|
|
||||||
|
fun translateType(type: KotlinType): String
|
||||||
|
= translateTypeFull(type).first
|
||||||
|
|
||||||
|
fun translateTypeBridge(type: KotlinType): String = translateTypeFull(type).second
|
||||||
|
|
||||||
|
fun translateTypeFqName(name: String): String {
|
||||||
|
return name.replace('.', '_')
|
||||||
|
}
|
||||||
|
|
||||||
|
private var functionIndex = 0
|
||||||
|
fun nextFunctionIndex() = functionIndex++
|
||||||
|
|
||||||
|
fun generateBindings(codegen: CodeGenerator) = BindingsBuilder(codegen).build()
|
||||||
|
|
||||||
|
inner class BindingsBuilder(val codegen: CodeGenerator) : ContextUtils {
|
||||||
|
override val context = this@CAdapterGenerator.context
|
||||||
|
|
||||||
|
internal val prefix = context.config.fullExportedNamePrefix.replace("-|\\.".toRegex(), "_")
|
||||||
|
private lateinit var outputStreamWriter: PrintWriter
|
||||||
|
|
||||||
|
// Primitive built-ins and unsigned types
|
||||||
|
private val predefinedTypes = listOf(
|
||||||
|
builtIns.byteType, builtIns.shortType,
|
||||||
|
builtIns.intType, builtIns.longType,
|
||||||
|
builtIns.floatType, builtIns.doubleType,
|
||||||
|
builtIns.charType, builtIns.booleanType,
|
||||||
|
builtIns.unitType
|
||||||
|
) + UnsignedType.values().map {
|
||||||
|
// Unfortunately, `context.ir` and `context.irBuiltins` are not initialized, so `context.ir.symbols.ubyte`, etc, are unreachable.
|
||||||
|
builtIns.builtInsModule.findClassAcrossModuleDependencies(it.classId)!!.defaultType
|
||||||
|
}
|
||||||
|
|
||||||
|
fun build() {
|
||||||
val top = scopes.pop()
|
val top = scopes.pop()
|
||||||
assert(scopes.isEmpty() && top.kind == ScopeKind.TOP)
|
assert(scopes.isEmpty() && top.kind == ScopeKind.TOP)
|
||||||
|
|
||||||
// Now, let's generate C world adapters for all functions.
|
// Now, let's generate C world adapters for all functions.
|
||||||
top.generateCAdapters()
|
top.generateCAdapters(::buildCAdapter)
|
||||||
|
|
||||||
// Then generate data structure, describing generated adapters.
|
// Then generate data structure, describing generated adapters.
|
||||||
makeGlobalStruct(top)
|
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)
|
||||||
@@ -1070,107 +1162,5 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
|||||||
outputStreamWriter.close()
|
outputStreamWriter.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val simpleNameMapping = mapOf(
|
|
||||||
"<this>" to "thiz",
|
|
||||||
"<set-?>" to "set"
|
|
||||||
)
|
|
||||||
|
|
||||||
private val primitiveTypeMapping = KonanPrimitiveType.values().associate {
|
|
||||||
it to when (it) {
|
|
||||||
KonanPrimitiveType.BOOLEAN -> "${prefix}_KBoolean"
|
|
||||||
KonanPrimitiveType.CHAR -> "${prefix}_KChar"
|
|
||||||
KonanPrimitiveType.BYTE -> "${prefix}_KByte"
|
|
||||||
KonanPrimitiveType.SHORT -> "${prefix}_KShort"
|
|
||||||
KonanPrimitiveType.INT -> "${prefix}_KInt"
|
|
||||||
KonanPrimitiveType.LONG -> "${prefix}_KLong"
|
|
||||||
KonanPrimitiveType.FLOAT -> "${prefix}_KFloat"
|
|
||||||
KonanPrimitiveType.DOUBLE -> "${prefix}_KDouble"
|
|
||||||
KonanPrimitiveType.NON_NULL_NATIVE_PTR -> "void*"
|
|
||||||
KonanPrimitiveType.VECTOR128 -> "${prefix}_KVector128"
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private val unsignedTypeMapping = UnsignedType.values().associate {
|
|
||||||
it.classId to when (it) {
|
|
||||||
UnsignedType.UBYTE -> "${prefix}_KUByte"
|
|
||||||
UnsignedType.USHORT -> "${prefix}_KUShort"
|
|
||||||
UnsignedType.UINT -> "${prefix}_KUInt"
|
|
||||||
UnsignedType.ULONG -> "${prefix}_KULong"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun isMappedToString(type: KotlinType): Boolean =
|
|
||||||
isMappedToString(type.computeBinaryType())
|
|
||||||
|
|
||||||
private fun isMappedToString(binaryType: BinaryType<ClassDescriptor>): Boolean =
|
|
||||||
when (binaryType) {
|
|
||||||
is BinaryType.Primitive -> false
|
|
||||||
is BinaryType.Reference -> binaryType.types.first() == context.builtIns.string
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun isMappedToReference(type: KotlinType) =
|
|
||||||
!isMappedToVoid(type) && !isMappedToString(type) &&
|
|
||||||
type.binaryTypeIsReference()
|
|
||||||
|
|
||||||
internal fun isMappedToVoid(type: KotlinType): Boolean {
|
|
||||||
return type.isUnit() || type.isNothing()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun translateName(name: Name): String {
|
|
||||||
val nameString = name.asString()
|
|
||||||
return when {
|
|
||||||
simpleNameMapping.contains(nameString) -> simpleNameMapping[nameString]!!
|
|
||||||
cKeywords.contains(nameString) -> "${nameString}_"
|
|
||||||
name.isSpecial -> nameString.replace("[<> ]".toRegex(), "_")
|
|
||||||
else -> nameString
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun translateTypeFull(type: KotlinType): Pair<String, String> =
|
|
||||||
if (isMappedToVoid(type)) {
|
|
||||||
"void" to "void"
|
|
||||||
} else {
|
|
||||||
translateNonVoidTypeFull(type)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun translateNonVoidTypeFull(type: KotlinType): Pair<String, String> = type.unwrapToPrimitiveOrReference(
|
|
||||||
eachInlinedClass = { inlinedClass, _ ->
|
|
||||||
unsignedTypeMapping[inlinedClass.classId]?.let {
|
|
||||||
return it to it
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ifPrimitive = { primitiveType, _ ->
|
|
||||||
primitiveTypeMapping[primitiveType]!!.let { it to it }
|
|
||||||
},
|
|
||||||
ifReference = {
|
|
||||||
val clazz = (it.computeBinaryType() as BinaryType.Reference).types.first()
|
|
||||||
if (clazz == context.builtIns.string) {
|
|
||||||
"const char*" to "KObjHeader*"
|
|
||||||
} else {
|
|
||||||
"${prefix}_kref_${translateTypeFqName(clazz.fqNameSafe.asString())}" to "KObjHeader*"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
fun translateType(element: SignatureElement): String =
|
|
||||||
translateTypeFull(element.type).first
|
|
||||||
|
|
||||||
fun translateType(type: KotlinType): String
|
|
||||||
= translateTypeFull(type).first
|
|
||||||
|
|
||||||
fun translateTypeBridge(type: KotlinType): String = translateTypeFull(type).second
|
|
||||||
|
|
||||||
fun translateTypeFqName(name: String): String {
|
|
||||||
return name.replace('.', '_')
|
|
||||||
}
|
|
||||||
|
|
||||||
private var functionIndex = 0
|
|
||||||
fun nextFunctionIndex() = functionIndex++
|
|
||||||
|
|
||||||
internal val kGetTypeFuncType get() =
|
|
||||||
LLVMFunctionType(codegen.kTypeInfoPtr, null, 0, 0)!!
|
|
||||||
// Abstraction leak for slot :(.
|
|
||||||
internal val kGetObjectFuncType get() =
|
|
||||||
LLVMFunctionType(codegen.kObjHeaderPtr, cValuesOf(codegen.kObjHeaderPtrPtr), 1, 0)!!
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user