LCOV - code coverage report
Current view: top level - lib/DebugInfo/PDB/Native - DbiModuleList.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 79 89 88.8 %
Date: 2018-10-20 13:21:21 Functions: 17 19 89.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- DbiModuleList.cpp - PDB module information list --------------------===//
       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             : #include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
      11             : #include "llvm/ADT/StringRef.h"
      12             : #include "llvm/ADT/iterator_range.h"
      13             : #include "llvm/DebugInfo/PDB/Native/RawError.h"
      14             : #include "llvm/Support/BinaryStreamReader.h"
      15             : #include "llvm/Support/Error.h"
      16             : #include <algorithm>
      17             : #include <cassert>
      18             : #include <cstddef>
      19             : #include <cstdint>
      20             : 
      21             : using namespace llvm;
      22             : using namespace llvm::pdb;
      23             : 
      24          67 : DbiModuleSourceFilesIterator::DbiModuleSourceFilesIterator(
      25          67 :     const DbiModuleList &Modules, uint32_t Modi, uint16_t Filei)
      26          67 :     : Modules(&Modules), Modi(Modi), Filei(Filei) {
      27          67 :   setValue();
      28          67 : }
      29             : 
      30         388 : bool DbiModuleSourceFilesIterator::
      31             : operator==(const DbiModuleSourceFilesIterator &R) const {
      32             :   // incompatible iterators are never equal
      33         388 :   if (!isCompatible(R))
      34             :     return false;
      35             : 
      36             :   // If they're compatible, and they're both ends, then they're equal.
      37         388 :   if (isEnd() && R.isEnd())
      38             :     return true;
      39             : 
      40             :   // If one is an end and the other is not, they're not equal.
      41         328 :   if (isEnd() != R.isEnd())
      42             :     return false;
      43             : 
      44             :   // Now we know:
      45             :   // - They're compatible
      46             :   // - They're not *both* end iterators
      47             :   // - Their endness is the same.
      48             :   // Thus, they're compatible iterators pointing to a valid file on the same
      49             :   // module.  All we need to check are the file indices.
      50             :   assert(Modules == R.Modules);
      51             :   assert(Modi == R.Modi);
      52             :   assert(!isEnd());
      53             :   assert(!R.isEnd());
      54             : 
      55           0 :   return (Filei == R.Filei);
      56             : }
      57             : 
      58           0 : bool DbiModuleSourceFilesIterator::
      59             : operator<(const DbiModuleSourceFilesIterator &R) const {
      60             :   assert(isCompatible(R));
      61             : 
      62             :   // It's not sufficient to compare the file indices, because default
      63             :   // constructed iterators could be equal to iterators with valid indices.  To
      64             :   // account for this, early-out if they're equal.
      65           0 :   if (*this == R)
      66             :     return false;
      67             : 
      68           0 :   return Filei < R.Filei;
      69             : }
      70             : 
      71          24 : std::ptrdiff_t DbiModuleSourceFilesIterator::
      72             : operator-(const DbiModuleSourceFilesIterator &R) const {
      73             :   assert(isCompatible(R));
      74             :   assert(!(*this < R));
      75             : 
      76             :   // If they're both end iterators, the distance is 0.
      77          24 :   if (isEnd() && R.isEnd())
      78             :     return 0;
      79             : 
      80             :   assert(!R.isEnd());
      81             : 
      82             :   // At this point, R cannot be end, but *this can, which means that *this
      83             :   // might be a universal end iterator with none of its fields set.  So in that
      84             :   // case have to rely on R as the authority to figure out how many files there
      85             :   // are to compute the distance.
      86          10 :   uint32_t Thisi = Filei;
      87          10 :   if (isEnd()) {
      88          10 :     uint32_t RealModi = R.Modi;
      89          10 :     Thisi = R.Modules->getSourceFileCount(RealModi);
      90             :   }
      91             : 
      92             :   assert(Thisi >= R.Filei);
      93          10 :   return Thisi - R.Filei;
      94             : }
      95             : 
      96         328 : DbiModuleSourceFilesIterator &DbiModuleSourceFilesIterator::
      97             : operator+=(std::ptrdiff_t N) {
      98             :   assert(!isEnd());
      99             : 
     100         328 :   Filei += N;
     101             :   assert(Filei <= Modules->getSourceFileCount(Modi));
     102         328 :   setValue();
     103         328 :   return *this;
     104             : }
     105             : 
     106           0 : DbiModuleSourceFilesIterator &DbiModuleSourceFilesIterator::
     107             : operator-=(std::ptrdiff_t N) {
     108             :   // Note that we can subtract from an end iterator, but not a universal end
     109             :   // iterator.
     110             :   assert(!isUniversalEnd());
     111             : 
     112             :   assert(N <= Filei);
     113             : 
     114           0 :   Filei -= N;
     115           0 :   return *this;
     116             : }
     117             : 
     118         395 : void DbiModuleSourceFilesIterator::setValue() {
     119         395 :   if (isEnd()) {
     120          67 :     ThisValue = "";
     121          67 :     return;
     122             :   }
     123             : 
     124         328 :   uint32_t Off = Modules->ModuleInitialFileIndex[Modi] + Filei;
     125         328 :   auto ExpectedValue = Modules->getFileName(Off);
     126         328 :   if (!ExpectedValue) {
     127           0 :     consumeError(ExpectedValue.takeError());
     128           0 :     Filei = Modules->getSourceFileCount(Modi);
     129             :   } else
     130         328 :     ThisValue = *ExpectedValue;
     131             : }
     132             : 
     133        1557 : bool DbiModuleSourceFilesIterator::isEnd() const {
     134        1557 :   if (isUniversalEnd())
     135             :     return true;
     136             : 
     137             :   assert(Modules);
     138             :   assert(Modi <= Modules->getModuleCount());
     139             :   assert(Filei <= Modules->getSourceFileCount(Modi));
     140             : 
     141        1135 :   if (Modi == Modules->getModuleCount())
     142             :     return true;
     143        1135 :   if (Filei == Modules->getSourceFileCount(Modi))
     144         141 :     return true;
     145             :   return false;
     146             : }
     147             : 
     148        2333 : bool DbiModuleSourceFilesIterator::isUniversalEnd() const { return !Modules; }
     149             : 
     150         388 : bool DbiModuleSourceFilesIterator::isCompatible(
     151             :     const DbiModuleSourceFilesIterator &R) const {
     152             :   // Universal iterators are compatible with any other iterator.
     153         388 :   if (isUniversalEnd() || R.isUniversalEnd())
     154         388 :     return true;
     155             : 
     156             :   // At this point, neither iterator is a universal end iterator, although one
     157             :   // or both might be non-universal end iterators.  Regardless, the module index
     158             :   // is valid, so they are compatible if and only if they refer to the same
     159             :   // module.
     160           0 :   return Modi == R.Modi;
     161             : }
     162             : 
     163         122 : Error DbiModuleList::initialize(BinaryStreamRef ModInfo,
     164             :                                 BinaryStreamRef FileInfo) {
     165         244 :   if (auto EC = initializeModInfo(ModInfo))
     166             :     return EC;
     167         244 :   if (auto EC = initializeFileInfo(FileInfo))
     168             :     return EC;
     169             : 
     170             :   return Error::success();
     171             : }
     172             : 
     173         122 : Error DbiModuleList::initializeModInfo(BinaryStreamRef ModInfo) {
     174             :   ModInfoSubstream = ModInfo;
     175             : 
     176         122 :   if (ModInfo.getLength() == 0)
     177             :     return Error::success();
     178             : 
     179         224 :   BinaryStreamReader Reader(ModInfo);
     180             : 
     181         224 :   if (auto EC = Reader.readArray(Descriptors, ModInfo.getLength()))
     182             :     return EC;
     183             : 
     184             :   return Error::success();
     185             : }
     186             : 
     187         122 : Error DbiModuleList::initializeFileInfo(BinaryStreamRef FileInfo) {
     188             :   FileInfoSubstream = FileInfo;
     189             : 
     190         122 :   if (FileInfo.getLength() == 0)
     191             :     return Error::success();
     192             : 
     193         122 :   BinaryStreamReader FISR(FileInfo);
     194         244 :   if (auto EC = FISR.readObject(FileInfoHeader))
     195             :     return EC;
     196             : 
     197             :   // First is an array of `NumModules` module indices.  This does not seem to be
     198             :   // used for anything meaningful, so we ignore it.
     199             :   FixedStreamArray<support::ulittle16_t> ModuleIndices;
     200         366 :   if (auto EC = FISR.readArray(ModuleIndices, FileInfoHeader->NumModules))
     201             :     return EC;
     202         366 :   if (auto EC = FISR.readArray(ModFileCountArray, FileInfoHeader->NumModules))
     203             :     return EC;
     204             : 
     205             :   // Compute the real number of source files.  We can't trust the value in
     206             :   // `FileInfoHeader->NumSourceFiles` because it is a unit16, and the sum of all
     207             :   // source file counts might be larger than a unit16.  So we compute the real
     208             :   // count by summing up the individual counts.
     209             :   uint32_t NumSourceFiles = 0;
     210         592 :   for (auto Count : ModFileCountArray)
     211         470 :     NumSourceFiles += Count;
     212             : 
     213             :   // In the reference implementation, this array is where the pointer documented
     214             :   // at the definition of ModuleInfoHeader::FileNameOffs points to.  Note that
     215             :   // although the field in ModuleInfoHeader is ignored this array is not, as it
     216             :   // is the authority on where each filename begins in the names buffer.
     217         244 :   if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles))
     218             :     return EC;
     219             : 
     220         244 :   if (auto EC = FISR.readStreamRef(NamesBuffer))
     221             :     return EC;
     222             : 
     223         244 :   auto DescriptorIter = Descriptors.begin();
     224             :   uint32_t NextFileIndex = 0;
     225         244 :   ModuleInitialFileIndex.resize(FileInfoHeader->NumModules);
     226         244 :   ModuleDescriptorOffsets.resize(FileInfoHeader->NumModules);
     227         714 :   for (size_t I = 0; I < FileInfoHeader->NumModules; ++I) {
     228             :     assert(DescriptorIter != Descriptors.end());
     229         470 :     ModuleInitialFileIndex[I] = NextFileIndex;
     230         470 :     ModuleDescriptorOffsets[I] = DescriptorIter.offset();
     231             : 
     232         470 :     NextFileIndex += ModFileCountArray[I];
     233             :     ++DescriptorIter;
     234             :   }
     235             : 
     236             :   assert(DescriptorIter == Descriptors.end());
     237             :   assert(NextFileIndex == NumSourceFiles);
     238             : 
     239             :   return Error::success();
     240             : }
     241             : 
     242        2219 : uint32_t DbiModuleList::getModuleCount() const {
     243        4438 :   return FileInfoHeader->NumModules;
     244             : }
     245             : 
     246         328 : uint32_t DbiModuleList::getSourceFileCount() const {
     247         328 :   return FileNameOffsets.size();
     248             : }
     249             : 
     250        1145 : uint16_t DbiModuleList::getSourceFileCount(uint32_t Modi) const {
     251        1145 :   return ModFileCountArray[Modi];
     252             : }
     253             : 
     254         517 : DbiModuleDescriptor DbiModuleList::getModuleDescriptor(uint32_t Modi) const {
     255             :   assert(Modi < getModuleCount());
     256         517 :   uint32_t Offset = ModuleDescriptorOffsets[Modi];
     257        1034 :   auto Iter = Descriptors.at(Offset);
     258             :   assert(Iter != Descriptors.end());
     259         517 :   return *Iter;
     260             : }
     261             : 
     262             : iterator_range<DbiModuleSourceFilesIterator>
     263          67 : DbiModuleList::source_files(uint32_t Modi) const {
     264             :   return make_range<DbiModuleSourceFilesIterator>(
     265             :       DbiModuleSourceFilesIterator(*this, Modi, 0),
     266          67 :       DbiModuleSourceFilesIterator());
     267             : }
     268             : 
     269         328 : Expected<StringRef> DbiModuleList::getFileName(uint32_t Index) const {
     270         328 :   BinaryStreamReader Names(NamesBuffer);
     271         328 :   if (Index >= getSourceFileCount())
     272             :     return make_error<RawError>(raw_error_code::index_out_of_bounds);
     273             : 
     274         328 :   uint32_t FileOffset = FileNameOffsets[Index];
     275             :   Names.setOffset(FileOffset);
     276         328 :   StringRef Name;
     277         656 :   if (auto EC = Names.readCString(Name))
     278             :     return std::move(EC);
     279             :   return Name;
     280             : }

Generated by: LCOV version 1.13