Line data Source code
1 : //===-- BitcodeWriter.h - ClangDoc Bitcode Writer --------------*- C++ -*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file implements a writer for serializing the clang-doc internal
11 : // representation to LLVM bitcode. The writer takes in a stream and emits the
12 : // generated bitcode to that stream.
13 : //
14 : //===----------------------------------------------------------------------===//
15 :
16 : #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEWRITER_H
17 : #define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEWRITER_H
18 :
19 : #include "Representation.h"
20 : #include "clang/AST/AST.h"
21 : #include "llvm/ADT/DenseMap.h"
22 : #include "llvm/ADT/SmallVector.h"
23 : #include "llvm/ADT/StringRef.h"
24 : #include "llvm/Bitcode/BitstreamWriter.h"
25 : #include <initializer_list>
26 : #include <vector>
27 :
28 : namespace clang {
29 : namespace doc {
30 :
31 : // Current version number of clang-doc bitcode.
32 : // Should be bumped when removing or changing BlockIds, RecordIds, or
33 : // BitCodeConstants, though they can be added without breaking it.
34 : static const unsigned VersionNumber = 2;
35 :
36 : struct BitCodeConstants {
37 : static constexpr unsigned RecordSize = 32U;
38 : static constexpr unsigned SignatureBitSize = 8U;
39 : static constexpr unsigned SubblockIDSize = 4U;
40 : static constexpr unsigned BoolSize = 1U;
41 : static constexpr unsigned IntSize = 16U;
42 : static constexpr unsigned StringLengthSize = 16U;
43 : static constexpr unsigned FilenameLengthSize = 16U;
44 : static constexpr unsigned LineNumberSize = 16U;
45 : static constexpr unsigned ReferenceTypeSize = 8U;
46 : static constexpr unsigned USRLengthSize = 6U;
47 : static constexpr unsigned USRBitLengthSize = 8U;
48 : static constexpr char Signature[4] = {'D', 'O', 'C', 'S'};
49 : static constexpr int USRHashSize = 20;
50 : };
51 :
52 : // New Ids need to be added to both the enum here and the relevant IdNameMap in
53 : // the implementation file.
54 : enum BlockId {
55 : BI_VERSION_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
56 : BI_NAMESPACE_BLOCK_ID,
57 : BI_ENUM_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_FUNCTION_BLOCK_ID,
63 : BI_COMMENT_BLOCK_ID,
64 : BI_REFERENCE_BLOCK_ID,
65 : BI_LAST,
66 : BI_FIRST = BI_VERSION_BLOCK_ID
67 : };
68 :
69 : // New Ids need to be added to the enum here, and to the relevant IdNameMap and
70 : // initialization list in the implementation file.
71 : enum RecordId {
72 : VERSION = 1,
73 : FUNCTION_USR,
74 : FUNCTION_NAME,
75 : FUNCTION_DEFLOCATION,
76 : FUNCTION_LOCATION,
77 : FUNCTION_ACCESS,
78 : FUNCTION_IS_METHOD,
79 : COMMENT_KIND,
80 : COMMENT_TEXT,
81 : COMMENT_NAME,
82 : COMMENT_DIRECTION,
83 : COMMENT_PARAMNAME,
84 : COMMENT_CLOSENAME,
85 : COMMENT_SELFCLOSING,
86 : COMMENT_EXPLICIT,
87 : COMMENT_ATTRKEY,
88 : COMMENT_ATTRVAL,
89 : COMMENT_ARG,
90 : FIELD_TYPE_NAME,
91 : MEMBER_TYPE_NAME,
92 : MEMBER_TYPE_ACCESS,
93 : NAMESPACE_USR,
94 : NAMESPACE_NAME,
95 : ENUM_USR,
96 : ENUM_NAME,
97 : ENUM_DEFLOCATION,
98 : ENUM_LOCATION,
99 : ENUM_MEMBER,
100 : ENUM_SCOPED,
101 : RECORD_USR,
102 : RECORD_NAME,
103 : RECORD_DEFLOCATION,
104 : RECORD_LOCATION,
105 : RECORD_TAG_TYPE,
106 : REFERENCE_USR,
107 : REFERENCE_NAME,
108 : REFERENCE_TYPE,
109 : REFERENCE_FIELD,
110 : RI_LAST,
111 : RI_FIRST = VERSION
112 : };
113 :
114 : static constexpr unsigned BlockIdCount = BI_LAST - BI_FIRST;
115 : static constexpr unsigned RecordIdCount = RI_LAST - RI_FIRST;
116 :
117 : // Identifiers for differentiating between subblocks
118 : enum class FieldId {
119 : F_default,
120 : F_namespace,
121 : F_parent,
122 : F_vparent,
123 : F_type,
124 : F_child_namespace,
125 : F_child_record
126 : };
127 :
128 : class ClangDocBitcodeWriter {
129 : public:
130 6 : ClangDocBitcodeWriter(llvm::BitstreamWriter &Stream) : Stream(Stream) {
131 6 : emitHeader();
132 6 : emitBlockInfoBlock();
133 6 : emitVersionBlock();
134 6 : }
135 :
136 : // Write a specific info to a bitcode stream.
137 : bool dispatchInfoForWrite(Info *I);
138 :
139 : // Block emission of different info types.
140 : void emitBlock(const NamespaceInfo &I);
141 : void emitBlock(const RecordInfo &I);
142 : void emitBlock(const FunctionInfo &I);
143 : void emitBlock(const EnumInfo &I);
144 : void emitBlock(const TypeInfo &B);
145 : void emitBlock(const FieldTypeInfo &B);
146 : void emitBlock(const MemberTypeInfo &B);
147 : void emitBlock(const CommentInfo &B);
148 : void emitBlock(const Reference &B, FieldId F);
149 :
150 : private:
151 : class AbbreviationMap {
152 : llvm::DenseMap<unsigned, unsigned> Abbrevs;
153 :
154 : public:
155 6 : AbbreviationMap() : Abbrevs(RecordIdCount) {}
156 :
157 : void add(RecordId RID, unsigned AbbrevID);
158 : unsigned get(RecordId RID) const;
159 : };
160 :
161 : class StreamSubBlockGuard {
162 : llvm::BitstreamWriter &Stream;
163 :
164 : public:
165 : StreamSubBlockGuard(llvm::BitstreamWriter &Stream_, BlockId ID)
166 : : Stream(Stream_) {
167 : // NOTE: SubBlockIDSize could theoretically be calculated on the fly,
168 : // based on the initialization list of records in each block.
169 : Stream.EnterSubblock(ID, BitCodeConstants::SubblockIDSize);
170 : }
171 :
172 : StreamSubBlockGuard(const StreamSubBlockGuard &) = delete;
173 : StreamSubBlockGuard &operator=(const StreamSubBlockGuard &) = delete;
174 :
175 : ~StreamSubBlockGuard() { Stream.ExitBlock(); }
176 : };
177 :
178 : // Emission of validation and overview blocks.
179 : void emitHeader();
180 : void emitVersionBlock();
181 : void emitRecordID(RecordId ID);
182 : void emitBlockID(BlockId ID);
183 : void emitBlockInfoBlock();
184 : void emitBlockInfo(BlockId BID, const std::vector<RecordId> &RIDs);
185 :
186 : // Emission of individual record types.
187 : void emitRecord(StringRef Str, RecordId ID);
188 : void emitRecord(const SymbolID &Str, RecordId ID);
189 : void emitRecord(const Location &Loc, RecordId ID);
190 : void emitRecord(const Reference &Ref, RecordId ID);
191 : void emitRecord(bool Value, RecordId ID);
192 : void emitRecord(int Value, RecordId ID);
193 : void emitRecord(unsigned Value, RecordId ID);
194 : bool prepRecordData(RecordId ID, bool ShouldEmit = true);
195 :
196 : // Emission of appropriate abbreviation type.
197 : void emitAbbrev(RecordId ID, BlockId Block);
198 :
199 : // Static size is the maximum length of the block/record names we're pushing
200 : // to this + 1. Longest is currently `MemberTypeBlock` at 15 chars.
201 : SmallVector<uint32_t, BitCodeConstants::RecordSize> Record;
202 : llvm::BitstreamWriter &Stream;
203 : AbbreviationMap Abbrevs;
204 : };
205 :
206 : } // namespace doc
207 : } // namespace clang
208 :
209 : #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEWRITER_H
|