Implement recording all modules used during bitcode generation
This commit is contained in:
committed by
SvyatoslavScherbina
parent
c4b8fa806f
commit
4431f8cbd9
+48
-8
@@ -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()
|
||||
|
||||
|
||||
+41
@@ -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
|
||||
+22
-5
@@ -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,
|
||||
|
||||
+13
-3
@@ -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> =
|
||||
|
||||
+4
-1
@@ -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
|
||||
|
||||
+5
-1
@@ -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)
|
||||
|
||||
+5
-1
@@ -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()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user