diff --git a/compiler/cli/cli-common/gen/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArgumentsCopyGenerated.kt b/compiler/cli/cli-common/gen/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArgumentsCopyGenerated.kt index 032f64559e9..65ae92a369c 100644 --- a/compiler/cli/cli-common/gen/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArgumentsCopyGenerated.kt +++ b/compiler/cli/cli-common/gen/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArgumentsCopyGenerated.kt @@ -22,9 +22,6 @@ fun copyK2NativeCompilerArguments(from: K2NativeCompilerArguments, to: K2NativeC to.checkExternalCalls = from.checkExternalCalls to.clangOptions = from.clangOptions?.copyOf() to.compileFromBitcode = from.compileFromBitcode - to.coverage = from.coverage - to.coverageFile = from.coverageFile - to.coveredLibraries = from.coveredLibraries?.copyOf() to.debug = from.debug to.debugInfoFormatVersion = from.debugInfoFormatVersion to.debugPrefixMap = from.debugPrefixMap?.copyOf() diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArguments.kt index 4f98d2da25f..8efc7e16b00 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArguments.kt @@ -353,21 +353,6 @@ The default value is 1.""" @Argument(value = "-Xdebug-info-version", description = "Generate debug info of the given version (1, 2).") var debugInfoFormatVersion: String = "1" /* command line parser doesn't accept kotlin.Int type */ - @Argument(value = "-Xcoverage", description = "Emit code coverage information.") - var coverage: Boolean = false - - @Argument( - value = "-Xlibrary-to-cover", - valueDescription = "", - description = """Emit code coverage information for the given library. -The library must be one of the ones passed with '-library'.""", - delimiter = Argument.Delimiters.none - ) - var coveredLibraries: Array? = null - - @Argument(value = "-Xcoverage-file", valueDescription = "", description = "Save coverage information to the given file.") - var coverageFile: String? = null - @Argument(value = "-Xno-objc-generics", description = "Disable generics support for framework header.") var noObjcGenerics: Boolean = false diff --git a/kotlin-native/CODE_COVERAGE.md b/kotlin-native/CODE_COVERAGE.md deleted file mode 100644 index f64949ed7e6..00000000000 --- a/kotlin-native/CODE_COVERAGE.md +++ /dev/null @@ -1,66 +0,0 @@ -# Code Coverage -Kotlin/Native has a code coverage support that is based on Clang's -[Source-based Code Coverage](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html). - -## **Please note**: -1. Currently, support for code coverage in Kotlin/Native is broken and not working out of the box. -If you would like to fix it and need guidance, - please contact us on the [public Slack](https://slack.kotlinlang.org/) on `#kotlin-native` channel. -2. Most of the described functionality might be incorporated into Gradle plugin some day. - -### Usage - -#### TL;DR -```bash -kotlinc-native main.kt -Xcoverage -./program.kexe -llvm-profdata merge program.kexe.profraw -o program.profdata -llvm-cov report program.kexe -instr-profile program.profdata -``` - -#### Compiling with coverage enabled - -There are 2 compiler flags that allows to generate coverage information: -* `-Xcoverage`. Generate coverage for immediate sources. -* `-Xlibrary-to-cover=`. Generate coverage for specified `klib`. -Note that library also should be either linked via `-library/-l` compiler option or be a transitive dependency. - -#### Running covered executable - -After the execution of the compiled binary (ex. `program.kexe`) `program.kexe.profraw` will be generated. -By default it will be generated in the same location where binary was created. The are two ways to override this behavior: - * `-Xcoverage-file=` compiler flag. - * `LLVM_PROFILE_FILE` environment variable. So if you run your program like this: -``` -LLVM_PROFILE_FILE=build/program.profraw ./program.kexe -``` -Then the coverage information will be stored to the `build` dir as `program.profraw`. - -#### Parsing `*.profraw` - -Generated file can be parsed with `llvm-profdata` utility. Basic usage: -``` -llvm-profdata merge default.profraw -o program.profdata -``` -See [command guide](http://llvm.org/docs/CommandGuide/llvm-profdata.html) for more options. - -#### Creating reports - -The last step is to create a report from the `program.profdata` file. -It can be done with `llvm-cov` utility (refer to [command guide](http://llvm.org/docs/CommandGuide/llvm-cov.html) for detailed usage). -For example, we can see a basic report using: -``` -llvm-cov report program.kexe -instr-profile program.profdata -``` -Or show a line-by-line coverage information in html: -``` -llvm-cov show program.kexe -instr-profile program.profdata -format=html > report.html -``` - -### Sample -Usually coverage information is collected during running of the tests. -Please refer to `samples/coverage` to see how it can be done. - - -### Useful links -* [LLVM Code Coverage Mapping Format](https://llvm.org/docs/CoverageMappingFormat.html) \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FeaturedLibraries.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FeaturedLibraries.kt index c37abd8575a..d5be143cd46 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FeaturedLibraries.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FeaturedLibraries.kt @@ -57,18 +57,6 @@ internal fun getIncludedLibraries( allowDefaultLibs = false ) -internal fun getCoveredLibraries( - configuration: CompilerConfiguration, - resolvedLibraries: KotlinLibraryResolveResult, - resolver: SearchPathResolver -): List = getFeaturedLibraries( - configuration.getList(KonanConfigKeys.LIBRARIES_TO_COVER), - resolvedLibraries, - resolver, - FeaturedLibrariesReporter.forCoveredLibraries(configuration), - allowDefaultLibs = true -) - private sealed class FeaturedLibrariesReporter { abstract fun reportIllegalKind(library: KonanLibrary) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt index 313c4c7eea9..2dd8e42c1f6 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt @@ -308,9 +308,6 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration return resolvedLibraries.filterRoots { (!it.isDefault && !this.purgeUserLibs) || it.isNeededForLink }.getFullList(TopologicalLibraryOrder).map { it as KonanLibrary } } - val shouldCoverSources = configuration.getBoolean(KonanConfigKeys.COVERAGE) - private val shouldCoverLibraries = !configuration.getList(KonanConfigKeys.LIBRARIES_TO_COVER).isNullOrEmpty() - private val defaultAllocationMode get() = if (sanitizer == null) AllocationMode.CUSTOM @@ -377,7 +374,6 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration GC.CONCURRENT_MARK_AND_SWEEP -> add("concurrent_ms_gc.bc") } } - if (shouldCoverLibraries || shouldCoverSources) add("profileRuntime.bc") if (target.supportsCoreSymbolication()) { add("source_info_core_symbolication.bc") } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt index 0d2e52a638e..09680c4d34d 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt @@ -135,12 +135,6 @@ class KonanConfigKeys { = CompilerConfigurationKey.create("verify compiler") val DEBUG_INFO_VERSION: CompilerConfigurationKey = CompilerConfigurationKey.create("debug info format version") - val COVERAGE: CompilerConfigurationKey - = CompilerConfigurationKey.create("emit coverage info for sources") - val LIBRARIES_TO_COVER: CompilerConfigurationKey> - = CompilerConfigurationKey.create("libraries that should be covered") - val PROFRAW_PATH: CompilerConfigurationKey - = CompilerConfigurationKey.create("path to *.profraw coverage output") val OBJC_GENERICS: CompilerConfigurationKey = CompilerConfigurationKey.create("write objc header with generics support") val DEBUG_PREFIX_MAP: CompilerConfigurationKey> diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLibrariesResolveSupport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLibrariesResolveSupport.kt index 0fb0bf38847..d3b20d92879 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLibrariesResolveSupport.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLibrariesResolveSupport.kt @@ -71,9 +71,6 @@ class KonanLibrariesResolveSupport( internal val exportedLibraries = getExportedLibraries(configuration, resolvedLibraries, resolver.searchPathResolver, report = true) - internal val coveredLibraries = - getCoveredLibraries(configuration, resolvedLibraries, resolver.searchPathResolver) - internal val includedLibraries = getIncludedLibraries(includedLibraryFiles, configuration, resolvedLibraries) } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Linker.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Linker.kt index 1022509802f..8f9e56713f2 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Linker.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Linker.kt @@ -40,7 +40,6 @@ internal fun determineLinkerOutput(context: PhaseContext): LinkerOutputKind = internal class Linker( private val config: KonanConfig, private val linkerOutput: LinkerOutputKind, - private val isCoverageEnabled: Boolean = false, private val outputFiles: OutputFiles, ) { private val platform = config.platform @@ -147,7 +146,6 @@ internal class Linker( debug = debug, kind = linkerOutput, outputDsymBundle = outputFiles.symbolicInfoFile, - needsProfileLibrary = isCoverageEnabled, mimallocEnabled = config.allocationMode == AllocationMode.MIMALLOC, sanitizer = config.sanitizer ) @@ -189,4 +187,4 @@ internal fun runLinkerCommands(context: PhaseContext, commands: List, c val extraInfo = listOfNotNull(extraUserInfo, extraUserSetupInfo).joinToString(separator = "\n") context.reportCompilationError("${e.toolName} invocation reported errors\n$extraInfo\n${e.message}") -} \ No newline at end of file +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/NativeGenerationState.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/NativeGenerationState.kt index a8d697f8a7f..c824f241149 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/NativeGenerationState.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/NativeGenerationState.kt @@ -13,7 +13,6 @@ import org.jetbrains.kotlin.backend.konan.driver.PhaseContext import org.jetbrains.kotlin.backend.konan.driver.utilities.BackendContextHolder import org.jetbrains.kotlin.backend.konan.driver.utilities.LlvmIrHolder import org.jetbrains.kotlin.backend.konan.llvm.* -import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport import org.jetbrains.kotlin.backend.konan.serialization.SerializedClassFields import org.jetbrains.kotlin.backend.konan.serialization.SerializedEagerInitializedFile @@ -101,8 +100,6 @@ internal class NativeGenerationState( val virtualFunctionTrampolines = mutableMapOf() - val coverage by lazy { CoverageManager(this) } - lateinit var objCExport: ObjCExport fun hasDebugInfo() = debugInfoDelegate.isInitialized() @@ -144,4 +141,4 @@ internal class NativeGenerationState( override val llvmModule: LLVMModuleRef get() = llvm.module -} \ No newline at end of file +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/SetupConfiguration.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/SetupConfiguration.kt index b35c8f3ad2a..ce24db5c8ef 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/SetupConfiguration.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/SetupConfiguration.kt @@ -172,9 +172,6 @@ fun CompilerConfiguration.setupFromArguments(arguments: K2NativeCompilerArgument put(BITCODE_EMBEDDING_MODE, selectBitcodeEmbeddingMode(this@setupFromArguments, arguments)) put(DEBUG_INFO_VERSION, arguments.debugInfoFormatVersion.toInt()) - put(COVERAGE, arguments.coverage) - put(LIBRARIES_TO_COVER, arguments.coveredLibraries.toNonNullList()) - arguments.coverageFile?.let { put(PROFRAW_PATH, it) } put(OBJC_GENERICS, !arguments.noObjcGenerics) put(DEBUG_PREFIX_MAP, parseDebugPrefixMap(arguments, this@setupFromArguments)) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Bitcode.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Bitcode.kt index 7b78dead654..4c5181e4a83 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Bitcode.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Bitcode.kt @@ -20,7 +20,6 @@ import org.jetbrains.kotlin.backend.konan.driver.PhaseEngine import org.jetbrains.kotlin.backend.konan.driver.utilities.LlvmIrHolder import org.jetbrains.kotlin.backend.konan.driver.utilities.getDefaultLlvmModuleActions import org.jetbrains.kotlin.backend.konan.insertAliasToEntryPoint -import org.jetbrains.kotlin.backend.konan.llvm.coverage.runCoveragePass import org.jetbrains.kotlin.backend.konan.llvm.verifyModule import org.jetbrains.kotlin.backend.konan.optimizations.RemoveRedundantSafepointsPass import org.jetbrains.kotlin.backend.konan.optimizations.removeMultipleThreadDataLoads @@ -102,13 +101,6 @@ internal val ThreadSanitizerPhase = optimizationPipelinePass( pipeline = ::ThreadSanitizerPipeline, ) -internal val CoveragePhase = createSimpleNamedCompilerPhase( - name = "Coverage", - description = "Produce coverage information", - postactions = getDefaultLlvmModuleActions(), - op = { context, _ -> runCoveragePass(context) } -) - internal val RemoveRedundantSafepointsPhase = createSimpleNamedCompilerPhase( name = "RemoveRedundantSafepoints", description = "Remove function prologue safepoints inlined to another function", @@ -172,9 +164,6 @@ internal fun PhaseEngine.runBitcodePostPro null -> {} } } - if (context is NativeGenerationState && context.coverage.enabled) { - newEngine(context) { it.runPhase(CoveragePhase) } - } if (context.config.memoryModel == MemoryModel.EXPERIMENTAL) { runPhase(RemoveRedundantSafepointsPhase) } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Linker.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Linker.kt index 8f108775bde..65e2205bacf 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Linker.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Linker.kt @@ -19,7 +19,6 @@ internal data class LinkerPhaseInput( val dependenciesTrackingResult: DependenciesTrackingResult, val outputFiles: OutputFiles, val resolvedCacheBinaries: ResolvedCacheBinaries, - val isCoverageEnabled: Boolean, ) internal val LinkerPhase = createSimpleNamedCompilerPhase( @@ -29,7 +28,6 @@ internal val LinkerPhase = createSimpleNamedCompilerPhase PhaseEngine.runBackend(backendContext: Contex depsFilePath.File().writeLines(DependenciesTrackingResult.serialize(dependenciesTrackingResult)) } val moduleCompilationOutput = ModuleCompilationOutput(bitcodeFile, dependenciesTrackingResult) - compileAndLink(moduleCompilationOutput, outputFiles.mainFileName, outputFiles, tempFiles, isCoverageEnabled = false) + compileAndLink(moduleCompilationOutput, outputFiles.mainFileName, outputFiles, tempFiles) } } finally { tempFiles.dispose() @@ -163,7 +163,7 @@ internal fun PhaseEngine.runBitcodeBackend(context: Bitcod bitcodeEngine.runBitcodePostProcessing() runPhase(WriteBitcodeFilePhase, WriteBitcodeFileInput(context.llvm.module, bitcodeFile)) val moduleCompilationOutput = ModuleCompilationOutput(bitcodeFile, dependencies) - compileAndLink(moduleCompilationOutput, outputFiles.mainFileName, outputFiles, tempFiles, isCoverageEnabled = false) + compileAndLink(moduleCompilationOutput, outputFiles.mainFileName, outputFiles, tempFiles) } } @@ -269,7 +269,6 @@ internal fun PhaseEngine.compileAndLink( linkerOutputFile: String, outputFiles: OutputFiles, temporaryFiles: TempFiles, - isCoverageEnabled: Boolean, ) { val compilationResult = temporaryFiles.create(File(outputFiles.nativeBinaryFile).name, ".o").javaFile() runPhase(ObjectFilesPhase, ObjectFilesPhaseInput(moduleCompilationOutput.bitcodeFile, compilationResult)) @@ -298,7 +297,6 @@ internal fun PhaseEngine.compileAndLink( moduleCompilationOutput.dependenciesTrackingResult, outputFiles, cacheBinaries, - isCoverageEnabled = isCoverageEnabled ) runPhase(LinkerPhase, linkerPhaseInput) if (context.config.produce.isCache) { @@ -388,4 +386,4 @@ private fun PhaseEngine.findDependenciesToCompile(): List // This guarantees that libraries initializers are emitted in correct order. private fun mergeDependencies(targetModule: IrModuleFragment, dependencies: List) { targetModule.files.addAll(0, dependencies.flatMap { it.files }) -} \ No newline at end of file +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 398f43f072a..8255c4e1a73 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -17,7 +17,6 @@ import org.jetbrains.kotlin.backend.konan.cexport.CAdapterExportedElements import org.jetbrains.kotlin.backend.konan.cgen.CBridgeOrigin import org.jetbrains.kotlin.backend.konan.descriptors.* import org.jetbrains.kotlin.backend.konan.ir.* -import org.jetbrains.kotlin.backend.konan.llvm.coverage.LLVMCoverageInstrumentation import org.jetbrains.kotlin.backend.konan.lower.* import org.jetbrains.kotlin.builtins.UnsignedType import org.jetbrains.kotlin.descriptors.Modality @@ -472,8 +471,6 @@ internal class CodeGeneratorVisitor( override fun visitModuleFragment(declaration: IrModuleFragment) { context.log{"visitModule : ${ir2string(declaration)}"} - generationState.coverage.collectRegions(declaration) - initializeCachedBoxes(generationState) declaration.acceptChildrenVoid(this) @@ -483,7 +480,6 @@ internal class CodeGeneratorVisitor( codegen.objCDataGenerator?.finishModule() - generationState.coverage.writeRegionInfo() overrideRuntimeGlobals() appendLlvmUsed("llvm.used", llvm.usedFunctions.map { it.toConstPointer().llvm } + llvm.usedGlobals) appendLlvmUsed("llvm.compiler.used", llvm.compilerUsedGlobals) @@ -744,9 +740,6 @@ internal class CodeGeneratorVisitor( constructor(llvmFunction: LlvmCallable, functionGenerationContext: FunctionGenerationContext) : this(functionGenerationContext, null, llvmFunction) - val coverageInstrumentation: LLVMCoverageInstrumentation? = - generationState.coverage.tryGetInstrumentation(declaration) { function, args -> functionGenerationContext.call(function, args) } - override fun genReturn(target: IrSymbolOwner, value: LLVMValueRef?) { if (declaration == null || target == declaration) { if ((target as IrFunction).returnsUnit()) { @@ -884,7 +877,6 @@ internal class CodeGeneratorVisitor( val parameterScope = ParameterScope(declaration, functionGenerationContext) using(parameterScope) usingParameterScope@{ using(VariableScope()) usingVariableScope@{ - recordCoverage(body) if (declaration.isReifiedInline) { callDirect(context.ir.symbols.throwIllegalStateExceptionWithMessage.owner, listOf(codegen.staticData.kotlinStringLiteral( @@ -974,18 +966,10 @@ internal class CodeGeneratorVisitor( } } - private fun recordCoverage(irElement: IrElement) { - val scope = currentCodeContext.functionScope() - if (scope is FunctionScope) { - scope.coverageInstrumentation?.instrumentIrElement(irElement) - } - } - //-------------------------------------------------------------------------// private fun evaluateExpression(value: IrExpression, resultSlot: LLVMValueRef? = null): LLVMValueRef { updateBuilderDebugLocation(value) - recordCoverage(value) when (value) { is IrTypeOperatorCall -> return evaluateTypeOperator (value, resultSlot) is IrCall -> return evaluateCall (value, resultSlot) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmCallable.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmCallable.kt index 7bf020c3875..df929136781 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmCallable.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmCallable.kt @@ -27,10 +27,6 @@ class LlvmCallable(val functionType: LLVMTypeRef, private val llvmValue: LLVMVal LLVMCountParamTypes(functionType) } - val pgoFunctionNameVar by lazy { - LLVMCreatePGOFunctionNameVar(llvmValue, name)!! - } - val isConstant by lazy { LLVMIsConstant(llvmValue) == 1 } @@ -82,4 +78,4 @@ class LlvmCallable(val functionType: LLVMTypeRef, private val llvmValue: LLVMVal // these functions are potentially unsafe, as they need to use same attribute provider when converted to callable internal fun toConstPointer() = constPointer(llvmValue) internal fun asCallback() = llvmValue -} \ No newline at end of file +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageInformation.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageInformation.kt deleted file mode 100644 index fa33e0072aa..00000000000 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageInformation.kt +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2010-2019 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.llvm.coverage - -import org.jetbrains.kotlin.backend.konan.llvm.computeSymbolName -import org.jetbrains.kotlin.backend.konan.llvm.lineAndColumn -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET -import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.declarations.name -import org.jetbrains.kotlin.ir.util.ir2string - -/** - * The most important class in the coverage package. - * It describes textual region of the code that is associated with IrElement. - * Besides the obvious [file] and line/column borders, it has [RegionKind] which is described later. - */ -class Region( - val startOffset: Int, - val endOffset: Int, - val file: IrFile, - val kind: RegionKind -) { - val startLineAndColumn: Pair - get() = file.fileEntry.lineAndColumn(startOffset) - - val endLineAndColumn: Pair - get() = file.fileEntry.lineAndColumn(endOffset) - - companion object { - fun fromIr(irElement: IrElement, irFile: IrFile, kind: RegionKind = RegionKind.Code) = - fromOffset(irElement.startOffset, irElement.endOffset, irFile, kind) - - fun fromOffset(startOffset: Int, endOffset: Int, irFile: IrFile, kind: RegionKind = RegionKind.Code) = - if (startOffset == UNDEFINED_OFFSET || endOffset == UNDEFINED_OFFSET || startOffset == endOffset) null - else Region(startOffset, endOffset, irFile, kind) - } - - override fun toString(): String { - val expansion = (kind as? RegionKind.Expansion)?.let { " expand to " + it.expandedFile.name } ?: "" - return "${file.name}$expansion: ${kind::class.simpleName} $startLineAndColumn -> $endLineAndColumn" - } -} - -/** - * Describes what is the given code region. - * Based on llvm::coverage::CounterMappingRegion. - * Currently only [RegionKind.Code] is used. - */ -sealed class RegionKind { - /** - * Regular peace of code. - */ - object Code : RegionKind() - /** - * Empty line. - */ - object Gap : RegionKind() - /** - * Region of code that is an expansion of another source file. - * Used for inline function. - */ - class Expansion(val expandedFile: IrFile) : RegionKind() -} - -/** - * "Regional" description of the [function]. - */ -class FunctionRegions( - val function: IrFunction, - val regions: Map -) { - // Enumeration is required for serialization and instrumentation calls. - val regionEnumeration = regions.values.mapIndexed { index, region -> region to index }.toMap() - // Actually, it should be computed. - // But since we don't support PGO structural hash doesn't really matter for now. - val structuralHash: Long = 0 - - override fun toString(): String = buildString { - appendLine("${function.computeSymbolName()} regions:") - regions.forEach { (irElem, region) -> appendLine("${ir2string(irElem)} -> ($region)") } - } -} - -/** - * Since file is the biggest unit in terms of the code coverage - * we aggregate [FunctionRegions] per [file]. - */ -class FileRegionInfo( - val file: IrFile, - val functions: List -) \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageManager.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageManager.kt deleted file mode 100644 index 6b7887e9632..00000000000 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageManager.kt +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2010-2019 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.llvm.coverage - -import llvm.* -import org.jetbrains.kotlin.backend.konan.* -import org.jetbrains.kotlin.backend.konan.llvm.LlvmCallable -import org.jetbrains.kotlin.backend.konan.reportCompilationError -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI -import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.declarations.IrModuleFragment -import org.jetbrains.kotlin.konan.file.File -import org.jetbrains.kotlin.konan.target.supportsCodeCoverage - -/** - * "Umbrella" class of all the of the code coverage related logic. - */ -internal class CoverageManager(val generationState: NativeGenerationState) { - private val context = generationState.context - private val config = generationState.config - - private val shouldCoverSources: Boolean = - config.shouldCoverSources - - private val librariesToCover: Set = - config.resolve.coveredLibraries.map { it.libraryName }.toSet() - - private val llvmProfileFilenameGlobal = "__llvm_profile_filename" - - private val defaultOutputFilePath: String by lazy { - "${generationState.outputFile}.profraw" - } - - private val outputFileName: String = - config.configuration.get(KonanConfigKeys.PROFRAW_PATH) - ?.let { File(it).absolutePath } - ?: defaultOutputFilePath - - val enabled: Boolean = - shouldCoverSources || librariesToCover.isNotEmpty() - - init { - if (enabled && !checkRestrictions()) { - generationState.reportCompilationError("Coverage is not supported for ${config.target}.") - } - } - - private fun checkRestrictions(): Boolean { - val isKindAllowed = config.produce.involvesBitcodeGeneration - val target = config.target - val isTargetAllowed = target.supportsCodeCoverage() - return isKindAllowed && isTargetAllowed - } - - private val filesRegionsInfo = mutableListOf() - - private fun getFunctionRegions(irFunction: IrFunction) = - filesRegionsInfo.flatMap { it.functions }.firstOrNull { it.function == irFunction } - - private val coveredModules: Set by lazy { - val coveredSources = if (shouldCoverSources) { - context.sourcesModules - } else { - emptySet() - } - val coveredLibs = context.irModules.filter { it.key in librariesToCover }.values - .map { it.descriptor }.toSet() - coveredLibs + coveredSources - } - - @OptIn(ObsoleteDescriptorBasedAPI::class) - private fun fileCoverageFilter(file: IrFile) = - file.moduleDescriptor in coveredModules - - /** - * Walk [irModuleFragment] subtree and collect [FileRegionInfo] for files that are part of [coveredModules]. - */ - fun collectRegions(irModuleFragment: IrModuleFragment) { - if (enabled) { - val regions = CoverageRegionCollector(this::fileCoverageFilter).collectFunctionRegions(irModuleFragment) - filesRegionsInfo += regions - } - } - - /** - * @return [LLVMCoverageInstrumentation] instance if [irFunction] should be covered. - */ - fun tryGetInstrumentation(irFunction: IrFunction?, callSitePlacer: (function: LlvmCallable, args: List) -> Unit) = - if (enabled && irFunction != null) { - getFunctionRegions(irFunction)?.let { LLVMCoverageInstrumentation(generationState, it, callSitePlacer) } - } else { - null - } - - /** - * Add __llvm_coverage_mapping to the LLVM module. - */ - fun writeRegionInfo() { - if (enabled) { - LLVMCoverageWriter(generationState, filesRegionsInfo).write() - } - } - - /** - * Add passes that should be executed after main LLVM optimization pipeline. - */ - fun addLateLlvmPasses(passManager: LLVMPassManagerRef) { - if (enabled) { - // It's a late pass since DCE can kill __llvm_profile_filename global. - LLVMAddInstrProfPass(passManager, outputFileName) - } - } - - /** - * Since we performing instruction profiling before internalization and global dce - * __llvm_profile_filename need to be added to exported symbols. - */ - fun addExportedSymbols(): List = - if (enabled) { - listOf(llvmProfileFilenameGlobal) - } else { - emptyList() - } -} - -internal fun runCoveragePass(generationState: NativeGenerationState) { - if (!generationState.coverage.enabled) return - val passManager = LLVMCreatePassManager()!! - LLVMKotlinAddTargetLibraryInfoWrapperPass(passManager, generationState.llvm.targetTriple) - generationState.coverage.addLateLlvmPasses(passManager) - LLVMRunPassManager(passManager, generationState.llvm.module) - LLVMDisposePassManager(passManager) -} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageRegionCollector.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageRegionCollector.kt deleted file mode 100644 index 670949e0ff1..00000000000 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageRegionCollector.kt +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright 2010-2019 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.llvm.coverage - -import org.jetbrains.kotlin.ir.util.sourceFileSymbol -import org.jetbrains.kotlin.backend.common.pop -import org.jetbrains.kotlin.backend.common.push -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.util.statements -import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid -import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid -import org.jetbrains.kotlin.ir.visitors.acceptVoid - -/** - * Collect all regions in the module. - * @param fileFilter filters files that should be processed. - */ -internal class CoverageRegionCollector(private val fileFilter: (IrFile) -> Boolean) { - - fun collectFunctionRegions(irModuleFragment: IrModuleFragment): List = - irModuleFragment.files - .filter(fileFilter) - .map { file -> - val collector = FunctionsCollector(file) - collector.visitFile(file) - FileRegionInfo(file, collector.functionRegions) - } - - private inner class FunctionsCollector(val file: IrFile) : IrElementVisitorVoid { - - val functionRegions = mutableListOf() - - override fun visitElement(element: IrElement) { - element.acceptChildrenVoid(this) - } - - override fun visitFunction(declaration: IrFunction) { - if (!declaration.isInline && !declaration.isExternal && !declaration.isGeneratedByCompiler) { - val regionsCollector = IrFunctionRegionsCollector(fileFilter, file) - declaration.acceptVoid(regionsCollector) - if (regionsCollector.regions.isNotEmpty()) { - functionRegions += FunctionRegions(declaration, regionsCollector.regions) - } - } - // TODO: Decide how to work with local functions. Should they be process separately? - declaration.acceptChildrenVoid(this) - } - } -} - -// User doesn't bother about compiler-generated declarations. -// So lets filter them. -private val IrFunction.isGeneratedByCompiler: Boolean - get() { - return origin != IrDeclarationOrigin.DEFINED || name.asString() == "Konan_start" - } - -/** - * Very similar to [org.jetbrains.kotlin.backend.konan.llvm.CodeGeneratorVisitor] but instead of bitcode generation we collect regions. - * [fileFilter]: specify which files should be processed by code coverage. Here it is required - * for checking calls to inline functions from other files. - * TODO: for now it is very inaccurate. - */ -private class IrFunctionRegionsCollector( - val fileFilter: (IrFile) -> Boolean, - val irFile: IrFile -) : IrElementVisitorVoid { - - private data class StatementContext(val current: IrStatement, val next: IrStatement?) - - val regions = mutableMapOf() - - private val irFileStack = mutableListOf(irFile) - - private val regionStack = mutableListOf() - - private val irStatementsStack = mutableListOf() - - private val currentFile: IrFile - get() = irFileStack.last() - - private val currentRegion: Region - get() = regionStack.last() - - override fun visitElement(element: IrElement) { - element.acceptChildrenVoid(this) - } - - override fun visitSimpleFunction(declaration: IrSimpleFunction) { - declaration.body?.let { body -> - visitInRegionContext(recordRegion(body) ?: return) { - body.acceptVoid(this) - } - } - } - - override fun visitConstructor(declaration: IrConstructor) { - val statements = declaration.body?.statements ?: return - visitInStatementContext(statements) { statement -> - if (statement is IrDelegatingConstructorCall && !declaration.isPrimary - || statement !is IrDelegatingConstructorCall && statement !is IrReturn) { - recordRegion(statement) - statement.acceptVoid(this) - } - } - } - - override fun visitBody(body: IrBody) = visitInStatementContext(body.statements) - - override fun visitContainerExpression(expression: IrContainerExpression) { - val statements = expression.statements - when (expression) { - is IrReturnableBlock -> { - val file = expression.sourceFileSymbol?.owner - if (file != null && file != currentFile && fileFilter(file)) { - recordRegion(expression) - visitInFileContext(file) { - visitInStatementContext(statements) - } - } - } - else -> visitInStatementContext(statements) - } - } - - // TODO: The following implementation produces correct region mapping, but something goes wrong later - // override fun visitFieldAccess(expression: IrFieldAccessExpression) { - // expression.receiver?.let { recordRegion(it) } - // expression.acceptChildrenVoid(this) - // } - - override fun visitWhen(expression: IrWhen) { - val branches = expression.branches - branches.forEach { - val condition = it.condition - val result = it.result - - if (condition is IrConst<*> && condition.value == true && condition.endOffset == result.endOffset) { - // Probably an 'else' branch. - // Note: can't rely on [IrElseBranch], because IR deserializer doesn't emit it. - recordRegion(result) - } else { - recordRegion(condition) - recordRegion(result, condition.endOffset, result.endOffset) - condition.acceptVoid(this) - } - result.acceptVoid(this) - } - } - - override fun visitLoop(loop: IrLoop) { - val condition = loop.condition - recordRegion(condition) - condition.acceptVoid(this) - - val body = loop.body ?: return - when (loop) { - is IrWhileLoop -> recordRegion(body, condition.endOffset, body.endOffset) - is IrDoWhileLoop -> recordRegion(body, body.startOffset, condition.startOffset) - } - body.acceptVoid(this) - } - - override fun visitBreakContinue(jump: IrBreakContinue) { - val (current, next) = irStatementsStack.lastOrNull() ?: return - recordRegion(next ?: return, current.endOffset, jump.loop.endOffset) - } - - override fun visitReturn(expression: IrReturn) { - irStatementsStack.subList(0, irStatementsStack.lastIndex) - .filter { (current, next) -> next != null && current.endOffset > expression.endOffset } - .forEach { (current, next) -> recordRegion(next!!, expression.endOffset, current.endOffset) } - val next = irStatementsStack.lastOrNull()?.next ?: return - val nextRegion = recordRegion(next, expression.endOffset, currentRegion.endOffset) ?: return - regionStack.pop() - regionStack.push(nextRegion) - } - - private fun visitInFileContext(file: IrFile, visit: () -> Unit) { - irFileStack.push(file) - visit() - irFileStack.pop() - } - - private fun visitInRegionContext(region: Region, visit: () -> Unit) { - regionStack.push(region) - visit() - regionStack.pop() - } - - private fun visitInStatementContext( - statements: List, - visit: (IrStatement) -> Unit = { statement -> statement.acceptVoid(this) } - ) { - for (i in 0..statements.lastIndex) { - val current = statements[i] - if (!current.hasValidOffsets()) { - continue - } - val nextInContext = irStatementsStack.lastOrNull()?.next - val next = if (i < statements.lastIndex && statements[i + 1].hasValidOffsets()) statements[i + 1] else nextInContext - irStatementsStack.push(StatementContext(current, next)) - visit(current) - irStatementsStack.pop() - } - } - - private fun recordRegion(irElement: IrElement, kind: RegionKind = RegionKind.Code) - = Region.fromIr(irElement, currentFile, kind)?.also { regions[irElement] = it } - - private fun recordRegion(irElement: IrElement, startOffset: Int, endOffset: Int, kind: RegionKind = RegionKind.Code) - = Region.fromOffset(startOffset, endOffset, currentFile, kind)?.also { regions[irElement] = it } - - private fun IrElement.hasValidOffsets() = startOffset != UNDEFINED_OFFSET && endOffset != UNDEFINED_OFFSET - && startOffset != endOffset -} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/LLVMCoverageInstrumentation.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/LLVMCoverageInstrumentation.kt deleted file mode 100644 index 0f181b51358..00000000000 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/LLVMCoverageInstrumentation.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2010-2019 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.llvm.coverage - -import llvm.* -import org.jetbrains.kotlin.backend.konan.NativeGenerationState -import org.jetbrains.kotlin.backend.konan.llvm.* -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.IrFunction - -/** - * Places calls to `llvm.instrprof.increment` in the beginning of the each - * region in [functionRegions]. - */ -internal class LLVMCoverageInstrumentation( - override val generationState: NativeGenerationState, - private val functionRegions: FunctionRegions, - private val callSitePlacer: (function: LlvmCallable, args: List) -> Unit -) : ContextUtils { - - private val functionNameGlobal = createFunctionNameGlobal(functionRegions.function) - - private val functionHash = llvm.int64(functionRegions.structuralHash) - - private val instrProfIncrement by lazy { - val incrementFun = LLVMInstrProfIncrement(llvm.module)!! - LlvmCallable( - getGlobalFunctionType(incrementFun), - incrementFun, - LlvmFunctionAttributeProvider.copyFromExternal(incrementFun) - ) - } - - // TODO: It's a great place for some debug output. - fun instrumentIrElement(element: IrElement) { - functionRegions.regions[element]?.let { - placeRegionIncrement(it) - } - } - - /** - * See https://llvm.org/docs/LangRef.html#llvm-instrprof-increment-intrinsic - */ - private fun placeRegionIncrement(region: Region) { - val numberOfRegions = llvm.int32(functionRegions.regions.size) - val regionNumber = llvm.int32(functionRegions.regionEnumeration.getValue(region)) - val args = listOf(functionNameGlobal, functionHash, numberOfRegions, regionNumber) - callSitePlacer(instrProfIncrement, args) - } - - // Each profiled function should have a global with its name in a specific format. - private fun createFunctionNameGlobal(function: IrFunction): LLVMValueRef { - val pgoFunctionName = function.llvmFunction.pgoFunctionNameVar - return LLVMConstBitCast(pgoFunctionName, llvm.int8PtrType)!! - } -} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/LLVMCoverageWriter.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/LLVMCoverageWriter.kt deleted file mode 100644 index 2d87161ec33..00000000000 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/LLVMCoverageWriter.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2010-2019 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.llvm.coverage - -import kotlinx.cinterop.* -import llvm.* -import org.jetbrains.kotlin.backend.konan.NativeGenerationState -import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.declarations.path -import org.jetbrains.kotlin.konan.file.File - -private fun RegionKind.toLLVMCoverageRegionKind(): LLVMCoverageRegionKind = when (this) { - RegionKind.Code -> LLVMCoverageRegionKind.CODE - RegionKind.Gap -> LLVMCoverageRegionKind.GAP - is RegionKind.Expansion -> LLVMCoverageRegionKind.EXPANSION -} - -private fun LLVMCoverageRegion.populateFrom(region: Region, regionId: Int, filesIndex: Map) = apply { - val (lineStart, columnStart) = region.startLineAndColumn - val (lineEnd, columnEnd) = region.endLineAndColumn - - fileId = filesIndex.getValue(region.file) - this.lineStart = lineStart - this.columnStart = columnStart - this.lineEnd = lineEnd - this.columnEnd = columnEnd - counterId = regionId - kind = region.kind.toLLVMCoverageRegionKind() - expandedFileId = if (region.kind is RegionKind.Expansion) filesIndex.getValue(region.kind.expandedFile) else 0 -} - -/** - * Writes all of the coverage information to the [org.jetbrains.kotlin.backend.konan.NativeGenerationState.llvm.module]. - * See http://llvm.org/docs/CoverageMappingFormat.html for the format description. - */ -internal class LLVMCoverageWriter( - private val generationState: NativeGenerationState, - private val filesRegionsInfo: List -) { - fun write() { - if (filesRegionsInfo.isEmpty()) return - - val module = generationState.llvm.module - val filesIndex = filesRegionsInfo.mapIndexed { index, fileRegionInfo -> fileRegionInfo.file to index }.toMap() - - val coverageGlobal = memScoped { - val (functionMappingRecords, functionCoverages) = filesRegionsInfo.flatMap { it.functions }.map { functionRegions -> - val regions = (functionRegions.regions.values).map { region -> - alloc().populateFrom(region, functionRegions.regionEnumeration.getValue(region), filesIndex).ptr - } - val fileIds = functionRegions.regions.map { filesIndex.getValue(it.value.file) }.toSet().toIntArray() - val functionCoverage = LLVMWriteCoverageRegionMapping( - fileIds.toCValues(), fileIds.size.signExtend(), - regions.toCValues(), regions.size.signExtend()) - - val functionName = generationState.llvmDeclarations.forFunction(functionRegions.function).name - val functionMappingRecord = LLVMAddFunctionMappingRecord(LLVMGetModuleContext(generationState.llvm.module), - functionName, functionRegions.structuralHash, functionCoverage)!! - - Pair(functionMappingRecord, functionCoverage) - }.unzip() - val (filenames, fileIds) = filesIndex.entries.toList().map { File(it.key.path).absolutePath to it.value }.unzip() - val retval = LLVMCoverageEmit(module, functionMappingRecords.toCValues(), functionMappingRecords.size.signExtend(), - filenames.toCStringArray(this), fileIds.toIntArray().toCValues(), fileIds.size.signExtend(), - functionCoverages.map { it }.toCValues(), functionCoverages.size.signExtend())!! - - // TODO: Is there a better way to cleanup fields of T* type in `memScoped`? - functionCoverages.forEach { LLVMFunctionCoverageDispose(it) } - - retval - } - generationState.llvm.usedGlobals.add(coverageGlobal) - } -} diff --git a/kotlin-native/backend.native/llvm.def b/kotlin-native/backend.native/llvm.def index 5004cc40a90..9d08146b0e2 100644 --- a/kotlin-native/backend.native/llvm.def +++ b/kotlin-native/backend.native/llvm.def @@ -1,9 +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/Transforms/PassManagerBuilder.h llvm-c/Transforms/IPO.h \ llvm-c/TargetMachine.h llvm-c/Target.h llvm-c/Linker.h llvm-c/Initialization.h \ - llvm-c/DebugInfo.h DebugInfoC.h CoverageMappingC.h CAPIExtensions.h RemoveRedundantSafepoints.h OpaquePointerAPI.h + llvm-c/DebugInfo.h DebugInfoC.h CAPIExtensions.h RemoveRedundantSafepoints.h OpaquePointerAPI.h -headerFilter = llvm-c/* llvm-c/**/* DebugInfoC.h CoverageMappingC.h CAPIExtensions.h RemoveRedundantSafepoints.h OpaquePointerAPI.h +headerFilter = llvm-c/* llvm-c/**/* DebugInfoC.h CAPIExtensions.h RemoveRedundantSafepoints.h OpaquePointerAPI.h compilerOpts = -std=c99 \ -Wall -W -Wno-unused-parameter -Wwrite-strings -Wmissing-field-initializers \ @@ -20,7 +20,7 @@ linkerOpts = -fvisibility-inlines-hidden \ -DNDEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS \ -ldebugInfo -lllvmext -# ./llvm-config --libs analysis bitreader bitwriter core linker target coverage analysis ipo instrumentation lto objcarcopts arm aarch64 webassembly x86 mips +# ./llvm-config --libs analysis bitreader bitwriter core linker target analysis ipo instrumentation lto objcarcopts arm aarch64 webassembly x86 mips linkerOpts.osx = \ -Wl,-search_paths_first -Wl,-headerpad_max_install_names \ -lpthread -lz -lm -lcurses -Wl,-U,_futimens -Wl,-U,_LLVMDumpType \ @@ -31,7 +31,7 @@ linkerOpts.osx = \ -lLLVMAArch64Utils -lLLVMAArch64Info -lLLVMARMDisassembler -lLLVMARMCodeGen -lLLVMCFGuard -lLLVMGlobalISel -lLLVMSelectionDAG \ -lLLVMAsmPrinter -lLLVMDebugInfoDWARF -lLLVMARMAsmParser -lLLVMARMDesc -lLLVMMCDisassembler -lLLVMARMUtils -lLLVMARMInfo -lLLVMLTO \ -lLLVMPasses -lLLVMCoroutines -lLLVMObjCARCOpts -lLLVMExtensions -lLLVMCodeGen -lLLVMipo -lLLVMInstrumentation -lLLVMVectorize \ - -lLLVMScalarOpts -lLLVMIRReader -lLLVMAsmParser -lLLVMInstCombine -lLLVMFrontendOpenMP -lLLVMAggressiveInstCombine -lLLVMCoverage \ + -lLLVMScalarOpts -lLLVMIRReader -lLLVMAsmParser -lLLVMInstCombine -lLLVMFrontendOpenMP -lLLVMAggressiveInstCombine \ -lLLVMTarget -lLLVMLinker -lLLVMTransformUtils -lLLVMBitWriter -lLLVMAnalysis -lLLVMProfileData -lLLVMObject -lLLVMTextAPI -lLLVMMCParser \ -lLLVMMC -lLLVMDebugInfoCodeView -lLLVMDebugInfoMSF -lLLVMBitReader -lLLVMCore -lLLVMRemarks -lLLVMBitstreamReader -lLLVMBinaryFormat \ -lLLVMSupport -lLLVMDemangle @@ -39,7 +39,7 @@ linkerOpts.osx = \ -# ./llvm-config --libs analysis bitreader bitwriter core linker target coverage analysis ipo instrumentation lto arm aarch64 webassembly x86 mips +# ./llvm-config --libs analysis bitreader bitwriter core linker target analysis ipo instrumentation lto arm aarch64 webassembly x86 mips linkerOpts.linux = \ -Wl,-z,noexecstack \ -lrt -ldl -lpthread -lz -lm \ @@ -49,12 +49,12 @@ linkerOpts.linux = \ -lLLVMAArch64Utils -lLLVMAArch64Info -lLLVMARMDisassembler -lLLVMARMCodeGen -lLLVMCFGuard -lLLVMGlobalISel -lLLVMSelectionDAG \ -lLLVMAsmPrinter -lLLVMDebugInfoDWARF -lLLVMARMAsmParser -lLLVMARMDesc -lLLVMMCDisassembler -lLLVMARMUtils -lLLVMARMInfo -lLLVMLTO \ -lLLVMPasses -lLLVMCoroutines -lLLVMObjCARCOpts -lLLVMExtensions -lLLVMCodeGen -lLLVMipo -lLLVMInstrumentation -lLLVMVectorize \ - -lLLVMScalarOpts -lLLVMIRReader -lLLVMAsmParser -lLLVMInstCombine -lLLVMFrontendOpenMP -lLLVMAggressiveInstCombine -lLLVMCoverage \ + -lLLVMScalarOpts -lLLVMIRReader -lLLVMAsmParser -lLLVMInstCombine -lLLVMFrontendOpenMP -lLLVMAggressiveInstCombine \ -lLLVMTarget -lLLVMLinker -lLLVMTransformUtils -lLLVMBitWriter -lLLVMAnalysis -lLLVMProfileData -lLLVMObject -lLLVMTextAPI -lLLVMMCParser \ -lLLVMMC -lLLVMDebugInfoCodeView -lLLVMDebugInfoMSF -lLLVMBitReader -lLLVMCore -lLLVMRemarks -lLLVMBitstreamReader -lLLVMBinaryFormat \ -lLLVMSupport -lLLVMDemangle -# ./llvm-config --libs analysis bitreader bitwriter core linker target coverage analysis ipo instrumentation lto arm aarch64 webassembly x86 +# ./llvm-config --libs analysis bitreader bitwriter core linker target analysis ipo instrumentation lto arm aarch64 webassembly x86 linkerOpts.mingw = \ -lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMX86Desc -lLLVMX86Info -lLLVMWebAssemblyDisassembler \ -lLLVMWebAssemblyCodeGen -lLLVMWebAssemblyDesc -lLLVMWebAssemblyAsmParser -lLLVMWebAssemblyInfo -lLLVMAArch64Disassembler \ @@ -62,7 +62,7 @@ linkerOpts.mingw = \ -lLLVMARMCodeGen -lLLVMCFGuard -lLLVMGlobalISel -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMDebugInfoDWARF -lLLVMARMAsmParser -lLLVMARMDesc \ -lLLVMMCDisassembler -lLLVMARMUtils -lLLVMARMInfo -lLLVMLTO -lLLVMPasses -lLLVMCoroutines -lLLVMObjCARCOpts -lLLVMExtensions -lLLVMCodeGen \ -lLLVMipo -lLLVMInstrumentation -lLLVMVectorize -lLLVMScalarOpts -lLLVMIRReader -lLLVMAsmParser -lLLVMInstCombine -lLLVMFrontendOpenMP \ - -lLLVMAggressiveInstCombine -lLLVMCoverage -lLLVMTarget -lLLVMLinker -lLLVMTransformUtils -lLLVMBitWriter -lLLVMAnalysis -lLLVMProfileData \ + -lLLVMAggressiveInstCombine -lLLVMTarget -lLLVMLinker -lLLVMTransformUtils -lLLVMBitWriter -lLLVMAnalysis -lLLVMProfileData \ -lLLVMObject -lLLVMTextAPI -lLLVMMCParser -lLLVMMC -lLLVMDebugInfoCodeView -lLLVMDebugInfoMSF -lLLVMBitReader -lLLVMCore -lLLVMRemarks \ -lLLVMBitstreamReader -lLLVMBinaryFormat -lLLVMSupport -lLLVMDemangle \ -lpsapi -lshell32 -lole32 -luuid -ladvapi32 diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index 8e56e7fbb94..ebc6f09cec1 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -123,9 +123,6 @@ allprojects { // backend.native/tests/framework ext.testOutputFramework = rootProject.file("$testOutputRoot/framework") - // backent.native/tests/coverage - ext.testOutputCoverage = rootProject.file("$testOutputRoot/coverage") - ext.testOutputFileCheck = rootProject.file("$testOutputRoot/filecheck") } testOutputExternal.mkdirs() @@ -187,7 +184,6 @@ tasks.named("run") { dependsOn(tasks.withType(FrameworkTest).matching { it.enabled }) // Add regular gradle test tasks dependsOn(tasks.withType(Test).matching { it.enabled }) - dependsOn(tasks.withType(CoverageTest).matching { it.enabled }) dependsOn(tasks.withType(FileCheckTest).matching { it.enabled }) dependsOn(":kotlin-native:Interop:Indexer:check") dependsOn(":kotlin-native:Interop:StubGenerator:check") @@ -5080,112 +5076,6 @@ if (isAppleTarget(project)) { } } -if (UtilsKt.getTestTargetSupportsCodeCoverage(project)) { - tasks.register("coverage_basic_program", CoverageTest) { - - binaryName = "CoverageBasic" - numberOfCoveredFunctions = 1 - numberOfCoveredLines = 3 - - konanArtifacts { - program(binaryName, targets: [ target ]) { - srcDir 'coverage/basic/program' - baseDir "$testOutputCoverage/$binaryName" - entryPoint "coverage.basic.program.main" - extraOpts "-Xcoverage", "-Xcoverage-file=$profrawFile" - extraOpts project.globalTestArgs - } - } - } - - tasks.register("coverage_basic_library", CoverageTest) { - - binaryName = "CoverageBasicLibrary" - numberOfCoveredFunctions = 1 - numberOfCoveredLines = 1 - - konanArtifacts { - library("lib_to_cover", targets: [target.name]) { - srcFiles 'coverage/basic/library/library.kt' - } - program(binaryName, targets: [ target ]) { - srcFiles 'coverage/basic/library/main.kt' - libraries { - artifact konanArtifacts.lib_to_cover - } - baseDir "$testOutputCoverage/$binaryName" - entryPoint "coverage.basic.library.main" - extraOpts "-Xcoverage-file=$profrawFile", "-Xlibrary-to-cover=${konanArtifacts.lib_to_cover.getArtifactByTarget(target.name)}" - extraOpts project.globalTestArgs - } - } - } - - tasks.register("coverage_controlflow", CoverageTest) { - binaryName = "CoverageControlFlow" - numberOfCoveredFunctions = 1 - numberOfCoveredLines = 102 - - konanArtifacts { - program(binaryName, targets: [ target ]) { - srcDir 'coverage/basic/controlflow' - baseDir "$testOutputCoverage/$binaryName" - entryPoint "coverage.basic.controlflow.main" - extraOpts "-Xcoverage", "-Xcoverage-file=$profrawFile" - extraOpts project.globalTestArgs - } - } - } - - tasks.register("coverage_jumps", CoverageTest) { - binaryName = "CoverageJumps" - numberOfCoveredFunctions = 8 - numberOfCoveredLines = 74 - - konanArtifacts { - program(binaryName, targets: [ target ]) { - srcDir 'coverage/basic/jumps' - baseDir "$testOutputCoverage/$binaryName" - entryPoint "coverage.basic.jumps.main" - extraOpts "-Xcoverage", "-Xcoverage-file=$profrawFile" - extraOpts project.globalTestArgs - } - } - } - - tasks.register("coverage_smoke0", CoverageTest) { - binaryName = "CoverageSmoke0" - numberOfCoveredFunctions = 2 - numberOfCoveredLines = 5 - - konanArtifacts { - program(binaryName, targets: [ target ]) { - srcDir 'coverage/basic/smoke0' - baseDir "$testOutputCoverage/$binaryName" - entryPoint "coverage.basic.smoke0.main" - extraOpts "-Xcoverage", "-Xcoverage-file=$profrawFile" - extraOpts project.globalTestArgs - } - } - } - - tasks.register("coverage_smoke1", CoverageTest) { - binaryName = "CoverageSmoke1" - numberOfCoveredFunctions = 9 - numberOfCoveredLines = 33 - - konanArtifacts { - program(binaryName, targets: [ target ]) { - srcDir 'coverage/basic/smoke1' - baseDir "$testOutputCoverage/$binaryName" - entryPoint "coverage.basic.smoke1.main" - extraOpts "-Xcoverage", "-Xcoverage-file=$profrawFile" - extraOpts project.globalTestArgs - } - } - } -} - standaloneTest("local_ea_arraysfieldwrite") { disabled = (cacheTesting != null) // Cache is not compatible with -opt. useGoldenData = true diff --git a/kotlin-native/backend.native/tests/coverage/basic/controlflow/main.kt b/kotlin-native/backend.native/tests/coverage/basic/controlflow/main.kt deleted file mode 100644 index 41788ed83eb..00000000000 --- a/kotlin-native/backend.native/tests/coverage/basic/controlflow/main.kt +++ /dev/null @@ -1,126 +0,0 @@ -package coverage.basic.controlflow - -fun main() { - - // If Expression - - var a = 1 - var b = 2 - if (a < b) println("a < b") - - if (a > b) { - println("a > b") - } else if (a == b) { - println("a == b") - } else { - println("a < b") - } - - if (a < b) { - println("a < b") - } - else - { - println("a >= b") - } - - var max = if (a > b) a else b - - max = if (a > b) { - println("Choose a") - a - } else { - println("Choose b") - b - } - - if (a < b) - - println("a < b") - else - - println("a >= b") - - if (a > b) - - println("a > b") - - else - - println("a <= b") - - // When Expression - - when { - a < b -> { - println("a < b") - } - - a == b -> - - println("a == b") - a > b -> { - println("a > b") - } - - else -> { - - - - } - } - - var x = 1 - when (x) { - 1 -> print("x == 1") - 2 -> print("x == 2") - else -> { // Note the block - print("x is neither 1 nor 2") - } - } - x = 2 - when (x) { - 1 -> print("x == 1") - 2 -> print("x == 2") - else -> { // Note the block - print("x is neither 1 nor 2") - } - } - x = 3 - when (x) { - 1 -> print("x == 1") - 2 -> print("x == 2") - else -> { // Note the block - print("x is neither 1 nor 2") - } - } - - when (x) { - 0, 1 - -> - print("x == 0 or x == 1") - else -> - print("otherwise") - } - - when { - else -> println("=)") - } - - // While Loops - - do { - b++ - } while (b < 5) - - while (a < 10) { - a++ - if (a > 7) { - println(a) - } - } - - while (a > 0) - - a-- -} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/coverage/basic/jumps/main.kt b/kotlin-native/backend.native/tests/coverage/basic/jumps/main.kt deleted file mode 100644 index a0306316b00..00000000000 --- a/kotlin-native/backend.native/tests/coverage/basic/jumps/main.kt +++ /dev/null @@ -1,90 +0,0 @@ -package coverage.basic.jumps - -fun simpleReturn(n: Int) { - if (n == 0) return - println(n) -} - -fun returnFromIfBranch(n: Int) { - if (n > 0) { - if (n > 10) { - return - } - } else if (n < -10) { - return - } else if (n == 0) { - return - } - println(n) -} - -fun returnFromWhenBranch(n: Int) { - when { - n == 0 -> return - n == 1 -> return - n == 2 -> { - println(n) - return - } - else -> println(n) - } -} - -fun breakFromWhile() { - var a = 7 - while (true) { - if (a < 4) break - println(a) - a-- - } -} - -fun continueFromDoWhile() { - var a = 0 - do { - if (a % 3 == 0) { - a++ - continue - } - println(a) - a++ - } while (a < 10) -} - -fun singleReturn() { - return -} - -fun nestedReturn() { - while (true) { - while (true) { - while (true) { - if (1 < 2) { - return - } - println() - } - println() - } - } - println() -} - -fun main() { - simpleReturn(0) - simpleReturn(1) - - returnFromIfBranch(1) - returnFromIfBranch(11) - returnFromIfBranch(-11) - returnFromIfBranch(0) - - returnFromWhenBranch(0) - returnFromWhenBranch(1) - returnFromWhenBranch(2) - - breakFromWhile() - continueFromDoWhile() - singleReturn() - nestedReturn() -} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/coverage/basic/library/library.kt b/kotlin-native/backend.native/tests/coverage/basic/library/library.kt deleted file mode 100644 index 1e47ead0a75..00000000000 --- a/kotlin-native/backend.native/tests/coverage/basic/library/library.kt +++ /dev/null @@ -1,3 +0,0 @@ -package coverage_library - -fun foo() = "foo" \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/coverage/basic/library/main.kt b/kotlin-native/backend.native/tests/coverage/basic/library/main.kt deleted file mode 100644 index c62f3636f90..00000000000 --- a/kotlin-native/backend.native/tests/coverage/basic/library/main.kt +++ /dev/null @@ -1,5 +0,0 @@ -package coverage.basic.library - -fun main() { - println(coverage_library.foo()) -} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/coverage/basic/program/main.kt b/kotlin-native/backend.native/tests/coverage/basic/program/main.kt deleted file mode 100644 index f06f146bc65..00000000000 --- a/kotlin-native/backend.native/tests/coverage/basic/program/main.kt +++ /dev/null @@ -1,5 +0,0 @@ -package coverage.basic.program - -fun main() { - println("OK") -} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/coverage/basic/smoke0/smoke0.kt b/kotlin-native/backend.native/tests/coverage/basic/smoke0/smoke0.kt deleted file mode 100644 index b32041494c9..00000000000 --- a/kotlin-native/backend.native/tests/coverage/basic/smoke0/smoke0.kt +++ /dev/null @@ -1,8 +0,0 @@ -package coverage.basic.smoke0 - -data class User(val name: String) - -fun main() { - val user = User("Happy Kotlin/Native user") - println(user) -} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/coverage/basic/smoke1/smoke1.kt b/kotlin-native/backend.native/tests/coverage/basic/smoke1/smoke1.kt deleted file mode 100644 index c7302e5eaf4..00000000000 --- a/kotlin-native/backend.native/tests/coverage/basic/smoke1/smoke1.kt +++ /dev/null @@ -1,48 +0,0 @@ -package coverage.basic.smoke1 - -class A(val prop: Int) { - - constructor() : this(1) - - fun action1() { - println(prop) - } - - fun action2() { - - } -} - -class B private constructor(val prop: String) { - - init { - println("init block") - } - - constructor(prop1: String, prop2: String) : this("$prop1, $prop2") - - constructor() : this("dummy") { - if (1 > 2) { - println("uncovered") - } else { - println("foo") - } - println("bar") - } - - override fun toString() = prop -} - -fun main(args: Array) { - val a1 = A(2) - a1.action1() - a1.action2() - val a2 = A() - a2.action1() - a2.action1() - - val b1 = B("Hello", "world") - val b2 = B() - println(b1) - println(b2) -} diff --git a/kotlin-native/backend.native/tests/samples/build.gradle.kts b/kotlin-native/backend.native/tests/samples/build.gradle.kts index 661fb29e6e0..3b744ca6ff9 100644 --- a/kotlin-native/backend.native/tests/samples/build.gradle.kts +++ b/kotlin-native/backend.native/tests/samples/build.gradle.kts @@ -58,7 +58,6 @@ val buildSamplesWithPlatformLibs by tasks.creating { dependsOn(":objc:assemble") dependsOn(":opengl:assemble") dependsOn(":uikit:assemble") - dependsOn(":coverage:assemble") dependsOn(":watchos:assemble") } diff --git a/kotlin-native/backend.native/tests/samples/coverage/build.gradle.kts b/kotlin-native/backend.native/tests/samples/coverage/build.gradle.kts deleted file mode 100644 index 8ce4b4da2db..00000000000 --- a/kotlin-native/backend.native/tests/samples/coverage/build.gradle.kts +++ /dev/null @@ -1,49 +0,0 @@ -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget - -plugins { - kotlin("multiplatform") -} - -kotlin { - // Determine host preset. - val hostOs = System.getProperty("os.name") - val isMingwX64 = hostOs.startsWith("Windows") - - // Create a target for the host platform. - val hostTarget = when { - hostOs == "Mac OS X" -> macosX64("coverage") - hostOs == "Linux" -> linuxX64("coverage") - isMingwX64 -> mingwX64("coverage") - else -> throw GradleException("Host OS '$hostOs' is not supported in Kotlin/Native $project.") - } - - hostTarget.apply { - binaries { - executable(listOf(DEBUG)) - } - binaries.getTest("DEBUG").apply { - freeCompilerArgs += listOf("-Xlibrary-to-cover=${compilations["main"].output.classesDirs.singleFile.absolutePath}") - } - } - - sourceSets { - val coverageMain by getting - val coverageTest by getting - } -} - -tasks.create("createCoverageReport") { - dependsOn("coverageTest") - - description = "Create coverage report" - - doLast { - val testDebugBinary = kotlin.targets["coverage"].let { it as KotlinNativeTarget }.binaries.getTest("DEBUG").outputFile - exec { - commandLine("llvm-profdata", "merge", "$testDebugBinary.profraw", "-o", "$testDebugBinary.profdata") - } - exec { - commandLine("llvm-cov", "show", "$testDebugBinary", "-instr-profile", "$testDebugBinary.profdata") - } - } -} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/samples/coverage/gradle.properties b/kotlin-native/backend.native/tests/samples/coverage/gradle.properties deleted file mode 100644 index 29e08e8ca88..00000000000 --- a/kotlin-native/backend.native/tests/samples/coverage/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -kotlin.code.style=official \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/samples/coverage/src/coverageMain/kotlin/bar.kt b/kotlin-native/backend.native/tests/samples/coverage/src/coverageMain/kotlin/bar.kt deleted file mode 100644 index c15d0ce71bc..00000000000 --- a/kotlin-native/backend.native/tests/samples/coverage/src/coverageMain/kotlin/bar.kt +++ /dev/null @@ -1,17 +0,0 @@ -fun baz(args: Array) { - if (args.size > 4) { - println("Too many") - } else { - println("Fine") - } -} - -class A { - init { - println("A::init") - } - - fun f() { - println("A::f") - } -} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/samples/coverage/src/coverageMain/kotlin/main.kt b/kotlin-native/backend.native/tests/samples/coverage/src/coverageMain/kotlin/main.kt deleted file mode 100644 index 546840df5bc..00000000000 --- a/kotlin-native/backend.native/tests/samples/coverage/src/coverageMain/kotlin/main.kt +++ /dev/null @@ -1,3 +0,0 @@ -fun main() { - baz(arrayOf("abc")) -} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/samples/coverage/src/coverageTest/kotlin/Tests.kt b/kotlin-native/backend.native/tests/samples/coverage/src/coverageTest/kotlin/Tests.kt deleted file mode 100644 index fd7d78c0bdb..00000000000 --- a/kotlin-native/backend.native/tests/samples/coverage/src/coverageTest/kotlin/Tests.kt +++ /dev/null @@ -1,15 +0,0 @@ -import kotlin.test.Test -import kotlin.test.assertTrue - -class CoverageTests { - @Test - fun testHello() { - main() - } - - @Test - fun testA() { - val a = A() - a.f() - } -} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/samples/settings.gradle.kts b/kotlin-native/backend.native/tests/samples/settings.gradle.kts index e88a0ee28d7..97ff992e72f 100644 --- a/kotlin-native/backend.native/tests/samples/settings.gradle.kts +++ b/kotlin-native/backend.native/tests/samples/settings.gradle.kts @@ -24,7 +24,6 @@ if (isMacos || isLinux || isWindows) { include(":libcurl") include(":videoplayer") include(":workers") - include(":coverage") } if (isMacos || isLinux) { diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CoverageTest.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CoverageTest.kt deleted file mode 100644 index a00f2343e13..00000000000 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CoverageTest.kt +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2010-2019 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 - -import groovy.lang.Closure -import org.gradle.api.DefaultTask -import org.gradle.api.Task -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.TaskAction -import org.gradle.api.tasks.Internal -import org.jetbrains.kotlin.konan.target.AppleConfigurables - -/** - * Test task for -Xcoverage and -Xlibraries-to-cover flags. Requires a binary to be built by the Konan plugin - * with - * konanArtifacts { - * program([binaryName], targets: [testTarget]) { - * ... - * extraOpts "-Xcoverage"/"-Xlibrary-to-cover=...", "-Xcoverage-file=$[profrawFile]" - * } - * } - * and a dependency set according to a pattern "run${binaryName}". - * - * @property numberOfCoveredFunctions Expected number of covered functions - * @property numberOfCoveredLines Expected number of covered lines in all functions - * @property binaryName Name of the produced binary - */ -open class CoverageTest : DefaultTask() { - - private val target = project.testTarget - private val platform = project.platformManager.platform(target) - private val configurables = platform.configurables - - // Use the same LLVM version as compiler when producing machine code: - private val llvmToolsDir = if (configurables is AppleConfigurables) { - "${configurables.absoluteTargetToolchain}/usr/bin" - } else { - "${configurables.absoluteLlvmHome}/bin" - } - - @Input - lateinit var binaryName: String - - // TODO: Consider better metric. - @Input - var numberOfCoveredFunctions: Int? = null - @Input - var numberOfCoveredLines: Int? = null - - @get:Internal - val profrawFile: String by lazy { - "${project.buildDir.absolutePath}/$binaryName.profraw" - } - - private val profdataFile: String by lazy { - "${project.buildDir.absolutePath}/$binaryName.profdata" - } - - private val outputDir: String by lazy { - project.file(project.property("testOutputCoverage")!!).absolutePath - } - - override fun configure(closure: Closure): Task { - super.configure(closure) - dependsOnDist() - val compileBinaryTask = project.tasks.named("compileKonan$binaryName").configure { - konanOldPluginTaskDependenciesWalker { - dependsOnDist() - } - } - dependsOn(compileBinaryTask) - return this - } - - @TaskAction - fun run() { - val suffix = target.family.exeSuffix - val pathToBinary = "$outputDir/$binaryName/$target/$binaryName.$suffix" - runProcess({ project.executor.execute(it) }, pathToBinary) - .ensureSuccessful(pathToBinary) - exec("llvm-profdata", "merge", profrawFile, "-o", profdataFile) - val llvmCovResult = exec("llvm-cov", "export", pathToBinary, "-instr-profile", profdataFile) - val jsonReport = llvmCovResult.stdOut - val llvmCovReport = parseLlvmCovReport(jsonReport) - try { - CoverageValidator(numberOfCoveredFunctions, numberOfCoveredLines).validateReport(llvmCovReport) - } catch (e: TestFailedException) { - // Show report in message to make debug easier. - val show = exec("llvm-cov", "show", pathToBinary, "-instr-profile", profdataFile).stdOut - // llvm-cov output contains '|' so another symbol is used as margin prefix. - throw TestFailedException(""" - >${e.message} - >$show - """.trimMargin(">")) - } - } - - private fun exec(llvmTool: String, vararg args: String): ProcessOutput { - val executable = "$llvmToolsDir/$llvmTool" - val result = runProcess(localExecutor(project), executable, args.toList()) - result.ensureSuccessful(llvmTool) - return result - } - - private fun ProcessOutput.ensureSuccessful(executable: String) { - if (exitCode != 0) { - println(""" - $executable failed. - exitCode: $exitCode - stdout: - $stdOut - stderr: - $stdErr - """.trimIndent()) - error("$executable failed") - } - } -} - -private class CoverageValidator( - val numberOfCoveredFunctions: Int?, - val numberOfCoveredLines: Int? -) { - fun validateReport(report: LlvmCovReport) { - val data = report.data - if (data.isEmpty()) { - failTest("Report data should not be empty!") - } - compareNumbers(numberOfCoveredFunctions, data[0].totals.functions.covered, "Number of covered functions") - compareNumbers(numberOfCoveredLines, data[0].totals.lines.covered, "Number of covered lines") - } - - private fun compareNumbers(expected: Int?, actual: Int, description: String) { - if (expected != null && actual != expected) { - failTest("$description differs from expected! Expected: $expected. Got: $actual") - } - } - - private fun failTest(message: String) { - throw TestFailedException(message) - } -} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/Utils.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/Utils.kt index 4e600873166..0f533d109e8 100644 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/Utils.kt +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/Utils.kt @@ -115,9 +115,6 @@ val Project.globalBuildArgs: List val Project.globalTestArgs: List get() = project.groovyPropertyArrayToList("globalTestArgs") -val Project.testTargetSupportsCodeCoverage: Boolean - get() = this.testTarget.supportsCodeCoverage() - fun projectOrFiles(proj: Project, notation: String): Any? { val propertyMapper = proj.findProperty("notationMapping") ?: return proj.project(notation) val mapping = (propertyMapper as? Map<*, *>)?.get(notation) as? String ?: return proj.project(notation) diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanCompileTask.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanCompileTask.kt index db6627b96ca..c958363b6c6 100644 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanCompileTask.kt +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanCompileTask.kt @@ -130,10 +130,8 @@ abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec { return result } - // Don't include coverage flags into the first stage because they are not supported when compiling a klib. private fun firstStageExtraOpts() = extraOpts - .excludeFlags("-Xcoverage") - .excludeArguments("-Xcoverage-file", "-Xlibrary-to-cover", "-Xpartial-linkage", "-Xpartial-linkage-loglevel") + .excludeArguments("-Xpartial-linkage", "-Xpartial-linkage-loglevel") // Don't include the -Xemit-lazy-objc-header and -language-version flags into // the second stage because this stage have no sources. diff --git a/kotlin-native/libllvmext/src/main/cpp/CAPIExtensions.cpp b/kotlin-native/libllvmext/src/main/cpp/CAPIExtensions.cpp index f524a5473f6..919d0e35963 100644 --- a/kotlin-native/libllvmext/src/main/cpp/CAPIExtensions.cpp +++ b/kotlin-native/libllvmext/src/main/cpp/CAPIExtensions.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -71,3 +72,8 @@ void LLVMPrintAllTimersToStdOut() { void LLVMClearAllTimers() { llvm::TimerGroup::clearAll(); } + +void LLVMKotlinAddTargetLibraryInfoWrapperPass(LLVMPassManagerRef passManagerRef, const char* targetTriple) { + legacy::PassManagerBase *passManager = unwrap(passManagerRef); + passManager->add(new TargetLibraryInfoWrapperPass(Triple(targetTriple))); +} diff --git a/kotlin-native/libllvmext/src/main/cpp/CoverageMappingC.cpp b/kotlin-native/libllvmext/src/main/cpp/CoverageMappingC.cpp deleted file mode 100644 index beb68e8c134..00000000000 --- a/kotlin-native/libllvmext/src/main/cpp/CoverageMappingC.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2010-2019 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. - */ - -#include "CoverageMappingC.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -using namespace llvm; -using namespace llvm::coverage; - -namespace llvm { - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetLibraryInfoImpl, LLVMTargetLibraryInfoRef) -} - -struct LLVMFunctionCoverage { - explicit LLVMFunctionCoverage(std::string coverageData) : coverageData(std::move(coverageData)) {} - - std::string coverageData; -}; - -static coverage::CounterMappingRegion::RegionKind determineRegionKind(const struct LLVMCoverageRegion& region) { - switch (region.kind) { - case LLVMCoverageRegionKind::CODE: - return coverage::CounterMappingRegion::RegionKind::CodeRegion; - case LLVMCoverageRegionKind::GAP: - return coverage::CounterMappingRegion::RegionKind::GapRegion; - case LLVMCoverageRegionKind::EXPANSION: - return coverage::CounterMappingRegion::RegionKind::ExpansionRegion; - } -} - -static coverage::CounterMappingRegion createCounterMappingRegion(struct LLVMCoverageRegion& region) { - auto regionKind = determineRegionKind(region); - int expandedFileId = 0; - if (regionKind == coverage::CounterMappingRegion::RegionKind::ExpansionRegion) { - expandedFileId = region.expandedFileId; - } - const Counter &counter = coverage::Counter::getCounter(region.counterId); - return coverage::CounterMappingRegion(counter, region.fileId, expandedFileId, region.lineStart, - region.columnStart, region.lineEnd, region.columnEnd, regionKind); -} - -LLVMFunctionCoverage* LLVMWriteCoverageRegionMapping(unsigned int *fileIdMapping, size_t fileIdMappingSize, - struct LLVMCoverageRegion **mappingRegions, size_t mappingRegionsSize) { - std::vector counterMappingRegions; - for (size_t i = 0; i < mappingRegionsSize; ++i) { - struct LLVMCoverageRegion region = *mappingRegions[i]; - counterMappingRegions.emplace_back(createCounterMappingRegion(region)); - } - CoverageMappingWriter writer(ArrayRef(fileIdMapping, fileIdMappingSize), None, counterMappingRegions); - std::string CoverageMapping; - raw_string_ostream OS(CoverageMapping); - writer.write(OS); - OS.flush(); - // Should be disposed with `LLVMFunctionCoverageDispose`. - return new LLVMFunctionCoverage(CoverageMapping); -} - -void LLVMFunctionCoverageDispose(struct LLVMFunctionCoverage* functionCoverage) { - delete functionCoverage; -} - -static StructType *getFunctionRecordTy(LLVMContext &Ctx) { -#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType, - Type *FunctionRecordTypes[] = { -#include "llvm/ProfileData/InstrProfData.inc" - }; - StructType *FunctionRecordTy = StructType::get(Ctx, makeArrayRef(FunctionRecordTypes), true); - return FunctionRecordTy; -} - -static llvm::Constant *addFunctionMappingRecord(llvm::LLVMContext &Ctx, StringRef NameValue, uint64_t FuncHash, - const std::string &CoverageMapping) { - llvm::StructType *FunctionRecordTy = getFunctionRecordTy(Ctx); - -#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init, - llvm::Constant *FunctionRecordVals[] = { -#include "llvm/ProfileData/InstrProfData.inc" - }; - return llvm::ConstantStruct::get(FunctionRecordTy, makeArrayRef(FunctionRecordVals)); -} - -// See https://github.com/llvm/llvm-project/blob/fa8fa044ec46b94e64971efa8852df0d58114062/clang/lib/CodeGen/CoverageMappingGen.cpp#L1284. -LLVMValueRef LLVMAddFunctionMappingRecord(LLVMContextRef context, const char *name, uint64_t hash, - struct LLVMFunctionCoverage *coverageMapping) { - return llvm::wrap(addFunctionMappingRecord(*llvm::unwrap(context), name, hash, coverageMapping->coverageData)); -} - -// See https://github.com/llvm/llvm-project/blob/fa8fa044ec46b94e64971efa8852df0d58114062/clang/lib/CodeGen/CoverageMappingGen.cpp#L1335. -// Please note that llvm/ProfileData/InstrProfData.inc refers to variable names of the function that includes it. So be careful with renaming. -static llvm::GlobalVariable* emitCoverageGlobal( - llvm::LLVMContext &Ctx, - llvm::Module &module, - std::vector &FunctionRecords, - const llvm::SmallVector &FilenameRefs, - const std::string &RawCoverageMappings) { - - auto *Int32Ty = llvm::Type::getInt32Ty(Ctx); - - std::string FilenamesAndCoverageMappings; - llvm::raw_string_ostream outputStream(FilenamesAndCoverageMappings); - CoverageFilenamesSectionWriter(FilenameRefs).write(outputStream); - outputStream << RawCoverageMappings; - size_t CoverageMappingSize = RawCoverageMappings.size(); - size_t FilenamesSize = outputStream.str().size() - CoverageMappingSize; - - // See https://llvm.org/docs/CoverageMappingFormat.html#llvm-ir-representation - // - // > Coverage mapping data which is an array of bytes. Zero paddings are added at the end to force 8 byte alignment. - // - if (size_t rem = outputStream.str().size() % 8) { - CoverageMappingSize += 8 - rem; - for (size_t i = 0; i < 8 - rem; ++i) { - outputStream << '\0'; - } - } - - StructType *functionRecordTy = getFunctionRecordTy(Ctx); - // Create the deferred function records array - auto functionRecordsTy = llvm::ArrayType::get(functionRecordTy, FunctionRecords.size()); - auto functionRecordsVal = llvm::ConstantArray::get(functionRecordsTy, FunctionRecords); - const unsigned NRecords = 0; - - llvm::Type *CovDataHeaderTypes[] = { -#define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType, - -#include "llvm/ProfileData/InstrProfData.inc" - }; - auto CovDataHeaderTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataHeaderTypes)); - llvm::Constant *CovDataHeaderVals[] = { -#define COVMAP_HEADER(Type, LLVMType, Name, Init) Init, - -#include "llvm/ProfileData/InstrProfData.inc" - }; - auto covDataHeaderVal = llvm::ConstantStruct::get(CovDataHeaderTy, makeArrayRef(CovDataHeaderVals)); - - auto *filenamesAndMappingsVal = llvm::ConstantDataArray::getString(Ctx, outputStream.str(), false); - // Create the coverage data record - llvm::Type *covDataTypes[] = {CovDataHeaderTy, functionRecordsTy, filenamesAndMappingsVal->getType()}; - auto covDataTy = llvm::StructType::get(Ctx, makeArrayRef(covDataTypes)); - - llvm::Constant *TUDataVals[] = {covDataHeaderVal, functionRecordsVal, filenamesAndMappingsVal}; - auto covDataVal = llvm::ConstantStruct::get(covDataTy, makeArrayRef(TUDataVals)); - // Will be deleted when module is disposed. - return new llvm::GlobalVariable(module, covDataTy, true, llvm::GlobalValue::InternalLinkage, - covDataVal, llvm::getCoverageMappingVarName()); -} - -static std::string createRawCoverageMapping(struct LLVMFunctionCoverage **functionCoverages, size_t functionCoveragesSize) { - std::vector coverageMappings; - for (size_t i = 0; i < functionCoveragesSize; ++i) { - coverageMappings.emplace_back(functionCoverages[i]->coverageData); - } - return llvm::join(coverageMappings.begin(), coverageMappings.end(), ""); -} - -LLVMValueRef LLVMCoverageEmit(LLVMModuleRef moduleRef, - LLVMValueRef *records, size_t recordsSize, - const char **filenames, int *filenamesIndices, size_t filenamesSize, - struct LLVMFunctionCoverage **functionCoverages, size_t functionCoveragesSize) { - LLVMContext &ctx = *unwrap(LLVMGetModuleContext(moduleRef)); - Module &module = *unwrap(moduleRef); - - std::vector functionRecords; - for (size_t i = 0; i < recordsSize; ++i) { - functionRecords.push_back(dyn_cast(unwrap(records[i]))); - } - llvm::SmallVector filenameRefs; - filenameRefs.resize(filenamesSize); - for (size_t i = 0; i < filenamesSize; ++i) { - if (sys::path::is_absolute(filenames[i])) { - filenameRefs[filenamesIndices[i]] = filenames[i]; - } else { - SmallString<256> path(filenames[i]); - sys::fs::make_absolute(path); - sys::path::remove_dots(path, true); - filenameRefs[filenamesIndices[i]] = path; - } - } - const std::string &rawCoverageMappings = createRawCoverageMapping(functionCoverages, functionCoveragesSize); - GlobalVariable *coverageGlobal = emitCoverageGlobal(ctx, module, functionRecords, filenameRefs, rawCoverageMappings); - - const std::string §ion = getInstrProfSectionName(IPSK_covmap, Triple(module.getTargetTriple()).getObjectFormat()); - coverageGlobal->setSection(section); - coverageGlobal->setAlignment(llvm::Align(8)); - return wrap(coverageGlobal); -} - -LLVMValueRef LLVMInstrProfIncrement(LLVMModuleRef moduleRef) { - Module &module = *unwrap(moduleRef); - return wrap(Intrinsic::getDeclaration(&module, Intrinsic::instrprof_increment, None)); -} - -LLVMValueRef LLVMCreatePGOFunctionNameVar(LLVMValueRef llvmFunction, const char *pgoFunctionName) { - auto *fnPtr = cast(unwrap(llvmFunction)); - return wrap(createPGOFuncNameVar(*fnPtr, pgoFunctionName)); -} - -void LLVMAddInstrProfPass(LLVMPassManagerRef passManagerRef, const char* outputFileName) { - legacy::PassManagerBase *passManager = unwrap(passManagerRef); - InstrProfOptions options; - options.InstrProfileOutput = outputFileName; - passManager->add(createInstrProfilingLegacyPass(options)); -} - -void LLVMKotlinAddTargetLibraryInfoWrapperPass(LLVMPassManagerRef passManagerRef, const char* targetTriple) { - legacy::PassManagerBase *passManager = unwrap(passManagerRef); - passManager->add(new TargetLibraryInfoWrapperPass(Triple(targetTriple))); -} diff --git a/kotlin-native/libllvmext/src/main/include/CoverageMappingC.h b/kotlin-native/libllvmext/src/main/include/CoverageMappingC.h deleted file mode 100644 index dfc21b780f7..00000000000 --- a/kotlin-native/libllvmext/src/main/include/CoverageMappingC.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2010-2019 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. - */ - -#ifndef __COVERAGE_MAPPING_C_H__ -# define __COVERAGE_MAPPING_C_H__ - -#include -#include - - -# ifdef __cplusplus -extern "C" { -# endif - -/** - * See org.jetbrains.kotlin.backend.konan.llvm.coverage.RegionKind. - */ -enum LLVMCoverageRegionKind { - CODE, - GAP, - EXPANSION -}; - -/** - * See org.jetbrains.kotlin.backend.konan.llvm.coverage.Region. - */ -struct LLVMCoverageRegion { - int fileId; - int lineStart; - int columnStart; - int lineEnd; - int columnEnd; - int counterId; - int expandedFileId; - enum LLVMCoverageRegionKind kind; -}; - -struct LLVMFunctionCoverage; - -/** - * Add record in the following format: https://llvm.org/docs/CoverageMappingFormat.html#function-record. - */ -LLVMValueRef -LLVMAddFunctionMappingRecord(LLVMContextRef context, const char *name, uint64_t hash, struct LLVMFunctionCoverage* coverageMapping); - -/** - * Wraps creation of coverage::CoverageMappingWriter and call to coverage::CoverageMappingWriter::write. - */ -struct LLVMFunctionCoverage* LLVMWriteCoverageRegionMapping(unsigned int *fileIdMapping, size_t fileIdMappingSize, - struct LLVMCoverageRegion **mappingRegions, size_t mappingRegionsSize); - -void LLVMFunctionCoverageDispose(struct LLVMFunctionCoverage* functionCoverage); - -/** - * Create __llvm_coverage_mapping global. - */ -LLVMValueRef LLVMCoverageEmit(LLVMModuleRef moduleRef, LLVMValueRef *records, size_t recordsSize, - const char **filenames, int *filenamesIndices, size_t filenamesSize, - struct LLVMFunctionCoverage** functionCoverages, size_t functionCoveragesSize); - -/** - * Wrapper for `llvm.instrprof.increment` declaration. - */ -LLVMValueRef LLVMInstrProfIncrement(LLVMModuleRef moduleRef); - -/** - * Wrapper for llvm::createPGOFuncNameVar. - */ -LLVMValueRef LLVMCreatePGOFunctionNameVar(LLVMValueRef llvmFunction, const char *pgoFunctionName); - -void LLVMAddInstrProfPass(LLVMPassManagerRef passManagerRef, const char* outputFileName); - -void LLVMKotlinAddTargetLibraryInfoWrapperPass(LLVMPassManagerRef passManagerRef, const char* targetTriple); - -void LLVMAddObjCARCContractPass(LLVMPassManagerRef passManagerRef); - -void LLVMKotlinInitializeTargets(); - -void LLVMSetNoTailCall(LLVMValueRef Call); - -# ifdef __cplusplus -} -# endif -#endif diff --git a/kotlin-native/runtime/build.gradle.kts b/kotlin-native/runtime/build.gradle.kts index a4677dcb571..39458661dec 100644 --- a/kotlin-native/runtime/build.gradle.kts +++ b/kotlin-native/runtime/build.gradle.kts @@ -229,13 +229,6 @@ bitcode { onlyIf { target.supportsLibBacktrace() } } - module("profileRuntime") { - srcRoot.set(layout.projectDirectory.dir("src/profile_runtime")) - sourceSets { - main {} - } - } - module("objc") { headersDirs.from(files("src/main/cpp")) sourceSets { diff --git a/kotlin-native/runtime/src/profile_runtime/cpp/ProfileRuntime.cpp b/kotlin-native/runtime/src/profile_runtime/cpp/ProfileRuntime.cpp deleted file mode 100644 index 46e9c43b45b..00000000000 --- a/kotlin-native/runtime/src/profile_runtime/cpp/ProfileRuntime.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Define symbols that are required for code coverage but missing in compiler-RT for MinGW.
 -// See https://reviews.llvm.org/D58106/ for details. -#ifdef KONAN_WINDOWS - -#include - -extern "C" { - -__attribute__((used)) -int lprofGetHostName(char *hostName, int length) { - const int maxHostNameLength = 128; - WCHAR buffer[maxHostNameLength]; - DWORD bufferSize = sizeof(buffer); - COMPUTER_NAME_FORMAT nameType = ComputerNameDnsFullyQualified; - if (!GetComputerNameExW(nameType, buffer, &bufferSize)) { - return -1; - } - int bytesWritten = WideCharToMultiByte(CP_UTF8, 0, buffer, -1, hostName, length, nullptr, nullptr); - if (bytesWritten == 0) { - return -1; - } else { - return 0; - } -} - -} - -#endif diff --git a/native/utils/src/org/jetbrains/kotlin/konan/target/KonanTargetExtenstions.kt b/native/utils/src/org/jetbrains/kotlin/konan/target/KonanTargetExtenstions.kt index ef3497441b9..8edd2e9de58 100644 --- a/native/utils/src/org/jetbrains/kotlin/konan/target/KonanTargetExtenstions.kt +++ b/native/utils/src/org/jetbrains/kotlin/konan/target/KonanTargetExtenstions.kt @@ -32,16 +32,6 @@ fun KonanTarget.pointerBits() = when (architecture) { Architecture.WASM32 -> 32 } - -fun KonanTarget.supportsCodeCoverage(): Boolean = - // TODO: Disabled for now, because we don't support - // coverage format from LLVM 11. - false -// this == KonanTarget.MINGW_X64 || -// this == KonanTarget.LINUX_X64 || -// this == KonanTarget.MACOS_X64 || -// this == KonanTarget.IOS_X64 - fun KonanTarget.supportsMimallocAllocator(): Boolean = when(this) { is KonanTarget.LINUX_X64 -> true diff --git a/native/utils/src/org/jetbrains/kotlin/konan/target/Linker.kt b/native/utils/src/org/jetbrains/kotlin/konan/target/Linker.kt index 364e34a6b4d..4758b92ee8a 100644 --- a/native/utils/src/org/jetbrains/kotlin/konan/target/Linker.kt +++ b/native/utils/src/org/jetbrains/kotlin/konan/target/Linker.kt @@ -64,7 +64,6 @@ private fun staticGnuArCommands(ar: String, executable: ExecutableFile, abstract class LinkerFlags(val configurables: Configurables) { protected val llvmBin = "${configurables.absoluteLlvmHome}/bin" - protected val llvmLib = "${configurables.absoluteLlvmHome}/lib" open val useCompilerDriverAsLinker: Boolean get() = false // TODO: refactor. @@ -76,7 +75,7 @@ abstract class LinkerFlags(val configurables: Configurables) { libraries: List, linkerArgs: List, optimize: Boolean, debug: Boolean, kind: LinkerOutputKind, outputDsymBundle: String, - needsProfileLibrary: Boolean, mimallocEnabled: Boolean, + needsProfileLibrary: Boolean = false, mimallocEnabled: Boolean, sanitizer: SanitizerKind? = null): List /** @@ -98,11 +97,6 @@ abstract class LinkerFlags(val configurables: Configurables) { System.err.println("Can't provide $libraryName.") return null } - - // Code coverage requires this library. - protected val profileLibrary: String? by lazy { - provideCompilerRtLibrary("profile") - } } class AndroidLinker(targetProperties: AndroidConfigurables) @@ -269,7 +263,6 @@ class MacOSBasedLinker(targetProperties: AppleConfigurables) +linkerKonanFlags if (mimallocEnabled) +mimallocLinkerDependencies if (compilerRtLibrary != null) +compilerRtLibrary!! - if (needsProfileLibrary) +profileLibrary!! +libraries +linkerArgs +rpath(dynamic, sanitizer) @@ -420,7 +413,6 @@ class GccBasedLinker(targetProperties: GccConfigurables) if (mimallocEnabled) +mimallocLinkerDependencies // See explanation about `-u__llvm_profile_runtime` here: // https://github.com/llvm/llvm-project/blob/21e270a479a24738d641e641115bce6af6ed360a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp#L930 - if (needsProfileLibrary) +listOf("-u__llvm_profile_runtime", profileLibrary!!) +linkerKonanFlags +linkerGccFlags +if (dynamic) "$libGcc/crtendS.o" else "$libGcc/crtend.o" @@ -494,7 +486,7 @@ class MingwLinker(targetProperties: MingwConfigurables) // --gc-sections flag may affect profiling. // See https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#drawbacks-and-limitations. // TODO: switching to lld may help. - if (optimize && !needsProfileLibrary) { + if (optimize) { // TODO: Can be removed after LLD update. // See KT-48085. if (!dynamic) { @@ -504,7 +496,6 @@ class MingwLinker(targetProperties: MingwConfigurables) if (!debug) +linkerNoDebugFlags if (dynamic) +linkerDynamicFlags +libraries - if (needsProfileLibrary) +profileLibrary!! +linkerArgs +linkerKonanFlags.filterNot { it in skipDefaultArguments } if (mimallocEnabled) +mimallocLinkerDependencies