clang-tools 22.0.0git
BitcodeWriter.cpp
Go to the documentation of this file.
1//===-- BitcodeWriter.cpp - ClangDoc Bitcode Writer ------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "BitcodeWriter.h"
10#include "llvm/ADT/IndexedMap.h"
11#include <initializer_list>
12
13namespace clang {
14namespace doc {
15
16// Empty SymbolID for comparison, so we don't have to construct one every time.
17static const SymbolID EmptySID = SymbolID();
18
19// Since id enums are not zero-indexed, we need to transform the given id into
20// its associated index.
22 using argument_type = unsigned;
23 unsigned operator()(unsigned ID) const { return ID - BI_FIRST; }
24};
25
27 using argument_type = unsigned;
28 unsigned operator()(unsigned ID) const { return ID - RI_FIRST; }
29};
30
31using AbbrevDsc = void (*)(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev);
32
33static void
34generateAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev,
35 const std::initializer_list<llvm::BitCodeAbbrevOp> Ops) {
36 for (const auto &Op : Ops)
37 Abbrev->Add(Op);
38}
39
40static void genBoolAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
41 generateAbbrev(Abbrev,
42 {// 0. Boolean
43 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
45}
46
47static void genIntAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
48 generateAbbrev(Abbrev,
49 {// 0. Fixed-size integer
50 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
52}
53
54static void genSymbolIdAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
55 generateAbbrev(Abbrev,
56 {// 0. Fixed-size integer (length of the sha1'd USR)
57 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
59 // 1. Fixed-size array of Char6 (USR)
60 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Array),
61 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
63}
64
65static void genStringAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
66 generateAbbrev(Abbrev,
67 {// 0. Fixed-size integer (length of the following string)
68 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
70 // 1. The string blob
71 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)});
72}
73
74// Assumes that the file will not have more than 65535 lines.
75static void genLocationAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
77 Abbrev,
78 {// 0. Fixed-size integer (line number)
79 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
81 // 1. Fixed-size integer (start line number)
82 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
84 // 2. Boolean (IsFileInRootDir)
85 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
87 // 3. Fixed-size integer (length of the following string (filename))
88 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
90 // 4. The string blob
91 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)});
92}
93
95 llvm::StringRef Name;
96 AbbrevDsc Abbrev = nullptr;
97
98 RecordIdDsc() = default;
99 RecordIdDsc(llvm::StringRef Name, AbbrevDsc Abbrev)
100 : Name(Name), Abbrev(Abbrev) {}
101
102 // Is this 'description' valid?
103 operator bool() const {
104 return Abbrev != nullptr && Name.data() != nullptr && !Name.empty();
105 }
106};
107
108static const llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor>
110 llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor> BlockIdNameMap;
112
113 // There is no init-list constructor for the IndexedMap, so have to
114 // improvise
115 static const std::vector<std::pair<BlockId, const char *const>> Inits = {
116 {BI_VERSION_BLOCK_ID, "VersionBlock"},
117 {BI_NAMESPACE_BLOCK_ID, "NamespaceBlock"},
118 {BI_ENUM_BLOCK_ID, "EnumBlock"},
119 {BI_ENUM_VALUE_BLOCK_ID, "EnumValueBlock"},
120 {BI_TYPEDEF_BLOCK_ID, "TypedefBlock"},
121 {BI_TYPE_BLOCK_ID, "TypeBlock"},
122 {BI_FIELD_TYPE_BLOCK_ID, "FieldTypeBlock"},
123 {BI_MEMBER_TYPE_BLOCK_ID, "MemberTypeBlock"},
124 {BI_RECORD_BLOCK_ID, "RecordBlock"},
125 {BI_BASE_RECORD_BLOCK_ID, "BaseRecordBlock"},
126 {BI_FUNCTION_BLOCK_ID, "FunctionBlock"},
127 {BI_COMMENT_BLOCK_ID, "CommentBlock"},
128 {BI_REFERENCE_BLOCK_ID, "ReferenceBlock"},
129 {BI_TEMPLATE_BLOCK_ID, "TemplateBlock"},
130 {BI_TEMPLATE_SPECIALIZATION_BLOCK_ID, "TemplateSpecializationBlock"},
131 {BI_TEMPLATE_PARAM_BLOCK_ID, "TemplateParamBlock"},
132 {BI_CONSTRAINT_BLOCK_ID, "ConstraintBlock"},
133 {BI_CONCEPT_BLOCK_ID, "ConceptBlock"},
134 {BI_VAR_BLOCK_ID, "VarBlock"},
135 {BI_FRIEND_BLOCK_ID, "FriendBlock"}};
136 assert(Inits.size() == BlockIdCount);
137 for (const auto &Init : Inits)
138 BlockIdNameMap[Init.first] = Init.second;
139 assert(BlockIdNameMap.size() == BlockIdCount);
140 return BlockIdNameMap;
141 }();
142
143static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor>
145 llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor> RecordIdNameMap;
147
148 // There is no init-list constructor for the IndexedMap, so have to
149 // improvise
150 static const std::vector<std::pair<RecordId, RecordIdDsc>> Inits = {
151 {VERSION, {"Version", &genIntAbbrev}},
152 {COMMENT_KIND, {"Kind", &genStringAbbrev}},
153 {COMMENT_TEXT, {"Text", &genStringAbbrev}},
154 {COMMENT_NAME, {"Name", &genStringAbbrev}},
155 {COMMENT_DIRECTION, {"Direction", &genStringAbbrev}},
156 {COMMENT_PARAMNAME, {"ParamName", &genStringAbbrev}},
157 {COMMENT_CLOSENAME, {"CloseName", &genStringAbbrev}},
158 {COMMENT_SELFCLOSING, {"SelfClosing", &genBoolAbbrev}},
159 {COMMENT_EXPLICIT, {"Explicit", &genBoolAbbrev}},
160 {COMMENT_ATTRKEY, {"AttrKey", &genStringAbbrev}},
161 {COMMENT_ATTRVAL, {"AttrVal", &genStringAbbrev}},
162 {COMMENT_ARG, {"Arg", &genStringAbbrev}},
163 {FIELD_TYPE_NAME, {"Name", &genStringAbbrev}},
164 {FIELD_DEFAULT_VALUE, {"DefaultValue", &genStringAbbrev}},
165 {FIELD_TYPE_IS_BUILTIN, {"IsBuiltin", &genBoolAbbrev}},
166 {FIELD_TYPE_IS_TEMPLATE, {"IsTemplate", &genBoolAbbrev}},
167 {MEMBER_TYPE_NAME, {"Name", &genStringAbbrev}},
168 {MEMBER_TYPE_ACCESS, {"Access", &genIntAbbrev}},
169 {MEMBER_TYPE_IS_STATIC, {"IsStatic", &genBoolAbbrev}},
170 {MEMBER_TYPE_IS_BUILTIN, {"IsBuiltin", &genBoolAbbrev}},
171 {MEMBER_TYPE_IS_TEMPLATE, {"IsTemplate", &genBoolAbbrev}},
172 {TYPE_IS_BUILTIN, {"IsBuiltin", &genBoolAbbrev}},
173 {TYPE_IS_TEMPLATE, {"IsTemplate", &genBoolAbbrev}},
174 {NAMESPACE_USR, {"USR", &genSymbolIdAbbrev}},
175 {NAMESPACE_NAME, {"Name", &genStringAbbrev}},
176 {NAMESPACE_PATH, {"Path", &genStringAbbrev}},
177 {NAMESPACE_PARENT_USR, {"ParentUSR", &genSymbolIdAbbrev}},
178 {ENUM_USR, {"USR", &genSymbolIdAbbrev}},
179 {ENUM_NAME, {"Name", &genStringAbbrev}},
180 {ENUM_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},
181 {ENUM_LOCATION, {"Location", &genLocationAbbrev}},
182 {ENUM_SCOPED, {"Scoped", &genBoolAbbrev}},
183 {ENUM_VALUE_NAME, {"Name", &genStringAbbrev}},
184 {ENUM_VALUE_VALUE, {"Value", &genStringAbbrev}},
185 {ENUM_VALUE_EXPR, {"Expr", &genStringAbbrev}},
186 {RECORD_USR, {"USR", &genSymbolIdAbbrev}},
187 {RECORD_NAME, {"Name", &genStringAbbrev}},
188 {RECORD_PATH, {"Path", &genStringAbbrev}},
189 {RECORD_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},
190 {RECORD_LOCATION, {"Location", &genLocationAbbrev}},
191 {RECORD_TAG_TYPE, {"TagType", &genIntAbbrev}},
192 {RECORD_IS_TYPE_DEF, {"IsTypeDef", &genBoolAbbrev}},
193 {RECORD_MANGLED_NAME, {"MangledName", &genStringAbbrev}},
194 {RECORD_PARENT_USR, {"ParentUSR", &genSymbolIdAbbrev}},
196 {BASE_RECORD_NAME, {"Name", &genStringAbbrev}},
197 {BASE_RECORD_PATH, {"Path", &genStringAbbrev}},
198 {BASE_RECORD_TAG_TYPE, {"TagType", &genIntAbbrev}},
199 {BASE_RECORD_IS_VIRTUAL, {"IsVirtual", &genBoolAbbrev}},
200 {BASE_RECORD_ACCESS, {"Access", &genIntAbbrev}},
201 {BASE_RECORD_IS_PARENT, {"IsParent", &genBoolAbbrev}},
202 {FUNCTION_USR, {"USR", &genSymbolIdAbbrev}},
203 {FUNCTION_NAME, {"Name", &genStringAbbrev}},
204 {FUNCTION_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},
205 {FUNCTION_LOCATION, {"Location", &genLocationAbbrev}},
206 {FUNCTION_ACCESS, {"Access", &genIntAbbrev}},
207 {FUNCTION_IS_METHOD, {"IsMethod", &genBoolAbbrev}},
208 {FUNCTION_IS_STATIC, {"IsStatic", &genBoolAbbrev}},
209 {REFERENCE_USR, {"USR", &genSymbolIdAbbrev}},
210 {REFERENCE_NAME, {"Name", &genStringAbbrev}},
211 {REFERENCE_QUAL_NAME, {"QualName", &genStringAbbrev}},
212 {REFERENCE_TYPE, {"RefType", &genIntAbbrev}},
213 {REFERENCE_PATH, {"Path", &genStringAbbrev}},
214 {REFERENCE_FIELD, {"Field", &genIntAbbrev}},
215 {REFERENCE_FILE, {"File", &genStringAbbrev}},
218 {"SpecializationOf", &genSymbolIdAbbrev}},
219 {TYPEDEF_USR, {"USR", &genSymbolIdAbbrev}},
220 {TYPEDEF_NAME, {"Name", &genStringAbbrev}},
221 {TYPEDEF_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},
222 {TYPEDEF_IS_USING, {"IsUsing", &genBoolAbbrev}},
223 {CONCEPT_USR, {"USR", &genSymbolIdAbbrev}},
224 {CONCEPT_NAME, {"Name", &genStringAbbrev}},
225 {CONCEPT_IS_TYPE, {"IsType", &genBoolAbbrev}},
227 {"ConstraintExpression", &genStringAbbrev}},
228 {CONCEPT_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},
229 {CONSTRAINT_EXPRESSION, {"Expression", &genStringAbbrev}},
230 {VAR_USR, {"USR", &genSymbolIdAbbrev}},
231 {VAR_NAME, {"Name", &genStringAbbrev}},
232 {VAR_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},
233 {VAR_IS_STATIC, {"IsStatic", &genBoolAbbrev}},
234 {FRIEND_IS_CLASS, {"IsClass", &genBoolAbbrev}}};
235
236 assert(Inits.size() == RecordIdCount);
237 for (const auto &Init : Inits) {
238 RecordIdNameMap[Init.first] = Init.second;
239 assert((Init.second.Name.size() + 1) <= BitCodeConstants::RecordSize);
240 }
241 assert(RecordIdNameMap.size() == RecordIdCount);
242 return RecordIdNameMap;
243 }();
244
245static const std::vector<std::pair<BlockId, std::vector<RecordId>>>
247 // Version Block
249 // Comment Block
254 // Type Block
256 // FieldType Block
260 // MemberType Block
264 // Enum Block
267 // Enum Value Block
270 // Typedef Block
273 // Namespace Block
276 // Record Block
281 // BaseRecord Block
286 // Function Block
290 // Reference Block
294 // Template Blocks.
298 // Concept Block
302 // Constraint Block
306
307// AbbreviationMap
308
309void ClangDocBitcodeWriter::AbbreviationMap::add(RecordId RID,
310 unsigned AbbrevID) {
311 assert(RecordIdNameMap[RID] && "Unknown RecordId.");
312 assert(!Abbrevs.contains(RID) && "Abbreviation already added.");
313 Abbrevs[RID] = AbbrevID;
314}
315
316unsigned ClangDocBitcodeWriter::AbbreviationMap::get(RecordId RID) const {
317 assert(RecordIdNameMap[RID] && "Unknown RecordId.");
318 assert(Abbrevs.contains(RID) && "Unknown abbreviation.");
319 return Abbrevs.lookup(RID);
320}
321
322// Validation and Overview Blocks
323
324/// Emits the magic number header to check that its the right format,
325/// in this case, 'DOCS'.
326void ClangDocBitcodeWriter::emitHeader() {
327 for (char C : BitCodeConstants::Signature)
328 Stream.Emit((unsigned)C, BitCodeConstants::SignatureBitSize);
329}
330
331void ClangDocBitcodeWriter::emitVersionBlock() {
332 StreamSubBlockGuard Block(Stream, BI_VERSION_BLOCK_ID);
333 emitRecord(VersionNumber, VERSION);
334}
335
336/// Emits a block ID and the block name to the BLOCKINFO block.
337void ClangDocBitcodeWriter::emitBlockID(BlockId BID) {
338 const auto &BlockIdName = BlockIdNameMap[BID];
339 assert(BlockIdName.data() && BlockIdName.size() && "Unknown BlockId.");
340
341 Record.clear();
342 Record.push_back(BID);
343 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
344 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,
345 ArrayRef<unsigned char>(BlockIdName.bytes_begin(),
346 BlockIdName.bytes_end()));
347}
348
349/// Emits a record name to the BLOCKINFO block.
350void ClangDocBitcodeWriter::emitRecordID(RecordId ID) {
351 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
352 prepRecordData(ID);
353 Record.append(RecordIdNameMap[ID].Name.begin(),
354 RecordIdNameMap[ID].Name.end());
355 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
356}
357
358// Abbreviations
359
360void ClangDocBitcodeWriter::emitAbbrev(RecordId ID, BlockId Block) {
361 assert(RecordIdNameMap[ID] && "Unknown abbreviation.");
362 auto Abbrev = std::make_shared<llvm::BitCodeAbbrev>();
363 Abbrev->Add(llvm::BitCodeAbbrevOp(ID));
364 RecordIdNameMap[ID].Abbrev(Abbrev);
365 Abbrevs.add(ID, Stream.EmitBlockInfoAbbrev(Block, std::move(Abbrev)));
366}
367
368// Records
369
370void ClangDocBitcodeWriter::emitRecord(const SymbolID &Sym, RecordId ID) {
371 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
372 assert(RecordIdNameMap[ID].Abbrev == &genSymbolIdAbbrev &&
373 "Abbrev type mismatch.");
374 if (!prepRecordData(ID, Sym != EmptySID))
375 return;
376 assert(Sym.size() == 20);
377 Record.push_back(Sym.size());
378 Record.append(Sym.begin(), Sym.end());
379 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
380}
381
382void ClangDocBitcodeWriter::emitRecord(llvm::StringRef Str, RecordId ID) {
383 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
384 assert(RecordIdNameMap[ID].Abbrev == &genStringAbbrev &&
385 "Abbrev type mismatch.");
386 if (!prepRecordData(ID, !Str.empty()))
387 return;
388 assert(Str.size() < (1U << BitCodeConstants::StringLengthSize));
389 Record.push_back(Str.size());
390 Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Str);
391}
392
393void ClangDocBitcodeWriter::emitRecord(const Location &Loc, RecordId ID) {
394 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
395 assert(RecordIdNameMap[ID].Abbrev == &genLocationAbbrev &&
396 "Abbrev type mismatch.");
397 if (!prepRecordData(ID, true))
398 return;
399 // FIXME: Assert that the line number is of the appropriate size.
400 Record.push_back(Loc.StartLineNumber);
401 Record.push_back(Loc.EndLineNumber);
402 assert(Loc.Filename.size() < (1U << BitCodeConstants::StringLengthSize));
403 Record.push_back(Loc.IsFileInRootDir);
404 Record.push_back(Loc.Filename.size());
405 Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Loc.Filename);
406}
407
408void ClangDocBitcodeWriter::emitRecord(bool Val, RecordId ID) {
409 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
410 assert(RecordIdNameMap[ID].Abbrev == &genBoolAbbrev &&
411 "Abbrev type mismatch.");
412 if (!prepRecordData(ID, Val))
413 return;
414 Record.push_back(Val);
415 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
416}
417
418void ClangDocBitcodeWriter::emitRecord(int Val, RecordId ID) {
419 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
420 assert(RecordIdNameMap[ID].Abbrev == &genIntAbbrev &&
421 "Abbrev type mismatch.");
422 if (!prepRecordData(ID, Val))
423 return;
424 // FIXME: Assert that the integer is of the appropriate size.
425 Record.push_back(Val);
426 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
427}
428
429void ClangDocBitcodeWriter::emitRecord(unsigned Val, RecordId ID) {
430 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
431 assert(RecordIdNameMap[ID].Abbrev == &genIntAbbrev &&
432 "Abbrev type mismatch.");
433 if (!prepRecordData(ID, Val))
434 return;
435 assert(Val < (1U << BitCodeConstants::IntSize));
436 Record.push_back(Val);
437 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
438}
439
440void ClangDocBitcodeWriter::emitRecord(const TemplateInfo &Templ) {}
441
442bool ClangDocBitcodeWriter::prepRecordData(RecordId ID, bool ShouldEmit) {
443 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
444 if (!ShouldEmit)
445 return false;
446 Record.clear();
447 Record.push_back(ID);
448 return true;
449}
450
451// BlockInfo Block
452
453void ClangDocBitcodeWriter::emitBlockInfoBlock() {
454 Stream.EnterBlockInfoBlock();
455 for (const auto &Block : RecordsByBlock) {
456 assert(Block.second.size() < (1U << BitCodeConstants::SubblockIDSize));
457 emitBlockInfo(Block.first, Block.second);
458 }
459 Stream.ExitBlock();
460}
461
462void ClangDocBitcodeWriter::emitBlockInfo(BlockId BID,
463 const std::vector<RecordId> &RIDs) {
464 assert(RIDs.size() < (1U << BitCodeConstants::SubblockIDSize));
465 emitBlockID(BID);
466 for (RecordId RID : RIDs) {
467 emitRecordID(RID);
468 emitAbbrev(RID, BID);
469 }
470}
471
472// Block emission
473
475 if (R.USR == EmptySID && R.Name.empty())
476 return;
477 StreamSubBlockGuard Block(Stream, BI_REFERENCE_BLOCK_ID);
478 emitRecord(R.USR, REFERENCE_USR);
479 emitRecord(R.Name, REFERENCE_NAME);
480 emitRecord(R.QualName, REFERENCE_QUAL_NAME);
481 emitRecord((unsigned)R.RefType, REFERENCE_TYPE);
482 emitRecord(R.Path, REFERENCE_PATH);
483 emitRecord((unsigned)Field, REFERENCE_FIELD);
485}
486
488 StreamSubBlockGuard Block(Stream, BI_FRIEND_BLOCK_ID);
490 emitRecord(R.IsClass, FRIEND_IS_CLASS);
491 if (R.Template)
493 if (R.Params)
494 for (const auto &P : *R.Params)
495 emitBlock(P);
496 if (R.ReturnType)
498 for (const auto &CI : R.Description)
499 emitBlock(CI);
500}
501
503 StreamSubBlockGuard Block(Stream, BI_TYPE_BLOCK_ID);
504 emitBlock(T.Type, FieldId::F_type);
505 emitRecord(T.IsBuiltIn, TYPE_IS_BUILTIN);
506 emitRecord(T.IsTemplate, TYPE_IS_TEMPLATE);
507}
508
510 StreamSubBlockGuard Block(Stream, BI_TYPEDEF_BLOCK_ID);
511 emitRecord(T.USR, TYPEDEF_USR);
512 emitRecord(T.Name, TYPEDEF_NAME);
513 for (const auto &N : T.Namespace)
515 for (const auto &CI : T.Description)
516 emitBlock(CI);
517 if (T.DefLoc)
518 emitRecord(*T.DefLoc, TYPEDEF_DEFLOCATION);
519 if (T.Template)
520 emitBlock(*T.Template);
521 emitRecord(T.IsUsing, TYPEDEF_IS_USING);
522 emitBlock(T.Underlying);
523}
524
526 StreamSubBlockGuard Block(Stream, BI_FIELD_TYPE_BLOCK_ID);
527 emitBlock(T.Type, FieldId::F_type);
528 emitRecord(T.Name, FIELD_TYPE_NAME);
529 emitRecord(T.DefaultValue, FIELD_DEFAULT_VALUE);
530 emitRecord(T.IsBuiltIn, FIELD_TYPE_IS_BUILTIN);
531 emitRecord(T.IsTemplate, FIELD_TYPE_IS_TEMPLATE);
532}
533
535 StreamSubBlockGuard Block(Stream, BI_MEMBER_TYPE_BLOCK_ID);
536 emitBlock(T.Type, FieldId::F_type);
537 emitRecord(T.Name, MEMBER_TYPE_NAME);
538 emitRecord(T.Access, MEMBER_TYPE_ACCESS);
539 emitRecord(T.IsStatic, MEMBER_TYPE_IS_STATIC);
540 emitRecord(T.IsBuiltIn, MEMBER_TYPE_IS_BUILTIN);
541 emitRecord(T.IsTemplate, MEMBER_TYPE_IS_TEMPLATE);
542 emitRecord(T.IsTemplate, MEMBER_TYPE_IS_TEMPLATE);
543 for (const auto &CI : T.Description)
544 emitBlock(CI);
545}
546
548 StreamSubBlockGuard Block(Stream, BI_COMMENT_BLOCK_ID);
549 // Handle Kind (enum) separately, since it is not a string.
550 emitRecord(commentKindToString(I.Kind), COMMENT_KIND);
551 for (const auto &L : std::vector<std::pair<llvm::StringRef, RecordId>>{
552 {I.Text, COMMENT_TEXT},
553 {I.Name, COMMENT_NAME},
557 emitRecord(L.first, L.second);
558 emitRecord(I.SelfClosing, COMMENT_SELFCLOSING);
559 emitRecord(I.Explicit, COMMENT_EXPLICIT);
560 for (const auto &A : I.AttrKeys)
561 emitRecord(A, COMMENT_ATTRKEY);
562 for (const auto &A : I.AttrValues)
563 emitRecord(A, COMMENT_ATTRVAL);
564 for (const auto &A : I.Args)
565 emitRecord(A, COMMENT_ARG);
566 for (const auto &C : I.Children)
567 emitBlock(*C);
568}
569
571 StreamSubBlockGuard Block(Stream, BI_NAMESPACE_BLOCK_ID);
572 emitRecord(I.USR, NAMESPACE_USR);
573 emitRecord(I.Name, NAMESPACE_NAME);
574 emitRecord(I.Path, NAMESPACE_PATH);
575 emitRecord(I.ParentUSR, NAMESPACE_PARENT_USR);
576 for (const auto &N : I.Namespace)
578 for (const auto &CI : I.Description)
579 emitBlock(CI);
580 for (const auto &C : I.Children.Namespaces)
582 for (const auto &C : I.Children.Records)
584 for (const auto &C : I.Children.Functions)
585 emitBlock(C);
586 for (const auto &C : I.Children.Enums)
587 emitBlock(C);
588 for (const auto &C : I.Children.Typedefs)
589 emitBlock(C);
590 for (const auto &C : I.Children.Concepts)
591 emitBlock(C);
592 for (const auto &C : I.Children.Variables)
593 emitBlock(C);
594}
595
597 StreamSubBlockGuard Block(Stream, BI_ENUM_BLOCK_ID);
598 emitRecord(I.USR, ENUM_USR);
599 emitRecord(I.Name, ENUM_NAME);
600 for (const auto &N : I.Namespace)
602 for (const auto &CI : I.Description)
603 emitBlock(CI);
604 if (I.DefLoc)
605 emitRecord(*I.DefLoc, ENUM_DEFLOCATION);
606 for (const auto &L : I.Loc)
607 emitRecord(L, ENUM_LOCATION);
608 emitRecord(I.Scoped, ENUM_SCOPED);
609 if (I.BaseType)
611 for (const auto &N : I.Members)
612 emitBlock(N);
613}
614
616 StreamSubBlockGuard Block(Stream, BI_ENUM_VALUE_BLOCK_ID);
617 emitRecord(I.Name, ENUM_VALUE_NAME);
618 emitRecord(I.Value, ENUM_VALUE_VALUE);
619 emitRecord(I.ValueExpr, ENUM_VALUE_EXPR);
620 for (const auto &CI : I.Description)
621 emitBlock(CI);
622}
623
625 StreamSubBlockGuard Block(Stream, BI_RECORD_BLOCK_ID);
626 emitRecord(I.USR, RECORD_USR);
627 emitRecord(I.Name, RECORD_NAME);
628 emitRecord(I.Path, RECORD_PATH);
629 emitRecord(I.MangledName, RECORD_MANGLED_NAME);
630 emitRecord(I.ParentUSR, RECORD_PARENT_USR);
631 for (const auto &N : I.Namespace)
633 for (const auto &CI : I.Description)
634 emitBlock(CI);
635 if (I.DefLoc)
636 emitRecord(*I.DefLoc, RECORD_DEFLOCATION);
637 for (const auto &L : I.Loc)
638 emitRecord(L, RECORD_LOCATION);
639 emitRecord(llvm::to_underlying(I.TagType), RECORD_TAG_TYPE);
640 emitRecord(I.IsTypeDef, RECORD_IS_TYPE_DEF);
641 for (const auto &N : I.Members)
642 emitBlock(N);
643 for (const auto &P : I.Parents)
645 for (const auto &P : I.VirtualParents)
647 for (const auto &PB : I.Bases)
648 emitBlock(PB);
649 for (const auto &C : I.Children.Records)
651 for (const auto &C : I.Children.Functions)
652 emitBlock(C);
653 for (const auto &C : I.Children.Enums)
654 emitBlock(C);
655 for (const auto &C : I.Children.Typedefs)
656 emitBlock(C);
657 if (I.Template)
659 for (const auto &C : I.Friends)
660 emitBlock(C);
661}
662
664 StreamSubBlockGuard Block(Stream, BI_BASE_RECORD_BLOCK_ID);
665 emitRecord(I.USR, BASE_RECORD_USR);
666 emitRecord(I.Name, BASE_RECORD_NAME);
667 emitRecord(I.Path, BASE_RECORD_PATH);
668 emitRecord(llvm::to_underlying(I.TagType), BASE_RECORD_TAG_TYPE);
669 emitRecord(I.IsVirtual, BASE_RECORD_IS_VIRTUAL);
670 emitRecord(I.Access, BASE_RECORD_ACCESS);
671 emitRecord(I.IsParent, BASE_RECORD_IS_PARENT);
672 for (const auto &M : I.Members)
673 emitBlock(M);
674 for (const auto &C : I.Children.Functions)
675 emitBlock(C);
676}
677
679 StreamSubBlockGuard Block(Stream, BI_FUNCTION_BLOCK_ID);
680 emitRecord(I.USR, FUNCTION_USR);
681 emitRecord(I.Name, FUNCTION_NAME);
682 for (const auto &N : I.Namespace)
684 for (const auto &CI : I.Description)
685 emitBlock(CI);
686 emitRecord(I.Access, FUNCTION_ACCESS);
687 emitRecord(I.IsMethod, FUNCTION_IS_METHOD);
688 emitRecord(I.IsStatic, FUNCTION_IS_STATIC);
689 if (I.DefLoc)
690 emitRecord(*I.DefLoc, FUNCTION_DEFLOCATION);
691 for (const auto &L : I.Loc)
692 emitRecord(L, FUNCTION_LOCATION);
695 for (const auto &N : I.Params)
696 emitBlock(N);
697 if (I.Template)
699}
700
702 StreamSubBlockGuard Block(Stream, BI_CONCEPT_BLOCK_ID);
703 emitRecord(I.USR, CONCEPT_USR);
704 emitRecord(I.Name, CONCEPT_NAME);
705 for (const auto &CI : I.Description)
706 emitBlock(CI);
707 emitRecord(I.IsType, CONCEPT_IS_TYPE);
710 if (I.DefLoc)
711 emitRecord(*I.DefLoc, CONCEPT_DEFLOCATION);
712}
713
715 StreamSubBlockGuard Block(Stream, BI_TEMPLATE_BLOCK_ID);
716 for (const auto &P : T.Params)
717 emitBlock(P);
718 if (T.Specialization)
719 emitBlock(*T.Specialization);
720 for (const auto &C : T.Constraints)
721 emitBlock(C);
722}
723
725 StreamSubBlockGuard Block(Stream, BI_TEMPLATE_SPECIALIZATION_BLOCK_ID);
726 emitRecord(T.SpecializationOf, TEMPLATE_SPECIALIZATION_OF);
727 for (const auto &P : T.Params)
728 emitBlock(P);
729}
730
732 StreamSubBlockGuard Block(Stream, BI_TEMPLATE_PARAM_BLOCK_ID);
733 emitRecord(T.Contents, TEMPLATE_PARAM_CONTENTS);
734}
735
737 StreamSubBlockGuard Block(Stream, BI_CONSTRAINT_BLOCK_ID);
738 emitRecord(C.ConstraintExpr, CONSTRAINT_EXPRESSION);
739 emitBlock(C.ConceptRef, FieldId::F_concept);
740}
741
743 StreamSubBlockGuard Block(Stream, BI_VAR_BLOCK_ID);
744 emitRecord(I.USR, VAR_USR);
745 emitRecord(I.Name, VAR_NAME);
746 for (const auto &N : I.Namespace)
748 for (const auto &CI : I.Description)
749 emitBlock(CI);
750 if (I.DefLoc)
751 emitRecord(*I.DefLoc, VAR_DEFLOCATION);
752 emitRecord(I.IsStatic, VAR_IS_STATIC);
753 emitBlock(I.Type);
754}
755
757 switch (I->IT) {
759 emitBlock(*static_cast<clang::doc::NamespaceInfo *>(I));
760 break;
762 emitBlock(*static_cast<clang::doc::RecordInfo *>(I));
763 break;
765 emitBlock(*static_cast<clang::doc::EnumInfo *>(I));
766 break;
768 emitBlock(*static_cast<clang::doc::FunctionInfo *>(I));
769 break;
771 emitBlock(*static_cast<clang::doc::TypedefInfo *>(I));
772 break;
774 emitBlock(*static_cast<clang::doc::ConceptInfo *>(I));
775 break;
777 emitBlock(*static_cast<VarInfo *>(I));
778 break;
780 emitBlock(*static_cast<FriendInfo *>(I));
781 break;
783 unsigned ID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
784 "Unexpected info, unable to write.");
785 Diags.Report(ID);
786 return true;
787 }
788 return false;
789}
790
791} // namespace doc
792} // namespace clang
void emitBlock(const NamespaceInfo &I)
static void genStringAbbrev(std::shared_ptr< llvm::BitCodeAbbrev > &Abbrev)
static const llvm::IndexedMap< RecordIdDsc, RecordIdToIndexFunctor > RecordIdNameMap
static void generateAbbrev(std::shared_ptr< llvm::BitCodeAbbrev > &Abbrev, const std::initializer_list< llvm::BitCodeAbbrevOp > Ops)
static const llvm::IndexedMap< llvm::StringRef, BlockIdToIndexFunctor > BlockIdNameMap
@ TEMPLATE_SPECIALIZATION_OF
@ MEMBER_TYPE_IS_TEMPLATE
@ TEMPLATE_PARAM_CONTENTS
@ CONCEPT_CONSTRAINT_EXPRESSION
static constexpr unsigned BlockIdCount
static const std::vector< std::pair< BlockId, std::vector< RecordId > > > RecordsByBlock
static const unsigned VersionNumber
void(*)(std::shared_ptr< llvm::BitCodeAbbrev > &Abbrev) AbbrevDsc
static void genIntAbbrev(std::shared_ptr< llvm::BitCodeAbbrev > &Abbrev)
static void genBoolAbbrev(std::shared_ptr< llvm::BitCodeAbbrev > &Abbrev)
static constexpr unsigned RecordIdCount
std::array< uint8_t, 20 > SymbolID
llvm::StringRef commentKindToString(CommentKind Kind)
static void genSymbolIdAbbrev(std::shared_ptr< llvm::BitCodeAbbrev > &Abbrev)
@ BI_CONSTRAINT_BLOCK_ID
@ BI_ENUM_VALUE_BLOCK_ID
@ BI_TEMPLATE_SPECIALIZATION_BLOCK_ID
@ BI_NAMESPACE_BLOCK_ID
@ BI_TEMPLATE_PARAM_BLOCK_ID
@ BI_MEMBER_TYPE_BLOCK_ID
@ BI_BASE_RECORD_BLOCK_ID
@ BI_FIELD_TYPE_BLOCK_ID
@ BI_REFERENCE_BLOCK_ID
static void genLocationAbbrev(std::shared_ptr< llvm::BitCodeAbbrev > &Abbrev)
static const SymbolID EmptySID
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static constexpr unsigned BoolSize
static constexpr unsigned LineNumberSize
static constexpr unsigned RecordSize
static constexpr unsigned StringLengthSize
static constexpr unsigned USRBitLengthSize
static constexpr unsigned char Signature[4]
static constexpr unsigned IntSize
static constexpr unsigned SignatureBitSize
static constexpr unsigned SubblockIDSize
static constexpr unsigned USRLengthSize
unsigned operator()(unsigned ID) const
SmallString< 8 > Direction
std::vector< std::unique_ptr< CommentInfo > > Children
llvm::SmallVector< SmallString< 16 >, 4 > AttrValues
SmallString< 16 > CloseName
SmallString< 16 > Name
SmallString< 64 > Text
llvm::SmallVector< SmallString< 16 >, 4 > AttrKeys
llvm::SmallVector< SmallString< 16 >, 4 > Args
SmallString< 16 > ParamName
SmallString< 16 > ConstraintExpression
llvm::SmallVector< EnumValueInfo, 4 > Members
std::optional< TypeInfo > BaseType
std::vector< CommentInfo > Description
Comment description of this field.
SmallString< 16 > ValueExpr
std::optional< TypeInfo > ReturnType
std::optional< SmallVector< FieldTypeInfo, 4 > > Params
std::optional< TemplateInfo > Template
llvm::SmallVector< FieldTypeInfo, 4 > Params
std::optional< TemplateInfo > Template
A base struct for Infos.
SmallString< 16 > Name
std::vector< CommentInfo > Description
llvm::SmallString< 128 > Path
llvm::SmallVector< Reference, 4 > Namespace
RecordIdDsc(llvm::StringRef Name, AbbrevDsc Abbrev)
unsigned operator()(unsigned ID) const
llvm::SmallVector< MemberTypeInfo, 4 > Members
std::optional< TemplateInfo > Template
std::vector< FriendInfo > Friends
llvm::SmallVector< Reference, 4 > VirtualParents
llvm::SmallVector< Reference, 4 > Parents
std::vector< BaseRecordInfo > Bases
SmallString< 16 > QualName
llvm::SmallString< 128 > Path
SmallString< 16 > DocumentationFileName
SmallString< 16 > Name
std::vector< Reference > Records
std::vector< TypedefInfo > Typedefs
std::vector< FunctionInfo > Functions
std::vector< Reference > Namespaces
std::vector< VarInfo > Variables
std::vector< EnumInfo > Enums
std::vector< ConceptInfo > Concepts
llvm::SmallVector< Location, 2 > Loc
std::optional< Location > DefLoc
SmallString< 16 > MangledName