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 {ENUM_USR, {"USR", &genSymbolIdAbbrev}},
178 {ENUM_NAME, {"Name", &genStringAbbrev}},
179 {ENUM_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},
180 {ENUM_LOCATION, {"Location", &genLocationAbbrev}},
181 {ENUM_SCOPED, {"Scoped", &genBoolAbbrev}},
182 {ENUM_VALUE_NAME, {"Name", &genStringAbbrev}},
183 {ENUM_VALUE_VALUE, {"Value", &genStringAbbrev}},
184 {ENUM_VALUE_EXPR, {"Expr", &genStringAbbrev}},
185 {RECORD_USR, {"USR", &genSymbolIdAbbrev}},
186 {RECORD_NAME, {"Name", &genStringAbbrev}},
187 {RECORD_PATH, {"Path", &genStringAbbrev}},
188 {RECORD_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},
189 {RECORD_LOCATION, {"Location", &genLocationAbbrev}},
190 {RECORD_TAG_TYPE, {"TagType", &genIntAbbrev}},
191 {RECORD_IS_TYPE_DEF, {"IsTypeDef", &genBoolAbbrev}},
192 {RECORD_MANGLED_NAME, {"MangledName", &genStringAbbrev}},
194 {BASE_RECORD_NAME, {"Name", &genStringAbbrev}},
195 {BASE_RECORD_PATH, {"Path", &genStringAbbrev}},
196 {BASE_RECORD_TAG_TYPE, {"TagType", &genIntAbbrev}},
197 {BASE_RECORD_IS_VIRTUAL, {"IsVirtual", &genBoolAbbrev}},
198 {BASE_RECORD_ACCESS, {"Access", &genIntAbbrev}},
199 {BASE_RECORD_IS_PARENT, {"IsParent", &genBoolAbbrev}},
200 {FUNCTION_USR, {"USR", &genSymbolIdAbbrev}},
201 {FUNCTION_NAME, {"Name", &genStringAbbrev}},
202 {FUNCTION_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},
203 {FUNCTION_LOCATION, {"Location", &genLocationAbbrev}},
204 {FUNCTION_ACCESS, {"Access", &genIntAbbrev}},
205 {FUNCTION_IS_METHOD, {"IsMethod", &genBoolAbbrev}},
206 {FUNCTION_IS_STATIC, {"IsStatic", &genBoolAbbrev}},
207 {REFERENCE_USR, {"USR", &genSymbolIdAbbrev}},
208 {REFERENCE_NAME, {"Name", &genStringAbbrev}},
209 {REFERENCE_QUAL_NAME, {"QualName", &genStringAbbrev}},
210 {REFERENCE_TYPE, {"RefType", &genIntAbbrev}},
211 {REFERENCE_PATH, {"Path", &genStringAbbrev}},
212 {REFERENCE_FIELD, {"Field", &genIntAbbrev}},
213 {REFERENCE_FILE, {"File", &genStringAbbrev}},
216 {"SpecializationOf", &genSymbolIdAbbrev}},
217 {TYPEDEF_USR, {"USR", &genSymbolIdAbbrev}},
218 {TYPEDEF_NAME, {"Name", &genStringAbbrev}},
219 {TYPEDEF_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},
220 {TYPEDEF_IS_USING, {"IsUsing", &genBoolAbbrev}},
221 {CONCEPT_USR, {"USR", &genSymbolIdAbbrev}},
222 {CONCEPT_NAME, {"Name", &genStringAbbrev}},
223 {CONCEPT_IS_TYPE, {"IsType", &genBoolAbbrev}},
225 {"ConstraintExpression", &genStringAbbrev}},
226 {CONSTRAINT_EXPRESSION, {"Expression", &genStringAbbrev}},
227 {VAR_USR, {"USR", &genSymbolIdAbbrev}},
228 {VAR_NAME, {"Name", &genStringAbbrev}},
229 {VAR_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},
230 {VAR_IS_STATIC, {"IsStatic", &genBoolAbbrev}},
231 {FRIEND_IS_CLASS, {"IsClass", &genBoolAbbrev}}};
232
233 assert(Inits.size() == RecordIdCount);
234 for (const auto &Init : Inits) {
235 RecordIdNameMap[Init.first] = Init.second;
236 assert((Init.second.Name.size() + 1) <= BitCodeConstants::RecordSize);
237 }
238 assert(RecordIdNameMap.size() == RecordIdCount);
239 return RecordIdNameMap;
240 }();
241
242static const std::vector<std::pair<BlockId, std::vector<RecordId>>>
244 // Version Block
246 // Comment Block
251 // Type Block
253 // FieldType Block
257 // MemberType Block
261 // Enum Block
264 // Enum Value Block
267 // Typedef Block
270 // Namespace Block
273 // Record Block
278 // BaseRecord Block
283 // Function Block
287 // Reference Block
291 // Template Blocks.
295 // Concept Block
299 // Constraint Block
303
304// AbbreviationMap
305
306constexpr unsigned char BitCodeConstants::Signature[];
307
308void ClangDocBitcodeWriter::AbbreviationMap::add(RecordId RID,
309 unsigned AbbrevID) {
310 assert(RecordIdNameMap[RID] && "Unknown RecordId.");
311 assert(!Abbrevs.contains(RID) && "Abbreviation already added.");
312 Abbrevs[RID] = AbbrevID;
313}
314
315unsigned ClangDocBitcodeWriter::AbbreviationMap::get(RecordId RID) const {
316 assert(RecordIdNameMap[RID] && "Unknown RecordId.");
317 assert(Abbrevs.contains(RID) && "Unknown abbreviation.");
318 return Abbrevs.lookup(RID);
319}
320
321// Validation and Overview Blocks
322
323/// Emits the magic number header to check that its the right format,
324/// in this case, 'DOCS'.
325void ClangDocBitcodeWriter::emitHeader() {
326 for (char C : BitCodeConstants::Signature)
327 Stream.Emit((unsigned)C, BitCodeConstants::SignatureBitSize);
328}
329
330void ClangDocBitcodeWriter::emitVersionBlock() {
331 StreamSubBlockGuard Block(Stream, BI_VERSION_BLOCK_ID);
332 emitRecord(VersionNumber, VERSION);
333}
334
335/// Emits a block ID and the block name to the BLOCKINFO block.
336void ClangDocBitcodeWriter::emitBlockID(BlockId BID) {
337 const auto &BlockIdName = BlockIdNameMap[BID];
338 assert(BlockIdName.data() && BlockIdName.size() && "Unknown BlockId.");
339
340 Record.clear();
341 Record.push_back(BID);
342 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
343 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,
344 ArrayRef<unsigned char>(BlockIdName.bytes_begin(),
345 BlockIdName.bytes_end()));
346}
347
348/// Emits a record name to the BLOCKINFO block.
349void ClangDocBitcodeWriter::emitRecordID(RecordId ID) {
350 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
351 prepRecordData(ID);
352 Record.append(RecordIdNameMap[ID].Name.begin(),
353 RecordIdNameMap[ID].Name.end());
354 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
355}
356
357// Abbreviations
358
359void ClangDocBitcodeWriter::emitAbbrev(RecordId ID, BlockId Block) {
360 assert(RecordIdNameMap[ID] && "Unknown abbreviation.");
361 auto Abbrev = std::make_shared<llvm::BitCodeAbbrev>();
362 Abbrev->Add(llvm::BitCodeAbbrevOp(ID));
363 RecordIdNameMap[ID].Abbrev(Abbrev);
364 Abbrevs.add(ID, Stream.EmitBlockInfoAbbrev(Block, std::move(Abbrev)));
365}
366
367// Records
368
369void ClangDocBitcodeWriter::emitRecord(const SymbolID &Sym, RecordId ID) {
370 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
371 assert(RecordIdNameMap[ID].Abbrev == &genSymbolIdAbbrev &&
372 "Abbrev type mismatch.");
373 if (!prepRecordData(ID, Sym != EmptySID))
374 return;
375 assert(Sym.size() == 20);
376 Record.push_back(Sym.size());
377 Record.append(Sym.begin(), Sym.end());
378 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
379}
380
381void ClangDocBitcodeWriter::emitRecord(llvm::StringRef Str, RecordId ID) {
382 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
383 assert(RecordIdNameMap[ID].Abbrev == &genStringAbbrev &&
384 "Abbrev type mismatch.");
385 if (!prepRecordData(ID, !Str.empty()))
386 return;
387 assert(Str.size() < (1U << BitCodeConstants::StringLengthSize));
388 Record.push_back(Str.size());
389 Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Str);
390}
391
392void ClangDocBitcodeWriter::emitRecord(const Location &Loc, RecordId ID) {
393 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
394 assert(RecordIdNameMap[ID].Abbrev == &genLocationAbbrev &&
395 "Abbrev type mismatch.");
396 if (!prepRecordData(ID, true))
397 return;
398 // FIXME: Assert that the line number is of the appropriate size.
399 Record.push_back(Loc.StartLineNumber);
400 Record.push_back(Loc.EndLineNumber);
401 assert(Loc.Filename.size() < (1U << BitCodeConstants::StringLengthSize));
402 Record.push_back(Loc.IsFileInRootDir);
403 Record.push_back(Loc.Filename.size());
404 Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Loc.Filename);
405}
406
407void ClangDocBitcodeWriter::emitRecord(bool Val, RecordId ID) {
408 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
409 assert(RecordIdNameMap[ID].Abbrev == &genBoolAbbrev &&
410 "Abbrev type mismatch.");
411 if (!prepRecordData(ID, Val))
412 return;
413 Record.push_back(Val);
414 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
415}
416
417void ClangDocBitcodeWriter::emitRecord(int Val, RecordId ID) {
418 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
419 assert(RecordIdNameMap[ID].Abbrev == &genIntAbbrev &&
420 "Abbrev type mismatch.");
421 if (!prepRecordData(ID, Val))
422 return;
423 // FIXME: Assert that the integer is of the appropriate size.
424 Record.push_back(Val);
425 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
426}
427
428void ClangDocBitcodeWriter::emitRecord(unsigned Val, RecordId ID) {
429 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
430 assert(RecordIdNameMap[ID].Abbrev == &genIntAbbrev &&
431 "Abbrev type mismatch.");
432 if (!prepRecordData(ID, Val))
433 return;
434 assert(Val < (1U << BitCodeConstants::IntSize));
435 Record.push_back(Val);
436 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
437}
438
439void ClangDocBitcodeWriter::emitRecord(const TemplateInfo &Templ) {}
440
441bool ClangDocBitcodeWriter::prepRecordData(RecordId ID, bool ShouldEmit) {
442 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
443 if (!ShouldEmit)
444 return false;
445 Record.clear();
446 Record.push_back(ID);
447 return true;
448}
449
450// BlockInfo Block
451
452void ClangDocBitcodeWriter::emitBlockInfoBlock() {
453 Stream.EnterBlockInfoBlock();
454 for (const auto &Block : RecordsByBlock) {
455 assert(Block.second.size() < (1U << BitCodeConstants::SubblockIDSize));
456 emitBlockInfo(Block.first, Block.second);
457 }
458 Stream.ExitBlock();
459}
460
461void ClangDocBitcodeWriter::emitBlockInfo(BlockId BID,
462 const std::vector<RecordId> &RIDs) {
463 assert(RIDs.size() < (1U << BitCodeConstants::SubblockIDSize));
464 emitBlockID(BID);
465 for (RecordId RID : RIDs) {
466 emitRecordID(RID);
467 emitAbbrev(RID, BID);
468 }
469}
470
471// Block emission
472
474 if (R.USR == EmptySID && R.Name.empty())
475 return;
476 StreamSubBlockGuard Block(Stream, BI_REFERENCE_BLOCK_ID);
477 emitRecord(R.USR, REFERENCE_USR);
478 emitRecord(R.Name, REFERENCE_NAME);
479 emitRecord(R.QualName, REFERENCE_QUAL_NAME);
480 emitRecord((unsigned)R.RefType, REFERENCE_TYPE);
481 emitRecord(R.Path, REFERENCE_PATH);
482 emitRecord((unsigned)Field, REFERENCE_FIELD);
484}
485
487 StreamSubBlockGuard Block(Stream, BI_FRIEND_BLOCK_ID);
489 emitRecord(R.IsClass, FRIEND_IS_CLASS);
490 if (R.Template)
492 if (R.Params)
493 for (const auto &P : *R.Params)
494 emitBlock(P);
495 if (R.ReturnType)
497}
498
500 StreamSubBlockGuard Block(Stream, BI_TYPE_BLOCK_ID);
501 emitBlock(T.Type, FieldId::F_type);
502 emitRecord(T.IsBuiltIn, TYPE_IS_BUILTIN);
503 emitRecord(T.IsTemplate, TYPE_IS_TEMPLATE);
504}
505
507 StreamSubBlockGuard Block(Stream, BI_TYPEDEF_BLOCK_ID);
508 emitRecord(T.USR, TYPEDEF_USR);
509 emitRecord(T.Name, TYPEDEF_NAME);
510 for (const auto &N : T.Namespace)
512 for (const auto &CI : T.Description)
513 emitBlock(CI);
514 if (T.DefLoc)
515 emitRecord(*T.DefLoc, TYPEDEF_DEFLOCATION);
516 emitRecord(T.IsUsing, TYPEDEF_IS_USING);
517 emitBlock(T.Underlying);
518}
519
521 StreamSubBlockGuard Block(Stream, BI_FIELD_TYPE_BLOCK_ID);
522 emitBlock(T.Type, FieldId::F_type);
523 emitRecord(T.Name, FIELD_TYPE_NAME);
524 emitRecord(T.DefaultValue, FIELD_DEFAULT_VALUE);
525 emitRecord(T.IsBuiltIn, FIELD_TYPE_IS_BUILTIN);
526 emitRecord(T.IsTemplate, FIELD_TYPE_IS_TEMPLATE);
527}
528
530 StreamSubBlockGuard Block(Stream, BI_MEMBER_TYPE_BLOCK_ID);
531 emitBlock(T.Type, FieldId::F_type);
532 emitRecord(T.Name, MEMBER_TYPE_NAME);
533 emitRecord(T.Access, MEMBER_TYPE_ACCESS);
534 emitRecord(T.IsStatic, MEMBER_TYPE_IS_STATIC);
535 emitRecord(T.IsBuiltIn, MEMBER_TYPE_IS_BUILTIN);
536 emitRecord(T.IsTemplate, MEMBER_TYPE_IS_TEMPLATE);
537 emitRecord(T.IsTemplate, MEMBER_TYPE_IS_TEMPLATE);
538 for (const auto &CI : T.Description)
539 emitBlock(CI);
540}
541
543 StreamSubBlockGuard Block(Stream, BI_COMMENT_BLOCK_ID);
544 // Handle Kind (enum) separately, since it is not a string.
545 emitRecord(commentKindToString(I.Kind), COMMENT_KIND);
546 for (const auto &L : std::vector<std::pair<llvm::StringRef, RecordId>>{
547 {I.Text, COMMENT_TEXT},
548 {I.Name, COMMENT_NAME},
552 emitRecord(L.first, L.second);
553 emitRecord(I.SelfClosing, COMMENT_SELFCLOSING);
554 emitRecord(I.Explicit, COMMENT_EXPLICIT);
555 for (const auto &A : I.AttrKeys)
556 emitRecord(A, COMMENT_ATTRKEY);
557 for (const auto &A : I.AttrValues)
558 emitRecord(A, COMMENT_ATTRVAL);
559 for (const auto &A : I.Args)
560 emitRecord(A, COMMENT_ARG);
561 for (const auto &C : I.Children)
562 emitBlock(*C);
563}
564
566 StreamSubBlockGuard Block(Stream, BI_NAMESPACE_BLOCK_ID);
567 emitRecord(I.USR, NAMESPACE_USR);
568 emitRecord(I.Name, NAMESPACE_NAME);
569 emitRecord(I.Path, NAMESPACE_PATH);
570 for (const auto &N : I.Namespace)
572 for (const auto &CI : I.Description)
573 emitBlock(CI);
574 for (const auto &C : I.Children.Namespaces)
576 for (const auto &C : I.Children.Records)
578 for (const auto &C : I.Children.Functions)
579 emitBlock(C);
580 for (const auto &C : I.Children.Enums)
581 emitBlock(C);
582 for (const auto &C : I.Children.Typedefs)
583 emitBlock(C);
584 for (const auto &C : I.Children.Concepts)
585 emitBlock(C);
586 for (const auto &C : I.Children.Variables)
587 emitBlock(C);
588}
589
591 StreamSubBlockGuard Block(Stream, BI_ENUM_BLOCK_ID);
592 emitRecord(I.USR, ENUM_USR);
593 emitRecord(I.Name, ENUM_NAME);
594 for (const auto &N : I.Namespace)
596 for (const auto &CI : I.Description)
597 emitBlock(CI);
598 if (I.DefLoc)
599 emitRecord(*I.DefLoc, ENUM_DEFLOCATION);
600 for (const auto &L : I.Loc)
601 emitRecord(L, ENUM_LOCATION);
602 emitRecord(I.Scoped, ENUM_SCOPED);
603 if (I.BaseType)
605 for (const auto &N : I.Members)
606 emitBlock(N);
607}
608
610 StreamSubBlockGuard Block(Stream, BI_ENUM_VALUE_BLOCK_ID);
611 emitRecord(I.Name, ENUM_VALUE_NAME);
612 emitRecord(I.Value, ENUM_VALUE_VALUE);
613 emitRecord(I.ValueExpr, ENUM_VALUE_EXPR);
614 for (const auto &CI : I.Description)
615 emitBlock(CI);
616}
617
619 StreamSubBlockGuard Block(Stream, BI_RECORD_BLOCK_ID);
620 emitRecord(I.USR, RECORD_USR);
621 emitRecord(I.Name, RECORD_NAME);
622 emitRecord(I.Path, RECORD_PATH);
623 emitRecord(I.MangledName, RECORD_MANGLED_NAME);
624 for (const auto &N : I.Namespace)
626 for (const auto &CI : I.Description)
627 emitBlock(CI);
628 if (I.DefLoc)
629 emitRecord(*I.DefLoc, RECORD_DEFLOCATION);
630 for (const auto &L : I.Loc)
631 emitRecord(L, RECORD_LOCATION);
632 emitRecord(llvm::to_underlying(I.TagType), RECORD_TAG_TYPE);
633 emitRecord(I.IsTypeDef, RECORD_IS_TYPE_DEF);
634 for (const auto &N : I.Members)
635 emitBlock(N);
636 for (const auto &P : I.Parents)
638 for (const auto &P : I.VirtualParents)
640 for (const auto &PB : I.Bases)
641 emitBlock(PB);
642 for (const auto &C : I.Children.Records)
644 for (const auto &C : I.Children.Functions)
645 emitBlock(C);
646 for (const auto &C : I.Children.Enums)
647 emitBlock(C);
648 for (const auto &C : I.Children.Typedefs)
649 emitBlock(C);
650 if (I.Template)
652 for (const auto &C : I.Friends)
653 emitBlock(C);
654}
655
657 StreamSubBlockGuard Block(Stream, BI_BASE_RECORD_BLOCK_ID);
658 emitRecord(I.USR, BASE_RECORD_USR);
659 emitRecord(I.Name, BASE_RECORD_NAME);
660 emitRecord(I.Path, BASE_RECORD_PATH);
661 emitRecord(llvm::to_underlying(I.TagType), BASE_RECORD_TAG_TYPE);
662 emitRecord(I.IsVirtual, BASE_RECORD_IS_VIRTUAL);
663 emitRecord(I.Access, BASE_RECORD_ACCESS);
664 emitRecord(I.IsParent, BASE_RECORD_IS_PARENT);
665 for (const auto &M : I.Members)
666 emitBlock(M);
667 for (const auto &C : I.Children.Functions)
668 emitBlock(C);
669}
670
672 StreamSubBlockGuard Block(Stream, BI_FUNCTION_BLOCK_ID);
673 emitRecord(I.USR, FUNCTION_USR);
674 emitRecord(I.Name, FUNCTION_NAME);
675 for (const auto &N : I.Namespace)
677 for (const auto &CI : I.Description)
678 emitBlock(CI);
679 emitRecord(I.Access, FUNCTION_ACCESS);
680 emitRecord(I.IsMethod, FUNCTION_IS_METHOD);
681 emitRecord(I.IsStatic, FUNCTION_IS_STATIC);
682 if (I.DefLoc)
683 emitRecord(*I.DefLoc, FUNCTION_DEFLOCATION);
684 for (const auto &L : I.Loc)
685 emitRecord(L, FUNCTION_LOCATION);
688 for (const auto &N : I.Params)
689 emitBlock(N);
690 if (I.Template)
692}
693
695 StreamSubBlockGuard Block(Stream, BI_CONCEPT_BLOCK_ID);
696 emitRecord(I.USR, CONCEPT_USR);
697 emitRecord(I.Name, CONCEPT_NAME);
698 for (const auto &CI : I.Description)
699 emitBlock(CI);
700 emitRecord(I.IsType, CONCEPT_IS_TYPE);
703}
704
706 StreamSubBlockGuard Block(Stream, BI_TEMPLATE_BLOCK_ID);
707 for (const auto &P : T.Params)
708 emitBlock(P);
709 if (T.Specialization)
710 emitBlock(*T.Specialization);
711 for (const auto &C : T.Constraints)
712 emitBlock(C);
713}
714
716 StreamSubBlockGuard Block(Stream, BI_TEMPLATE_SPECIALIZATION_BLOCK_ID);
717 emitRecord(T.SpecializationOf, TEMPLATE_SPECIALIZATION_OF);
718 for (const auto &P : T.Params)
719 emitBlock(P);
720}
721
723 StreamSubBlockGuard Block(Stream, BI_TEMPLATE_PARAM_BLOCK_ID);
724 emitRecord(T.Contents, TEMPLATE_PARAM_CONTENTS);
725}
726
728 StreamSubBlockGuard Block(Stream, BI_CONSTRAINT_BLOCK_ID);
729 emitRecord(C.ConstraintExpr, CONSTRAINT_EXPRESSION);
730 emitBlock(C.ConceptRef, FieldId::F_concept);
731}
732
734 StreamSubBlockGuard Block(Stream, BI_VAR_BLOCK_ID);
735 emitRecord(I.USR, VAR_USR);
736 emitRecord(I.Name, VAR_NAME);
737 for (const auto &N : I.Namespace)
739 for (const auto &CI : I.Description)
740 emitBlock(CI);
741 if (I.DefLoc)
742 emitRecord(*I.DefLoc, VAR_DEFLOCATION);
743 emitRecord(I.IsStatic, VAR_IS_STATIC);
744 emitBlock(I.Type);
745}
746
748 switch (I->IT) {
750 emitBlock(*static_cast<clang::doc::NamespaceInfo *>(I));
751 break;
753 emitBlock(*static_cast<clang::doc::RecordInfo *>(I));
754 break;
756 emitBlock(*static_cast<clang::doc::EnumInfo *>(I));
757 break;
759 emitBlock(*static_cast<clang::doc::FunctionInfo *>(I));
760 break;
762 emitBlock(*static_cast<clang::doc::TypedefInfo *>(I));
763 break;
765 emitBlock(*static_cast<clang::doc::ConceptInfo *>(I));
766 break;
768 emitBlock(*static_cast<VarInfo *>(I));
769 break;
771 emitBlock(*static_cast<FriendInfo *>(I));
772 break;
774 llvm::errs() << "Unexpected info, unable to write.\n";
775 return true;
776 }
777 return false;
778}
779
780} // namespace doc
781} // 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 char Signature[4]
static constexpr unsigned RecordSize
static constexpr unsigned StringLengthSize
static constexpr unsigned USRBitLengthSize
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