Implement recording all modules used during bitcode generation

This commit is contained in:
Svyatoslav Scherbina
2017-10-23 17:49:18 +03:00
committed by SvyatoslavScherbina
parent c4b8fa806f
commit 4431f8cbd9
7 changed files with 138 additions and 19 deletions
@@ -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<LibraryReaderImpl>()
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()
@@ -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
@@ -1273,8 +1273,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
context.llvmDeclarations.forSingleton(descriptor).instanceFieldRef
} else {
val llvmType = codegen.getLLVMType(descriptor.defaultType)
codegen.importGlobal(descriptor.objectInstanceFieldSymbolName, llvmType,
threadLocal = true)
codegen.importGlobal(
descriptor.objectInstanceFieldSymbolName,
llvmType,
origin = descriptor.llvmSymbolOrigin,
threadLocal = true
)
}
objects += llvmGlobal
return llvmGlobal
@@ -2114,8 +2118,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
assert(!classDescriptor.isInterface)
return if (classDescriptor.isExternalObjCClass()) {
context.llvm.imports.add(classDescriptor.llvmSymbolOrigin)
val lookUpFunction = context.llvm.externalFunction("Kotlin_Interop_getObjCClass",
functionType(int8TypePtr, false, int8TypePtr))
functionType(int8TypePtr, false, int8TypePtr),
origin = context.standardLlvmSymbolsOrigin
)
call(lookUpFunction,
listOf(codegen.staticData.cStringLiteral(classDescriptor.name.asString()).llvm))
@@ -2160,8 +2168,17 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
val functionType = functionType(int8TypePtr, true, int8TypePtr, int8TypePtr)
val normalMessenger = context.llvm.externalFunction("objc_msgSend$messengerNameSuffix", functionType)
val superMessenger = context.llvm.externalFunction("objc_msgSendSuper$messengerNameSuffix", functionType)
val libobjc = context.standardLlvmSymbolsOrigin
val normalMessenger = context.llvm.externalFunction(
"objc_msgSend$messengerNameSuffix",
functionType,
origin = libobjc
)
val superMessenger = context.llvm.externalFunction(
"objc_msgSendSuper$messengerNameSuffix",
functionType,
origin = libobjc
)
val superClass = args.single()
val messenger = LLVMBuildSelect(gen.builder,
@@ -43,8 +43,14 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
val companionObjectDescriptor = descriptor.companionObjectDescriptor
val classMethods = companionObjectDescriptor?.generateOverridingMethodDescs() ?: emptyList()
val superclassName = descriptor.getSuperClassNotAny()!!.name.asString()
val protocolNames = descriptor.getSuperInterfaces().map { it.name.asString().removeSuffix("Protocol") }
val superclassName = descriptor.getSuperClassNotAny()!!.let {
context.llvm.imports.add(it.llvmSymbolOrigin)
it.name.asString()
}
val protocolNames = descriptor.getSuperInterfaces().map {
context.llvm.imports.add(it.llvmSymbolOrigin)
it.name.asString().removeSuffix("Protocol")
}
val bodySize =
LLVMStoreSizeOfType(llvmTargetData, context.llvmDeclarations.forClass(descriptor).bodyType).toInt()
@@ -123,7 +129,11 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
private fun generateMethodDesc(info: ObjCMethodInfo) = ObjCMethodDesc(
info.selector,
info.encoding,
context.llvm.externalFunction(info.imp, functionType(voidType))
context.llvm.externalFunction(
info.imp,
functionType(voidType),
origin = info.bridge.llvmSymbolOrigin
)
)
private fun ClassDescriptor.generateOverridingMethodDescs(): List<ObjCMethodDesc> =
@@ -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
@@ -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)
@@ -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()
}