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,
|
put(VERBOSE_PHASES,
|
||||||
arguments.verbosePhases.toNonNullList())
|
arguments.verbosePhases.toNonNullList())
|
||||||
put(LIST_PHASES, arguments.listPhases)
|
put(LIST_PHASES, arguments.listPhases)
|
||||||
put(TIME_PHASES, arguments.timePhases)
|
|
||||||
|
|
||||||
put(COMPATIBLE_COMPILER_VERSIONS,
|
put(COMPATIBLE_COMPILER_VERSIONS,
|
||||||
arguments.compatibleCompilerVersions.toNonNullList())
|
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")
|
@Argument(value = "-Xtemporary-files-dir", deprecatedName = "--temporary_files_dir", valueDescription = "<path>", description = "Save temporary files to the given directory")
|
||||||
var temporaryFilesDir: String? = null
|
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")
|
@Argument(value = "-Xverify-bitcode", deprecatedName = "--verify_bitcode", description = "Verify llvm bitcode after each method")
|
||||||
var verifyBitCode: Boolean = false
|
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")
|
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 {
|
private val KonanConfig.bitcodeEmbeddingMode get() = configuration.get(KonanConfigKeys.BITCODE_EMBEDDING_MODE)!!.also {
|
||||||
require(it == Mode.NONE || this.produce == CompilerOutputKind.FRAMEWORK) {
|
require(it == Mode.NONE || this.produce == CompilerOutputKind.FRAMEWORK) {
|
||||||
"${it.name.toLowerCase()} bitcode embedding mode is not supported when producing ${this.produce.name.toLowerCase()}"
|
"${it.name.toLowerCase()} bitcode embedding mode is not supported when producing ${this.produce.name.toLowerCase()}"
|
||||||
|
|||||||
+30
-29
@@ -4,16 +4,19 @@
|
|||||||
*/
|
*/
|
||||||
package org.jetbrains.kotlin.backend.konan
|
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.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.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.CURRENT
|
||||||
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||||
import org.jetbrains.kotlin.konan.KonanVersion
|
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.library.KonanLibraryVersioning
|
||||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
|
import org.jetbrains.kotlin.konan.target.Family
|
||||||
|
|
||||||
val CompilerOutputKind.isNativeBinary: Boolean get() = when (this) {
|
val CompilerOutputKind.isNativeBinary: Boolean get() = when (this) {
|
||||||
CompilerOutputKind.PROGRAM, CompilerOutputKind.DYNAMIC,
|
CompilerOutputKind.PROGRAM, CompilerOutputKind.DYNAMIC,
|
||||||
@@ -28,20 +31,30 @@ internal fun produceCStubs(context: Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun shouldRunBitcodePasses(context: Context): Boolean =
|
private fun linkAllDependecies(context: Context, generatedBitcodeFiles: List<String>) {
|
||||||
context.coverage.enabled
|
|
||||||
|
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 llvmModule = context.llvmModule!!
|
||||||
val passManager = LLVMCreatePassManager()!!
|
bitcodeFiles.forEach {
|
||||||
val targetLibraryInfo = LLVMGetTargetLibraryInfo(llvmModule)
|
parseAndLinkBitcodeFile(llvmModule, it)
|
||||||
LLVMAddTargetLibraryInfo(targetLibraryInfo, passManager)
|
}
|
||||||
context.coverage.addLlvmPasses(passManager)
|
}
|
||||||
LLVMRunPassManager(passManager, llvmModule)
|
|
||||||
LLVMDisposePassManager(passManager)
|
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) {
|
internal fun produceOutput(context: Context) {
|
||||||
@@ -57,7 +70,6 @@ internal fun produceOutput(context: Context) {
|
|||||||
CompilerOutputKind.PROGRAM -> {
|
CompilerOutputKind.PROGRAM -> {
|
||||||
val output = tempFiles.nativeBinaryFileName
|
val output = tempFiles.nativeBinaryFileName
|
||||||
context.bitcodeFileName = output
|
context.bitcodeFileName = output
|
||||||
|
|
||||||
val generatedBitcodeFiles =
|
val generatedBitcodeFiles =
|
||||||
if (produce == CompilerOutputKind.DYNAMIC || produce == CompilerOutputKind.STATIC) {
|
if (produce == CompilerOutputKind.DYNAMIC || produce == CompilerOutputKind.STATIC) {
|
||||||
produceCAdapterBitcode(
|
produceCAdapterBitcode(
|
||||||
@@ -66,20 +78,11 @@ internal fun produceOutput(context: Context) {
|
|||||||
tempFiles.cAdapterBitcodeName)
|
tempFiles.cAdapterBitcodeName)
|
||||||
listOf(tempFiles.cAdapterBitcodeName)
|
listOf(tempFiles.cAdapterBitcodeName)
|
||||||
} else emptyList()
|
} 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) {
|
if (produce == CompilerOutputKind.FRAMEWORK && context.config.produceStaticFramework) {
|
||||||
embedAppleLinkerOptionsToBitcode(context.llvm, context.config)
|
embedAppleLinkerOptionsToBitcode(context.llvm, context.config)
|
||||||
}
|
}
|
||||||
|
linkAllDependecies(context, generatedBitcodeFiles)
|
||||||
|
runLlvmPipeline(context)
|
||||||
LLVMWriteBitcodeToFile(context.llvmModule!!, output)
|
LLVMWriteBitcodeToFile(context.llvmModule!!, output)
|
||||||
}
|
}
|
||||||
CompilerOutputKind.LIBRARY -> {
|
CompilerOutputKind.LIBRARY -> {
|
||||||
@@ -94,7 +97,6 @@ internal fun produceOutput(context: Context) {
|
|||||||
val nopack = config.getBoolean(KonanConfigKeys.NOPACK)
|
val nopack = config.getBoolean(KonanConfigKeys.NOPACK)
|
||||||
val manifestProperties = context.config.manifestProperties
|
val manifestProperties = context.config.manifestProperties
|
||||||
|
|
||||||
|
|
||||||
val library = buildLibrary(
|
val library = buildLibrary(
|
||||||
context.config.nativeLibraries,
|
context.config.nativeLibraries,
|
||||||
context.config.includeBinaries,
|
context.config.includeBinaries,
|
||||||
@@ -109,7 +111,6 @@ internal fun produceOutput(context: Context) {
|
|||||||
manifestProperties,
|
manifestProperties,
|
||||||
context.dataFlowGraph)
|
context.dataFlowGraph)
|
||||||
|
|
||||||
context.library = library
|
|
||||||
context.bitcodeFileName = library.mainBitcodeFileName
|
context.bitcodeFileName = library.mainBitcodeFileName
|
||||||
}
|
}
|
||||||
CompilerOutputKind.BITCODE -> {
|
CompilerOutputKind.BITCODE -> {
|
||||||
|
|||||||
+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.common.validateIrModule
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.KonanIr
|
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.library.LinkData
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_BRIDGE_METHOD
|
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.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
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.objcexport.ObjCExport
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager
|
import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
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.
|
* 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)
|
val llvmImports: LlvmImports = Llvm.ImportsImpl(this)
|
||||||
lateinit var llvmDeclarations: LlvmDeclarations
|
lateinit var llvmDeclarations: LlvmDeclarations
|
||||||
lateinit var bitcodeFileName: String
|
lateinit var bitcodeFileName: String
|
||||||
lateinit var library: KonanLibraryWriter
|
|
||||||
|
|
||||||
val cStubsManager = CStubsManager(config.target)
|
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 shouldPrintLocations() = config.configuration.getBoolean(KonanConfigKeys.PRINT_LOCATIONS)
|
||||||
|
|
||||||
fun shouldProfilePhases() = config.configuration.getBoolean(KonanConfigKeys.TIME_PHASES)
|
fun shouldProfilePhases() = config.phaseConfig.needProfiling
|
||||||
|
|
||||||
fun shouldContainDebugInfo() = config.debug
|
fun shouldContainDebugInfo() = config.debug
|
||||||
|
|
||||||
@@ -469,7 +467,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
|||||||
internal val stdlibModule
|
internal val stdlibModule
|
||||||
get() = this.builtIns.any.module
|
get() = this.builtIns.any.module
|
||||||
|
|
||||||
lateinit var linkStage: LinkStage
|
lateinit var compilerOutput: List<ObjectFile>
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MemberScope.getContributedClassifier(name: String) =
|
private fun MemberScope.getContributedClassifier(name: String) =
|
||||||
|
|||||||
-2
@@ -96,8 +96,6 @@ class KonanConfigKeys {
|
|||||||
= CompilerConfigurationKey.create("target we compile for")
|
= CompilerConfigurationKey.create("target we compile for")
|
||||||
val TEMPORARY_FILES_DIR: CompilerConfigurationKey<String?>
|
val TEMPORARY_FILES_DIR: CompilerConfigurationKey<String?>
|
||||||
= CompilerConfigurationKey.create("directory for temporary files")
|
= CompilerConfigurationKey.create("directory for temporary files")
|
||||||
val TIME_PHASES: CompilerConfigurationKey<Boolean>
|
|
||||||
= CompilerConfigurationKey.create("time backend phases")
|
|
||||||
val VERIFY_BITCODE: CompilerConfigurationKey<Boolean>
|
val VERIFY_BITCODE: CompilerConfigurationKey<Boolean>
|
||||||
= CompilerConfigurationKey.create("verify bitcode")
|
= CompilerConfigurationKey.create("verify bitcode")
|
||||||
val VERIFY_DESCRIPTORS: CompilerConfigurationKey<Boolean>
|
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
|
package org.jetbrains.kotlin.backend.konan
|
||||||
|
|
||||||
|
import llvm.LLVMWriteBitcodeToFile
|
||||||
import org.jetbrains.kotlin.backend.common.LoggingContext
|
import org.jetbrains.kotlin.backend.common.LoggingContext
|
||||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.*
|
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.isForwardDeclarationModule
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
|
import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
|
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.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.DescriptorTable
|
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.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
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.konan.target.CompilerOutputKind
|
||||||
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
|
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
|
||||||
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
||||||
@@ -185,20 +190,14 @@ internal val serializerPhase = konanUnitPhase(
|
|||||||
description = "Serialize descriptor tree and inline IR bodies"
|
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(
|
internal val objectFilesPhase = konanUnitPhase(
|
||||||
op = { linkStage.makeObjectFiles() },
|
op = { compilerOutput = BitcodeCompiler(this).makeObjectFiles(bitcodeFileName) },
|
||||||
name = "ObjectFiles",
|
name = "ObjectFiles",
|
||||||
description = "Bitcode to object file"
|
description = "Bitcode to object file"
|
||||||
)
|
)
|
||||||
|
|
||||||
internal val linkerPhase = konanUnitPhase(
|
internal val linkerPhase = konanUnitPhase(
|
||||||
op = { linkStage.linkStage() },
|
op = { Linker(this).link(compilerOutput) },
|
||||||
name = "Linker",
|
name = "Linker",
|
||||||
description = "Linker"
|
description = "Linker"
|
||||||
)
|
)
|
||||||
@@ -206,8 +205,7 @@ internal val linkerPhase = konanUnitPhase(
|
|||||||
internal val linkPhase = namedUnitPhase(
|
internal val linkPhase = namedUnitPhase(
|
||||||
name = "Link",
|
name = "Link",
|
||||||
description = "Link stage",
|
description = "Link stage",
|
||||||
lower = setUpLinkStagePhase then
|
lower = objectFilesPhase then
|
||||||
objectFilesPhase then
|
|
||||||
linkerPhase
|
linkerPhase
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -304,7 +302,6 @@ internal val bitcodePhase = namedIrModulePhase(
|
|||||||
escapeAnalysisPhase then
|
escapeAnalysisPhase then
|
||||||
codegenPhase then
|
codegenPhase then
|
||||||
finalizeDebugInfoPhase then
|
finalizeDebugInfoPhase then
|
||||||
bitcodePassesPhase then
|
|
||||||
cStubsPhase
|
cStubsPhase
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -330,9 +327,9 @@ val toplevelPhase: CompilerPhase<*, Unit, Unit> = namedUnitPhase(
|
|||||||
dependenciesLowerPhase then // Then lower all libraries in topological order.
|
dependenciesLowerPhase then // Then lower all libraries in topological order.
|
||||||
// With that we guarantee that inline functions are unlowered while being inlined.
|
// With that we guarantee that inline functions are unlowered while being inlined.
|
||||||
bitcodePhase then
|
bitcodePhase then
|
||||||
produceOutputPhase then
|
|
||||||
verifyBitcodePhase then
|
verifyBitcodePhase then
|
||||||
printBitcodePhase then
|
printBitcodePhase then
|
||||||
|
produceOutputPhase then
|
||||||
unitSink()
|
unitSink()
|
||||||
) then
|
) then
|
||||||
linkPhase
|
linkPhase
|
||||||
|
|||||||
-10
@@ -124,16 +124,6 @@ internal val cStubsPhase = makeKonanModuleOpPhase(
|
|||||||
op = { context, _ -> produceCStubs(context) }
|
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(
|
internal val produceOutputPhase = makeKonanModuleOpPhase(
|
||||||
name = "ProduceOutput",
|
name = "ProduceOutput",
|
||||||
description = "Produce output",
|
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 runtimeFile = context.config.distribution.runtime(target)
|
||||||
val runtime = Runtime(runtimeFile) // TODO: dispose
|
val runtime = Runtime(runtimeFile) // TODO: dispose
|
||||||
|
|
||||||
|
val targetTriple = runtime.target
|
||||||
|
|
||||||
init {
|
init {
|
||||||
LLVMSetDataLayout(llvmModule, runtime.dataLayout)
|
LLVMSetDataLayout(llvmModule, runtime.dataLayout)
|
||||||
LLVMSetTarget(llvmModule, runtime.target)
|
LLVMSetTarget(llvmModule, targetTriple)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun importRtFunction(name: String) = importFunction(name, runtime.llvmModule)
|
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()
|
codegen.objCDataGenerator?.finishModule()
|
||||||
|
|
||||||
BitcodeEmbedding.processModule(context.llvm)
|
|
||||||
context.coverage.writeRegionInfo()
|
context.coverage.writeRegionInfo()
|
||||||
appendDebugSelector()
|
appendDebugSelector()
|
||||||
appendLlvmUsed("llvm.used", context.llvm.usedFunctions + context.llvm.usedGlobals)
|
appendLlvmUsed("llvm.used", context.llvm.usedFunctions + context.llvm.usedGlobals)
|
||||||
|
|||||||
+5
-7
@@ -4,12 +4,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.jetbrains.kotlin.backend.konan.llvm.coverage
|
package org.jetbrains.kotlin.backend.konan.llvm.coverage
|
||||||
|
|
||||||
import llvm.LLVMAddInstrProfPass
|
import llvm.*
|
||||||
import llvm.LLVMPassManagerRef
|
import org.jetbrains.kotlin.backend.konan.*
|
||||||
import llvm.LLVMValueRef
|
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
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.backend.konan.reportCompilationError
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
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) {
|
if (enabled) {
|
||||||
|
// It's a late pass since DCE can kill __llvm_profile_filename global.
|
||||||
LLVMAddInstrProfPass(passManager, outputFileName)
|
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 \
|
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 \
|
compilerOpts = -std=c99 \
|
||||||
-Wall -W -Wno-unused-parameter -Wwrite-strings -Wmissing-field-initializers \
|
-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 \
|
-pedantic -Wno-long-long -Wcovered-switch-default -Wnon-virtual-dtor -Wdelete-non-virtual-dtor \
|
||||||
-std=c++11 \
|
-std=c++11 \
|
||||||
-DNDEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS \
|
-DNDEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS \
|
||||||
-ldebugInfo -lcoverageMapping -lLLVMCoverage -lLLVMTarget -lLLVMInstrumentation \
|
-ldebugInfo -lcoverageMapping
|
||||||
-lLLVMMC -lLLVMLinker -lLLVMTransformUtils -lLLVMBitWriter \
|
|
||||||
-lLLVMBitReader -lLLVMAnalysis -lLLVMProfileData -lLLVMObject -lLLVMMCParser -lLLVMMC \
|
|
||||||
-lLLVMCore -lLLVMBinaryFormat -lLLVMSupport -lLLVMDemangle
|
|
||||||
|
|
||||||
# ./llvm-config --libs analysis bitreader bitwriter core linker target coverage
|
|
||||||
|
|
||||||
|
|
||||||
|
# ./llvm-config --libs analysis bitreader bitwriter core linker target coverage analysis ipo instrumentation lto objcarcopts arm aarch64 webassembly x86 mips
|
||||||
linkerOpts.osx = -fPIC \
|
linkerOpts.osx = -fPIC \
|
||||||
-Wl,-search_paths_first -Wl,-headerpad_max_install_names \
|
-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 \
|
-Wl,-z,noexecstack \
|
||||||
-lrt -ldl -lpthread -lz -lm
|
-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 -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
|
# It looks like mingw port compiled without LLVM_ENABLE_DUMP
|
||||||
#Note: ld on mingw process -Wl,-U,_LLVMDumpType use different from other platform
|
#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 groovy.lang.Closure
|
||||||
import org.gradle.api.Action
|
import org.gradle.api.Action
|
||||||
import org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.Task
|
import org.gradle.api.Task
|
||||||
import org.gradle.api.tasks.Input
|
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.gradle.api.tasks.TaskAction
|
||||||
|
|
||||||
import org.jetbrains.kotlin.konan.target.*
|
import org.jetbrains.kotlin.konan.target.*
|
||||||
@@ -55,9 +52,11 @@ open class FrameworkTest : DefaultTask() {
|
|||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun run() {
|
fun run() {
|
||||||
val frameworkPath = "$testOutput/$frameworkName/${project.testTarget().name}"
|
val frameworkParentDirPath = "$testOutput/$frameworkName/${project.testTarget().name}"
|
||||||
|
val frameworkPath = "$frameworkParentDirPath/$frameworkName.framework"
|
||||||
codesign(project, Paths.get(frameworkPath, "$frameworkName.framework").toString())
|
val frameworkBinaryPath = "$frameworkPath/$frameworkName"
|
||||||
|
validateBitcodeEmbedding(frameworkBinaryPath)
|
||||||
|
codesign(project, frameworkPath)
|
||||||
|
|
||||||
// create a test provider and get main entry point
|
// create a test provider and get main entry point
|
||||||
val provider = Paths.get(testOutput, frameworkName, "provider.swift")
|
val provider = Paths.get(testOutput, frameworkName, "provider.swift")
|
||||||
@@ -77,7 +76,7 @@ open class FrameworkTest : DefaultTask() {
|
|||||||
// Compile swift sources
|
// Compile swift sources
|
||||||
val sources = swiftSources.map { Paths.get(it).toString() } +
|
val sources = swiftSources.map { Paths.get(it).toString() } +
|
||||||
listOf(provider.toString(), swiftMain)
|
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")
|
val testExecutable = Paths.get(testOutput, frameworkName, "swiftTestExecutable")
|
||||||
swiftc(sources, options, testExecutable)
|
swiftc(sources, options, testExecutable)
|
||||||
|
|
||||||
@@ -139,4 +138,32 @@ open class FrameworkTest : DefaultTask() {
|
|||||||
check(exitCode == 0, { "Compilation failed" })
|
check(exitCode == 0, { "Compilation failed" })
|
||||||
check(output.toFile().exists(), { "Compiler swiftc hasn't produced an output file: $output" })
|
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
|
testKotlinVersion=1.3.40-dev-2423
|
||||||
# See https://teamcity.jetbrains.com/project.html?projectId=Kotlin_KotlinNativeShared&tab=projectOverview
|
# See https://teamcity.jetbrains.com/project.html?projectId=Kotlin_KotlinNativeShared&tab=projectOverview
|
||||||
sharedRepo=https://dl.bintray.com/jetbrains/kotlin-native-dependencies
|
sharedRepo=https://dl.bintray.com/jetbrains/kotlin-native-dependencies
|
||||||
sharedVersion=1.0-dev-50
|
sharedVersion=1.0-dev-57
|
||||||
konanVersion=1.3.0
|
konanVersion=1.3.0
|
||||||
org.gradle.jvmargs='-Dfile.encoding=UTF-8'
|
org.gradle.jvmargs='-Dfile.encoding=UTF-8'
|
||||||
org.gradle.workers.max=4
|
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
|
llvmHome.macos_x64 = clang-llvm-6.0.1-darwin-macos
|
||||||
targetToolchain.macos_x64 = target-toolchain-9-macos_x64
|
targetToolchain.macos_x64 = target-toolchain-9-macos_x64
|
||||||
libffiDir.macos_x64 = libffi-3.2.1-3-darwin-macos
|
libffiDir.macos_x64 = libffi-3.2.1-3-darwin-macos
|
||||||
|
additionalToolsDir.macos_x64 = xcode-addon-9-macos_x64
|
||||||
|
|
||||||
arch.macos_x64 = x86_64
|
arch.macos_x64 = x86_64
|
||||||
targetSysRoot.macos_x64 = target-sysroot-9-macos_x64
|
targetSysRoot.macos_x64 = target-sysroot-9-macos_x64
|
||||||
llvmLtoFlags.macos_x64 =
|
|
||||||
llvmLtoOptFlags.macos_x64 = -O3 -function-sections
|
clangFlags.macos_x64 = -cc1 -emit-obj -disable-llvm-passes -x ir
|
||||||
llvmLtoNooptFlags.macos_x64 = -O1
|
clangNooptFlags.macos_x64 = -O1
|
||||||
llvmLtoDynamicFlags.macos_x64 = -relocation-model=pic
|
clangOptFlags.macos_x64 = -O3
|
||||||
|
clangDebugFlags.macos_x64 = -O0
|
||||||
|
clangDynamicFlags.macos_x64 =
|
||||||
|
|
||||||
linkerKonanFlags.macos_x64 = -lSystem -lc++ -lobjc -framework Foundation
|
linkerKonanFlags.macos_x64 = -lSystem -lc++ -lobjc -framework Foundation
|
||||||
linkerOptimizationFlags.macos_x64 = -dead_strip
|
linkerOptimizationFlags.macos_x64 = -dead_strip
|
||||||
linkerNoDebugFlags.macos_x64 = -S
|
linkerNoDebugFlags.macos_x64 = -S
|
||||||
linkerDynamicFlags.macos_x64 = -dylib
|
linkerDynamicFlags.macos_x64 = -dylib
|
||||||
|
|
||||||
osVersionMinFlagLd.macos_x64 = -macosx_version_min
|
osVersionMinFlagLd.macos_x64 = -macosx_version_min
|
||||||
osVersionMinFlagClang.macos_x64 = -mmacosx-version-min
|
osVersionMinFlagClang.macos_x64 = -mmacosx-version-min
|
||||||
osVersionMin.macos_x64 = 10.11
|
osVersionMin.macos_x64 = 10.11
|
||||||
entrySelector.macos_x64 = -alias _Konan_main _main
|
entrySelector.macos_x64 = -alias _Konan_main _main
|
||||||
dependencies.macos_x64 = \
|
dependencies.macos_x64 = \
|
||||||
libffi-3.2.1-3-darwin-macos \
|
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 = \
|
target-sysroot-9-macos_x64.default = \
|
||||||
remote:internal
|
remote:internal
|
||||||
@@ -64,6 +70,10 @@ target-sysroot-9-macos_x64.default = \
|
|||||||
target-toolchain-9-macos_x64.default = \
|
target-toolchain-9-macos_x64.default = \
|
||||||
remote:internal
|
remote:internal
|
||||||
|
|
||||||
|
xcode-addon-9-macos_x64.default = \
|
||||||
|
remote:internal
|
||||||
|
|
||||||
|
|
||||||
# Apple's 32-bit iOS.
|
# Apple's 32-bit iOS.
|
||||||
targetToolchain.macos_x64-ios_arm32 = target-toolchain-9-macos_x64
|
targetToolchain.macos_x64-ios_arm32 = target-toolchain-9-macos_x64
|
||||||
dependencies.macos_x64-ios_arm32 = \
|
dependencies.macos_x64-ios_arm32 = \
|
||||||
@@ -77,13 +87,15 @@ arch.ios_arm32 = armv7
|
|||||||
entrySelector.ios_arm32 = -alias _Konan_main _main
|
entrySelector.ios_arm32 = -alias _Konan_main _main
|
||||||
# Shared with 64-bit version.
|
# Shared with 64-bit version.
|
||||||
targetSysRoot.ios_arm32 = target-sysroot-9-ios_arm64
|
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
|
linkerNoDebugFlags.ios_arm32 = -S
|
||||||
linkerDynamicFlags.ios_arm32 = -dylib
|
linkerDynamicFlags.ios_arm32 = -dylib
|
||||||
llvmLtoNooptFlags.ios_arm32 = -O1
|
linkerKonanFlags.ios_arm32 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 11.2
|
||||||
llvmLtoDynamicFlags.ios_arm32 = -relocation-model=pic
|
|
||||||
linkerKonanFlags.ios_arm32 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 12.2
|
|
||||||
linkerOptimizationFlags.ios_arm32 = -dead_strip
|
linkerOptimizationFlags.ios_arm32 = -dead_strip
|
||||||
osVersionMinFlagLd.ios_arm32 = -iphoneos_version_min
|
osVersionMinFlagLd.ios_arm32 = -iphoneos_version_min
|
||||||
osVersionMinFlagClang.ios_arm32 = -miphoneos-version-min
|
osVersionMinFlagClang.ios_arm32 = -miphoneos-version-min
|
||||||
@@ -101,13 +113,16 @@ target-sysroot-9-ios_arm64.default = \
|
|||||||
arch.ios_arm64 = arm64
|
arch.ios_arm64 = arm64
|
||||||
entrySelector.ios_arm64 = -alias _Konan_main _main
|
entrySelector.ios_arm64 = -alias _Konan_main _main
|
||||||
targetSysRoot.ios_arm64 = target-sysroot-9-ios_arm64
|
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
|
linkerNoDebugFlags.ios_arm64 = -S
|
||||||
linkerDynamicFlags.ios_arm64 = -dylib
|
linkerDynamicFlags.ios_arm64 = -dylib
|
||||||
llvmLtoNooptFlags.ios_arm64 = -O1
|
linkerKonanFlags.ios_arm64 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 11.2
|
||||||
llvmLtoDynamicFlags.ios_arm64 = -relocation-model=pic
|
|
||||||
linkerKonanFlags.ios_arm64 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 12.2
|
|
||||||
linkerOptimizationFlags.ios_arm64 = -dead_strip
|
linkerOptimizationFlags.ios_arm64 = -dead_strip
|
||||||
osVersionMinFlagLd.ios_arm64 = -iphoneos_version_min
|
osVersionMinFlagLd.ios_arm64 = -iphoneos_version_min
|
||||||
osVersionMinFlagClang.ios_arm64 = -miphoneos-version-min
|
osVersionMinFlagClang.ios_arm64 = -miphoneos-version-min
|
||||||
@@ -125,11 +140,14 @@ target-sysroot-9-ios_x64.default = \
|
|||||||
arch.ios_x64 = x86_64
|
arch.ios_x64 = x86_64
|
||||||
entrySelector.ios_x64 = -alias _Konan_main _main
|
entrySelector.ios_x64 = -alias _Konan_main _main
|
||||||
targetSysRoot.ios_x64 = target-sysroot-9-ios_x64
|
targetSysRoot.ios_x64 = target-sysroot-9-ios_x64
|
||||||
llvmLtoFlags.ios_x64 =
|
|
||||||
llvmLtoOptFlags.ios_x64 = -O3 -function-sections
|
clangFlags.ios_x64 = -cc1 -emit-obj -disable-llvm-passes -x ir
|
||||||
llvmLtoNooptFlags.ios_x64 = -O1
|
clangNooptFlags.ios_x64 = -O1
|
||||||
llvmLtoDynamicFlags.ios_x64 = -relocation-model=pic
|
clangOptFlags.ios_x64 = -O3
|
||||||
linkerKonanFlags.ios_x64 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 12.2
|
clangDebugFlags.ios_x64 = -O0
|
||||||
|
clangDynamicFlags.ios_x64 =
|
||||||
|
|
||||||
|
linkerKonanFlags.ios_x64 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 11.2
|
||||||
linkerOptimizationFlags.ios_x64 = -dead_strip
|
linkerOptimizationFlags.ios_x64 = -dead_strip
|
||||||
linkerNoDebugFlags.ios_x64 = -S
|
linkerNoDebugFlags.ios_x64 = -S
|
||||||
linkerDynamicFlags.ios_x64 = -dylib
|
linkerDynamicFlags.ios_x64 = -dylib
|
||||||
|
|||||||
@@ -30,6 +30,15 @@ model {
|
|||||||
if (!project.parent.convention.plugins.platformInfo.isWindows())
|
if (!project.parent.convention.plugins.platformInfo.isWindows())
|
||||||
cppCompiler.args "-fPIC"
|
cppCompiler.args "-fPIC"
|
||||||
cppCompiler.args "--std=c++11", "-I${llvmDir}/include", "-I${projectDir}/src/main/include"
|
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"
|
linker.args "-L${llvmDir}/lib", "-lLLVMCore", "-lLLVMSupport"
|
||||||
}
|
}
|
||||||
binaries.withType(SharedLibraryBinarySpec) { binary ->
|
binaries.withType(SharedLibraryBinarySpec) { binary ->
|
||||||
|
|||||||
@@ -228,3 +228,21 @@ LLVMTargetLibraryInfoRef LLVMGetTargetLibraryInfo(LLVMModuleRef moduleRef) {
|
|||||||
auto* libraryInfo = new TargetLibraryInfoImpl(Triple(unwrap(moduleRef)->getTargetTriple()));
|
auto* libraryInfo = new TargetLibraryInfoImpl(Triple(unwrap(moduleRef)->getTargetTriple()));
|
||||||
return llvm::wrap(libraryInfo);
|
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);
|
LLVMTargetLibraryInfoRef LLVMGetTargetLibraryInfo(LLVMModuleRef moduleRef);
|
||||||
|
|
||||||
|
void LLVMKotlinInitializeTargets();
|
||||||
|
|
||||||
# ifdef __cplusplus
|
# ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
||||||
# endif
|
# endif
|
||||||
#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_watchos=target-sysroot-$KONAN_TOOLCHAIN_VERSION-watchos_arm32
|
||||||
TARBALL_watchsimulator=target-sysroot-$KONAN_TOOLCHAIN_VERSION-watchos_x64
|
TARBALL_watchsimulator=target-sysroot-$KONAN_TOOLCHAIN_VERSION-watchos_x64
|
||||||
TARBALL_xcode=target-toolchain-$KONAN_TOOLCHAIN_VERSION-macos_x64
|
TARBALL_xcode=target-toolchain-$KONAN_TOOLCHAIN_VERSION-macos_x64
|
||||||
|
TARBALL_xcode_addon=xcode-addon-$KONAN_TOOLCHAIN_VERSION-macos_x64
|
||||||
OUT=`pwd`
|
OUT=`pwd`
|
||||||
|
|
||||||
for s in $SDKS; do
|
for s in $SDKS; do
|
||||||
@@ -26,3 +27,10 @@ t=`grealpath $t/../..`
|
|||||||
tarball=$TARBALL_xcode
|
tarball=$TARBALL_xcode
|
||||||
echo "Packing toolchain $OUT/$tarball.tar.gz..."
|
echo "Packing toolchain $OUT/$tarball.tar.gz..."
|
||||||
$SHELL -c "tar czf $OUT/$tarball.tar.gz -C $t -s '/^\./$tarball/' ."
|
$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