CoverageMappingWriter.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. //=-- CoverageMappingWriter.cpp - Code coverage mapping writer -------------=//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file contains support for writing coverage mapping data for
  11. // instrumentation based coverage.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "llvm/ProfileData/CoverageMappingWriter.h"
  15. #include "llvm/Support/LEB128.h"
  16. using namespace llvm;
  17. using namespace coverage;
  18. void CoverageFilenamesSectionWriter::write(raw_ostream &OS) {
  19. encodeULEB128(Filenames.size(), OS);
  20. for (const auto &Filename : Filenames) {
  21. encodeULEB128(Filename.size(), OS);
  22. OS << Filename;
  23. }
  24. }
  25. namespace {
  26. /// \brief Gather only the expressions that are used by the mapping
  27. /// regions in this function.
  28. class CounterExpressionsMinimizer {
  29. ArrayRef<CounterExpression> Expressions;
  30. llvm::SmallVector<CounterExpression, 16> UsedExpressions;
  31. std::vector<unsigned> AdjustedExpressionIDs;
  32. public:
  33. void mark(Counter C) {
  34. if (!C.isExpression())
  35. return;
  36. unsigned ID = C.getExpressionID();
  37. AdjustedExpressionIDs[ID] = 1;
  38. mark(Expressions[ID].LHS);
  39. mark(Expressions[ID].RHS);
  40. }
  41. void gatherUsed(Counter C) {
  42. if (!C.isExpression() || !AdjustedExpressionIDs[C.getExpressionID()])
  43. return;
  44. AdjustedExpressionIDs[C.getExpressionID()] = UsedExpressions.size();
  45. const auto &E = Expressions[C.getExpressionID()];
  46. UsedExpressions.push_back(E);
  47. gatherUsed(E.LHS);
  48. gatherUsed(E.RHS);
  49. }
  50. CounterExpressionsMinimizer(ArrayRef<CounterExpression> Expressions,
  51. ArrayRef<CounterMappingRegion> MappingRegions)
  52. : Expressions(Expressions) {
  53. AdjustedExpressionIDs.resize(Expressions.size(), 0);
  54. for (const auto &I : MappingRegions)
  55. mark(I.Count);
  56. for (const auto &I : MappingRegions)
  57. gatherUsed(I.Count);
  58. }
  59. ArrayRef<CounterExpression> getExpressions() const { return UsedExpressions; }
  60. /// \brief Adjust the given counter to correctly transition from the old
  61. /// expression ids to the new expression ids.
  62. Counter adjust(Counter C) const {
  63. if (C.isExpression())
  64. C = Counter::getExpression(AdjustedExpressionIDs[C.getExpressionID()]);
  65. return C;
  66. }
  67. };
  68. }
  69. /// \brief Encode the counter.
  70. ///
  71. /// The encoding uses the following format:
  72. /// Low 2 bits - Tag:
  73. /// Counter::Zero(0) - A Counter with kind Counter::Zero
  74. /// Counter::CounterValueReference(1) - A counter with kind
  75. /// Counter::CounterValueReference
  76. /// Counter::Expression(2) + CounterExpression::Subtract(0) -
  77. /// A counter with kind Counter::Expression and an expression
  78. /// with kind CounterExpression::Subtract
  79. /// Counter::Expression(2) + CounterExpression::Add(1) -
  80. /// A counter with kind Counter::Expression and an expression
  81. /// with kind CounterExpression::Add
  82. /// Remaining bits - Counter/Expression ID.
  83. static unsigned encodeCounter(ArrayRef<CounterExpression> Expressions,
  84. Counter C) {
  85. unsigned Tag = unsigned(C.getKind());
  86. if (C.isExpression())
  87. Tag += Expressions[C.getExpressionID()].Kind;
  88. unsigned ID = C.getCounterID();
  89. assert(ID <=
  90. (std::numeric_limits<unsigned>::max() >> Counter::EncodingTagBits));
  91. return Tag | (ID << Counter::EncodingTagBits);
  92. }
  93. static void writeCounter(ArrayRef<CounterExpression> Expressions, Counter C,
  94. raw_ostream &OS) {
  95. encodeULEB128(encodeCounter(Expressions, C), OS);
  96. }
  97. void CoverageMappingWriter::write(raw_ostream &OS) {
  98. // Sort the regions in an ascending order by the file id and the starting
  99. // location.
  100. std::stable_sort(MappingRegions.begin(), MappingRegions.end());
  101. // Write out the fileid -> filename mapping.
  102. encodeULEB128(VirtualFileMapping.size(), OS);
  103. for (const auto &FileID : VirtualFileMapping)
  104. encodeULEB128(FileID, OS);
  105. // Write out the expressions.
  106. CounterExpressionsMinimizer Minimizer(Expressions, MappingRegions);
  107. auto MinExpressions = Minimizer.getExpressions();
  108. encodeULEB128(MinExpressions.size(), OS);
  109. for (const auto &E : MinExpressions) {
  110. writeCounter(MinExpressions, Minimizer.adjust(E.LHS), OS);
  111. writeCounter(MinExpressions, Minimizer.adjust(E.RHS), OS);
  112. }
  113. // Write out the mapping regions.
  114. // Split the regions into subarrays where each region in a
  115. // subarray has a fileID which is the index of that subarray.
  116. unsigned PrevLineStart = 0;
  117. unsigned CurrentFileID = ~0U;
  118. for (auto I = MappingRegions.begin(), E = MappingRegions.end(); I != E; ++I) {
  119. if (I->FileID != CurrentFileID) {
  120. // Ensure that all file ids have at least one mapping region.
  121. assert(I->FileID == (CurrentFileID + 1));
  122. // Find the number of regions with this file id.
  123. unsigned RegionCount = 1;
  124. for (auto J = I + 1; J != E && I->FileID == J->FileID; ++J)
  125. ++RegionCount;
  126. // Start a new region sub-array.
  127. encodeULEB128(RegionCount, OS);
  128. CurrentFileID = I->FileID;
  129. PrevLineStart = 0;
  130. }
  131. Counter Count = Minimizer.adjust(I->Count);
  132. switch (I->Kind) {
  133. case CounterMappingRegion::CodeRegion:
  134. writeCounter(MinExpressions, Count, OS);
  135. break;
  136. case CounterMappingRegion::ExpansionRegion: {
  137. assert(Count.isZero());
  138. assert(I->ExpandedFileID <=
  139. (std::numeric_limits<unsigned>::max() >>
  140. Counter::EncodingCounterTagAndExpansionRegionTagBits));
  141. // Mark an expansion region with a set bit that follows the counter tag,
  142. // and pack the expanded file id into the remaining bits.
  143. unsigned EncodedTagExpandedFileID =
  144. (1 << Counter::EncodingTagBits) |
  145. (I->ExpandedFileID
  146. << Counter::EncodingCounterTagAndExpansionRegionTagBits);
  147. encodeULEB128(EncodedTagExpandedFileID, OS);
  148. break;
  149. }
  150. case CounterMappingRegion::SkippedRegion:
  151. assert(Count.isZero());
  152. encodeULEB128(uint64_t(I->Kind)
  153. << Counter::EncodingCounterTagAndExpansionRegionTagBits,
  154. OS);
  155. break;
  156. }
  157. assert(I->LineStart >= PrevLineStart);
  158. encodeULEB128(I->LineStart - PrevLineStart, OS);
  159. encodeULEB128(I->ColumnStart, OS);
  160. assert(I->LineEnd >= I->LineStart);
  161. encodeULEB128(I->LineEnd - I->LineStart, OS);
  162. encodeULEB128(I->ColumnEnd, OS);
  163. PrevLineStart = I->LineStart;
  164. }
  165. // Ensure that all file ids have at least one mapping region.
  166. assert(CurrentFileID == (VirtualFileMapping.size() - 1));
  167. }