From bd5b4b2f524a73df5ef1081793433ce2c3a8e522 Mon Sep 17 00:00:00 2001 From: Alexander Gorshenev Date: Wed, 30 Nov 2016 04:07:00 +0300 Subject: [PATCH] Annotation used --- .../backend/konan/llvm/CodeGenerator.kt | 4 +++ .../kotlin/backend/konan/llvm/Context.kt | 2 ++ .../kotlin/backend/konan/llvm/IrToBitcode.kt | 19 ++++++++++++ .../backend/konan/llvm/UsedAnnotation.kt | 12 ++++++++ backend.native/tests/main.c | 29 ++++++------------- runtime/src/main/kotlin/kotlin/Annotations.kt | 8 ++++- 6 files changed, 53 insertions(+), 21 deletions(-) create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/UsedAnnotation.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt index 9b2b1cbfce4..c0fe94efe24 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt @@ -43,6 +43,10 @@ internal class CodeGenerator(override val context: Context) : ContextUtils { currentFunction!!.registerVariable(name, v) } + + if (descriptor.usedAnnotation) { + context.usedFunctions.add(fn!!) + } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Context.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Context.kt index cd0f3678434..24bb6b29f54 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Context.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Context.kt @@ -29,4 +29,6 @@ internal class Context(val irModule: IrModuleFragment, val runtime: Runtime, val val isInstanceFunction = importRtFunction("IsInstance") val checkInstanceFunction = importRtFunction("CheckInstance") val throwExceptionFunction = importRtFunction("ThrowException") + + val usedFunctions = mutableListOf() } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 12c82392709..cae0d77d5e0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -165,6 +165,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid override fun visitModuleFragment(module: IrModuleFragment) { logger.log("visitModule : ${ir2string(module)}") module.acceptChildrenVoid(this) + + appendLlvmUsed(context.usedFunctions) + metadator.endModule(module) } @@ -1436,4 +1439,20 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid }) return skipBody } + + //-------------------------------------------------------------------------// + + fun appendLlvmUsed(args: List) { + if (args.isEmpty()) return + + memScoped { + val arrayLength = args.size + val argsCasted = args.map{it -> constPointer(LLVMConstBitCast(it, int8TypePtr)) } + val llvmUsedGlobal = + context.staticData.placeGlobalArray("llvm.used", int8TypePtr, argsCasted) + + LLVMSetLinkage(llvmUsedGlobal.llvmGlobal, LLVMLinkage.LLVMAppendingLinkage); + LLVMSetSection(llvmUsedGlobal.llvmGlobal, "llvm.metadata"); + } + } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/UsedAnnotation.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/UsedAnnotation.kt new file mode 100644 index 00000000000..de15a909460 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/UsedAnnotation.kt @@ -0,0 +1,12 @@ +package org.jetbrains.kotlin.backend.konan.llvm + +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.annotations.* +import org.jetbrains.kotlin.name.FqName + +private val annotationName = FqName("kotlin.Used") + +internal val FunctionDescriptor.usedAnnotation: Boolean + get() { + return (this.annotations.findAnnotation(annotationName) != null) + } diff --git a/backend.native/tests/main.c b/backend.native/tests/main.c index 2c0c0d4f125..f12ebf38b83 100644 --- a/backend.native/tests/main.c +++ b/backend.native/tests/main.c @@ -12,10 +12,16 @@ extern int run_test(); void * resolve_symbol(char *name) { - /* here we can add here some magic to resolve symbols in kotlin native*/ - return dlsym(RTLD_DEFAULT, name); + /* here we can add here some magic to resolve symbols in kotlin native*/ + void* symbol = dlsym(RTLD_DEFAULT, name); + + if (!symbol) { + printf("Could not find kotlin symbol '%s': %s\n", name, dlerror()); + exit(1); + } + + return symbol; } - int kotlinNativeMain() { @@ -28,20 +34,3 @@ kotlinNativeMain() { #endif } -int ktype_kotlin_any asm("_ktype:kotlin.Any"); - -#define DEFINE(name, symbol) int name() asm(#symbol); -#define DECLARE(name) \ -int \ -name() { \ - abort(); \ - return 1; \ -} - -#define DEFINE_AND_DECLARE(name, sym) \ - DEFINE(name, sym) \ - DECLARE(name) - -DEFINE_AND_DECLARE(kfun_kotlin_any_to_string,_kfun:kotlin.Any.toString) -DEFINE_AND_DECLARE(kfun_kotlin_any_hash_code,_kfun:kotlin.Any.hashCode) -DEFINE_AND_DECLARE(kfun_kotlin_any_equals,_kfun:kotlin.Any.equals) diff --git a/runtime/src/main/kotlin/kotlin/Annotations.kt b/runtime/src/main/kotlin/kotlin/Annotations.kt index 550c9b64a61..82051fca6aa 100644 --- a/runtime/src/main/kotlin/kotlin/Annotations.kt +++ b/runtime/src/main/kotlin/kotlin/Annotations.kt @@ -34,4 +34,10 @@ public annotation class Suppress(vararg val names: String) @Target(AnnotationTarget.TYPE) //@Retention(SOURCE) //@MustBeDocumented -public annotation class UnsafeVariance \ No newline at end of file +public annotation class UnsafeVariance + +/** + * Preserve the function entry point during global optimizations + */ +public annotation class Used +