Calling Kotlin from C++ runtime (#107)

* backend: support exporting Kotlin functions for C++ runtime

* runtime: implement several functions in Kotlin

* Throw{NullPointer,ArrayIndexOutOfBounds,ClassCast}Exception

* runtime: add literal declared in Kotlin as empty string

Also
* add corresponding test
* use empty string literal in strdedup2
  (however keep it disabled)

* fixup! runtime: add literal declared in Kotlin as empty string

* Review feedback: add more TheEmptyString() usages

Also improve string index checks in runtime
This commit is contained in:
SvyatoslavScherbina
2016-12-01 20:10:03 +07:00
committed by Nikolay Igotti
parent f9167ea91e
commit e38ac775ad
10 changed files with 90 additions and 48 deletions
@@ -4,16 +4,20 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind.*
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.findOriginalTopMostOverriddenDescriptors
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
private val symbolNameAnnotation = FqName("konan.SymbolName")
private val exportForCppRuntimeAnnotation = FqName("konan.internal.ExportForCppRuntime")
fun typeToHashString(type: KotlinType): String {
if (TypeUtils.isTypeParameter(type)) return "GENERIC"
@@ -52,18 +56,32 @@ internal val FunctionDescriptor.symbolName: String
get() {
this.annotations.findAnnotation(symbolNameAnnotation)?.let {
if (this.isExternal) {
val nameValue = it.allValueArguments.values.single() as StringValue
return nameValue.value
return getStringValue(it)!!
} else {
// ignore; TODO: report compile error
}
}
this.annotations.findAnnotation(exportForCppRuntimeAnnotation)?.let {
val name = getStringValue(it) ?: this.name.asString()
return name // no wrapping currently required
}
val containingDeclarationPart = containingDeclaration.fqNameSafe.let {
if (it.isRoot) "" else "$it."
}
return "kfun:$containingDeclarationPart$functionName"
}
private fun getStringValue(annotation: AnnotationDescriptor): String? {
annotation.allValueArguments.values.ifNotEmpty {
val stringValue = this.single() as StringValue
return stringValue.value
}
return null
}
internal val ClassDescriptor.symbolName: String
get() = when (this.kind) {
CLASS -> "kclass:"
+8 -1
View File
@@ -323,6 +323,11 @@ task tostring2(type: RunKonanTest) {
source = "runtime/basic/tostring2.kt"
}
task empty_substring(type: RunKonanTest) {
goldValue = "\n"
source = "runtime/basic/empty_substring.kt"
}
task array0(type: RunKonanTest) {
goldValue = "5\n6\n7\n8\n9\n10\n11\n12\n13\n"
source = "runtime/basic/array0.kt"
@@ -395,7 +400,9 @@ task strdedup1(type: RunKonanTest) {
}
/*
TODO: enable after supporting Unit object
TODO: string deduplication across several components seems to require
linking them as bitcode modules before translating to machine code.
task strdedup2(type: RunKonanTest) {
goldValue = "true\ntrue\n"
source = "datagen/literals/strdedup2.kt"
@@ -1,6 +1,6 @@
fun main(args : Array<String>) {
val str1 = "kotlin.Unit"
val str2 = Unit.toString()
val str1 = ""
val str2 = "hello".subSequence(2, 2)
println(str1 == str2)
println(str1 === str2)
}
@@ -0,0 +1,4 @@
fun main(args : Array<String>) {
val hello = "Hello world"
println(hello.subSequence(1, 1).toString())
}