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