Use clang instead if llvm-lto for darwin-based targets (#2974)
* Use LLVM C API for optimizations * Use Clang for bitcode compilation * Test bitcode embedding
This commit is contained in:
@@ -171,7 +171,6 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
||||
put(VERBOSE_PHASES,
|
||||
arguments.verbosePhases.toNonNullList())
|
||||
put(LIST_PHASES, arguments.listPhases)
|
||||
put(TIME_PHASES, arguments.timePhases)
|
||||
|
||||
put(COMPATIBLE_COMPILER_VERSIONS,
|
||||
arguments.compatibleCompilerVersions.toNonNullList())
|
||||
|
||||
@@ -153,9 +153,6 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
|
||||
@Argument(value = "-Xtemporary-files-dir", deprecatedName = "--temporary_files_dir", valueDescription = "<path>", description = "Save temporary files to the given directory")
|
||||
var temporaryFilesDir: String? = null
|
||||
|
||||
@Argument(value = "-Xtime", deprecatedName = "--time", description = "Report execution time for compiler phases")
|
||||
var timePhases: Boolean = false
|
||||
|
||||
@Argument(value = "-Xverify-bitcode", deprecatedName = "--verify_bitcode", description = "Verify llvm bitcode after each method")
|
||||
var verifyBitCode: Boolean = false
|
||||
|
||||
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.parseBitcodeFile
|
||||
import org.jetbrains.kotlin.konan.exec.Command
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
|
||||
typealias BitcodeFile = String
|
||||
typealias ObjectFile = String
|
||||
typealias ExecutableFile = String
|
||||
|
||||
private fun mangleSymbol(target: KonanTarget,symbol: String) =
|
||||
if (target.family == Family.IOS || target.family == Family.OSX) {
|
||||
"_$symbol"
|
||||
} else {
|
||||
symbol
|
||||
}
|
||||
|
||||
internal class BitcodeCompiler(val context: Context) {
|
||||
|
||||
private val target = context.config.target
|
||||
private val platform = context.config.platform
|
||||
private val optimize = context.shouldOptimize()
|
||||
private val debug = context.config.debug
|
||||
|
||||
private fun MutableList<String>.addNonEmpty(elements: List<String>) {
|
||||
addAll(elements.filter { !it.isEmpty() })
|
||||
}
|
||||
|
||||
private val exportedSymbols = context.coverage.addExportedSymbols()
|
||||
|
||||
private fun runTool(vararg command: String) =
|
||||
Command(*command)
|
||||
.logWith(context::log)
|
||||
.execute()
|
||||
|
||||
private fun temporary(name: String, suffix: String): String =
|
||||
context.config.tempFiles.create(name, suffix).absolutePath
|
||||
|
||||
private fun targetTool(tool: String, vararg arg: String) {
|
||||
val absoluteToolName = if (platform.configurables is AppleConfigurables) {
|
||||
"${platform.absoluteTargetToolchain}/usr/bin/$tool"
|
||||
} else {
|
||||
"${platform.absoluteTargetToolchain}/bin/$tool"
|
||||
}
|
||||
runTool(absoluteToolName, *arg)
|
||||
}
|
||||
|
||||
private fun hostLlvmTool(tool: String, vararg arg: String) {
|
||||
val absoluteToolName = "${platform.absoluteLlvmHome}/bin/$tool"
|
||||
runTool(absoluteToolName, *arg)
|
||||
}
|
||||
|
||||
private fun llvmLto(configurables: LlvmLtoFlags, file: BitcodeFile): ObjectFile {
|
||||
val combined = temporary("combined", ".o")
|
||||
val arguments = mutableListOf<String>().apply {
|
||||
addNonEmpty(configurables.llvmLtoFlags)
|
||||
addNonEmpty(llvmProfilingFlags())
|
||||
when {
|
||||
optimize -> addNonEmpty(configurables.llvmLtoOptFlags)
|
||||
debug -> addNonEmpty(platform.llvmDebugOptFlags)
|
||||
else -> addNonEmpty(configurables.llvmLtoNooptFlags)
|
||||
}
|
||||
addNonEmpty(configurables.llvmLtoDynamicFlags)
|
||||
add(file)
|
||||
// Prevent symbols from being deleted by DCE.
|
||||
addNonEmpty(exportedSymbols.map { "-exported-symbol=${mangleSymbol(target, it)}"} )
|
||||
}
|
||||
hostLlvmTool("llvm-lto", "-o", combined, *arguments.toTypedArray())
|
||||
return combined
|
||||
}
|
||||
|
||||
private fun opt(optFlags: OptFlags, bitcodeFile: BitcodeFile): BitcodeFile {
|
||||
val flags = (optFlags.optFlags + when {
|
||||
optimize -> optFlags.optOptFlags
|
||||
debug -> optFlags.optDebugFlags
|
||||
else -> optFlags.optNooptFlags
|
||||
} + llvmProfilingFlags()).toTypedArray()
|
||||
val optimizedBc = temporary("opt_output", ".bc")
|
||||
hostLlvmTool("opt", bitcodeFile, "-o", optimizedBc, *flags)
|
||||
|
||||
if (shouldRunLateBitcodePasses(context)) {
|
||||
val module = parseBitcodeFile(optimizedBc)
|
||||
runLateBitcodePasses(context, module)
|
||||
LLVMWriteBitcodeToFile(module, optimizedBc)
|
||||
}
|
||||
|
||||
return optimizedBc
|
||||
}
|
||||
|
||||
private fun llc(llcFlags: LlcFlags, bitcodeFile: BitcodeFile): ObjectFile {
|
||||
val flags = (llcFlags.llcFlags + when {
|
||||
optimize -> llcFlags.llcOptFlags
|
||||
debug -> llcFlags.llcDebugFlags
|
||||
else -> llcFlags.llcNooptFlags
|
||||
} + llvmProfilingFlags()).toTypedArray()
|
||||
val combinedO = temporary("llc_output", ".o")
|
||||
hostLlvmTool("llc", bitcodeFile, "-o", combinedO, *flags, "-filetype=obj")
|
||||
return combinedO
|
||||
}
|
||||
|
||||
private fun bitcodeToWasm(configurables: WasmConfigurables, file: BitcodeFile): String {
|
||||
val optimizedBc = opt(configurables, file)
|
||||
val compiled = llc(configurables, optimizedBc)
|
||||
|
||||
// TODO: should be moved to linker.
|
||||
val linkedWasm = temporary("linked", ".wasm")
|
||||
hostLlvmTool("wasm-ld", compiled, "-o", linkedWasm, *configurables.lldFlags.toTypedArray())
|
||||
|
||||
return linkedWasm
|
||||
}
|
||||
|
||||
private fun optAndLlc(configurables: ZephyrConfigurables, file: BitcodeFile): String {
|
||||
val optimizedBc = temporary("optimized", ".bc")
|
||||
val optFlags = llvmProfilingFlags() + listOf("-O3", "-internalize", "-globaldce")
|
||||
hostLlvmTool("opt", file, "-o=$optimizedBc", *optFlags.toTypedArray())
|
||||
|
||||
val combinedO = temporary("combined", ".o")
|
||||
val llcFlags = llvmProfilingFlags() + listOf("-function-sections", "-data-sections")
|
||||
hostLlvmTool("llc", optimizedBc, "-filetype=obj", "-o", combinedO, *llcFlags.toTypedArray())
|
||||
|
||||
return combinedO
|
||||
}
|
||||
|
||||
private fun clang(configurables: AppleConfigurables, file: BitcodeFile): ObjectFile {
|
||||
val objectFile = temporary("result", ".o")
|
||||
|
||||
val profilingFlags = llvmProfilingFlags().map { listOf("-mllvm", it) }.flatten()
|
||||
|
||||
val flags = mutableListOf<String>().apply {
|
||||
addNonEmpty(configurables.clangFlags)
|
||||
addNonEmpty(listOf("-triple", context.llvm.targetTriple))
|
||||
addNonEmpty(when {
|
||||
optimize -> configurables.clangOptFlags
|
||||
debug -> configurables.clangDebugFlags
|
||||
else -> configurables.clangNooptFlags
|
||||
})
|
||||
addNonEmpty(BitcodeEmbedding.getClangOptions(context.config))
|
||||
if (determineLinkerOutput(context) == LinkerOutputKind.DYNAMIC_LIBRARY) {
|
||||
addNonEmpty(configurables.clangDynamicFlags)
|
||||
}
|
||||
addNonEmpty(profilingFlags)
|
||||
}
|
||||
targetTool("clang++", *flags.toTypedArray(), file, "-o", objectFile)
|
||||
return objectFile
|
||||
}
|
||||
|
||||
// llvm-lto, opt and llc share same profiling flags, so we can
|
||||
// reuse this function.
|
||||
private fun llvmProfilingFlags(): List<String> {
|
||||
val flags = mutableListOf<String>()
|
||||
if (context.shouldProfilePhases()) {
|
||||
flags += "-time-passes"
|
||||
}
|
||||
if (context.inVerbosePhase) {
|
||||
flags += "-debug-pass=Structure"
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
fun makeObjectFiles(bitcodeFile: BitcodeFile): List<ObjectFile> =
|
||||
listOf(when (val configurables = platform.configurables) {
|
||||
is AppleConfigurables ->
|
||||
clang(configurables, bitcodeFile)
|
||||
is WasmConfigurables ->
|
||||
bitcodeToWasm(configurables, bitcodeFile)
|
||||
is ZephyrConfigurables ->
|
||||
optAndLlc(configurables, bitcodeFile)
|
||||
is LlvmLtoFlags ->
|
||||
llvmLto(configurables, bitcodeFile)
|
||||
else ->
|
||||
error("Unsupported configurables kind: ${configurables::class.simpleName}!")
|
||||
})
|
||||
}
|
||||
+6
@@ -16,6 +16,12 @@ object BitcodeEmbedding {
|
||||
Mode.FULL -> listOf("-bitcode_bundle")
|
||||
}
|
||||
|
||||
internal fun getClangOptions(config: KonanConfig): List<String> = when (config.bitcodeEmbeddingMode) {
|
||||
BitcodeEmbedding.Mode.NONE -> listOf("-fembed-bitcode=off")
|
||||
BitcodeEmbedding.Mode.MARKER -> listOf("-fembed-bitcode=marker")
|
||||
BitcodeEmbedding.Mode.FULL -> listOf("-fembed-bitcode=all")
|
||||
}
|
||||
|
||||
private val KonanConfig.bitcodeEmbeddingMode get() = configuration.get(KonanConfigKeys.BITCODE_EMBEDDING_MODE)!!.also {
|
||||
require(it == Mode.NONE || this.produce == CompilerOutputKind.FRAMEWORK) {
|
||||
"${it.name.toLowerCase()} bitcode embedding mode is not supported when producing ${this.produce.name.toLowerCase()}"
|
||||
|
||||
+31
-30
@@ -4,16 +4,19 @@
|
||||
*/
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import llvm.*
|
||||
import llvm.LLVMLinkModules2
|
||||
import llvm.LLVMModuleRef
|
||||
import llvm.LLVMWriteBitcodeToFile
|
||||
import org.jetbrains.kotlin.backend.konan.library.impl.buildLibrary
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.Llvm
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.embedLlvmLinkOptions
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.parseBitcodeFile
|
||||
import org.jetbrains.kotlin.konan.CURRENT
|
||||
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.file.isBitcode
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibraryVersioning
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.Family
|
||||
|
||||
val CompilerOutputKind.isNativeBinary: Boolean get() = when (this) {
|
||||
CompilerOutputKind.PROGRAM, CompilerOutputKind.DYNAMIC,
|
||||
@@ -28,20 +31,30 @@ internal fun produceCStubs(context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun shouldRunBitcodePasses(context: Context): Boolean =
|
||||
context.coverage.enabled
|
||||
private fun linkAllDependecies(context: Context, generatedBitcodeFiles: List<String>) {
|
||||
|
||||
val nativeLibraries = context.config.nativeLibraries + context.config.defaultNativeLibraries
|
||||
val bitcodeLibraries = context.llvm.bitcodeToLink.map { it.bitcodePaths }.flatten().filter { it.isBitcode }
|
||||
val additionalBitcodeFilesToLink = context.llvm.additionalProducedBitcodeFiles
|
||||
val bitcodeFiles = (nativeLibraries + generatedBitcodeFiles + additionalBitcodeFilesToLink + bitcodeLibraries).toSet()
|
||||
|
||||
internal fun runBitcodePasses(context: Context) {
|
||||
if (!shouldRunBitcodePasses(context)) {
|
||||
return
|
||||
}
|
||||
val llvmModule = context.llvmModule!!
|
||||
val passManager = LLVMCreatePassManager()!!
|
||||
val targetLibraryInfo = LLVMGetTargetLibraryInfo(llvmModule)
|
||||
LLVMAddTargetLibraryInfo(targetLibraryInfo, passManager)
|
||||
context.coverage.addLlvmPasses(passManager)
|
||||
LLVMRunPassManager(passManager, llvmModule)
|
||||
LLVMDisposePassManager(passManager)
|
||||
bitcodeFiles.forEach {
|
||||
parseAndLinkBitcodeFile(llvmModule, it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun shouldOptimizeWithLlvmApi(context: Context) =
|
||||
(context.config.target.family == Family.IOS || context.config.target.family == Family.OSX)
|
||||
|
||||
private fun shoudRunClosedWorldCleanUp(context: Context) =
|
||||
// GlobalDCE will kill coverage-related globals.
|
||||
!context.coverage.enabled
|
||||
|
||||
private fun runLlvmPipeline(context: Context) = when {
|
||||
shouldOptimizeWithLlvmApi(context) -> runLlvmOptimizationPipeline(context)
|
||||
shoudRunClosedWorldCleanUp(context) -> runClosedWorldCleanup(context)
|
||||
else -> {}
|
||||
}
|
||||
|
||||
internal fun produceOutput(context: Context) {
|
||||
@@ -57,7 +70,6 @@ internal fun produceOutput(context: Context) {
|
||||
CompilerOutputKind.PROGRAM -> {
|
||||
val output = tempFiles.nativeBinaryFileName
|
||||
context.bitcodeFileName = output
|
||||
|
||||
val generatedBitcodeFiles =
|
||||
if (produce == CompilerOutputKind.DYNAMIC || produce == CompilerOutputKind.STATIC) {
|
||||
produceCAdapterBitcode(
|
||||
@@ -66,20 +78,11 @@ internal fun produceOutput(context: Context) {
|
||||
tempFiles.cAdapterBitcodeName)
|
||||
listOf(tempFiles.cAdapterBitcodeName)
|
||||
} else emptyList()
|
||||
|
||||
val nativeLibraries =
|
||||
context.config.nativeLibraries +
|
||||
context.config.defaultNativeLibraries +
|
||||
generatedBitcodeFiles
|
||||
|
||||
for (library in nativeLibraries) {
|
||||
parseAndLinkBitcodeFile(context.llvmModule!!, library)
|
||||
}
|
||||
|
||||
if (produce == CompilerOutputKind.FRAMEWORK && context.config.produceStaticFramework) {
|
||||
embedAppleLinkerOptionsToBitcode(context.llvm, context.config)
|
||||
}
|
||||
|
||||
linkAllDependecies(context, generatedBitcodeFiles)
|
||||
runLlvmPipeline(context)
|
||||
LLVMWriteBitcodeToFile(context.llvmModule!!, output)
|
||||
}
|
||||
CompilerOutputKind.LIBRARY -> {
|
||||
@@ -94,7 +97,6 @@ internal fun produceOutput(context: Context) {
|
||||
val nopack = config.getBoolean(KonanConfigKeys.NOPACK)
|
||||
val manifestProperties = context.config.manifestProperties
|
||||
|
||||
|
||||
val library = buildLibrary(
|
||||
context.config.nativeLibraries,
|
||||
context.config.includeBinaries,
|
||||
@@ -109,7 +111,6 @@ internal fun produceOutput(context: Context) {
|
||||
manifestProperties,
|
||||
context.dataFlowGraph)
|
||||
|
||||
context.library = library
|
||||
context.bitcodeFileName = library.mainBitcodeFileName
|
||||
}
|
||||
CompilerOutputKind.BITCODE -> {
|
||||
@@ -147,4 +148,4 @@ private fun embedAppleLinkerOptionsToBitcode(llvm: Llvm, config: KonanConfig) {
|
||||
llvm.nativeDependenciesToLink.flatMap { findEmbeddableOptions(it.linkerOpts) }
|
||||
|
||||
embedLlvmLinkOptions(llvm.llvmModule, optionsToEmbed)
|
||||
}
|
||||
}
|
||||
+3
-5
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.backend.common.descriptors.WrappedTypeParameterDescr
|
||||
import org.jetbrains.kotlin.backend.common.validateIrModule
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.ir.KonanIr
|
||||
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryWriter
|
||||
import org.jetbrains.kotlin.backend.konan.library.LinkData
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_BRIDGE_METHOD
|
||||
@@ -40,7 +39,6 @@ import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
@@ -54,6 +52,7 @@ import org.jetbrains.kotlin.backend.common.serialization.KotlinMangler
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
/**
|
||||
* Offset for synthetic elements created by lowerings and not attributable to other places in the source code.
|
||||
@@ -322,7 +321,6 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||
val llvmImports: LlvmImports = Llvm.ImportsImpl(this)
|
||||
lateinit var llvmDeclarations: LlvmDeclarations
|
||||
lateinit var bitcodeFileName: String
|
||||
lateinit var library: KonanLibraryWriter
|
||||
|
||||
val cStubsManager = CStubsManager(config.target)
|
||||
|
||||
@@ -441,7 +439,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||
|
||||
fun shouldPrintLocations() = config.configuration.getBoolean(KonanConfigKeys.PRINT_LOCATIONS)
|
||||
|
||||
fun shouldProfilePhases() = config.configuration.getBoolean(KonanConfigKeys.TIME_PHASES)
|
||||
fun shouldProfilePhases() = config.phaseConfig.needProfiling
|
||||
|
||||
fun shouldContainDebugInfo() = config.debug
|
||||
|
||||
@@ -469,7 +467,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||
internal val stdlibModule
|
||||
get() = this.builtIns.any.module
|
||||
|
||||
lateinit var linkStage: LinkStage
|
||||
lateinit var compilerOutput: List<ObjectFile>
|
||||
}
|
||||
|
||||
private fun MemberScope.getContributedClassifier(name: String) =
|
||||
|
||||
-2
@@ -96,8 +96,6 @@ class KonanConfigKeys {
|
||||
= CompilerConfigurationKey.create("target we compile for")
|
||||
val TEMPORARY_FILES_DIR: CompilerConfigurationKey<String?>
|
||||
= CompilerConfigurationKey.create("directory for temporary files")
|
||||
val TIME_PHASES: CompilerConfigurationKey<Boolean>
|
||||
= CompilerConfigurationKey.create("time backend phases")
|
||||
val VERIFY_BITCODE: CompilerConfigurationKey<Boolean>
|
||||
= CompilerConfigurationKey.create("verify bitcode")
|
||||
val VERIFY_DESCRIPTORS: CompilerConfigurationKey<Boolean>
|
||||
|
||||
-250
@@ -1,250 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import org.jetbrains.kotlin.konan.KonanExternalToolFailure
|
||||
import org.jetbrains.kotlin.konan.exec.Command
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.file.isBitcode
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
|
||||
typealias BitcodeFile = String
|
||||
typealias ObjectFile = String
|
||||
typealias ExecutableFile = String
|
||||
|
||||
private fun determineLinkerOutput(context: Context): LinkerOutputKind =
|
||||
when (context.config.produce) {
|
||||
CompilerOutputKind.FRAMEWORK -> {
|
||||
val staticFramework = context.config.produceStaticFramework
|
||||
if (staticFramework) LinkerOutputKind.STATIC_LIBRARY else LinkerOutputKind.DYNAMIC_LIBRARY
|
||||
}
|
||||
CompilerOutputKind.DYNAMIC -> LinkerOutputKind.DYNAMIC_LIBRARY
|
||||
CompilerOutputKind.STATIC -> LinkerOutputKind.STATIC_LIBRARY
|
||||
CompilerOutputKind.PROGRAM -> LinkerOutputKind.EXECUTABLE
|
||||
else -> TODO("${context.config.produce} should not reach native linker stage")
|
||||
}
|
||||
|
||||
internal class LinkStage(val context: Context) {
|
||||
|
||||
private val config = context.config.configuration
|
||||
private val target = context.config.target
|
||||
private val platform = context.config.platform
|
||||
private val linker = platform.linker
|
||||
|
||||
private val optimize = context.shouldOptimize()
|
||||
private val debug = context.config.debug
|
||||
private val linkerOutput = determineLinkerOutput(context)
|
||||
|
||||
private val nomain = config.get(KonanConfigKeys.NOMAIN) ?: false
|
||||
private val emitted = context.bitcodeFileName
|
||||
|
||||
private val bitcodeLibraries = context.llvm.bitcodeToLink
|
||||
private val nativeDependencies = context.llvm.nativeDependenciesToLink
|
||||
|
||||
private val additionalBitcodeFilesToLink = context.llvm.additionalProducedBitcodeFiles
|
||||
|
||||
private fun MutableList<String>.addNonEmpty(elements: List<String>) {
|
||||
addAll(elements.filter { !it.isEmpty() })
|
||||
}
|
||||
|
||||
private val exportedSymbols = context.coverage.addExportedSymbols()
|
||||
|
||||
private fun mangleSymbol(symbol: String) =
|
||||
if (target.family == Family.IOS || target.family == Family.OSX) {
|
||||
"_$symbol"
|
||||
} else {
|
||||
symbol
|
||||
}
|
||||
|
||||
private fun runTool(command: List<String>) = runTool(*command.toTypedArray())
|
||||
private fun runTool(vararg command: String) =
|
||||
Command(*command)
|
||||
.logWith(context::log)
|
||||
.execute()
|
||||
|
||||
private fun llvmLto(files: List<BitcodeFile>): ObjectFile {
|
||||
val combined = temporary("combined", ".o")
|
||||
|
||||
val tool = "${platform.absoluteLlvmHome}/bin/llvm-lto"
|
||||
val command = mutableListOf(tool, "-o", combined)
|
||||
command.addNonEmpty(platform.llvmLtoFlags)
|
||||
command.addNonEmpty(llvmProfilingFlags())
|
||||
when {
|
||||
optimize -> command.addNonEmpty(platform.llvmLtoOptFlags)
|
||||
debug -> command.addNonEmpty(platform.llvmDebugOptFlags)
|
||||
else -> command.addNonEmpty(platform.llvmLtoNooptFlags)
|
||||
}
|
||||
command.addNonEmpty(platform.llvmLtoDynamicFlags)
|
||||
command.addNonEmpty(files)
|
||||
// Prevent symbols from being deleted by DCE.
|
||||
command.addNonEmpty(exportedSymbols.map { "-exported-symbol=${mangleSymbol(it)}"} )
|
||||
runTool(command)
|
||||
|
||||
return combined
|
||||
}
|
||||
|
||||
private fun temporary(name: String, suffix: String): String =
|
||||
context.config.tempFiles.create(name, suffix).absolutePath
|
||||
|
||||
private fun targetTool(tool: String, vararg arg: String) {
|
||||
val absoluteToolName = "${platform.absoluteTargetToolchain}/bin/$tool"
|
||||
runTool(absoluteToolName, *arg)
|
||||
}
|
||||
|
||||
private fun hostLlvmTool(tool: String, vararg arg: String) {
|
||||
val absoluteToolName = "${platform.absoluteLlvmHome}/bin/$tool"
|
||||
runTool(absoluteToolName, *arg)
|
||||
}
|
||||
|
||||
private fun bitcodeToWasm(bitcodeFiles: List<BitcodeFile>): String {
|
||||
val configurables = platform.configurables as WasmConfigurables
|
||||
|
||||
val combinedBc = temporary("combined", ".bc")
|
||||
// TODO: use -only-needed for the stdlib
|
||||
hostLlvmTool("llvm-link", *bitcodeFiles.toTypedArray(), "-o", combinedBc)
|
||||
val optFlags = (configurables.optFlags + when {
|
||||
optimize -> configurables.optOptFlags
|
||||
debug -> configurables.optDebugFlags
|
||||
else -> configurables.optNooptFlags
|
||||
} + llvmProfilingFlags()).toTypedArray()
|
||||
val optimizedBc = temporary("optimized", ".bc")
|
||||
hostLlvmTool("opt", combinedBc, "-o", optimizedBc, *optFlags)
|
||||
val llcFlags = (configurables.llcFlags + when {
|
||||
optimize -> configurables.llcOptFlags
|
||||
debug -> configurables.llcDebugFlags
|
||||
else -> configurables.llcNooptFlags
|
||||
} + llvmProfilingFlags()).toTypedArray()
|
||||
val combinedO = temporary("combined", ".o")
|
||||
hostLlvmTool("llc", optimizedBc, "-o", combinedO, *llcFlags, "-filetype=obj")
|
||||
val linkedWasm = temporary("linked", ".wasm")
|
||||
hostLlvmTool("wasm-ld", combinedO, "-o", linkedWasm, *configurables.lldFlags.toTypedArray())
|
||||
return linkedWasm
|
||||
}
|
||||
|
||||
private fun llvmLinkAndLlc(bitcodeFiles: List<BitcodeFile>): String {
|
||||
val combinedBc = temporary("combined", ".bc")
|
||||
hostLlvmTool("llvm-link", "-o", combinedBc, *bitcodeFiles.toTypedArray())
|
||||
|
||||
val optimizedBc = temporary("optimized", ".bc")
|
||||
val optFlags = llvmProfilingFlags() + listOf("-O3", "-internalize", "-globaldce")
|
||||
hostLlvmTool("opt", combinedBc, "-o=$optimizedBc", *optFlags.toTypedArray())
|
||||
|
||||
val combinedO = temporary("combined", ".o")
|
||||
val llcFlags = llvmProfilingFlags() + listOf("-function-sections", "-data-sections")
|
||||
hostLlvmTool("llc", optimizedBc, "-filetype=obj", "-o", combinedO, *llcFlags.toTypedArray())
|
||||
|
||||
return combinedO
|
||||
}
|
||||
|
||||
// llvm-lto, opt and llc share same profiling flags, so we can
|
||||
// reuse this function.
|
||||
private fun llvmProfilingFlags(): List<String> {
|
||||
val flags = mutableListOf<String>()
|
||||
if (context.shouldProfilePhases()) {
|
||||
flags += "-time-passes"
|
||||
}
|
||||
if (context.inVerbosePhase) {
|
||||
flags += "-debug-pass=Structure"
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
private fun asLinkerArgs(args: List<String>): List<String> {
|
||||
if (linker.useCompilerDriverAsLinker) {
|
||||
return args
|
||||
}
|
||||
|
||||
val result = mutableListOf<String>()
|
||||
for (arg in args) {
|
||||
// If user passes compiler arguments to us - transform them to linker ones.
|
||||
if (arg.startsWith("-Wl,")) {
|
||||
result.addAll(arg.substring(4).split(','))
|
||||
} else {
|
||||
result.add(arg)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Ideally we'd want to have
|
||||
// #pragma weak main = Konan_main
|
||||
// in the launcher.cpp.
|
||||
// Unfortunately, anything related to weak linking on MacOS
|
||||
// only seems to be working with dynamic libraries.
|
||||
// So we stick to "-alias _main _konan_main" on Mac.
|
||||
// And just do the same on Linux.
|
||||
private val entryPointSelector: List<String>
|
||||
get() = if (nomain || linkerOutput != LinkerOutputKind.EXECUTABLE) emptyList() else platform.entrySelector
|
||||
|
||||
private fun link(objectFiles: List<ObjectFile>,
|
||||
includedBinaries: List<String>,
|
||||
libraryProvidedLinkerFlags: List<String>): ExecutableFile? {
|
||||
val frameworkLinkerArgs: List<String>
|
||||
val executable: String
|
||||
|
||||
if (context.config.produce != CompilerOutputKind.FRAMEWORK) {
|
||||
frameworkLinkerArgs = emptyList()
|
||||
executable = context.config.outputFile
|
||||
} else {
|
||||
val framework = File(context.config.outputFile)
|
||||
val dylibName = framework.name.removeSuffix(".framework")
|
||||
val dylibRelativePath = when (target.family) {
|
||||
Family.IOS -> dylibName
|
||||
Family.OSX -> "Versions/A/$dylibName"
|
||||
else -> error(target)
|
||||
}
|
||||
frameworkLinkerArgs = listOf("-install_name", "@rpath/${framework.name}/$dylibRelativePath")
|
||||
val dylibPath = framework.child(dylibRelativePath)
|
||||
dylibPath.parentFile.mkdirs()
|
||||
executable = dylibPath.absolutePath
|
||||
}
|
||||
|
||||
try {
|
||||
File(executable).delete()
|
||||
linker.linkCommands(objectFiles = objectFiles, executable = executable,
|
||||
libraries = linker.linkStaticLibraries(includedBinaries) + context.config.defaultSystemLibraries,
|
||||
linkerArgs = entryPointSelector +
|
||||
asLinkerArgs(config.getNotNull(KonanConfigKeys.LINKER_ARGS)) +
|
||||
BitcodeEmbedding.getLinkerOptions(context.config) +
|
||||
libraryProvidedLinkerFlags + frameworkLinkerArgs,
|
||||
optimize = optimize, debug = debug, kind = linkerOutput,
|
||||
outputDsymBundle = context.config.outputFile + ".dSYM").forEach {
|
||||
it.logWith(context::log)
|
||||
it.execute()
|
||||
}
|
||||
} catch (e: KonanExternalToolFailure) {
|
||||
context.reportCompilationError("${e.toolName} invocation reported errors")
|
||||
}
|
||||
return executable
|
||||
}
|
||||
|
||||
val objectFiles = mutableListOf<String>()
|
||||
|
||||
fun makeObjectFiles() {
|
||||
|
||||
val bitcodeFiles = listOf(emitted) + additionalBitcodeFilesToLink +
|
||||
bitcodeLibraries.map { it.bitcodePaths }.flatten().filter { it.isBitcode }
|
||||
|
||||
objectFiles.add(when (platform.configurables) {
|
||||
is WasmConfigurables
|
||||
-> bitcodeToWasm(bitcodeFiles)
|
||||
is ZephyrConfigurables
|
||||
-> llvmLinkAndLlc(bitcodeFiles)
|
||||
else
|
||||
-> llvmLto(bitcodeFiles)
|
||||
})
|
||||
}
|
||||
|
||||
fun linkStage() {
|
||||
val includedBinaries =
|
||||
nativeDependencies.map { it.includedPaths }.flatten()
|
||||
|
||||
val libraryProvidedLinkerFlags =
|
||||
nativeDependencies.map { it.linkerOpts }.flatten()
|
||||
|
||||
link(objectFiles, includedBinaries, libraryProvidedLinkerFlags)
|
||||
}
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import org.jetbrains.kotlin.konan.KonanExternalToolFailure
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.Family
|
||||
import org.jetbrains.kotlin.konan.target.LinkerOutputKind
|
||||
|
||||
internal fun determineLinkerOutput(context: Context): LinkerOutputKind =
|
||||
when (context.config.produce) {
|
||||
CompilerOutputKind.FRAMEWORK -> {
|
||||
val staticFramework = context.config.produceStaticFramework
|
||||
if (staticFramework) LinkerOutputKind.STATIC_LIBRARY else LinkerOutputKind.DYNAMIC_LIBRARY
|
||||
}
|
||||
CompilerOutputKind.DYNAMIC -> LinkerOutputKind.DYNAMIC_LIBRARY
|
||||
CompilerOutputKind.STATIC -> LinkerOutputKind.STATIC_LIBRARY
|
||||
CompilerOutputKind.PROGRAM -> LinkerOutputKind.EXECUTABLE
|
||||
else -> TODO("${context.config.produce} should not reach native linker stage")
|
||||
}
|
||||
|
||||
// TODO: We have a Linker.kt file in the shared module.
|
||||
internal class Linker(val context: Context) {
|
||||
|
||||
private val platform = context.config.platform
|
||||
private val config = context.config.configuration
|
||||
private val linkerOutput = determineLinkerOutput(context)
|
||||
private val nomain = config.get(KonanConfigKeys.NOMAIN) ?: false
|
||||
private val linker = platform.linker
|
||||
private val target = context.config.target
|
||||
private val optimize = context.shouldOptimize()
|
||||
private val debug = context.config.debug
|
||||
|
||||
// Ideally we'd want to have
|
||||
// #pragma weak main = Konan_main
|
||||
// in the launcher.cpp.
|
||||
// Unfortunately, anything related to weak linking on MacOS
|
||||
// only seems to be working with dynamic libraries.
|
||||
// So we stick to "-alias _main _konan_main" on Mac.
|
||||
// And just do the same on Linux.
|
||||
private val entryPointSelector: List<String>
|
||||
get() = if (nomain || linkerOutput != LinkerOutputKind.EXECUTABLE) emptyList() else platform.entrySelector
|
||||
|
||||
fun link(objectFiles: List<ObjectFile>) {
|
||||
val nativeDependencies = context.llvm.nativeDependenciesToLink
|
||||
val includedBinaries = nativeDependencies.map { it.includedPaths }.flatten()
|
||||
val libraryProvidedLinkerFlags = nativeDependencies.map { it.linkerOpts }.flatten()
|
||||
runLinker(objectFiles, includedBinaries, libraryProvidedLinkerFlags)
|
||||
}
|
||||
|
||||
private fun asLinkerArgs(args: List<String>): List<String> {
|
||||
if (linker.useCompilerDriverAsLinker) {
|
||||
return args
|
||||
}
|
||||
|
||||
val result = mutableListOf<String>()
|
||||
for (arg in args) {
|
||||
// If user passes compiler arguments to us - transform them to linker ones.
|
||||
if (arg.startsWith("-Wl,")) {
|
||||
result.addAll(arg.substring(4).split(','))
|
||||
} else {
|
||||
result.add(arg)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun runLinker(objectFiles: List<ObjectFile>,
|
||||
includedBinaries: List<String>,
|
||||
libraryProvidedLinkerFlags: List<String>): ExecutableFile? {
|
||||
val frameworkLinkerArgs: List<String>
|
||||
val executable: String
|
||||
|
||||
if (context.config.produce != CompilerOutputKind.FRAMEWORK) {
|
||||
frameworkLinkerArgs = emptyList()
|
||||
executable = context.config.outputFile
|
||||
} else {
|
||||
val framework = File(context.config.outputFile)
|
||||
val dylibName = framework.name.removeSuffix(".framework")
|
||||
val dylibRelativePath = when (target.family) {
|
||||
Family.IOS -> dylibName
|
||||
Family.OSX -> "Versions/A/$dylibName"
|
||||
else -> error(target)
|
||||
}
|
||||
frameworkLinkerArgs = listOf("-install_name", "@rpath/${framework.name}/$dylibRelativePath")
|
||||
val dylibPath = framework.child(dylibRelativePath)
|
||||
dylibPath.parentFile.mkdirs()
|
||||
executable = dylibPath.absolutePath
|
||||
}
|
||||
|
||||
try {
|
||||
File(executable).delete()
|
||||
linker.linkCommands(objectFiles = objectFiles, executable = executable,
|
||||
libraries = linker.linkStaticLibraries(includedBinaries) + context.config.defaultSystemLibraries,
|
||||
linkerArgs = entryPointSelector +
|
||||
asLinkerArgs(config.getNotNull(KonanConfigKeys.LINKER_ARGS)) +
|
||||
BitcodeEmbedding.getLinkerOptions(context.config) +
|
||||
libraryProvidedLinkerFlags + frameworkLinkerArgs,
|
||||
optimize = optimize, debug = debug, kind = linkerOutput,
|
||||
outputDsymBundle = context.config.outputFile + ".dSYM").forEach {
|
||||
it.logWith(context::log)
|
||||
it.execute()
|
||||
}
|
||||
} catch (e: KonanExternalToolFailure) {
|
||||
context.reportCompilationError("${e.toolName} invocation reported errors")
|
||||
}
|
||||
return executable
|
||||
}
|
||||
|
||||
}
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import kotlinx.cinterop.alloc
|
||||
import kotlinx.cinterop.memScoped
|
||||
import kotlinx.cinterop.ptr
|
||||
import kotlinx.cinterop.value
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
|
||||
private fun initializeLlvmGlobalPassRegistry() {
|
||||
val passRegistry = LLVMGetGlobalPassRegistry()
|
||||
|
||||
LLVMInitializeCore(passRegistry)
|
||||
LLVMInitializeTransformUtils(passRegistry)
|
||||
LLVMInitializeScalarOpts(passRegistry)
|
||||
LLVMInitializeVectorization(passRegistry)
|
||||
LLVMInitializeInstCombine(passRegistry)
|
||||
LLVMInitializeIPO(passRegistry)
|
||||
LLVMInitializeInstrumentation(passRegistry)
|
||||
LLVMInitializeAnalysis(passRegistry)
|
||||
LLVMInitializeIPA(passRegistry)
|
||||
LLVMInitializeCodeGen(passRegistry)
|
||||
LLVMInitializeTarget(passRegistry)
|
||||
}
|
||||
|
||||
internal fun shouldRunLateBitcodePasses(context: Context): Boolean {
|
||||
return context.coverage.enabled
|
||||
}
|
||||
|
||||
internal fun runLateBitcodePasses(context: Context, llvmModule: LLVMModuleRef) {
|
||||
val passManager = LLVMCreatePassManager()!!
|
||||
val targetLibraryInfo = LLVMGetTargetLibraryInfo(llvmModule)
|
||||
LLVMAddTargetLibraryInfo(targetLibraryInfo, passManager)
|
||||
context.coverage.addLateLlvmPasses(passManager)
|
||||
LLVMRunPassManager(passManager, llvmModule)
|
||||
LLVMDisposePassManager(passManager)
|
||||
}
|
||||
|
||||
private class LlvmPipelineConfiguration(context: Context) {
|
||||
|
||||
private val target = context.config.target
|
||||
|
||||
val targetTriple: String = context.llvm.targetTriple
|
||||
|
||||
val cpuArchitecture: String = when (target) {
|
||||
KonanTarget.IOS_ARM32 -> "armv7"
|
||||
KonanTarget.IOS_ARM64 -> "arm64"
|
||||
KonanTarget.MACOS_X64 -> "core2"
|
||||
else -> error("There is no support for ${target.name} target yet.")
|
||||
}
|
||||
|
||||
val cpuFeatures: String = ""
|
||||
|
||||
val customInlineThreshold: Int? = when {
|
||||
context.shouldOptimize() -> 100
|
||||
context.shouldContainDebugInfo() -> null
|
||||
else -> null
|
||||
}
|
||||
|
||||
val optimizationLevel: Int = when {
|
||||
context.shouldOptimize() -> 3
|
||||
context.shouldContainDebugInfo() -> 0
|
||||
else -> 1
|
||||
}
|
||||
|
||||
val sizeLevel: Int = when {
|
||||
context.shouldOptimize() -> 0
|
||||
context.shouldContainDebugInfo() -> 0
|
||||
else -> 0
|
||||
}
|
||||
|
||||
val codegenOptimizationLevel: LLVMCodeGenOptLevel = when {
|
||||
context.shouldOptimize() -> LLVMCodeGenOptLevel.LLVMCodeGenLevelAggressive
|
||||
context.shouldContainDebugInfo() -> LLVMCodeGenOptLevel.LLVMCodeGenLevelNone
|
||||
else -> LLVMCodeGenOptLevel.LLVMCodeGenLevelDefault
|
||||
}
|
||||
|
||||
val relocMode: LLVMRelocMode = LLVMRelocMode.LLVMRelocDefault
|
||||
|
||||
val codeModel: LLVMCodeModel = LLVMCodeModel.LLVMCodeModelDefault
|
||||
}
|
||||
|
||||
// Since we are in a "closed world" internalization and global dce
|
||||
// can be safely used to reduce size of a bitcode.
|
||||
internal fun runClosedWorldCleanup(context: Context) {
|
||||
initializeLlvmGlobalPassRegistry()
|
||||
val llvmModule = context.llvmModule!!
|
||||
val modulePasses = LLVMCreatePassManager()
|
||||
LLVMAddInternalizePass(modulePasses, 0)
|
||||
LLVMAddGlobalDCEPass(modulePasses)
|
||||
LLVMRunPassManager(modulePasses, llvmModule)
|
||||
LLVMDisposePassManager(modulePasses)
|
||||
}
|
||||
|
||||
internal fun runLlvmOptimizationPipeline(context: Context) {
|
||||
val llvmModule = context.llvmModule!!
|
||||
val config = LlvmPipelineConfiguration(context)
|
||||
|
||||
memScoped {
|
||||
LLVMKotlinInitializeTargets()
|
||||
|
||||
initializeLlvmGlobalPassRegistry()
|
||||
val passBuilder = LLVMPassManagerBuilderCreate()
|
||||
val modulePasses = LLVMCreatePassManager()
|
||||
LLVMPassManagerBuilderSetOptLevel(passBuilder, config.optimizationLevel)
|
||||
LLVMPassManagerBuilderSetSizeLevel(passBuilder, config.sizeLevel)
|
||||
// TODO: use LLVMGetTargetFromName instead.
|
||||
val target = alloc<LLVMTargetRefVar>()
|
||||
val foundLlvmTarget = LLVMGetTargetFromTriple(config.targetTriple, target.ptr, null) == 0
|
||||
check(foundLlvmTarget) { "Cannot get target from triple ${config.targetTriple}." }
|
||||
|
||||
val targetMachine = LLVMCreateTargetMachine(
|
||||
target.value,
|
||||
config.targetTriple,
|
||||
config.cpuArchitecture,
|
||||
config.cpuFeatures,
|
||||
config.codegenOptimizationLevel,
|
||||
config.relocMode,
|
||||
config.codeModel)
|
||||
|
||||
val targetLibraryInfo = LLVMGetTargetLibraryInfo(llvmModule)
|
||||
LLVMAddTargetLibraryInfo(targetLibraryInfo, modulePasses)
|
||||
// TargetTransformInfo pass.
|
||||
LLVMAddAnalysisPasses(targetMachine, modulePasses)
|
||||
// Since we are in a "closed world" internalization and global dce
|
||||
// can be safely used to reduce size of a bitcode.
|
||||
LLVMAddInternalizePass(modulePasses, 0)
|
||||
LLVMAddGlobalDCEPass(modulePasses)
|
||||
|
||||
config.customInlineThreshold?.let { threshold ->
|
||||
LLVMPassManagerBuilderUseInlinerWithThreshold(passBuilder, threshold)
|
||||
}
|
||||
// Pipeline that is similar to `llvm-lto`.
|
||||
// TODO: Add ObjC optimization passes.
|
||||
LLVMPassManagerBuilderPopulateLTOPassManager(passBuilder, modulePasses, Internalize = 0, RunInliner = 1)
|
||||
LLVMPassManagerBuilderDispose(passBuilder)
|
||||
|
||||
LLVMRunPassManager(modulePasses, llvmModule)
|
||||
|
||||
LLVMDisposeTargetMachine(targetMachine)
|
||||
LLVMDisposePassManager(modulePasses)
|
||||
}
|
||||
if (shouldRunLateBitcodePasses(context)) {
|
||||
runLateBitcodePasses(context, llvmModule)
|
||||
}
|
||||
}
|
||||
+10
-13
@@ -1,9 +1,9 @@
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import llvm.LLVMWriteBitcodeToFile
|
||||
import org.jetbrains.kotlin.backend.common.LoggingContext
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||
import org.jetbrains.kotlin.backend.common.phaser.*
|
||||
import org.jetbrains.kotlin.backend.common.serialization.DeserializationStrategy
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isForwardDeclarationModule
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
|
||||
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
|
||||
@@ -15,10 +15,15 @@ import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.backend.common.serialization.DescriptorTable
|
||||
import org.jetbrains.kotlin.backend.konan.library.impl.buildLibrary
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||
import org.jetbrains.kotlin.konan.CURRENT
|
||||
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibraryVersioning
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
|
||||
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
||||
@@ -185,20 +190,14 @@ internal val serializerPhase = konanUnitPhase(
|
||||
description = "Serialize descriptor tree and inline IR bodies"
|
||||
)
|
||||
|
||||
internal val setUpLinkStagePhase = konanUnitPhase(
|
||||
op = { linkStage = LinkStage(this) },
|
||||
name = "SetUpLinkStage",
|
||||
description = "Set up link stage"
|
||||
)
|
||||
|
||||
internal val objectFilesPhase = konanUnitPhase(
|
||||
op = { linkStage.makeObjectFiles() },
|
||||
op = { compilerOutput = BitcodeCompiler(this).makeObjectFiles(bitcodeFileName) },
|
||||
name = "ObjectFiles",
|
||||
description = "Bitcode to object file"
|
||||
)
|
||||
|
||||
internal val linkerPhase = konanUnitPhase(
|
||||
op = { linkStage.linkStage() },
|
||||
op = { Linker(this).link(compilerOutput) },
|
||||
name = "Linker",
|
||||
description = "Linker"
|
||||
)
|
||||
@@ -206,8 +205,7 @@ internal val linkerPhase = konanUnitPhase(
|
||||
internal val linkPhase = namedUnitPhase(
|
||||
name = "Link",
|
||||
description = "Link stage",
|
||||
lower = setUpLinkStagePhase then
|
||||
objectFilesPhase then
|
||||
lower = objectFilesPhase then
|
||||
linkerPhase
|
||||
)
|
||||
|
||||
@@ -304,7 +302,6 @@ internal val bitcodePhase = namedIrModulePhase(
|
||||
escapeAnalysisPhase then
|
||||
codegenPhase then
|
||||
finalizeDebugInfoPhase then
|
||||
bitcodePassesPhase then
|
||||
cStubsPhase
|
||||
)
|
||||
|
||||
@@ -330,9 +327,9 @@ val toplevelPhase: CompilerPhase<*, Unit, Unit> = namedUnitPhase(
|
||||
dependenciesLowerPhase then // Then lower all libraries in topological order.
|
||||
// With that we guarantee that inline functions are unlowered while being inlined.
|
||||
bitcodePhase then
|
||||
produceOutputPhase then
|
||||
verifyBitcodePhase then
|
||||
printBitcodePhase then
|
||||
produceOutputPhase then
|
||||
unitSink()
|
||||
) then
|
||||
linkPhase
|
||||
|
||||
-10
@@ -124,16 +124,6 @@ internal val cStubsPhase = makeKonanModuleOpPhase(
|
||||
op = { context, _ -> produceCStubs(context) }
|
||||
)
|
||||
|
||||
/**
|
||||
* Runs specific passes over context.llvmModule. The main compilation pipeline
|
||||
* is performed by [linkPhase].
|
||||
*/
|
||||
internal val bitcodePassesPhase = makeKonanModuleOpPhase(
|
||||
name = "BitcodePasses",
|
||||
description = "Run custom LLVM passes over bitcode",
|
||||
op = { context, _ -> runBitcodePasses(context) }
|
||||
)
|
||||
|
||||
internal val produceOutputPhase = makeKonanModuleOpPhase(
|
||||
name = "ProduceOutput",
|
||||
description = "Produce output",
|
||||
|
||||
+3
-1
@@ -409,9 +409,11 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
||||
val runtimeFile = context.config.distribution.runtime(target)
|
||||
val runtime = Runtime(runtimeFile) // TODO: dispose
|
||||
|
||||
val targetTriple = runtime.target
|
||||
|
||||
init {
|
||||
LLVMSetDataLayout(llvmModule, runtime.dataLayout)
|
||||
LLVMSetTarget(llvmModule, runtime.target)
|
||||
LLVMSetTarget(llvmModule, targetTriple)
|
||||
}
|
||||
|
||||
private fun importRtFunction(name: String) = importFunction(name, runtime.llvmModule)
|
||||
|
||||
-1
@@ -318,7 +318,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
codegen.objCDataGenerator?.finishModule()
|
||||
|
||||
BitcodeEmbedding.processModule(context.llvm)
|
||||
context.coverage.writeRegionInfo()
|
||||
appendDebugSelector()
|
||||
appendLlvmUsed("llvm.used", context.llvm.usedFunctions + context.llvm.usedGlobals)
|
||||
|
||||
+5
-7
@@ -4,12 +4,9 @@
|
||||
*/
|
||||
package org.jetbrains.kotlin.backend.konan.llvm.coverage
|
||||
|
||||
import llvm.LLVMAddInstrProfPass
|
||||
import llvm.LLVMPassManagerRef
|
||||
import llvm.LLVMValueRef
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
||||
import org.jetbrains.kotlin.backend.konan.isNativeBinary
|
||||
import org.jetbrains.kotlin.backend.konan.reportCompilationError
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
@@ -106,10 +103,11 @@ internal class CoverageManager(val context: Context) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add InstrProfilingLegacyPass to the list of llvm passes
|
||||
* Add passes that should be executed after main LLVM optimization pipeline.
|
||||
*/
|
||||
fun addLlvmPasses(passManager: LLVMPassManagerRef) {
|
||||
fun addLateLlvmPasses(passManager: LLVMPassManagerRef) {
|
||||
if (enabled) {
|
||||
// It's a late pass since DCE can kill __llvm_profile_filename global.
|
||||
LLVMAddInstrProfPass(passManager, outputFileName)
|
||||
}
|
||||
}
|
||||
|
||||
+15
-13
@@ -1,7 +1,9 @@
|
||||
headers = llvm-c/Core.h llvm-c/Target.h llvm-c/Analysis.h llvm-c/BitWriter.h \
|
||||
llvm-c/BitReader.h llvm-c/Linker.h DebugInfoC.h CoverageMappingC.h
|
||||
llvm-c/BitReader.h llvm-c/Transforms/PassManagerBuilder.h llvm-c/Transforms/IPO.h \
|
||||
llvm-c/TargetMachine.h llvm-c/Target.h llvm-c/Linker.h llvm-c/Initialization.h \
|
||||
DebugInfoC.h CoverageMappingC.h
|
||||
|
||||
headerFilter = llvm-c/* DebugInfoC.h CoverageMappingC.h
|
||||
headerFilter = llvm-c/* llvm-c/**/* DebugInfoC.h CoverageMappingC.h
|
||||
|
||||
compilerOpts = -std=c99 \
|
||||
-Wall -W -Wno-unused-parameter -Wwrite-strings -Wmissing-field-initializers \
|
||||
@@ -16,25 +18,25 @@ linkerOpts = -fvisibility-inlines-hidden \
|
||||
-pedantic -Wno-long-long -Wcovered-switch-default -Wnon-virtual-dtor -Wdelete-non-virtual-dtor \
|
||||
-std=c++11 \
|
||||
-DNDEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS \
|
||||
-ldebugInfo -lcoverageMapping -lLLVMCoverage -lLLVMTarget -lLLVMInstrumentation \
|
||||
-lLLVMMC -lLLVMLinker -lLLVMTransformUtils -lLLVMBitWriter \
|
||||
-lLLVMBitReader -lLLVMAnalysis -lLLVMProfileData -lLLVMObject -lLLVMMCParser -lLLVMMC \
|
||||
-lLLVMCore -lLLVMBinaryFormat -lLLVMSupport -lLLVMDemangle
|
||||
|
||||
# ./llvm-config --libs analysis bitreader bitwriter core linker target coverage
|
||||
|
||||
-ldebugInfo -lcoverageMapping
|
||||
|
||||
# ./llvm-config --libs analysis bitreader bitwriter core linker target coverage analysis ipo instrumentation lto objcarcopts arm aarch64 webassembly x86 mips
|
||||
linkerOpts.osx = -fPIC \
|
||||
-Wl,-search_paths_first -Wl,-headerpad_max_install_names \
|
||||
-lpthread -lz -lm -lcurses -Wl,-U,_futimens -Wl,-U,_LLVMDumpType
|
||||
-lpthread -lz -lm -lcurses -Wl,-U,_futimens -Wl,-U,_LLVMDumpType \
|
||||
-lLLVMLTO -lLLVMPasses -lLLVMObjCARCOpts -lLLVMipo -lLLVMInstrumentation -lLLVMVectorize -lLLVMIRReader -lLLVMAsmParser -lLLVMMipsDisassembler -lLLVMMipsCodeGen -lLLVMMipsAsmParser -lLLVMMipsDesc -lLLVMMipsInfo -lLLVMMipsAsmPrinter -lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMX86Desc -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMWebAssemblyDisassembler -lLLVMWebAssemblyCodeGen -lLLVMWebAssemblyDesc -lLLVMWebAssemblyInfo -lLLVMWebAssemblyAsmPrinter -lLLVMAArch64Disassembler -lLLVMAArch64CodeGen -lLLVMAArch64AsmParser -lLLVMAArch64Desc -lLLVMAArch64Info -lLLVMAArch64AsmPrinter -lLLVMAArch64Utils -lLLVMARMDisassembler -lLLVMARMCodeGen -lLLVMGlobalISel -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMDebugInfoCodeView -lLLVMDebugInfoMSF -lLLVMCodeGen -lLLVMScalarOpts -lLLVMInstCombine -lLLVMARMAsmParser -lLLVMARMDesc -lLLVMMCDisassembler -lLLVMARMInfo -lLLVMARMAsmPrinter -lLLVMARMUtils -lLLVMCoverage -lLLVMTarget -lLLVMLinker -lLLVMTransformUtils -lLLVMBitWriter -lLLVMAnalysis -lLLVMProfileData -lLLVMObject -lLLVMMCParser -lLLVMMC -lLLVMBitReader -lLLVMCore -lLLVMBinaryFormat -lLLVMSupport -lLLVMDemangle
|
||||
|
||||
linkerOpts.linux= -fPIC \
|
||||
# ./llvm-config --libs analysis bitreader bitwriter core linker target coverage analysis ipo instrumentation lto
|
||||
linkerOpts.linux= -lLLVMLTO -lLLVMPasses -lLLVMObjCARCOpts -lLLVMCodeGen -lLLVMipo -lLLVMInstrumentation -lLLVMVectorize -lLLVMScalarOpts -lLLVMIRReader -lLLVMAsmParser -lLLVMInstCombine -lLLVMCoverage -lLLVMTarget -lLLVMLinker -lLLVMTransformUtils -lLLVMBitWriter -lLLVMAnalysis -lLLVMProfileData -lLLVMObject -lLLVMMCParser -lLLVMMC -lLLVMBitReader -lLLVMCore -lLLVMBinaryFormat -lLLVMSupport -lLLVMDemangle \
|
||||
-fPIC \
|
||||
-Wl,-z,noexecstack \
|
||||
-lrt -ldl -lpthread -lz -lm
|
||||
|
||||
linkerOpts.mingw = -lole32 -luuid -static-libgcc -static-libstdc++ \
|
||||
# ./llvm-config --libs analysis bitreader bitwriter core linker target coverage analysis ipo instrumentation lto
|
||||
linkerOpts.mingw = -lLLVMLTO -lLLVMPasses -lLLVMObjCARCOpts -lLLVMCodeGen -lLLVMipo -lLLVMInstrumentation -lLLVMVectorize -lLLVMScalarOpts -lLLVMIRReader -lLLVMAsmParser -lLLVMInstCombine -lLLVMCoverage -lLLVMTarget -lLLVMLinker -lLLVMTransformUtils -lLLVMBitWriter -lLLVMAnalysis -lLLVMProfileData -lLLVMObject -lLLVMMCParser -lLLVMMC -lLLVMBitReader -lLLVMCore -lLLVMBinaryFormat -lLLVMSupport -lLLVMDemangle \
|
||||
-lole32 -luuid -static-libgcc -static-libstdc++ \
|
||||
-Wl,-Bstatic -lz \
|
||||
-Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive,-Bdynamic
|
||||
-Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive,-Bdynamic \
|
||||
|
||||
# It looks like mingw port compiled without LLVM_ENABLE_DUMP
|
||||
#Note: ld on mingw process -Wl,-U,_LLVMDumpType use different from other platform
|
||||
|
||||
@@ -3,11 +3,8 @@ package org.jetbrains.kotlin
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.SourceSetContainer
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
@@ -55,9 +52,11 @@ open class FrameworkTest : DefaultTask() {
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
val frameworkPath = "$testOutput/$frameworkName/${project.testTarget().name}"
|
||||
|
||||
codesign(project, Paths.get(frameworkPath, "$frameworkName.framework").toString())
|
||||
val frameworkParentDirPath = "$testOutput/$frameworkName/${project.testTarget().name}"
|
||||
val frameworkPath = "$frameworkParentDirPath/$frameworkName.framework"
|
||||
val frameworkBinaryPath = "$frameworkPath/$frameworkName"
|
||||
validateBitcodeEmbedding(frameworkBinaryPath)
|
||||
codesign(project, frameworkPath)
|
||||
|
||||
// create a test provider and get main entry point
|
||||
val provider = Paths.get(testOutput, frameworkName, "provider.swift")
|
||||
@@ -77,7 +76,7 @@ open class FrameworkTest : DefaultTask() {
|
||||
// Compile swift sources
|
||||
val sources = swiftSources.map { Paths.get(it).toString() } +
|
||||
listOf(provider.toString(), swiftMain)
|
||||
val options = listOf("-g", "-Xlinker", "-rpath", "-Xlinker", frameworkPath, "-F", frameworkPath)
|
||||
val options = listOf("-g", "-Xlinker", "-rpath", "-Xlinker", frameworkParentDirPath, "-F", frameworkParentDirPath)
|
||||
val testExecutable = Paths.get(testOutput, frameworkName, "swiftTestExecutable")
|
||||
swiftc(sources, options, testExecutable)
|
||||
|
||||
@@ -139,4 +138,32 @@ open class FrameworkTest : DefaultTask() {
|
||||
check(exitCode == 0, { "Compilation failed" })
|
||||
check(output.toFile().exists(), { "Compiler swiftc hasn't produced an output file: $output" })
|
||||
}
|
||||
}
|
||||
|
||||
private fun validateBitcodeEmbedding(frameworkBinary: String) {
|
||||
// Check only the full bitcode embedding for now.
|
||||
if (!fullBitcode) {
|
||||
return
|
||||
}
|
||||
val testTarget = project.testTarget()
|
||||
val configurables = project.platformManager().platform(testTarget).configurables as AppleConfigurables
|
||||
|
||||
val bitcodeBuildTool = "${configurables.absoluteAdditionalToolsDir}/bin/bitcode-build-tool"
|
||||
val ldPath = "${configurables.absoluteTargetToolchain}/usr/bin/ld"
|
||||
val sdk = when (testTarget) {
|
||||
KonanTarget.IOS_X64 -> Xcode.current.iphonesimulatorSdk
|
||||
KonanTarget.IOS_ARM64, KonanTarget.IOS_ARM32 -> Xcode.current.iphoneosSdk
|
||||
KonanTarget.MACOS_X64 -> Xcode.current.macosxSdk
|
||||
else -> error("Cannot validate bitcode for test target $testTarget")
|
||||
}
|
||||
|
||||
val args = listOf("--sdk", sdk, "-v", "-t", ldPath, frameworkBinary)
|
||||
val (stdOut, stdErr, exitCode) = runProcess(executor = localExecutor(project), executable = bitcodeBuildTool, args = args)
|
||||
check(exitCode == 0) {
|
||||
"""
|
||||
|bitcode-build-tool failed:
|
||||
|stdout: $stdOut
|
||||
|stderr: $stdErr
|
||||
""".trimMargin()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -23,8 +23,9 @@ kotlinVersion=1.3.40-dev-2423
|
||||
testKotlinVersion=1.3.40-dev-2423
|
||||
# See https://teamcity.jetbrains.com/project.html?projectId=Kotlin_KotlinNativeShared&tab=projectOverview
|
||||
sharedRepo=https://dl.bintray.com/jetbrains/kotlin-native-dependencies
|
||||
sharedVersion=1.0-dev-50
|
||||
sharedVersion=1.0-dev-57
|
||||
konanVersion=1.3.0
|
||||
org.gradle.jvmargs='-Dfile.encoding=UTF-8'
|
||||
org.gradle.workers.max=4
|
||||
#kotlinProjectPath=/Users/jetbrains/kotlin-native/kotlin
|
||||
#kotlinProjectPath=/Users/jetbrains/IdeaProjects/kotlin
|
||||
#sharedProjectPath=/Users/jetbrains/IdeaProjects/kotlin-native-shared
|
||||
+38
-20
@@ -39,24 +39,30 @@ llvmVersion = 6.0.1
|
||||
llvmHome.macos_x64 = clang-llvm-6.0.1-darwin-macos
|
||||
targetToolchain.macos_x64 = target-toolchain-9-macos_x64
|
||||
libffiDir.macos_x64 = libffi-3.2.1-3-darwin-macos
|
||||
additionalToolsDir.macos_x64 = xcode-addon-9-macos_x64
|
||||
|
||||
arch.macos_x64 = x86_64
|
||||
targetSysRoot.macos_x64 = target-sysroot-9-macos_x64
|
||||
llvmLtoFlags.macos_x64 =
|
||||
llvmLtoOptFlags.macos_x64 = -O3 -function-sections
|
||||
llvmLtoNooptFlags.macos_x64 = -O1
|
||||
llvmLtoDynamicFlags.macos_x64 = -relocation-model=pic
|
||||
|
||||
clangFlags.macos_x64 = -cc1 -emit-obj -disable-llvm-passes -x ir
|
||||
clangNooptFlags.macos_x64 = -O1
|
||||
clangOptFlags.macos_x64 = -O3
|
||||
clangDebugFlags.macos_x64 = -O0
|
||||
clangDynamicFlags.macos_x64 =
|
||||
|
||||
linkerKonanFlags.macos_x64 = -lSystem -lc++ -lobjc -framework Foundation
|
||||
linkerOptimizationFlags.macos_x64 = -dead_strip
|
||||
linkerNoDebugFlags.macos_x64 = -S
|
||||
linkerDynamicFlags.macos_x64 = -dylib
|
||||
|
||||
osVersionMinFlagLd.macos_x64 = -macosx_version_min
|
||||
osVersionMinFlagClang.macos_x64 = -mmacosx-version-min
|
||||
osVersionMin.macos_x64 = 10.11
|
||||
entrySelector.macos_x64 = -alias _Konan_main _main
|
||||
dependencies.macos_x64 = \
|
||||
libffi-3.2.1-3-darwin-macos \
|
||||
clang-llvm-6.0.1-darwin-macos
|
||||
clang-llvm-6.0.1-darwin-macos \
|
||||
xcode-addon-9-macos_x64
|
||||
|
||||
target-sysroot-9-macos_x64.default = \
|
||||
remote:internal
|
||||
@@ -64,6 +70,10 @@ target-sysroot-9-macos_x64.default = \
|
||||
target-toolchain-9-macos_x64.default = \
|
||||
remote:internal
|
||||
|
||||
xcode-addon-9-macos_x64.default = \
|
||||
remote:internal
|
||||
|
||||
|
||||
# Apple's 32-bit iOS.
|
||||
targetToolchain.macos_x64-ios_arm32 = target-toolchain-9-macos_x64
|
||||
dependencies.macos_x64-ios_arm32 = \
|
||||
@@ -77,13 +87,15 @@ arch.ios_arm32 = armv7
|
||||
entrySelector.ios_arm32 = -alias _Konan_main _main
|
||||
# Shared with 64-bit version.
|
||||
targetSysRoot.ios_arm32 = target-sysroot-9-ios_arm64
|
||||
llvmLtoFlags.ios_arm32 =
|
||||
llvmLtoOptFlags.ios_arm32 = -O3 -function-sections
|
||||
|
||||
clangFlags.ios_arm32 = -cc1 -emit-obj -disable-llvm-optzns -x ir
|
||||
clangNooptFlags.ios_arm32 = -O1
|
||||
clangOptFlags.ios_arm32 = -O3
|
||||
clangDebugFlags.ios_arm32 = -O0
|
||||
clangDynamicFlags.ios_arm32 =
|
||||
linkerNoDebugFlags.ios_arm32 = -S
|
||||
linkerDynamicFlags.ios_arm32 = -dylib
|
||||
llvmLtoNooptFlags.ios_arm32 = -O1
|
||||
llvmLtoDynamicFlags.ios_arm32 = -relocation-model=pic
|
||||
linkerKonanFlags.ios_arm32 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 12.2
|
||||
linkerKonanFlags.ios_arm32 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 11.2
|
||||
linkerOptimizationFlags.ios_arm32 = -dead_strip
|
||||
osVersionMinFlagLd.ios_arm32 = -iphoneos_version_min
|
||||
osVersionMinFlagClang.ios_arm32 = -miphoneos-version-min
|
||||
@@ -101,13 +113,16 @@ target-sysroot-9-ios_arm64.default = \
|
||||
arch.ios_arm64 = arm64
|
||||
entrySelector.ios_arm64 = -alias _Konan_main _main
|
||||
targetSysRoot.ios_arm64 = target-sysroot-9-ios_arm64
|
||||
llvmLtoFlags.ios_arm64 =
|
||||
llvmLtoOptFlags.ios_arm64 = -O3 -function-sections
|
||||
|
||||
clangFlags.ios_arm64 = -cc1 -emit-obj -disable-llvm-passes -x ir
|
||||
clangNooptFlags.ios_arm64 = -O1
|
||||
clangOptFlags.ios_arm64 = -O3
|
||||
clangDebugFlags.ios_arm64 = -O0
|
||||
clangDynamicFlags.ios_arm64 =
|
||||
|
||||
linkerNoDebugFlags.ios_arm64 = -S
|
||||
linkerDynamicFlags.ios_arm64 = -dylib
|
||||
llvmLtoNooptFlags.ios_arm64 = -O1
|
||||
llvmLtoDynamicFlags.ios_arm64 = -relocation-model=pic
|
||||
linkerKonanFlags.ios_arm64 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 12.2
|
||||
linkerKonanFlags.ios_arm64 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 11.2
|
||||
linkerOptimizationFlags.ios_arm64 = -dead_strip
|
||||
osVersionMinFlagLd.ios_arm64 = -iphoneos_version_min
|
||||
osVersionMinFlagClang.ios_arm64 = -miphoneos-version-min
|
||||
@@ -125,11 +140,14 @@ target-sysroot-9-ios_x64.default = \
|
||||
arch.ios_x64 = x86_64
|
||||
entrySelector.ios_x64 = -alias _Konan_main _main
|
||||
targetSysRoot.ios_x64 = target-sysroot-9-ios_x64
|
||||
llvmLtoFlags.ios_x64 =
|
||||
llvmLtoOptFlags.ios_x64 = -O3 -function-sections
|
||||
llvmLtoNooptFlags.ios_x64 = -O1
|
||||
llvmLtoDynamicFlags.ios_x64 = -relocation-model=pic
|
||||
linkerKonanFlags.ios_x64 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 12.2
|
||||
|
||||
clangFlags.ios_x64 = -cc1 -emit-obj -disable-llvm-passes -x ir
|
||||
clangNooptFlags.ios_x64 = -O1
|
||||
clangOptFlags.ios_x64 = -O3
|
||||
clangDebugFlags.ios_x64 = -O0
|
||||
clangDynamicFlags.ios_x64 =
|
||||
|
||||
linkerKonanFlags.ios_x64 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 11.2
|
||||
linkerOptimizationFlags.ios_x64 = -dead_strip
|
||||
linkerNoDebugFlags.ios_x64 = -S
|
||||
linkerDynamicFlags.ios_x64 = -dylib
|
||||
|
||||
@@ -30,6 +30,15 @@ model {
|
||||
if (!project.parent.convention.plugins.platformInfo.isWindows())
|
||||
cppCompiler.args "-fPIC"
|
||||
cppCompiler.args "--std=c++11", "-I${llvmDir}/include", "-I${projectDir}/src/main/include"
|
||||
if (isMac()) {
|
||||
cppCompiler.args "-DKONAN_MACOS=1"
|
||||
} else if (isWindows()) {
|
||||
cppCompiler.args "-DKONAN_WINDOWS=1"
|
||||
} else if (isLinux()) {
|
||||
cppCompiler.args "-DKONAN_LINUX=1"
|
||||
} else {
|
||||
throw new Error("Unsupported host OS.")
|
||||
}
|
||||
linker.args "-L${llvmDir}/lib", "-lLLVMCore", "-lLLVMSupport"
|
||||
}
|
||||
binaries.withType(SharedLibraryBinarySpec) { binary ->
|
||||
|
||||
@@ -227,4 +227,22 @@ void LLVMAddInstrProfPass(LLVMPassManagerRef passManagerRef, const char* outputF
|
||||
LLVMTargetLibraryInfoRef LLVMGetTargetLibraryInfo(LLVMModuleRef moduleRef) {
|
||||
auto* libraryInfo = new TargetLibraryInfoImpl(Triple(unwrap(moduleRef)->getTargetTriple()));
|
||||
return llvm::wrap(libraryInfo);
|
||||
}
|
||||
|
||||
void LLVMKotlinInitializeTargets() {
|
||||
#define INIT_LLVM_TARGET(TargetName) \
|
||||
LLVMInitialize##TargetName##TargetInfo();\
|
||||
LLVMInitialize##TargetName##Target();\
|
||||
LLVMInitialize##TargetName##TargetMC();
|
||||
#if KONAN_MACOS
|
||||
INIT_LLVM_TARGET(AArch64)
|
||||
INIT_LLVM_TARGET(ARM)
|
||||
INIT_LLVM_TARGET(Mips)
|
||||
INIT_LLVM_TARGET(X86)
|
||||
INIT_LLVM_TARGET(WebAssembly)
|
||||
#elif KONAN_LINUX
|
||||
#elif KONAN_WINDOWS
|
||||
#endif
|
||||
|
||||
#undef INIT_LLVM_TARGET
|
||||
}
|
||||
@@ -74,8 +74,9 @@ void LLVMAddInstrProfPass(LLVMPassManagerRef passManagerRef, const char* outputF
|
||||
|
||||
LLVMTargetLibraryInfoRef LLVMGetTargetLibraryInfo(LLVMModuleRef moduleRef);
|
||||
|
||||
void LLVMKotlinInitializeTargets();
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,7 @@ TARBALL_iphonesimulator=target-sysroot-$KONAN_TOOLCHAIN_VERSION-ios_x64
|
||||
TARBALL_watchos=target-sysroot-$KONAN_TOOLCHAIN_VERSION-watchos_arm32
|
||||
TARBALL_watchsimulator=target-sysroot-$KONAN_TOOLCHAIN_VERSION-watchos_x64
|
||||
TARBALL_xcode=target-toolchain-$KONAN_TOOLCHAIN_VERSION-macos_x64
|
||||
TARBALL_xcode_addon=xcode-addon-$KONAN_TOOLCHAIN_VERSION-macos_x64
|
||||
OUT=`pwd`
|
||||
|
||||
for s in $SDKS; do
|
||||
@@ -26,3 +27,10 @@ t=`grealpath $t/../..`
|
||||
tarball=$TARBALL_xcode
|
||||
echo "Packing toolchain $OUT/$tarball.tar.gz..."
|
||||
$SHELL -c "tar czf $OUT/$tarball.tar.gz -C $t -s '/^\./$tarball/' ."
|
||||
|
||||
t=`xcrun -f bitcode-build-tool`
|
||||
t=`dirname $t`
|
||||
t=`grealpath $t/..`
|
||||
tarball=$TARBALL_xcode_addon
|
||||
echo "Packing additional tools $OUT/$tarball.tar.gz..."
|
||||
$SHELL -c "tar czf $OUT/$tarball.tar.gz -C $t -s '/^\./$tarball/' ."
|
||||
Reference in New Issue
Block a user