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