LLVM  6.0.0svn
DbiModuleList.cpp
Go to the documentation of this file.
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 
11 #include "llvm/ADT/StringRef.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 
25  const DbiModuleList &Modules, uint32_t Modi, uint16_t Filei)
26  : Modules(&Modules), Modi(Modi), Filei(Filei) {
27  setValue();
28 }
29 
32  // incompatible iterators are never equal
33  if (!isCompatible(R))
34  return false;
35 
36  // If they're compatible, and they're both ends, then they're equal.
37  if (isEnd() && R.isEnd())
38  return true;
39 
40  // If one is an end and the other is not, they're not equal.
41  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  return (Filei == R.Filei);
56 }
57 
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  if (*this == R)
66  return false;
67 
68  return Filei < R.Filei;
69 }
70 
71 std::ptrdiff_t DbiModuleSourceFilesIterator::
73  assert(isCompatible(R));
74  assert(!(*this < R));
75 
76  // If they're both end iterators, the distance is 0.
77  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  uint32_t Thisi = Filei;
87  if (isEnd()) {
88  uint32_t RealModi = R.Modi;
89  Thisi = R.Modules->getSourceFileCount(RealModi);
90  }
91 
92  assert(Thisi >= R.Filei);
93  return Thisi - R.Filei;
94 }
95 
97 operator+=(std::ptrdiff_t N) {
98  assert(!isEnd());
99 
100  Filei += N;
101  assert(Filei <= Modules->getSourceFileCount(Modi));
102  setValue();
103  return *this;
104 }
105 
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  Filei -= N;
115  return *this;
116 }
117 
118 void DbiModuleSourceFilesIterator::setValue() {
119  if (isEnd()) {
120  ThisValue = "";
121  return;
122  }
123 
124  uint32_t Off = Modules->ModuleInitialFileIndex[Modi] + Filei;
125  auto ExpectedValue = Modules->getFileName(Off);
126  if (!ExpectedValue) {
127  consumeError(ExpectedValue.takeError());
128  Filei = Modules->getSourceFileCount(Modi);
129  } else
130  ThisValue = *ExpectedValue;
131 }
132 
133 bool DbiModuleSourceFilesIterator::isEnd() const {
134  if (isUniversalEnd())
135  return true;
136 
137  assert(Modules);
138  assert(Modi <= Modules->getModuleCount());
139  assert(Filei <= Modules->getSourceFileCount(Modi));
140 
141  if (Modi == Modules->getModuleCount())
142  return true;
143  if (Filei == Modules->getSourceFileCount(Modi))
144  return true;
145  return false;
146 }
147 
148 bool DbiModuleSourceFilesIterator::isUniversalEnd() const { return !Modules; }
149 
150 bool DbiModuleSourceFilesIterator::isCompatible(
151  const DbiModuleSourceFilesIterator &R) const {
152  // Universal iterators are compatible with any other iterator.
153  if (isUniversalEnd() || R.isUniversalEnd())
154  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  return Modi == R.Modi;
161 }
162 
165  if (auto EC = initializeModInfo(ModInfo))
166  return EC;
167  if (auto EC = initializeFileInfo(FileInfo))
168  return EC;
169 
170  return Error::success();
171 }
172 
173 Error DbiModuleList::initializeModInfo(BinaryStreamRef ModInfo) {
174  ModInfoSubstream = ModInfo;
175 
176  if (ModInfo.getLength() == 0)
177  return Error::success();
178 
179  BinaryStreamReader Reader(ModInfo);
180 
181  if (auto EC = Reader.readArray(Descriptors, ModInfo.getLength()))
182  return EC;
183 
184  return Error::success();
185 }
186 
187 Error DbiModuleList::initializeFileInfo(BinaryStreamRef FileInfo) {
188  FileInfoSubstream = FileInfo;
189 
190  if (FileInfo.getLength() == 0)
191  return Error::success();
192 
193  BinaryStreamReader FISR(FileInfo);
194  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.
200  if (auto EC = FISR.readArray(ModuleIndices, FileInfoHeader->NumModules))
201  return EC;
202  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  for (auto Count : ModFileCountArray)
211  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  if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles))
218  return EC;
219 
220  if (auto EC = FISR.readStreamRef(NamesBuffer))
221  return EC;
222 
223  auto DescriptorIter = Descriptors.begin();
224  uint32_t NextFileIndex = 0;
225  ModuleInitialFileIndex.resize(FileInfoHeader->NumModules);
226  ModuleDescriptorOffsets.resize(FileInfoHeader->NumModules);
227  for (size_t I = 0; I < FileInfoHeader->NumModules; ++I) {
228  assert(DescriptorIter != Descriptors.end());
229  ModuleInitialFileIndex[I] = NextFileIndex;
230  ModuleDescriptorOffsets[I] = DescriptorIter.offset();
231 
232  NextFileIndex += ModFileCountArray[I];
233  ++DescriptorIter;
234  }
235 
236  assert(DescriptorIter == Descriptors.end());
237  assert(NextFileIndex == NumSourceFiles);
238 
239  return Error::success();
240 }
241 
243  return FileInfoHeader->NumModules;
244 }
245 
247  return FileNameOffsets.size();
248 }
249 
251  return ModFileCountArray[Modi];
252 }
253 
255  assert(Modi < getModuleCount());
256  uint32_t Offset = ModuleDescriptorOffsets[Modi];
257  auto Iter = Descriptors.at(Offset);
258  assert(Iter != Descriptors.end());
259  return *Iter;
260 }
261 
264  return make_range<DbiModuleSourceFilesIterator>(
265  DbiModuleSourceFilesIterator(*this, Modi, 0),
267 }
268 
270  BinaryStreamReader Names(NamesBuffer);
271  if (Index >= getSourceFileCount())
272  return make_error<RawError>(raw_error_code::index_out_of_bounds);
273 
274  uint32_t FileOffset = FileNameOffsets[Index];
275  Names.setOffset(FileOffset);
276  StringRef Name;
277  if (auto EC = Names.readCString(Name))
278  return std::move(EC);
279  return Name;
280 }
DbiModuleSourceFilesIterator & operator-=(std::ptrdiff_t N)
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
Expected< StringRef > getFileName(uint32_t Index) const
DbiModuleSourceFilesIterator & operator+=(std::ptrdiff_t N)
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
Error readObject(const T *&Dest)
Get a pointer to an object of type T from the underlying stream, as if by memcpy, and store the resul...
DbiModuleDescriptor getModuleDescriptor(uint32_t Modi) const
FixedStreamArray is similar to VarStreamArray, except with each record having a fixed-length.
iterator_range< DbiModuleSourceFilesIterator > source_files(uint32_t Modi) const
uint32_t getSourceFileCount() const
uint32_t getModuleCount() const
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
Error readCString(StringRef &Dest)
Read a null terminated string from Dest.
Error initialize(BinaryStreamRef ModInfo, BinaryStreamRef FileInfo)
bool operator==(const DbiModuleSourceFilesIterator &R) const
std::ptrdiff_t operator-(const DbiModuleSourceFilesIterator &R) const
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:962
void setOffset(uint32_t Off)
uint32_t getLength() const
static ErrorSuccess success()
Create a success value.
Definition: Error.h:313
BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.
A range adaptor for a pair of iterators.
#define I(x, y, z)
Definition: MD5.cpp:58
#define N
Error readStreamRef(BinaryStreamRef &Ref)
Read the entire remainder of the underlying stream into Ref.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
Provides read only access to a subclass of BinaryStream.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
Error readArray(ArrayRef< T > &Array, uint32_t NumElements)
Get a reference to a NumElements element array of objects of type T from the underlying stream as if ...
bool operator<(const DbiModuleSourceFilesIterator &RHS) const