1 | //===-- BitcodeWriter.h - 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 | // This file implements a writer for serializing the clang-doc internal |
10 | // representation to LLVM bitcode. The writer takes in a stream and emits the |
11 | // generated bitcode to that stream. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEWRITER_H |
16 | #define |
17 | |
18 | #include "Representation.h" |
19 | #include "clang/AST/AST.h" |
20 | #include "llvm/ADT/DenseMap.h" |
21 | #include "llvm/ADT/SmallVector.h" |
22 | #include "llvm/ADT/StringRef.h" |
23 | #include "llvm/Bitstream/BitstreamWriter.h" |
24 | #include <initializer_list> |
25 | #include <vector> |
26 | |
27 | namespace clang { |
28 | namespace doc { |
29 | |
30 | // Current version number of clang-doc bitcode. |
31 | // Should be bumped when removing or changing BlockIds, RecordIds, or |
32 | // BitCodeConstants, though they can be added without breaking it. |
33 | static const unsigned VersionNumber = 3; |
34 | |
35 | struct BitCodeConstants { |
36 | static constexpr unsigned RecordSize = 32U; |
37 | static constexpr unsigned SignatureBitSize = 8U; |
38 | static constexpr unsigned SubblockIDSize = 4U; |
39 | static constexpr unsigned BoolSize = 1U; |
40 | static constexpr unsigned IntSize = 16U; |
41 | static constexpr unsigned StringLengthSize = 16U; |
42 | static constexpr unsigned FilenameLengthSize = 16U; |
43 | static constexpr unsigned LineNumberSize = 32U; |
44 | static constexpr unsigned ReferenceTypeSize = 8U; |
45 | static constexpr unsigned USRLengthSize = 6U; |
46 | static constexpr unsigned USRBitLengthSize = 8U; |
47 | static constexpr unsigned char Signature[4] = {'D', 'O', 'C', 'S'}; |
48 | static constexpr int USRHashSize = 20; |
49 | }; |
50 | |
51 | // New Ids need to be added to both the enum here and the relevant IdNameMap in |
52 | // the implementation file. |
53 | enum BlockId { |
54 | BI_VERSION_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID, |
55 | BI_NAMESPACE_BLOCK_ID, |
56 | BI_ENUM_BLOCK_ID, |
57 | BI_ENUM_VALUE_BLOCK_ID, |
58 | BI_TYPE_BLOCK_ID, |
59 | BI_FIELD_TYPE_BLOCK_ID, |
60 | BI_MEMBER_TYPE_BLOCK_ID, |
61 | BI_RECORD_BLOCK_ID, |
62 | BI_BASE_RECORD_BLOCK_ID, |
63 | BI_FUNCTION_BLOCK_ID, |
64 | , |
65 | BI_REFERENCE_BLOCK_ID, |
66 | BI_TEMPLATE_BLOCK_ID, |
67 | BI_TEMPLATE_SPECIALIZATION_BLOCK_ID, |
68 | BI_TEMPLATE_PARAM_BLOCK_ID, |
69 | BI_TYPEDEF_BLOCK_ID, |
70 | BI_LAST, |
71 | BI_FIRST = BI_VERSION_BLOCK_ID |
72 | }; |
73 | |
74 | // New Ids need to be added to the enum here, and to the relevant IdNameMap and |
75 | // initialization list in the implementation file. |
76 | enum RecordId { |
77 | VERSION = 1, |
78 | FUNCTION_USR, |
79 | FUNCTION_NAME, |
80 | FUNCTION_DEFLOCATION, |
81 | FUNCTION_LOCATION, |
82 | FUNCTION_ACCESS, |
83 | FUNCTION_IS_METHOD, |
84 | , |
85 | , |
86 | , |
87 | , |
88 | , |
89 | , |
90 | , |
91 | , |
92 | , |
93 | , |
94 | , |
95 | FIELD_TYPE_NAME, |
96 | FIELD_DEFAULT_VALUE, |
97 | MEMBER_TYPE_NAME, |
98 | MEMBER_TYPE_ACCESS, |
99 | NAMESPACE_USR, |
100 | NAMESPACE_NAME, |
101 | NAMESPACE_PATH, |
102 | ENUM_USR, |
103 | ENUM_NAME, |
104 | ENUM_DEFLOCATION, |
105 | ENUM_LOCATION, |
106 | ENUM_SCOPED, |
107 | ENUM_VALUE_NAME, |
108 | ENUM_VALUE_VALUE, |
109 | ENUM_VALUE_EXPR, |
110 | RECORD_USR, |
111 | RECORD_NAME, |
112 | RECORD_PATH, |
113 | RECORD_DEFLOCATION, |
114 | RECORD_LOCATION, |
115 | RECORD_TAG_TYPE, |
116 | RECORD_IS_TYPE_DEF, |
117 | BASE_RECORD_USR, |
118 | BASE_RECORD_NAME, |
119 | BASE_RECORD_PATH, |
120 | BASE_RECORD_TAG_TYPE, |
121 | BASE_RECORD_IS_VIRTUAL, |
122 | BASE_RECORD_ACCESS, |
123 | BASE_RECORD_IS_PARENT, |
124 | REFERENCE_USR, |
125 | REFERENCE_NAME, |
126 | REFERENCE_QUAL_NAME, |
127 | REFERENCE_TYPE, |
128 | REFERENCE_PATH, |
129 | REFERENCE_FIELD, |
130 | TEMPLATE_PARAM_CONTENTS, |
131 | TEMPLATE_SPECIALIZATION_OF, |
132 | TYPEDEF_USR, |
133 | TYPEDEF_NAME, |
134 | TYPEDEF_DEFLOCATION, |
135 | TYPEDEF_IS_USING, |
136 | RI_LAST, |
137 | RI_FIRST = VERSION |
138 | }; |
139 | |
140 | static constexpr unsigned BlockIdCount = BI_LAST - BI_FIRST; |
141 | static constexpr unsigned RecordIdCount = RI_LAST - RI_FIRST; |
142 | |
143 | // Identifiers for differentiating between subblocks |
144 | enum class FieldId { |
145 | F_default, |
146 | F_namespace, |
147 | F_parent, |
148 | F_vparent, |
149 | F_type, |
150 | F_child_namespace, |
151 | F_child_record |
152 | }; |
153 | |
154 | class ClangDocBitcodeWriter { |
155 | public: |
156 | ClangDocBitcodeWriter(llvm::BitstreamWriter &Stream) : Stream(Stream) { |
157 | emitHeader(); |
158 | emitBlockInfoBlock(); |
159 | emitVersionBlock(); |
160 | } |
161 | |
162 | // Write a specific info to a bitcode stream. |
163 | bool dispatchInfoForWrite(Info *I); |
164 | |
165 | // Block emission of different info types. |
166 | void emitBlock(const NamespaceInfo &I); |
167 | void emitBlock(const RecordInfo &I); |
168 | void emitBlock(const BaseRecordInfo &I); |
169 | void emitBlock(const FunctionInfo &I); |
170 | void emitBlock(const EnumInfo &I); |
171 | void emitBlock(const EnumValueInfo &I); |
172 | void emitBlock(const TypeInfo &B); |
173 | void emitBlock(const TypedefInfo &B); |
174 | void emitBlock(const FieldTypeInfo &B); |
175 | void emitBlock(const MemberTypeInfo &T); |
176 | void (const CommentInfo &B); |
177 | void emitBlock(const TemplateInfo &T); |
178 | void emitBlock(const TemplateSpecializationInfo &T); |
179 | void emitBlock(const TemplateParamInfo &T); |
180 | void emitBlock(const Reference &B, FieldId F); |
181 | |
182 | private: |
183 | class AbbreviationMap { |
184 | llvm::DenseMap<unsigned, unsigned> Abbrevs; |
185 | |
186 | public: |
187 | AbbreviationMap() : Abbrevs(RecordIdCount) {} |
188 | |
189 | void add(RecordId RID, unsigned AbbrevID); |
190 | unsigned get(RecordId RID) const; |
191 | }; |
192 | |
193 | class StreamSubBlockGuard { |
194 | llvm::BitstreamWriter &Stream; |
195 | |
196 | public: |
197 | StreamSubBlockGuard(llvm::BitstreamWriter &Stream_, BlockId ID) |
198 | : Stream(Stream_) { |
199 | // NOTE: SubBlockIDSize could theoretically be calculated on the fly, |
200 | // based on the initialization list of records in each block. |
201 | Stream.EnterSubblock(BlockID: ID, CodeLen: BitCodeConstants::SubblockIDSize); |
202 | } |
203 | |
204 | StreamSubBlockGuard(const StreamSubBlockGuard &) = delete; |
205 | StreamSubBlockGuard &operator=(const StreamSubBlockGuard &) = delete; |
206 | |
207 | ~StreamSubBlockGuard() { Stream.ExitBlock(); } |
208 | }; |
209 | |
210 | // Emission of validation and overview blocks. |
211 | void (); |
212 | void emitVersionBlock(); |
213 | void emitRecordID(RecordId ID); |
214 | void emitBlockID(BlockId ID); |
215 | void emitBlockInfoBlock(); |
216 | void emitBlockInfo(BlockId BID, const std::vector<RecordId> &RIDs); |
217 | |
218 | // Emission of individual record types. |
219 | void emitRecord(StringRef Str, RecordId ID); |
220 | void emitRecord(const SymbolID &Str, RecordId ID); |
221 | void emitRecord(const Location &Loc, RecordId ID); |
222 | void emitRecord(const Reference &Ref, RecordId ID); |
223 | void emitRecord(bool Value, RecordId ID); |
224 | void emitRecord(int Value, RecordId ID); |
225 | void emitRecord(unsigned Value, RecordId ID); |
226 | void emitRecord(const TemplateInfo &Templ); |
227 | bool prepRecordData(RecordId ID, bool ShouldEmit = true); |
228 | |
229 | // Emission of appropriate abbreviation type. |
230 | void emitAbbrev(RecordId ID, BlockId Block); |
231 | |
232 | // Static size is the maximum length of the block/record names we're pushing |
233 | // to this + 1. Longest is currently `MemberTypeBlock` at 15 chars. |
234 | SmallVector<uint32_t, BitCodeConstants::RecordSize> Record; |
235 | llvm::BitstreamWriter &Stream; |
236 | AbbreviationMap Abbrevs; |
237 | }; |
238 | |
239 | } // namespace doc |
240 | } // namespace clang |
241 | |
242 | #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEWRITER_H |
243 | |