You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.167
Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
parent
e19d552987
commit
b084638f15
@ -1,208 +0,0 @@
|
||||
//===- CoverageMappingWriter.cpp - Code coverage mapping writer -----------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains support for writing coverage mapping data for
|
||||
// instrumentation based coverage.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/LEB128.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace coverage;
|
||||
|
||||
void CoverageFilenamesSectionWriter::write(raw_ostream &OS) {
|
||||
encodeULEB128(Filenames.size(), OS);
|
||||
for (const auto &Filename : Filenames) {
|
||||
encodeULEB128(Filename.size(), OS);
|
||||
OS << Filename;
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// \brief Gather only the expressions that are used by the mapping
|
||||
/// regions in this function.
|
||||
class CounterExpressionsMinimizer {
|
||||
ArrayRef<CounterExpression> Expressions;
|
||||
SmallVector<CounterExpression, 16> UsedExpressions;
|
||||
std::vector<unsigned> AdjustedExpressionIDs;
|
||||
|
||||
public:
|
||||
CounterExpressionsMinimizer(ArrayRef<CounterExpression> Expressions,
|
||||
ArrayRef<CounterMappingRegion> MappingRegions)
|
||||
: Expressions(Expressions) {
|
||||
AdjustedExpressionIDs.resize(Expressions.size(), 0);
|
||||
for (const auto &I : MappingRegions)
|
||||
mark(I.Count);
|
||||
for (const auto &I : MappingRegions)
|
||||
gatherUsed(I.Count);
|
||||
}
|
||||
|
||||
void mark(Counter C) {
|
||||
if (!C.isExpression())
|
||||
return;
|
||||
unsigned ID = C.getExpressionID();
|
||||
AdjustedExpressionIDs[ID] = 1;
|
||||
mark(Expressions[ID].LHS);
|
||||
mark(Expressions[ID].RHS);
|
||||
}
|
||||
|
||||
void gatherUsed(Counter C) {
|
||||
if (!C.isExpression() || !AdjustedExpressionIDs[C.getExpressionID()])
|
||||
return;
|
||||
AdjustedExpressionIDs[C.getExpressionID()] = UsedExpressions.size();
|
||||
const auto &E = Expressions[C.getExpressionID()];
|
||||
UsedExpressions.push_back(E);
|
||||
gatherUsed(E.LHS);
|
||||
gatherUsed(E.RHS);
|
||||
}
|
||||
|
||||
ArrayRef<CounterExpression> getExpressions() const { return UsedExpressions; }
|
||||
|
||||
/// \brief Adjust the given counter to correctly transition from the old
|
||||
/// expression ids to the new expression ids.
|
||||
Counter adjust(Counter C) const {
|
||||
if (C.isExpression())
|
||||
C = Counter::getExpression(AdjustedExpressionIDs[C.getExpressionID()]);
|
||||
return C;
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
/// \brief Encode the counter.
|
||||
///
|
||||
/// The encoding uses the following format:
|
||||
/// Low 2 bits - Tag:
|
||||
/// Counter::Zero(0) - A Counter with kind Counter::Zero
|
||||
/// Counter::CounterValueReference(1) - A counter with kind
|
||||
/// Counter::CounterValueReference
|
||||
/// Counter::Expression(2) + CounterExpression::Subtract(0) -
|
||||
/// A counter with kind Counter::Expression and an expression
|
||||
/// with kind CounterExpression::Subtract
|
||||
/// Counter::Expression(2) + CounterExpression::Add(1) -
|
||||
/// A counter with kind Counter::Expression and an expression
|
||||
/// with kind CounterExpression::Add
|
||||
/// Remaining bits - Counter/Expression ID.
|
||||
static unsigned encodeCounter(ArrayRef<CounterExpression> Expressions,
|
||||
Counter C) {
|
||||
unsigned Tag = unsigned(C.getKind());
|
||||
if (C.isExpression())
|
||||
Tag += Expressions[C.getExpressionID()].Kind;
|
||||
unsigned ID = C.getCounterID();
|
||||
assert(ID <=
|
||||
(std::numeric_limits<unsigned>::max() >> Counter::EncodingTagBits));
|
||||
return Tag | (ID << Counter::EncodingTagBits);
|
||||
}
|
||||
|
||||
static void writeCounter(ArrayRef<CounterExpression> Expressions, Counter C,
|
||||
raw_ostream &OS) {
|
||||
encodeULEB128(encodeCounter(Expressions, C), OS);
|
||||
}
|
||||
|
||||
void CoverageMappingWriter::write(raw_ostream &OS) {
|
||||
// Check that we don't have any bogus regions.
|
||||
assert(all_of(MappingRegions,
|
||||
[](const CounterMappingRegion &CMR) {
|
||||
return CMR.startLoc() <= CMR.endLoc();
|
||||
}) &&
|
||||
"Source region does not begin before it ends");
|
||||
|
||||
// Sort the regions in an ascending order by the file id and the starting
|
||||
// location. Sort by region kinds to ensure stable order for tests.
|
||||
std::stable_sort(
|
||||
MappingRegions.begin(), MappingRegions.end(),
|
||||
[](const CounterMappingRegion &LHS, const CounterMappingRegion &RHS) {
|
||||
if (LHS.FileID != RHS.FileID)
|
||||
return LHS.FileID < RHS.FileID;
|
||||
if (LHS.startLoc() != RHS.startLoc())
|
||||
return LHS.startLoc() < RHS.startLoc();
|
||||
return LHS.Kind < RHS.Kind;
|
||||
});
|
||||
|
||||
// Write out the fileid -> filename mapping.
|
||||
encodeULEB128(VirtualFileMapping.size(), OS);
|
||||
for (const auto &FileID : VirtualFileMapping)
|
||||
encodeULEB128(FileID, OS);
|
||||
|
||||
// Write out the expressions.
|
||||
CounterExpressionsMinimizer Minimizer(Expressions, MappingRegions);
|
||||
auto MinExpressions = Minimizer.getExpressions();
|
||||
encodeULEB128(MinExpressions.size(), OS);
|
||||
for (const auto &E : MinExpressions) {
|
||||
writeCounter(MinExpressions, Minimizer.adjust(E.LHS), OS);
|
||||
writeCounter(MinExpressions, Minimizer.adjust(E.RHS), OS);
|
||||
}
|
||||
|
||||
// Write out the mapping regions.
|
||||
// Split the regions into subarrays where each region in a
|
||||
// subarray has a fileID which is the index of that subarray.
|
||||
unsigned PrevLineStart = 0;
|
||||
unsigned CurrentFileID = ~0U;
|
||||
for (auto I = MappingRegions.begin(), E = MappingRegions.end(); I != E; ++I) {
|
||||
if (I->FileID != CurrentFileID) {
|
||||
// Ensure that all file ids have at least one mapping region.
|
||||
assert(I->FileID == (CurrentFileID + 1));
|
||||
// Find the number of regions with this file id.
|
||||
unsigned RegionCount = 1;
|
||||
for (auto J = I + 1; J != E && I->FileID == J->FileID; ++J)
|
||||
++RegionCount;
|
||||
// Start a new region sub-array.
|
||||
encodeULEB128(RegionCount, OS);
|
||||
|
||||
CurrentFileID = I->FileID;
|
||||
PrevLineStart = 0;
|
||||
}
|
||||
Counter Count = Minimizer.adjust(I->Count);
|
||||
switch (I->Kind) {
|
||||
case CounterMappingRegion::CodeRegion:
|
||||
case CounterMappingRegion::GapRegion:
|
||||
writeCounter(MinExpressions, Count, OS);
|
||||
break;
|
||||
case CounterMappingRegion::ExpansionRegion: {
|
||||
assert(Count.isZero());
|
||||
assert(I->ExpandedFileID <=
|
||||
(std::numeric_limits<unsigned>::max() >>
|
||||
Counter::EncodingCounterTagAndExpansionRegionTagBits));
|
||||
// Mark an expansion region with a set bit that follows the counter tag,
|
||||
// and pack the expanded file id into the remaining bits.
|
||||
unsigned EncodedTagExpandedFileID =
|
||||
(1 << Counter::EncodingTagBits) |
|
||||
(I->ExpandedFileID
|
||||
<< Counter::EncodingCounterTagAndExpansionRegionTagBits);
|
||||
encodeULEB128(EncodedTagExpandedFileID, OS);
|
||||
break;
|
||||
}
|
||||
case CounterMappingRegion::SkippedRegion:
|
||||
assert(Count.isZero());
|
||||
encodeULEB128(unsigned(I->Kind)
|
||||
<< Counter::EncodingCounterTagAndExpansionRegionTagBits,
|
||||
OS);
|
||||
break;
|
||||
}
|
||||
assert(I->LineStart >= PrevLineStart);
|
||||
encodeULEB128(I->LineStart - PrevLineStart, OS);
|
||||
encodeULEB128(I->ColumnStart, OS);
|
||||
assert(I->LineEnd >= I->LineStart);
|
||||
encodeULEB128(I->LineEnd - I->LineStart, OS);
|
||||
encodeULEB128(I->ColumnEnd, OS);
|
||||
PrevLineStart = I->LineStart;
|
||||
}
|
||||
// Ensure that all file ids have at least one mapping region.
|
||||
assert(CurrentFileID == (VirtualFileMapping.size() - 1));
|
||||
}
|
Reference in New Issue
Block a user