From cb2da32521407049c52656c69f7c149ab5d426a4 Mon Sep 17 00:00:00 2001 From: SvyatoslavScherbina Date: Wed, 11 Sep 2019 10:17:30 +0300 Subject: [PATCH] Group static initializers by modules in codegen (#3325) --- .../kotlin/backend/konan/llvm/ContextUtils.kt | 4 +- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 68 +++++++++++++++---- 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt index 02fa09b8309..06cd7562112 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt @@ -524,7 +524,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { val usedFunctions = mutableListOf() val usedGlobals = mutableListOf() val compilerUsedGlobals = mutableListOf() - val staticInitializers = mutableListOf() + val staticInitializers = mutableListOf() val fileInitializers = mutableListOf() val objects = mutableSetOf() val sharedObjects = mutableSetOf() @@ -546,3 +546,5 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { val llvmFloat = LLVMFloatType()!! val llvmDouble = LLVMDoubleType()!! } + +class StaticInitializer(val file: IrFile, val initializer: LLVMValueRef) 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 16873ca01ba..fa37a8dacd6 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 @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.resolve.descriptorUtil.classId +import org.jetbrains.kotlin.resolve.descriptorUtil.module internal enum class FieldStorage { MAIN_THREAD, @@ -441,7 +442,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map() + } + + context.llvm.staticInitializers.forEach { + val library = it.file.packageFragmentDescriptor.module.konanLibrary + val initializers = libraryToInitializers[library] + ?: error("initializer for not included library ${library?.libraryFile}") + + initializers.add(it.initializer) + } + + val ctorFunctions = libraries.map { library -> + val ctorName = if (library != null) { + library.moduleConstructorName + } else { + context.config.moduleId.moduleConstructorName + } + + val ctorFunction = LLVMAddFunction(context.llvmModule, ctorName, kVoidFuncType)!! + LLVMSetLinkage(ctorFunction, LLVMLinkage.LLVMExternalLinkage) + + val initializers = libraryToInitializers.getValue(library) + appendStaticInitializers(ctorFunction, initializers) + + ctorFunction + } + + appendGlobalCtors(ctorFunctions) + } + + private fun appendStaticInitializers(ctorFunction: LLVMValueRef, initializers: List) { generateFunction(codegen, ctorFunction) { - val initGuard = LLVMAddGlobal(context.llvmModule, int32Type, "Konan_init_guard") + val initGuardName = ctorFunction.name.orEmpty() + "_guard" + val initGuard = LLVMAddGlobal(context.llvmModule, int32Type, initGuardName) LLVMSetInitializer(initGuard, kImmZero) LLVMSetLinkage(initGuard, LLVMLinkage.LLVMPrivateLinkage) val bbInited = basicBlock("inited", null) @@ -2296,30 +2330,36 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map) { if (context.config.produce.isNativeBinary) { + // Generate function calling all [ctorFunctions]. + val globalCtorFunction = LLVMAddFunction(context.llvmModule, "_Konan_constructors", kVoidFuncType)!! + LLVMSetLinkage(globalCtorFunction, LLVMLinkage.LLVMPrivateLinkage) + generateFunction(codegen, globalCtorFunction) { + ctorFunctions.forEach { + call(it, emptyList(), Lifetime.IRRELEVANT, + exceptionHandler = ExceptionHandler.Caller, verbatim = true) + } + ret(null) + } + // Append initializers of global variables in "llvm.global_ctors" array. val globalCtors = context.llvm.staticData.placeGlobalArray("llvm.global_ctors", kCtorType, - listOf(createGlobalCtor(ctorFunction))) + listOf(createGlobalCtor(globalCtorFunction))) LLVMSetLinkage(globalCtors.llvmGlobal, LLVMLinkage.LLVMAppendingLinkage) if (context.config.produce == CompilerOutputKind.PROGRAM) { // Provide an optional handle for calling .ctors, if standard constructors mechanism // is not available on the platform (i.e. WASM, embedded). - val globalCtorFunction = LLVMAddFunction(context.llvmModule, "_Konan_constructors", kVoidFuncType)!! LLVMSetLinkage(globalCtorFunction, LLVMLinkage.LLVMExternalLinkage) - generateFunction(codegen, globalCtorFunction) { - // Unfortunately, LLVMAddAlias() doesn't seem to work on WASM yet. - call(ctorFunction, emptyList(), Lifetime.IRRELEVANT, - exceptionHandler = ExceptionHandler.Caller, verbatim = true) - ret(null) - } appendLlvmUsed("llvm.used", listOf(globalCtorFunction)) } }