From 4431f8cbd9fdd7793b3093f6ea2059f2b18c00cd Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Mon, 23 Oct 2017 17:49:18 +0300 Subject: [PATCH] Implement recording all modules used during bitcode generation --- .../kotlin/backend/konan/llvm/ContextUtils.kt | 56 ++++++++++++++++--- .../kotlin/backend/konan/llvm/Imports.kt | 41 ++++++++++++++ .../kotlin/backend/konan/llvm/IrToBitcode.kt | 27 +++++++-- .../llvm/KotlinObjCClassInfoGenerator.kt | 16 +++++- .../backend/konan/llvm/LlvmDeclarations.kt | 5 +- .../kotlin/backend/konan/llvm/LlvmUtils.kt | 6 +- .../backend/konan/llvm/StaticObjects.kt | 6 +- 7 files changed, 138 insertions(+), 19 deletions(-) create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Imports.kt 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 b7d68f74a2c..db8b8f80c63 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 @@ -19,8 +19,12 @@ package org.jetbrains.kotlin.backend.konan.llvm import kotlinx.cinterop.* import llvm.* import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.descriptors.CurrentKonanModule +import org.jetbrains.kotlin.backend.konan.descriptors.DeserializedKonanModule +import org.jetbrains.kotlin.backend.konan.descriptors.LlvmSymbolOrigin import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.backend.konan.hash.GlobalHash +import org.jetbrains.kotlin.backend.konan.library.impl.LibraryReaderImpl import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor @@ -167,7 +171,8 @@ internal interface ContextUtils : RuntimeAware { } return if (isExternal(this)) { - context.llvm.externalFunction(this.symbolName, getLlvmFunctionType(this)) + context.llvm.externalFunction(this.symbolName, getLlvmFunctionType(this), + origin = this.llvmSymbolOrigin) } else { context.llvmDeclarations.forFunction(this).llvmFunction } @@ -185,7 +190,8 @@ internal interface ContextUtils : RuntimeAware { val ClassDescriptor.typeInfoPtr: ConstPointer get() { return if (isExternal(this)) { - constPointer(importGlobal(this.typeInfoSymbolName, runtime.typeInfoType)) + constPointer(importGlobal(this.typeInfoSymbolName, runtime.typeInfoType, + origin = this.llvmSymbolOrigin)) } else { context.llvmDeclarations.forClass(this).typeInfo } @@ -280,7 +286,9 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { return LLVMAddFunction(llvmModule, "llvm.memset.p0i8.i32", functionType)!! } - internal fun externalFunction(name: String, type: LLVMTypeRef): LLVMValueRef { + internal fun externalFunction(name: String, type: LLVMTypeRef, origin: LlvmSymbolOrigin): LLVMValueRef { + this.imports.add(origin) + val found = LLVMGetNamedFunction(llvmModule, name) if (found != null) { assert (getFunctionType(found) == type) @@ -291,12 +299,32 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { } } - private fun externalNounwindFunction(name: String, type: LLVMTypeRef): LLVMValueRef { - val function = externalFunction(name, type) + private fun externalNounwindFunction(name: String, type: LLVMTypeRef, origin: LlvmSymbolOrigin): LLVMValueRef { + val function = externalFunction(name, type, origin) LLVMAddFunctionAttr(function, LLVMNoUnwindAttribute) return function } + private val usedLibraries = mutableSetOf() + + val imports = object : LlvmImports { + + private val allLibraries = context.librariesWithDependencies.toSet() + + override fun add(origin: LlvmSymbolOrigin) { + val reader = when (origin) { + CurrentKonanModule -> return + is DeserializedKonanModule -> origin.reader + } + + if (reader !in allLibraries) { + error("$reader (${reader.libraryName}) is used but not requested") + } + + usedLibraries.add(reader as LibraryReaderImpl) + } + } + val staticData = StaticData(context) val runtimeFile = context.config.distribution.runtime @@ -335,9 +363,21 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { else -> "__gxx_personality_v0" } - val gxxPersonalityFunction = externalNounwindFunction(personalityFunctionName, functionType(int32Type, true)) - val cxaBeginCatchFunction = externalNounwindFunction("__cxa_begin_catch", functionType(int8TypePtr, false, int8TypePtr)) - val cxaEndCatchFunction = externalNounwindFunction("__cxa_end_catch", functionType(voidType, false)) + val gxxPersonalityFunction = externalNounwindFunction( + personalityFunctionName, + functionType(int32Type, true), + origin = context.standardLlvmSymbolsOrigin + ) + val cxaBeginCatchFunction = externalNounwindFunction( + "__cxa_begin_catch", + functionType(int8TypePtr, false, int8TypePtr), + origin = context.standardLlvmSymbolsOrigin + ) + val cxaEndCatchFunction = externalNounwindFunction( + "__cxa_end_catch", + functionType(voidType, false), + origin = context.standardLlvmSymbolsOrigin + ) val memsetFunction = importMemset() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Imports.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Imports.kt new file mode 100644 index 00000000000..0a7a77ebb4c --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Imports.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.descriptors.LlvmSymbolOrigin +import org.jetbrains.kotlin.backend.konan.descriptors.SyntheticModules +import org.jetbrains.kotlin.backend.konan.descriptors.origin +import org.jetbrains.kotlin.backend.konan.descriptors.stdlibModule +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.resolve.descriptorUtil.module + +internal interface LlvmImports { + fun add(origin: LlvmSymbolOrigin) +} + +internal val DeclarationDescriptor.llvmSymbolOrigin: LlvmSymbolOrigin + get() { + val module = this.module + val moduleOrigin = module.origin + when (moduleOrigin) { + is LlvmSymbolOrigin -> return moduleOrigin + SyntheticModules -> error("Declaration is synthetic and can't be an origin of LLVM symbol:\n${this}") + } + } + +internal val Context.standardLlvmSymbolsOrigin: LlvmSymbolOrigin get() = this.stdlibModule.llvmSymbolOrigin 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 1a2d9856a35..2eac2fbd499 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 @@ -1273,8 +1273,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map = diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt index f8060207c69..c8e3d2e1ae7 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt @@ -372,7 +372,10 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : return } - context.llvm.externalFunction(descriptor.symbolName, llvmFunctionType) + context.llvm.externalFunction(descriptor.symbolName, llvmFunctionType, + // Assume that `external fun` is defined in native libs attached to this module: + origin = descriptor.llvmSymbolOrigin + ) } else { val symbolName = if (descriptor.isExported()) { descriptor.symbolName diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt index 83f46aac599..429b4d24476 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.backend.konan.llvm import kotlinx.cinterop.* import llvm.* +import org.jetbrains.kotlin.backend.konan.descriptors.LlvmSymbolOrigin internal val LLVMValueRef.type: LLVMTypeRef get() = LLVMTypeOf(this)!! @@ -191,8 +192,11 @@ internal fun ContextUtils.addGlobal(name: String, type: LLVMTypeRef, isExported: return result } -internal fun ContextUtils.importGlobal(name: String, type: LLVMTypeRef, +internal fun ContextUtils.importGlobal(name: String, type: LLVMTypeRef, origin: LlvmSymbolOrigin, threadLocal: Boolean = false): LLVMValueRef { + + context.llvm.imports.add(origin) + val found = LLVMGetNamedGlobal(context.llvmModule, name) if (found != null) { assert (getGlobalType(found) == type) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt index 1fe8651941b..e95acf2e972 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt @@ -159,7 +159,11 @@ internal val ContextUtils.theUnitInstanceRef: ConstPointer get() { val unitDescriptor = context.builtIns.unit return if (isExternal(unitDescriptor)) { - constPointer(importGlobal(theUnitInstanceName, context.llvm.runtime.objHeaderType)) + constPointer(importGlobal( + theUnitInstanceName, + context.llvm.runtime.objHeaderType, + origin = unitDescriptor.llvmSymbolOrigin + )) } else { context.llvmDeclarations.getUnitInstanceRef() }