diff options
Diffstat (limited to 'compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp')
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp | 231 |
1 files changed, 143 insertions, 88 deletions
diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp index 60789b07e54..0471baa1f9c 100644 --- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp @@ -1,10 +1,12 @@ #include "LLVMWrapper.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Module.h" #include "llvm/ProfileData/Coverage/CoverageMapping.h" #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h" #include "llvm/ProfileData/InstrProf.h" -#include "llvm/ADT/ArrayRef.h" - -#include <iostream> using namespace llvm; @@ -35,45 +37,68 @@ static coverage::Counter fromRust(LLVMRustCounter Counter) { report_fatal_error("Bad LLVMRustCounterKind!"); } -// FFI equivalent of enum `llvm::coverage::CounterMappingRegion::RegionKind` -// https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L213-L234 -enum class LLVMRustCounterMappingRegionKind { - CodeRegion = 0, - ExpansionRegion = 1, - SkippedRegion = 2, - GapRegion = 3, - BranchRegion = 4, +struct LLVMRustMCDCDecisionParameters { + uint32_t BitmapIdx; + uint16_t NumConditions; }; -static coverage::CounterMappingRegion::RegionKind -fromRust(LLVMRustCounterMappingRegionKind Kind) { - switch (Kind) { - case LLVMRustCounterMappingRegionKind::CodeRegion: - return coverage::CounterMappingRegion::CodeRegion; - case LLVMRustCounterMappingRegionKind::ExpansionRegion: - return coverage::CounterMappingRegion::ExpansionRegion; - case LLVMRustCounterMappingRegionKind::SkippedRegion: - return coverage::CounterMappingRegion::SkippedRegion; - case LLVMRustCounterMappingRegionKind::GapRegion: - return coverage::CounterMappingRegion::GapRegion; - case LLVMRustCounterMappingRegionKind::BranchRegion: - return coverage::CounterMappingRegion::BranchRegion; - } - report_fatal_error("Bad LLVMRustCounterMappingRegionKind!"); +struct LLVMRustMCDCBranchParameters { + int16_t ConditionID; + int16_t ConditionIDs[2]; +}; + +#if LLVM_VERSION_GE(19, 0) +static coverage::mcdc::BranchParameters +fromRust(LLVMRustMCDCBranchParameters Params) { + return coverage::mcdc::BranchParameters( + Params.ConditionID, {Params.ConditionIDs[0], Params.ConditionIDs[1]}); } -// FFI equivalent of struct `llvm::coverage::CounterMappingRegion` -// https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L211-L304 -struct LLVMRustCounterMappingRegion { - LLVMRustCounter Count; - LLVMRustCounter FalseCount; +static coverage::mcdc::DecisionParameters +fromRust(LLVMRustMCDCDecisionParameters Params) { + return coverage::mcdc::DecisionParameters(Params.BitmapIdx, + Params.NumConditions); +} +#endif + +// Must match the layout of +// `rustc_codegen_llvm::coverageinfo::ffi::CoverageSpan`. +struct LLVMRustCoverageSpan { uint32_t FileID; - uint32_t ExpandedFileID; uint32_t LineStart; uint32_t ColumnStart; uint32_t LineEnd; uint32_t ColumnEnd; - LLVMRustCounterMappingRegionKind Kind; +}; + +// Must match the layout of `rustc_codegen_llvm::coverageinfo::ffi::CodeRegion`. +struct LLVMRustCoverageCodeRegion { + LLVMRustCoverageSpan Span; + LLVMRustCounter Count; +}; + +// Must match the layout of +// `rustc_codegen_llvm::coverageinfo::ffi::BranchRegion`. +struct LLVMRustCoverageBranchRegion { + LLVMRustCoverageSpan Span; + LLVMRustCounter TrueCount; + LLVMRustCounter FalseCount; +}; + +// Must match the layout of +// `rustc_codegen_llvm::coverageinfo::ffi::MCDCBranchRegion`. +struct LLVMRustCoverageMCDCBranchRegion { + LLVMRustCoverageSpan Span; + LLVMRustCounter TrueCount; + LLVMRustCounter FalseCount; + LLVMRustMCDCBranchParameters MCDCBranchParams; +}; + +// Must match the layout of +// `rustc_codegen_llvm::coverageinfo::ffi::MCDCDecisionRegion`. +struct LLVMRustCoverageMCDCDecisionRegion { + LLVMRustCoverageSpan Span; + LLVMRustMCDCDecisionParameters MCDCDecisionParams; }; // FFI equivalent of enum `llvm::coverage::CounterExpression::ExprKind` @@ -102,51 +127,38 @@ fromRust(LLVMRustCounterExprKind Kind) { report_fatal_error("Bad LLVMRustCounterExprKind!"); } -extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer( - const char *const Filenames[], - size_t FilenamesLen, - const size_t *const Lengths, - size_t LengthsLen, +extern "C" void LLVMRustCoverageWriteFilenamesToBuffer( + const char *const Filenames[], size_t FilenamesLen, // String start pointers + const size_t *const Lengths, size_t LengthsLen, // Corresponding lengths RustStringRef BufferOut) { if (FilenamesLen != LengthsLen) { report_fatal_error( - "Mismatched lengths in LLVMRustCoverageWriteFilenamesSectionToBuffer"); + "Mismatched lengths in LLVMRustCoverageWriteFilenamesToBuffer"); } - SmallVector<std::string,32> FilenameRefs; + SmallVector<std::string, 32> FilenameRefs; FilenameRefs.reserve(FilenamesLen); for (size_t i = 0; i < FilenamesLen; i++) { FilenameRefs.emplace_back(Filenames[i], Lengths[i]); } - auto FilenamesWriter = - coverage::CoverageFilenamesSectionWriter(ArrayRef<std::string>(FilenameRefs)); + auto FilenamesWriter = coverage::CoverageFilenamesSectionWriter( + ArrayRef<std::string>(FilenameRefs)); auto OS = RawRustStringOstream(BufferOut); FilenamesWriter.write(OS); } -extern "C" void LLVMRustCoverageWriteMappingToBuffer( - const unsigned *VirtualFileMappingIDs, - unsigned NumVirtualFileMappingIDs, - const LLVMRustCounterExpression *RustExpressions, - unsigned NumExpressions, - const LLVMRustCounterMappingRegion *RustMappingRegions, - unsigned NumMappingRegions, - RustStringRef BufferOut) { +extern "C" void LLVMRustCoverageWriteFunctionMappingsToBuffer( + const unsigned *VirtualFileMappingIDs, size_t NumVirtualFileMappingIDs, + const LLVMRustCounterExpression *RustExpressions, size_t NumExpressions, + const LLVMRustCoverageCodeRegion *CodeRegions, size_t NumCodeRegions, + const LLVMRustCoverageBranchRegion *BranchRegions, size_t NumBranchRegions, + const LLVMRustCoverageMCDCBranchRegion *MCDCBranchRegions, + size_t NumMCDCBranchRegions, + const LLVMRustCoverageMCDCDecisionRegion *MCDCDecisionRegions, + size_t NumMCDCDecisionRegions, RustStringRef BufferOut) { // Convert from FFI representation to LLVM representation. - SmallVector<coverage::CounterMappingRegion, 0> MappingRegions; - MappingRegions.reserve(NumMappingRegions); - for (const auto &Region : ArrayRef<LLVMRustCounterMappingRegion>( - RustMappingRegions, NumMappingRegions)) { - MappingRegions.emplace_back( - fromRust(Region.Count), fromRust(Region.FalseCount), -#if LLVM_VERSION_GE(18, 0) && LLVM_VERSION_LT(19, 0) - coverage::CounterMappingRegion::MCDCParameters{}, -#endif - Region.FileID, Region.ExpandedFileID, - Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd, - fromRust(Region.Kind)); - } + // Expressions: std::vector<coverage::CounterExpression> Expressions; Expressions.reserve(NumExpressions); for (const auto &Expression : @@ -156,54 +168,97 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer( fromRust(Expression.RHS)); } + std::vector<coverage::CounterMappingRegion> MappingRegions; + MappingRegions.reserve(NumCodeRegions + NumBranchRegions + + NumMCDCBranchRegions + NumMCDCDecisionRegions); + + // Code regions: + for (const auto &Region : ArrayRef(CodeRegions, NumCodeRegions)) { + MappingRegions.push_back(coverage::CounterMappingRegion::makeRegion( + fromRust(Region.Count), Region.Span.FileID, Region.Span.LineStart, + Region.Span.ColumnStart, Region.Span.LineEnd, Region.Span.ColumnEnd)); + } + + // Branch regions: + for (const auto &Region : ArrayRef(BranchRegions, NumBranchRegions)) { + MappingRegions.push_back(coverage::CounterMappingRegion::makeBranchRegion( + fromRust(Region.TrueCount), fromRust(Region.FalseCount), + Region.Span.FileID, Region.Span.LineStart, Region.Span.ColumnStart, + Region.Span.LineEnd, Region.Span.ColumnEnd)); + } + +#if LLVM_VERSION_GE(19, 0) + // MC/DC branch regions: + for (const auto &Region : ArrayRef(MCDCBranchRegions, NumMCDCBranchRegions)) { + MappingRegions.push_back(coverage::CounterMappingRegion::makeBranchRegion( + fromRust(Region.TrueCount), fromRust(Region.FalseCount), + Region.Span.FileID, Region.Span.LineStart, Region.Span.ColumnStart, + Region.Span.LineEnd, Region.Span.ColumnEnd, + fromRust(Region.MCDCBranchParams))); + } + + // MC/DC decision regions: + for (const auto &Region : + ArrayRef(MCDCDecisionRegions, NumMCDCDecisionRegions)) { + MappingRegions.push_back(coverage::CounterMappingRegion::makeDecisionRegion( + fromRust(Region.MCDCDecisionParams), Region.Span.FileID, + Region.Span.LineStart, Region.Span.ColumnStart, Region.Span.LineEnd, + Region.Span.ColumnEnd)); + } +#endif + + // Write the converted expressions and mappings to a byte buffer. auto CoverageMappingWriter = coverage::CoverageMappingWriter( ArrayRef<unsigned>(VirtualFileMappingIDs, NumVirtualFileMappingIDs), - Expressions, - MappingRegions); + Expressions, MappingRegions); auto OS = RawRustStringOstream(BufferOut); CoverageMappingWriter.write(OS); } -extern "C" LLVMValueRef LLVMRustCoverageCreatePGOFuncNameVar( - LLVMValueRef F, - const char *FuncName, - size_t FuncNameLen) { +extern "C" LLVMValueRef +LLVMRustCoverageCreatePGOFuncNameVar(LLVMValueRef F, const char *FuncName, + size_t FuncNameLen) { auto FuncNameRef = StringRef(FuncName, FuncNameLen); return wrap(createPGOFuncNameVar(*cast<Function>(unwrap(F)), FuncNameRef)); } -extern "C" uint64_t LLVMRustCoverageHashByteArray( - const char *Bytes, - size_t NumBytes) { - auto StrRef = StringRef(Bytes, NumBytes); - return IndexedInstrProf::ComputeHash(StrRef); +extern "C" uint64_t LLVMRustCoverageHashBytes(const char *Bytes, + size_t NumBytes) { + return IndexedInstrProf::ComputeHash(StringRef(Bytes, NumBytes)); } -static void WriteSectionNameToString(LLVMModuleRef M, - InstrProfSectKind SK, - RustStringRef Str) { +// Private helper function for getting the covmap and covfun section names. +static void writeInstrProfSectionNameToString(LLVMModuleRef M, + InstrProfSectKind SectKind, + RustStringRef OutStr) { auto TargetTriple = Triple(unwrap(M)->getTargetTriple()); - auto name = getInstrProfSectionName(SK, TargetTriple.getObjectFormat()); - auto OS = RawRustStringOstream(Str); + auto name = getInstrProfSectionName(SectKind, TargetTriple.getObjectFormat()); + auto OS = RawRustStringOstream(OutStr); OS << name; } -extern "C" void LLVMRustCoverageWriteMapSectionNameToString(LLVMModuleRef M, - RustStringRef Str) { - WriteSectionNameToString(M, IPSK_covmap, Str); +extern "C" void +LLVMRustCoverageWriteCovmapSectionNameToString(LLVMModuleRef M, + RustStringRef OutStr) { + writeInstrProfSectionNameToString(M, IPSK_covmap, OutStr); } -extern "C" void LLVMRustCoverageWriteFuncSectionNameToString(LLVMModuleRef M, - RustStringRef Str) { - WriteSectionNameToString(M, IPSK_covfun, Str); +extern "C" void +LLVMRustCoverageWriteCovfunSectionNameToString(LLVMModuleRef M, + RustStringRef OutStr) { + writeInstrProfSectionNameToString(M, IPSK_covfun, OutStr); } -extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) { +extern "C" void +LLVMRustCoverageWriteCovmapVarNameToString(RustStringRef OutStr) { auto name = getCoverageMappingVarName(); - auto OS = RawRustStringOstream(Str); + auto OS = RawRustStringOstream(OutStr); OS << name; } extern "C" uint32_t LLVMRustCoverageMappingVersion() { - return coverage::CovMapVersion::Version6; + // This should always be `CurrentVersion`, because that's the version LLVM + // will use when encoding the data we give it. If for some reason we ever + // want to override the version number we _emit_, do it on the Rust side. + return coverage::CovMapVersion::CurrentVersion; } |
