Avoid hanging external functions. (#2265)

This commit is contained in:
Nikolay Igotti
2018-10-30 18:47:38 +03:00
committed by GitHub
parent d02a51ba98
commit 0a43fa21d3
5 changed files with 29 additions and 22 deletions
@@ -460,13 +460,4 @@ typealias CArrayPointerVar<T> = CPointerVar<T>
/**
* The C function.
*/
class CFunction<T : Function<*>>(rawPtr: NativePtr) : CPointed(rawPtr)
/**
* Returns a pointer to C function which calls given Kotlin *static* function.
*
* @param function must be *static*, i.e. an (unbound) reference to a Kotlin function or
* a closure which doesn't capture any variable
*/
@Deprecated("The function type is too general. Supply argument with known arity.", level = DeprecationLevel.ERROR)
external fun <F : Function<*>> staticCFunction(function: F): CPointer<CFunction<F>>
class CFunction<T : Function<*>>(rawPtr: NativePtr) : CPointed(rawPtr)
@@ -602,7 +602,7 @@ class StubGenerator(
} else {
sequenceOf(
annotationForUnableToImport,
"external $header"
"$header = throw UnsupportedOperationException()"
)
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.backend.konan.llvm
import llvm.LLVMTypeRef
import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
import org.jetbrains.kotlin.backend.konan.isInlined
@@ -104,6 +105,9 @@ internal tailrec fun DeclarationDescriptor.isExported(): Boolean {
private val symbolNameAnnotation = FqName("kotlin.native.SymbolName")
private val intrinsicAnnotation = FqName("kotlin.native.internal.Intrinsic")
private val objCMethodAnnotation = FqName("kotlinx.cinterop.ObjCMethod")
private val cnameAnnotation = FqName("kotlin.native.CName")
private val exportForCppRuntimeAnnotation = FqName("kotlin.native.internal.ExportForCppRuntime")
@@ -205,13 +209,17 @@ internal val FunctionDescriptor.symbolName: String
if (!this.isExported()) {
throw AssertionError(this.descriptor.toString())
}
this.descriptor.annotations.findAnnotation(symbolNameAnnotation)?.let {
if (this.isExternal) {
if (isExternal) {
this.descriptor.annotations.findAnnotation(symbolNameAnnotation)?.let {
return getStringValue(it)!!
} else {
// ignore; TODO: report compile error
}
if (!this.descriptor.annotations.hasAnnotation(intrinsicAnnotation) &&
!this.descriptor.annotations.hasAnnotation(objCMethodAnnotation)) {
throw Error("external function ${this.descriptor} must have @SymbolName, @Intrinsic or @ObjCMethod annotation")
}
}
this.descriptor.annotations.findAnnotation(exportForCppRuntimeAnnotation)?.let {
val name = getStringValue(it) ?: this.name.asString()
return name // no wrapping currently required
@@ -24,7 +24,9 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
internal fun DeclarationDescriptor.symbolName(): String = when (this) {
// TODO: merge with FunctionDescriptor.symbolName in BinaryInterface.kt.
internal val DeclarationDescriptor.symbolName: String get() = when (this) {
is FunctionDescriptor
-> this.uniqueName
is PropertyDescriptor
@@ -35,7 +37,7 @@ internal fun DeclarationDescriptor.symbolName(): String = when (this) {
}
internal val DeclarationDescriptor.uniqId
get() = this.symbolName().localHash.value
get() = this.symbolName.localHash.value
internal val DeclarationDescriptor.isSerializableExpectClass: Boolean
get() = this is ClassDescriptor && ExpectedActualDeclarationChecker.shouldGenerateExpectClass(this)
@@ -154,6 +156,8 @@ internal tailrec fun DeclarationDescriptor.isExported(): Boolean {
private val symbolNameAnnotation = FqName("kotlin.native.SymbolName")
private val intrinsicAnnotation = FqName("kotlin.native.internal.Intrinsic")
private val exportForCppRuntimeAnnotation = FqName("kotlin.native.internal.ExportForCppRuntime")
private val cnameAnnotation = FqName("kotlin.native.internal.CName")
@@ -244,13 +248,16 @@ private val FunctionDescriptor.uniqueName: String
throw AssertionError(this.toString())
}
this.annotations.findAnnotation(symbolNameAnnotation)?.let {
if (this.isExternal) {
if (this.isExternal) {
this.annotations.findAnnotation(symbolNameAnnotation)?.let {
return getStringValue(it)!!
} else {
// ignore; TODO: report compile error
}
if (!annotations.hasAnnotation(intrinsicAnnotation)) {
throw Error("external function $this must have @SymbolName annotation")
}
}
// TODO: check that only external function has @SymbolName.
this.annotations.findAnnotation(exportForCppRuntimeAnnotation)?.let {
val name = getStringValue(it) ?: this.name.asString()
+2 -1
View File
@@ -2,13 +2,14 @@
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import kotlin.native.internal.ExportForCppRuntime
// This function is produced by the code generator given
// the '-entry foo.bar.main' flag.
// It calls the requested entry point.
// The default is main(Array<String>):Unit in the root package.
@ExportForCppRuntime
@SymbolName("EntryPointSelector")
external fun EntryPointSelector(args: Array<String>)
@ExportForCppRuntime