Bump version to 19.1.0git
[llvm-project.git] / clang-tools-extra / clang-doc / BitcodeWriter.cpp
blob7e5a11783d303a668584d622c23ea8e48a30cc2c
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 //===----------------------------------------------------------------------===//
9 #include "BitcodeWriter.h"
10 #include "llvm/ADT/IndexedMap.h"
11 #include <initializer_list>
13 namespace clang {
14 namespace doc {
16 // Empty SymbolID for comparison, so we don't have to construct one every time.
17 static const SymbolID EmptySID = SymbolID();
19 // Since id enums are not zero-indexed, we need to transform the given id into
20 // its associated index.
21 struct BlockIdToIndexFunctor {
22 using argument_type = unsigned;
23 unsigned operator()(unsigned ID) const { return ID - BI_FIRST; }
26 struct RecordIdToIndexFunctor {
27 using argument_type = unsigned;
28 unsigned operator()(unsigned ID) const { return ID - RI_FIRST; }
31 using AbbrevDsc = void (*)(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev);
33 static void AbbrevGen(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev,
34 const std::initializer_list<llvm::BitCodeAbbrevOp> Ops) {
35 for (const auto &Op : Ops)
36 Abbrev->Add(Op);
39 static void BoolAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
40 AbbrevGen(Abbrev,
41 {// 0. Boolean
42 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
43 BitCodeConstants::BoolSize)});
46 static void IntAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
47 AbbrevGen(Abbrev,
48 {// 0. Fixed-size integer
49 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
50 BitCodeConstants::IntSize)});
53 static void SymbolIDAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
54 AbbrevGen(Abbrev,
55 {// 0. Fixed-size integer (length of the sha1'd USR)
56 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
57 BitCodeConstants::USRLengthSize),
58 // 1. Fixed-size array of Char6 (USR)
59 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Array),
60 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
61 BitCodeConstants::USRBitLengthSize)});
64 static void StringAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
65 AbbrevGen(Abbrev,
66 {// 0. Fixed-size integer (length of the following string)
67 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
68 BitCodeConstants::StringLengthSize),
69 // 1. The string blob
70 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)});
73 // Assumes that the file will not have more than 65535 lines.
74 static void LocationAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
75 AbbrevGen(
76 Abbrev,
77 {// 0. Fixed-size integer (line number)
78 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
79 BitCodeConstants::LineNumberSize),
80 // 1. Boolean (IsFileInRootDir)
81 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
82 BitCodeConstants::BoolSize),
83 // 2. Fixed-size integer (length of the following string (filename))
84 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
85 BitCodeConstants::StringLengthSize),
86 // 3. The string blob
87 llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)});
90 struct RecordIdDsc {
91 llvm::StringRef Name;
92 AbbrevDsc Abbrev = nullptr;
94 RecordIdDsc() = default;
95 RecordIdDsc(llvm::StringRef Name, AbbrevDsc Abbrev)
96 : Name(Name), Abbrev(Abbrev) {}
98 // Is this 'description' valid?
99 operator bool() const {
100 return Abbrev != nullptr && Name.data() != nullptr && !Name.empty();
104 static const llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor>
105 BlockIdNameMap = []() {
106 llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor> BlockIdNameMap;
107 BlockIdNameMap.resize(BlockIdCount);
109 // There is no init-list constructor for the IndexedMap, so have to
110 // improvise
111 static const std::vector<std::pair<BlockId, const char *const>> Inits = {
112 {BI_VERSION_BLOCK_ID, "VersionBlock"},
113 {BI_NAMESPACE_BLOCK_ID, "NamespaceBlock"},
114 {BI_ENUM_BLOCK_ID, "EnumBlock"},
115 {BI_ENUM_VALUE_BLOCK_ID, "EnumValueBlock"},
116 {BI_TYPEDEF_BLOCK_ID, "TypedefBlock"},
117 {BI_TYPE_BLOCK_ID, "TypeBlock"},
118 {BI_FIELD_TYPE_BLOCK_ID, "FieldTypeBlock"},
119 {BI_MEMBER_TYPE_BLOCK_ID, "MemberTypeBlock"},
120 {BI_RECORD_BLOCK_ID, "RecordBlock"},
121 {BI_BASE_RECORD_BLOCK_ID, "BaseRecordBlock"},
122 {BI_FUNCTION_BLOCK_ID, "FunctionBlock"},
123 {BI_COMMENT_BLOCK_ID, "CommentBlock"},
124 {BI_REFERENCE_BLOCK_ID, "ReferenceBlock"},
125 {BI_TEMPLATE_BLOCK_ID, "TemplateBlock"},
126 {BI_TEMPLATE_SPECIALIZATION_BLOCK_ID, "TemplateSpecializationBlock"},
127 {BI_TEMPLATE_PARAM_BLOCK_ID, "TemplateParamBlock"}};
128 assert(Inits.size() == BlockIdCount);
129 for (const auto &Init : Inits)
130 BlockIdNameMap[Init.first] = Init.second;
131 assert(BlockIdNameMap.size() == BlockIdCount);
132 return BlockIdNameMap;
133 }();
135 static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor>
136 RecordIdNameMap = []() {
137 llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor> RecordIdNameMap;
138 RecordIdNameMap.resize(RecordIdCount);
140 // There is no init-list constructor for the IndexedMap, so have to
141 // improvise
142 static const std::vector<std::pair<RecordId, RecordIdDsc>> Inits = {
143 {VERSION, {"Version", &IntAbbrev}},
144 {COMMENT_KIND, {"Kind", &StringAbbrev}},
145 {COMMENT_TEXT, {"Text", &StringAbbrev}},
146 {COMMENT_NAME, {"Name", &StringAbbrev}},
147 {COMMENT_DIRECTION, {"Direction", &StringAbbrev}},
148 {COMMENT_PARAMNAME, {"ParamName", &StringAbbrev}},
149 {COMMENT_CLOSENAME, {"CloseName", &StringAbbrev}},
150 {COMMENT_SELFCLOSING, {"SelfClosing", &BoolAbbrev}},
151 {COMMENT_EXPLICIT, {"Explicit", &BoolAbbrev}},
152 {COMMENT_ATTRKEY, {"AttrKey", &StringAbbrev}},
153 {COMMENT_ATTRVAL, {"AttrVal", &StringAbbrev}},
154 {COMMENT_ARG, {"Arg", &StringAbbrev}},
155 {FIELD_TYPE_NAME, {"Name", &StringAbbrev}},
156 {FIELD_DEFAULT_VALUE, {"DefaultValue", &StringAbbrev}},
157 {MEMBER_TYPE_NAME, {"Name", &StringAbbrev}},
158 {MEMBER_TYPE_ACCESS, {"Access", &IntAbbrev}},
159 {NAMESPACE_USR, {"USR", &SymbolIDAbbrev}},
160 {NAMESPACE_NAME, {"Name", &StringAbbrev}},
161 {NAMESPACE_PATH, {"Path", &StringAbbrev}},
162 {ENUM_USR, {"USR", &SymbolIDAbbrev}},
163 {ENUM_NAME, {"Name", &StringAbbrev}},
164 {ENUM_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
165 {ENUM_LOCATION, {"Location", &LocationAbbrev}},
166 {ENUM_SCOPED, {"Scoped", &BoolAbbrev}},
167 {ENUM_VALUE_NAME, {"Name", &StringAbbrev}},
168 {ENUM_VALUE_VALUE, {"Value", &StringAbbrev}},
169 {ENUM_VALUE_EXPR, {"Expr", &StringAbbrev}},
170 {RECORD_USR, {"USR", &SymbolIDAbbrev}},
171 {RECORD_NAME, {"Name", &StringAbbrev}},
172 {RECORD_PATH, {"Path", &StringAbbrev}},
173 {RECORD_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
174 {RECORD_LOCATION, {"Location", &LocationAbbrev}},
175 {RECORD_TAG_TYPE, {"TagType", &IntAbbrev}},
176 {RECORD_IS_TYPE_DEF, {"IsTypeDef", &BoolAbbrev}},
177 {BASE_RECORD_USR, {"USR", &SymbolIDAbbrev}},
178 {BASE_RECORD_NAME, {"Name", &StringAbbrev}},
179 {BASE_RECORD_PATH, {"Path", &StringAbbrev}},
180 {BASE_RECORD_TAG_TYPE, {"TagType", &IntAbbrev}},
181 {BASE_RECORD_IS_VIRTUAL, {"IsVirtual", &BoolAbbrev}},
182 {BASE_RECORD_ACCESS, {"Access", &IntAbbrev}},
183 {BASE_RECORD_IS_PARENT, {"IsParent", &BoolAbbrev}},
184 {FUNCTION_USR, {"USR", &SymbolIDAbbrev}},
185 {FUNCTION_NAME, {"Name", &StringAbbrev}},
186 {FUNCTION_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
187 {FUNCTION_LOCATION, {"Location", &LocationAbbrev}},
188 {FUNCTION_ACCESS, {"Access", &IntAbbrev}},
189 {FUNCTION_IS_METHOD, {"IsMethod", &BoolAbbrev}},
190 {REFERENCE_USR, {"USR", &SymbolIDAbbrev}},
191 {REFERENCE_NAME, {"Name", &StringAbbrev}},
192 {REFERENCE_QUAL_NAME, {"QualName", &StringAbbrev}},
193 {REFERENCE_TYPE, {"RefType", &IntAbbrev}},
194 {REFERENCE_PATH, {"Path", &StringAbbrev}},
195 {REFERENCE_FIELD, {"Field", &IntAbbrev}},
196 {TEMPLATE_PARAM_CONTENTS, {"Contents", &StringAbbrev}},
197 {TEMPLATE_SPECIALIZATION_OF, {"SpecializationOf", &SymbolIDAbbrev}},
198 {TYPEDEF_USR, {"USR", &SymbolIDAbbrev}},
199 {TYPEDEF_NAME, {"Name", &StringAbbrev}},
200 {TYPEDEF_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
201 {TYPEDEF_IS_USING, {"IsUsing", &BoolAbbrev}}};
202 assert(Inits.size() == RecordIdCount);
203 for (const auto &Init : Inits) {
204 RecordIdNameMap[Init.first] = Init.second;
205 assert((Init.second.Name.size() + 1) <= BitCodeConstants::RecordSize);
207 assert(RecordIdNameMap.size() == RecordIdCount);
208 return RecordIdNameMap;
209 }();
211 static const std::vector<std::pair<BlockId, std::vector<RecordId>>>
212 RecordsByBlock{
213 // Version Block
214 {BI_VERSION_BLOCK_ID, {VERSION}},
215 // Comment Block
216 {BI_COMMENT_BLOCK_ID,
217 {COMMENT_KIND, COMMENT_TEXT, COMMENT_NAME, COMMENT_DIRECTION,
218 COMMENT_PARAMNAME, COMMENT_CLOSENAME, COMMENT_SELFCLOSING,
219 COMMENT_EXPLICIT, COMMENT_ATTRKEY, COMMENT_ATTRVAL, COMMENT_ARG}},
220 // Type Block
221 {BI_TYPE_BLOCK_ID, {}},
222 // FieldType Block
223 {BI_FIELD_TYPE_BLOCK_ID, {FIELD_TYPE_NAME, FIELD_DEFAULT_VALUE}},
224 // MemberType Block
225 {BI_MEMBER_TYPE_BLOCK_ID, {MEMBER_TYPE_NAME, MEMBER_TYPE_ACCESS}},
226 // Enum Block
227 {BI_ENUM_BLOCK_ID,
228 {ENUM_USR, ENUM_NAME, ENUM_DEFLOCATION, ENUM_LOCATION, ENUM_SCOPED}},
229 // Enum Value Block
230 {BI_ENUM_VALUE_BLOCK_ID,
231 {ENUM_VALUE_NAME, ENUM_VALUE_VALUE, ENUM_VALUE_EXPR}},
232 // Typedef Block
233 {BI_TYPEDEF_BLOCK_ID,
234 {TYPEDEF_USR, TYPEDEF_NAME, TYPEDEF_DEFLOCATION, TYPEDEF_IS_USING}},
235 // Namespace Block
236 {BI_NAMESPACE_BLOCK_ID,
237 {NAMESPACE_USR, NAMESPACE_NAME, NAMESPACE_PATH}},
238 // Record Block
239 {BI_RECORD_BLOCK_ID,
240 {RECORD_USR, RECORD_NAME, RECORD_PATH, RECORD_DEFLOCATION,
241 RECORD_LOCATION, RECORD_TAG_TYPE, RECORD_IS_TYPE_DEF}},
242 // BaseRecord Block
243 {BI_BASE_RECORD_BLOCK_ID,
244 {BASE_RECORD_USR, BASE_RECORD_NAME, BASE_RECORD_PATH,
245 BASE_RECORD_TAG_TYPE, BASE_RECORD_IS_VIRTUAL, BASE_RECORD_ACCESS,
246 BASE_RECORD_IS_PARENT}},
247 // Function Block
248 {BI_FUNCTION_BLOCK_ID,
249 {FUNCTION_USR, FUNCTION_NAME, FUNCTION_DEFLOCATION, FUNCTION_LOCATION,
250 FUNCTION_ACCESS, FUNCTION_IS_METHOD}},
251 // Reference Block
252 {BI_REFERENCE_BLOCK_ID,
253 {REFERENCE_USR, REFERENCE_NAME, REFERENCE_QUAL_NAME, REFERENCE_TYPE,
254 REFERENCE_PATH, REFERENCE_FIELD}},
255 // Template Blocks.
256 {BI_TEMPLATE_BLOCK_ID, {}},
257 {BI_TEMPLATE_PARAM_BLOCK_ID, {TEMPLATE_PARAM_CONTENTS}},
258 {BI_TEMPLATE_SPECIALIZATION_BLOCK_ID, {TEMPLATE_SPECIALIZATION_OF}}};
260 // AbbreviationMap
262 constexpr unsigned char BitCodeConstants::Signature[];
264 void ClangDocBitcodeWriter::AbbreviationMap::add(RecordId RID,
265 unsigned AbbrevID) {
266 assert(RecordIdNameMap[RID] && "Unknown RecordId.");
267 assert(!Abbrevs.contains(RID) && "Abbreviation already added.");
268 Abbrevs[RID] = AbbrevID;
271 unsigned ClangDocBitcodeWriter::AbbreviationMap::get(RecordId RID) const {
272 assert(RecordIdNameMap[RID] && "Unknown RecordId.");
273 assert(Abbrevs.contains(RID) && "Unknown abbreviation.");
274 return Abbrevs.lookup(RID);
277 // Validation and Overview Blocks
279 /// Emits the magic number header to check that its the right format,
280 /// in this case, 'DOCS'.
281 void ClangDocBitcodeWriter::emitHeader() {
282 for (char C : BitCodeConstants::Signature)
283 Stream.Emit((unsigned)C, BitCodeConstants::SignatureBitSize);
286 void ClangDocBitcodeWriter::emitVersionBlock() {
287 StreamSubBlockGuard Block(Stream, BI_VERSION_BLOCK_ID);
288 emitRecord(VersionNumber, VERSION);
291 /// Emits a block ID and the block name to the BLOCKINFO block.
292 void ClangDocBitcodeWriter::emitBlockID(BlockId BID) {
293 const auto &BlockIdName = BlockIdNameMap[BID];
294 assert(BlockIdName.data() && BlockIdName.size() && "Unknown BlockId.");
296 Record.clear();
297 Record.push_back(BID);
298 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
299 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,
300 ArrayRef<unsigned char>(BlockIdName.bytes_begin(),
301 BlockIdName.bytes_end()));
304 /// Emits a record name to the BLOCKINFO block.
305 void ClangDocBitcodeWriter::emitRecordID(RecordId ID) {
306 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
307 prepRecordData(ID);
308 Record.append(RecordIdNameMap[ID].Name.begin(),
309 RecordIdNameMap[ID].Name.end());
310 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
313 // Abbreviations
315 void ClangDocBitcodeWriter::emitAbbrev(RecordId ID, BlockId Block) {
316 assert(RecordIdNameMap[ID] && "Unknown abbreviation.");
317 auto Abbrev = std::make_shared<llvm::BitCodeAbbrev>();
318 Abbrev->Add(llvm::BitCodeAbbrevOp(ID));
319 RecordIdNameMap[ID].Abbrev(Abbrev);
320 Abbrevs.add(ID, Stream.EmitBlockInfoAbbrev(Block, std::move(Abbrev)));
323 // Records
325 void ClangDocBitcodeWriter::emitRecord(const SymbolID &Sym, RecordId ID) {
326 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
327 assert(RecordIdNameMap[ID].Abbrev == &SymbolIDAbbrev &&
328 "Abbrev type mismatch.");
329 if (!prepRecordData(ID, Sym != EmptySID))
330 return;
331 assert(Sym.size() == 20);
332 Record.push_back(Sym.size());
333 Record.append(Sym.begin(), Sym.end());
334 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
337 void ClangDocBitcodeWriter::emitRecord(llvm::StringRef Str, RecordId ID) {
338 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
339 assert(RecordIdNameMap[ID].Abbrev == &StringAbbrev &&
340 "Abbrev type mismatch.");
341 if (!prepRecordData(ID, !Str.empty()))
342 return;
343 assert(Str.size() < (1U << BitCodeConstants::StringLengthSize));
344 Record.push_back(Str.size());
345 Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Str);
348 void ClangDocBitcodeWriter::emitRecord(const Location &Loc, RecordId ID) {
349 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
350 assert(RecordIdNameMap[ID].Abbrev == &LocationAbbrev &&
351 "Abbrev type mismatch.");
352 if (!prepRecordData(ID, true))
353 return;
354 // FIXME: Assert that the line number is of the appropriate size.
355 Record.push_back(Loc.LineNumber);
356 assert(Loc.Filename.size() < (1U << BitCodeConstants::StringLengthSize));
357 Record.push_back(Loc.IsFileInRootDir);
358 Record.push_back(Loc.Filename.size());
359 Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Loc.Filename);
362 void ClangDocBitcodeWriter::emitRecord(bool Val, RecordId ID) {
363 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
364 assert(RecordIdNameMap[ID].Abbrev == &BoolAbbrev && "Abbrev type mismatch.");
365 if (!prepRecordData(ID, Val))
366 return;
367 Record.push_back(Val);
368 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
371 void ClangDocBitcodeWriter::emitRecord(int Val, RecordId ID) {
372 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
373 assert(RecordIdNameMap[ID].Abbrev == &IntAbbrev && "Abbrev type mismatch.");
374 if (!prepRecordData(ID, Val))
375 return;
376 // FIXME: Assert that the integer is of the appropriate size.
377 Record.push_back(Val);
378 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
381 void ClangDocBitcodeWriter::emitRecord(unsigned Val, RecordId ID) {
382 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
383 assert(RecordIdNameMap[ID].Abbrev == &IntAbbrev && "Abbrev type mismatch.");
384 if (!prepRecordData(ID, Val))
385 return;
386 assert(Val < (1U << BitCodeConstants::IntSize));
387 Record.push_back(Val);
388 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
391 void ClangDocBitcodeWriter::emitRecord(const TemplateInfo &Templ) {}
393 bool ClangDocBitcodeWriter::prepRecordData(RecordId ID, bool ShouldEmit) {
394 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
395 if (!ShouldEmit)
396 return false;
397 Record.clear();
398 Record.push_back(ID);
399 return true;
402 // BlockInfo Block
404 void ClangDocBitcodeWriter::emitBlockInfoBlock() {
405 Stream.EnterBlockInfoBlock();
406 for (const auto &Block : RecordsByBlock) {
407 assert(Block.second.size() < (1U << BitCodeConstants::SubblockIDSize));
408 emitBlockInfo(Block.first, Block.second);
410 Stream.ExitBlock();
413 void ClangDocBitcodeWriter::emitBlockInfo(BlockId BID,
414 const std::vector<RecordId> &RIDs) {
415 assert(RIDs.size() < (1U << BitCodeConstants::SubblockIDSize));
416 emitBlockID(BID);
417 for (RecordId RID : RIDs) {
418 emitRecordID(RID);
419 emitAbbrev(RID, BID);
423 // Block emission
425 void ClangDocBitcodeWriter::emitBlock(const Reference &R, FieldId Field) {
426 if (R.USR == EmptySID && R.Name.empty())
427 return;
428 StreamSubBlockGuard Block(Stream, BI_REFERENCE_BLOCK_ID);
429 emitRecord(R.USR, REFERENCE_USR);
430 emitRecord(R.Name, REFERENCE_NAME);
431 emitRecord(R.QualName, REFERENCE_QUAL_NAME);
432 emitRecord((unsigned)R.RefType, REFERENCE_TYPE);
433 emitRecord(R.Path, REFERENCE_PATH);
434 emitRecord((unsigned)Field, REFERENCE_FIELD);
437 void ClangDocBitcodeWriter::emitBlock(const TypeInfo &T) {
438 StreamSubBlockGuard Block(Stream, BI_TYPE_BLOCK_ID);
439 emitBlock(T.Type, FieldId::F_type);
442 void ClangDocBitcodeWriter::emitBlock(const TypedefInfo &T) {
443 StreamSubBlockGuard Block(Stream, BI_TYPEDEF_BLOCK_ID);
444 emitRecord(T.USR, TYPEDEF_USR);
445 emitRecord(T.Name, TYPEDEF_NAME);
446 for (const auto &N : T.Namespace)
447 emitBlock(N, FieldId::F_namespace);
448 for (const auto &CI : T.Description)
449 emitBlock(CI);
450 if (T.DefLoc)
451 emitRecord(*T.DefLoc, TYPEDEF_DEFLOCATION);
452 emitRecord(T.IsUsing, TYPEDEF_IS_USING);
453 emitBlock(T.Underlying);
456 void ClangDocBitcodeWriter::emitBlock(const FieldTypeInfo &T) {
457 StreamSubBlockGuard Block(Stream, BI_FIELD_TYPE_BLOCK_ID);
458 emitBlock(T.Type, FieldId::F_type);
459 emitRecord(T.Name, FIELD_TYPE_NAME);
460 emitRecord(T.DefaultValue, FIELD_DEFAULT_VALUE);
463 void ClangDocBitcodeWriter::emitBlock(const MemberTypeInfo &T) {
464 StreamSubBlockGuard Block(Stream, BI_MEMBER_TYPE_BLOCK_ID);
465 emitBlock(T.Type, FieldId::F_type);
466 emitRecord(T.Name, MEMBER_TYPE_NAME);
467 emitRecord(T.Access, MEMBER_TYPE_ACCESS);
468 for (const auto &CI : T.Description)
469 emitBlock(CI);
472 void ClangDocBitcodeWriter::emitBlock(const CommentInfo &I) {
473 StreamSubBlockGuard Block(Stream, BI_COMMENT_BLOCK_ID);
474 for (const auto &L : std::vector<std::pair<llvm::StringRef, RecordId>>{
475 {I.Kind, COMMENT_KIND},
476 {I.Text, COMMENT_TEXT},
477 {I.Name, COMMENT_NAME},
478 {I.Direction, COMMENT_DIRECTION},
479 {I.ParamName, COMMENT_PARAMNAME},
480 {I.CloseName, COMMENT_CLOSENAME}})
481 emitRecord(L.first, L.second);
482 emitRecord(I.SelfClosing, COMMENT_SELFCLOSING);
483 emitRecord(I.Explicit, COMMENT_EXPLICIT);
484 for (const auto &A : I.AttrKeys)
485 emitRecord(A, COMMENT_ATTRKEY);
486 for (const auto &A : I.AttrValues)
487 emitRecord(A, COMMENT_ATTRVAL);
488 for (const auto &A : I.Args)
489 emitRecord(A, COMMENT_ARG);
490 for (const auto &C : I.Children)
491 emitBlock(*C);
494 void ClangDocBitcodeWriter::emitBlock(const NamespaceInfo &I) {
495 StreamSubBlockGuard Block(Stream, BI_NAMESPACE_BLOCK_ID);
496 emitRecord(I.USR, NAMESPACE_USR);
497 emitRecord(I.Name, NAMESPACE_NAME);
498 emitRecord(I.Path, NAMESPACE_PATH);
499 for (const auto &N : I.Namespace)
500 emitBlock(N, FieldId::F_namespace);
501 for (const auto &CI : I.Description)
502 emitBlock(CI);
503 for (const auto &C : I.Children.Namespaces)
504 emitBlock(C, FieldId::F_child_namespace);
505 for (const auto &C : I.Children.Records)
506 emitBlock(C, FieldId::F_child_record);
507 for (const auto &C : I.Children.Functions)
508 emitBlock(C);
509 for (const auto &C : I.Children.Enums)
510 emitBlock(C);
511 for (const auto &C : I.Children.Typedefs)
512 emitBlock(C);
515 void ClangDocBitcodeWriter::emitBlock(const EnumInfo &I) {
516 StreamSubBlockGuard Block(Stream, BI_ENUM_BLOCK_ID);
517 emitRecord(I.USR, ENUM_USR);
518 emitRecord(I.Name, ENUM_NAME);
519 for (const auto &N : I.Namespace)
520 emitBlock(N, FieldId::F_namespace);
521 for (const auto &CI : I.Description)
522 emitBlock(CI);
523 if (I.DefLoc)
524 emitRecord(*I.DefLoc, ENUM_DEFLOCATION);
525 for (const auto &L : I.Loc)
526 emitRecord(L, ENUM_LOCATION);
527 emitRecord(I.Scoped, ENUM_SCOPED);
528 if (I.BaseType)
529 emitBlock(*I.BaseType);
530 for (const auto &N : I.Members)
531 emitBlock(N);
534 void ClangDocBitcodeWriter::emitBlock(const EnumValueInfo &I) {
535 StreamSubBlockGuard Block(Stream, BI_ENUM_VALUE_BLOCK_ID);
536 emitRecord(I.Name, ENUM_VALUE_NAME);
537 emitRecord(I.Value, ENUM_VALUE_VALUE);
538 emitRecord(I.ValueExpr, ENUM_VALUE_EXPR);
541 void ClangDocBitcodeWriter::emitBlock(const RecordInfo &I) {
542 StreamSubBlockGuard Block(Stream, BI_RECORD_BLOCK_ID);
543 emitRecord(I.USR, RECORD_USR);
544 emitRecord(I.Name, RECORD_NAME);
545 emitRecord(I.Path, RECORD_PATH);
546 for (const auto &N : I.Namespace)
547 emitBlock(N, FieldId::F_namespace);
548 for (const auto &CI : I.Description)
549 emitBlock(CI);
550 if (I.DefLoc)
551 emitRecord(*I.DefLoc, RECORD_DEFLOCATION);
552 for (const auto &L : I.Loc)
553 emitRecord(L, RECORD_LOCATION);
554 emitRecord(llvm::to_underlying(I.TagType), RECORD_TAG_TYPE);
555 emitRecord(I.IsTypeDef, RECORD_IS_TYPE_DEF);
556 for (const auto &N : I.Members)
557 emitBlock(N);
558 for (const auto &P : I.Parents)
559 emitBlock(P, FieldId::F_parent);
560 for (const auto &P : I.VirtualParents)
561 emitBlock(P, FieldId::F_vparent);
562 for (const auto &PB : I.Bases)
563 emitBlock(PB);
564 for (const auto &C : I.Children.Records)
565 emitBlock(C, FieldId::F_child_record);
566 for (const auto &C : I.Children.Functions)
567 emitBlock(C);
568 for (const auto &C : I.Children.Enums)
569 emitBlock(C);
570 for (const auto &C : I.Children.Typedefs)
571 emitBlock(C);
572 if (I.Template)
573 emitBlock(*I.Template);
576 void ClangDocBitcodeWriter::emitBlock(const BaseRecordInfo &I) {
577 StreamSubBlockGuard Block(Stream, BI_BASE_RECORD_BLOCK_ID);
578 emitRecord(I.USR, BASE_RECORD_USR);
579 emitRecord(I.Name, BASE_RECORD_NAME);
580 emitRecord(I.Path, BASE_RECORD_PATH);
581 emitRecord(llvm::to_underlying(I.TagType), BASE_RECORD_TAG_TYPE);
582 emitRecord(I.IsVirtual, BASE_RECORD_IS_VIRTUAL);
583 emitRecord(I.Access, BASE_RECORD_ACCESS);
584 emitRecord(I.IsParent, BASE_RECORD_IS_PARENT);
585 for (const auto &M : I.Members)
586 emitBlock(M);
587 for (const auto &C : I.Children.Functions)
588 emitBlock(C);
591 void ClangDocBitcodeWriter::emitBlock(const FunctionInfo &I) {
592 StreamSubBlockGuard Block(Stream, BI_FUNCTION_BLOCK_ID);
593 emitRecord(I.USR, FUNCTION_USR);
594 emitRecord(I.Name, FUNCTION_NAME);
595 for (const auto &N : I.Namespace)
596 emitBlock(N, FieldId::F_namespace);
597 for (const auto &CI : I.Description)
598 emitBlock(CI);
599 emitRecord(I.Access, FUNCTION_ACCESS);
600 emitRecord(I.IsMethod, FUNCTION_IS_METHOD);
601 if (I.DefLoc)
602 emitRecord(*I.DefLoc, FUNCTION_DEFLOCATION);
603 for (const auto &L : I.Loc)
604 emitRecord(L, FUNCTION_LOCATION);
605 emitBlock(I.Parent, FieldId::F_parent);
606 emitBlock(I.ReturnType);
607 for (const auto &N : I.Params)
608 emitBlock(N);
609 if (I.Template)
610 emitBlock(*I.Template);
613 void ClangDocBitcodeWriter::emitBlock(const TemplateInfo &T) {
614 StreamSubBlockGuard Block(Stream, BI_TEMPLATE_BLOCK_ID);
615 for (const auto &P : T.Params)
616 emitBlock(P);
617 if (T.Specialization)
618 emitBlock(*T.Specialization);
621 void ClangDocBitcodeWriter::emitBlock(const TemplateSpecializationInfo &T) {
622 StreamSubBlockGuard Block(Stream, BI_TEMPLATE_SPECIALIZATION_BLOCK_ID);
623 emitRecord(T.SpecializationOf, TEMPLATE_SPECIALIZATION_OF);
624 for (const auto &P : T.Params)
625 emitBlock(P);
628 void ClangDocBitcodeWriter::emitBlock(const TemplateParamInfo &T) {
629 StreamSubBlockGuard Block(Stream, BI_TEMPLATE_PARAM_BLOCK_ID);
630 emitRecord(T.Contents, TEMPLATE_PARAM_CONTENTS);
633 bool ClangDocBitcodeWriter::dispatchInfoForWrite(Info *I) {
634 switch (I->IT) {
635 case InfoType::IT_namespace:
636 emitBlock(*static_cast<clang::doc::NamespaceInfo *>(I));
637 break;
638 case InfoType::IT_record:
639 emitBlock(*static_cast<clang::doc::RecordInfo *>(I));
640 break;
641 case InfoType::IT_enum:
642 emitBlock(*static_cast<clang::doc::EnumInfo *>(I));
643 break;
644 case InfoType::IT_function:
645 emitBlock(*static_cast<clang::doc::FunctionInfo *>(I));
646 break;
647 case InfoType::IT_typedef:
648 emitBlock(*static_cast<clang::doc::TypedefInfo *>(I));
649 break;
650 default:
651 llvm::errs() << "Unexpected info, unable to write.\n";
652 return true;
654 return false;
657 } // namespace doc
658 } // namespace clang