xref: /llvm-project/clang-tools-extra/clang-doc/BitcodeWriter.cpp (revision 5ef2456a438578b0783241a2744efc62d47e5ab6)
1e975a473SJulie Hockett //===--  BitcodeWriter.cpp - ClangDoc Bitcode Writer ------------*- C++ -*-===//
2e975a473SJulie Hockett //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e975a473SJulie Hockett //
7e975a473SJulie Hockett //===----------------------------------------------------------------------===//
8e975a473SJulie Hockett 
9e975a473SJulie Hockett #include "BitcodeWriter.h"
10e975a473SJulie Hockett #include "llvm/ADT/IndexedMap.h"
11e975a473SJulie Hockett #include <initializer_list>
12e975a473SJulie Hockett 
13e975a473SJulie Hockett namespace clang {
14e975a473SJulie Hockett namespace doc {
15e975a473SJulie Hockett 
16b59cd77cSJulie Hockett // Empty SymbolID for comparison, so we don't have to construct one every time.
17b59cd77cSJulie Hockett static const SymbolID EmptySID = SymbolID();
18b59cd77cSJulie Hockett 
19e975a473SJulie Hockett // Since id enums are not zero-indexed, we need to transform the given id into
20e975a473SJulie Hockett // its associated index.
21e975a473SJulie Hockett struct BlockIdToIndexFunctor {
22e975a473SJulie Hockett   using argument_type = unsigned;
23e975a473SJulie Hockett   unsigned operator()(unsigned ID) const { return ID - BI_FIRST; }
24e975a473SJulie Hockett };
25e975a473SJulie Hockett 
26e975a473SJulie Hockett struct RecordIdToIndexFunctor {
27e975a473SJulie Hockett   using argument_type = unsigned;
28e975a473SJulie Hockett   unsigned operator()(unsigned ID) const { return ID - RI_FIRST; }
29e975a473SJulie Hockett };
30e975a473SJulie Hockett 
31e975a473SJulie Hockett using AbbrevDsc = void (*)(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev);
32e975a473SJulie Hockett 
33e975a473SJulie Hockett static void AbbrevGen(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev,
34e975a473SJulie Hockett                       const std::initializer_list<llvm::BitCodeAbbrevOp> Ops) {
35e975a473SJulie Hockett   for (const auto &Op : Ops)
36e975a473SJulie Hockett     Abbrev->Add(Op);
37e975a473SJulie Hockett }
38e975a473SJulie Hockett 
39e975a473SJulie Hockett static void BoolAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
40e975a473SJulie Hockett   AbbrevGen(Abbrev,
41e975a473SJulie Hockett             {// 0. Boolean
42e975a473SJulie Hockett              llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
43e975a473SJulie Hockett                                    BitCodeConstants::BoolSize)});
44e975a473SJulie Hockett }
45e975a473SJulie Hockett 
46e975a473SJulie Hockett static void IntAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
47e975a473SJulie Hockett   AbbrevGen(Abbrev,
48e975a473SJulie Hockett             {// 0. Fixed-size integer
49e975a473SJulie Hockett              llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
50e975a473SJulie Hockett                                    BitCodeConstants::IntSize)});
51e975a473SJulie Hockett }
52e975a473SJulie Hockett 
53e975a473SJulie Hockett static void SymbolIDAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
54e975a473SJulie Hockett   AbbrevGen(Abbrev,
55e975a473SJulie Hockett             {// 0. Fixed-size integer (length of the sha1'd USR)
56e975a473SJulie Hockett              llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
57e975a473SJulie Hockett                                    BitCodeConstants::USRLengthSize),
58e975a473SJulie Hockett              // 1. Fixed-size array of Char6 (USR)
59e975a473SJulie Hockett              llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Array),
60e975a473SJulie Hockett              llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
61e975a473SJulie Hockett                                    BitCodeConstants::USRBitLengthSize)});
62e975a473SJulie Hockett }
63e975a473SJulie Hockett 
64e975a473SJulie Hockett static void StringAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
65e975a473SJulie Hockett   AbbrevGen(Abbrev,
66e975a473SJulie Hockett             {// 0. Fixed-size integer (length of the following string)
67e975a473SJulie Hockett              llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
68e975a473SJulie Hockett                                    BitCodeConstants::StringLengthSize),
69e975a473SJulie Hockett              // 1. The string blob
70e975a473SJulie Hockett              llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)});
71e975a473SJulie Hockett }
72e975a473SJulie Hockett 
73e975a473SJulie Hockett // Assumes that the file will not have more than 65535 lines.
74e975a473SJulie Hockett static void LocationAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
75e975a473SJulie Hockett   AbbrevGen(
76e975a473SJulie Hockett       Abbrev,
77e975a473SJulie Hockett       {// 0. Fixed-size integer (line number)
78e975a473SJulie Hockett        llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
79e975a473SJulie Hockett                              BitCodeConstants::LineNumberSize),
80665e9676SDiego Astiazaran        // 1. Boolean (IsFileInRootDir)
81665e9676SDiego Astiazaran        llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
82665e9676SDiego Astiazaran                              BitCodeConstants::BoolSize),
83665e9676SDiego Astiazaran        // 2. Fixed-size integer (length of the following string (filename))
84e975a473SJulie Hockett        llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
85e975a473SJulie Hockett                              BitCodeConstants::StringLengthSize),
86665e9676SDiego Astiazaran        // 3. The string blob
87e975a473SJulie Hockett        llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)});
88e975a473SJulie Hockett }
89e975a473SJulie Hockett 
90e975a473SJulie Hockett struct RecordIdDsc {
91e975a473SJulie Hockett   llvm::StringRef Name;
92e975a473SJulie Hockett   AbbrevDsc Abbrev = nullptr;
93e975a473SJulie Hockett 
94e975a473SJulie Hockett   RecordIdDsc() = default;
95e975a473SJulie Hockett   RecordIdDsc(llvm::StringRef Name, AbbrevDsc Abbrev)
96e975a473SJulie Hockett       : Name(Name), Abbrev(Abbrev) {}
97e975a473SJulie Hockett 
98e975a473SJulie Hockett   // Is this 'description' valid?
99e975a473SJulie Hockett   operator bool() const {
100e975a473SJulie Hockett     return Abbrev != nullptr && Name.data() != nullptr && !Name.empty();
101e975a473SJulie Hockett   }
102e975a473SJulie Hockett };
103e975a473SJulie Hockett 
104e975a473SJulie Hockett static const llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor>
105e975a473SJulie Hockett     BlockIdNameMap = []() {
106e975a473SJulie Hockett       llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor> BlockIdNameMap;
107e975a473SJulie Hockett       BlockIdNameMap.resize(BlockIdCount);
108e975a473SJulie Hockett 
109e975a473SJulie Hockett       // There is no init-list constructor for the IndexedMap, so have to
110e975a473SJulie Hockett       // improvise
111e975a473SJulie Hockett       static const std::vector<std::pair<BlockId, const char *const>> Inits = {
112e975a473SJulie Hockett           {BI_VERSION_BLOCK_ID, "VersionBlock"},
113e975a473SJulie Hockett           {BI_NAMESPACE_BLOCK_ID, "NamespaceBlock"},
114e975a473SJulie Hockett           {BI_ENUM_BLOCK_ID, "EnumBlock"},
115eaa7b324SBrett Wilson           {BI_ENUM_VALUE_BLOCK_ID, "EnumValueBlock"},
11621fb70c6SBrett Wilson           {BI_TYPEDEF_BLOCK_ID, "TypedefBlock"},
117e975a473SJulie Hockett           {BI_TYPE_BLOCK_ID, "TypeBlock"},
118e975a473SJulie Hockett           {BI_FIELD_TYPE_BLOCK_ID, "FieldTypeBlock"},
119e975a473SJulie Hockett           {BI_MEMBER_TYPE_BLOCK_ID, "MemberTypeBlock"},
120e975a473SJulie Hockett           {BI_RECORD_BLOCK_ID, "RecordBlock"},
121ba3d595fSDiego Astiazaran           {BI_BASE_RECORD_BLOCK_ID, "BaseRecordBlock"},
122e975a473SJulie Hockett           {BI_FUNCTION_BLOCK_ID, "FunctionBlock"},
123b59cd77cSJulie Hockett           {BI_COMMENT_BLOCK_ID, "CommentBlock"},
1244a68babdSBrett Wilson           {BI_REFERENCE_BLOCK_ID, "ReferenceBlock"},
1254a68babdSBrett Wilson           {BI_TEMPLATE_BLOCK_ID, "TemplateBlock"},
1264a68babdSBrett Wilson           {BI_TEMPLATE_SPECIALIZATION_BLOCK_ID, "TemplateSpecializationBlock"},
1274a68babdSBrett Wilson           {BI_TEMPLATE_PARAM_BLOCK_ID, "TemplateParamBlock"}};
128e975a473SJulie Hockett       assert(Inits.size() == BlockIdCount);
129e975a473SJulie Hockett       for (const auto &Init : Inits)
130e975a473SJulie Hockett         BlockIdNameMap[Init.first] = Init.second;
131e975a473SJulie Hockett       assert(BlockIdNameMap.size() == BlockIdCount);
132e975a473SJulie Hockett       return BlockIdNameMap;
133e975a473SJulie Hockett     }();
134e975a473SJulie Hockett 
135e975a473SJulie Hockett static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor>
136e975a473SJulie Hockett     RecordIdNameMap = []() {
137e975a473SJulie Hockett       llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor> RecordIdNameMap;
138e975a473SJulie Hockett       RecordIdNameMap.resize(RecordIdCount);
139e975a473SJulie Hockett 
140e975a473SJulie Hockett       // There is no init-list constructor for the IndexedMap, so have to
141e975a473SJulie Hockett       // improvise
142e975a473SJulie Hockett       static const std::vector<std::pair<RecordId, RecordIdDsc>> Inits = {
143e975a473SJulie Hockett           {VERSION, {"Version", &IntAbbrev}},
144e975a473SJulie Hockett           {COMMENT_KIND, {"Kind", &StringAbbrev}},
145e975a473SJulie Hockett           {COMMENT_TEXT, {"Text", &StringAbbrev}},
146e975a473SJulie Hockett           {COMMENT_NAME, {"Name", &StringAbbrev}},
147e975a473SJulie Hockett           {COMMENT_DIRECTION, {"Direction", &StringAbbrev}},
148e975a473SJulie Hockett           {COMMENT_PARAMNAME, {"ParamName", &StringAbbrev}},
149e975a473SJulie Hockett           {COMMENT_CLOSENAME, {"CloseName", &StringAbbrev}},
150e975a473SJulie Hockett           {COMMENT_SELFCLOSING, {"SelfClosing", &BoolAbbrev}},
151e975a473SJulie Hockett           {COMMENT_EXPLICIT, {"Explicit", &BoolAbbrev}},
152e975a473SJulie Hockett           {COMMENT_ATTRKEY, {"AttrKey", &StringAbbrev}},
153e975a473SJulie Hockett           {COMMENT_ATTRVAL, {"AttrVal", &StringAbbrev}},
154e975a473SJulie Hockett           {COMMENT_ARG, {"Arg", &StringAbbrev}},
155e975a473SJulie Hockett           {FIELD_TYPE_NAME, {"Name", &StringAbbrev}},
156e191086bSBrett Wilson           {FIELD_DEFAULT_VALUE, {"DefaultValue", &StringAbbrev}},
157e975a473SJulie Hockett           {MEMBER_TYPE_NAME, {"Name", &StringAbbrev}},
158e975a473SJulie Hockett           {MEMBER_TYPE_ACCESS, {"Access", &IntAbbrev}},
159e975a473SJulie Hockett           {NAMESPACE_USR, {"USR", &SymbolIDAbbrev}},
160e975a473SJulie Hockett           {NAMESPACE_NAME, {"Name", &StringAbbrev}},
1612c1c9a24SJulie Hockett           {NAMESPACE_PATH, {"Path", &StringAbbrev}},
162e975a473SJulie Hockett           {ENUM_USR, {"USR", &SymbolIDAbbrev}},
163e975a473SJulie Hockett           {ENUM_NAME, {"Name", &StringAbbrev}},
164e975a473SJulie Hockett           {ENUM_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
165e975a473SJulie Hockett           {ENUM_LOCATION, {"Location", &LocationAbbrev}},
166e975a473SJulie Hockett           {ENUM_SCOPED, {"Scoped", &BoolAbbrev}},
167eaa7b324SBrett Wilson           {ENUM_VALUE_NAME, {"Name", &StringAbbrev}},
168eaa7b324SBrett Wilson           {ENUM_VALUE_VALUE, {"Value", &StringAbbrev}},
169eaa7b324SBrett Wilson           {ENUM_VALUE_EXPR, {"Expr", &StringAbbrev}},
170e975a473SJulie Hockett           {RECORD_USR, {"USR", &SymbolIDAbbrev}},
171e975a473SJulie Hockett           {RECORD_NAME, {"Name", &StringAbbrev}},
1722c1c9a24SJulie Hockett           {RECORD_PATH, {"Path", &StringAbbrev}},
173e975a473SJulie Hockett           {RECORD_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
174e975a473SJulie Hockett           {RECORD_LOCATION, {"Location", &LocationAbbrev}},
175e975a473SJulie Hockett           {RECORD_TAG_TYPE, {"TagType", &IntAbbrev}},
176b1f01e27SJulie Hockett           {RECORD_IS_TYPE_DEF, {"IsTypeDef", &BoolAbbrev}},
177ba3d595fSDiego Astiazaran           {BASE_RECORD_USR, {"USR", &SymbolIDAbbrev}},
178ba3d595fSDiego Astiazaran           {BASE_RECORD_NAME, {"Name", &StringAbbrev}},
179ba3d595fSDiego Astiazaran           {BASE_RECORD_PATH, {"Path", &StringAbbrev}},
180ba3d595fSDiego Astiazaran           {BASE_RECORD_TAG_TYPE, {"TagType", &IntAbbrev}},
181ba3d595fSDiego Astiazaran           {BASE_RECORD_IS_VIRTUAL, {"IsVirtual", &BoolAbbrev}},
182ba3d595fSDiego Astiazaran           {BASE_RECORD_ACCESS, {"Access", &IntAbbrev}},
183ba3d595fSDiego Astiazaran           {BASE_RECORD_IS_PARENT, {"IsParent", &BoolAbbrev}},
184e975a473SJulie Hockett           {FUNCTION_USR, {"USR", &SymbolIDAbbrev}},
185e975a473SJulie Hockett           {FUNCTION_NAME, {"Name", &StringAbbrev}},
186e975a473SJulie Hockett           {FUNCTION_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
187e975a473SJulie Hockett           {FUNCTION_LOCATION, {"Location", &LocationAbbrev}},
188e975a473SJulie Hockett           {FUNCTION_ACCESS, {"Access", &IntAbbrev}},
189b59cd77cSJulie Hockett           {FUNCTION_IS_METHOD, {"IsMethod", &BoolAbbrev}},
190b59cd77cSJulie Hockett           {REFERENCE_USR, {"USR", &SymbolIDAbbrev}},
191b59cd77cSJulie Hockett           {REFERENCE_NAME, {"Name", &StringAbbrev}},
1924a68babdSBrett Wilson           {REFERENCE_QUAL_NAME, {"QualName", &StringAbbrev}},
193b59cd77cSJulie Hockett           {REFERENCE_TYPE, {"RefType", &IntAbbrev}},
1942c1c9a24SJulie Hockett           {REFERENCE_PATH, {"Path", &StringAbbrev}},
19521fb70c6SBrett Wilson           {REFERENCE_FIELD, {"Field", &IntAbbrev}},
1964a68babdSBrett Wilson           {TEMPLATE_PARAM_CONTENTS, {"Contents", &StringAbbrev}},
1974a68babdSBrett Wilson           {TEMPLATE_SPECIALIZATION_OF, {"SpecializationOf", &SymbolIDAbbrev}},
19821fb70c6SBrett Wilson           {TYPEDEF_USR, {"USR", &SymbolIDAbbrev}},
19921fb70c6SBrett Wilson           {TYPEDEF_NAME, {"Name", &StringAbbrev}},
20021fb70c6SBrett Wilson           {TYPEDEF_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
20121fb70c6SBrett Wilson           {TYPEDEF_IS_USING, {"IsUsing", &BoolAbbrev}}};
202e975a473SJulie Hockett       assert(Inits.size() == RecordIdCount);
203e975a473SJulie Hockett       for (const auto &Init : Inits) {
204e975a473SJulie Hockett         RecordIdNameMap[Init.first] = Init.second;
205e975a473SJulie Hockett         assert((Init.second.Name.size() + 1) <= BitCodeConstants::RecordSize);
206e975a473SJulie Hockett       }
207e975a473SJulie Hockett       assert(RecordIdNameMap.size() == RecordIdCount);
208e975a473SJulie Hockett       return RecordIdNameMap;
209e975a473SJulie Hockett     }();
210e975a473SJulie Hockett 
211e975a473SJulie Hockett static const std::vector<std::pair<BlockId, std::vector<RecordId>>>
212e975a473SJulie Hockett     RecordsByBlock{
213e975a473SJulie Hockett         // Version Block
214e975a473SJulie Hockett         {BI_VERSION_BLOCK_ID, {VERSION}},
215e975a473SJulie Hockett         // Comment Block
216e975a473SJulie Hockett         {BI_COMMENT_BLOCK_ID,
217e975a473SJulie Hockett          {COMMENT_KIND, COMMENT_TEXT, COMMENT_NAME, COMMENT_DIRECTION,
218e975a473SJulie Hockett           COMMENT_PARAMNAME, COMMENT_CLOSENAME, COMMENT_SELFCLOSING,
219e975a473SJulie Hockett           COMMENT_EXPLICIT, COMMENT_ATTRKEY, COMMENT_ATTRVAL, COMMENT_ARG}},
220e975a473SJulie Hockett         // Type Block
221b59cd77cSJulie Hockett         {BI_TYPE_BLOCK_ID, {}},
222e975a473SJulie Hockett         // FieldType Block
223e191086bSBrett Wilson         {BI_FIELD_TYPE_BLOCK_ID, {FIELD_TYPE_NAME, FIELD_DEFAULT_VALUE}},
224e975a473SJulie Hockett         // MemberType Block
225b59cd77cSJulie Hockett         {BI_MEMBER_TYPE_BLOCK_ID, {MEMBER_TYPE_NAME, MEMBER_TYPE_ACCESS}},
226e975a473SJulie Hockett         // Enum Block
227e975a473SJulie Hockett         {BI_ENUM_BLOCK_ID,
228eaa7b324SBrett Wilson          {ENUM_USR, ENUM_NAME, ENUM_DEFLOCATION, ENUM_LOCATION, ENUM_SCOPED}},
229eaa7b324SBrett Wilson         // Enum Value Block
230eaa7b324SBrett Wilson         {BI_ENUM_VALUE_BLOCK_ID,
231eaa7b324SBrett Wilson          {ENUM_VALUE_NAME, ENUM_VALUE_VALUE, ENUM_VALUE_EXPR}},
23221fb70c6SBrett Wilson         // Typedef Block
23321fb70c6SBrett Wilson         {BI_TYPEDEF_BLOCK_ID,
23421fb70c6SBrett Wilson          {TYPEDEF_USR, TYPEDEF_NAME, TYPEDEF_DEFLOCATION, TYPEDEF_IS_USING}},
235e975a473SJulie Hockett         // Namespace Block
2362c1c9a24SJulie Hockett         {BI_NAMESPACE_BLOCK_ID,
2372c1c9a24SJulie Hockett          {NAMESPACE_USR, NAMESPACE_NAME, NAMESPACE_PATH}},
238e975a473SJulie Hockett         // Record Block
239e975a473SJulie Hockett         {BI_RECORD_BLOCK_ID,
2402c1c9a24SJulie Hockett          {RECORD_USR, RECORD_NAME, RECORD_PATH, RECORD_DEFLOCATION,
2412c1c9a24SJulie Hockett           RECORD_LOCATION, RECORD_TAG_TYPE, RECORD_IS_TYPE_DEF}},
242ba3d595fSDiego Astiazaran         // BaseRecord Block
243ba3d595fSDiego Astiazaran         {BI_BASE_RECORD_BLOCK_ID,
244ba3d595fSDiego Astiazaran          {BASE_RECORD_USR, BASE_RECORD_NAME, BASE_RECORD_PATH,
245ba3d595fSDiego Astiazaran           BASE_RECORD_TAG_TYPE, BASE_RECORD_IS_VIRTUAL, BASE_RECORD_ACCESS,
246ba3d595fSDiego Astiazaran           BASE_RECORD_IS_PARENT}},
247e975a473SJulie Hockett         // Function Block
248e975a473SJulie Hockett         {BI_FUNCTION_BLOCK_ID,
249b59cd77cSJulie Hockett          {FUNCTION_USR, FUNCTION_NAME, FUNCTION_DEFLOCATION, FUNCTION_LOCATION,
250b59cd77cSJulie Hockett           FUNCTION_ACCESS, FUNCTION_IS_METHOD}},
251b59cd77cSJulie Hockett         // Reference Block
252b59cd77cSJulie Hockett         {BI_REFERENCE_BLOCK_ID,
2534a68babdSBrett Wilson          {REFERENCE_USR, REFERENCE_NAME, REFERENCE_QUAL_NAME, REFERENCE_TYPE,
2544a68babdSBrett Wilson           REFERENCE_PATH, REFERENCE_FIELD}},
2554a68babdSBrett Wilson         // Template Blocks.
2564a68babdSBrett Wilson         {BI_TEMPLATE_BLOCK_ID, {}},
2574a68babdSBrett Wilson         {BI_TEMPLATE_PARAM_BLOCK_ID, {TEMPLATE_PARAM_CONTENTS}},
2584a68babdSBrett Wilson         {BI_TEMPLATE_SPECIALIZATION_BLOCK_ID, {TEMPLATE_SPECIALIZATION_OF}}};
259e975a473SJulie Hockett 
260e975a473SJulie Hockett // AbbreviationMap
261e975a473SJulie Hockett 
2620e828958SJF Bastien constexpr unsigned char BitCodeConstants::Signature[];
263d0f9a872SJulie Hockett 
264e975a473SJulie Hockett void ClangDocBitcodeWriter::AbbreviationMap::add(RecordId RID,
265e975a473SJulie Hockett                                                  unsigned AbbrevID) {
266e975a473SJulie Hockett   assert(RecordIdNameMap[RID] && "Unknown RecordId.");
2674e585e51SKazu Hirata   assert(!Abbrevs.contains(RID) && "Abbreviation already added.");
268e975a473SJulie Hockett   Abbrevs[RID] = AbbrevID;
269e975a473SJulie Hockett }
270e975a473SJulie Hockett 
271e975a473SJulie Hockett unsigned ClangDocBitcodeWriter::AbbreviationMap::get(RecordId RID) const {
272e975a473SJulie Hockett   assert(RecordIdNameMap[RID] && "Unknown RecordId.");
2734e585e51SKazu Hirata   assert(Abbrevs.contains(RID) && "Unknown abbreviation.");
274e975a473SJulie Hockett   return Abbrevs.lookup(RID);
275e975a473SJulie Hockett }
276e975a473SJulie Hockett 
277e975a473SJulie Hockett // Validation and Overview Blocks
278e975a473SJulie Hockett 
279282dc72cSDmitri Gribenko /// Emits the magic number header to check that its the right format,
280e975a473SJulie Hockett /// in this case, 'DOCS'.
281e975a473SJulie Hockett void ClangDocBitcodeWriter::emitHeader() {
282d0f9a872SJulie Hockett   for (char C : BitCodeConstants::Signature)
283e975a473SJulie Hockett     Stream.Emit((unsigned)C, BitCodeConstants::SignatureBitSize);
284e975a473SJulie Hockett }
285e975a473SJulie Hockett 
286e975a473SJulie Hockett void ClangDocBitcodeWriter::emitVersionBlock() {
287e975a473SJulie Hockett   StreamSubBlockGuard Block(Stream, BI_VERSION_BLOCK_ID);
288e975a473SJulie Hockett   emitRecord(VersionNumber, VERSION);
289e975a473SJulie Hockett }
290e975a473SJulie Hockett 
291282dc72cSDmitri Gribenko /// Emits a block ID and the block name to the BLOCKINFO block.
292e975a473SJulie Hockett void ClangDocBitcodeWriter::emitBlockID(BlockId BID) {
293e975a473SJulie Hockett   const auto &BlockIdName = BlockIdNameMap[BID];
294e975a473SJulie Hockett   assert(BlockIdName.data() && BlockIdName.size() && "Unknown BlockId.");
295e975a473SJulie Hockett 
296e975a473SJulie Hockett   Record.clear();
297e975a473SJulie Hockett   Record.push_back(BID);
298e975a473SJulie Hockett   Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
299e975a473SJulie Hockett   Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,
3009345d982SJulie Hockett                     ArrayRef<unsigned char>(BlockIdName.bytes_begin(),
3019345d982SJulie Hockett                                             BlockIdName.bytes_end()));
302e975a473SJulie Hockett }
303e975a473SJulie Hockett 
304282dc72cSDmitri Gribenko /// Emits a record name to the BLOCKINFO block.
305e975a473SJulie Hockett void ClangDocBitcodeWriter::emitRecordID(RecordId ID) {
306e975a473SJulie Hockett   assert(RecordIdNameMap[ID] && "Unknown RecordId.");
307e975a473SJulie Hockett   prepRecordData(ID);
308e975a473SJulie Hockett   Record.append(RecordIdNameMap[ID].Name.begin(),
309e975a473SJulie Hockett                 RecordIdNameMap[ID].Name.end());
310e975a473SJulie Hockett   Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
311e975a473SJulie Hockett }
312e975a473SJulie Hockett 
313e975a473SJulie Hockett // Abbreviations
314e975a473SJulie Hockett 
315e975a473SJulie Hockett void ClangDocBitcodeWriter::emitAbbrev(RecordId ID, BlockId Block) {
316e975a473SJulie Hockett   assert(RecordIdNameMap[ID] && "Unknown abbreviation.");
317e975a473SJulie Hockett   auto Abbrev = std::make_shared<llvm::BitCodeAbbrev>();
318e975a473SJulie Hockett   Abbrev->Add(llvm::BitCodeAbbrevOp(ID));
319e975a473SJulie Hockett   RecordIdNameMap[ID].Abbrev(Abbrev);
320e975a473SJulie Hockett   Abbrevs.add(ID, Stream.EmitBlockInfoAbbrev(Block, std::move(Abbrev)));
321e975a473SJulie Hockett }
322e975a473SJulie Hockett 
323e975a473SJulie Hockett // Records
324e975a473SJulie Hockett 
325e975a473SJulie Hockett void ClangDocBitcodeWriter::emitRecord(const SymbolID &Sym, RecordId ID) {
326e975a473SJulie Hockett   assert(RecordIdNameMap[ID] && "Unknown RecordId.");
327e975a473SJulie Hockett   assert(RecordIdNameMap[ID].Abbrev == &SymbolIDAbbrev &&
328e975a473SJulie Hockett          "Abbrev type mismatch.");
329b59cd77cSJulie Hockett   if (!prepRecordData(ID, Sym != EmptySID))
330e975a473SJulie Hockett     return;
331e975a473SJulie Hockett   assert(Sym.size() == 20);
332e975a473SJulie Hockett   Record.push_back(Sym.size());
333e975a473SJulie Hockett   Record.append(Sym.begin(), Sym.end());
334e975a473SJulie Hockett   Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
335e975a473SJulie Hockett }
336e975a473SJulie Hockett 
337e975a473SJulie Hockett void ClangDocBitcodeWriter::emitRecord(llvm::StringRef Str, RecordId ID) {
338e975a473SJulie Hockett   assert(RecordIdNameMap[ID] && "Unknown RecordId.");
339e975a473SJulie Hockett   assert(RecordIdNameMap[ID].Abbrev == &StringAbbrev &&
340e975a473SJulie Hockett          "Abbrev type mismatch.");
341e975a473SJulie Hockett   if (!prepRecordData(ID, !Str.empty()))
342e975a473SJulie Hockett     return;
343e975a473SJulie Hockett   assert(Str.size() < (1U << BitCodeConstants::StringLengthSize));
344e975a473SJulie Hockett   Record.push_back(Str.size());
345e975a473SJulie Hockett   Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Str);
346e975a473SJulie Hockett }
347e975a473SJulie Hockett 
348e975a473SJulie Hockett void ClangDocBitcodeWriter::emitRecord(const Location &Loc, RecordId ID) {
349e975a473SJulie Hockett   assert(RecordIdNameMap[ID] && "Unknown RecordId.");
350e975a473SJulie Hockett   assert(RecordIdNameMap[ID].Abbrev == &LocationAbbrev &&
351e975a473SJulie Hockett          "Abbrev type mismatch.");
352e975a473SJulie Hockett   if (!prepRecordData(ID, true))
353e975a473SJulie Hockett     return;
354e975a473SJulie Hockett   // FIXME: Assert that the line number is of the appropriate size.
355e975a473SJulie Hockett   Record.push_back(Loc.LineNumber);
356e975a473SJulie Hockett   assert(Loc.Filename.size() < (1U << BitCodeConstants::StringLengthSize));
357665e9676SDiego Astiazaran   Record.push_back(Loc.IsFileInRootDir);
358f276624eSJulie Hockett   Record.push_back(Loc.Filename.size());
359f276624eSJulie Hockett   Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Loc.Filename);
360e975a473SJulie Hockett }
361e975a473SJulie Hockett 
362e975a473SJulie Hockett void ClangDocBitcodeWriter::emitRecord(bool Val, RecordId ID) {
363e975a473SJulie Hockett   assert(RecordIdNameMap[ID] && "Unknown RecordId.");
364e975a473SJulie Hockett   assert(RecordIdNameMap[ID].Abbrev == &BoolAbbrev && "Abbrev type mismatch.");
365e975a473SJulie Hockett   if (!prepRecordData(ID, Val))
366e975a473SJulie Hockett     return;
367e975a473SJulie Hockett   Record.push_back(Val);
368e975a473SJulie Hockett   Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
369e975a473SJulie Hockett }
370e975a473SJulie Hockett 
371e975a473SJulie Hockett void ClangDocBitcodeWriter::emitRecord(int Val, RecordId ID) {
372e975a473SJulie Hockett   assert(RecordIdNameMap[ID] && "Unknown RecordId.");
373e975a473SJulie Hockett   assert(RecordIdNameMap[ID].Abbrev == &IntAbbrev && "Abbrev type mismatch.");
374e975a473SJulie Hockett   if (!prepRecordData(ID, Val))
375e975a473SJulie Hockett     return;
376e975a473SJulie Hockett   // FIXME: Assert that the integer is of the appropriate size.
377e975a473SJulie Hockett   Record.push_back(Val);
378e975a473SJulie Hockett   Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
379e975a473SJulie Hockett }
380e975a473SJulie Hockett 
381e975a473SJulie Hockett void ClangDocBitcodeWriter::emitRecord(unsigned Val, RecordId ID) {
382e975a473SJulie Hockett   assert(RecordIdNameMap[ID] && "Unknown RecordId.");
383e975a473SJulie Hockett   assert(RecordIdNameMap[ID].Abbrev == &IntAbbrev && "Abbrev type mismatch.");
384e975a473SJulie Hockett   if (!prepRecordData(ID, Val))
385e975a473SJulie Hockett     return;
386e975a473SJulie Hockett   assert(Val < (1U << BitCodeConstants::IntSize));
387e975a473SJulie Hockett   Record.push_back(Val);
388e975a473SJulie Hockett   Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
389e975a473SJulie Hockett }
390e975a473SJulie Hockett 
3914a68babdSBrett Wilson void ClangDocBitcodeWriter::emitRecord(const TemplateInfo &Templ) {}
3924a68babdSBrett Wilson 
393e975a473SJulie Hockett bool ClangDocBitcodeWriter::prepRecordData(RecordId ID, bool ShouldEmit) {
394e975a473SJulie Hockett   assert(RecordIdNameMap[ID] && "Unknown RecordId.");
395e975a473SJulie Hockett   if (!ShouldEmit)
396e975a473SJulie Hockett     return false;
397e975a473SJulie Hockett   Record.clear();
398e975a473SJulie Hockett   Record.push_back(ID);
399e975a473SJulie Hockett   return true;
400e975a473SJulie Hockett }
401e975a473SJulie Hockett 
402e975a473SJulie Hockett // BlockInfo Block
403e975a473SJulie Hockett 
404e975a473SJulie Hockett void ClangDocBitcodeWriter::emitBlockInfoBlock() {
405e975a473SJulie Hockett   Stream.EnterBlockInfoBlock();
406e975a473SJulie Hockett   for (const auto &Block : RecordsByBlock) {
407e975a473SJulie Hockett     assert(Block.second.size() < (1U << BitCodeConstants::SubblockIDSize));
408e975a473SJulie Hockett     emitBlockInfo(Block.first, Block.second);
409e975a473SJulie Hockett   }
410e975a473SJulie Hockett   Stream.ExitBlock();
411e975a473SJulie Hockett }
412e975a473SJulie Hockett 
413e975a473SJulie Hockett void ClangDocBitcodeWriter::emitBlockInfo(BlockId BID,
414e975a473SJulie Hockett                                           const std::vector<RecordId> &RIDs) {
415e975a473SJulie Hockett   assert(RIDs.size() < (1U << BitCodeConstants::SubblockIDSize));
416e975a473SJulie Hockett   emitBlockID(BID);
417e975a473SJulie Hockett   for (RecordId RID : RIDs) {
418e975a473SJulie Hockett     emitRecordID(RID);
419e975a473SJulie Hockett     emitAbbrev(RID, BID);
420e975a473SJulie Hockett   }
421e975a473SJulie Hockett }
422e975a473SJulie Hockett 
423e975a473SJulie Hockett // Block emission
424e975a473SJulie Hockett 
425b59cd77cSJulie Hockett void ClangDocBitcodeWriter::emitBlock(const Reference &R, FieldId Field) {
426b59cd77cSJulie Hockett   if (R.USR == EmptySID && R.Name.empty())
427b59cd77cSJulie Hockett     return;
428b59cd77cSJulie Hockett   StreamSubBlockGuard Block(Stream, BI_REFERENCE_BLOCK_ID);
429b59cd77cSJulie Hockett   emitRecord(R.USR, REFERENCE_USR);
430b59cd77cSJulie Hockett   emitRecord(R.Name, REFERENCE_NAME);
4314a68babdSBrett Wilson   emitRecord(R.QualName, REFERENCE_QUAL_NAME);
432b59cd77cSJulie Hockett   emitRecord((unsigned)R.RefType, REFERENCE_TYPE);
4332c1c9a24SJulie Hockett   emitRecord(R.Path, REFERENCE_PATH);
434b59cd77cSJulie Hockett   emitRecord((unsigned)Field, REFERENCE_FIELD);
435b59cd77cSJulie Hockett }
436b59cd77cSJulie Hockett 
437e975a473SJulie Hockett void ClangDocBitcodeWriter::emitBlock(const TypeInfo &T) {
438e975a473SJulie Hockett   StreamSubBlockGuard Block(Stream, BI_TYPE_BLOCK_ID);
439b59cd77cSJulie Hockett   emitBlock(T.Type, FieldId::F_type);
440e975a473SJulie Hockett }
441e975a473SJulie Hockett 
44221fb70c6SBrett Wilson void ClangDocBitcodeWriter::emitBlock(const TypedefInfo &T) {
44321fb70c6SBrett Wilson   StreamSubBlockGuard Block(Stream, BI_TYPEDEF_BLOCK_ID);
44421fb70c6SBrett Wilson   emitRecord(T.USR, TYPEDEF_USR);
44521fb70c6SBrett Wilson   emitRecord(T.Name, TYPEDEF_NAME);
44621fb70c6SBrett Wilson   for (const auto &N : T.Namespace)
44721fb70c6SBrett Wilson     emitBlock(N, FieldId::F_namespace);
4487231c996SBrett Wilson   for (const auto &CI : T.Description)
4497231c996SBrett Wilson     emitBlock(CI);
45021fb70c6SBrett Wilson   if (T.DefLoc)
45121fb70c6SBrett Wilson     emitRecord(*T.DefLoc, TYPEDEF_DEFLOCATION);
45221fb70c6SBrett Wilson   emitRecord(T.IsUsing, TYPEDEF_IS_USING);
45321fb70c6SBrett Wilson   emitBlock(T.Underlying);
45421fb70c6SBrett Wilson }
45521fb70c6SBrett Wilson 
456e975a473SJulie Hockett void ClangDocBitcodeWriter::emitBlock(const FieldTypeInfo &T) {
457e975a473SJulie Hockett   StreamSubBlockGuard Block(Stream, BI_FIELD_TYPE_BLOCK_ID);
458b59cd77cSJulie Hockett   emitBlock(T.Type, FieldId::F_type);
459e975a473SJulie Hockett   emitRecord(T.Name, FIELD_TYPE_NAME);
460e191086bSBrett Wilson   emitRecord(T.DefaultValue, FIELD_DEFAULT_VALUE);
461e975a473SJulie Hockett }
462e975a473SJulie Hockett 
463e975a473SJulie Hockett void ClangDocBitcodeWriter::emitBlock(const MemberTypeInfo &T) {
464e975a473SJulie Hockett   StreamSubBlockGuard Block(Stream, BI_MEMBER_TYPE_BLOCK_ID);
465b59cd77cSJulie Hockett   emitBlock(T.Type, FieldId::F_type);
466e975a473SJulie Hockett   emitRecord(T.Name, MEMBER_TYPE_NAME);
467e975a473SJulie Hockett   emitRecord(T.Access, MEMBER_TYPE_ACCESS);
46899baa10fSBrett Wilson   for (const auto &CI : T.Description)
46999baa10fSBrett Wilson     emitBlock(CI);
470e975a473SJulie Hockett }
471e975a473SJulie Hockett 
472e975a473SJulie Hockett void ClangDocBitcodeWriter::emitBlock(const CommentInfo &I) {
473e975a473SJulie Hockett   StreamSubBlockGuard Block(Stream, BI_COMMENT_BLOCK_ID);
474b59cd77cSJulie Hockett   for (const auto &L : std::vector<std::pair<llvm::StringRef, RecordId>>{
475e975a473SJulie Hockett            {I.Kind, COMMENT_KIND},
476e975a473SJulie Hockett            {I.Text, COMMENT_TEXT},
477e975a473SJulie Hockett            {I.Name, COMMENT_NAME},
478e975a473SJulie Hockett            {I.Direction, COMMENT_DIRECTION},
479e975a473SJulie Hockett            {I.ParamName, COMMENT_PARAMNAME},
480e975a473SJulie Hockett            {I.CloseName, COMMENT_CLOSENAME}})
481e975a473SJulie Hockett     emitRecord(L.first, L.second);
482e975a473SJulie Hockett   emitRecord(I.SelfClosing, COMMENT_SELFCLOSING);
483e975a473SJulie Hockett   emitRecord(I.Explicit, COMMENT_EXPLICIT);
484e975a473SJulie Hockett   for (const auto &A : I.AttrKeys)
485e975a473SJulie Hockett     emitRecord(A, COMMENT_ATTRKEY);
486e975a473SJulie Hockett   for (const auto &A : I.AttrValues)
487e975a473SJulie Hockett     emitRecord(A, COMMENT_ATTRVAL);
488e975a473SJulie Hockett   for (const auto &A : I.Args)
489e975a473SJulie Hockett     emitRecord(A, COMMENT_ARG);
490e975a473SJulie Hockett   for (const auto &C : I.Children)
491e975a473SJulie Hockett     emitBlock(*C);
492e975a473SJulie Hockett }
493e975a473SJulie Hockett 
494e975a473SJulie Hockett void ClangDocBitcodeWriter::emitBlock(const NamespaceInfo &I) {
495e975a473SJulie Hockett   StreamSubBlockGuard Block(Stream, BI_NAMESPACE_BLOCK_ID);
496d0f9a872SJulie Hockett   emitRecord(I.USR, NAMESPACE_USR);
497d0f9a872SJulie Hockett   emitRecord(I.Name, NAMESPACE_NAME);
4982c1c9a24SJulie Hockett   emitRecord(I.Path, NAMESPACE_PATH);
499d0f9a872SJulie Hockett   for (const auto &N : I.Namespace)
500d0f9a872SJulie Hockett     emitBlock(N, FieldId::F_namespace);
501d0f9a872SJulie Hockett   for (const auto &CI : I.Description)
502d0f9a872SJulie Hockett     emitBlock(CI);
50321fb70c6SBrett Wilson   for (const auto &C : I.Children.Namespaces)
5048899c29bSJulie Hockett     emitBlock(C, FieldId::F_child_namespace);
50521fb70c6SBrett Wilson   for (const auto &C : I.Children.Records)
5068899c29bSJulie Hockett     emitBlock(C, FieldId::F_child_record);
50721fb70c6SBrett Wilson   for (const auto &C : I.Children.Functions)
5088899c29bSJulie Hockett     emitBlock(C);
50921fb70c6SBrett Wilson   for (const auto &C : I.Children.Enums)
51021fb70c6SBrett Wilson     emitBlock(C);
51121fb70c6SBrett Wilson   for (const auto &C : I.Children.Typedefs)
5128899c29bSJulie Hockett     emitBlock(C);
513e975a473SJulie Hockett }
514e975a473SJulie Hockett 
515e975a473SJulie Hockett void ClangDocBitcodeWriter::emitBlock(const EnumInfo &I) {
516e975a473SJulie Hockett   StreamSubBlockGuard Block(Stream, BI_ENUM_BLOCK_ID);
517d0f9a872SJulie Hockett   emitRecord(I.USR, ENUM_USR);
518d0f9a872SJulie Hockett   emitRecord(I.Name, ENUM_NAME);
519d0f9a872SJulie Hockett   for (const auto &N : I.Namespace)
520d0f9a872SJulie Hockett     emitBlock(N, FieldId::F_namespace);
521d0f9a872SJulie Hockett   for (const auto &CI : I.Description)
522d0f9a872SJulie Hockett     emitBlock(CI);
523e975a473SJulie Hockett   if (I.DefLoc)
524ed8fceaaSKazu Hirata     emitRecord(*I.DefLoc, ENUM_DEFLOCATION);
525e975a473SJulie Hockett   for (const auto &L : I.Loc)
526e975a473SJulie Hockett     emitRecord(L, ENUM_LOCATION);
527e975a473SJulie Hockett   emitRecord(I.Scoped, ENUM_SCOPED);
528eaa7b324SBrett Wilson   if (I.BaseType)
529eaa7b324SBrett Wilson     emitBlock(*I.BaseType);
530e975a473SJulie Hockett   for (const auto &N : I.Members)
531eaa7b324SBrett Wilson     emitBlock(N);
532eaa7b324SBrett Wilson }
533eaa7b324SBrett Wilson 
534eaa7b324SBrett Wilson void ClangDocBitcodeWriter::emitBlock(const EnumValueInfo &I) {
535eaa7b324SBrett Wilson   StreamSubBlockGuard Block(Stream, BI_ENUM_VALUE_BLOCK_ID);
536eaa7b324SBrett Wilson   emitRecord(I.Name, ENUM_VALUE_NAME);
537eaa7b324SBrett Wilson   emitRecord(I.Value, ENUM_VALUE_VALUE);
538eaa7b324SBrett Wilson   emitRecord(I.ValueExpr, ENUM_VALUE_EXPR);
539*5ef2456aSPeterChou1   for (const auto &CI : I.Description)
540*5ef2456aSPeterChou1     emitBlock(CI);
541e975a473SJulie Hockett }
542e975a473SJulie Hockett 
543e975a473SJulie Hockett void ClangDocBitcodeWriter::emitBlock(const RecordInfo &I) {
544e975a473SJulie Hockett   StreamSubBlockGuard Block(Stream, BI_RECORD_BLOCK_ID);
545d0f9a872SJulie Hockett   emitRecord(I.USR, RECORD_USR);
546d0f9a872SJulie Hockett   emitRecord(I.Name, RECORD_NAME);
5472c1c9a24SJulie Hockett   emitRecord(I.Path, RECORD_PATH);
548d0f9a872SJulie Hockett   for (const auto &N : I.Namespace)
549d0f9a872SJulie Hockett     emitBlock(N, FieldId::F_namespace);
550d0f9a872SJulie Hockett   for (const auto &CI : I.Description)
551d0f9a872SJulie Hockett     emitBlock(CI);
552e975a473SJulie Hockett   if (I.DefLoc)
553ed8fceaaSKazu Hirata     emitRecord(*I.DefLoc, RECORD_DEFLOCATION);
554e975a473SJulie Hockett   for (const auto &L : I.Loc)
555e975a473SJulie Hockett     emitRecord(L, RECORD_LOCATION);
556edd690b0SVlad Serebrennikov   emitRecord(llvm::to_underlying(I.TagType), RECORD_TAG_TYPE);
557b1f01e27SJulie Hockett   emitRecord(I.IsTypeDef, RECORD_IS_TYPE_DEF);
558e975a473SJulie Hockett   for (const auto &N : I.Members)
559e975a473SJulie Hockett     emitBlock(N);
560e975a473SJulie Hockett   for (const auto &P : I.Parents)
561b59cd77cSJulie Hockett     emitBlock(P, FieldId::F_parent);
562e975a473SJulie Hockett   for (const auto &P : I.VirtualParents)
563b59cd77cSJulie Hockett     emitBlock(P, FieldId::F_vparent);
564ba3d595fSDiego Astiazaran   for (const auto &PB : I.Bases)
565ba3d595fSDiego Astiazaran     emitBlock(PB);
56621fb70c6SBrett Wilson   for (const auto &C : I.Children.Records)
5678899c29bSJulie Hockett     emitBlock(C, FieldId::F_child_record);
56821fb70c6SBrett Wilson   for (const auto &C : I.Children.Functions)
5698899c29bSJulie Hockett     emitBlock(C);
57021fb70c6SBrett Wilson   for (const auto &C : I.Children.Enums)
57121fb70c6SBrett Wilson     emitBlock(C);
57221fb70c6SBrett Wilson   for (const auto &C : I.Children.Typedefs)
5738899c29bSJulie Hockett     emitBlock(C);
5744a68babdSBrett Wilson   if (I.Template)
5754a68babdSBrett Wilson     emitBlock(*I.Template);
576e975a473SJulie Hockett }
577e975a473SJulie Hockett 
578ba3d595fSDiego Astiazaran void ClangDocBitcodeWriter::emitBlock(const BaseRecordInfo &I) {
579ba3d595fSDiego Astiazaran   StreamSubBlockGuard Block(Stream, BI_BASE_RECORD_BLOCK_ID);
580ba3d595fSDiego Astiazaran   emitRecord(I.USR, BASE_RECORD_USR);
581ba3d595fSDiego Astiazaran   emitRecord(I.Name, BASE_RECORD_NAME);
582ba3d595fSDiego Astiazaran   emitRecord(I.Path, BASE_RECORD_PATH);
583edd690b0SVlad Serebrennikov   emitRecord(llvm::to_underlying(I.TagType), BASE_RECORD_TAG_TYPE);
584ba3d595fSDiego Astiazaran   emitRecord(I.IsVirtual, BASE_RECORD_IS_VIRTUAL);
585ba3d595fSDiego Astiazaran   emitRecord(I.Access, BASE_RECORD_ACCESS);
586ba3d595fSDiego Astiazaran   emitRecord(I.IsParent, BASE_RECORD_IS_PARENT);
587ba3d595fSDiego Astiazaran   for (const auto &M : I.Members)
588ba3d595fSDiego Astiazaran     emitBlock(M);
58921fb70c6SBrett Wilson   for (const auto &C : I.Children.Functions)
590ba3d595fSDiego Astiazaran     emitBlock(C);
591ba3d595fSDiego Astiazaran }
592ba3d595fSDiego Astiazaran 
593e975a473SJulie Hockett void ClangDocBitcodeWriter::emitBlock(const FunctionInfo &I) {
594e975a473SJulie Hockett   StreamSubBlockGuard Block(Stream, BI_FUNCTION_BLOCK_ID);
595d0f9a872SJulie Hockett   emitRecord(I.USR, FUNCTION_USR);
596d0f9a872SJulie Hockett   emitRecord(I.Name, FUNCTION_NAME);
597d0f9a872SJulie Hockett   for (const auto &N : I.Namespace)
598d0f9a872SJulie Hockett     emitBlock(N, FieldId::F_namespace);
599d0f9a872SJulie Hockett   for (const auto &CI : I.Description)
600d0f9a872SJulie Hockett     emitBlock(CI);
6016a29ae4bSDiego Astiazaran   emitRecord(I.Access, FUNCTION_ACCESS);
602e975a473SJulie Hockett   emitRecord(I.IsMethod, FUNCTION_IS_METHOD);
603e975a473SJulie Hockett   if (I.DefLoc)
604ed8fceaaSKazu Hirata     emitRecord(*I.DefLoc, FUNCTION_DEFLOCATION);
605e975a473SJulie Hockett   for (const auto &L : I.Loc)
606e975a473SJulie Hockett     emitRecord(L, FUNCTION_LOCATION);
607b59cd77cSJulie Hockett   emitBlock(I.Parent, FieldId::F_parent);
608e975a473SJulie Hockett   emitBlock(I.ReturnType);
609e975a473SJulie Hockett   for (const auto &N : I.Params)
610e975a473SJulie Hockett     emitBlock(N);
6114a68babdSBrett Wilson   if (I.Template)
6124a68babdSBrett Wilson     emitBlock(*I.Template);
6134a68babdSBrett Wilson }
6144a68babdSBrett Wilson 
6154a68babdSBrett Wilson void ClangDocBitcodeWriter::emitBlock(const TemplateInfo &T) {
6164a68babdSBrett Wilson   StreamSubBlockGuard Block(Stream, BI_TEMPLATE_BLOCK_ID);
6174a68babdSBrett Wilson   for (const auto &P : T.Params)
6184a68babdSBrett Wilson     emitBlock(P);
6194a68babdSBrett Wilson   if (T.Specialization)
6204a68babdSBrett Wilson     emitBlock(*T.Specialization);
6214a68babdSBrett Wilson }
6224a68babdSBrett Wilson 
6234a68babdSBrett Wilson void ClangDocBitcodeWriter::emitBlock(const TemplateSpecializationInfo &T) {
6244a68babdSBrett Wilson   StreamSubBlockGuard Block(Stream, BI_TEMPLATE_SPECIALIZATION_BLOCK_ID);
6254a68babdSBrett Wilson   emitRecord(T.SpecializationOf, TEMPLATE_SPECIALIZATION_OF);
6264a68babdSBrett Wilson   for (const auto &P : T.Params)
6274a68babdSBrett Wilson     emitBlock(P);
6284a68babdSBrett Wilson }
6294a68babdSBrett Wilson 
6304a68babdSBrett Wilson void ClangDocBitcodeWriter::emitBlock(const TemplateParamInfo &T) {
6314a68babdSBrett Wilson   StreamSubBlockGuard Block(Stream, BI_TEMPLATE_PARAM_BLOCK_ID);
6324a68babdSBrett Wilson   emitRecord(T.Contents, TEMPLATE_PARAM_CONTENTS);
633e975a473SJulie Hockett }
634e975a473SJulie Hockett 
635d0f9a872SJulie Hockett bool ClangDocBitcodeWriter::dispatchInfoForWrite(Info *I) {
636d0f9a872SJulie Hockett   switch (I->IT) {
637d0f9a872SJulie Hockett   case InfoType::IT_namespace:
638d0f9a872SJulie Hockett     emitBlock(*static_cast<clang::doc::NamespaceInfo *>(I));
639d0f9a872SJulie Hockett     break;
640d0f9a872SJulie Hockett   case InfoType::IT_record:
641d0f9a872SJulie Hockett     emitBlock(*static_cast<clang::doc::RecordInfo *>(I));
642d0f9a872SJulie Hockett     break;
643d0f9a872SJulie Hockett   case InfoType::IT_enum:
644d0f9a872SJulie Hockett     emitBlock(*static_cast<clang::doc::EnumInfo *>(I));
645d0f9a872SJulie Hockett     break;
646d0f9a872SJulie Hockett   case InfoType::IT_function:
647d0f9a872SJulie Hockett     emitBlock(*static_cast<clang::doc::FunctionInfo *>(I));
648d0f9a872SJulie Hockett     break;
64921fb70c6SBrett Wilson   case InfoType::IT_typedef:
65021fb70c6SBrett Wilson     emitBlock(*static_cast<clang::doc::TypedefInfo *>(I));
65121fb70c6SBrett Wilson     break;
652d0f9a872SJulie Hockett   default:
653d0f9a872SJulie Hockett     llvm::errs() << "Unexpected info, unable to write.\n";
654d0f9a872SJulie Hockett     return true;
655d0f9a872SJulie Hockett   }
656d0f9a872SJulie Hockett   return false;
657d0f9a872SJulie Hockett }
658e975a473SJulie Hockett 
659e975a473SJulie Hockett } // namespace doc
660e975a473SJulie Hockett } // namespace clang
661