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 kotlinx.cinterop.*
|
||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
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.konan.target.KonanTarget
|
||||||
import org.jetbrains.kotlin.backend.konan.hash.GlobalHash
|
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.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
@@ -167,7 +171,8 @@ internal interface ContextUtils : RuntimeAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return if (isExternal(this)) {
|
return if (isExternal(this)) {
|
||||||
context.llvm.externalFunction(this.symbolName, getLlvmFunctionType(this))
|
context.llvm.externalFunction(this.symbolName, getLlvmFunctionType(this),
|
||||||
|
origin = this.llvmSymbolOrigin)
|
||||||
} else {
|
} else {
|
||||||
context.llvmDeclarations.forFunction(this).llvmFunction
|
context.llvmDeclarations.forFunction(this).llvmFunction
|
||||||
}
|
}
|
||||||
@@ -185,7 +190,8 @@ internal interface ContextUtils : RuntimeAware {
|
|||||||
val ClassDescriptor.typeInfoPtr: ConstPointer
|
val ClassDescriptor.typeInfoPtr: ConstPointer
|
||||||
get() {
|
get() {
|
||||||
return if (isExternal(this)) {
|
return if (isExternal(this)) {
|
||||||
constPointer(importGlobal(this.typeInfoSymbolName, runtime.typeInfoType))
|
constPointer(importGlobal(this.typeInfoSymbolName, runtime.typeInfoType,
|
||||||
|
origin = this.llvmSymbolOrigin))
|
||||||
} else {
|
} else {
|
||||||
context.llvmDeclarations.forClass(this).typeInfo
|
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)!!
|
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)
|
val found = LLVMGetNamedFunction(llvmModule, name)
|
||||||
if (found != null) {
|
if (found != null) {
|
||||||
assert (getFunctionType(found) == type)
|
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 {
|
private fun externalNounwindFunction(name: String, type: LLVMTypeRef, origin: LlvmSymbolOrigin): LLVMValueRef {
|
||||||
val function = externalFunction(name, type)
|
val function = externalFunction(name, type, origin)
|
||||||
LLVMAddFunctionAttr(function, LLVMNoUnwindAttribute)
|
LLVMAddFunctionAttr(function, LLVMNoUnwindAttribute)
|
||||||
return function
|
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 staticData = StaticData(context)
|
||||||
|
|
||||||
val runtimeFile = context.config.distribution.runtime
|
val runtimeFile = context.config.distribution.runtime
|
||||||
@@ -335,9 +363,21 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
|||||||
else -> "__gxx_personality_v0"
|
else -> "__gxx_personality_v0"
|
||||||
}
|
}
|
||||||
|
|
||||||
val gxxPersonalityFunction = externalNounwindFunction(personalityFunctionName, functionType(int32Type, true))
|
val gxxPersonalityFunction = externalNounwindFunction(
|
||||||
val cxaBeginCatchFunction = externalNounwindFunction("__cxa_begin_catch", functionType(int8TypePtr, false, int8TypePtr))
|
personalityFunctionName,
|
||||||
val cxaEndCatchFunction = externalNounwindFunction("__cxa_end_catch", functionType(voidType, false))
|
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()
|
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
|
context.llvmDeclarations.forSingleton(descriptor).instanceFieldRef
|
||||||
} else {
|
} else {
|
||||||
val llvmType = codegen.getLLVMType(descriptor.defaultType)
|
val llvmType = codegen.getLLVMType(descriptor.defaultType)
|
||||||
codegen.importGlobal(descriptor.objectInstanceFieldSymbolName, llvmType,
|
codegen.importGlobal(
|
||||||
threadLocal = true)
|
descriptor.objectInstanceFieldSymbolName,
|
||||||
|
llvmType,
|
||||||
|
origin = descriptor.llvmSymbolOrigin,
|
||||||
|
threadLocal = true
|
||||||
|
)
|
||||||
}
|
}
|
||||||
objects += llvmGlobal
|
objects += llvmGlobal
|
||||||
return llvmGlobal
|
return llvmGlobal
|
||||||
@@ -2114,8 +2118,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
assert(!classDescriptor.isInterface)
|
assert(!classDescriptor.isInterface)
|
||||||
|
|
||||||
return if (classDescriptor.isExternalObjCClass()) {
|
return if (classDescriptor.isExternalObjCClass()) {
|
||||||
|
context.llvm.imports.add(classDescriptor.llvmSymbolOrigin)
|
||||||
|
|
||||||
val lookUpFunction = context.llvm.externalFunction("Kotlin_Interop_getObjCClass",
|
val lookUpFunction = context.llvm.externalFunction("Kotlin_Interop_getObjCClass",
|
||||||
functionType(int8TypePtr, false, int8TypePtr))
|
functionType(int8TypePtr, false, int8TypePtr),
|
||||||
|
origin = context.standardLlvmSymbolsOrigin
|
||||||
|
)
|
||||||
|
|
||||||
call(lookUpFunction,
|
call(lookUpFunction,
|
||||||
listOf(codegen.staticData.cStringLiteral(classDescriptor.name.asString()).llvm))
|
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 functionType = functionType(int8TypePtr, true, int8TypePtr, int8TypePtr)
|
||||||
|
|
||||||
val normalMessenger = context.llvm.externalFunction("objc_msgSend$messengerNameSuffix", functionType)
|
val libobjc = context.standardLlvmSymbolsOrigin
|
||||||
val superMessenger = context.llvm.externalFunction("objc_msgSendSuper$messengerNameSuffix", functionType)
|
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 superClass = args.single()
|
||||||
val messenger = LLVMBuildSelect(gen.builder,
|
val messenger = LLVMBuildSelect(gen.builder,
|
||||||
|
|||||||
+13
-3
@@ -43,8 +43,14 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
|
|||||||
val companionObjectDescriptor = descriptor.companionObjectDescriptor
|
val companionObjectDescriptor = descriptor.companionObjectDescriptor
|
||||||
val classMethods = companionObjectDescriptor?.generateOverridingMethodDescs() ?: emptyList()
|
val classMethods = companionObjectDescriptor?.generateOverridingMethodDescs() ?: emptyList()
|
||||||
|
|
||||||
val superclassName = descriptor.getSuperClassNotAny()!!.name.asString()
|
val superclassName = descriptor.getSuperClassNotAny()!!.let {
|
||||||
val protocolNames = descriptor.getSuperInterfaces().map { it.name.asString().removeSuffix("Protocol") }
|
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 =
|
val bodySize =
|
||||||
LLVMStoreSizeOfType(llvmTargetData, context.llvmDeclarations.forClass(descriptor).bodyType).toInt()
|
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(
|
private fun generateMethodDesc(info: ObjCMethodInfo) = ObjCMethodDesc(
|
||||||
info.selector,
|
info.selector,
|
||||||
info.encoding,
|
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> =
|
private fun ClassDescriptor.generateOverridingMethodDescs(): List<ObjCMethodDesc> =
|
||||||
|
|||||||
+4
-1
@@ -372,7 +372,10 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
return
|
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 {
|
} else {
|
||||||
val symbolName = if (descriptor.isExported()) {
|
val symbolName = if (descriptor.isExported()) {
|
||||||
descriptor.symbolName
|
descriptor.symbolName
|
||||||
|
|||||||
+5
-1
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
|||||||
|
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import llvm.*
|
import llvm.*
|
||||||
|
import org.jetbrains.kotlin.backend.konan.descriptors.LlvmSymbolOrigin
|
||||||
|
|
||||||
internal val LLVMValueRef.type: LLVMTypeRef
|
internal val LLVMValueRef.type: LLVMTypeRef
|
||||||
get() = LLVMTypeOf(this)!!
|
get() = LLVMTypeOf(this)!!
|
||||||
@@ -191,8 +192,11 @@ internal fun ContextUtils.addGlobal(name: String, type: LLVMTypeRef, isExported:
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun ContextUtils.importGlobal(name: String, type: LLVMTypeRef,
|
internal fun ContextUtils.importGlobal(name: String, type: LLVMTypeRef, origin: LlvmSymbolOrigin,
|
||||||
threadLocal: Boolean = false): LLVMValueRef {
|
threadLocal: Boolean = false): LLVMValueRef {
|
||||||
|
|
||||||
|
context.llvm.imports.add(origin)
|
||||||
|
|
||||||
val found = LLVMGetNamedGlobal(context.llvmModule, name)
|
val found = LLVMGetNamedGlobal(context.llvmModule, name)
|
||||||
if (found != null) {
|
if (found != null) {
|
||||||
assert (getGlobalType(found) == type)
|
assert (getGlobalType(found) == type)
|
||||||
|
|||||||
+5
-1
@@ -159,7 +159,11 @@ internal val ContextUtils.theUnitInstanceRef: ConstPointer
|
|||||||
get() {
|
get() {
|
||||||
val unitDescriptor = context.builtIns.unit
|
val unitDescriptor = context.builtIns.unit
|
||||||
return if (isExternal(unitDescriptor)) {
|
return if (isExternal(unitDescriptor)) {
|
||||||
constPointer(importGlobal(theUnitInstanceName, context.llvm.runtime.objHeaderType))
|
constPointer(importGlobal(
|
||||||
|
theUnitInstanceName,
|
||||||
|
context.llvm.runtime.objHeaderType,
|
||||||
|
origin = unitDescriptor.llvmSymbolOrigin
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
context.llvmDeclarations.getUnitInstanceRef()
|
context.llvmDeclarations.getUnitInstanceRef()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user