[K/N][codegen] Use generationState instead of context wherever possible
This commit is contained in:
+3
-2
@@ -12,8 +12,9 @@ typealias BitcodeFile = String
|
||||
typealias ObjectFile = String
|
||||
typealias ExecutableFile = String
|
||||
|
||||
internal class BitcodeCompiler(val context: Context) {
|
||||
internal class BitcodeCompiler(val generationState: NativeGenerationState) {
|
||||
|
||||
private val context = generationState.context
|
||||
private val platform = context.config.platform
|
||||
private val optimize = context.shouldOptimize()
|
||||
private val debug = context.config.debug
|
||||
@@ -31,7 +32,7 @@ internal class BitcodeCompiler(val context: Context) {
|
||||
.execute()
|
||||
|
||||
private fun temporary(name: String, suffix: String): String =
|
||||
context.generationState.tempFiles.create(name, suffix).absolutePath
|
||||
generationState.tempFiles.create(name, suffix).absolutePath
|
||||
|
||||
private fun targetTool(tool: String, vararg arg: String) {
|
||||
val absoluteToolName = if (platform.configurables is AppleConfigurables) {
|
||||
|
||||
+18
-16
@@ -167,26 +167,27 @@ internal val Context.getUnboxFunction: (IrClass) -> IrSimpleFunction by Context.
|
||||
* Initialize static boxing.
|
||||
* If output target is native binary then the cache is created.
|
||||
*/
|
||||
internal fun initializeCachedBoxes(context: Context) {
|
||||
internal fun initializeCachedBoxes(generationState: NativeGenerationState) {
|
||||
BoxCache.values().forEach { cache ->
|
||||
val cacheName = "${cache.name}_CACHE"
|
||||
val rangeStart = "${cache.name}_RANGE_FROM"
|
||||
val rangeEnd = "${cache.name}_RANGE_TO"
|
||||
initCache(cache, context, cacheName, rangeStart, rangeEnd,
|
||||
declareOnly = !context.generationState.shouldDefineCachedBoxes
|
||||
).also { context.generationState.llvm.boxCacheGlobals[cache] = it }
|
||||
initCache(cache, generationState, cacheName, rangeStart, rangeEnd,
|
||||
declareOnly = !generationState.shouldDefineCachedBoxes
|
||||
).also { generationState.llvm.boxCacheGlobals[cache] = it }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds global that refers to the cache.
|
||||
*/
|
||||
private fun initCache(cache: BoxCache, context: Context, cacheName: String,
|
||||
private fun initCache(cache: BoxCache, generationState: NativeGenerationState, cacheName: String,
|
||||
rangeStartName: String, rangeEndName: String, declareOnly: Boolean) : StaticData.Global {
|
||||
|
||||
val context = generationState.context
|
||||
val kotlinType = context.irBuiltIns.getKotlinClass(cache)
|
||||
val staticData = context.generationState.llvm.staticData
|
||||
val llvm = context.generationState.llvm
|
||||
val staticData = generationState.llvm.staticData
|
||||
val llvm = generationState.llvm
|
||||
val llvmType = kotlinType.defaultType.toLLVMType(llvm)
|
||||
val llvmBoxType = llvm.structType(llvm.runtime.objHeaderType, llvmType)
|
||||
val (start, end) = context.config.target.getBoxCacheRange(cache)
|
||||
@@ -207,14 +208,15 @@ private fun initCache(cache: BoxCache, context: Context, cacheName: String,
|
||||
}
|
||||
}
|
||||
|
||||
internal fun IrConstantPrimitive.toBoxCacheValue(context: Context): ConstValue? {
|
||||
internal fun IrConstantPrimitive.toBoxCacheValue(generationState: NativeGenerationState): ConstValue? {
|
||||
val irBuiltIns = generationState.context.irBuiltIns
|
||||
val cacheType = when (value.type) {
|
||||
context.irBuiltIns.booleanType -> BoxCache.BOOLEAN
|
||||
context.irBuiltIns.byteType -> BoxCache.BYTE
|
||||
context.irBuiltIns.shortType -> BoxCache.SHORT
|
||||
context.irBuiltIns.charType -> BoxCache.CHAR
|
||||
context.irBuiltIns.intType -> BoxCache.INT
|
||||
context.irBuiltIns.longType -> BoxCache.LONG
|
||||
irBuiltIns.booleanType -> BoxCache.BOOLEAN
|
||||
irBuiltIns.byteType -> BoxCache.BYTE
|
||||
irBuiltIns.shortType -> BoxCache.SHORT
|
||||
irBuiltIns.charType -> BoxCache.CHAR
|
||||
irBuiltIns.intType -> BoxCache.INT
|
||||
irBuiltIns.longType -> BoxCache.LONG
|
||||
else -> return null
|
||||
}
|
||||
val value = when (value.kind) {
|
||||
@@ -226,9 +228,9 @@ internal fun IrConstantPrimitive.toBoxCacheValue(context: Context): ConstValue?
|
||||
IrConstKind.Long -> value.value as Long
|
||||
else -> throw IllegalArgumentException("IrConst of kind ${value.kind} can't be converted to box cache")
|
||||
}
|
||||
val (start, end) = context.config.target.getBoxCacheRange(cacheType)
|
||||
val (start, end) = generationState.context.config.target.getBoxCacheRange(cacheType)
|
||||
return if (value in start..end) {
|
||||
context.generationState.llvm.let { llvm ->
|
||||
generationState.llvm.let { llvm ->
|
||||
llvm.boxCacheGlobals[cacheType]?.pointer?.getElementPtr(llvm, value.toInt() - start)?.getElementPtr(llvm, 0)
|
||||
}
|
||||
} else {
|
||||
|
||||
+4
-4
@@ -719,7 +719,7 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
||||
fun generateBindings(codegen: CodeGenerator) = BindingsBuilder(codegen).build()
|
||||
|
||||
inner class BindingsBuilder(val codegen: CodeGenerator) : ContextUtils {
|
||||
override val context = this@CAdapterGenerator.context
|
||||
override val generationState = codegen.generationState
|
||||
|
||||
internal val prefix = context.config.fullExportedNamePrefix.replace("-|\\.".toRegex(), "_")
|
||||
private lateinit var outputStreamWriter: PrintWriter
|
||||
@@ -929,7 +929,7 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
||||
val exportedSymbols = mutableListOf<String>()
|
||||
|
||||
private fun makeGlobalStruct(top: ExportedElementScope) {
|
||||
val headerFile = context.generationState.outputFiles.cAdapterHeader
|
||||
val headerFile = generationState.outputFiles.cAdapterHeader
|
||||
outputStreamWriter = headerFile.printWriter()
|
||||
|
||||
val exportedSymbol = "${prefix}_symbols"
|
||||
@@ -1014,7 +1014,7 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
||||
outputStreamWriter.close()
|
||||
println("Produced library API in ${prefix}_api.h")
|
||||
|
||||
outputStreamWriter = context.generationState.tempFiles
|
||||
outputStreamWriter = generationState.tempFiles
|
||||
.cAdapterCpp
|
||||
.printWriter()
|
||||
|
||||
@@ -1154,7 +1154,7 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
||||
outputStreamWriter.close()
|
||||
|
||||
if (context.config.target.family == Family.MINGW) {
|
||||
outputStreamWriter = context.generationState.outputFiles
|
||||
outputStreamWriter = generationState.outputFiles
|
||||
.cAdapterDef
|
||||
.printWriter()
|
||||
output("EXPORTS")
|
||||
|
||||
+10
-9
@@ -20,8 +20,9 @@ private fun LLVMValueRef.isLLVMBuiltin(): Boolean {
|
||||
}
|
||||
|
||||
|
||||
private class CallsChecker(context: Context, goodFunctions: List<String>) {
|
||||
private val llvm = context.generationState.llvm
|
||||
private class CallsChecker(generationState: NativeGenerationState, goodFunctions: List<String>) {
|
||||
private val llvm = generationState.llvm
|
||||
private val context = generationState.context
|
||||
private val goodFunctionsExact = goodFunctions.filterNot { it.endsWith("*") }.toSet()
|
||||
private val goodFunctionsByPrefix = goodFunctions.filter { it.endsWith("*") }.map { it.substring(0, it.length - 1) }.sorted()
|
||||
|
||||
@@ -164,8 +165,8 @@ private class CallsChecker(context: Context, goodFunctions: List<String>) {
|
||||
private const val functionListGlobal = "Kotlin_callsCheckerKnownFunctions"
|
||||
private const val functionListSizeGlobal = "Kotlin_callsCheckerKnownFunctionsCount"
|
||||
|
||||
internal fun checkLlvmModuleExternalCalls(context: Context) {
|
||||
val llvm = context.generationState.llvm
|
||||
internal fun checkLlvmModuleExternalCalls(generationState: NativeGenerationState) {
|
||||
val llvm = generationState.llvm
|
||||
val staticData = llvm.staticData
|
||||
|
||||
|
||||
@@ -177,19 +178,19 @@ internal fun checkLlvmModuleExternalCalls(context: Context) {
|
||||
}.toList()
|
||||
} ?: emptyList()
|
||||
|
||||
val checker = CallsChecker(context, goodFunctions)
|
||||
val checker = CallsChecker(generationState, goodFunctions)
|
||||
getFunctions(llvm.module)
|
||||
.filter { !it.isExternalFunction() && it !in ignoredFunctions }
|
||||
.forEach(checker::processFunction)
|
||||
// otherwise optimiser can inline it
|
||||
staticData.getGlobal(functionListGlobal)?.setExternallyInitialized(true);
|
||||
staticData.getGlobal(functionListSizeGlobal)?.setExternallyInitialized(true);
|
||||
context.verifyBitCode()
|
||||
generationState.verifyBitCode()
|
||||
}
|
||||
|
||||
// this should be a separate pass, to handle DCE correctly
|
||||
internal fun addFunctionsListSymbolForChecker(context: Context) {
|
||||
val llvm = context.generationState.llvm
|
||||
internal fun addFunctionsListSymbolForChecker(generationState: NativeGenerationState) {
|
||||
val llvm = generationState.llvm
|
||||
val staticData = llvm.staticData
|
||||
|
||||
val functions = getFunctions(llvm.module)
|
||||
@@ -203,5 +204,5 @@ internal fun addFunctionsListSymbolForChecker(context: Context) {
|
||||
staticData.getGlobal(functionListSizeGlobal)
|
||||
?.setInitializer(llvm.constInt32(functions.size))
|
||||
?: throw IllegalStateException("$functionListSizeGlobal global not found")
|
||||
context.verifyBitCode()
|
||||
generationState.verifyBitCode()
|
||||
}
|
||||
|
||||
+61
-59
@@ -87,13 +87,14 @@ internal fun llvmIrDumpCallback(state: ActionState, module: IrModuleFragment, co
|
||||
}
|
||||
}
|
||||
|
||||
internal fun produceCStubs(context: Context) {
|
||||
context.generationState.cStubsManager.compile(
|
||||
internal fun produceCStubs(generationState: NativeGenerationState) {
|
||||
val context = generationState.context
|
||||
generationState.cStubsManager.compile(
|
||||
context.config.clang,
|
||||
context.messageCollector,
|
||||
context.inVerbosePhase
|
||||
).forEach {
|
||||
parseAndLinkBitcodeFile(context, context.generationState.llvm.module, it.absolutePath)
|
||||
parseAndLinkBitcodeFile(generationState, generationState.llvm.module, it.absolutePath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,11 +112,11 @@ private data class LlvmModules(
|
||||
* - Runtime modules. These may be used as an input for a separate LTO (e.g. for debug builds).
|
||||
* - Everything else.
|
||||
*/
|
||||
private fun collectLlvmModules(context: Context, generatedBitcodeFiles: List<String>): LlvmModules {
|
||||
val config = context.config
|
||||
private fun collectLlvmModules(generationState: NativeGenerationState, generatedBitcodeFiles: List<String>): LlvmModules {
|
||||
val config = generationState.context.config
|
||||
|
||||
val (bitcodePartOfStdlib, bitcodeLibraries) = context.generationState.llvm.bitcodeToLink
|
||||
.partition { it.isStdlib && context.generationState.producedLlvmModuleContainsStdlib }
|
||||
val (bitcodePartOfStdlib, bitcodeLibraries) = generationState.llvm.bitcodeToLink
|
||||
.partition { it.isStdlib && generationState.producedLlvmModuleContainsStdlib }
|
||||
.toList()
|
||||
.map { libraries ->
|
||||
libraries.flatMap { it.bitcodePaths }.filter { it.isBitcode }
|
||||
@@ -123,7 +124,7 @@ private fun collectLlvmModules(context: Context, generatedBitcodeFiles: List<Str
|
||||
|
||||
val nativeLibraries = config.nativeLibraries + config.launcherNativeLibraries
|
||||
.takeIf { config.produce == CompilerOutputKind.PROGRAM }.orEmpty()
|
||||
val additionalBitcodeFilesToLink = context.generationState.llvm.additionalProducedBitcodeFiles
|
||||
val additionalBitcodeFilesToLink = generationState.llvm.additionalProducedBitcodeFiles
|
||||
val exceptionsSupportNativeLibrary = listOf(config.exceptionsSupportNativeLibrary)
|
||||
.takeIf { config.produce == CompilerOutputKind.DYNAMIC_CACHE }.orEmpty()
|
||||
val additionalBitcodeFiles = nativeLibraries +
|
||||
@@ -132,12 +133,12 @@ private fun collectLlvmModules(context: Context, generatedBitcodeFiles: List<Str
|
||||
bitcodeLibraries +
|
||||
exceptionsSupportNativeLibrary
|
||||
|
||||
val runtimeNativeLibraries = context.config.runtimeNativeLibraries
|
||||
val runtimeNativeLibraries = config.runtimeNativeLibraries
|
||||
|
||||
|
||||
fun parseBitcodeFiles(files: List<String>): List<LLVMModuleRef> = files.map { bitcodeFile ->
|
||||
val parsedModule = parseBitcodeFile(context.generationState.llvmContext, bitcodeFile)
|
||||
if (!context.shouldUseDebugInfoFromNativeLibs()) {
|
||||
val parsedModule = parseBitcodeFile(generationState.llvmContext, bitcodeFile)
|
||||
if (!generationState.context.shouldUseDebugInfoFromNativeLibs()) {
|
||||
LLVMStripModuleDebugInfo(parsedModule)
|
||||
}
|
||||
parsedModule
|
||||
@@ -145,67 +146,68 @@ private fun collectLlvmModules(context: Context, generatedBitcodeFiles: List<Str
|
||||
|
||||
val runtimeModules = parseBitcodeFiles(
|
||||
(runtimeNativeLibraries + bitcodePartOfStdlib)
|
||||
.takeIf { context.generationState.shouldLinkRuntimeNativeLibraries }.orEmpty()
|
||||
.takeIf { generationState.shouldLinkRuntimeNativeLibraries }.orEmpty()
|
||||
)
|
||||
val additionalModules = parseBitcodeFiles(additionalBitcodeFiles)
|
||||
return LlvmModules(
|
||||
runtimeModules.ifNotEmpty { this + context.generateRuntimeConstantsModule() } ?: emptyList(),
|
||||
additionalModules + listOfNotNull(patchObjCRuntimeModule(context))
|
||||
runtimeModules.ifNotEmpty { this + generationState.generateRuntimeConstantsModule() } ?: emptyList(),
|
||||
additionalModules + listOfNotNull(patchObjCRuntimeModule(generationState))
|
||||
)
|
||||
}
|
||||
|
||||
private fun linkAllDependencies(context: Context, generatedBitcodeFiles: List<String>) {
|
||||
val (runtimeModules, additionalModules) = collectLlvmModules(context, generatedBitcodeFiles)
|
||||
private fun linkAllDependencies(generationState: NativeGenerationState, generatedBitcodeFiles: List<String>) {
|
||||
val (runtimeModules, additionalModules) = collectLlvmModules(generationState, generatedBitcodeFiles)
|
||||
// TODO: Possibly slow, maybe to a separate phase?
|
||||
val optimizedRuntimeModules = RuntimeLinkageStrategy.pick(context, runtimeModules).run()
|
||||
val optimizedRuntimeModules = RuntimeLinkageStrategy.pick(generationState, runtimeModules).run()
|
||||
|
||||
(optimizedRuntimeModules + additionalModules).forEach {
|
||||
val failed = llvmLinkModules2(context, context.generationState.llvm.module, it)
|
||||
val failed = llvmLinkModules2(generationState, generationState.llvm.module, it)
|
||||
if (failed != 0) {
|
||||
error("Failed to link ${it.getName()}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun insertAliasToEntryPoint(context: Context) {
|
||||
val nomain = context.config.configuration.get(KonanConfigKeys.NOMAIN) ?: false
|
||||
if (context.config.produce != CompilerOutputKind.PROGRAM || nomain)
|
||||
private fun insertAliasToEntryPoint(generationState: NativeGenerationState) {
|
||||
val config = generationState.context.config
|
||||
val nomain = config.configuration.get(KonanConfigKeys.NOMAIN) ?: false
|
||||
if (config.produce != CompilerOutputKind.PROGRAM || nomain)
|
||||
return
|
||||
val module = context.generationState.llvm.module
|
||||
val entryPointName = context.config.entryPointName
|
||||
val module = generationState.llvm.module
|
||||
val entryPointName = config.entryPointName
|
||||
val entryPoint = LLVMGetNamedFunction(module, entryPointName)
|
||||
?: error("Module doesn't contain `$entryPointName`")
|
||||
LLVMAddAlias(module, LLVMTypeOf(entryPoint)!!, entryPoint, "main")
|
||||
}
|
||||
|
||||
internal fun linkBitcodeDependencies(context: Context) {
|
||||
val config = context.config.configuration
|
||||
val tempFiles = context.generationState.tempFiles
|
||||
val produce = config.get(KonanConfigKeys.PRODUCE)
|
||||
internal fun linkBitcodeDependencies(generationState: NativeGenerationState) {
|
||||
val config = generationState.context.config
|
||||
val tempFiles = generationState.tempFiles
|
||||
val produce = config.produce
|
||||
|
||||
val generatedBitcodeFiles =
|
||||
if (produce == CompilerOutputKind.DYNAMIC || produce == CompilerOutputKind.STATIC) {
|
||||
produceCAdapterBitcode(
|
||||
context.config.clang,
|
||||
config.clang,
|
||||
tempFiles.cAdapterCppName,
|
||||
tempFiles.cAdapterBitcodeName)
|
||||
listOf(tempFiles.cAdapterBitcodeName)
|
||||
} else emptyList()
|
||||
if (produce == CompilerOutputKind.FRAMEWORK && context.config.produceStaticFramework) {
|
||||
embedAppleLinkerOptionsToBitcode(context.generationState.llvm, context.config)
|
||||
if (produce == CompilerOutputKind.FRAMEWORK && config.produceStaticFramework) {
|
||||
embedAppleLinkerOptionsToBitcode(generationState.llvm, config)
|
||||
}
|
||||
linkAllDependencies(context, generatedBitcodeFiles)
|
||||
linkAllDependencies(generationState, generatedBitcodeFiles)
|
||||
|
||||
}
|
||||
|
||||
internal fun produceOutput(context: Context) {
|
||||
|
||||
val config = context.config.configuration
|
||||
val tempFiles = context.generationState.tempFiles
|
||||
val produce = context.config.produce
|
||||
internal fun produceOutput(generationState: NativeGenerationState) {
|
||||
val context = generationState.context
|
||||
val config = context.config
|
||||
val tempFiles = generationState.tempFiles
|
||||
val produce = config.produce
|
||||
if (produce == CompilerOutputKind.FRAMEWORK) {
|
||||
context.objCExport.produceFrameworkInterface()
|
||||
if (context.config.omitFrameworkBinary) {
|
||||
generationState.objCExport.produceFrameworkInterface()
|
||||
if (config.omitFrameworkBinary) {
|
||||
// Compiler does not compile anything in this mode, so return early.
|
||||
return
|
||||
}
|
||||
@@ -218,21 +220,21 @@ internal fun produceOutput(context: Context) {
|
||||
CompilerOutputKind.STATIC_CACHE,
|
||||
CompilerOutputKind.PROGRAM -> {
|
||||
val output = tempFiles.nativeBinaryFileName
|
||||
context.bitcodeFileName = output
|
||||
generationState.bitcodeFileName = output
|
||||
// Insert `_main` after pipeline so we won't worry about optimizations
|
||||
// corrupting entry point.
|
||||
insertAliasToEntryPoint(context)
|
||||
LLVMWriteBitcodeToFile(context.generationState.llvm.module, output)
|
||||
insertAliasToEntryPoint(generationState)
|
||||
LLVMWriteBitcodeToFile(generationState.llvm.module, output)
|
||||
}
|
||||
CompilerOutputKind.LIBRARY -> {
|
||||
val nopack = config.getBoolean(KonanConfigKeys.NOPACK)
|
||||
val output = context.generationState.outputFiles.klibOutputFileName(!nopack)
|
||||
val libraryName = context.config.moduleId
|
||||
val shortLibraryName = context.config.shortModuleName
|
||||
val nopack = config.configuration.getBoolean(KonanConfigKeys.NOPACK)
|
||||
val output = generationState.outputFiles.klibOutputFileName(!nopack)
|
||||
val libraryName = config.moduleId
|
||||
val shortLibraryName = config.shortModuleName
|
||||
val neededLibraries = context.librariesWithDependencies
|
||||
val abiVersion = KotlinAbiVersion.CURRENT
|
||||
val compilerVersion = CompilerVersion.CURRENT.toString()
|
||||
val libraryVersion = config.get(KonanConfigKeys.LIBRARY_VERSION)
|
||||
val libraryVersion = config.configuration.get(KonanConfigKeys.LIBRARY_VERSION)
|
||||
val metadataVersion = KlibMetadataVersion.INSTANCE.toString()
|
||||
val irVersion = KlibIrVersion.INSTANCE.toString()
|
||||
val versions = KotlinLibraryVersioning(
|
||||
@@ -242,19 +244,19 @@ internal fun produceOutput(context: Context) {
|
||||
metadataVersion = metadataVersion,
|
||||
irVersion = irVersion
|
||||
)
|
||||
val target = context.config.target
|
||||
val manifestProperties = context.config.manifestProperties
|
||||
val target = config.target
|
||||
val manifestProperties = config.manifestProperties
|
||||
|
||||
if (!nopack) {
|
||||
val suffix = context.config.produce.suffix(target)
|
||||
val suffix = config.produce.suffix(target)
|
||||
if (!output.endsWith(suffix)) {
|
||||
error("please specify correct output: packed: ${!nopack}, $output$suffix")
|
||||
}
|
||||
}
|
||||
|
||||
val library = buildLibrary(
|
||||
context.config.nativeLibraries,
|
||||
context.config.includeBinaries,
|
||||
config.nativeLibraries,
|
||||
config.includeBinaries,
|
||||
neededLibraries,
|
||||
context.serializedMetadata!!,
|
||||
context.serializedIr,
|
||||
@@ -267,23 +269,23 @@ internal fun produceOutput(context: Context) {
|
||||
manifestProperties,
|
||||
context.dataFlowGraph)
|
||||
|
||||
context.bitcodeFileName = library.mainBitcodeFileName
|
||||
generationState.bitcodeFileName = library.mainBitcodeFileName
|
||||
}
|
||||
CompilerOutputKind.BITCODE -> {
|
||||
val output = context.generationState.outputFile
|
||||
context.bitcodeFileName = output
|
||||
LLVMWriteBitcodeToFile(context.generationState.llvm.module, output)
|
||||
val output = generationState.outputFile
|
||||
generationState.bitcodeFileName = output
|
||||
LLVMWriteBitcodeToFile(generationState.llvm.module, output)
|
||||
}
|
||||
else -> error("not supported: $produce")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun parseAndLinkBitcodeFile(context: Context, llvmModule: LLVMModuleRef, path: String) {
|
||||
val parsedModule = parseBitcodeFile(context.generationState.llvmContext, path)
|
||||
if (!context.shouldUseDebugInfoFromNativeLibs()) {
|
||||
private fun parseAndLinkBitcodeFile(generationState: NativeGenerationState, llvmModule: LLVMModuleRef, path: String) {
|
||||
val parsedModule = parseBitcodeFile(generationState.llvmContext, path)
|
||||
if (!generationState.context.shouldUseDebugInfoFromNativeLibs()) {
|
||||
LLVMStripModuleDebugInfo(parsedModule)
|
||||
}
|
||||
val failed = llvmLinkModules2(context, llvmModule, parsedModule)
|
||||
val failed = llvmLinkModules2(generationState, llvmModule, parsedModule)
|
||||
if (failed != 0) {
|
||||
throw Error("failed to link $path")
|
||||
}
|
||||
|
||||
+5
-8
@@ -15,9 +15,10 @@ import org.jetbrains.kotlin.backend.konan.descriptors.GlobalHierarchyAnalysisRes
|
||||
import org.jetbrains.kotlin.backend.konan.ir.KonanIr
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.CodegenClassMetadata
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.Lifetime
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager
|
||||
import org.jetbrains.kotlin.backend.konan.lower.*
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportCodeSpec
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportedInterface
|
||||
import org.jetbrains.kotlin.backend.konan.optimizations.DevirtualizationAnalysis
|
||||
import org.jetbrains.kotlin.backend.konan.optimizations.ModuleDFG
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.KonanIrLinker
|
||||
@@ -65,8 +66,6 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config), Confi
|
||||
|
||||
lateinit var moduleDescriptor: ModuleDescriptor
|
||||
|
||||
lateinit var objCExport: ObjCExport
|
||||
|
||||
lateinit var cAdapterGenerator: CAdapterGenerator
|
||||
|
||||
lateinit var expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>
|
||||
@@ -190,10 +189,10 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config), Confi
|
||||
InteropBuiltIns(this.builtIns)
|
||||
}
|
||||
|
||||
lateinit var bitcodeFileName: String
|
||||
lateinit var library: KonanLibraryLayout
|
||||
var objCExportedInterface: ObjCExportedInterface? = null
|
||||
var objCExportCodeSpec: ObjCExportCodeSpec? = null
|
||||
|
||||
val coverage by lazy { CoverageManager(this) }
|
||||
lateinit var library: KonanLibraryLayout
|
||||
|
||||
fun separator(title: String) {
|
||||
println("\n\n--- ${title} ----------------------\n")
|
||||
@@ -229,8 +228,6 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config), Confi
|
||||
internal val stdlibModule
|
||||
get() = this.builtIns.any.module
|
||||
|
||||
lateinit var compilerOutput: List<ObjectFile>
|
||||
|
||||
val declaredLocalArrays: MutableMap<String, LLVMTypeRef> = HashMap()
|
||||
|
||||
lateinit var irLinker: KonanIrLinker
|
||||
|
||||
+4
-3
@@ -22,14 +22,15 @@ import org.jetbrains.kotlin.name.Name
|
||||
|
||||
internal object DECLARATION_ORIGIN_ENTRY_POINT : IrDeclarationOriginImpl("ENTRY_POINT")
|
||||
|
||||
internal fun makeEntryPoint(context: Context): IrFunction {
|
||||
internal fun makeEntryPoint(generationState: NativeGenerationState): IrFunction {
|
||||
val context = generationState.context
|
||||
val actualMain = context.ir.symbols.entryPoint!!.owner
|
||||
// TODO: Do we need to do something with the offsets if <main> is in a cached library?
|
||||
val startOffset = if (context.generationState.llvmModuleSpecification.containsDeclaration(actualMain))
|
||||
val startOffset = if (generationState.llvmModuleSpecification.containsDeclaration(actualMain))
|
||||
actualMain.startOffset
|
||||
else
|
||||
SYNTHETIC_OFFSET
|
||||
val endOffset = if (context.generationState.llvmModuleSpecification.containsDeclaration(actualMain))
|
||||
val endOffset = if (generationState.llvmModuleSpecification.containsDeclaration(actualMain))
|
||||
actualMain.endOffset
|
||||
else
|
||||
SYNTHETIC_OFFSET
|
||||
|
||||
+10
-10
@@ -150,7 +150,7 @@ internal val sharedVariablesPhase = makeKonanFileLoweringPhase(
|
||||
)
|
||||
|
||||
internal val inventNamesForLocalClasses = makeKonanFileLoweringPhase(
|
||||
{ NativeInventNamesForLocalClasses(it) },
|
||||
{ NativeInventNamesForLocalClasses(it.generationState) },
|
||||
name = "InventNamesForLocalClasses",
|
||||
description = "Invent names for local classes and anonymous objects"
|
||||
)
|
||||
@@ -186,7 +186,7 @@ internal val wrapInlineDeclarationsWithReifiedTypeParametersLowering = makeKonan
|
||||
|
||||
internal val inlinePhase = makeKonanFileOpPhase(
|
||||
{ context, irFile ->
|
||||
FunctionInlining(context, NativeInlineFunctionResolver(context)).lower(irFile)
|
||||
FunctionInlining(context, NativeInlineFunctionResolver(context, context.generationState)).lower(irFile)
|
||||
},
|
||||
name = "Inline",
|
||||
description = "Functions inlining",
|
||||
@@ -250,10 +250,10 @@ internal val initializersPhase = makeKonanFileLoweringPhase(
|
||||
prerequisite = setOf(enumConstructorsPhase)
|
||||
)
|
||||
|
||||
internal val objectClassesPhase = makeKonanFileLoweringPhase(
|
||||
::ObjectClassLowering,
|
||||
internal val objectClassesPhase = makeKonanFileOpPhase(
|
||||
op = { context, irFile -> ObjectClassLowering(context.generationState).lower(irFile) },
|
||||
name = "ObjectClasses",
|
||||
description = "Enum constructors lowering"
|
||||
description = "Object classes lowering"
|
||||
)
|
||||
|
||||
internal val localFunctionsPhase = makeKonanFileOpPhase(
|
||||
@@ -333,13 +333,13 @@ internal val testProcessorPhase = makeKonanFileOpPhase(
|
||||
)
|
||||
|
||||
internal val delegationPhase = makeKonanFileLoweringPhase(
|
||||
::PropertyDelegationLowering,
|
||||
{ PropertyDelegationLowering(it.generationState) },
|
||||
name = "Delegation",
|
||||
description = "Delegation lowering"
|
||||
)
|
||||
|
||||
internal val functionReferencePhase = makeKonanFileLoweringPhase(
|
||||
::FunctionReferenceLowering,
|
||||
{ FunctionReferenceLowering(it.generationState) },
|
||||
name = "FunctionReference",
|
||||
description = "Function references lowering",
|
||||
prerequisite = setOf(delegationPhase, localFunctionsPhase) // TODO: make weak dependency on `testProcessorPhase`
|
||||
@@ -382,7 +382,7 @@ internal val builtinOperatorPhase = makeKonanFileLoweringPhase(
|
||||
)
|
||||
|
||||
internal val interopPhase = makeKonanFileLoweringPhase(
|
||||
::InteropLowering,
|
||||
{ InteropLowering(it.generationState) },
|
||||
name = "Interop",
|
||||
description = "Interop lowering",
|
||||
prerequisite = setOf(inlinePhase, localFunctionsPhase, functionReferencePhase)
|
||||
@@ -397,7 +397,7 @@ internal val varargPhase = makeKonanFileLoweringPhase(
|
||||
|
||||
internal val coroutinesPhase = makeKonanFileOpPhase(
|
||||
{ context, irFile ->
|
||||
NativeSuspendFunctionsLowering(context).lower(irFile)
|
||||
NativeSuspendFunctionsLowering(context.generationState).lower(irFile)
|
||||
AddContinuationToNonLocalSuspendFunctionsLowering(context).lower(irFile)
|
||||
NativeAddContinuationToFunctionCallsLowering(context).lower(irFile)
|
||||
AddFunctionSupertypeToSuspendFunctionLowering(context).lower(irFile)
|
||||
@@ -483,7 +483,7 @@ internal val exportInternalAbiPhase = makeKonanFileLoweringPhase(
|
||||
)
|
||||
|
||||
internal val useInternalAbiPhase = makeKonanFileLoweringPhase(
|
||||
::ImportCachesAbiTransformer,
|
||||
{ ImportCachesAbiTransformer(it.generationState) },
|
||||
name = "UseInternalAbi",
|
||||
description = "Use internal ABI functions to access private entities"
|
||||
)
|
||||
+21
-20
@@ -33,8 +33,9 @@ internal fun determineLinkerOutput(context: Context): LinkerOutputKind =
|
||||
else -> TODO("${context.config.produce} should not reach native linker stage")
|
||||
}
|
||||
|
||||
internal class CacheStorage(val context: Context) {
|
||||
private val outputFiles = context.generationState.outputFiles
|
||||
internal class CacheStorage(val generationState: NativeGenerationState) {
|
||||
private val config = generationState.context.config
|
||||
private val outputFiles = generationState.outputFiles
|
||||
|
||||
fun renameOutput() {
|
||||
// For caches the output file is a directory. It might be created by someone else,
|
||||
@@ -53,30 +54,30 @@ internal class CacheStorage(val context: Context) {
|
||||
}
|
||||
|
||||
private fun saveCacheBitcodeDependencies() {
|
||||
val bitcodeDependencies = context.config.resolvedLibraries
|
||||
val bitcodeDependencies = config.resolvedLibraries
|
||||
.getFullList(TopologicalLibraryOrder)
|
||||
.map { it as KonanLibrary }
|
||||
.filter {
|
||||
context.generationState.llvmImports.bitcodeIsUsed(it)
|
||||
&& it != context.config.cacheSupport.libraryToCache?.klib // Skip loops.
|
||||
generationState.llvmImports.bitcodeIsUsed(it)
|
||||
&& it != config.cacheSupport.libraryToCache?.klib // Skip loops.
|
||||
}
|
||||
outputFiles.bitcodeDependenciesFile!!.writeLines(bitcodeDependencies.map { it.uniqueName })
|
||||
}
|
||||
|
||||
private fun saveInlineFunctionBodies() {
|
||||
outputFiles.inlineFunctionBodiesFile!!.writeBytes(
|
||||
InlineFunctionBodyReferenceSerializer.serialize(context.generationState.inlineFunctionBodies))
|
||||
InlineFunctionBodyReferenceSerializer.serialize(generationState.inlineFunctionBodies))
|
||||
}
|
||||
|
||||
private fun saveClassFields() {
|
||||
outputFiles.classFieldsFile!!.writeBytes(
|
||||
ClassFieldsSerializer.serialize(context.generationState.classFields))
|
||||
ClassFieldsSerializer.serialize(generationState.classFields))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: We have a Linker.kt file in the shared module.
|
||||
internal class Linker(val context: Context) {
|
||||
|
||||
internal class Linker(val generationState: NativeGenerationState) {
|
||||
private val context = generationState.context
|
||||
private val platform = context.config.platform
|
||||
private val config = context.config.configuration
|
||||
private val linkerOutput = determineLinkerOutput(context)
|
||||
@@ -86,13 +87,13 @@ internal class Linker(val context: Context) {
|
||||
private val debug = context.config.debug || context.config.lightDebug
|
||||
|
||||
fun link(objectFiles: List<ObjectFile>) {
|
||||
val nativeDependencies = context.generationState.llvm.nativeDependenciesToLink
|
||||
val nativeDependencies = generationState.llvm.nativeDependenciesToLink
|
||||
|
||||
val includedBinariesLibraries = context.config.libraryToCache?.let { listOf(it.klib) }
|
||||
?: nativeDependencies.filterNot { context.config.cachedLibraries.isLibraryCached(it) }
|
||||
val includedBinaries = includedBinariesLibraries.map { (it as? KonanLibrary)?.includedPaths.orEmpty() }.flatten()
|
||||
|
||||
val libraryProvidedLinkerFlags = context.generationState.llvm.allNativeDependencies.map { it.linkerOpts }.flatten()
|
||||
val libraryProvidedLinkerFlags = generationState.llvm.allNativeDependencies.map { it.linkerOpts }.flatten()
|
||||
|
||||
runLinker(objectFiles, includedBinaries, libraryProvidedLinkerFlags)
|
||||
}
|
||||
@@ -117,7 +118,7 @@ internal class Linker(val context: Context) {
|
||||
private fun runLinker(objectFiles: List<ObjectFile>,
|
||||
includedBinaries: List<String>,
|
||||
libraryProvidedLinkerFlags: List<String>): ExecutableFile? {
|
||||
val outputFiles = context.generationState.outputFiles
|
||||
val outputFiles = generationState.outputFiles
|
||||
|
||||
val additionalLinkerArgs: List<String>
|
||||
val executable: String
|
||||
@@ -134,7 +135,7 @@ internal class Linker(val context: Context) {
|
||||
}
|
||||
executable = outputFiles.nativeBinaryFile
|
||||
} else {
|
||||
val framework = File(context.generationState.outputFile)
|
||||
val framework = File(generationState.outputFile)
|
||||
val dylibName = framework.name.removeSuffix(".framework")
|
||||
val dylibRelativePath = when (target.family) {
|
||||
Family.IOS,
|
||||
@@ -149,7 +150,7 @@ internal class Linker(val context: Context) {
|
||||
executable = dylibPath.absolutePath
|
||||
}
|
||||
|
||||
val needsProfileLibrary = context.coverage.enabled
|
||||
val needsProfileLibrary = generationState.coverage.enabled
|
||||
val mimallocEnabled = context.config.allocationMode == AllocationMode.MIMALLOC
|
||||
|
||||
val linkerInput = determineLinkerInput(objectFiles, linkerOutput)
|
||||
@@ -203,7 +204,7 @@ internal class Linker(val context: Context) {
|
||||
}
|
||||
|
||||
private fun determineLinkerInput(objectFiles: List<ObjectFile>, linkerOutputKind: LinkerOutputKind): LinkerInput {
|
||||
val caches = determineCachesToLink(context)
|
||||
val caches = determineCachesToLink(generationState)
|
||||
// Since we have several linker stages that involve caching,
|
||||
// we should detect cache usage early to report errors correctly.
|
||||
val cachingInvolved = caches.static.isNotEmpty() || caches.dynamic.isNotEmpty()
|
||||
@@ -213,7 +214,7 @@ internal class Linker(val context: Context) {
|
||||
LinkerInput(objectFiles, CachesToLink(emptyList(), caches.dynamic), emptyList(), cachingInvolved)
|
||||
}
|
||||
shouldPerformPreLink(caches, linkerOutputKind) -> {
|
||||
val preLinkResult = context.generationState.tempFiles.create("withStaticCaches", ".o").absolutePath
|
||||
val preLinkResult = generationState.tempFiles.create("withStaticCaches", ".o").absolutePath
|
||||
val preLinkCommands = linker.preLinkCommands(objectFiles + caches.static, preLinkResult)
|
||||
LinkerInput(listOf(preLinkResult), CachesToLink(emptyList(), caches.dynamic), preLinkCommands, cachingInvolved)
|
||||
}
|
||||
@@ -231,13 +232,13 @@ private class LinkerInput(
|
||||
|
||||
private class CachesToLink(val static: List<String>, val dynamic: List<String>)
|
||||
|
||||
private fun determineCachesToLink(context: Context): CachesToLink {
|
||||
private fun determineCachesToLink(generationState: NativeGenerationState): CachesToLink {
|
||||
val staticCaches = mutableListOf<String>()
|
||||
val dynamicCaches = mutableListOf<String>()
|
||||
|
||||
context.generationState.llvm.allCachedBitcodeDependencies.forEach { library ->
|
||||
val currentBinaryContainsLibrary = context.generationState.llvmModuleSpecification.containsLibrary(library)
|
||||
val cache = context.config.cachedLibraries.getLibraryCache(library)
|
||||
generationState.llvm.allCachedBitcodeDependencies.forEach { library ->
|
||||
val currentBinaryContainsLibrary = generationState.llvmModuleSpecification.containsLibrary(library)
|
||||
val cache = generationState.context.config.cachedLibraries.getLibraryCache(library)
|
||||
?: error("Library $library is expected to be cached")
|
||||
|
||||
// Consistency check. Generally guaranteed by implementation.
|
||||
|
||||
+3
-3
@@ -43,7 +43,7 @@ internal class DefaultLlvmModuleSpecification(cachedLibraries: CachedLibraries)
|
||||
}
|
||||
|
||||
internal class CacheLlvmModuleSpecification(
|
||||
private val context: Context,
|
||||
private val generationState: NativeGenerationState,
|
||||
cachedLibraries: CachedLibraries,
|
||||
private val libraryToCache: PartialCacheInfo
|
||||
) : LlvmModuleSpecificationBase(cachedLibraries) {
|
||||
@@ -52,10 +52,10 @@ internal class CacheLlvmModuleSpecification(
|
||||
override fun containsLibrary(library: KotlinLibrary): Boolean = library == libraryToCache.klib
|
||||
|
||||
override fun containsDeclaration(declaration: IrDeclaration): Boolean {
|
||||
if (context.generationState.shouldDefineFunctionClasses && declaration.getPackageFragment().isFunctionInterfaceFile)
|
||||
if (generationState.shouldDefineFunctionClasses && declaration.getPackageFragment().isFunctionInterfaceFile)
|
||||
return true
|
||||
if (!super.containsDeclaration(declaration)) return false
|
||||
return (context.generationState.cacheDeserializationStrategy as? CacheDeserializationStrategy.SingleFile)
|
||||
return (generationState.cacheDeserializationStrategy as? CacheDeserializationStrategy.SingleFile)
|
||||
?.filePath.let { it == null || it == declaration.fileOrNull?.path }
|
||||
}
|
||||
}
|
||||
|
||||
+14
-4
@@ -10,7 +10,9 @@ import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.DebugInfo
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.Llvm
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.LlvmDeclarations
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.verifyModule
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.SerializedClassFields
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.SerializedInlineFunctionReference
|
||||
import org.jetbrains.kotlin.ir.declarations.IrAttributeContainer
|
||||
@@ -40,7 +42,7 @@ internal class FileLowerState {
|
||||
"$prefix${cStubCount++}"
|
||||
}
|
||||
|
||||
internal class NativeGenerationState(private val context: Context, val cacheDeserializationStrategy: CacheDeserializationStrategy?) {
|
||||
internal class NativeGenerationState(val context: Context, val cacheDeserializationStrategy: CacheDeserializationStrategy?) {
|
||||
private val config = context.config
|
||||
|
||||
private val outputPath = config.cacheSupport.tryGetImplicitOutput(cacheDeserializationStrategy) ?: config.outputPath
|
||||
@@ -75,7 +77,7 @@ internal class NativeGenerationState(private val context: Context, val cacheDese
|
||||
|
||||
val llvmModuleSpecification by lazy {
|
||||
if (config.produce.isCache)
|
||||
CacheLlvmModuleSpecification(context, config.cachedLibraries,
|
||||
CacheLlvmModuleSpecification(this, config.cachedLibraries,
|
||||
PartialCacheInfo(config.libraryToCache!!.klib, cacheDeserializationStrategy!!))
|
||||
else DefaultLlvmModuleSpecification(config.cachedLibraries)
|
||||
}
|
||||
@@ -83,8 +85,8 @@ internal class NativeGenerationState(private val context: Context, val cacheDese
|
||||
val producedLlvmModuleContainsStdlib get() = llvmModuleSpecification.containsModule(context.stdlibModule)
|
||||
|
||||
private val runtimeDelegate = lazy { Runtime(llvmContext, config.distribution.compilerInterface(config.target)) }
|
||||
private val llvmDelegate = lazy { Llvm(context, LLVMModuleCreateWithNameInContext("out", llvmContext)!!) }
|
||||
private val debugInfoDelegate = lazy { DebugInfo(context) }
|
||||
private val llvmDelegate = lazy { Llvm(this, LLVMModuleCreateWithNameInContext("out", llvmContext)!!) }
|
||||
private val debugInfoDelegate = lazy { DebugInfo(this) }
|
||||
|
||||
val llvmContext = LLVMContextCreate()!!
|
||||
val llvmImports = Llvm.ImportsImpl(context)
|
||||
@@ -94,6 +96,14 @@ internal class NativeGenerationState(private val context: Context, val cacheDese
|
||||
val cStubsManager = CStubsManager(config.target, this)
|
||||
lateinit var llvmDeclarations: LlvmDeclarations
|
||||
|
||||
lateinit var bitcodeFileName: String
|
||||
|
||||
lateinit var compilerOutput: List<ObjectFile>
|
||||
|
||||
val coverage by lazy { CoverageManager(this) }
|
||||
|
||||
lateinit var objCExport: ObjCExport
|
||||
|
||||
fun hasDebugInfo() = debugInfoDelegate.isInitialized()
|
||||
|
||||
fun verifyBitCode() {
|
||||
|
||||
+7
-5
@@ -86,10 +86,11 @@ private fun tryGetInlineThreshold(context: Context): Int? {
|
||||
* Still, runtime is not intended to be debugged by user, and we can optimize it pretty aggressively
|
||||
* even in debug compilation.
|
||||
*/
|
||||
internal fun createLTOPipelineConfigForRuntime(context: Context): LlvmPipelineConfig {
|
||||
internal fun createLTOPipelineConfigForRuntime(generationState: NativeGenerationState): LlvmPipelineConfig {
|
||||
val context = generationState.context
|
||||
val configurables: Configurables = context.config.platform.configurables
|
||||
return LlvmPipelineConfig(
|
||||
context.generationState.llvm.targetTriple,
|
||||
generationState.llvm.targetTriple,
|
||||
getCpuModel(context),
|
||||
getCpuFeatures(context),
|
||||
LlvmOptimizationLevel.AGGRESSIVE,
|
||||
@@ -114,7 +115,8 @@ internal fun createLTOPipelineConfigForRuntime(context: Context): LlvmPipelineCo
|
||||
* In case of debug we do almost nothing (that's why we need [createLTOPipelineConfigForRuntime]),
|
||||
* but for release binaries we rely on "closed" world and enable a lot of optimizations.
|
||||
*/
|
||||
internal fun createLTOFinalPipelineConfig(context: Context): LlvmPipelineConfig {
|
||||
internal fun createLTOFinalPipelineConfig(generationState: NativeGenerationState): LlvmPipelineConfig {
|
||||
val context = generationState.context
|
||||
val target = context.config.target
|
||||
val configurables: Configurables = context.config.platform.configurables
|
||||
val cpuModel = getCpuModel(context)
|
||||
@@ -142,7 +144,7 @@ internal fun createLTOFinalPipelineConfig(context: Context): LlvmPipelineConfig
|
||||
val globalDce = true
|
||||
// Since we are in a "closed world" internalization can be safely used
|
||||
// to reduce size of a bitcode with global dce.
|
||||
val internalize = context.generationState.llvmModuleSpecification.isFinal
|
||||
val internalize = generationState.llvmModuleSpecification.isFinal
|
||||
// Hidden visibility makes symbols internal when linking the binary.
|
||||
// When producing dynamic library, this enables stripping unused symbols from binary with -dead_strip flag,
|
||||
// similar to DCE enabled by internalize but later:
|
||||
@@ -160,7 +162,7 @@ internal fun createLTOFinalPipelineConfig(context: Context): LlvmPipelineConfig
|
||||
}
|
||||
|
||||
return LlvmPipelineConfig(
|
||||
context.generationState.llvm.targetTriple,
|
||||
generationState.llvm.targetTriple,
|
||||
cpuModel,
|
||||
cpuFeatures,
|
||||
optimizationLevel,
|
||||
|
||||
+10
-9
@@ -36,7 +36,7 @@ internal sealed class RuntimeLinkageStrategy {
|
||||
* Links all runtime modules into a single one and optimizes it.
|
||||
*/
|
||||
class LinkAndOptimize(
|
||||
private val context: Context,
|
||||
private val generationState: NativeGenerationState,
|
||||
private val runtimeNativeLibraries: List<LLVMModuleRef>
|
||||
) : RuntimeLinkageStrategy() {
|
||||
|
||||
@@ -44,15 +44,15 @@ internal sealed class RuntimeLinkageStrategy {
|
||||
if (runtimeNativeLibraries.isEmpty()) {
|
||||
return emptyList()
|
||||
}
|
||||
val runtimeModule = LLVMModuleCreateWithNameInContext("runtime", context.generationState.llvmContext)!!
|
||||
val runtimeModule = LLVMModuleCreateWithNameInContext("runtime", generationState.llvmContext)!!
|
||||
runtimeNativeLibraries.forEach {
|
||||
val failed = llvmLinkModules2(context, runtimeModule, it)
|
||||
val failed = llvmLinkModules2(generationState, runtimeModule, it)
|
||||
if (failed != 0) {
|
||||
throw Error("Failed to link ${it.getName()}")
|
||||
}
|
||||
}
|
||||
val config = createLTOPipelineConfigForRuntime(context)
|
||||
LlvmOptimizationPipeline(config, runtimeModule, context).use {
|
||||
val config = createLTOPipelineConfigForRuntime(generationState)
|
||||
LlvmOptimizationPipeline(config, runtimeModule, generationState.context).use {
|
||||
it.run()
|
||||
}
|
||||
return listOf(runtimeModule)
|
||||
@@ -63,12 +63,13 @@ internal sealed class RuntimeLinkageStrategy {
|
||||
/**
|
||||
* Choose runtime linkage strategy based on current compiler configuration and [BinaryOptions.linkRuntime].
|
||||
*/
|
||||
internal fun pick(context: Context, runtimeLlvmModules: List<LLVMModuleRef>): RuntimeLinkageStrategy {
|
||||
val binaryOption = context.config.configuration.get(BinaryOptions.linkRuntime)
|
||||
internal fun pick(generationState: NativeGenerationState, runtimeLlvmModules: List<LLVMModuleRef>): RuntimeLinkageStrategy {
|
||||
val config = generationState.context.config
|
||||
val binaryOption = config.configuration.get(BinaryOptions.linkRuntime)
|
||||
return when {
|
||||
binaryOption == RuntimeLinkageStrategyBinaryOption.Raw -> Raw(runtimeLlvmModules)
|
||||
binaryOption == RuntimeLinkageStrategyBinaryOption.Optimize -> LinkAndOptimize(context, runtimeLlvmModules)
|
||||
context.config.debug -> LinkAndOptimize(context, runtimeLlvmModules)
|
||||
binaryOption == RuntimeLinkageStrategyBinaryOption.Optimize -> LinkAndOptimize(generationState, runtimeLlvmModules)
|
||||
config.debug -> LinkAndOptimize(generationState, runtimeLlvmModules)
|
||||
else -> Raw(runtimeLlvmModules)
|
||||
}
|
||||
|
||||
|
||||
+8
-10
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.lower.CacheInfoBuilder
|
||||
import org.jetbrains.kotlin.backend.konan.lower.ExpectToActualDefaultValueCopier
|
||||
import org.jetbrains.kotlin.backend.konan.lower.SamSuperTypesChecker
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.createCodeSpec
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.produceObjCExportInterface
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.KonanIdSignaturer
|
||||
@@ -92,13 +91,12 @@ internal val createSymbolTablePhase = konanUnitPhase(
|
||||
|
||||
internal val objCExportPhase = konanUnitPhase(
|
||||
op = {
|
||||
val objcInterface = when {
|
||||
objCExportedInterface = when {
|
||||
!config.target.family.isAppleFamily -> null
|
||||
config.produce != CompilerOutputKind.FRAMEWORK -> null
|
||||
else -> produceObjCExportInterface(this)
|
||||
}
|
||||
val codeSpec = objcInterface?.createCodeSpec(symbolTable!!)
|
||||
objCExport = ObjCExport(this, objcInterface, codeSpec)
|
||||
objCExportCodeSpec = objCExportedInterface?.createCodeSpec(symbolTable!!)
|
||||
},
|
||||
name = "ObjCExport",
|
||||
description = "Objective-C header generation",
|
||||
@@ -135,7 +133,7 @@ internal val buildAdditionalCacheInfoPhase = konanUnitPhase(
|
||||
if (moduleDeserializer == null) {
|
||||
require(module.descriptor.isFromInteropLibrary()) { "No module deserializer for ${module.descriptor}" }
|
||||
} else {
|
||||
CacheInfoBuilder(this, moduleDeserializer).build()
|
||||
CacheInfoBuilder(this.generationState, moduleDeserializer, module).build()
|
||||
}
|
||||
},
|
||||
name = "BuildAdditionalCacheInfo",
|
||||
@@ -216,25 +214,25 @@ internal val serializerPhase = konanUnitPhase(
|
||||
)
|
||||
|
||||
internal val saveAdditionalCacheInfoPhase = konanUnitPhase(
|
||||
op = { CacheStorage(this).saveAdditionalCacheInfo() },
|
||||
op = { CacheStorage(generationState).saveAdditionalCacheInfo() },
|
||||
name = "SaveAdditionalCacheInfo",
|
||||
description = "Save additional cache info (inline functions bodies and fields of classes)"
|
||||
)
|
||||
|
||||
internal val objectFilesPhase = konanUnitPhase(
|
||||
op = { compilerOutput = BitcodeCompiler(this).makeObjectFiles(bitcodeFileName) },
|
||||
op = { this.generationState.compilerOutput = BitcodeCompiler(this.generationState).makeObjectFiles(this.generationState.bitcodeFileName) },
|
||||
name = "ObjectFiles",
|
||||
description = "Bitcode to object file"
|
||||
)
|
||||
|
||||
internal val linkerPhase = konanUnitPhase(
|
||||
op = { Linker(this).link(compilerOutput) },
|
||||
op = { Linker(this.generationState).link(this.generationState.compilerOutput) },
|
||||
name = "Linker",
|
||||
description = "Linker"
|
||||
)
|
||||
|
||||
internal val finalizeCachePhase = konanUnitPhase(
|
||||
op = { CacheStorage(this).renameOutput() },
|
||||
op = { CacheStorage(this.generationState).renameOutput() },
|
||||
name = "FinalizeCache",
|
||||
description = "Finalize cache (rename temp to the final dist)"
|
||||
)
|
||||
@@ -393,7 +391,7 @@ internal val entryPointPhase = makeCustomPhase<Context, IrModuleFragment>(
|
||||
context.irModule!!.addFile(NaiveSourceBasedFileEntryImpl("entryPointOwner"), FqName("kotlin.native.internal.abi"))
|
||||
}
|
||||
|
||||
file.addChild(makeEntryPoint(context))
|
||||
file.addChild(makeEntryPoint(context.generationState))
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
+16
-12
@@ -9,6 +9,7 @@ import llvm.LLVMStoreSizeOfType
|
||||
import org.jetbrains.kotlin.backend.common.lower.coroutines.getOrCreateFunctionWithContinuationStub
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.Llvm
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.computeFunctionName
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.toLLVMType
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.localHash
|
||||
@@ -407,31 +408,34 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context) {
|
||||
* All fields of the class instance.
|
||||
* The order respects the class hierarchy, i.e. a class [fields] contains superclass [fields] as a prefix.
|
||||
*/
|
||||
val fields: List<FieldInfo>
|
||||
get() = fieldsInternal.map { fieldInfo ->
|
||||
val mappedField = fieldInfo.irField?.let { context.mapping.lateInitFieldToNullableField[it] ?: it }
|
||||
if (mappedField == fieldInfo.irField)
|
||||
fieldInfo
|
||||
else
|
||||
mappedField!!.toFieldInfo().also { it.index = fieldInfo.index }
|
||||
}
|
||||
fun getFields(llvm: Llvm): List<FieldInfo> = getFieldsInternal(llvm).map { fieldInfo ->
|
||||
val mappedField = fieldInfo.irField?.let { context.mapping.lateInitFieldToNullableField[it] ?: it }
|
||||
if (mappedField == fieldInfo.irField)
|
||||
fieldInfo
|
||||
else
|
||||
mappedField!!.toFieldInfo().also { it.index = fieldInfo.index }
|
||||
}
|
||||
|
||||
private var fields: List<FieldInfo>? = null
|
||||
|
||||
private fun getFieldsInternal(llvm: Llvm): List<FieldInfo> {
|
||||
fields?.let { return it }
|
||||
|
||||
private val fieldsInternal: List<FieldInfo> by lazy {
|
||||
val superClass = irClass.getSuperClassNotAny()
|
||||
val superFields = if (superClass != null) context.getLayoutBuilder(superClass).fieldsInternal else emptyList()
|
||||
val superFields = if (superClass != null) context.getLayoutBuilder(superClass).getFieldsInternal(llvm) else emptyList()
|
||||
|
||||
val declaredFields = getDeclaredFields()
|
||||
val sortedDeclaredFields = if (irClass.hasAnnotation(KonanFqNames.noReorderFields))
|
||||
declaredFields
|
||||
else
|
||||
declaredFields.sortedByDescending {
|
||||
with(context.generationState.llvm) { LLVMStoreSizeOfType(runtime.targetData, it.type.toLLVMType(this)) }
|
||||
with(llvm) { LLVMStoreSizeOfType(runtime.targetData, it.type.toLLVMType(this)) }
|
||||
}
|
||||
|
||||
val superFieldsCount = 1 /* First field is ObjHeader */ + superFields.size
|
||||
sortedDeclaredFields.forEachIndexed { index, field -> field.index = superFieldsCount + index }
|
||||
|
||||
superFields + sortedDeclaredFields
|
||||
return (superFields + sortedDeclaredFields).also { fields = it }
|
||||
}
|
||||
|
||||
val associatedObjects by lazy {
|
||||
|
||||
+14
-11
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.konan.llvm.coverage.runCoveragePass
|
||||
import org.jetbrains.kotlin.backend.konan.lower.InlineClassPropertyAccessorsLowering
|
||||
import org.jetbrains.kotlin.backend.konan.lower.RedundantCoercionsCleaner
|
||||
import org.jetbrains.kotlin.backend.konan.lower.ReturnsInsertionLowering
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
||||
import org.jetbrains.kotlin.backend.konan.optimizations.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
@@ -24,14 +25,14 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
internal val createLLVMDeclarationsPhase = makeKonanModuleOpPhase(
|
||||
name = "CreateLLVMDeclarations",
|
||||
description = "Map IR declarations to LLVM",
|
||||
op = { context, _ -> context.generationState.llvmDeclarations = createLlvmDeclarations(context) }
|
||||
op = { context, _ -> context.generationState.llvmDeclarations = createLlvmDeclarations(context.generationState, context.ir.irModule) }
|
||||
)
|
||||
|
||||
internal val RTTIPhase = makeKonanModuleOpPhase(
|
||||
name = "RTTI",
|
||||
description = "RTTI generation",
|
||||
op = { context, irModule ->
|
||||
val visitor = RTTIGeneratorVisitor(context)
|
||||
val visitor = RTTIGeneratorVisitor(context.generationState)
|
||||
irModule.acceptVoid(visitor)
|
||||
visitor.dispose()
|
||||
}
|
||||
@@ -245,7 +246,9 @@ internal val codegenPhase = makeKonanModuleOpPhase(
|
||||
name = "Codegen",
|
||||
description = "Code generation",
|
||||
op = { context, irModule ->
|
||||
irModule.acceptVoid(CodeGeneratorVisitor(context, context.lifetimes))
|
||||
context.generationState.objCExport = ObjCExport(context.generationState, context.objCExportedInterface, context.objCExportCodeSpec)
|
||||
|
||||
irModule.acceptVoid(CodeGeneratorVisitor(context.generationState, context.lifetimes))
|
||||
|
||||
if (context.generationState.hasDebugInfo())
|
||||
DIFinalize(context.generationState.debugInfo.builder)
|
||||
@@ -255,25 +258,25 @@ internal val codegenPhase = makeKonanModuleOpPhase(
|
||||
internal val cStubsPhase = makeKonanModuleOpPhase(
|
||||
name = "CStubs",
|
||||
description = "C stubs compilation",
|
||||
op = { context, _ -> produceCStubs(context) }
|
||||
op = { context, _ -> produceCStubs(context.generationState) }
|
||||
)
|
||||
|
||||
internal val linkBitcodeDependenciesPhase = makeKonanModuleOpPhase(
|
||||
name = "LinkBitcodeDependencies",
|
||||
description = "Link bitcode dependencies",
|
||||
op = { context, _ -> linkBitcodeDependencies(context) }
|
||||
op = { context, _ -> linkBitcodeDependencies(context.generationState) }
|
||||
)
|
||||
|
||||
internal val checkExternalCallsPhase = makeKonanModuleOpPhase(
|
||||
name = "CheckExternalCalls",
|
||||
description = "Check external calls",
|
||||
op = { context, _ -> checkLlvmModuleExternalCalls(context) }
|
||||
op = { context, _ -> checkLlvmModuleExternalCalls(context.generationState) }
|
||||
)
|
||||
|
||||
internal val rewriteExternalCallsCheckerGlobals = makeKonanModuleOpPhase(
|
||||
name = "RewriteExternalCallsCheckerGlobals",
|
||||
description = "Rewrite globals for external calls checker after optimizer run",
|
||||
op = { context, _ -> addFunctionsListSymbolForChecker(context) }
|
||||
op = { context, _ -> addFunctionsListSymbolForChecker(context.generationState) }
|
||||
)
|
||||
|
||||
|
||||
@@ -282,7 +285,7 @@ internal val bitcodeOptimizationPhase = makeKonanModuleOpPhase(
|
||||
name = "BitcodeOptimization",
|
||||
description = "Optimize bitcode",
|
||||
op = { context, _ ->
|
||||
val config = createLTOFinalPipelineConfig(context)
|
||||
val config = createLTOFinalPipelineConfig(context.generationState)
|
||||
LlvmOptimizationPipeline(config, context.generationState.llvm.module, context).use {
|
||||
it.run()
|
||||
}
|
||||
@@ -292,13 +295,13 @@ internal val bitcodeOptimizationPhase = makeKonanModuleOpPhase(
|
||||
internal val coveragePhase = makeKonanModuleOpPhase(
|
||||
name = "Coverage",
|
||||
description = "Produce coverage information",
|
||||
op = { context, _ -> runCoveragePass(context) }
|
||||
op = { context, _ -> runCoveragePass(context.generationState) }
|
||||
)
|
||||
|
||||
internal val optimizeTLSDataLoadsPhase = makeKonanModuleOpPhase(
|
||||
name = "OptimizeTLSDataLoads",
|
||||
description = "Optimize multiple loads of thread data",
|
||||
op = { context, _ -> removeMultipleThreadDataLoads(context) }
|
||||
op = { context, _ -> removeMultipleThreadDataLoads(context.generationState) }
|
||||
)
|
||||
|
||||
internal val produceOutputPhase = namedUnitPhase(
|
||||
@@ -306,7 +309,7 @@ internal val produceOutputPhase = namedUnitPhase(
|
||||
description = "Produce output",
|
||||
lower = object : CompilerPhase<Context, Unit, Unit> {
|
||||
override fun invoke(phaseConfig: PhaseConfigurationService, phaserState: PhaserState<Unit>, context: Context, input: Unit) {
|
||||
produceOutput(context)
|
||||
produceOutput(context.generationState)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
+8
-8
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.konan.ForeignExceptionMode
|
||||
|
||||
|
||||
internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
internal class CodeGenerator(override val generationState: NativeGenerationState) : ContextUtils {
|
||||
fun llvmFunction(function: IrFunction): LlvmCallable =
|
||||
llvmFunctionOrNull(function)
|
||||
?: error("no function ${function.name} in ${function.file.fqName}")
|
||||
@@ -32,7 +32,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
fun llvmFunctionOrNull(function: IrFunction): LlvmCallable? =
|
||||
function.llvmFunctionOrNull
|
||||
|
||||
val llvmDeclarations = context.generationState.llvmDeclarations
|
||||
val llvmDeclarations = generationState.llvmDeclarations
|
||||
val intPtrType = LLVMIntPtrTypeInContext(llvm.llvmContext, llvmTargetData)!!
|
||||
internal val immOneIntPtrType = LLVMConstInt(intPtrType, 1, 1)!!
|
||||
internal val immThreeIntPtrType = LLVMConstInt(intPtrType, 3, 1)!!
|
||||
@@ -350,7 +350,7 @@ internal class StackLocalsManagerImpl(
|
||||
call(llvm.zeroArrayRefsFunction, listOf(stackLocal.objHeaderPtr))
|
||||
} else {
|
||||
val type = llvmDeclarations.forClass(stackLocal.irClass).bodyType
|
||||
for (field in context.getLayoutBuilder(stackLocal.irClass).fields) {
|
||||
for (field in context.getLayoutBuilder(stackLocal.irClass).getFields(llvm)) {
|
||||
val fieldIndex = field.index
|
||||
val fieldType = LLVMStructGetTypeAtIndex(type, fieldIndex)!!
|
||||
|
||||
@@ -427,8 +427,8 @@ internal abstract class FunctionGenerationContext(
|
||||
irFunction = builder.irFunction
|
||||
)
|
||||
|
||||
override val context = codegen.context
|
||||
val llvmDeclarations = codegen.llvmDeclarations
|
||||
override val generationState = codegen.generationState
|
||||
val llvmDeclarations = generationState.llvmDeclarations
|
||||
val vars = VariableManager(this)
|
||||
private val basicBlockToLastLocation = mutableMapOf<LLVMBasicBlockRef, LocationInfoRange>()
|
||||
|
||||
@@ -496,7 +496,7 @@ internal abstract class FunctionGenerationContext(
|
||||
init {
|
||||
irFunction?.let {
|
||||
if (!irFunction.isExported()) {
|
||||
if (!context.config.producePerFileCache || irFunction !in context.generationState.calledFromExportedInlineFunctions)
|
||||
if (!context.config.producePerFileCache || irFunction !in generationState.calledFromExportedInlineFunctions)
|
||||
LLVMSetLinkage(function, LLVMLinkage.LLVMInternalLinkage) // (Cannot do this before the function body is created)
|
||||
}
|
||||
}
|
||||
@@ -544,7 +544,7 @@ internal abstract class FunctionGenerationContext(
|
||||
val slotAddress = LLVMBuildAlloca(builder, type, name)!!
|
||||
variableLocation?.let {
|
||||
DIInsertDeclaration(
|
||||
builder = codegen.context.generationState.debugInfo.builder,
|
||||
builder = generationState.debugInfo.builder,
|
||||
value = slotAddress,
|
||||
localVariable = it.localVariable,
|
||||
location = it.location,
|
||||
@@ -1354,7 +1354,7 @@ internal abstract class FunctionGenerationContext(
|
||||
val expr = longArrayOf(DwarfOp.DW_OP_plus_uconst.value,
|
||||
runtime.pointerSize * slot.toLong()).toCValues()
|
||||
DIInsertDeclaration(
|
||||
builder = codegen.context.generationState.debugInfo.builder,
|
||||
builder = generationState.debugInfo.builder,
|
||||
value = slots,
|
||||
localVariable = variable.localVariable,
|
||||
location = variable.location,
|
||||
|
||||
+17
-13
@@ -136,10 +136,13 @@ internal sealed class Lifetime(val slotType: SlotType) {
|
||||
* Provides utility methods to the implementer.
|
||||
*/
|
||||
internal interface ContextUtils : RuntimeAware {
|
||||
val generationState: NativeGenerationState
|
||||
|
||||
val context: Context
|
||||
get() = generationState.context
|
||||
|
||||
override val runtime: Runtime
|
||||
get() = context.generationState.llvm.runtime
|
||||
get() = generationState.llvm.runtime
|
||||
|
||||
val argumentAbiInfo: TargetAbiInfo
|
||||
get() = context.targetAbiInfo
|
||||
@@ -153,17 +156,17 @@ internal interface ContextUtils : RuntimeAware {
|
||||
get() = runtime.targetData
|
||||
|
||||
val llvm: Llvm
|
||||
get() = context.generationState.llvm
|
||||
get() = generationState.llvm
|
||||
|
||||
val staticData: KotlinStaticData
|
||||
get() = context.generationState.llvm.staticData
|
||||
get() = generationState.llvm.staticData
|
||||
|
||||
/**
|
||||
* TODO: maybe it'd be better to replace with [IrDeclaration::isEffectivelyExternal()],
|
||||
* or just drop all [else] branches of corresponding conditionals.
|
||||
*/
|
||||
fun isExternal(declaration: IrDeclaration): Boolean {
|
||||
return !context.generationState.llvmModuleSpecification.containsDeclaration(declaration)
|
||||
return !generationState.llvmModuleSpecification.containsDeclaration(declaration)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,7 +195,7 @@ internal interface ContextUtils : RuntimeAware {
|
||||
llvm.externalFunction(proto)
|
||||
}
|
||||
} else {
|
||||
context.generationState.llvmDeclarations.forFunctionOrNull(this)
|
||||
generationState.llvmDeclarations.forFunctionOrNull(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +220,7 @@ internal interface ContextUtils : RuntimeAware {
|
||||
constPointer(importGlobal(typeInfoSymbolName, runtime.typeInfoType,
|
||||
origin = this.llvmSymbolOrigin))
|
||||
} else {
|
||||
context.generationState.llvmDeclarations.forClass(this).typeInfo
|
||||
generationState.llvmDeclarations.forClass(this).typeInfo
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,8 +297,9 @@ internal class ConstFloat64(llvm: Llvm, val value: Double) : ConstValue {
|
||||
}
|
||||
|
||||
@Suppress("FunctionName", "PropertyName", "PrivatePropertyName")
|
||||
internal class Llvm(private val context: Context, val module: LLVMModuleRef) : RuntimeAware {
|
||||
val llvmContext = context.generationState.llvmContext
|
||||
internal class Llvm(private val generationState: NativeGenerationState, val module: LLVMModuleRef) : RuntimeAware {
|
||||
private val context = generationState.context
|
||||
val llvmContext = generationState.llvmContext
|
||||
|
||||
private fun importFunction(name: String, otherModule: LLVMModuleRef): LlvmCallable {
|
||||
if (LLVMGetNamedFunction(module, name) != null) {
|
||||
@@ -357,7 +361,7 @@ internal class Llvm(private val context: Context, val module: LLVMModuleRef) : R
|
||||
}
|
||||
}
|
||||
|
||||
val imports get() = context.generationState.llvmImports
|
||||
val imports get() = generationState.llvmImports
|
||||
|
||||
class ImportsImpl(private val context: Context) : LlvmImports {
|
||||
|
||||
@@ -450,11 +454,11 @@ internal class Llvm(private val context: Context, val module: LLVMModuleRef) : R
|
||||
}
|
||||
|
||||
private fun shouldContainBitcode(library: KonanLibrary): Boolean {
|
||||
if (!context.generationState.llvmModuleSpecification.containsLibrary(library)) {
|
||||
if (!generationState.llvmModuleSpecification.containsLibrary(library)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (!context.generationState.llvmModuleSpecification.isFinal) {
|
||||
if (!generationState.llvmModuleSpecification.isFinal) {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -464,11 +468,11 @@ internal class Llvm(private val context: Context, val module: LLVMModuleRef) : R
|
||||
|
||||
val additionalProducedBitcodeFiles = mutableListOf<String>()
|
||||
|
||||
val staticData = KotlinStaticData(context, this, module)
|
||||
val staticData = KotlinStaticData(generationState, this, module)
|
||||
|
||||
private val target = context.config.target
|
||||
|
||||
override val runtime get() = context.generationState.runtime
|
||||
override val runtime get() = generationState.runtime
|
||||
|
||||
val targetTriple = runtime.target
|
||||
|
||||
|
||||
+6
-6
@@ -57,7 +57,7 @@ internal object DWARF {
|
||||
|
||||
fun KonanConfig.debugInfoVersion(): Int = configuration[KonanConfigKeys.DEBUG_INFO_VERSION] ?: 1
|
||||
|
||||
internal class DebugInfo(override val context: Context) : ContextUtils {
|
||||
internal class DebugInfo(override val generationState: NativeGenerationState) : ContextUtils {
|
||||
private val config = context.config
|
||||
|
||||
val builder: DIBuilderRef = LLVMCreateDIBuilder(llvm.module)!!
|
||||
@@ -66,7 +66,7 @@ internal class DebugInfo(override val context: Context) : ContextUtils {
|
||||
val objHeaderPointerType: DITypeOpaqueRef
|
||||
|
||||
init {
|
||||
val path = context.generationState.outputFile.toFileAndFolder(config)
|
||||
val path = generationState.outputFile.toFileAndFolder(config)
|
||||
compilationUnit = DICreateCompilationUnit(
|
||||
builder = builder,
|
||||
lang = DWARF.language(config),
|
||||
@@ -266,12 +266,12 @@ internal fun String?.toFileAndFolder(config: KonanConfig): FileAndFolder {
|
||||
|
||||
internal fun alignTo(value: Long, align: Long): Long = (value + align - 1) / align * align
|
||||
|
||||
internal fun setupBridgeDebugInfo(context: Context, function: LLVMValueRef): LocationInfo? {
|
||||
if (!context.shouldContainLocationDebugInfo()) {
|
||||
internal fun setupBridgeDebugInfo(generationState: NativeGenerationState, function: LLVMValueRef): LocationInfo? {
|
||||
if (!generationState.context.shouldContainLocationDebugInfo()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val debugInfo = context.generationState.debugInfo
|
||||
val debugInfo = generationState.debugInfo
|
||||
val file = debugInfo.compilerGeneratedFile
|
||||
|
||||
// TODO: can we share the scope among all bridges?
|
||||
@@ -282,7 +282,7 @@ internal fun setupBridgeDebugInfo(context: Context, function: LLVMValueRef): Loc
|
||||
linkageName = function.name,
|
||||
file = file,
|
||||
lineNo = 0,
|
||||
type = debugInfo.subroutineType(context.generationState.runtime.targetData, emptyList()), // TODO: use proper type.
|
||||
type = debugInfo.subroutineType(generationState.runtime.targetData, emptyList()), // TODO: use proper type.
|
||||
isLocal = 0,
|
||||
isDefinition = 1,
|
||||
scopeLine = 0
|
||||
|
||||
+36
-35
@@ -81,10 +81,10 @@ internal fun IrField.isGlobalNonPrimitive(context: Context) = when {
|
||||
internal fun IrField.shouldBeFrozen(context: Context): Boolean =
|
||||
this.storageKind(context) == FieldStorageKind.SHARED_FROZEN
|
||||
|
||||
internal class RTTIGeneratorVisitor(context: Context) : IrElementVisitorVoid {
|
||||
val generator = RTTIGenerator(context)
|
||||
internal class RTTIGeneratorVisitor(generationState: NativeGenerationState) : IrElementVisitorVoid {
|
||||
val generator = RTTIGenerator(generationState)
|
||||
|
||||
val kotlinObjCClassInfoGenerator = KotlinObjCClassInfoGenerator(context)
|
||||
val kotlinObjCClassInfoGenerator = KotlinObjCClassInfoGenerator(generationState)
|
||||
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
@@ -191,12 +191,13 @@ private interface CodeContext {
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrElement, Lifetime>) : IrElementVisitorVoid {
|
||||
private val llvm = context.generationState.llvm
|
||||
internal class CodeGeneratorVisitor(val generationState: NativeGenerationState, val lifetimes: Map<IrElement, Lifetime>) : IrElementVisitorVoid {
|
||||
private val context = generationState.context
|
||||
private val llvm = generationState.llvm
|
||||
private val debugInfo: DebugInfo
|
||||
get() = context.generationState.debugInfo
|
||||
get() = generationState.debugInfo
|
||||
|
||||
val codegen = CodeGenerator(context)
|
||||
val codegen = CodeGenerator(generationState)
|
||||
|
||||
// TODO: consider eliminating mutable state
|
||||
private var currentCodeContext: CodeContext = TopLevelCodeContext
|
||||
@@ -330,12 +331,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
private fun FunctionGenerationContext.initThreadLocalField(irField: IrField) {
|
||||
val initializer = irField.initializer ?: return
|
||||
val address = context.generationState.llvmDeclarations.forStaticField(irField).storageAddressAccess.getAddress(this)
|
||||
val address = generationState.llvmDeclarations.forStaticField(irField).storageAddressAccess.getAddress(this)
|
||||
storeAny(evaluateExpression(initializer.expression), address, false)
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.initGlobalField(irField: IrField) {
|
||||
val address = context.generationState.llvmDeclarations.forStaticField(irField).storageAddressAccess.getAddress(this)
|
||||
val address = generationState.llvmDeclarations.forStaticField(irField).storageAddressAccess.getAddress(this)
|
||||
val initialValue = if (irField.hasNonConstInitializer) {
|
||||
val initialization = evaluateExpression(irField.initializer!!.expression)
|
||||
if (irField.shouldBeFrozen(context))
|
||||
@@ -409,18 +410,18 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
override fun visitModuleFragment(declaration: IrModuleFragment) {
|
||||
context.log{"visitModule : ${ir2string(declaration)}"}
|
||||
|
||||
context.coverage.collectRegions(declaration)
|
||||
generationState.coverage.collectRegions(declaration)
|
||||
|
||||
initializeCachedBoxes(context)
|
||||
initializeCachedBoxes(generationState)
|
||||
declaration.acceptChildrenVoid(this)
|
||||
|
||||
runAndProcessInitializers(null) {
|
||||
// Note: it is here because it also generates some bitcode.
|
||||
context.objCExport.generate(codegen)
|
||||
generationState.objCExport.generate(codegen)
|
||||
|
||||
codegen.objCDataGenerator?.finishModule()
|
||||
|
||||
context.coverage.writeRegionInfo()
|
||||
generationState.coverage.writeRegionInfo()
|
||||
overrideRuntimeGlobals()
|
||||
appendLlvmUsed("llvm.used", llvm.usedFunctions + llvm.usedGlobals)
|
||||
appendLlvmUsed("llvm.compiler.used", llvm.compilerUsedGlobals)
|
||||
@@ -505,7 +506,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
// Only if a subject for memory management.
|
||||
.forEach { irField ->
|
||||
if (irField.type.binaryTypeIsReference() && irField.storageKind(context) != FieldStorageKind.THREAD_LOCAL) {
|
||||
val address = context.generationState.llvmDeclarations.forStaticField(irField).storageAddressAccess.getAddress(
|
||||
val address = generationState.llvmDeclarations.forStaticField(irField).storageAddressAccess.getAddress(
|
||||
functionGenerationContext
|
||||
)
|
||||
storeHeapRef(codegen.kNullObjHeaderPtr, address)
|
||||
@@ -695,7 +696,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
this(functionGenerationContext, null, llvmFunction)
|
||||
|
||||
val coverageInstrumentation: LLVMCoverageInstrumentation? =
|
||||
context.coverage.tryGetInstrumentation(declaration) { function, args -> functionGenerationContext.call(function, args) }
|
||||
generationState.coverage.tryGetInstrumentation(declaration) { function, args -> functionGenerationContext.call(function, args) }
|
||||
|
||||
override fun genReturn(target: IrSymbolOwner, value: LLVMValueRef?) {
|
||||
if (declaration == null || target == declaration) {
|
||||
@@ -886,7 +887,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
debugFieldDeclaration(declaration)
|
||||
if (context.needGlobalInit(declaration)) {
|
||||
val type = declaration.type.toLLVMType(llvm)
|
||||
val globalPropertyAccess = context.generationState.llvmDeclarations.forStaticField(declaration).storageAddressAccess
|
||||
val globalPropertyAccess = generationState.llvmDeclarations.forStaticField(declaration).storageAddressAccess
|
||||
val initializer = declaration.initializer?.expression
|
||||
val globalProperty = (globalPropertyAccess as? GlobalAddressAccess)?.getAddress(null)
|
||||
if (globalProperty != null) {
|
||||
@@ -1669,7 +1670,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
if (context.config.threadsAreAllowed && value.symbol.owner.isGlobalNonPrimitive(context)) {
|
||||
functionGenerationContext.checkGlobalsAccessible(currentCodeContext.exceptionHandler)
|
||||
}
|
||||
val ptr = context.generationState.llvmDeclarations.forStaticField(value.symbol.owner).storageAddressAccess.getAddress(
|
||||
val ptr = generationState.llvmDeclarations.forStaticField(value.symbol.owner).storageAddressAccess.getAddress(
|
||||
functionGenerationContext
|
||||
)
|
||||
functionGenerationContext.loadSlot(ptr, !value.symbol.owner.isFinal, resultSlot)
|
||||
@@ -1738,7 +1739,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
functionGenerationContext.storeAny(valueToAssign, fieldPtrOfClass(thisPtr, value.symbol.owner), false)
|
||||
} else {
|
||||
assert(value.receiver == null)
|
||||
val globalAddress = context.generationState.llvmDeclarations.forStaticField(value.symbol.owner).storageAddressAccess.getAddress(
|
||||
val globalAddress = generationState.llvmDeclarations.forStaticField(value.symbol.owner).storageAddressAccess.getAddress(
|
||||
functionGenerationContext
|
||||
)
|
||||
if (context.config.threadsAreAllowed && value.symbol.owner.storageKind(context) == FieldStorageKind.GLOBAL)
|
||||
@@ -1759,7 +1760,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
private fun fieldPtrOfClass(thisPtr: LLVMValueRef, value: IrField): LLVMValueRef {
|
||||
val fieldInfo = context.generationState.llvmDeclarations.forField(value)
|
||||
val fieldInfo = generationState.llvmDeclarations.forField(value)
|
||||
|
||||
val typePtr = pointerType(fieldInfo.classBodyType)
|
||||
|
||||
@@ -1822,7 +1823,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
require(value.type.toLLVMType(llvm) == codegen.kObjHeaderPtr) {
|
||||
"Can't wrap ${value.value.kind.asString} constant to type ${value.type.render()}"
|
||||
}
|
||||
value.toBoxCacheValue(context) ?: llvm.staticData.createConstKotlinObject(
|
||||
value.toBoxCacheValue(generationState) ?: llvm.staticData.createConstKotlinObject(
|
||||
constructedType.getClass()!!,
|
||||
evaluateConst(value.value)
|
||||
)
|
||||
@@ -1854,7 +1855,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val fields = if (value.constructor.owner.isConstantConstructorIntrinsic) {
|
||||
intrinsicGenerator.evaluateConstantConstructorFields(value, value.valueArguments.map { evaluateConstantValue(it) })
|
||||
} else {
|
||||
val fields = context.getLayoutBuilder(constructedClass).fields
|
||||
val fields = context.getLayoutBuilder(constructedClass).getFields(llvm)
|
||||
val valueParameters = value.constructor.owner.valueParameters.associateBy { it.name.toString() }
|
||||
fields.map { field ->
|
||||
if (field.isConst) {
|
||||
@@ -1905,7 +1906,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
//-------------------------------------------------------------------------//
|
||||
private inner class ReturnableBlockScope(val returnableBlock: IrReturnableBlock, val resultSlot: LLVMValueRef?) :
|
||||
FileScope(returnableBlock.inlineFunctionSymbol?.owner?.let {
|
||||
context.generationState.loweredInlineFunctions[it]?.irFile ?: it.fileOrNull
|
||||
generationState.loweredInlineFunctions[it]?.irFile ?: it.fileOrNull
|
||||
}
|
||||
?: (currentCodeContext.fileScope() as? FileScope)?.file
|
||||
?: error("returnable block should belong to current file at least")) {
|
||||
@@ -1914,13 +1915,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
var resultPhi : LLVMValueRef? = null
|
||||
private val functionScope by lazy {
|
||||
returnableBlock.inlineFunctionSymbol?.owner?.let {
|
||||
it.scope(file().fileEntry.line(context.generationState.loweredInlineFunctions[it]?.startOffset ?: it.startOffset))
|
||||
it.scope(file().fileEntry.line(generationState.loweredInlineFunctions[it]?.startOffset ?: it.startOffset))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getExit(): LLVMBasicBlockRef {
|
||||
val location = returnableBlock.inlineFunctionSymbol?.owner?.let {
|
||||
location(context.generationState.loweredInlineFunctions[it]?.endOffset ?: it.endOffset)
|
||||
location(generationState.loweredInlineFunctions[it]?.endOffset ?: it.endOffset)
|
||||
} ?: returnableBlock.statements.lastOrNull()?.let {
|
||||
location(it.endOffset)
|
||||
}
|
||||
@@ -2670,7 +2671,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
// Globals set this way cannot be const, but are overridable when producing final executable.
|
||||
private fun overrideRuntimeGlobal(name: String, value: ConstValue) {
|
||||
// TODO: A similar mechanism is used in `ObjCExportCodeGenerator`. Consider merging them.
|
||||
if (context.generationState.llvmModuleSpecification.importsKotlinDeclarationsFromOtherSharedLibraries()) {
|
||||
if (generationState.llvmModuleSpecification.importsKotlinDeclarationsFromOtherSharedLibraries()) {
|
||||
// When some dynamic caches are used, we consider that stdlib is in the dynamic cache as well.
|
||||
// Runtime is linked into stdlib module only, so import runtime global from it.
|
||||
val global = codegen.importGlobal(name, value.llvmType, context.standardLlvmSymbolsOrigin)
|
||||
@@ -2683,11 +2684,11 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
llvm.otherStaticInitializers += initializer
|
||||
} else {
|
||||
context.generationState.llvmImports.add(context.standardLlvmSymbolsOrigin)
|
||||
generationState.llvmImports.add(context.standardLlvmSymbolsOrigin)
|
||||
// Define a strong runtime global. It'll overrule a weak global defined in a statically linked runtime.
|
||||
val global = llvm.staticData.placeGlobal(name, value, true)
|
||||
|
||||
if (context.generationState.llvmModuleSpecification.importsKotlinDeclarationsFromOtherObjectFiles()) {
|
||||
if (generationState.llvmModuleSpecification.importsKotlinDeclarationsFromOtherObjectFiles()) {
|
||||
llvm.usedGlobals += global.llvmGlobal
|
||||
LLVMSetVisibility(global.llvmGlobal, LLVMVisibility.LLVMHiddenVisibility)
|
||||
}
|
||||
@@ -2782,14 +2783,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
val ctorName = when {
|
||||
// TODO: Try to not use moduleId.
|
||||
library == null -> (if (context.config.produce.isCache) context.generationState.outputFiles.cacheFileName else context.config.moduleId).moduleConstructorName
|
||||
library == null -> (if (context.config.produce.isCache) generationState.outputFiles.cacheFileName else context.config.moduleId).moduleConstructorName
|
||||
library == context.config.libraryToCache?.klib
|
||||
&& context.config.producePerFileCache ->
|
||||
fileCtorName(library.uniqueName, context.generationState.outputFiles.perFileCacheFileName)
|
||||
fileCtorName(library.uniqueName, generationState.outputFiles.perFileCacheFileName)
|
||||
else -> library.moduleConstructorName
|
||||
}
|
||||
|
||||
if (library == null || context.generationState.llvmModuleSpecification.containsLibrary(library)) {
|
||||
if (library == null || generationState.llvmModuleSpecification.containsLibrary(library)) {
|
||||
val otherInitializers = llvm.otherStaticInitializers.takeIf { library == null }.orEmpty()
|
||||
|
||||
val ctorFunction = addCtorFunction(ctorName)
|
||||
@@ -2906,10 +2907,9 @@ internal class LocationInfo(val scope: DIScopeOpaqueRef,
|
||||
val column: Int,
|
||||
val inlinedAt: LocationInfo? = null)
|
||||
|
||||
internal fun Context.generateRuntimeConstantsModule() : LLVMModuleRef {
|
||||
val llvm = generationState.llvm
|
||||
val llvmModule = LLVMModuleCreateWithNameInContext("constants", generationState.llvmContext)!!
|
||||
LLVMSetDataLayout(llvmModule, generationState.runtime.dataLayout)
|
||||
internal fun NativeGenerationState.generateRuntimeConstantsModule() : LLVMModuleRef {
|
||||
val llvmModule = LLVMModuleCreateWithNameInContext("constants", llvmContext)!!
|
||||
LLVMSetDataLayout(llvmModule, runtime.dataLayout)
|
||||
val static = StaticData(llvmModule, llvm)
|
||||
|
||||
fun setRuntimeConstGlobal(name: String, value: ConstValue) {
|
||||
@@ -2918,7 +2918,8 @@ internal fun Context.generateRuntimeConstantsModule() : LLVMModuleRef {
|
||||
global.setLinkage(LLVMLinkage.LLVMExternalLinkage)
|
||||
}
|
||||
|
||||
setRuntimeConstGlobal("Kotlin_needDebugInfo", llvm.constInt32(if (shouldContainDebugInfo()) 1 else 0))
|
||||
val config = context.config
|
||||
setRuntimeConstGlobal("Kotlin_needDebugInfo", llvm.constInt32(if (context.shouldContainDebugInfo()) 1 else 0))
|
||||
setRuntimeConstGlobal("Kotlin_runtimeAssertsMode", llvm.constInt32(config.runtimeAssertsMode.value))
|
||||
val runtimeLogs = config.runtimeLogs?.let {
|
||||
static.cStringLiteral(it)
|
||||
|
||||
+3
-3
@@ -16,11 +16,11 @@ import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
|
||||
internal class KotlinObjCClassInfoGenerator(override val context: Context) : ContextUtils {
|
||||
internal class KotlinObjCClassInfoGenerator(override val generationState: NativeGenerationState) : ContextUtils {
|
||||
fun generate(irClass: IrClass) {
|
||||
assert(irClass.isFinalClass)
|
||||
|
||||
val objCLLvmDeclarations = context.generationState.llvmDeclarations.forClass(irClass).objCDeclarations!!
|
||||
val objCLLvmDeclarations = generationState.llvmDeclarations.forClass(irClass).objCDeclarations!!
|
||||
|
||||
val instanceMethods = generateInstanceMethodDescs(irClass)
|
||||
|
||||
@@ -148,7 +148,7 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
|
||||
return constPointer(function)
|
||||
}
|
||||
|
||||
private val codegen = CodeGenerator(context)
|
||||
private val codegen = CodeGenerator(generationState)
|
||||
|
||||
companion object {
|
||||
const val createdClassFieldIndex = 11
|
||||
|
||||
+3
-2
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
||||
import kotlinx.cinterop.cValuesOf
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
import org.jetbrains.kotlin.backend.konan.ir.llvmSymbolOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
@@ -16,7 +17,7 @@ private fun ConstPointer.add(index: LLVMValueRef): ConstPointer {
|
||||
return constPointer(LLVMConstGEP(llvm, cValuesOf(index), 1)!!)
|
||||
}
|
||||
|
||||
internal class KotlinStaticData(override val context: Context, override val llvm: Llvm, module: LLVMModuleRef) : ContextUtils, StaticData(module, llvm) {
|
||||
internal class KotlinStaticData(override val generationState: NativeGenerationState, override val llvm: Llvm, module: LLVMModuleRef) : ContextUtils, StaticData(module, llvm) {
|
||||
private val stringLiterals = mutableMapOf<String, ConstPointer>()
|
||||
|
||||
// Must match OBJECT_TAG_PERMANENT_CONTAINER in C++.
|
||||
@@ -107,7 +108,7 @@ internal class KotlinStaticData(override val context: Context, override val llvm
|
||||
kind.llvmName, runtime.objHeaderType, origin = descriptor.llvmSymbolOrigin
|
||||
))
|
||||
} else {
|
||||
context.generationState.llvmDeclarations.forUnique(kind).pointer
|
||||
generationState.llvmDeclarations.forUnique(kind).pointer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -22,9 +22,9 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import kotlin.collections.set
|
||||
|
||||
internal fun createLlvmDeclarations(context: Context): LlvmDeclarations {
|
||||
val generator = DeclarationsGeneratorVisitor(context)
|
||||
context.ir.irModule.acceptChildrenVoid(generator)
|
||||
internal fun createLlvmDeclarations(generationState: NativeGenerationState, irModule: IrModuleFragment): LlvmDeclarations {
|
||||
val generator = DeclarationsGeneratorVisitor(generationState)
|
||||
irModule.acceptChildrenVoid(generator)
|
||||
return LlvmDeclarations(generator.uniques)
|
||||
}
|
||||
|
||||
@@ -89,8 +89,8 @@ private fun ContextUtils.createClassBodyType(name: String, fields: List<ClassLay
|
||||
return classType
|
||||
}
|
||||
|
||||
private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
IrElementVisitorVoid, ContextUtils {
|
||||
private class DeclarationsGeneratorVisitor(override val generationState: NativeGenerationState)
|
||||
: IrElementVisitorVoid, ContextUtils {
|
||||
|
||||
val uniques = mutableMapOf<UniqueKind, UniqueLlvmDeclarations>()
|
||||
|
||||
@@ -156,7 +156,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
private fun createClassDeclarations(declaration: IrClass): ClassLlvmDeclarations {
|
||||
val internalName = qualifyInternalName(declaration)
|
||||
|
||||
val fields = context.getLayoutBuilder(declaration).fields
|
||||
val fields = context.getLayoutBuilder(declaration).getFields(llvm)
|
||||
val bodyType = createClassBodyType("kclassbody:$internalName", fields)
|
||||
|
||||
val typeInfoPtr: ConstPointer
|
||||
@@ -168,7 +168,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
if (!context.config.producePerFileCache)
|
||||
"${MangleConstant.CLASS_PREFIX}:$internalName"
|
||||
else {
|
||||
val containerName = (context.generationState.cacheDeserializationStrategy as CacheDeserializationStrategy.SingleFile).filePath
|
||||
val containerName = (generationState.cacheDeserializationStrategy as CacheDeserializationStrategy.SingleFile).filePath
|
||||
declaration.computePrivateTypeInfoSymbolName(containerName)
|
||||
}
|
||||
}
|
||||
@@ -196,7 +196,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
throw IllegalArgumentException("Global '$typeInfoSymbolName' already exists")
|
||||
}
|
||||
} else {
|
||||
if (!context.config.producePerFileCache || declaration !in context.generationState.constructedFromExportedInlineFunctions)
|
||||
if (!context.config.producePerFileCache || declaration !in generationState.constructedFromExportedInlineFunctions)
|
||||
LLVMSetLinkage(llvmTypeInfoPtr, LLVMLinkage.LLVMInternalLinkage)
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
if (!containingClass.requiresRtti()) return
|
||||
val classDeclarations = (containingClass.metadata as? CodegenClassMetadata)?.llvm
|
||||
?: error(containingClass.descriptor.toString())
|
||||
val allFields = context.getLayoutBuilder(containingClass).fields
|
||||
val allFields = context.getLayoutBuilder(containingClass).getFields(llvm)
|
||||
val fieldInfo = allFields.firstOrNull { it.irField == declaration } ?: error("Field ${declaration.render()} is not found")
|
||||
declaration.metadata = CodegenInstanceFieldMetadata(
|
||||
declaration.metadata?.name,
|
||||
@@ -341,7 +341,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
"${MangleConstant.FUN_PREFIX}:${qualifyInternalName(declaration)}"
|
||||
else {
|
||||
val containerName = declaration.parentClassOrNull?.fqNameForIrSerialization?.asString()
|
||||
?: (context.generationState.cacheDeserializationStrategy as CacheDeserializationStrategy.SingleFile).filePath
|
||||
?: (generationState.cacheDeserializationStrategy as CacheDeserializationStrategy.SingleFile).filePath
|
||||
declaration.computePrivateSymbolName(containerName)
|
||||
}
|
||||
}
|
||||
|
||||
+12
-11
@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
internal class RTTIGenerator(override val generationState: NativeGenerationState) : ContextUtils {
|
||||
|
||||
private val acyclicCache = mutableMapOf<IrType, Boolean>()
|
||||
private val safeAcyclicFieldTypes = setOf(
|
||||
@@ -26,7 +26,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
context.irBuiltIns.booleanClass, context.irBuiltIns.charClass,
|
||||
context.irBuiltIns.byteClass, context.irBuiltIns.shortClass, context.irBuiltIns.intClass,
|
||||
context.irBuiltIns.longClass,
|
||||
context.irBuiltIns.floatClass,context.irBuiltIns.doubleClass) +
|
||||
context.irBuiltIns.floatClass, context.irBuiltIns.doubleClass) +
|
||||
context.ir.symbols.primitiveTypesToPrimitiveArrays.values +
|
||||
context.ir.symbols.unsignedTypesToUnsignedArrays.values
|
||||
|
||||
@@ -45,7 +45,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
private fun checkAcyclicClass(irClass: IrClass): Boolean = when {
|
||||
irClass.symbol == context.ir.symbols.array -> false
|
||||
irClass.isArray -> true
|
||||
context.getLayoutBuilder(irClass).fields.all { checkAcyclicFieldType(it.type) } -> true
|
||||
context.getLayoutBuilder(irClass).getFields(llvm).all { checkAcyclicFieldType(it.type) } -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
val className = irClass.fqNameForIrSerialization
|
||||
|
||||
val llvmDeclarations = context.generationState.llvmDeclarations.forClass(irClass)
|
||||
val llvmDeclarations = generationState.llvmDeclarations.forClass(irClass)
|
||||
|
||||
val bodyType = llvmDeclarations.bodyType
|
||||
|
||||
@@ -422,7 +422,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
return NullPointer(runtime.extendedTypeInfoType)
|
||||
|
||||
val className = irClass.fqNameForIrSerialization.toString()
|
||||
val llvmDeclarations = context.generationState.llvmDeclarations.forClass(irClass)
|
||||
val llvmDeclarations = generationState.llvmDeclarations.forClass(irClass)
|
||||
val bodyType = llvmDeclarations.bodyType
|
||||
val elementType = getElementType(irClass)
|
||||
|
||||
@@ -435,7 +435,8 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
debugOperationsSize, debugOperations)
|
||||
} else {
|
||||
class FieldRecord(val offset: Int, val type: Int, val name: String)
|
||||
val fields = context.getLayoutBuilder(irClass).fields.map {
|
||||
|
||||
val fields = context.getLayoutBuilder(irClass).getFields(llvm).map {
|
||||
FieldRecord(
|
||||
LLVMOffsetOfElement(llvmTargetData, bodyType, it.index).toInt(),
|
||||
mapRuntimeType(LLVMStructGetTypeAtIndex(bodyType, it.index)!!),
|
||||
@@ -450,8 +451,8 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
Struct(runtime.extendedTypeInfoType, llvm.constInt32(fields.size), offsetsPtr, typesPtr, namesPtr,
|
||||
debugOperationsSize, debugOperations)
|
||||
|
||||
}
|
||||
|
||||
val result = staticData.placeGlobal("", value)
|
||||
result.setConstant(true)
|
||||
return result.pointer
|
||||
@@ -465,7 +466,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
val associatedObjectTableRecords = associatedObjects.map { (key, value) ->
|
||||
val function = context.getObjectClassInstanceFunction(value)
|
||||
val llvmFunction = context.generationState.llvmDeclarations.forFunction(function).llvmValue
|
||||
val llvmFunction = generationState.llvmDeclarations.forFunction(function).llvmValue
|
||||
|
||||
Struct(runtime.associatedObjectTableRecordType, key.typeInfoPtr, constPointer(llvmFunction))
|
||||
}
|
||||
@@ -596,16 +597,16 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
when {
|
||||
irClass.isAnonymousObject -> {
|
||||
relativeName = context.generationState.getLocalClassName(irClass)
|
||||
relativeName = generationState.getLocalClassName(irClass)
|
||||
flags = 0 // Forbid to use package and relative names in KClass.[simpleName|qualifiedName].
|
||||
}
|
||||
irClass.isLocal -> {
|
||||
relativeName = context.generationState.getLocalClassName(irClass)
|
||||
relativeName = generationState.getLocalClassName(irClass)
|
||||
flags = TF_REFLECTION_SHOW_REL_NAME // Only allow relative name to be used in KClass.simpleName.
|
||||
}
|
||||
isLoweredFunctionReference(irClass) -> {
|
||||
// TODO: might return null so use fallback here, to be fixed in KT-47194
|
||||
relativeName = context.generationState.getLocalClassName(irClass) ?: generateDefaultRelativeName(irClass)
|
||||
relativeName = generationState.getLocalClassName(irClass) ?: generateDefaultRelativeName(irClass)
|
||||
flags = 0 // Forbid to use package and relative names in KClass.[simpleName|qualifiedName].
|
||||
}
|
||||
else -> {
|
||||
|
||||
+17
-15
@@ -19,22 +19,24 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
/**
|
||||
* "Umbrella" class of all the of the code coverage related logic.
|
||||
*/
|
||||
internal class CoverageManager(val context: Context) {
|
||||
internal class CoverageManager(val generationState: NativeGenerationState) {
|
||||
private val context = generationState.context
|
||||
private val config = context.config
|
||||
|
||||
private val shouldCoverSources: Boolean =
|
||||
context.config.shouldCoverSources
|
||||
config.shouldCoverSources
|
||||
|
||||
private val librariesToCover: Set<String> =
|
||||
context.config.resolve.coveredLibraries.map { it.libraryName }.toSet()
|
||||
config.resolve.coveredLibraries.map { it.libraryName }.toSet()
|
||||
|
||||
private val llvmProfileFilenameGlobal = "__llvm_profile_filename"
|
||||
|
||||
private val defaultOutputFilePath: String by lazy {
|
||||
"${context.generationState.outputFile}.profraw"
|
||||
"${generationState.outputFile}.profraw"
|
||||
}
|
||||
|
||||
private val outputFileName: String =
|
||||
context.config.configuration.get(KonanConfigKeys.PROFRAW_PATH)
|
||||
config.configuration.get(KonanConfigKeys.PROFRAW_PATH)
|
||||
?.let { File(it).absolutePath }
|
||||
?: defaultOutputFilePath
|
||||
|
||||
@@ -43,13 +45,13 @@ internal class CoverageManager(val context: Context) {
|
||||
|
||||
init {
|
||||
if (enabled && !checkRestrictions()) {
|
||||
context.reportCompilationError("Coverage is not supported for ${context.config.target}.")
|
||||
context.reportCompilationError("Coverage is not supported for ${config.target}.")
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkRestrictions(): Boolean {
|
||||
val isKindAllowed = context.config.produce.involvesBitcodeGeneration
|
||||
val target = context.config.target
|
||||
val isKindAllowed = config.produce.involvesBitcodeGeneration
|
||||
val target = config.target
|
||||
val isTargetAllowed = target.supportsCodeCoverage()
|
||||
return isKindAllowed && isTargetAllowed
|
||||
}
|
||||
@@ -85,7 +87,7 @@ internal class CoverageManager(val context: Context) {
|
||||
*/
|
||||
fun tryGetInstrumentation(irFunction: IrFunction?, callSitePlacer: (function: LLVMValueRef, args: List<LLVMValueRef>) -> Unit) =
|
||||
if (enabled && irFunction != null) {
|
||||
getFunctionRegions(irFunction)?.let { LLVMCoverageInstrumentation(context, it, callSitePlacer) }
|
||||
getFunctionRegions(irFunction)?.let { LLVMCoverageInstrumentation(generationState, it, callSitePlacer) }
|
||||
} else {
|
||||
null
|
||||
}
|
||||
@@ -95,7 +97,7 @@ internal class CoverageManager(val context: Context) {
|
||||
*/
|
||||
fun writeRegionInfo() {
|
||||
if (enabled) {
|
||||
LLVMCoverageWriter(context, filesRegionsInfo).write()
|
||||
LLVMCoverageWriter(generationState, filesRegionsInfo).write()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,11 +123,11 @@ internal class CoverageManager(val context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun runCoveragePass(context: Context) {
|
||||
if (!context.coverage.enabled) return
|
||||
internal fun runCoveragePass(generationState: NativeGenerationState) {
|
||||
if (!generationState.coverage.enabled) return
|
||||
val passManager = LLVMCreatePassManager()!!
|
||||
LLVMKotlinAddTargetLibraryInfoWrapperPass(passManager, context.generationState.llvm.targetTriple)
|
||||
context.coverage.addLateLlvmPasses(passManager)
|
||||
LLVMRunPassManager(passManager, context.generationState.llvm.module)
|
||||
LLVMKotlinAddTargetLibraryInfoWrapperPass(passManager, generationState.llvm.targetTriple)
|
||||
generationState.coverage.addLateLlvmPasses(passManager)
|
||||
LLVMRunPassManager(passManager, generationState.llvm.module)
|
||||
LLVMDisposePassManager(passManager)
|
||||
}
|
||||
+2
-1
@@ -9,6 +9,7 @@ import llvm.LLVMCreatePGOFunctionNameVar
|
||||
import llvm.LLVMInstrProfIncrement
|
||||
import llvm.LLVMValueRef
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
@@ -18,7 +19,7 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
* region in [functionRegions].
|
||||
*/
|
||||
internal class LLVMCoverageInstrumentation(
|
||||
override val context: Context,
|
||||
override val generationState: NativeGenerationState,
|
||||
private val functionRegions: FunctionRegions,
|
||||
private val callSitePlacer: (function: LLVMValueRef, args: List<LLVMValueRef>) -> Unit
|
||||
) : ContextUtils {
|
||||
|
||||
+6
-5
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.konan.llvm.coverage
|
||||
import kotlinx.cinterop.*
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.name
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.path
|
||||
@@ -34,13 +35,13 @@ private fun LLVMCoverageRegion.populateFrom(region: Region, regionId: Int, files
|
||||
* See http://llvm.org/docs/CoverageMappingFormat.html for the format description.
|
||||
*/
|
||||
internal class LLVMCoverageWriter(
|
||||
private val context: Context,
|
||||
private val generationState: NativeGenerationState,
|
||||
private val filesRegionsInfo: List<FileRegionInfo>
|
||||
) {
|
||||
fun write() {
|
||||
if (filesRegionsInfo.isEmpty()) return
|
||||
|
||||
val module = context.generationState.llvm.module
|
||||
val module = generationState.llvm.module
|
||||
val filesIndex = filesRegionsInfo.mapIndexed { index, fileRegionInfo -> fileRegionInfo.file to index }.toMap()
|
||||
|
||||
val coverageGlobal = memScoped {
|
||||
@@ -53,8 +54,8 @@ internal class LLVMCoverageWriter(
|
||||
fileIds.toCValues(), fileIds.size.signExtend(),
|
||||
regions.toCValues(), regions.size.signExtend())
|
||||
|
||||
val functionName = context.generationState.llvmDeclarations.forFunction(functionRegions.function).llvmValue.name
|
||||
val functionMappingRecord = LLVMAddFunctionMappingRecord(LLVMGetModuleContext(context.generationState.llvm.module),
|
||||
val functionName = generationState.llvmDeclarations.forFunction(functionRegions.function).llvmValue.name
|
||||
val functionMappingRecord = LLVMAddFunctionMappingRecord(LLVMGetModuleContext(generationState.llvm.module),
|
||||
functionName, functionRegions.structuralHash, functionCoverage)!!
|
||||
|
||||
Pair(functionMappingRecord, functionCoverage)
|
||||
@@ -69,6 +70,6 @@ internal class LLVMCoverageWriter(
|
||||
|
||||
retval
|
||||
}
|
||||
context.generationState.llvm.usedGlobals.add(coverageGlobal)
|
||||
generationState.llvm.usedGlobals.add(coverageGlobal)
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -7,9 +7,10 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
||||
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
|
||||
internal fun llvmLinkModules2(context: Context, dest: LLVMModuleRef, src: LLVMModuleRef): LLVMBool {
|
||||
val diagnosticHandler = DefaultLlvmDiagnosticHandler(context, object : DefaultLlvmDiagnosticHandler.Policy {
|
||||
internal fun llvmLinkModules2(generationState: NativeGenerationState, dest: LLVMModuleRef, src: LLVMModuleRef): LLVMBool {
|
||||
val diagnosticHandler = DefaultLlvmDiagnosticHandler(generationState.context, object : DefaultLlvmDiagnosticHandler.Policy {
|
||||
override fun suppressWarning(diagnostic: LlvmDiagnostic): Boolean {
|
||||
if (super.suppressWarning(diagnostic)) return true
|
||||
|
||||
@@ -24,7 +25,7 @@ internal fun llvmLinkModules2(context: Context, dest: LLVMModuleRef, src: LLVMMo
|
||||
}
|
||||
})
|
||||
|
||||
return withLlvmDiagnosticHandler(context.generationState.llvmContext, diagnosticHandler) {
|
||||
return withLlvmDiagnosticHandler(generationState.llvmContext, diagnosticHandler) {
|
||||
LLVMLinkModules2(dest, src)
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.backend.konan.getARCRetainAutoreleasedReturnValueMar
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
|
||||
internal open class ObjCCodeGenerator(val codegen: CodeGenerator) {
|
||||
val generationState = codegen.generationState
|
||||
val context = codegen.context
|
||||
val llvm = codegen.llvm
|
||||
|
||||
|
||||
+7
-8
@@ -8,26 +8,27 @@ package org.jetbrains.kotlin.backend.konan.llvm.objc
|
||||
import kotlinx.cinterop.*
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
import org.jetbrains.kotlin.backend.konan.isFinalBinary
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.NSNumberKind
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamer
|
||||
|
||||
internal fun patchObjCRuntimeModule(context: Context): LLVMModuleRef? {
|
||||
val config = context.config
|
||||
internal fun patchObjCRuntimeModule(generationState: NativeGenerationState): LLVMModuleRef? {
|
||||
val config = generationState.context.config
|
||||
if (!(config.isFinalBinary && config.target.family.isAppleFamily)) return null
|
||||
|
||||
val patchBuilder = PatchBuilder(context)
|
||||
val patchBuilder = PatchBuilder(generationState.objCExport.namer)
|
||||
patchBuilder.addObjCPatches()
|
||||
|
||||
val bitcodeFile = config.objCNativeLibrary
|
||||
val parsedModule = parseBitcodeFile(context.generationState.llvmContext, bitcodeFile)
|
||||
val parsedModule = parseBitcodeFile(generationState.llvmContext, bitcodeFile)
|
||||
|
||||
patchBuilder.buildAndApply(parsedModule, context.generationState.llvm)
|
||||
patchBuilder.buildAndApply(parsedModule, generationState.llvm)
|
||||
return parsedModule
|
||||
}
|
||||
|
||||
private class PatchBuilder(val context: Context) {
|
||||
private class PatchBuilder(val objCExportNamer: ObjCExportNamer) {
|
||||
enum class GlobalKind(val prefix: String) {
|
||||
OBJC_CLASS("OBJC_CLASS_\$_"),
|
||||
OBJC_METACLASS("OBJC_METACLASS_\$_"),
|
||||
@@ -51,8 +52,6 @@ private class PatchBuilder(val context: Context) {
|
||||
val globalPatches = mutableListOf<GlobalPatch>()
|
||||
val literalPatches = mutableListOf<LiteralPatch>()
|
||||
|
||||
val objCExportNamer = context.objCExport.namer
|
||||
|
||||
// Note: exported classes anyway use the same prefix,
|
||||
// so using more unique private prefix wouldn't help to prevent any clashes.
|
||||
private val privatePrefix = objCExportNamer.topLevelNamePrefix
|
||||
|
||||
+32
-32
@@ -215,7 +215,7 @@ internal open class ObjCExportCodeGeneratorBase(codegen: CodeGenerator) : ObjCCo
|
||||
val runtime get() = codegen.runtime
|
||||
val staticData get() = codegen.staticData
|
||||
|
||||
val rttiGenerator = RTTIGenerator(context)
|
||||
val rttiGenerator = RTTIGenerator(generationState)
|
||||
|
||||
private val objcTerminate: LlvmCallable by lazy {
|
||||
llvm.externalFunction(LlvmFunctionProto(
|
||||
@@ -287,7 +287,7 @@ internal class ObjCExportBlockCodeGenerator(codegen: CodeGenerator) : ObjCExport
|
||||
// 1. Enumerates [BuiltInFictitiousFunctionIrClassFactory] built classes, which may be incomplete otherwise.
|
||||
// 2. Modifies stdlib global initializers.
|
||||
// 3. Defines runtime-declared globals.
|
||||
require(context.generationState.shouldDefineFunctionClasses)
|
||||
require(generationState.shouldDefineFunctionClasses)
|
||||
}
|
||||
|
||||
fun generate() {
|
||||
@@ -499,7 +499,7 @@ internal class ObjCExportCodeGenerator(
|
||||
descriptorToAdapter[adapter.objCName] = typeAdapter
|
||||
|
||||
if (irClass != null) {
|
||||
if (!context.generationState.llvmModuleSpecification.importsKotlinDeclarationsFromOtherSharedLibraries()) {
|
||||
if (!generationState.llvmModuleSpecification.importsKotlinDeclarationsFromOtherSharedLibraries()) {
|
||||
setObjCExportTypeInfo(irClass, typeAdapter = typeAdapter)
|
||||
} else {
|
||||
// Optimization: avoid generating huge initializers;
|
||||
@@ -527,7 +527,7 @@ internal class ObjCExportCodeGenerator(
|
||||
emitSortedAdapters(placedClassAdapters, "Kotlin_ObjCExport_sortedClassAdapters")
|
||||
emitSortedAdapters(placedInterfaceAdapters, "Kotlin_ObjCExport_sortedProtocolAdapters")
|
||||
|
||||
if (context.generationState.llvmModuleSpecification.importsKotlinDeclarationsFromOtherSharedLibraries()) {
|
||||
if (generationState.llvmModuleSpecification.importsKotlinDeclarationsFromOtherSharedLibraries()) {
|
||||
replaceExternalWeakOrCommonGlobal(
|
||||
"Kotlin_ObjCExport_initTypeAdapters",
|
||||
llvm.constInt1(true),
|
||||
@@ -555,7 +555,7 @@ internal class ObjCExportCodeGenerator(
|
||||
if (determineLinkerOutput(context) == LinkerOutputKind.STATIC_LIBRARY) {
|
||||
// Might be affected by https://youtrack.jetbrains.com/issue/KT-42254.
|
||||
// The code below generally follows [replaceExternalWeakOrCommonGlobal] implementation.
|
||||
if (context.generationState.llvmModuleSpecification.importsKotlinDeclarationsFromOtherObjectFiles()) {
|
||||
if (generationState.llvmModuleSpecification.importsKotlinDeclarationsFromOtherObjectFiles()) {
|
||||
// So the compiler uses caches. If a user is linking two such static frameworks into a single binary,
|
||||
// the linker might fail with a lot of "duplicate symbol" errors due to KT-42254.
|
||||
// Adding a similar symbol that would explicitly hint to take a look at the YouTrack issue if reported.
|
||||
@@ -701,14 +701,14 @@ private fun ObjCExportCodeGenerator.replaceExternalWeakOrCommonGlobal(
|
||||
origin: CompiledKlibModuleOrigin
|
||||
) {
|
||||
// TODO: A similar mechanism is used in `IrToBitcode.overrideRuntimeGlobal`. Consider merging them.
|
||||
if (context.generationState.llvmModuleSpecification.importsKotlinDeclarationsFromOtherSharedLibraries()) {
|
||||
if (generationState.llvmModuleSpecification.importsKotlinDeclarationsFromOtherSharedLibraries()) {
|
||||
val global = codegen.importGlobal(name, value.llvmType, origin)
|
||||
externalGlobalInitializers[global] = value
|
||||
} else {
|
||||
context.generationState.llvmImports.add(origin)
|
||||
generationState.llvmImports.add(origin)
|
||||
val global = staticData.placeGlobal(name, value, isExported = true)
|
||||
|
||||
if (context.generationState.llvmModuleSpecification.importsKotlinDeclarationsFromOtherObjectFiles()) {
|
||||
if (generationState.llvmModuleSpecification.importsKotlinDeclarationsFromOtherObjectFiles()) {
|
||||
// Note: actually this is required only if global's weak/common definition is in another object file,
|
||||
// but it is simpler to do this for all globals, considering that all usages can't be removed by DCE anyway.
|
||||
llvm.usedGlobals += global.llvmGlobal
|
||||
@@ -745,7 +745,7 @@ private fun ObjCExportCodeGenerator.setObjCExportTypeInfo(
|
||||
|
||||
private fun ObjCExportCodeGeneratorBase.setOwnWritableTypeInfo(irClass: IrClass, writableTypeInfoValue: Struct) {
|
||||
require(!codegen.isExternal(irClass))
|
||||
val writeableTypeInfoGlobal = context.generationState.llvmDeclarations.forClass(irClass).writableTypeInfoGlobal!!
|
||||
val writeableTypeInfoGlobal = generationState.llvmDeclarations.forClass(irClass).writableTypeInfoGlobal!!
|
||||
writeableTypeInfoGlobal.setLinkage(LLVMLinkage.LLVMExternalLinkage)
|
||||
writeableTypeInfoGlobal.setInitializer(writableTypeInfoValue)
|
||||
}
|
||||
@@ -872,7 +872,7 @@ private val ObjCExportBlockCodeGenerator.mappedFunctionNClasses get() =
|
||||
.filter { it.descriptor.isMappedFunctionClass() }
|
||||
|
||||
private fun ObjCExportBlockCodeGenerator.emitFunctionConverters() {
|
||||
require(context.generationState.shouldDefineFunctionClasses)
|
||||
require(generationState.shouldDefineFunctionClasses)
|
||||
mappedFunctionNClasses.forEach { functionClass ->
|
||||
val convertToRetained = kotlinFunctionToRetainedBlockConverter(BlockPointerBridge(functionClass.arity, returnsVoid = false))
|
||||
|
||||
@@ -882,7 +882,7 @@ private fun ObjCExportBlockCodeGenerator.emitFunctionConverters() {
|
||||
}
|
||||
|
||||
private fun ObjCExportBlockCodeGenerator.emitBlockToKotlinFunctionConverters() {
|
||||
require(context.generationState.shouldDefineFunctionClasses)
|
||||
require(generationState.shouldDefineFunctionClasses)
|
||||
val functionClassesByArity = mappedFunctionNClasses.associateBy { it.arity }
|
||||
|
||||
val arityLimit = (functionClassesByArity.keys.maxOrNull() ?: -1) + 1
|
||||
@@ -956,7 +956,7 @@ private fun ObjCExportCodeGenerator.emitCollectionConverters() {
|
||||
}
|
||||
|
||||
private fun ObjCExportFunctionGenerationContextBuilder.setupBridgeDebugInfo() {
|
||||
val location = setupBridgeDebugInfo(this.objCExportCodegen.context, function)
|
||||
val location = setupBridgeDebugInfo(this.objCExportCodegen.generationState, function)
|
||||
startLocation = location
|
||||
endLocation = location
|
||||
}
|
||||
@@ -967,7 +967,7 @@ private inline fun ObjCExportCodeGenerator.generateObjCImpBy(
|
||||
suffix: String,
|
||||
genBody: ObjCExportFunctionGenerationContext.() -> Unit
|
||||
): LLVMValueRef {
|
||||
val functionType = objCFunctionType(context, methodBridge)
|
||||
val functionType = objCFunctionType(generationState, methodBridge)
|
||||
val functionName = "objc2kotlin_$suffix"
|
||||
val result = functionGenerator(functionType, functionName) {
|
||||
if (debugInfo) {
|
||||
@@ -1107,7 +1107,7 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
|
||||
// Release init receiver, as required by convention.
|
||||
objcReleaseFromRunnableThreadState(param(0))
|
||||
}
|
||||
Zero(returnType.toLlvmRetType(context).llvmType).llvm
|
||||
Zero(returnType.toLlvmRetType(generationState).llvmType).llvm
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1138,7 +1138,7 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
|
||||
MethodBridge.ReturnValue.Void -> null
|
||||
MethodBridge.ReturnValue.HashCode -> {
|
||||
val kotlinHashCode = targetResult!!
|
||||
if (codegen.context.is64BitNSInteger()) zext(kotlinHashCode, llvm.int64Type) else kotlinHashCode
|
||||
if (generationState.is64BitNSInteger()) zext(kotlinHashCode, llvm.int64Type) else kotlinHashCode
|
||||
}
|
||||
is MethodBridge.ReturnValue.Mapped -> if (LLVMTypeOf(targetResult!!) == llvm.voidType) {
|
||||
returnBridge.bridge.makeNothing(llvm)
|
||||
@@ -1332,7 +1332,7 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge(
|
||||
|
||||
val retainAutoreleasedTargetResult = methodBridge.returnBridge.isAutoreleasedObjCReference()
|
||||
|
||||
val objCFunctionType = objCFunctionType(context, methodBridge)
|
||||
val objCFunctionType = objCFunctionType(generationState, methodBridge)
|
||||
val objcMsgSend = msgSender(objCFunctionType)
|
||||
|
||||
// Using terminatingExceptionHandler, so any exception thrown by the method will lead to the termination,
|
||||
@@ -1370,7 +1370,7 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge(
|
||||
MethodBridge.ReturnValue.Void -> null
|
||||
|
||||
MethodBridge.ReturnValue.HashCode -> {
|
||||
if (codegen.context.is64BitNSInteger()) {
|
||||
if (generationState.is64BitNSInteger()) {
|
||||
val low = trunc(targetResult, llvm.int32Type)
|
||||
val high = trunc(shr(targetResult, 32, signed = false), llvm.int32Type)
|
||||
xor(low, high)
|
||||
@@ -1877,7 +1877,7 @@ private inline fun ObjCExportCodeGenerator.generateObjCToKotlinSyntheticGetter(
|
||||
MethodBridgeReceiver.Static, valueParameters = emptyList()
|
||||
)
|
||||
|
||||
val functionType = objCFunctionType(context, methodBridge)
|
||||
val functionType = objCFunctionType(generationState, methodBridge)
|
||||
val functionName = "objc2kotlin_$suffix"
|
||||
val imp = functionGenerator(functionType, functionName) {
|
||||
switchToRunnable = true
|
||||
@@ -1975,9 +1975,9 @@ private fun ObjCExportCodeGenerator.createThrowableAsErrorAdapter(): ObjCExportC
|
||||
return objCToKotlinMethodAdapter(selector, methodBridge, imp)
|
||||
}
|
||||
|
||||
private fun objCFunctionType(context: Context, methodBridge: MethodBridge): LlvmFunctionSignature {
|
||||
val paramTypes = methodBridge.paramBridges.map { it.toLlvmParamType(context.generationState.llvm) }
|
||||
val returnType = methodBridge.returnBridge.toLlvmRetType(context)
|
||||
private fun objCFunctionType(generationState: NativeGenerationState, methodBridge: MethodBridge): LlvmFunctionSignature {
|
||||
val paramTypes = methodBridge.paramBridges.map { it.toLlvmParamType(generationState.llvm) }
|
||||
val returnType = methodBridge.returnBridge.toLlvmRetType(generationState)
|
||||
return LlvmFunctionSignature(returnType, paramTypes, isVararg = false)
|
||||
}
|
||||
|
||||
@@ -2006,21 +2006,21 @@ private fun MethodBridgeParameter.toLlvmParamType(llvm: Llvm): LlvmParamType = w
|
||||
}
|
||||
|
||||
private fun MethodBridge.ReturnValue.toLlvmRetType(
|
||||
context: Context
|
||||
generationState: NativeGenerationState
|
||||
): LlvmRetType {
|
||||
val llvm = context.generationState.llvm
|
||||
val llvm = generationState.llvm
|
||||
return when (this) {
|
||||
MethodBridge.ReturnValue.Suspend,
|
||||
MethodBridge.ReturnValue.Void -> LlvmRetType(llvm.voidType)
|
||||
|
||||
MethodBridge.ReturnValue.HashCode -> LlvmRetType(if (context.is64BitNSInteger()) llvm.int64Type else llvm.int32Type)
|
||||
MethodBridge.ReturnValue.HashCode -> LlvmRetType(if (generationState.is64BitNSInteger()) llvm.int64Type else llvm.int32Type)
|
||||
is MethodBridge.ReturnValue.Mapped -> this.bridge.toLlvmParamType(llvm)
|
||||
MethodBridge.ReturnValue.WithError.Success -> ValueTypeBridge(ObjCValueType.BOOL).toLlvmParamType(llvm)
|
||||
|
||||
MethodBridge.ReturnValue.Instance.InitResult,
|
||||
MethodBridge.ReturnValue.Instance.FactoryResult -> ReferenceBridge.toLlvmParamType(llvm)
|
||||
|
||||
is MethodBridge.ReturnValue.WithError.ZeroForError -> this.successBridge.toLlvmRetType(context)
|
||||
is MethodBridge.ReturnValue.WithError.ZeroForError -> this.successBridge.toLlvmRetType(generationState)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2040,22 +2040,22 @@ internal fun ObjCExportCodeGenerator.getEncoding(methodBridge: MethodBridge): St
|
||||
}
|
||||
}
|
||||
|
||||
val returnTypeEncoding = methodBridge.returnBridge.getObjCEncoding(context)
|
||||
val returnTypeEncoding = methodBridge.returnBridge.getObjCEncoding(generationState)
|
||||
|
||||
val paramSize = paramOffset
|
||||
return "$returnTypeEncoding$paramSize$params"
|
||||
}
|
||||
|
||||
private fun MethodBridge.ReturnValue.getObjCEncoding(context: Context): String = when (this) {
|
||||
private fun MethodBridge.ReturnValue.getObjCEncoding(generationState: NativeGenerationState): String = when (this) {
|
||||
MethodBridge.ReturnValue.Suspend,
|
||||
MethodBridge.ReturnValue.Void -> "v"
|
||||
MethodBridge.ReturnValue.HashCode -> if (context.is64BitNSInteger()) "Q" else "I"
|
||||
MethodBridge.ReturnValue.HashCode -> if (generationState.is64BitNSInteger()) "Q" else "I"
|
||||
is MethodBridge.ReturnValue.Mapped -> this.bridge.objCEncoding
|
||||
MethodBridge.ReturnValue.WithError.Success -> ObjCValueType.BOOL.encoding
|
||||
|
||||
MethodBridge.ReturnValue.Instance.InitResult,
|
||||
MethodBridge.ReturnValue.Instance.FactoryResult -> ReferenceBridge.objCEncoding
|
||||
is MethodBridge.ReturnValue.WithError.ZeroForError -> this.successBridge.getObjCEncoding(context)
|
||||
is MethodBridge.ReturnValue.WithError.ZeroForError -> this.successBridge.getObjCEncoding(generationState)
|
||||
}
|
||||
|
||||
private val MethodBridgeParameter.objCEncoding: String get() = when (this) {
|
||||
@@ -2071,10 +2071,10 @@ private val TypeBridge.objCEncoding: String get() = when (this) {
|
||||
is ValueTypeBridge -> this.objCValueType.encoding
|
||||
}
|
||||
|
||||
private fun Context.is64BitNSInteger(): Boolean {
|
||||
val configurables = this.config.platform.configurables
|
||||
private fun NativeGenerationState.is64BitNSInteger(): Boolean {
|
||||
val configurables = context.config.platform.configurables
|
||||
require(configurables is AppleConfigurables) {
|
||||
"Target ${configurables.target} has no support for NSInteger type."
|
||||
}
|
||||
return generationState.llvm.nsIntegerTypeWidth == 64L
|
||||
return llvm.nsIntegerTypeWidth == 64L
|
||||
}
|
||||
|
||||
+32
-29
@@ -5,8 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_FUNCTION_CLASS
|
||||
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.KonanIrLinker
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerIr
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
@@ -16,34 +16,37 @@ import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
|
||||
internal class CacheInfoBuilder(private val context: Context, private val moduleDeserializer: KonanIrLinker.KonanPartialModuleDeserializer) {
|
||||
fun build() = with(moduleDeserializer) {
|
||||
moduleFragment.acceptChildrenVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
internal class CacheInfoBuilder(
|
||||
private val generationState: NativeGenerationState,
|
||||
private val moduleDeserializer: KonanIrLinker.KonanPartialModuleDeserializer,
|
||||
private val irModule: IrModuleFragment
|
||||
) {
|
||||
fun build() = irModule.acceptChildrenVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
|
||||
if (!declaration.isInterface && !declaration.isLocal
|
||||
&& declaration.isExported && declaration.origin != DECLARATION_ORIGIN_FUNCTION_CLASS
|
||||
) {
|
||||
val declaredFields = generationState.context.getLayoutBuilder(declaration).getDeclaredFields()
|
||||
generationState.classFields.add(moduleDeserializer.buildClassFields(declaration, declaredFields))
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
// Don't need to visit the children here: classes would be all local and wouldn't be handled anyway,
|
||||
// as for functions - both their callees will be handled and inline bodies will be built for the top function.
|
||||
|
||||
if (!declaration.isInterface && !declaration.isLocal
|
||||
&& declaration.isExported && declaration.origin != DECLARATION_ORIGIN_FUNCTION_CLASS
|
||||
) {
|
||||
context.generationState.classFields.add(buildClassFields(declaration, context.getLayoutBuilder(declaration).getDeclaredFields()))
|
||||
}
|
||||
if (!declaration.isFakeOverride && declaration.isInline && declaration.isExported) {
|
||||
generationState.inlineFunctionBodies.add(moduleDeserializer.buildInlineFunctionReference(declaration))
|
||||
trackCallees(declaration)
|
||||
}
|
||||
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
// Don't need to visit the children here: classes would be all local and wouldn't be handled anyway,
|
||||
// as for functions - both their callees will be handled and inline bodies will be built for the top function.
|
||||
|
||||
if (!declaration.isFakeOverride && declaration.isInline && declaration.isExported) {
|
||||
context.generationState.inlineFunctionBodies.add(buildInlineFunctionReference(declaration))
|
||||
trackCallees(declaration)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
private val IrDeclaration.isExported
|
||||
get() = with(KonanManglerIr) { isExported(compatibleMode = moduleDeserializer.compatibilityMode.oldSignatures) }
|
||||
@@ -61,9 +64,9 @@ internal class CacheInfoBuilder(private val context: Context, private val module
|
||||
|
||||
private fun processFunction(function: IrFunction) {
|
||||
if (function.getPackageFragment() !is IrExternalPackageFragment) {
|
||||
context.generationState.calledFromExportedInlineFunctions.add(function)
|
||||
generationState.calledFromExportedInlineFunctions.add(function)
|
||||
(function as? IrConstructor)?.constructedClass?.let {
|
||||
context.generationState.constructedFromExportedInlineFunctions.add(it)
|
||||
generationState.constructedFromExportedInlineFunctions.add(it)
|
||||
}
|
||||
if (function.isInline && !function.isExported) {
|
||||
// An exported inline function calls a non-exported inline function:
|
||||
@@ -76,13 +79,13 @@ internal class CacheInfoBuilder(private val context: Context, private val module
|
||||
override fun visitGetObjectValue(expression: IrGetObjectValue) {
|
||||
expression.acceptChildrenVoid(this)
|
||||
|
||||
processFunction(context.getObjectClassInstanceFunction(expression.symbol.owner))
|
||||
processFunction(generationState.context.getObjectClassInstanceFunction(expression.symbol.owner))
|
||||
}
|
||||
|
||||
override fun visitGetEnumValue(expression: IrGetEnumValue) {
|
||||
expression.acceptChildrenVoid(this)
|
||||
|
||||
processFunction(context.enumsSupport.getValueGetter(expression.symbol.owner.parentAsClass))
|
||||
processFunction(generationState.context.enumsSupport.getValueGetter(expression.symbol.owner.parentAsClass))
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall) {
|
||||
|
||||
+7
-5
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.getOrPut
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
import org.jetbrains.kotlin.backend.konan.NativeMapping
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.ir.llvmSymbolOrigin
|
||||
@@ -145,9 +146,10 @@ internal class ExportCachesAbiVisitor(val context: Context) : FileLoweringPass,
|
||||
}
|
||||
}
|
||||
|
||||
internal class ImportCachesAbiTransformer(val context: Context) : FileLoweringPass, IrElementTransformerVoid() {
|
||||
private val cachesAbiSupport = context.cachesAbiSupport
|
||||
private val llvmImports = context.generationState.llvmImports
|
||||
internal class ImportCachesAbiTransformer(val generationState: NativeGenerationState) : FileLoweringPass, IrElementTransformerVoid() {
|
||||
private val cachesAbiSupport = generationState.context.cachesAbiSupport
|
||||
private val innerClassesSupport = generationState.context.innerClassesSupport
|
||||
private val llvmImports = generationState.llvmImports
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
irFile.transformChildrenVoid(this)
|
||||
@@ -162,9 +164,9 @@ internal class ImportCachesAbiTransformer(val context: Context) : FileLoweringPa
|
||||
val property = field.correspondingPropertySymbol?.owner
|
||||
|
||||
return when {
|
||||
context.generationState.llvmModuleSpecification.containsDeclaration(field) -> expression
|
||||
generationState.llvmModuleSpecification.containsDeclaration(field) -> expression
|
||||
|
||||
irClass?.isInner == true && context.innerClassesSupport.getOuterThisField(irClass) == field -> {
|
||||
irClass?.isInner == true && innerClassesSupport.getOuterThisField(irClass) == field -> {
|
||||
val accessor = cachesAbiSupport.getOuterThisAccessor(irClass)
|
||||
llvmImports.add(irClass.llvmSymbolOrigin)
|
||||
return irCall(expression.startOffset, expression.endOffset, accessor, emptyList()).apply {
|
||||
|
||||
+4
-2
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.ir.buildSimpleAnnotation
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
@@ -24,7 +25,8 @@ import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
internal class PropertyDelegationLowering(val context: Context) : FileLoweringPass {
|
||||
internal class PropertyDelegationLowering(val generationState: NativeGenerationState) : FileLoweringPass {
|
||||
private val context = generationState.context
|
||||
private var tempIndex = 0
|
||||
|
||||
private fun getKPropertyImpl(receiverTypes: List<IrType>,
|
||||
@@ -234,7 +236,7 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
|
||||
irFile,
|
||||
irFile,
|
||||
this,
|
||||
this@PropertyDelegationLowering.context,
|
||||
generationState,
|
||||
irBuilder,
|
||||
)
|
||||
val (newClass, newExpression) = builder.build()
|
||||
|
||||
+8
-6
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.pop
|
||||
import org.jetbrains.kotlin.backend.common.push
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.computeFullName
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
@@ -28,7 +29,7 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
internal class FunctionReferenceLowering(val context: Context) : FileLoweringPass {
|
||||
internal class FunctionReferenceLowering(val generationState: NativeGenerationState) : FileLoweringPass {
|
||||
private object DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL : IrDeclarationOriginImpl("FUNCTION_REFERENCE_IMPL")
|
||||
|
||||
companion object {
|
||||
@@ -136,9 +137,9 @@ internal class FunctionReferenceLowering(val context: Context) : FileLoweringPas
|
||||
|
||||
fun transformFunctionReference(expression: IrFunctionReference, samSuperType: IrType? = null): IrExpression {
|
||||
val parent: IrDeclarationContainer = (currentClass?.irElement as? IrClass) ?: irFile
|
||||
val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol,
|
||||
val irBuilder = generationState.context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol,
|
||||
expression.startOffset, expression.endOffset)
|
||||
val (clazz, newExpression) = FunctionReferenceBuilder(irFile, parent, expression, context, irBuilder, samSuperType).build()
|
||||
val (clazz, newExpression) = FunctionReferenceBuilder(irFile, parent, expression, generationState, irBuilder, samSuperType).build()
|
||||
generatedClasses.add(clazz)
|
||||
return newExpression
|
||||
}
|
||||
@@ -153,16 +154,17 @@ internal class FunctionReferenceLowering(val context: Context) : FileLoweringPas
|
||||
val irFile: IrFile,
|
||||
val parent: IrDeclarationParent,
|
||||
val functionReference: IrFunctionReference,
|
||||
val context: Context,
|
||||
val generationState: NativeGenerationState,
|
||||
val irBuilder: IrBuilderWithScope,
|
||||
val samSuperType: IrType? = null,
|
||||
) {
|
||||
data class BuiltFunctionReference(val functionReferenceClass: IrClass, val functionReferenceExpression: IrExpression)
|
||||
|
||||
private val context = generationState.context
|
||||
private val irBuiltIns = context.irBuiltIns
|
||||
private val symbols = context.ir.symbols
|
||||
private val irFactory = context.irFactory
|
||||
private val fileLowerState = context.generationState.fileLowerState
|
||||
private val fileLowerState = generationState.fileLowerState
|
||||
|
||||
private val startOffset = functionReference.startOffset
|
||||
private val endOffset = functionReference.endOffset
|
||||
@@ -202,7 +204,7 @@ internal class FunctionReferenceLowering(val context: Context) : FileLoweringPas
|
||||
createParameterDeclarations()
|
||||
|
||||
// copy the generated name for IrClass, partially solves KT-47194
|
||||
context.generationState.copyLocalClassName(functionReference, this)
|
||||
generationState.copyLocalClassName(functionReference, this)
|
||||
}
|
||||
|
||||
private val functionReferenceThis = functionReferenceClass.thisReceiver!!
|
||||
|
||||
+20
-12
@@ -46,10 +46,10 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.konan.ForeignExceptionMode
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
|
||||
internal class InteropLowering(context: Context) : FileLoweringPass {
|
||||
internal class InteropLowering(generationState: NativeGenerationState) : FileLoweringPass {
|
||||
// TODO: merge these lowerings.
|
||||
private val part1 = InteropLoweringPart1(context)
|
||||
private val part2 = InteropLoweringPart2(context)
|
||||
private val part1 = InteropLoweringPart1(generationState)
|
||||
private val part2 = InteropLoweringPart2(generationState)
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
part1.lower(irFile)
|
||||
@@ -57,7 +57,9 @@ internal class InteropLowering(context: Context) : FileLoweringPass {
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class BaseInteropIrTransformer(private val context: Context) : IrBuildingTransformer(context) {
|
||||
private abstract class BaseInteropIrTransformer(
|
||||
private val generationState: NativeGenerationState
|
||||
) : IrBuildingTransformer(generationState.context) {
|
||||
|
||||
protected inline fun <T> generateWithStubs(element: IrElement? = null, block: KotlinStubs.() -> T): T =
|
||||
createKotlinStubs(element).block()
|
||||
@@ -81,7 +83,8 @@ private abstract class BaseInteropIrTransformer(private val context: Context) :
|
||||
}
|
||||
|
||||
return object : KotlinStubs {
|
||||
private val cStubsManager = context.generationState.cStubsManager
|
||||
private val context = generationState.context
|
||||
private val cStubsManager = generationState.cStubsManager
|
||||
|
||||
override val irBuiltIns get() = context.irBuiltIns
|
||||
override val symbols get() = context.ir.symbols
|
||||
@@ -106,7 +109,7 @@ private abstract class BaseInteropIrTransformer(private val context: Context) :
|
||||
"$uniquePrefix${cStubsManager.getUniqueName(prefix)}"
|
||||
|
||||
override fun getUniqueKotlinFunctionReferenceClassName(prefix: String) =
|
||||
context.generationState.fileLowerState.getFunctionReferenceImplUniqueName(prefix)
|
||||
generationState.fileLowerState.getFunctionReferenceImplUniqueName(prefix)
|
||||
|
||||
override val target get() = context.config.target
|
||||
|
||||
@@ -126,7 +129,8 @@ private abstract class BaseInteropIrTransformer(private val context: Context) :
|
||||
protected abstract fun addTopLevel(declaration: IrDeclaration)
|
||||
}
|
||||
|
||||
private class InteropLoweringPart1(val context: Context) : BaseInteropIrTransformer(context), FileLoweringPass {
|
||||
private class InteropLoweringPart1(val generationState: NativeGenerationState) : BaseInteropIrTransformer(generationState), FileLoweringPass {
|
||||
private val context = generationState.context
|
||||
|
||||
private val symbols get() = context.ir.symbols
|
||||
|
||||
@@ -539,7 +543,7 @@ private class InteropLoweringPart1(val context: Context) : BaseInteropIrTransfor
|
||||
): IrExpression = generateWithStubs(call) {
|
||||
if (method.parent !is IrClass) {
|
||||
// Category-provided.
|
||||
this@InteropLoweringPart1.context.generationState.llvmImports.add(method.llvmSymbolOrigin)
|
||||
generationState.llvmImports.add(method.llvmSymbolOrigin)
|
||||
}
|
||||
|
||||
this.generateObjCCall(
|
||||
@@ -746,9 +750,9 @@ private class InteropLoweringPart1(val context: Context) : BaseInteropIrTransfor
|
||||
/**
|
||||
* Lowers some interop intrinsic calls.
|
||||
*/
|
||||
private class InteropLoweringPart2(val context: Context) : FileLoweringPass {
|
||||
private class InteropLoweringPart2(val generationState: NativeGenerationState) : FileLoweringPass {
|
||||
override fun lower(irFile: IrFile) {
|
||||
val transformer = InteropTransformer(context, irFile)
|
||||
val transformer = InteropTransformer(generationState, irFile)
|
||||
irFile.transformChildrenVoid(transformer)
|
||||
|
||||
while (transformer.newTopLevelDeclarations.isNotEmpty()) {
|
||||
@@ -765,7 +769,11 @@ private class InteropLoweringPart2(val context: Context) : FileLoweringPass {
|
||||
}
|
||||
}
|
||||
|
||||
private class InteropTransformer(val context: Context, override val irFile: IrFile) : BaseInteropIrTransformer(context) {
|
||||
private class InteropTransformer(
|
||||
val generationState: NativeGenerationState,
|
||||
override val irFile: IrFile
|
||||
) : BaseInteropIrTransformer(generationState) {
|
||||
private val context = generationState.context
|
||||
|
||||
val newTopLevelDeclarations = mutableListOf<IrDeclaration>()
|
||||
|
||||
@@ -1003,7 +1011,7 @@ private class InteropTransformer(val context: Context, override val irFile: IrFi
|
||||
private fun generateCCall(expression: IrCall): IrExpression {
|
||||
val function = expression.symbol.owner
|
||||
|
||||
context.generationState.llvmImports.add(function.llvmSymbolOrigin)
|
||||
generationState.llvmImports.add(function.llvmSymbolOrigin)
|
||||
val exceptionMode = ForeignExceptionMode.byValue(
|
||||
function.konanLibrary?.manifestProperties?.getProperty(ForeignExceptionMode.manifestKey)
|
||||
)
|
||||
|
||||
+7
-6
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.common.lower.inline.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.InlineFunctionOriginInfo
|
||||
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
import org.jetbrains.kotlin.backend.konan.NativeMapping
|
||||
import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
@@ -37,16 +38,16 @@ internal class InlineFunctionsSupport(mapping: NativeMapping) {
|
||||
}
|
||||
|
||||
// TODO: This is a bit hacky. Think about adopting persistent IR ideas.
|
||||
internal class NativeInlineFunctionResolver(override val context: Context) : DefaultInlineFunctionResolver(context) {
|
||||
internal class NativeInlineFunctionResolver(override val context: Context, val generationState: NativeGenerationState) : DefaultInlineFunctionResolver(context) {
|
||||
override fun getFunctionDeclaration(symbol: IrFunctionSymbol): IrFunction {
|
||||
val function = super.getFunctionDeclaration(symbol)
|
||||
|
||||
context.generationState.loweredInlineFunctions[function]?.let { return it.irFunction }
|
||||
generationState.loweredInlineFunctions[function]?.let { return it.irFunction }
|
||||
|
||||
val packageFragment = function.getPackageFragment()
|
||||
val (possiblyLoweredFunction, shouldLower) = if (packageFragment !is IrExternalPackageFragment) {
|
||||
context.inlineFunctionsSupport.getNonLoweredInlineFunction(function, copy = context.config.producePerFileCache).also {
|
||||
context.generationState.loweredInlineFunctions[function] =
|
||||
generationState.loweredInlineFunctions[function] =
|
||||
InlineFunctionOriginInfo(it, packageFragment as IrFile, function.startOffset, function.endOffset)
|
||||
} to true
|
||||
} else {
|
||||
@@ -58,7 +59,7 @@ internal class NativeInlineFunctionResolver(override val context: Context) : Def
|
||||
"No IR and no cache for ${function.render()}"
|
||||
}
|
||||
val (shouldLower, deserializedInlineFunction) = moduleDeserializer.deserializeInlineFunction(function)
|
||||
context.generationState.loweredInlineFunctions[function] = deserializedInlineFunction
|
||||
generationState.loweredInlineFunctions[function] = deserializedInlineFunction
|
||||
function to shouldLower
|
||||
}
|
||||
|
||||
@@ -66,7 +67,7 @@ internal class NativeInlineFunctionResolver(override val context: Context) : Def
|
||||
|
||||
val body = possiblyLoweredFunction.body ?: return possiblyLoweredFunction
|
||||
|
||||
PreInlineLowering(context).lower(body, possiblyLoweredFunction, context.generationState.loweredInlineFunctions[function]!!.irFile)
|
||||
PreInlineLowering(context).lower(body, possiblyLoweredFunction, generationState.loweredInlineFunctions[function]!!.irFile)
|
||||
|
||||
ArrayConstructorLowering(context).lower(body, possiblyLoweredFunction)
|
||||
|
||||
@@ -80,7 +81,7 @@ internal class NativeInlineFunctionResolver(override val context: Context) : Def
|
||||
|
||||
LocalClassesInInlineLambdasLowering(context).lower(body, possiblyLoweredFunction)
|
||||
|
||||
if (context.generationState.llvmModuleSpecification.containsDeclaration(function)) {
|
||||
if (generationState.llvmModuleSpecification.containsDeclaration(function)) {
|
||||
// Do not extract local classes off of inline functions from cached libraries.
|
||||
LocalClassesInInlineFunctionsLowering(context).lower(body, possiblyLoweredFunction)
|
||||
LocalClassesExtractionFromInlineFunctionsLowering(context).lower(body, possiblyLoweredFunction)
|
||||
|
||||
+3
-2
@@ -7,15 +7,16 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.lower.InventNamesForLocalClasses
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
import org.jetbrains.kotlin.ir.declarations.IrAttributeContainer
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
|
||||
// TODO: consider replacing '$' by another delimeter that can't be used in class name specified with backticks (``)
|
||||
internal class NativeInventNamesForLocalClasses(val context: Context) : InventNamesForLocalClasses(allowTopLevelCallables = true) {
|
||||
internal class NativeInventNamesForLocalClasses(val generationState: NativeGenerationState) : InventNamesForLocalClasses(allowTopLevelCallables = true) {
|
||||
override fun computeTopLevelClassName(clazz: IrClass): String = clazz.name.asString()
|
||||
override fun sanitizeNameIfNeeded(name: String) = name
|
||||
|
||||
override fun putLocalClassName(declaration: IrAttributeContainer, localClassName: String) {
|
||||
context.generationState.putLocalClassName(declaration, localClassName)
|
||||
generationState.putLocalClassName(declaration, localClassName)
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -4,6 +4,7 @@ import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.common.lower.coroutines.getOrCreateFunctionWithContinuationStub
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
@@ -29,9 +30,11 @@ import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
internal class NativeSuspendFunctionsLowering(ctx: Context) : AbstractSuspendFunctionsLowering<Context>(ctx) {
|
||||
internal class NativeSuspendFunctionsLowering(
|
||||
generationState: NativeGenerationState
|
||||
) : AbstractSuspendFunctionsLowering<Context>(generationState.context) {
|
||||
private val symbols = context.ir.symbols
|
||||
private val fileLowerState = context.generationState.fileLowerState
|
||||
private val fileLowerState = generationState.fileLowerState
|
||||
|
||||
override val stateMachineMethodName = Name.identifier("invokeSuspend")
|
||||
|
||||
|
||||
+3
-2
@@ -62,7 +62,8 @@ internal fun Context.getObjectClassInstanceFunction(clazz: IrClass) = mapping.ob
|
||||
}
|
||||
}
|
||||
|
||||
internal class ObjectClassLowering(val context: Context) : FileLoweringPass {
|
||||
internal class ObjectClassLowering(val generationState: NativeGenerationState) : FileLoweringPass {
|
||||
val context = generationState.context
|
||||
val symbols = context.ir.symbols
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
@@ -166,7 +167,7 @@ internal class ObjectClassLowering(val context: Context) : FileLoweringPass {
|
||||
|
||||
private fun IrClass.hasConstStateAndNoSideEffects(): Boolean {
|
||||
if (this.hasAnnotation(KonanFqNames.canBePrecreated)) return true
|
||||
val fields = context.getLayoutBuilder(this).fields
|
||||
val fields = context.getLayoutBuilder(this).getFields(generationState.llvm)
|
||||
return fields.all { it.isConst } && this.constructors.all { it.isAutogeneratedSimpleConstructor() }
|
||||
}
|
||||
|
||||
|
||||
+5
-4
@@ -56,10 +56,11 @@ internal fun produceObjCExportInterface(context: Context): ObjCExportedInterface
|
||||
}
|
||||
|
||||
internal class ObjCExport(
|
||||
val context: Context,
|
||||
val generationState: NativeGenerationState,
|
||||
private val exportedInterface: ObjCExportedInterface?,
|
||||
private val codeSpec: ObjCExportCodeSpec?
|
||||
) {
|
||||
private val context = generationState.context
|
||||
private val target get() = context.config.target
|
||||
private val topLevelNamePrefix get() = context.objCExportTopLevelNamePrefix
|
||||
|
||||
@@ -68,7 +69,7 @@ internal class ObjCExport(
|
||||
internal fun generate(codegen: CodeGenerator) {
|
||||
if (!target.family.isAppleFamily) return
|
||||
|
||||
if (context.generationState.shouldDefineFunctionClasses) {
|
||||
if (generationState.shouldDefineFunctionClasses) {
|
||||
ObjCExportBlockCodeGenerator(codegen).generate()
|
||||
}
|
||||
|
||||
@@ -101,7 +102,7 @@ internal class ObjCExport(
|
||||
}
|
||||
|
||||
private fun produceFrameworkSpecific(headerLines: List<String>) {
|
||||
val frameworkDirectory = File(context.generationState.outputFile)
|
||||
val frameworkDirectory = File(generationState.outputFile)
|
||||
val frameworkName = frameworkDirectory.name.removeSuffix(".framework")
|
||||
val frameworkBuilder = FrameworkBuilder(
|
||||
context.config,
|
||||
@@ -154,7 +155,7 @@ internal class ObjCExport(
|
||||
val result = Command(clangCommand).getResult(withErrors = true)
|
||||
|
||||
if (result.exitCode == 0) {
|
||||
context.generationState.llvm.additionalProducedBitcodeFiles += bitcode.absolutePath
|
||||
generationState.llvm.additionalProducedBitcodeFiles += bitcode.absolutePath
|
||||
} else {
|
||||
// Note: ignoring compile errors intentionally.
|
||||
// In this case resulting framework will likely be unusable due to compile errors when importing it.
|
||||
|
||||
+4
-3
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.konan.optimizations
|
||||
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.getBasicBlocks
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.getFunctions
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.getInstructions
|
||||
@@ -31,10 +32,10 @@ private fun process(function: LLVMValueRef, currentThreadTLV: LLVMValueRef) {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun removeMultipleThreadDataLoads(context: Context) {
|
||||
val currentThreadTLV = context.generationState.llvm.runtimeAnnotationMap["current_thread_tlv"]?.singleOrNull() ?: return
|
||||
internal fun removeMultipleThreadDataLoads(generationState: NativeGenerationState) {
|
||||
val currentThreadTLV = generationState.llvm.runtimeAnnotationMap["current_thread_tlv"]?.singleOrNull() ?: return
|
||||
|
||||
getFunctions(context.generationState.llvm.module)
|
||||
getFunctions(generationState.llvm.module)
|
||||
.filter { it.name?.startsWith("kfun:") == true }
|
||||
.filterNot { LLVMIsDeclaration(it) == 1 }
|
||||
.forEach { process(it, currentThreadTLV) }
|
||||
|
||||
Reference in New Issue
Block a user