LLVM API Documentation
00001 //=-- CoverageMappingWriter.cpp - Code coverage mapping writer -------------=// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file contains support for writing coverage mapping data for 00011 // instrumentation based coverage. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "llvm/ProfileData/CoverageMappingWriter.h" 00016 #include "llvm/Support/LEB128.h" 00017 00018 using namespace llvm; 00019 using namespace coverage; 00020 00021 void CoverageFilenamesSectionWriter::write(raw_ostream &OS) { 00022 encodeULEB128(Filenames.size(), OS); 00023 for (const auto &Filename : Filenames) { 00024 encodeULEB128(Filename.size(), OS); 00025 OS << Filename; 00026 } 00027 } 00028 00029 namespace { 00030 /// \brief Gather only the expressions that are used by the mapping 00031 /// regions in this function. 00032 class CounterExpressionsMinimizer { 00033 ArrayRef<CounterExpression> Expressions; 00034 llvm::SmallVector<CounterExpression, 16> UsedExpressions; 00035 std::vector<unsigned> AdjustedExpressionIDs; 00036 00037 public: 00038 void mark(Counter C) { 00039 if (!C.isExpression()) 00040 return; 00041 unsigned ID = C.getExpressionID(); 00042 AdjustedExpressionIDs[ID] = 1; 00043 mark(Expressions[ID].LHS); 00044 mark(Expressions[ID].RHS); 00045 } 00046 00047 void gatherUsed(Counter C) { 00048 if (!C.isExpression() || !AdjustedExpressionIDs[C.getExpressionID()]) 00049 return; 00050 AdjustedExpressionIDs[C.getExpressionID()] = UsedExpressions.size(); 00051 const auto &E = Expressions[C.getExpressionID()]; 00052 UsedExpressions.push_back(E); 00053 gatherUsed(E.LHS); 00054 gatherUsed(E.RHS); 00055 } 00056 00057 CounterExpressionsMinimizer(ArrayRef<CounterExpression> Expressions, 00058 ArrayRef<CounterMappingRegion> MappingRegions) 00059 : Expressions(Expressions) { 00060 AdjustedExpressionIDs.resize(Expressions.size(), 0); 00061 for (const auto &I : MappingRegions) 00062 mark(I.Count); 00063 for (const auto &I : MappingRegions) 00064 gatherUsed(I.Count); 00065 } 00066 00067 ArrayRef<CounterExpression> getExpressions() const { return UsedExpressions; } 00068 00069 /// \brief Adjust the given counter to correctly transition from the old 00070 /// expression ids to the new expression ids. 00071 Counter adjust(Counter C) const { 00072 if (C.isExpression()) 00073 C = Counter::getExpression(AdjustedExpressionIDs[C.getExpressionID()]); 00074 return C; 00075 } 00076 }; 00077 } 00078 00079 /// \brief Return the number of regions that have the given FileID. 00080 static unsigned countFileIDs(ArrayRef<CounterMappingRegion> Regions, 00081 unsigned FileID) { 00082 unsigned Result = 0; 00083 for (const auto &I : Regions) { 00084 if (I.FileID == FileID) 00085 ++Result; 00086 if (I.FileID > FileID) 00087 break; 00088 } 00089 return Result; 00090 } 00091 00092 /// \brief Encode the counter. 00093 /// 00094 /// The encoding uses the following format: 00095 /// Low 2 bits - Tag: 00096 /// Counter::Zero(0) - A Counter with kind Counter::Zero 00097 /// Counter::CounterValueReference(1) - A counter with kind 00098 /// Counter::CounterValueReference 00099 /// Counter::Expression(2) + CounterExpression::Subtract(0) - 00100 /// A counter with kind Counter::Expression and an expression 00101 /// with kind CounterExpression::Subtract 00102 /// Counter::Expression(2) + CounterExpression::Add(1) - 00103 /// A counter with kind Counter::Expression and an expression 00104 /// with kind CounterExpression::Add 00105 /// Remaining bits - Counter/Expression ID. 00106 static unsigned encodeCounter(ArrayRef<CounterExpression> Expressions, 00107 Counter C) { 00108 unsigned Tag = unsigned(C.getKind()); 00109 if (C.isExpression()) 00110 Tag += Expressions[C.getExpressionID()].Kind; 00111 unsigned ID = C.getCounterID(); 00112 assert(ID <= 00113 (std::numeric_limits<unsigned>::max() >> Counter::EncodingTagBits)); 00114 return Tag | (ID << Counter::EncodingTagBits); 00115 } 00116 00117 static void writeCounter(ArrayRef<CounterExpression> Expressions, Counter C, 00118 raw_ostream &OS) { 00119 encodeULEB128(encodeCounter(Expressions, C), OS); 00120 } 00121 00122 void CoverageMappingWriter::write(raw_ostream &OS) { 00123 // Sort the regions in an ascending order by the file id and the starting 00124 // location. 00125 std::sort(MappingRegions.begin(), MappingRegions.end()); 00126 00127 // Write out the fileid -> filename mapping. 00128 encodeULEB128(VirtualFileMapping.size(), OS); 00129 for (const auto &FileID : VirtualFileMapping) 00130 encodeULEB128(FileID, OS); 00131 00132 // Write out the expressions. 00133 CounterExpressionsMinimizer Minimizer(Expressions, MappingRegions); 00134 auto MinExpressions = Minimizer.getExpressions(); 00135 encodeULEB128(MinExpressions.size(), OS); 00136 for (const auto &E : MinExpressions) { 00137 writeCounter(MinExpressions, Minimizer.adjust(E.LHS), OS); 00138 writeCounter(MinExpressions, Minimizer.adjust(E.RHS), OS); 00139 } 00140 00141 // Write out the mapping regions. 00142 // Split the regions into subarrays where each region in a 00143 // subarray has a fileID which is the index of that subarray. 00144 unsigned PrevLineStart = 0; 00145 unsigned CurrentFileID = MappingRegions.front().FileID; 00146 assert(CurrentFileID == 0); 00147 encodeULEB128(countFileIDs(MappingRegions, CurrentFileID), OS); 00148 for (const auto &I : MappingRegions) { 00149 if (I.FileID != CurrentFileID) { 00150 // Ensure that all file ids have at least one mapping region. 00151 assert(I.FileID == (CurrentFileID + 1)); 00152 // Start a new region sub-array. 00153 CurrentFileID = I.FileID; 00154 encodeULEB128(countFileIDs(MappingRegions, CurrentFileID), OS); 00155 PrevLineStart = 0; 00156 } 00157 Counter Count = Minimizer.adjust(I.Count); 00158 switch (I.Kind) { 00159 case CounterMappingRegion::CodeRegion: 00160 writeCounter(MinExpressions, Count, OS); 00161 break; 00162 case CounterMappingRegion::ExpansionRegion: { 00163 assert(Count.isZero()); 00164 assert(I.ExpandedFileID <= 00165 (std::numeric_limits<unsigned>::max() >> 00166 Counter::EncodingCounterTagAndExpansionRegionTagBits)); 00167 // Mark an expansion region with a set bit that follows the counter tag, 00168 // and pack the expanded file id into the remaining bits. 00169 unsigned EncodedTagExpandedFileID = 00170 (1 << Counter::EncodingTagBits) | 00171 (I.ExpandedFileID 00172 << Counter::EncodingCounterTagAndExpansionRegionTagBits); 00173 encodeULEB128(EncodedTagExpandedFileID, OS); 00174 break; 00175 } 00176 case CounterMappingRegion::SkippedRegion: 00177 assert(Count.isZero()); 00178 encodeULEB128(unsigned(I.Kind) 00179 << Counter::EncodingCounterTagAndExpansionRegionTagBits, 00180 OS); 00181 break; 00182 } 00183 assert(I.LineStart >= PrevLineStart); 00184 encodeULEB128(I.LineStart - PrevLineStart, OS); 00185 uint64_t CodeBeforeColumnStart = 00186 uint64_t(I.HasCodeBefore) | 00187 (uint64_t(I.ColumnStart) 00188 << CounterMappingRegion::EncodingHasCodeBeforeBits); 00189 encodeULEB128(CodeBeforeColumnStart, OS); 00190 assert(I.LineEnd >= I.LineStart); 00191 encodeULEB128(I.LineEnd - I.LineStart, OS); 00192 encodeULEB128(I.ColumnEnd, OS); 00193 PrevLineStart = I.LineStart; 00194 } 00195 // Ensure that all file ids have at least one mapping region. 00196 assert(CurrentFileID == (VirtualFileMapping.size() - 1)); 00197 }