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 LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEWRITER_H
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
27namespace clang {
28namespace 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.
33static const unsigned VersionNumber = 3;
34
35struct 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.
53enum 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 BI_COMMENT_BLOCK_ID,
65 BI_REFERENCE_BLOCK_ID,
66 BI_TEMPLATE_BLOCK_ID,
67 BI_TEMPLATE_SPECIALIZATION_BLOCK_ID,
68 BI_TEMPLATE_PARAM_BLOCK_ID,
69 BI_CONSTRAINT_BLOCK_ID,
70 BI_TYPEDEF_BLOCK_ID,
71 BI_CONCEPT_BLOCK_ID,
72 BI_VAR_BLOCK_ID,
73 BI_FRIEND_BLOCK_ID,
74 BI_LAST,
75 BI_FIRST = BI_VERSION_BLOCK_ID
76};
77
78// New Ids need to be added to the enum here, and to the relevant IdNameMap and
79// initialization list in the implementation file.
80enum RecordId {
81 VERSION = 1,
82 FUNCTION_USR,
83 FUNCTION_NAME,
84 FUNCTION_DEFLOCATION,
85 FUNCTION_LOCATION,
86 FUNCTION_ACCESS,
87 FUNCTION_IS_METHOD,
88 FUNCTION_IS_STATIC,
89 COMMENT_KIND,
90 COMMENT_TEXT,
91 COMMENT_NAME,
92 COMMENT_DIRECTION,
93 COMMENT_PARAMNAME,
94 COMMENT_CLOSENAME,
95 COMMENT_SELFCLOSING,
96 COMMENT_EXPLICIT,
97 COMMENT_ATTRKEY,
98 COMMENT_ATTRVAL,
99 COMMENT_ARG,
100 TYPE_IS_BUILTIN,
101 TYPE_IS_TEMPLATE,
102 FIELD_TYPE_NAME,
103 FIELD_DEFAULT_VALUE,
104 FIELD_TYPE_IS_BUILTIN,
105 FIELD_TYPE_IS_TEMPLATE,
106 MEMBER_TYPE_NAME,
107 MEMBER_TYPE_ACCESS,
108 MEMBER_TYPE_IS_STATIC,
109 MEMBER_TYPE_IS_BUILTIN,
110 MEMBER_TYPE_IS_TEMPLATE,
111 NAMESPACE_USR,
112 NAMESPACE_NAME,
113 NAMESPACE_PATH,
114 ENUM_USR,
115 ENUM_NAME,
116 ENUM_DEFLOCATION,
117 ENUM_LOCATION,
118 ENUM_SCOPED,
119 ENUM_VALUE_NAME,
120 ENUM_VALUE_VALUE,
121 ENUM_VALUE_EXPR,
122 RECORD_USR,
123 RECORD_NAME,
124 RECORD_PATH,
125 RECORD_DEFLOCATION,
126 RECORD_LOCATION,
127 RECORD_TAG_TYPE,
128 RECORD_IS_TYPE_DEF,
129 RECORD_MANGLED_NAME,
130 BASE_RECORD_USR,
131 BASE_RECORD_NAME,
132 BASE_RECORD_PATH,
133 BASE_RECORD_TAG_TYPE,
134 BASE_RECORD_IS_VIRTUAL,
135 BASE_RECORD_ACCESS,
136 BASE_RECORD_IS_PARENT,
137 REFERENCE_USR,
138 REFERENCE_NAME,
139 REFERENCE_QUAL_NAME,
140 REFERENCE_TYPE,
141 REFERENCE_PATH,
142 REFERENCE_FIELD,
143 TEMPLATE_PARAM_CONTENTS,
144 TEMPLATE_SPECIALIZATION_OF,
145 TYPEDEF_USR,
146 TYPEDEF_NAME,
147 TYPEDEF_DEFLOCATION,
148 TYPEDEF_IS_USING,
149 CONCEPT_USR,
150 CONCEPT_NAME,
151 CONCEPT_IS_TYPE,
152 CONCEPT_CONSTRAINT_EXPRESSION,
153 CONSTRAINT_EXPRESSION,
154 VAR_USR,
155 VAR_NAME,
156 VAR_DEFLOCATION,
157 VAR_IS_STATIC,
158 FRIEND_IS_CLASS,
159 RI_LAST,
160 RI_FIRST = VERSION
161};
162
163static constexpr unsigned BlockIdCount = BI_LAST - BI_FIRST;
164static constexpr unsigned RecordIdCount = RI_LAST - RI_FIRST;
165
166// Identifiers for differentiating between subblocks
167enum class FieldId {
168 F_default,
169 F_namespace,
170 F_parent,
171 F_vparent,
172 F_type,
173 F_child_namespace,
174 F_child_record,
175 F_concept,
176 F_friend
177};
178
179class ClangDocBitcodeWriter {
180public:
181 ClangDocBitcodeWriter(llvm::BitstreamWriter &Stream) : Stream(Stream) {
182 emitHeader();
183 emitBlockInfoBlock();
184 emitVersionBlock();
185 }
186
187 // Write a specific info to a bitcode stream.
188 bool dispatchInfoForWrite(Info *I);
189
190 // Block emission of different info types.
191 void emitBlock(const NamespaceInfo &I);
192 void emitBlock(const RecordInfo &I);
193 void emitBlock(const BaseRecordInfo &I);
194 void emitBlock(const FunctionInfo &I);
195 void emitBlock(const EnumInfo &I);
196 void emitBlock(const EnumValueInfo &I);
197 void emitBlock(const TypeInfo &B);
198 void emitBlock(const TypedefInfo &B);
199 void emitBlock(const FieldTypeInfo &B);
200 void emitBlock(const MemberTypeInfo &T);
201 void emitBlock(const CommentInfo &B);
202 void emitBlock(const TemplateInfo &T);
203 void emitBlock(const TemplateSpecializationInfo &T);
204 void emitBlock(const TemplateParamInfo &T);
205 void emitBlock(const ConceptInfo &T);
206 void emitBlock(const ConstraintInfo &T);
207 void emitBlock(const Reference &B, FieldId F);
208 void emitBlock(const FriendInfo &R);
209 void emitBlock(const VarInfo &B);
210
211private:
212 class AbbreviationMap {
213 llvm::DenseMap<unsigned, unsigned> Abbrevs;
214
215 public:
216 AbbreviationMap() : Abbrevs(RecordIdCount) {}
217
218 void add(RecordId RID, unsigned AbbrevID);
219 unsigned get(RecordId RID) const;
220 };
221
222 class StreamSubBlockGuard {
223 llvm::BitstreamWriter &Stream;
224
225 public:
226 StreamSubBlockGuard(llvm::BitstreamWriter &Stream_, BlockId ID)
227 : Stream(Stream_) {
228 // NOTE: SubBlockIDSize could theoretically be calculated on the fly,
229 // based on the initialization list of records in each block.
230 Stream.EnterSubblock(BlockID: ID, CodeLen: BitCodeConstants::SubblockIDSize);
231 }
232
233 StreamSubBlockGuard(const StreamSubBlockGuard &) = delete;
234 StreamSubBlockGuard &operator=(const StreamSubBlockGuard &) = delete;
235
236 ~StreamSubBlockGuard() { Stream.ExitBlock(); }
237 };
238
239 // Emission of validation and overview blocks.
240 void emitHeader();
241 void emitVersionBlock();
242 void emitRecordID(RecordId ID);
243 void emitBlockID(BlockId ID);
244 void emitBlockInfoBlock();
245 void emitBlockInfo(BlockId BID, const std::vector<RecordId> &RIDs);
246
247 // Emission of individual record types.
248 void emitRecord(StringRef Str, RecordId ID);
249 void emitRecord(const SymbolID &Str, RecordId ID);
250 void emitRecord(const Location &Loc, RecordId ID);
251 void emitRecord(const Reference &Ref, RecordId ID);
252 void emitRecord(bool Value, RecordId ID);
253 void emitRecord(int Value, RecordId ID);
254 void emitRecord(unsigned Value, RecordId ID);
255 void emitRecord(const TemplateInfo &Templ);
256 bool prepRecordData(RecordId ID, bool ShouldEmit = true);
257
258 // Emission of appropriate abbreviation type.
259 void emitAbbrev(RecordId ID, BlockId Block);
260
261 // Static size is the maximum length of the block/record names we're pushing
262 // to this + 1. Longest is currently `MemberTypeBlock` at 15 chars.
263 SmallVector<uint32_t, BitCodeConstants::RecordSize> Record;
264 llvm::BitstreamWriter &Stream;
265 AbbreviationMap Abbrevs;
266};
267
268} // namespace doc
269} // namespace clang
270
271#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEWRITER_H
272

source code of clang-tools-extra/clang-doc/BitcodeWriter.h