Fix few problems in generation of C bindings. (#1453)

This commit is contained in:
Nikolay Igotti
2018-03-30 13:53:03 +03:00
committed by GitHub
parent 54bede3db3
commit 5c931033da
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
import org.jetbrains.kotlin.resolve.descriptorUtil.module 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.isUnit
private enum class ScopeKind { private enum class ScopeKind {
TOP, TOP,
@@ -87,7 +88,27 @@ private val cKeywords = setOf(
"_Alignas", "_Alignof", "_Atomic", "_Generic", "_Noreturn", "_Static_assert", "_Thread_local", "_Alignas", "_Alignof", "_Atomic", "_Generic", "_Noreturn", "_Static_assert", "_Thread_local",
// Not exactly keywords, but reserved or standard-defined. // Not exactly keywords, but reserved or standard-defined.
"and", "not", "or", "xor", "and", "not", "or", "xor",
"bool", "complex", "imaginary" "bool", "complex", "imaginary",
// C++ keywords not listed above.
"alignas", "alignof", "and_eq", "asm",
"bitand", "bitor", "bool",
"catch", "char16_t", "char32_t", "class", "compl", "constexpr", "const_cast",
"decltype", "delete", "dynamic_cast",
"explicit", "export",
"false", "friend",
"inline",
"mutable",
"namespace", "new", "noexcept", "not_eq", "nullptr",
"operator", "or_eq",
"private", "protected", "public",
"reinterpret_cast",
"static_assert",
"template", "this", "thread_local", "throw", "true", "try", "typeid", "typename",
"using",
"virtual",
"wchar_t",
"xor_eq"
) )
private val cnameAnnotation = FqName("konan.internal.CName") private val cnameAnnotation = FqName("konan.internal.CName")
@@ -253,6 +274,9 @@ private class ExportedElement(val kind: ElementKind,
val isClass = declaration is ClassDescriptor && declaration.kind != ClassKind.ENUM_ENTRY val isClass = declaration is ClassDescriptor && declaration.kind != ClassKind.ENUM_ENTRY
val isEnumEntry = declaration is ClassDescriptor && declaration.kind == ClassKind.ENUM_ENTRY val isEnumEntry = declaration is ClassDescriptor && declaration.kind == ClassKind.ENUM_ENTRY
fun KotlinType.includeToSignature() = !this.isUnit()
fun makeCFunctionSignature(shortName: Boolean): List<Pair<String, ClassDescriptor>> { fun makeCFunctionSignature(shortName: Boolean): List<Pair<String, ClassDescriptor>> {
if (!isFunction) { if (!isFunction) {
throw Error("only for functions") throw Error("only for functions")
@@ -267,9 +291,11 @@ private class ExportedElement(val kind: ElementKind,
else -> uniqueName(original, shortName) to TypeUtils.getClassDescriptor(original.returnType!!)!! else -> uniqueName(original, shortName) to TypeUtils.getClassDescriptor(original.returnType!!)!!
} }
val uniqueNames = owner.paramsToUniqueNames(original.explicitParameters) val uniqueNames = owner.paramsToUniqueNames(original.explicitParameters)
val params = ArrayList(original.explicitParameters.mapIndexed { idx, it -> val params = ArrayList(original.explicitParameters
uniqueNames[idx] to TypeUtils.getClassDescriptor(it.type)!! .filter { it.type.includeToSignature() }
}) .map { it ->
uniqueNames[it]!! to TypeUtils.getClassDescriptor(it.type)!!
})
return listOf(returned) + params return listOf(returned) + params
} }
@@ -285,9 +311,11 @@ private class ExportedElement(val kind: ElementKind,
else -> original.returnType!! else -> original.returnType!!
} }
val returnedClass = TypeUtils.getClassDescriptor(returnedType)!! val returnedClass = TypeUtils.getClassDescriptor(returnedType)!!
val params = ArrayList(original.allParameters.map { val params = ArrayList(original.allParameters
owner.translateTypeBridge(TypeUtils.getClassDescriptor(it.type)!!) .filter { it.type.includeToSignature() }
}) .map {
owner.translateTypeBridge(TypeUtils.getClassDescriptor(it.type)!!)
})
if (owner.isMappedToReference(returnedClass) || owner.isMappedToString(returnedClass)) { if (owner.isMappedToReference(returnedClass) || owner.isMappedToString(returnedClass)) {
params += "KObjHeader**" params += "KObjHeader**"
} }
@@ -359,7 +387,9 @@ private class ExportedElement(val kind: ElementKind,
"((${owner.translateType(clazz)}){ .pinned = CreateStablePointer(${name})})" "((${owner.translateType(clazz)}){ .pinned = CreateStablePointer(${name})})"
} }
else -> { else -> {
assert(clazz.isValueType) assert(clazz.isValueType) {
println(clazz.toString())
}
name name
} }
} }
@@ -434,6 +464,9 @@ private class ExportedElement(val kind: ElementKind,
val original = descriptor.original val original = descriptor.original
addUsedType(original.correspondingProperty.type, set) addUsedType(original.correspondingProperty.type, set)
} }
is ClassDescriptor -> {
set += descriptor
}
} }
} }
} }
@@ -463,16 +496,16 @@ internal class CAdapterGenerator(
private lateinit var outputStreamWriter: PrintWriter private lateinit var outputStreamWriter: PrintWriter
private val paramNamesRecorded = mutableMapOf<String, Int>() private val paramNamesRecorded = mutableMapOf<String, Int>()
internal fun paramsToUniqueNames(params: List<ParameterDescriptor>): List<String> { internal fun paramsToUniqueNames(params: List<ParameterDescriptor>): Map<ParameterDescriptor, String> {
paramNamesRecorded.clear() paramNamesRecorded.clear()
return params.map { return params.associate {
val name = translateName(it.name.asString()) val name = translateName(it.name.asString())
val count = paramNamesRecorded.getOrDefault(name, 0) val count = paramNamesRecorded.getOrDefault(name, 0)
paramNamesRecorded[name] = count + 1 paramNamesRecorded[name] = count + 1
if (count == 0) { if (count == 0) {
name it to name
} else { } else {
"$name${count.toString()}" it to "$name${count.toString()}"
} }
} }
} }
@@ -671,7 +704,7 @@ internal class CAdapterGenerator(
element.isClass -> element.isClass ->
output("/* Type for ${element.name} = */ ${element.cname}, ", indent) output("/* Type for ${element.name} = */ ${element.cname}, ", indent)
element.isEnumEntry -> element.isEnumEntry ->
output("/* enum entry getter ${element.name} = */ ${element.cname}_impl", indent) output("/* enum entry getter ${element.name} = */ ${element.cname}_impl,", indent)
// TODO: handle properties. // TODO: handle properties.
} }
} }