xref: /llvm-project/clang-tools-extra/clang-doc/BitcodeWriter.h (revision 4a68babd9973f043fd3e40f159fbb990880606a6)
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 
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   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_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   COMMENT_KIND,
85   COMMENT_TEXT,
86   COMMENT_NAME,
87   COMMENT_DIRECTION,
88   COMMENT_PARAMNAME,
89   COMMENT_CLOSENAME,
90   COMMENT_SELFCLOSING,
91   COMMENT_EXPLICIT,
92   COMMENT_ATTRKEY,
93   COMMENT_ATTRVAL,
94   COMMENT_ARG,
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:
ClangDocBitcodeWriter(llvm::BitstreamWriter & Stream)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 emitBlock(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:
AbbreviationMap()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:
StreamSubBlockGuard(llvm::BitstreamWriter & Stream_,BlockId ID)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(ID, BitCodeConstants::SubblockIDSize);
202     }
203 
204     StreamSubBlockGuard(const StreamSubBlockGuard &) = delete;
205     StreamSubBlockGuard &operator=(const StreamSubBlockGuard &) = delete;
206 
~StreamSubBlockGuard()207     ~StreamSubBlockGuard() { Stream.ExitBlock(); }
208   };
209 
210   // Emission of validation and overview blocks.
211   void emitHeader();
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