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