[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / clang-tools-extra / clang-doc / BitcodeWriter.cpp
blob3daeb8076c42f05324aeff3318cfe3ae400b8218
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_TYPE_BLOCK_ID, "TypeBlock"},
116 {BI_FIELD_TYPE_BLOCK_ID, "FieldTypeBlock"},
117 {BI_MEMBER_TYPE_BLOCK_ID, "MemberTypeBlock"},
118 {BI_RECORD_BLOCK_ID, "RecordBlock"},
119 {BI_BASE_RECORD_BLOCK_ID, "BaseRecordBlock"},
120 {BI_FUNCTION_BLOCK_ID, "FunctionBlock"},
121 {BI_COMMENT_BLOCK_ID, "CommentBlock"},
122 {BI_REFERENCE_BLOCK_ID, "ReferenceBlock"}};
123 assert(Inits.size() == BlockIdCount);
124 for (const auto &Init : Inits)
125 BlockIdNameMap[Init.first] = Init.second;
126 assert(BlockIdNameMap.size() == BlockIdCount);
127 return BlockIdNameMap;
128 }();
130 static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor>
131 RecordIdNameMap = []() {
132 llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor> RecordIdNameMap;
133 RecordIdNameMap.resize(RecordIdCount);
135 // There is no init-list constructor for the IndexedMap, so have to
136 // improvise
137 static const std::vector<std::pair<RecordId, RecordIdDsc>> Inits = {
138 {VERSION, {"Version", &IntAbbrev}},
139 {COMMENT_KIND, {"Kind", &StringAbbrev}},
140 {COMMENT_TEXT, {"Text", &StringAbbrev}},
141 {COMMENT_NAME, {"Name", &StringAbbrev}},
142 {COMMENT_DIRECTION, {"Direction", &StringAbbrev}},
143 {COMMENT_PARAMNAME, {"ParamName", &StringAbbrev}},
144 {COMMENT_CLOSENAME, {"CloseName", &StringAbbrev}},
145 {COMMENT_SELFCLOSING, {"SelfClosing", &BoolAbbrev}},
146 {COMMENT_EXPLICIT, {"Explicit", &BoolAbbrev}},
147 {COMMENT_ATTRKEY, {"AttrKey", &StringAbbrev}},
148 {COMMENT_ATTRVAL, {"AttrVal", &StringAbbrev}},
149 {COMMENT_ARG, {"Arg", &StringAbbrev}},
150 {FIELD_TYPE_NAME, {"Name", &StringAbbrev}},
151 {MEMBER_TYPE_NAME, {"Name", &StringAbbrev}},
152 {MEMBER_TYPE_ACCESS, {"Access", &IntAbbrev}},
153 {NAMESPACE_USR, {"USR", &SymbolIDAbbrev}},
154 {NAMESPACE_NAME, {"Name", &StringAbbrev}},
155 {NAMESPACE_PATH, {"Path", &StringAbbrev}},
156 {ENUM_USR, {"USR", &SymbolIDAbbrev}},
157 {ENUM_NAME, {"Name", &StringAbbrev}},
158 {ENUM_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
159 {ENUM_LOCATION, {"Location", &LocationAbbrev}},
160 {ENUM_MEMBER, {"Member", &StringAbbrev}},
161 {ENUM_SCOPED, {"Scoped", &BoolAbbrev}},
162 {RECORD_USR, {"USR", &SymbolIDAbbrev}},
163 {RECORD_NAME, {"Name", &StringAbbrev}},
164 {RECORD_PATH, {"Path", &StringAbbrev}},
165 {RECORD_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
166 {RECORD_LOCATION, {"Location", &LocationAbbrev}},
167 {RECORD_TAG_TYPE, {"TagType", &IntAbbrev}},
168 {RECORD_IS_TYPE_DEF, {"IsTypeDef", &BoolAbbrev}},
169 {BASE_RECORD_USR, {"USR", &SymbolIDAbbrev}},
170 {BASE_RECORD_NAME, {"Name", &StringAbbrev}},
171 {BASE_RECORD_PATH, {"Path", &StringAbbrev}},
172 {BASE_RECORD_TAG_TYPE, {"TagType", &IntAbbrev}},
173 {BASE_RECORD_IS_VIRTUAL, {"IsVirtual", &BoolAbbrev}},
174 {BASE_RECORD_ACCESS, {"Access", &IntAbbrev}},
175 {BASE_RECORD_IS_PARENT, {"IsParent", &BoolAbbrev}},
176 {FUNCTION_USR, {"USR", &SymbolIDAbbrev}},
177 {FUNCTION_NAME, {"Name", &StringAbbrev}},
178 {FUNCTION_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
179 {FUNCTION_LOCATION, {"Location", &LocationAbbrev}},
180 {FUNCTION_ACCESS, {"Access", &IntAbbrev}},
181 {FUNCTION_IS_METHOD, {"IsMethod", &BoolAbbrev}},
182 {REFERENCE_USR, {"USR", &SymbolIDAbbrev}},
183 {REFERENCE_NAME, {"Name", &StringAbbrev}},
184 {REFERENCE_TYPE, {"RefType", &IntAbbrev}},
185 {REFERENCE_PATH, {"Path", &StringAbbrev}},
186 {REFERENCE_IS_IN_GLOBAL_NAMESPACE,
187 {"IsInGlobalNamespace", &BoolAbbrev}},
188 {REFERENCE_FIELD, {"Field", &IntAbbrev}}};
189 assert(Inits.size() == RecordIdCount);
190 for (const auto &Init : Inits) {
191 RecordIdNameMap[Init.first] = Init.second;
192 assert((Init.second.Name.size() + 1) <= BitCodeConstants::RecordSize);
194 assert(RecordIdNameMap.size() == RecordIdCount);
195 return RecordIdNameMap;
196 }();
198 static const std::vector<std::pair<BlockId, std::vector<RecordId>>>
199 RecordsByBlock{
200 // Version Block
201 {BI_VERSION_BLOCK_ID, {VERSION}},
202 // Comment Block
203 {BI_COMMENT_BLOCK_ID,
204 {COMMENT_KIND, COMMENT_TEXT, COMMENT_NAME, COMMENT_DIRECTION,
205 COMMENT_PARAMNAME, COMMENT_CLOSENAME, COMMENT_SELFCLOSING,
206 COMMENT_EXPLICIT, COMMENT_ATTRKEY, COMMENT_ATTRVAL, COMMENT_ARG}},
207 // Type Block
208 {BI_TYPE_BLOCK_ID, {}},
209 // FieldType Block
210 {BI_FIELD_TYPE_BLOCK_ID, {FIELD_TYPE_NAME}},
211 // MemberType Block
212 {BI_MEMBER_TYPE_BLOCK_ID, {MEMBER_TYPE_NAME, MEMBER_TYPE_ACCESS}},
213 // Enum Block
214 {BI_ENUM_BLOCK_ID,
215 {ENUM_USR, ENUM_NAME, ENUM_DEFLOCATION, ENUM_LOCATION, ENUM_MEMBER,
216 ENUM_SCOPED}},
217 // Namespace Block
218 {BI_NAMESPACE_BLOCK_ID,
219 {NAMESPACE_USR, NAMESPACE_NAME, NAMESPACE_PATH}},
220 // Record Block
221 {BI_RECORD_BLOCK_ID,
222 {RECORD_USR, RECORD_NAME, RECORD_PATH, RECORD_DEFLOCATION,
223 RECORD_LOCATION, RECORD_TAG_TYPE, RECORD_IS_TYPE_DEF}},
224 // BaseRecord Block
225 {BI_BASE_RECORD_BLOCK_ID,
226 {BASE_RECORD_USR, BASE_RECORD_NAME, BASE_RECORD_PATH,
227 BASE_RECORD_TAG_TYPE, BASE_RECORD_IS_VIRTUAL, BASE_RECORD_ACCESS,
228 BASE_RECORD_IS_PARENT}},
229 // Function Block
230 {BI_FUNCTION_BLOCK_ID,
231 {FUNCTION_USR, FUNCTION_NAME, FUNCTION_DEFLOCATION, FUNCTION_LOCATION,
232 FUNCTION_ACCESS, FUNCTION_IS_METHOD}},
233 // Reference Block
234 {BI_REFERENCE_BLOCK_ID,
235 {REFERENCE_USR, REFERENCE_NAME, REFERENCE_TYPE, REFERENCE_PATH,
236 REFERENCE_IS_IN_GLOBAL_NAMESPACE, REFERENCE_FIELD}}};
238 // AbbreviationMap
240 constexpr unsigned char BitCodeConstants::Signature[];
242 void ClangDocBitcodeWriter::AbbreviationMap::add(RecordId RID,
243 unsigned AbbrevID) {
244 assert(RecordIdNameMap[RID] && "Unknown RecordId.");
245 assert(Abbrevs.find(RID) == Abbrevs.end() && "Abbreviation already added.");
246 Abbrevs[RID] = AbbrevID;
249 unsigned ClangDocBitcodeWriter::AbbreviationMap::get(RecordId RID) const {
250 assert(RecordIdNameMap[RID] && "Unknown RecordId.");
251 assert(Abbrevs.find(RID) != Abbrevs.end() && "Unknown abbreviation.");
252 return Abbrevs.lookup(RID);
255 // Validation and Overview Blocks
257 /// Emits the magic number header to check that its the right format,
258 /// in this case, 'DOCS'.
259 void ClangDocBitcodeWriter::emitHeader() {
260 for (char C : BitCodeConstants::Signature)
261 Stream.Emit((unsigned)C, BitCodeConstants::SignatureBitSize);
264 void ClangDocBitcodeWriter::emitVersionBlock() {
265 StreamSubBlockGuard Block(Stream, BI_VERSION_BLOCK_ID);
266 emitRecord(VersionNumber, VERSION);
269 /// Emits a block ID and the block name to the BLOCKINFO block.
270 void ClangDocBitcodeWriter::emitBlockID(BlockId BID) {
271 const auto &BlockIdName = BlockIdNameMap[BID];
272 assert(BlockIdName.data() && BlockIdName.size() && "Unknown BlockId.");
274 Record.clear();
275 Record.push_back(BID);
276 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
277 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,
278 ArrayRef<unsigned char>(BlockIdName.bytes_begin(),
279 BlockIdName.bytes_end()));
282 /// Emits a record name to the BLOCKINFO block.
283 void ClangDocBitcodeWriter::emitRecordID(RecordId ID) {
284 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
285 prepRecordData(ID);
286 Record.append(RecordIdNameMap[ID].Name.begin(),
287 RecordIdNameMap[ID].Name.end());
288 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
291 // Abbreviations
293 void ClangDocBitcodeWriter::emitAbbrev(RecordId ID, BlockId Block) {
294 assert(RecordIdNameMap[ID] && "Unknown abbreviation.");
295 auto Abbrev = std::make_shared<llvm::BitCodeAbbrev>();
296 Abbrev->Add(llvm::BitCodeAbbrevOp(ID));
297 RecordIdNameMap[ID].Abbrev(Abbrev);
298 Abbrevs.add(ID, Stream.EmitBlockInfoAbbrev(Block, std::move(Abbrev)));
301 // Records
303 void ClangDocBitcodeWriter::emitRecord(const SymbolID &Sym, RecordId ID) {
304 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
305 assert(RecordIdNameMap[ID].Abbrev == &SymbolIDAbbrev &&
306 "Abbrev type mismatch.");
307 if (!prepRecordData(ID, Sym != EmptySID))
308 return;
309 assert(Sym.size() == 20);
310 Record.push_back(Sym.size());
311 Record.append(Sym.begin(), Sym.end());
312 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
315 void ClangDocBitcodeWriter::emitRecord(llvm::StringRef Str, RecordId ID) {
316 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
317 assert(RecordIdNameMap[ID].Abbrev == &StringAbbrev &&
318 "Abbrev type mismatch.");
319 if (!prepRecordData(ID, !Str.empty()))
320 return;
321 assert(Str.size() < (1U << BitCodeConstants::StringLengthSize));
322 Record.push_back(Str.size());
323 Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Str);
326 void ClangDocBitcodeWriter::emitRecord(const Location &Loc, RecordId ID) {
327 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
328 assert(RecordIdNameMap[ID].Abbrev == &LocationAbbrev &&
329 "Abbrev type mismatch.");
330 if (!prepRecordData(ID, true))
331 return;
332 // FIXME: Assert that the line number is of the appropriate size.
333 Record.push_back(Loc.LineNumber);
334 assert(Loc.Filename.size() < (1U << BitCodeConstants::StringLengthSize));
335 Record.push_back(Loc.IsFileInRootDir);
336 Record.push_back(Loc.Filename.size());
337 Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Loc.Filename);
340 void ClangDocBitcodeWriter::emitRecord(bool Val, RecordId ID) {
341 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
342 assert(RecordIdNameMap[ID].Abbrev == &BoolAbbrev && "Abbrev type mismatch.");
343 if (!prepRecordData(ID, Val))
344 return;
345 Record.push_back(Val);
346 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
349 void ClangDocBitcodeWriter::emitRecord(int Val, RecordId ID) {
350 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
351 assert(RecordIdNameMap[ID].Abbrev == &IntAbbrev && "Abbrev type mismatch.");
352 if (!prepRecordData(ID, Val))
353 return;
354 // FIXME: Assert that the integer is of the appropriate size.
355 Record.push_back(Val);
356 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
359 void ClangDocBitcodeWriter::emitRecord(unsigned Val, RecordId ID) {
360 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
361 assert(RecordIdNameMap[ID].Abbrev == &IntAbbrev && "Abbrev type mismatch.");
362 if (!prepRecordData(ID, Val))
363 return;
364 assert(Val < (1U << BitCodeConstants::IntSize));
365 Record.push_back(Val);
366 Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
369 bool ClangDocBitcodeWriter::prepRecordData(RecordId ID, bool ShouldEmit) {
370 assert(RecordIdNameMap[ID] && "Unknown RecordId.");
371 if (!ShouldEmit)
372 return false;
373 Record.clear();
374 Record.push_back(ID);
375 return true;
378 // BlockInfo Block
380 void ClangDocBitcodeWriter::emitBlockInfoBlock() {
381 Stream.EnterBlockInfoBlock();
382 for (const auto &Block : RecordsByBlock) {
383 assert(Block.second.size() < (1U << BitCodeConstants::SubblockIDSize));
384 emitBlockInfo(Block.first, Block.second);
386 Stream.ExitBlock();
389 void ClangDocBitcodeWriter::emitBlockInfo(BlockId BID,
390 const std::vector<RecordId> &RIDs) {
391 assert(RIDs.size() < (1U << BitCodeConstants::SubblockIDSize));
392 emitBlockID(BID);
393 for (RecordId RID : RIDs) {
394 emitRecordID(RID);
395 emitAbbrev(RID, BID);
399 // Block emission
401 void ClangDocBitcodeWriter::emitBlock(const Reference &R, FieldId Field) {
402 if (R.USR == EmptySID && R.Name.empty())
403 return;
404 StreamSubBlockGuard Block(Stream, BI_REFERENCE_BLOCK_ID);
405 emitRecord(R.USR, REFERENCE_USR);
406 emitRecord(R.Name, REFERENCE_NAME);
407 emitRecord((unsigned)R.RefType, REFERENCE_TYPE);
408 emitRecord(R.Path, REFERENCE_PATH);
409 emitRecord(R.IsInGlobalNamespace, REFERENCE_IS_IN_GLOBAL_NAMESPACE);
410 emitRecord((unsigned)Field, REFERENCE_FIELD);
413 void ClangDocBitcodeWriter::emitBlock(const TypeInfo &T) {
414 StreamSubBlockGuard Block(Stream, BI_TYPE_BLOCK_ID);
415 emitBlock(T.Type, FieldId::F_type);
418 void ClangDocBitcodeWriter::emitBlock(const FieldTypeInfo &T) {
419 StreamSubBlockGuard Block(Stream, BI_FIELD_TYPE_BLOCK_ID);
420 emitBlock(T.Type, FieldId::F_type);
421 emitRecord(T.Name, FIELD_TYPE_NAME);
424 void ClangDocBitcodeWriter::emitBlock(const MemberTypeInfo &T) {
425 StreamSubBlockGuard Block(Stream, BI_MEMBER_TYPE_BLOCK_ID);
426 emitBlock(T.Type, FieldId::F_type);
427 emitRecord(T.Name, MEMBER_TYPE_NAME);
428 emitRecord(T.Access, MEMBER_TYPE_ACCESS);
429 for (const auto &CI : T.Description)
430 emitBlock(CI);
433 void ClangDocBitcodeWriter::emitBlock(const CommentInfo &I) {
434 StreamSubBlockGuard Block(Stream, BI_COMMENT_BLOCK_ID);
435 for (const auto &L : std::vector<std::pair<llvm::StringRef, RecordId>>{
436 {I.Kind, COMMENT_KIND},
437 {I.Text, COMMENT_TEXT},
438 {I.Name, COMMENT_NAME},
439 {I.Direction, COMMENT_DIRECTION},
440 {I.ParamName, COMMENT_PARAMNAME},
441 {I.CloseName, COMMENT_CLOSENAME}})
442 emitRecord(L.first, L.second);
443 emitRecord(I.SelfClosing, COMMENT_SELFCLOSING);
444 emitRecord(I.Explicit, COMMENT_EXPLICIT);
445 for (const auto &A : I.AttrKeys)
446 emitRecord(A, COMMENT_ATTRKEY);
447 for (const auto &A : I.AttrValues)
448 emitRecord(A, COMMENT_ATTRVAL);
449 for (const auto &A : I.Args)
450 emitRecord(A, COMMENT_ARG);
451 for (const auto &C : I.Children)
452 emitBlock(*C);
455 void ClangDocBitcodeWriter::emitBlock(const NamespaceInfo &I) {
456 StreamSubBlockGuard Block(Stream, BI_NAMESPACE_BLOCK_ID);
457 emitRecord(I.USR, NAMESPACE_USR);
458 emitRecord(I.Name, NAMESPACE_NAME);
459 emitRecord(I.Path, NAMESPACE_PATH);
460 for (const auto &N : I.Namespace)
461 emitBlock(N, FieldId::F_namespace);
462 for (const auto &CI : I.Description)
463 emitBlock(CI);
464 for (const auto &C : I.ChildNamespaces)
465 emitBlock(C, FieldId::F_child_namespace);
466 for (const auto &C : I.ChildRecords)
467 emitBlock(C, FieldId::F_child_record);
468 for (const auto &C : I.ChildFunctions)
469 emitBlock(C);
470 for (const auto &C : I.ChildEnums)
471 emitBlock(C);
474 void ClangDocBitcodeWriter::emitBlock(const EnumInfo &I) {
475 StreamSubBlockGuard Block(Stream, BI_ENUM_BLOCK_ID);
476 emitRecord(I.USR, ENUM_USR);
477 emitRecord(I.Name, ENUM_NAME);
478 for (const auto &N : I.Namespace)
479 emitBlock(N, FieldId::F_namespace);
480 for (const auto &CI : I.Description)
481 emitBlock(CI);
482 if (I.DefLoc)
483 emitRecord(*I.DefLoc, ENUM_DEFLOCATION);
484 for (const auto &L : I.Loc)
485 emitRecord(L, ENUM_LOCATION);
486 emitRecord(I.Scoped, ENUM_SCOPED);
487 for (const auto &N : I.Members)
488 emitRecord(N, ENUM_MEMBER);
491 void ClangDocBitcodeWriter::emitBlock(const RecordInfo &I) {
492 StreamSubBlockGuard Block(Stream, BI_RECORD_BLOCK_ID);
493 emitRecord(I.USR, RECORD_USR);
494 emitRecord(I.Name, RECORD_NAME);
495 emitRecord(I.Path, RECORD_PATH);
496 for (const auto &N : I.Namespace)
497 emitBlock(N, FieldId::F_namespace);
498 for (const auto &CI : I.Description)
499 emitBlock(CI);
500 if (I.DefLoc)
501 emitRecord(*I.DefLoc, RECORD_DEFLOCATION);
502 for (const auto &L : I.Loc)
503 emitRecord(L, RECORD_LOCATION);
504 emitRecord(I.TagType, RECORD_TAG_TYPE);
505 emitRecord(I.IsTypeDef, RECORD_IS_TYPE_DEF);
506 for (const auto &N : I.Members)
507 emitBlock(N);
508 for (const auto &P : I.Parents)
509 emitBlock(P, FieldId::F_parent);
510 for (const auto &P : I.VirtualParents)
511 emitBlock(P, FieldId::F_vparent);
512 for (const auto &PB : I.Bases)
513 emitBlock(PB);
514 for (const auto &C : I.ChildRecords)
515 emitBlock(C, FieldId::F_child_record);
516 for (const auto &C : I.ChildFunctions)
517 emitBlock(C);
518 for (const auto &C : I.ChildEnums)
519 emitBlock(C);
522 void ClangDocBitcodeWriter::emitBlock(const BaseRecordInfo &I) {
523 StreamSubBlockGuard Block(Stream, BI_BASE_RECORD_BLOCK_ID);
524 emitRecord(I.USR, BASE_RECORD_USR);
525 emitRecord(I.Name, BASE_RECORD_NAME);
526 emitRecord(I.Path, BASE_RECORD_PATH);
527 emitRecord(I.TagType, BASE_RECORD_TAG_TYPE);
528 emitRecord(I.IsVirtual, BASE_RECORD_IS_VIRTUAL);
529 emitRecord(I.Access, BASE_RECORD_ACCESS);
530 emitRecord(I.IsParent, BASE_RECORD_IS_PARENT);
531 for (const auto &M : I.Members)
532 emitBlock(M);
533 for (const auto &C : I.ChildFunctions)
534 emitBlock(C);
537 void ClangDocBitcodeWriter::emitBlock(const FunctionInfo &I) {
538 StreamSubBlockGuard Block(Stream, BI_FUNCTION_BLOCK_ID);
539 emitRecord(I.USR, FUNCTION_USR);
540 emitRecord(I.Name, FUNCTION_NAME);
541 for (const auto &N : I.Namespace)
542 emitBlock(N, FieldId::F_namespace);
543 for (const auto &CI : I.Description)
544 emitBlock(CI);
545 emitRecord(I.Access, FUNCTION_ACCESS);
546 emitRecord(I.IsMethod, FUNCTION_IS_METHOD);
547 if (I.DefLoc)
548 emitRecord(*I.DefLoc, FUNCTION_DEFLOCATION);
549 for (const auto &L : I.Loc)
550 emitRecord(L, FUNCTION_LOCATION);
551 emitBlock(I.Parent, FieldId::F_parent);
552 emitBlock(I.ReturnType);
553 for (const auto &N : I.Params)
554 emitBlock(N);
557 bool ClangDocBitcodeWriter::dispatchInfoForWrite(Info *I) {
558 switch (I->IT) {
559 case InfoType::IT_namespace:
560 emitBlock(*static_cast<clang::doc::NamespaceInfo *>(I));
561 break;
562 case InfoType::IT_record:
563 emitBlock(*static_cast<clang::doc::RecordInfo *>(I));
564 break;
565 case InfoType::IT_enum:
566 emitBlock(*static_cast<clang::doc::EnumInfo *>(I));
567 break;
568 case InfoType::IT_function:
569 emitBlock(*static_cast<clang::doc::FunctionInfo *>(I));
570 break;
571 default:
572 llvm::errs() << "Unexpected info, unable to write.\n";
573 return true;
575 return false;
578 } // namespace doc
579 } // namespace clang