[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.LLVMModuleCreateWithNameInContext
|
||||||
import llvm.LLVMModuleRef
|
import llvm.LLVMModuleRef
|
||||||
import llvm.LLVMStripModuleDebugInfo
|
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.llvmContext
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.llvmLinkModules2
|
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.
|
* To avoid combinatorial explosion, we split runtime into several LLVM modules.
|
||||||
@@ -83,6 +82,8 @@ internal sealed class RuntimeLinkageStrategy {
|
|||||||
LLVMStripModuleDebugInfo(parsedModule)
|
LLVMStripModuleDebugInfo(parsedModule)
|
||||||
}
|
}
|
||||||
parsedModule
|
parsedModule
|
||||||
|
}?.let {
|
||||||
|
it + context.generateRuntimeConstantsModule()
|
||||||
}
|
}
|
||||||
return when {
|
return when {
|
||||||
runtimeLlvmModules == null -> return None
|
runtimeLlvmModules == null -> return None
|
||||||
|
|||||||
+24
-24
@@ -439,7 +439,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
codegen.objCDataGenerator?.finishModule()
|
codegen.objCDataGenerator?.finishModule()
|
||||||
|
|
||||||
context.coverage.writeRegionInfo()
|
context.coverage.writeRegionInfo()
|
||||||
setRuntimeConstGlobals()
|
|
||||||
overrideRuntimeGlobals()
|
overrideRuntimeGlobals()
|
||||||
appendLlvmUsed("llvm.used", context.llvm.usedFunctions + context.llvm.usedGlobals)
|
appendLlvmUsed("llvm.used", context.llvm.usedFunctions + context.llvm.usedGlobals)
|
||||||
appendLlvmUsed("llvm.compiler.used", context.llvm.compilerUsedGlobals)
|
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")
|
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.
|
// Globals set this way cannot be const, but are overridable when producing final executable.
|
||||||
private fun overrideRuntimeGlobal(name: String, value: ConstValue) {
|
private fun overrideRuntimeGlobal(name: String, value: ConstValue) {
|
||||||
// TODO: A similar mechanism is used in `ObjCExportCodeGenerator`. Consider merging them.
|
// TODO: A similar mechanism is used in `ObjCExportCodeGenerator`. Consider merging them.
|
||||||
@@ -2964,3 +2940,27 @@ internal class LocationInfo(val scope: DIScopeOpaqueRef,
|
|||||||
assert(line != 0)
|
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.
|
* 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
|
* 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.
|
* will significantly increase code size, if not eliminated.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user