clang-tools  7.0.0
BitcodeReader.cpp
Go to the documentation of this file.
1 //===-- BitcodeReader.cpp - ClangDoc Bitcode Reader ------------*- 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 
10 #include "BitcodeReader.h"
11 #include "llvm/ADT/IndexedMap.h"
12 #include "llvm/ADT/Optional.h"
13 #include "llvm/Support/raw_ostream.h"
14 
15 namespace clang {
16 namespace doc {
17 
18 using Record = llvm::SmallVector<uint64_t, 1024>;
19 
20 bool decodeRecord(Record R, llvm::SmallVectorImpl<char> &Field,
21  llvm::StringRef Blob) {
22  Field.assign(Blob.begin(), Blob.end());
23  return true;
24 }
25 
26 bool decodeRecord(Record R, SymbolID &Field, llvm::StringRef Blob) {
28  return false;
29 
30  // First position in the record is the length of the following array, so we
31  // copy the following elements to the field.
32  for (int I = 0, E = R[0]; I < E; ++I)
33  Field[I] = R[I + 1];
34  return true;
35 }
36 
37 bool decodeRecord(Record R, bool &Field, llvm::StringRef Blob) {
38  Field = R[0] != 0;
39  return true;
40 }
41 
42 bool decodeRecord(Record R, int &Field, llvm::StringRef Blob) {
43  if (R[0] > INT_MAX)
44  return false;
45  Field = (int)R[0];
46  return true;
47 }
48 
49 bool decodeRecord(Record R, AccessSpecifier &Field, llvm::StringRef Blob) {
50  switch (R[0]) {
51  case AS_public:
52  case AS_private:
53  case AS_protected:
54  case AS_none:
55  Field = (AccessSpecifier)R[0];
56  return true;
57  default:
58  return false;
59  }
60 }
61 
62 bool decodeRecord(Record R, TagTypeKind &Field, llvm::StringRef Blob) {
63  switch (R[0]) {
64  case TTK_Struct:
65  case TTK_Interface:
66  case TTK_Union:
67  case TTK_Class:
68  case TTK_Enum:
69  Field = (TagTypeKind)R[0];
70  return true;
71  default:
72  return false;
73  }
74 }
75 
76 bool decodeRecord(Record R, llvm::Optional<Location> &Field,
77  llvm::StringRef Blob) {
78  if (R[0] > INT_MAX)
79  return false;
80  Field.emplace((int)R[0], Blob);
81  return true;
82 }
83 
84 bool decodeRecord(Record R, InfoType &Field, llvm::StringRef Blob) {
85  switch (auto IT = static_cast<InfoType>(R[0])) {
90  case InfoType::IT_enum:
91  Field = IT;
92  return true;
93  }
94  return false;
95 }
96 
97 bool decodeRecord(Record R, FieldId &Field, llvm::StringRef Blob) {
98  switch (auto F = static_cast<FieldId>(R[0])) {
100  case FieldId::F_parent:
101  case FieldId::F_vparent:
102  case FieldId::F_type:
103  case FieldId::F_default:
104  Field = F;
105  return true;
106  }
107  return false;
108 }
109 
110 bool decodeRecord(Record R, llvm::SmallVectorImpl<llvm::SmallString<16>> &Field,
111  llvm::StringRef Blob) {
112  Field.push_back(Blob);
113  return true;
114 }
115 
116 bool decodeRecord(Record R, llvm::SmallVectorImpl<Location> &Field,
117  llvm::StringRef Blob) {
118  if (R[0] > INT_MAX)
119  return false;
120  Field.emplace_back((int)R[0], Blob);
121  return true;
122 }
123 
124 bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob,
125  const unsigned VersionNo) {
126  if (ID == VERSION && R[0] == VersionNo)
127  return true;
128  return false;
129 }
130 
131 bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob,
132  NamespaceInfo *I) {
133  switch (ID) {
134  case NAMESPACE_USR:
135  return decodeRecord(R, I->USR, Blob);
136  case NAMESPACE_NAME:
137  return decodeRecord(R, I->Name, Blob);
138  default:
139  return false;
140  }
141 }
142 
143 bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, RecordInfo *I) {
144  switch (ID) {
145  case RECORD_USR:
146  return decodeRecord(R, I->USR, Blob);
147  case RECORD_NAME:
148  return decodeRecord(R, I->Name, Blob);
149  case RECORD_DEFLOCATION:
150  return decodeRecord(R, I->DefLoc, Blob);
151  case RECORD_LOCATION:
152  return decodeRecord(R, I->Loc, Blob);
153  case RECORD_TAG_TYPE:
154  return decodeRecord(R, I->TagType, Blob);
155  default:
156  return false;
157  }
158 }
159 
160 bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, EnumInfo *I) {
161  switch (ID) {
162  case ENUM_USR:
163  return decodeRecord(R, I->USR, Blob);
164  case ENUM_NAME:
165  return decodeRecord(R, I->Name, Blob);
166  case ENUM_DEFLOCATION:
167  return decodeRecord(R, I->DefLoc, Blob);
168  case ENUM_LOCATION:
169  return decodeRecord(R, I->Loc, Blob);
170  case ENUM_MEMBER:
171  return decodeRecord(R, I->Members, Blob);
172  case ENUM_SCOPED:
173  return decodeRecord(R, I->Scoped, Blob);
174  default:
175  return false;
176  }
177 }
178 
179 bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, FunctionInfo *I) {
180  switch (ID) {
181  case FUNCTION_USR:
182  return decodeRecord(R, I->USR, Blob);
183  case FUNCTION_NAME:
184  return decodeRecord(R, I->Name, Blob);
186  return decodeRecord(R, I->DefLoc, Blob);
187  case FUNCTION_LOCATION:
188  return decodeRecord(R, I->Loc, Blob);
189  case FUNCTION_ACCESS:
190  return decodeRecord(R, I->Access, Blob);
191  case FUNCTION_IS_METHOD:
192  return decodeRecord(R, I->IsMethod, Blob);
193  default:
194  return false;
195  }
196 }
197 
198 bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, TypeInfo *I) {
199  return true;
200 }
201 
202 bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob,
203  FieldTypeInfo *I) {
204  switch (ID) {
205  case FIELD_TYPE_NAME:
206  return decodeRecord(R, I->Name, Blob);
207  default:
208  return false;
209  }
210 }
211 
212 bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob,
213  MemberTypeInfo *I) {
214  switch (ID) {
215  case MEMBER_TYPE_NAME:
216  return decodeRecord(R, I->Name, Blob);
217  case MEMBER_TYPE_ACCESS:
218  return decodeRecord(R, I->Access, Blob);
219  default:
220  return false;
221  }
222 }
223 
224 bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, CommentInfo *I) {
225  switch (ID) {
226  case COMMENT_KIND:
227  return decodeRecord(R, I->Kind, Blob);
228  case COMMENT_TEXT:
229  return decodeRecord(R, I->Text, Blob);
230  case COMMENT_NAME:
231  return decodeRecord(R, I->Name, Blob);
232  case COMMENT_DIRECTION:
233  return decodeRecord(R, I->Direction, Blob);
234  case COMMENT_PARAMNAME:
235  return decodeRecord(R, I->ParamName, Blob);
236  case COMMENT_CLOSENAME:
237  return decodeRecord(R, I->CloseName, Blob);
238  case COMMENT_ATTRKEY:
239  return decodeRecord(R, I->AttrKeys, Blob);
240  case COMMENT_ATTRVAL:
241  return decodeRecord(R, I->AttrValues, Blob);
242  case COMMENT_ARG:
243  return decodeRecord(R, I->Args, Blob);
244  case COMMENT_SELFCLOSING:
245  return decodeRecord(R, I->SelfClosing, Blob);
246  case COMMENT_EXPLICIT:
247  return decodeRecord(R, I->Explicit, Blob);
248  default:
249  return false;
250  }
251 }
252 
253 bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, Reference *I,
254  FieldId &F) {
255  switch (ID) {
256  case REFERENCE_USR:
257  return decodeRecord(R, I->USR, Blob);
258  case REFERENCE_NAME:
259  return decodeRecord(R, I->Name, Blob);
260  case REFERENCE_TYPE:
261  return decodeRecord(R, I->RefType, Blob);
262  case REFERENCE_FIELD:
263  return decodeRecord(R, F, Blob);
264  default:
265  return false;
266  }
267 }
268 
269 template <typename T> CommentInfo *getCommentInfo(T I) {
270  llvm::errs() << "Cannot have comment subblock.\n";
271  exit(1);
272 }
273 
275  I->Description.emplace_back();
276  return &I->Description.back();
277 }
278 
280  I->Description.emplace_back();
281  return &I->Description.back();
282 }
283 
285  I->Description.emplace_back();
286  return &I->Description.back();
287 }
288 
290  I->Description.emplace_back();
291  return &I->Description.back();
292 }
293 
295  I->Children.emplace_back(llvm::make_unique<CommentInfo>());
296  return I->Children.back().get();
297 }
298 
299 template <> CommentInfo *getCommentInfo(std::unique_ptr<CommentInfo> &I) {
300  return getCommentInfo(I.get());
301 }
302 
303 template <typename T, typename TTypeInfo>
304 void addTypeInfo(T I, TTypeInfo &&TI) {
305  llvm::errs() << "Invalid type for info.\n";
306  exit(1);
307 }
308 
309 template <> void addTypeInfo(RecordInfo *I, MemberTypeInfo &&T) {
310  I->Members.emplace_back(std::move(T));
311 }
312 
313 template <> void addTypeInfo(FunctionInfo *I, TypeInfo &&T) {
314  I->ReturnType = std::move(T);
315 }
316 
317 template <> void addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) {
318  I->Params.emplace_back(std::move(T));
319 }
320 
321 template <typename T> void addReference(T I, Reference &&R, FieldId F) {
322  llvm::errs() << "Invalid field type for info.\n";
323  exit(1);
324 }
325 
326 template <> void addReference(TypeInfo *I, Reference &&R, FieldId F) {
327  switch (F) {
328  case FieldId::F_type:
329  I->Type = std::move(R);
330  break;
331  default:
332  llvm::errs() << "Invalid field type for info.\n";
333  exit(1);
334  }
335 }
336 
337 template <> void addReference(FieldTypeInfo *I, Reference &&R, FieldId F) {
338  switch (F) {
339  case FieldId::F_type:
340  I->Type = std::move(R);
341  break;
342  default:
343  llvm::errs() << "Invalid field type for info.\n";
344  exit(1);
345  }
346 }
347 
348 template <> void addReference(MemberTypeInfo *I, Reference &&R, FieldId F) {
349  switch (F) {
350  case FieldId::F_type:
351  I->Type = std::move(R);
352  break;
353  default:
354  llvm::errs() << "Invalid field type for info.\n";
355  exit(1);
356  }
357 }
358 
359 template <> void addReference(EnumInfo *I, Reference &&R, FieldId F) {
360  switch (F) {
362  I->Namespace.emplace_back(std::move(R));
363  break;
364  default:
365  llvm::errs() << "Invalid field type for info.\n";
366  exit(1);
367  }
368 }
369 
370 template <> void addReference(NamespaceInfo *I, Reference &&R, FieldId F) {
371  switch (F) {
373  I->Namespace.emplace_back(std::move(R));
374  break;
375  default:
376  llvm::errs() << "Invalid field type for info.\n";
377  exit(1);
378  }
379 }
380 
381 template <> void addReference(FunctionInfo *I, Reference &&R, FieldId F) {
382  switch (F) {
384  I->Namespace.emplace_back(std::move(R));
385  break;
386  case FieldId::F_parent:
387  I->Parent = std::move(R);
388  break;
389  default:
390  llvm::errs() << "Invalid field type for info.\n";
391  exit(1);
392  }
393 }
394 
395 template <> void addReference(RecordInfo *I, Reference &&R, FieldId F) {
396  switch (F) {
398  I->Namespace.emplace_back(std::move(R));
399  break;
400  case FieldId::F_parent:
401  I->Parents.emplace_back(std::move(R));
402  break;
403  case FieldId::F_vparent:
404  I->VirtualParents.emplace_back(std::move(R));
405  break;
406  default:
407  llvm::errs() << "Invalid field type for info.\n";
408  exit(1);
409  }
410 }
411 
412 // Read records from bitcode into a given info.
413 template <typename T> bool ClangDocBitcodeReader::readRecord(unsigned ID, T I) {
414  Record R;
415  llvm::StringRef Blob;
416  unsigned RecID = Stream.readRecord(ID, R, &Blob);
417  return parseRecord(R, RecID, Blob, I);
418 }
419 
420 template <> bool ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {
421  Record R;
422  llvm::StringRef Blob;
423  unsigned RecID = Stream.readRecord(ID, R, &Blob);
424  return parseRecord(R, RecID, Blob, I, CurrentReferenceField);
425 }
426 
427 // Read a block of records into a single info.
428 template <typename T> bool ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
429  if (Stream.EnterSubBlock(ID))
430  return false;
431 
432  while (true) {
433  unsigned BlockOrCode = 0;
434  Cursor Res = skipUntilRecordOrBlock(BlockOrCode);
435 
436  switch (Res) {
437  case Cursor::BadBlock:
438  return false;
439  case Cursor::BlockEnd:
440  return true;
441  case Cursor::BlockBegin:
442  if (readSubBlock(BlockOrCode, I))
443  continue;
444  if (!Stream.SkipBlock())
445  return false;
446  continue;
447  case Cursor::Record:
448  break;
449  }
450  if (!readRecord(BlockOrCode, I))
451  return false;
452  }
453 }
454 
455 template <typename T>
456 bool ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
457  switch (ID) {
458  // Blocks can only have Comment, Reference, or TypeInfo subblocks
459  case BI_COMMENT_BLOCK_ID:
460  if (readBlock(ID, getCommentInfo(I)))
461  return true;
462  return false;
463  case BI_TYPE_BLOCK_ID: {
464  TypeInfo TI;
465  if (readBlock(ID, &TI)) {
466  addTypeInfo(I, std::move(TI));
467  return true;
468  }
469  return false;
470  }
471  case BI_FIELD_TYPE_BLOCK_ID: {
472  FieldTypeInfo TI;
473  if (readBlock(ID, &TI)) {
474  addTypeInfo(I, std::move(TI));
475  return true;
476  }
477  return false;
478  }
480  MemberTypeInfo TI;
481  if (readBlock(ID, &TI)) {
482  addTypeInfo(I, std::move(TI));
483  return true;
484  }
485  return false;
486  }
487  case BI_REFERENCE_BLOCK_ID: {
488  Reference R;
489  if (readBlock(ID, &R)) {
490  addReference(I, std::move(R), CurrentReferenceField);
491  return true;
492  }
493  return false;
494  }
495  default:
496  llvm::errs() << "Invalid subblock type.\n";
497  return false;
498  }
499 }
500 
501 ClangDocBitcodeReader::Cursor
502 ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) {
503  BlockOrRecordID = 0;
504 
505  while (!Stream.AtEndOfStream()) {
506  unsigned Code = Stream.ReadCode();
507 
508  switch ((llvm::bitc::FixedAbbrevIDs)Code) {
509  case llvm::bitc::ENTER_SUBBLOCK:
510  BlockOrRecordID = Stream.ReadSubBlockID();
511  return Cursor::BlockBegin;
512  case llvm::bitc::END_BLOCK:
513  if (Stream.ReadBlockEnd())
514  return Cursor::BadBlock;
515  return Cursor::BlockEnd;
516  case llvm::bitc::DEFINE_ABBREV:
517  Stream.ReadAbbrevRecord();
518  continue;
519  case llvm::bitc::UNABBREV_RECORD:
520  return Cursor::BadBlock;
521  default:
522  BlockOrRecordID = Code;
523  return Cursor::Record;
524  }
525  }
526  llvm_unreachable("Premature stream end.");
527 }
528 
529 bool ClangDocBitcodeReader::validateStream() {
530  if (Stream.AtEndOfStream())
531  return false;
532 
533  // Sniff for the signature.
534  if (Stream.Read(8) != BitCodeConstants::Signature[0] ||
535  Stream.Read(8) != BitCodeConstants::Signature[1] ||
536  Stream.Read(8) != BitCodeConstants::Signature[2] ||
537  Stream.Read(8) != BitCodeConstants::Signature[3])
538  return false;
539  return true;
540 }
541 
542 bool ClangDocBitcodeReader::readBlockInfoBlock() {
543  BlockInfo = Stream.ReadBlockInfoBlock();
544  if (!BlockInfo)
545  return false;
546  Stream.setBlockInfo(&*BlockInfo);
547  return true;
548 }
549 
550 template <typename T>
551 std::unique_ptr<Info> ClangDocBitcodeReader::createInfo(unsigned ID) {
552  std::unique_ptr<Info> I = llvm::make_unique<T>();
553  if (readBlock(ID, static_cast<T *>(I.get())))
554  return I;
555  llvm::errs() << "Error reading from block.\n";
556  return nullptr;
557 }
558 
559 std::unique_ptr<Info> ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
560  switch (ID) {
562  return createInfo<NamespaceInfo>(ID);
563  case BI_RECORD_BLOCK_ID:
564  return createInfo<RecordInfo>(ID);
565  case BI_ENUM_BLOCK_ID:
566  return createInfo<EnumInfo>(ID);
568  return createInfo<FunctionInfo>(ID);
569  default:
570  llvm::errs() << "Error reading from block.\n";
571  return nullptr;
572  }
573 }
574 
575 // Entry point
576 std::vector<std::unique_ptr<Info>> ClangDocBitcodeReader::readBitcode() {
577  std::vector<std::unique_ptr<Info>> Infos;
578  if (!validateStream())
579  return Infos;
580 
581  // Read the top level blocks.
582  while (!Stream.AtEndOfStream()) {
583  unsigned Code = Stream.ReadCode();
584  if (Code != llvm::bitc::ENTER_SUBBLOCK)
585  return Infos;
586 
587  unsigned ID = Stream.ReadSubBlockID();
588  switch (ID) {
589  // NamedType and Comment blocks should not appear at the top level
590  case BI_TYPE_BLOCK_ID:
593  case BI_COMMENT_BLOCK_ID:
595  llvm::errs() << "Invalid top level block.\n";
596  return Infos;
598  case BI_RECORD_BLOCK_ID:
599  case BI_ENUM_BLOCK_ID:
601  if (std::unique_ptr<Info> I = readBlockToInfo(ID)) {
602  Infos.emplace_back(std::move(I));
603  }
604  return Infos;
605  case BI_VERSION_BLOCK_ID:
606  if (readBlock(ID, VersionNumber))
607  continue;
608  return Infos;
609  case llvm::bitc::BLOCKINFO_BLOCK_ID:
610  if (readBlockInfoBlock())
611  continue;
612  return Infos;
613  default:
614  if (!Stream.SkipBlock())
615  continue;
616  }
617  }
618  return Infos;
619 }
620 
621 } // namespace doc
622 } // namespace clang
llvm::SmallVector< Reference, 4 > Namespace
bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, const unsigned VersionNo)
static const unsigned VersionNumber
Definition: BitcodeWriter.h:34
llvm::SmallVector< uint64_t, 1024 > Record
SmallString< 16 > Name
llvm::Optional< Location > DefLoc
llvm::SmallVector< Location, 2 > Loc
void addTypeInfo(T I, TTypeInfo &&TI)
llvm::SmallVector< Reference, 4 > VirtualParents
llvm::SmallVector< FieldTypeInfo, 4 > Params
void addReference(T I, Reference &&R, FieldId F)
static constexpr char Signature[4]
Definition: BitcodeWriter.h:48
llvm::SmallVector< SmallString< 16 >, 4 > Members
llvm::SmallVector< SmallString< 16 >, 4 > AttrValues
std::vector< CommentInfo > Description
llvm::SmallVector< SmallString< 16 >, 4 > Args
static constexpr int USRHashSize
Definition: BitcodeWriter.h:49
SmallString< 16 > Name
llvm::SmallVector< Reference, 4 > Parents
SmallString< 16 > ParamName
llvm::SmallVector< SmallString< 16 >, 4 > AttrKeys
SmallString< 16 > Name
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
SmallString< 16 > Name
SmallString< 16 > CloseName
SmallString< 8 > Direction
CommentInfo * getCommentInfo(T I)
llvm::SmallVector< MemberTypeInfo, 4 > Members
SmallString< 16 > Kind
std::vector< std::unique_ptr< CommentInfo > > Children
SmallString< 64 > Text
std::array< uint8_t, 20 > SymbolID
std::vector< std::unique_ptr< Info > > readBitcode()
bool decodeRecord(Record R, llvm::SmallVectorImpl< char > &Field, llvm::StringRef Blob)