blob: ab997af739ea107d9aed3033840d4d615dc0ec4e [file] [log] [blame]
Julie Hockette975a472018-03-22 23:34:46 +00001//===-- 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
28namespace clang {
29namespace 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.
Julie Hockettb59cd772018-05-04 17:02:13 +000034static const unsigned VersionNumber = 2;
Julie Hockette975a472018-03-22 23:34:46 +000035
36struct BitCodeConstants {
37 static constexpr unsigned RecordSize = 16U;
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};
49
50// New Ids need to be added to both the enum here and the relevant IdNameMap in
51// the implementation file.
52enum BlockId {
53 BI_VERSION_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
54 BI_NAMESPACE_BLOCK_ID,
55 BI_ENUM_BLOCK_ID,
56 BI_TYPE_BLOCK_ID,
57 BI_FIELD_TYPE_BLOCK_ID,
58 BI_MEMBER_TYPE_BLOCK_ID,
59 BI_RECORD_BLOCK_ID,
60 BI_FUNCTION_BLOCK_ID,
61 BI_COMMENT_BLOCK_ID,
Julie Hockettb59cd772018-05-04 17:02:13 +000062 BI_REFERENCE_BLOCK_ID,
63 BI_LAST,
64 BI_FIRST = BI_VERSION_BLOCK_ID
Julie Hockette975a472018-03-22 23:34:46 +000065};
66
67// New Ids need to be added to the enum here, and to the relevant IdNameMap and
68// initialization list in the implementation file.
Julie Hockettb59cd772018-05-04 17:02:13 +000069#define INFORECORDS(X) X##_USR, X##_NAME
Julie Hockette975a472018-03-22 23:34:46 +000070
71enum RecordId {
72 VERSION = 1,
73 INFORECORDS(FUNCTION),
74 FUNCTION_DEFLOCATION,
75 FUNCTION_LOCATION,
Julie Hockette975a472018-03-22 23:34:46 +000076 FUNCTION_ACCESS,
77 FUNCTION_IS_METHOD,
78 COMMENT_KIND,
79 COMMENT_TEXT,
80 COMMENT_NAME,
81 COMMENT_DIRECTION,
82 COMMENT_PARAMNAME,
83 COMMENT_CLOSENAME,
84 COMMENT_SELFCLOSING,
85 COMMENT_EXPLICIT,
86 COMMENT_ATTRKEY,
87 COMMENT_ATTRVAL,
88 COMMENT_ARG,
Julie Hockette975a472018-03-22 23:34:46 +000089 FIELD_TYPE_NAME,
Julie Hockette975a472018-03-22 23:34:46 +000090 MEMBER_TYPE_NAME,
91 MEMBER_TYPE_ACCESS,
92 INFORECORDS(NAMESPACE),
93 INFORECORDS(ENUM),
94 ENUM_DEFLOCATION,
95 ENUM_LOCATION,
96 ENUM_MEMBER,
97 ENUM_SCOPED,
98 INFORECORDS(RECORD),
99 RECORD_DEFLOCATION,
100 RECORD_LOCATION,
101 RECORD_TAG_TYPE,
Julie Hockettb59cd772018-05-04 17:02:13 +0000102 REFERENCE_USR,
103 REFERENCE_NAME,
104 REFERENCE_TYPE,
105 REFERENCE_FIELD,
106 RI_LAST,
107 RI_FIRST = VERSION
Julie Hockette975a472018-03-22 23:34:46 +0000108};
109
Julie Hockettb59cd772018-05-04 17:02:13 +0000110static constexpr unsigned BlockIdCount = BI_LAST - BI_FIRST;
111static constexpr unsigned RecordIdCount = RI_LAST - RI_FIRST;
Julie Hockette975a472018-03-22 23:34:46 +0000112
113#undef INFORECORDS
114
Julie Hockettb59cd772018-05-04 17:02:13 +0000115// Identifiers for differentiating between subblocks
116enum class FieldId { F_namespace = 1, F_parent, F_vparent, F_type };
117
Julie Hockette975a472018-03-22 23:34:46 +0000118class ClangDocBitcodeWriter {
119public:
120 ClangDocBitcodeWriter(llvm::BitstreamWriter &Stream) : Stream(Stream) {
121 emitHeader();
122 emitBlockInfoBlock();
123 emitVersionBlock();
124 }
125
126#ifndef NDEBUG // Don't want explicit dtor unless needed.
127 ~ClangDocBitcodeWriter() {
128 // Check that the static size is large-enough.
129 assert(Record.capacity() > BitCodeConstants::RecordSize);
130 }
131#endif
132
133 // Block emission of different info types.
134 void emitBlock(const NamespaceInfo &I);
135 void emitBlock(const RecordInfo &I);
136 void emitBlock(const FunctionInfo &I);
137 void emitBlock(const EnumInfo &I);
138 void emitBlock(const TypeInfo &B);
139 void emitBlock(const FieldTypeInfo &B);
140 void emitBlock(const MemberTypeInfo &B);
141 void emitBlock(const CommentInfo &B);
Julie Hockettb59cd772018-05-04 17:02:13 +0000142 void emitBlock(const Reference &B, FieldId F);
Julie Hockette975a472018-03-22 23:34:46 +0000143
144private:
145 class AbbreviationMap {
146 llvm::DenseMap<unsigned, unsigned> Abbrevs;
147
148 public:
149 AbbreviationMap() : Abbrevs(RecordIdCount) {}
150
151 void add(RecordId RID, unsigned AbbrevID);
152 unsigned get(RecordId RID) const;
153 };
154
155 class StreamSubBlockGuard {
156 llvm::BitstreamWriter &Stream;
157
158 public:
159 StreamSubBlockGuard(llvm::BitstreamWriter &Stream_, BlockId ID)
160 : Stream(Stream_) {
161 // NOTE: SubBlockIDSize could theoretically be calculated on the fly,
162 // based on the initialization list of records in each block.
163 Stream.EnterSubblock(ID, BitCodeConstants::SubblockIDSize);
164 }
165
166 StreamSubBlockGuard() = default;
167 StreamSubBlockGuard(const StreamSubBlockGuard &) = delete;
168 StreamSubBlockGuard &operator=(const StreamSubBlockGuard &) = delete;
169
170 ~StreamSubBlockGuard() { Stream.ExitBlock(); }
171 };
172
173 // Emission of validation and overview blocks.
174 void emitHeader();
175 void emitVersionBlock();
176 void emitRecordID(RecordId ID);
177 void emitBlockID(BlockId ID);
178 void emitBlockInfoBlock();
179 void emitBlockInfo(BlockId BID, const std::vector<RecordId> &RIDs);
180
181 // Emission of individual record types.
182 void emitRecord(StringRef Str, RecordId ID);
183 void emitRecord(const SymbolID &Str, RecordId ID);
184 void emitRecord(const Location &Loc, RecordId ID);
185 void emitRecord(const Reference &Ref, RecordId ID);
186 void emitRecord(bool Value, RecordId ID);
187 void emitRecord(int Value, RecordId ID);
188 void emitRecord(unsigned Value, RecordId ID);
189 bool prepRecordData(RecordId ID, bool ShouldEmit = true);
190
191 // Emission of appropriate abbreviation type.
192 void emitAbbrev(RecordId ID, BlockId Block);
193
194 // Static size is the maximum length of the block/record names we're pushing
195 // to this + 1. Longest is currently `MemberTypeBlock` at 15 chars.
196 SmallVector<uint32_t, BitCodeConstants::RecordSize> Record;
197 llvm::BitstreamWriter &Stream;
198 AbbreviationMap Abbrevs;
199};
200
201} // namespace doc
202} // namespace clang
203
204#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEWRITER_H