blob: dcb7c91e7bc9e487ee48d187a25854ae46cfdbee [file] [log] [blame]
Julie Hockette975a472018-03-22 23:34:46 +00001//===-- BitcodeWriter.h - ClangDoc Bitcode Writer --------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Julie Hockette975a472018-03-22 23:34:46 +00006//
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"
Francis Visoiu Mistrihe0308272019-07-03 22:40:07 +000023#include "llvm/Bitstream/BitstreamWriter.h"
Julie Hockette975a472018-03-22 23:34:46 +000024#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.
Julie Hockettb59cd772018-05-04 17:02:13 +000033static const unsigned VersionNumber = 2;
Julie Hockette975a472018-03-22 23:34:46 +000034
35struct BitCodeConstants {
Julie Hockettd0f9a872018-06-04 17:22:20 +000036 static constexpr unsigned RecordSize = 32U;
Julie Hockette975a472018-03-22 23:34:46 +000037 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 = 16U;
44 static constexpr unsigned ReferenceTypeSize = 8U;
45 static constexpr unsigned USRLengthSize = 6U;
46 static constexpr unsigned USRBitLengthSize = 8U;
JF Bastien0e828952019-06-26 19:50:12 +000047 static constexpr unsigned char Signature[4] = {'D', 'O', 'C', 'S'};
Julie Hockettd0f9a872018-06-04 17:22:20 +000048 static constexpr int USRHashSize = 20;
Julie Hockette975a472018-03-22 23:34:46 +000049};
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_TYPE_BLOCK_ID,
58 BI_FIELD_TYPE_BLOCK_ID,
59 BI_MEMBER_TYPE_BLOCK_ID,
60 BI_RECORD_BLOCK_ID,
61 BI_FUNCTION_BLOCK_ID,
62 BI_COMMENT_BLOCK_ID,
Julie Hockettb59cd772018-05-04 17:02:13 +000063 BI_REFERENCE_BLOCK_ID,
64 BI_LAST,
65 BI_FIRST = BI_VERSION_BLOCK_ID
Julie Hockette975a472018-03-22 23:34:46 +000066};
67
68// New Ids need to be added to the enum here, and to the relevant IdNameMap and
69// initialization list in the implementation file.
Julie Hockette975a472018-03-22 23:34:46 +000070enum RecordId {
71 VERSION = 1,
Julie Hockett8899c292018-08-02 20:10:17 +000072 FUNCTION_USR,
73 FUNCTION_NAME,
Julie Hockette975a472018-03-22 23:34:46 +000074 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,
Julie Hockett8899c292018-08-02 20:10:17 +000092 NAMESPACE_USR,
93 NAMESPACE_NAME,
Julie Hockett2c1c9a22019-07-12 18:32:00 +000094 NAMESPACE_PATH,
Julie Hockett8899c292018-08-02 20:10:17 +000095 ENUM_USR,
96 ENUM_NAME,
Julie Hockette975a472018-03-22 23:34:46 +000097 ENUM_DEFLOCATION,
98 ENUM_LOCATION,
99 ENUM_MEMBER,
100 ENUM_SCOPED,
Julie Hockett8899c292018-08-02 20:10:17 +0000101 RECORD_USR,
102 RECORD_NAME,
Julie Hockett2c1c9a22019-07-12 18:32:00 +0000103 RECORD_PATH,
Julie Hockette975a472018-03-22 23:34:46 +0000104 RECORD_DEFLOCATION,
105 RECORD_LOCATION,
106 RECORD_TAG_TYPE,
Julie Hockettb1f01e22019-06-24 19:31:02 +0000107 RECORD_IS_TYPE_DEF,
Julie Hockettb59cd772018-05-04 17:02:13 +0000108 REFERENCE_USR,
109 REFERENCE_NAME,
110 REFERENCE_TYPE,
Julie Hockett2c1c9a22019-07-12 18:32:00 +0000111 REFERENCE_PATH,
Diego Astiazaran15e468e2019-08-06 00:11:34 +0000112 REFERENCE_IS_IN_GLOBAL_NAMESPACE,
Julie Hockettb59cd772018-05-04 17:02:13 +0000113 REFERENCE_FIELD,
114 RI_LAST,
115 RI_FIRST = VERSION
Julie Hockette975a472018-03-22 23:34:46 +0000116};
117
Julie Hockettb59cd772018-05-04 17:02:13 +0000118static constexpr unsigned BlockIdCount = BI_LAST - BI_FIRST;
119static constexpr unsigned RecordIdCount = RI_LAST - RI_FIRST;
Julie Hockette975a472018-03-22 23:34:46 +0000120
Julie Hockettb59cd772018-05-04 17:02:13 +0000121// Identifiers for differentiating between subblocks
Julie Hockett8899c292018-08-02 20:10:17 +0000122enum class FieldId {
123 F_default,
124 F_namespace,
125 F_parent,
126 F_vparent,
127 F_type,
128 F_child_namespace,
129 F_child_record
130};
Julie Hockettb59cd772018-05-04 17:02:13 +0000131
Julie Hockette975a472018-03-22 23:34:46 +0000132class ClangDocBitcodeWriter {
133public:
134 ClangDocBitcodeWriter(llvm::BitstreamWriter &Stream) : Stream(Stream) {
135 emitHeader();
136 emitBlockInfoBlock();
137 emitVersionBlock();
138 }
139
Julie Hockettd0f9a872018-06-04 17:22:20 +0000140 // Write a specific info to a bitcode stream.
141 bool dispatchInfoForWrite(Info *I);
Julie Hockette975a472018-03-22 23:34:46 +0000142
143 // Block emission of different info types.
144 void emitBlock(const NamespaceInfo &I);
145 void emitBlock(const RecordInfo &I);
146 void emitBlock(const FunctionInfo &I);
147 void emitBlock(const EnumInfo &I);
148 void emitBlock(const TypeInfo &B);
149 void emitBlock(const FieldTypeInfo &B);
150 void emitBlock(const MemberTypeInfo &B);
151 void emitBlock(const CommentInfo &B);
Julie Hockettb59cd772018-05-04 17:02:13 +0000152 void emitBlock(const Reference &B, FieldId F);
Julie Hockette975a472018-03-22 23:34:46 +0000153
154private:
155 class AbbreviationMap {
156 llvm::DenseMap<unsigned, unsigned> Abbrevs;
157
158 public:
159 AbbreviationMap() : Abbrevs(RecordIdCount) {}
160
161 void add(RecordId RID, unsigned AbbrevID);
162 unsigned get(RecordId RID) const;
163 };
164
165 class StreamSubBlockGuard {
166 llvm::BitstreamWriter &Stream;
167
168 public:
169 StreamSubBlockGuard(llvm::BitstreamWriter &Stream_, BlockId ID)
170 : Stream(Stream_) {
171 // NOTE: SubBlockIDSize could theoretically be calculated on the fly,
172 // based on the initialization list of records in each block.
173 Stream.EnterSubblock(ID, BitCodeConstants::SubblockIDSize);
174 }
175
Julie Hockette975a472018-03-22 23:34:46 +0000176 StreamSubBlockGuard(const StreamSubBlockGuard &) = delete;
177 StreamSubBlockGuard &operator=(const StreamSubBlockGuard &) = delete;
178
179 ~StreamSubBlockGuard() { Stream.ExitBlock(); }
180 };
181
182 // Emission of validation and overview blocks.
183 void emitHeader();
184 void emitVersionBlock();
185 void emitRecordID(RecordId ID);
186 void emitBlockID(BlockId ID);
187 void emitBlockInfoBlock();
188 void emitBlockInfo(BlockId BID, const std::vector<RecordId> &RIDs);
189
190 // Emission of individual record types.
191 void emitRecord(StringRef Str, RecordId ID);
192 void emitRecord(const SymbolID &Str, RecordId ID);
193 void emitRecord(const Location &Loc, RecordId ID);
194 void emitRecord(const Reference &Ref, RecordId ID);
195 void emitRecord(bool Value, RecordId ID);
196 void emitRecord(int Value, RecordId ID);
197 void emitRecord(unsigned Value, RecordId ID);
198 bool prepRecordData(RecordId ID, bool ShouldEmit = true);
199
200 // Emission of appropriate abbreviation type.
201 void emitAbbrev(RecordId ID, BlockId Block);
202
203 // Static size is the maximum length of the block/record names we're pushing
204 // to this + 1. Longest is currently `MemberTypeBlock` at 15 chars.
205 SmallVector<uint32_t, BitCodeConstants::RecordSize> Record;
206 llvm::BitstreamWriter &Stream;
207 AbbreviationMap Abbrevs;
208};
209
210} // namespace doc
211} // namespace clang
212
213#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEWRITER_H