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: ClangDocBitcodeWriter(llvm::BitstreamWriter & Stream)130 ClangDocBitcodeWriter(llvm::BitstreamWriter &Stream) : Stream(Stream) { 131 emitHeader(); 132 emitBlockInfoBlock(); 133 emitVersionBlock(); 134 } 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: AbbreviationMap()155 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: StreamSubBlockGuard(llvm::BitstreamWriter & Stream_,BlockId ID)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 ~StreamSubBlockGuard()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 210