[K/N] Make overridden runtime variables available during stdlib lto
This commit is contained in:
+3
-2
@@ -8,10 +8,9 @@ package org.jetbrains.kotlin.backend.konan
|
||||
import llvm.LLVMModuleCreateWithNameInContext
|
||||
import llvm.LLVMModuleRef
|
||||
import llvm.LLVMStripModuleDebugInfo
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.getName
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.llvmContext
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.llvmLinkModules2
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.parseBitcodeFile
|
||||
|
||||
/**
|
||||
* To avoid combinatorial explosion, we split runtime into several LLVM modules.
|
||||
@@ -83,6 +82,8 @@ internal sealed class RuntimeLinkageStrategy {
|
||||
LLVMStripModuleDebugInfo(parsedModule)
|
||||
}
|
||||
parsedModule
|
||||
}?.let {
|
||||
it + context.generateRuntimeConstantsModule()
|
||||
}
|
||||
return when {
|
||||
runtimeLlvmModules == null -> return None
|
||||
|
||||
+24
-24
@@ -439,7 +439,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
codegen.objCDataGenerator?.finishModule()
|
||||
|
||||
context.coverage.writeRegionInfo()
|
||||
setRuntimeConstGlobals()
|
||||
overrideRuntimeGlobals()
|
||||
appendLlvmUsed("llvm.used", context.llvm.usedFunctions + context.llvm.usedGlobals)
|
||||
appendLlvmUsed("llvm.compiler.used", context.llvm.compilerUsedGlobals)
|
||||
@@ -2721,29 +2720,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
LLVMSetSection(llvmUsedGlobal.llvmGlobal, "llvm.metadata")
|
||||
}
|
||||
|
||||
// Globals set this way will be const, but can only be built into runtime-containing module. Which
|
||||
// means they are set at stdlib-cache compilation time.
|
||||
private fun setRuntimeConstGlobal(name: String, value: ConstValue) {
|
||||
val global = context.llvm.staticData.placeGlobal(name, value)
|
||||
global.setConstant(true)
|
||||
global.setLinkage(LLVMLinkage.LLVMExternalLinkage)
|
||||
}
|
||||
|
||||
private fun setRuntimeConstGlobals() {
|
||||
if (!context.producedLlvmModuleContainsStdlib)
|
||||
return
|
||||
|
||||
setRuntimeConstGlobal("Kotlin_needDebugInfo", Int32(if (context.shouldContainDebugInfo()) 1 else 0))
|
||||
setRuntimeConstGlobal("Kotlin_runtimeAssertsMode", Int32(context.config.runtimeAssertsMode.value))
|
||||
val runtimeLogs = context.config.runtimeLogs?.let {
|
||||
context.llvm.staticData.cStringLiteral(it)
|
||||
} ?: NullPointer(int8Type)
|
||||
setRuntimeConstGlobal("Kotlin_runtimeLogs", runtimeLogs)
|
||||
setRuntimeConstGlobal("Kotlin_freezingEnabled", Int32(if (context.config.freezing.enableFreezeAtRuntime) 1 else 0))
|
||||
setRuntimeConstGlobal("Kotlin_freezingChecksEnabled", Int32(if (context.config.freezing.enableFreezeChecks) 1 else 0))
|
||||
setRuntimeConstGlobal("Kotlin_gcSchedulerType", Int32(context.config.gcSchedulerType.value))
|
||||
}
|
||||
|
||||
// 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.
|
||||
@@ -2964,3 +2940,27 @@ internal class LocationInfo(val scope: DIScopeOpaqueRef,
|
||||
assert(line != 0)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Context.generateRuntimeConstantsModule() : LLVMModuleRef {
|
||||
val llvmModule = LLVMModuleCreateWithNameInContext("constants", llvmContext)!!
|
||||
LLVMSetDataLayout(llvmModule, llvm.runtime.dataLayout)
|
||||
val static = StaticData(llvmModule)
|
||||
|
||||
fun setRuntimeConstGlobal(name: String, value: ConstValue) {
|
||||
val global = static.placeGlobal(name, value)
|
||||
global.setConstant(true)
|
||||
global.setLinkage(LLVMLinkage.LLVMExternalLinkage)
|
||||
}
|
||||
|
||||
setRuntimeConstGlobal("Kotlin_needDebugInfo", Int32(if (shouldContainDebugInfo()) 1 else 0))
|
||||
setRuntimeConstGlobal("Kotlin_runtimeAssertsMode", Int32(config.runtimeAssertsMode.value))
|
||||
val runtimeLogs = config.runtimeLogs?.let {
|
||||
static.cStringLiteral(it)
|
||||
} ?: NullPointer(int8Type)
|
||||
setRuntimeConstGlobal("Kotlin_runtimeLogs", runtimeLogs)
|
||||
setRuntimeConstGlobal("Kotlin_freezingEnabled", Int32(if (config.freezing.enableFreezeAtRuntime) 1 else 0))
|
||||
setRuntimeConstGlobal("Kotlin_freezingChecksEnabled", Int32(if (config.freezing.enableFreezeChecks) 1 else 0))
|
||||
setRuntimeConstGlobal("Kotlin_gcSchedulerType", Int32(config.gcSchedulerType.value))
|
||||
|
||||
return llvmModule
|
||||
}
|
||||
@@ -27,7 +27,7 @@ using string_view = std::experimental::string_view;
|
||||
/**
|
||||
* There are two ways, how compiler can define variables for runtime usage. This one, and the other one with details in source file.
|
||||
*
|
||||
* This is one is variables defined by setRuntimeConstGlobals in IrToBitcode.kt. They are eligible for runtime optimizations,
|
||||
* This is one is variables defined by generateRuntimeConstantsModule in IrToBitcode.kt. They are eligible for runtime optimizations,
|
||||
* and fixed at the point of compiling caches. So use this way for variables, which are heavily used on performance-critical passes or
|
||||
* will significantly increase code size, if not eliminated.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user