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
306void ClangDocBitcodeWriter::AbbreviationMap::add(RecordId RID,
307 unsigned AbbrevID) {
308 assert(RecordIdNameMap[RID] && "Unknown RecordId.");
309 assert(!Abbrevs.contains(RID) && "Abbreviation already added.");
310 Abbrevs[RID] = AbbrevID;
311}
312
313unsigned ClangDocBitcodeWriter::AbbreviationMap::get(RecordId RID) const {
314 assert(RecordIdNameMap[RID] && "Unknown RecordId.");
315 assert(Abbrevs.contains(RID) && "Unknown abbreviation.");
316 return Abbrevs.lookup(RID);
317}
318
319// Validation and Overview Blocks
320
321/// Emits the magic number header to check that its the right format,
322/// in this case, 'DOCS'.
323void ClangDocBitcodeWriter::emitHeader() {
324 for (char C : BitCodeConstants::Signature)
325 Stream.Emit((unsigned)C, BitCodeConstants::SignatureBitSize);
326}
327
328void ClangDocBitcodeWriter::emitVersionBlock() {
329 StreamSubBlockGuard Block(Stream, BI_VERSION_BLOCK_ID);
330 emitRecord(VersionNumber, VERSION);
331}
332
333/// Emits a block ID and the block name to the BLOCKINFO block.
334void ClangDocBitcodeWriter::emitBlockID(BlockId BID) {
335 const auto &BlockIdName = BlockIdNameMap[BID];
336 assert(BlockIdName.data() && BlockIdName.size() && "Unknown BlockId.");
337
338 Record.clear();
339 Record.push_back(BID);
340 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
341 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,
342 ArrayRef<unsigned char>(BlockIdName.bytes_begin(),
343 BlockIdName.bytes_end()));
344}
345
346/// Emits a record name to the BLOCKINFO block.
347void ClangDocBitcodeWriter::emitRecordID(RecordId ID) {
348 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
349 prepRecordData(ID);
350 Record.append(RecordIdNameMap[ID].Name.begin(),
351 RecordIdNameMap[ID].Name.end());
352 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
353}
354
355// Abbreviations
356
357void ClangDocBitcodeWriter::emitAbbrev(RecordId ID, BlockId Block) {
358 assert(RecordIdNameMap[ID] && "Unknown abbreviation.");
359 auto Abbrev = std::make_shared<llvm::BitCodeAbbrev>();
360 Abbrev->Add(llvm::BitCodeAbbrevOp(ID));
361 RecordIdNameMap[ID].Abbrev(Abbrev);
362 Abbrevs.add(ID, Stream.EmitBlockInfoAbbrev(Block, std::move(Abbrev)));
363}
364
365// Records
366
367void ClangDocBitcodeWriter::emitRecord(const SymbolID &Sym, RecordId ID) {
368 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
369 assert(RecordIdNameMap[ID].Abbrev == &genSymbolIdAbbrev &&
370 "Abbrev type mismatch.");
371 if (!prepRecordData(ID, Sym != EmptySID))
372 return;
373 assert(Sym.size() == 20);
374 Record.push_back(Sym.size());
375 Record.append(Sym.begin(), Sym.end());
376 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
377}
378
379void ClangDocBitcodeWriter::emitRecord(llvm::StringRef Str, RecordId ID) {
380 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
381 assert(RecordIdNameMap[ID].Abbrev == &genStringAbbrev &&
382 "Abbrev type mismatch.");
383 if (!prepRecordData(ID, !Str.empty()))
384 return;
385 assert(Str.size() < (1U << BitCodeConstants::StringLengthSize));
386 Record.push_back(Str.size());
387 Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Str);
388}
389
390void ClangDocBitcodeWriter::emitRecord(const Location &Loc, RecordId ID) {
391 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
392 assert(RecordIdNameMap[ID].Abbrev == &genLocationAbbrev &&
393 "Abbrev type mismatch.");
394 if (!prepRecordData(ID, true))
395 return;
396 // FIXME: Assert that the line number is of the appropriate size.
397 Record.push_back(Loc.StartLineNumber);
398 Record.push_back(Loc.EndLineNumber);
399 assert(Loc.Filename.size() < (1U << BitCodeConstants::StringLengthSize));
400 Record.push_back(Loc.IsFileInRootDir);
401 Record.push_back(Loc.Filename.size());
402 Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Loc.Filename);
403}
404
405void ClangDocBitcodeWriter::emitRecord(bool Val, RecordId ID) {
406 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
407 assert(RecordIdNameMap[ID].Abbrev == &genBoolAbbrev &&
408 "Abbrev type mismatch.");
409 if (!prepRecordData(ID, Val))
410 return;
411 Record.push_back(Val);
412 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
413}
414
415void ClangDocBitcodeWriter::emitRecord(int Val, RecordId ID) {
416 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
417 assert(RecordIdNameMap[ID].Abbrev == &genIntAbbrev &&
418 "Abbrev type mismatch.");
419 if (!prepRecordData(ID, Val))
420 return;
421 // FIXME: Assert that the integer is of the appropriate size.
422 Record.push_back(Val);
423 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
424}
425
426void ClangDocBitcodeWriter::emitRecord(unsigned Val, RecordId ID) {
427 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
428 assert(RecordIdNameMap[ID].Abbrev == &genIntAbbrev &&
429 "Abbrev type mismatch.");
430 if (!prepRecordData(ID, Val))
431 return;
432 assert(Val < (1U << BitCodeConstants::IntSize));
433 Record.push_back(Val);
434 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
435}
436
437void ClangDocBitcodeWriter::emitRecord(const TemplateInfo &Templ) {}
438
439bool ClangDocBitcodeWriter::prepRecordData(RecordId ID, bool ShouldEmit) {
440 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
441 if (!ShouldEmit)
442 return false;
443 Record.clear();
444 Record.push_back(ID);
445 return true;
446}
447
448// BlockInfo Block
449
450void ClangDocBitcodeWriter::emitBlockInfoBlock() {
451 Stream.EnterBlockInfoBlock();
452 for (const auto &Block : RecordsByBlock) {
453 assert(Block.second.size() < (1U << BitCodeConstants::SubblockIDSize));
454 emitBlockInfo(Block.first, Block.second);
455 }
456 Stream.ExitBlock();
457}
458
459void ClangDocBitcodeWriter::emitBlockInfo(BlockId BID,
460 const std::vector<RecordId> &RIDs) {
461 assert(RIDs.size() < (1U << BitCodeConstants::SubblockIDSize));
462 emitBlockID(BID);
463 for (RecordId RID : RIDs) {
464 emitRecordID(RID);
465 emitAbbrev(RID, BID);
466 }
467}
468
469// Block emission
470
472 if (R.USR == EmptySID && R.Name.empty())
473 return;
474 StreamSubBlockGuard Block(Stream, BI_REFERENCE_BLOCK_ID);
475 emitRecord(R.USR, REFERENCE_USR);
476 emitRecord(R.Name, REFERENCE_NAME);
477 emitRecord(R.QualName, REFERENCE_QUAL_NAME);
478 emitRecord((unsigned)R.RefType, REFERENCE_TYPE);
479 emitRecord(R.Path, REFERENCE_PATH);
480 emitRecord((unsigned)Field, REFERENCE_FIELD);
482}
483
485 StreamSubBlockGuard Block(Stream, BI_FRIEND_BLOCK_ID);
487 emitRecord(R.IsClass, FRIEND_IS_CLASS);
488 if (R.Template)
490 if (R.Params)
491 for (const auto &P : *R.Params)
492 emitBlock(P);
493 if (R.ReturnType)
495}
496
498 StreamSubBlockGuard Block(Stream, BI_TYPE_BLOCK_ID);
499 emitBlock(T.Type, FieldId::F_type);
500 emitRecord(T.IsBuiltIn, TYPE_IS_BUILTIN);
501 emitRecord(T.IsTemplate, TYPE_IS_TEMPLATE);
502}
503
505 StreamSubBlockGuard Block(Stream, BI_TYPEDEF_BLOCK_ID);
506 emitRecord(T.USR, TYPEDEF_USR);
507 emitRecord(T.Name, TYPEDEF_NAME);
508 for (const auto &N : T.Namespace)
510 for (const auto &CI : T.Description)
511 emitBlock(CI);
512 if (T.DefLoc)
513 emitRecord(*T.DefLoc, TYPEDEF_DEFLOCATION);
514 emitRecord(T.IsUsing, TYPEDEF_IS_USING);
515 emitBlock(T.Underlying);
516}
517
519 StreamSubBlockGuard Block(Stream, BI_FIELD_TYPE_BLOCK_ID);
520 emitBlock(T.Type, FieldId::F_type);
521 emitRecord(T.Name, FIELD_TYPE_NAME);
522 emitRecord(T.DefaultValue, FIELD_DEFAULT_VALUE);
523 emitRecord(T.IsBuiltIn, FIELD_TYPE_IS_BUILTIN);
524 emitRecord(T.IsTemplate, FIELD_TYPE_IS_TEMPLATE);
525}
526
528 StreamSubBlockGuard Block(Stream, BI_MEMBER_TYPE_BLOCK_ID);
529 emitBlock(T.Type, FieldId::F_type);
530 emitRecord(T.Name, MEMBER_TYPE_NAME);
531 emitRecord(T.Access, MEMBER_TYPE_ACCESS);
532 emitRecord(T.IsStatic, MEMBER_TYPE_IS_STATIC);
533 emitRecord(T.IsBuiltIn, MEMBER_TYPE_IS_BUILTIN);
534 emitRecord(T.IsTemplate, MEMBER_TYPE_IS_TEMPLATE);
535 emitRecord(T.IsTemplate, MEMBER_TYPE_IS_TEMPLATE);
536 for (const auto &CI : T.Description)
537 emitBlock(CI);
538}
539
541 StreamSubBlockGuard Block(Stream, BI_COMMENT_BLOCK_ID);
542 // Handle Kind (enum) separately, since it is not a string.
543 emitRecord(commentKindToString(I.Kind), COMMENT_KIND);
544 for (const auto &L : std::vector<std::pair<llvm::StringRef, RecordId>>{
545 {I.Text, COMMENT_TEXT},
546 {I.Name, COMMENT_NAME},
550 emitRecord(L.first, L.second);
551 emitRecord(I.SelfClosing, COMMENT_SELFCLOSING);
552 emitRecord(I.Explicit, COMMENT_EXPLICIT);
553 for (const auto &A : I.AttrKeys)
554 emitRecord(A, COMMENT_ATTRKEY);
555 for (const auto &A : I.AttrValues)
556 emitRecord(A, COMMENT_ATTRVAL);
557 for (const auto &A : I.Args)
558 emitRecord(A, COMMENT_ARG);
559 for (const auto &C : I.Children)
560 emitBlock(*C);
561}
562
564 StreamSubBlockGuard Block(Stream, BI_NAMESPACE_BLOCK_ID);
565 emitRecord(I.USR, NAMESPACE_USR);
566 emitRecord(I.Name, NAMESPACE_NAME);
567 emitRecord(I.Path, NAMESPACE_PATH);
568 for (const auto &N : I.Namespace)
570 for (const auto &CI : I.Description)
571 emitBlock(CI);
572 for (const auto &C : I.Children.Namespaces)
574 for (const auto &C : I.Children.Records)
576 for (const auto &C : I.Children.Functions)
577 emitBlock(C);
578 for (const auto &C : I.Children.Enums)
579 emitBlock(C);
580 for (const auto &C : I.Children.Typedefs)
581 emitBlock(C);
582 for (const auto &C : I.Children.Concepts)
583 emitBlock(C);
584 for (const auto &C : I.Children.Variables)
585 emitBlock(C);
586}
587
589 StreamSubBlockGuard Block(Stream, BI_ENUM_BLOCK_ID);
590 emitRecord(I.USR, ENUM_USR);
591 emitRecord(I.Name, ENUM_NAME);
592 for (const auto &N : I.Namespace)
594 for (const auto &CI : I.Description)
595 emitBlock(CI);
596 if (I.DefLoc)
597 emitRecord(*I.DefLoc, ENUM_DEFLOCATION);
598 for (const auto &L : I.Loc)
599 emitRecord(L, ENUM_LOCATION);
600 emitRecord(I.Scoped, ENUM_SCOPED);
601 if (I.BaseType)
603 for (const auto &N : I.Members)
604 emitBlock(N);
605}
606
608 StreamSubBlockGuard Block(Stream, BI_ENUM_VALUE_BLOCK_ID);
609 emitRecord(I.Name, ENUM_VALUE_NAME);
610 emitRecord(I.Value, ENUM_VALUE_VALUE);
611 emitRecord(I.ValueExpr, ENUM_VALUE_EXPR);
612 for (const auto &CI : I.Description)
613 emitBlock(CI);
614}
615
617 StreamSubBlockGuard Block(Stream, BI_RECORD_BLOCK_ID);
618 emitRecord(I.USR, RECORD_USR);
619 emitRecord(I.Name, RECORD_NAME);
620 emitRecord(I.Path, RECORD_PATH);
621 emitRecord(I.MangledName, RECORD_MANGLED_NAME);
622 for (const auto &N : I.Namespace)
624 for (const auto &CI : I.Description)
625 emitBlock(CI);
626 if (I.DefLoc)
627 emitRecord(*I.DefLoc, RECORD_DEFLOCATION);
628 for (const auto &L : I.Loc)
629 emitRecord(L, RECORD_LOCATION);
630 emitRecord(llvm::to_underlying(I.TagType), RECORD_TAG_TYPE);
631 emitRecord(I.IsTypeDef, RECORD_IS_TYPE_DEF);
632 for (const auto &N : I.Members)
633 emitBlock(N);
634 for (const auto &P : I.Parents)
636 for (const auto &P : I.VirtualParents)
638 for (const auto &PB : I.Bases)
639 emitBlock(PB);
640 for (const auto &C : I.Children.Records)
642 for (const auto &C : I.Children.Functions)
643 emitBlock(C);
644 for (const auto &C : I.Children.Enums)
645 emitBlock(C);
646 for (const auto &C : I.Children.Typedefs)
647 emitBlock(C);
648 if (I.Template)
650 for (const auto &C : I.Friends)
651 emitBlock(C);
652}
653
655 StreamSubBlockGuard Block(Stream, BI_BASE_RECORD_BLOCK_ID);
656 emitRecord(I.USR, BASE_RECORD_USR);
657 emitRecord(I.Name, BASE_RECORD_NAME);
658 emitRecord(I.Path, BASE_RECORD_PATH);
659 emitRecord(llvm::to_underlying(I.TagType), BASE_RECORD_TAG_TYPE);
660 emitRecord(I.IsVirtual, BASE_RECORD_IS_VIRTUAL);
661 emitRecord(I.Access, BASE_RECORD_ACCESS);
662 emitRecord(I.IsParent, BASE_RECORD_IS_PARENT);
663 for (const auto &M : I.Members)
664 emitBlock(M);
665 for (const auto &C : I.Children.Functions)
666 emitBlock(C);
667}
668
670 StreamSubBlockGuard Block(Stream, BI_FUNCTION_BLOCK_ID);
671 emitRecord(I.USR, FUNCTION_USR);
672 emitRecord(I.Name, FUNCTION_NAME);
673 for (const auto &N : I.Namespace)
675 for (const auto &CI : I.Description)
676 emitBlock(CI);
677 emitRecord(I.Access, FUNCTION_ACCESS);
678 emitRecord(I.IsMethod, FUNCTION_IS_METHOD);
679 emitRecord(I.IsStatic, FUNCTION_IS_STATIC);
680 if (I.DefLoc)
681 emitRecord(*I.DefLoc, FUNCTION_DEFLOCATION);
682 for (const auto &L : I.Loc)
683 emitRecord(L, FUNCTION_LOCATION);
686 for (const auto &N : I.Params)
687 emitBlock(N);
688 if (I.Template)
690}
691
693 StreamSubBlockGuard Block(Stream, BI_CONCEPT_BLOCK_ID);
694 emitRecord(I.USR, CONCEPT_USR);
695 emitRecord(I.Name, CONCEPT_NAME);
696 for (const auto &CI : I.Description)
697 emitBlock(CI);
698 emitRecord(I.IsType, CONCEPT_IS_TYPE);
701}
702
704 StreamSubBlockGuard Block(Stream, BI_TEMPLATE_BLOCK_ID);
705 for (const auto &P : T.Params)
706 emitBlock(P);
707 if (T.Specialization)
708 emitBlock(*T.Specialization);
709 for (const auto &C : T.Constraints)
710 emitBlock(C);
711}
712
714 StreamSubBlockGuard Block(Stream, BI_TEMPLATE_SPECIALIZATION_BLOCK_ID);
715 emitRecord(T.SpecializationOf, TEMPLATE_SPECIALIZATION_OF);
716 for (const auto &P : T.Params)
717 emitBlock(P);
718}
719
721 StreamSubBlockGuard Block(Stream, BI_TEMPLATE_PARAM_BLOCK_ID);
722 emitRecord(T.Contents, TEMPLATE_PARAM_CONTENTS);
723}
724
726 StreamSubBlockGuard Block(Stream, BI_CONSTRAINT_BLOCK_ID);
727 emitRecord(C.ConstraintExpr, CONSTRAINT_EXPRESSION);
728 emitBlock(C.ConceptRef, FieldId::F_concept);
729}
730
732 StreamSubBlockGuard Block(Stream, BI_VAR_BLOCK_ID);
733 emitRecord(I.USR, VAR_USR);
734 emitRecord(I.Name, VAR_NAME);
735 for (const auto &N : I.Namespace)
737 for (const auto &CI : I.Description)
738 emitBlock(CI);
739 if (I.DefLoc)
740 emitRecord(*I.DefLoc, VAR_DEFLOCATION);
741 emitRecord(I.IsStatic, VAR_IS_STATIC);
742 emitBlock(I.Type);
743}
744
746 switch (I->IT) {
748 emitBlock(*static_cast<clang::doc::NamespaceInfo *>(I));
749 break;
751 emitBlock(*static_cast<clang::doc::RecordInfo *>(I));
752 break;
754 emitBlock(*static_cast<clang::doc::EnumInfo *>(I));
755 break;
757 emitBlock(*static_cast<clang::doc::FunctionInfo *>(I));
758 break;
760 emitBlock(*static_cast<clang::doc::TypedefInfo *>(I));
761 break;
763 emitBlock(*static_cast<clang::doc::ConceptInfo *>(I));
764 break;
766 emitBlock(*static_cast<VarInfo *>(I));
767 break;
769 emitBlock(*static_cast<FriendInfo *>(I));
770 break;
772 llvm::errs() << "Unexpected info, unable to write.\n";
773 return true;
774 }
775 return false;
776}
777
778} // namespace doc
779} // 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