269 lines · c
1//===-- BitcodeWriter.h - ClangDoc Bitcode Writer --------------*- C++ -*-===//2//3// 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-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements a writer for serializing the clang-doc internal10// representation to LLVM bitcode. The writer takes in a stream and emits the11// generated bitcode to that stream.12//13//===----------------------------------------------------------------------===//14 15#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEWRITER_H16#define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEWRITER_H17 18#include "Representation.h"19#include "llvm/ADT/DenseMap.h"20#include "llvm/Bitstream/BitstreamWriter.h"21#include <vector>22 23namespace clang {24namespace doc {25 26// Current version number of clang-doc bitcode.27// Should be bumped when removing or changing BlockIds, RecordIds, or28// BitCodeConstants, though they can be added without breaking it.29static const unsigned VersionNumber = 3;30 31struct BitCodeConstants {32 static constexpr unsigned RecordSize = 32U;33 static constexpr unsigned SignatureBitSize = 8U;34 static constexpr unsigned SubblockIDSize = 4U;35 static constexpr unsigned BoolSize = 1U;36 static constexpr unsigned IntSize = 16U;37 static constexpr unsigned StringLengthSize = 16U;38 static constexpr unsigned FilenameLengthSize = 16U;39 static constexpr unsigned LineNumberSize = 32U;40 static constexpr unsigned ReferenceTypeSize = 8U;41 static constexpr unsigned USRLengthSize = 6U;42 static constexpr unsigned USRBitLengthSize = 8U;43 static constexpr unsigned char Signature[4] = {'D', 'O', 'C', 'S'};44 static constexpr int USRHashSize = 20;45};46 47// New Ids need to be added to both the enum here and the relevant IdNameMap in48// the implementation file.49enum BlockId {50 BI_VERSION_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,51 BI_NAMESPACE_BLOCK_ID,52 BI_ENUM_BLOCK_ID,53 BI_ENUM_VALUE_BLOCK_ID,54 BI_TYPE_BLOCK_ID,55 BI_FIELD_TYPE_BLOCK_ID,56 BI_MEMBER_TYPE_BLOCK_ID,57 BI_RECORD_BLOCK_ID,58 BI_BASE_RECORD_BLOCK_ID,59 BI_FUNCTION_BLOCK_ID,60 BI_COMMENT_BLOCK_ID,61 BI_REFERENCE_BLOCK_ID,62 BI_TEMPLATE_BLOCK_ID,63 BI_TEMPLATE_SPECIALIZATION_BLOCK_ID,64 BI_TEMPLATE_PARAM_BLOCK_ID,65 BI_CONSTRAINT_BLOCK_ID,66 BI_TYPEDEF_BLOCK_ID,67 BI_CONCEPT_BLOCK_ID,68 BI_VAR_BLOCK_ID,69 BI_FRIEND_BLOCK_ID,70 BI_LAST,71 BI_FIRST = BI_VERSION_BLOCK_ID72};73 74// New Ids need to be added to the enum here, and to the relevant IdNameMap and75// initialization list in the implementation file.76enum RecordId {77 VERSION = 1,78 FUNCTION_USR,79 FUNCTION_NAME,80 FUNCTION_DEFLOCATION,81 FUNCTION_LOCATION,82 FUNCTION_ACCESS,83 FUNCTION_IS_METHOD,84 FUNCTION_IS_STATIC,85 COMMENT_KIND,86 COMMENT_TEXT,87 COMMENT_NAME,88 COMMENT_DIRECTION,89 COMMENT_PARAMNAME,90 COMMENT_CLOSENAME,91 COMMENT_SELFCLOSING,92 COMMENT_EXPLICIT,93 COMMENT_ATTRKEY,94 COMMENT_ATTRVAL,95 COMMENT_ARG,96 TYPE_IS_BUILTIN,97 TYPE_IS_TEMPLATE,98 FIELD_TYPE_NAME,99 FIELD_DEFAULT_VALUE,100 FIELD_TYPE_IS_BUILTIN,101 FIELD_TYPE_IS_TEMPLATE,102 MEMBER_TYPE_NAME,103 MEMBER_TYPE_ACCESS,104 MEMBER_TYPE_IS_STATIC,105 MEMBER_TYPE_IS_BUILTIN,106 MEMBER_TYPE_IS_TEMPLATE,107 NAMESPACE_USR,108 NAMESPACE_NAME,109 NAMESPACE_PATH,110 ENUM_USR,111 ENUM_NAME,112 ENUM_DEFLOCATION,113 ENUM_LOCATION,114 ENUM_SCOPED,115 ENUM_VALUE_NAME,116 ENUM_VALUE_VALUE,117 ENUM_VALUE_EXPR,118 RECORD_USR,119 RECORD_NAME,120 RECORD_PATH,121 RECORD_DEFLOCATION,122 RECORD_LOCATION,123 RECORD_TAG_TYPE,124 RECORD_IS_TYPE_DEF,125 RECORD_MANGLED_NAME,126 BASE_RECORD_USR,127 BASE_RECORD_NAME,128 BASE_RECORD_PATH,129 BASE_RECORD_TAG_TYPE,130 BASE_RECORD_IS_VIRTUAL,131 BASE_RECORD_ACCESS,132 BASE_RECORD_IS_PARENT,133 REFERENCE_USR,134 REFERENCE_NAME,135 REFERENCE_QUAL_NAME,136 REFERENCE_TYPE,137 REFERENCE_PATH,138 REFERENCE_FIELD,139 REFERENCE_FILE,140 TEMPLATE_PARAM_CONTENTS,141 TEMPLATE_SPECIALIZATION_OF,142 TYPEDEF_USR,143 TYPEDEF_NAME,144 TYPEDEF_DEFLOCATION,145 TYPEDEF_IS_USING,146 CONCEPT_USR,147 CONCEPT_NAME,148 CONCEPT_IS_TYPE,149 CONCEPT_CONSTRAINT_EXPRESSION,150 CONSTRAINT_EXPRESSION,151 VAR_USR,152 VAR_NAME,153 VAR_DEFLOCATION,154 VAR_IS_STATIC,155 FRIEND_IS_CLASS,156 RI_LAST,157 RI_FIRST = VERSION158};159 160static constexpr unsigned BlockIdCount = BI_LAST - BI_FIRST;161static constexpr unsigned RecordIdCount = RI_LAST - RI_FIRST;162 163// Identifiers for differentiating between subblocks164enum class FieldId {165 F_default,166 F_namespace,167 F_parent,168 F_vparent,169 F_type,170 F_child_namespace,171 F_child_record,172 F_concept,173 F_friend174};175 176class ClangDocBitcodeWriter {177public:178 ClangDocBitcodeWriter(llvm::BitstreamWriter &Stream) : Stream(Stream) {179 emitHeader();180 emitBlockInfoBlock();181 emitVersionBlock();182 }183 184 // Write a specific info to a bitcode stream.185 bool dispatchInfoForWrite(Info *I);186 187 // Block emission of different info types.188 void emitBlock(const NamespaceInfo &I);189 void emitBlock(const RecordInfo &I);190 void emitBlock(const BaseRecordInfo &I);191 void emitBlock(const FunctionInfo &I);192 void emitBlock(const EnumInfo &I);193 void emitBlock(const EnumValueInfo &I);194 void emitBlock(const TypeInfo &B);195 void emitBlock(const TypedefInfo &B);196 void emitBlock(const FieldTypeInfo &B);197 void emitBlock(const MemberTypeInfo &T);198 void emitBlock(const CommentInfo &B);199 void emitBlock(const TemplateInfo &T);200 void emitBlock(const TemplateSpecializationInfo &T);201 void emitBlock(const TemplateParamInfo &T);202 void emitBlock(const ConceptInfo &T);203 void emitBlock(const ConstraintInfo &T);204 void emitBlock(const Reference &B, FieldId F);205 void emitBlock(const FriendInfo &R);206 void emitBlock(const VarInfo &B);207 208private:209 class AbbreviationMap {210 llvm::DenseMap<unsigned, unsigned> Abbrevs;211 212 public:213 AbbreviationMap() : Abbrevs(RecordIdCount) {}214 215 void add(RecordId RID, unsigned AbbrevID);216 unsigned get(RecordId RID) const;217 };218 219 class StreamSubBlockGuard {220 llvm::BitstreamWriter &Stream;221 222 public:223 StreamSubBlockGuard(llvm::BitstreamWriter &Stream_, BlockId ID)224 : Stream(Stream_) {225 // NOTE: SubBlockIDSize could theoretically be calculated on the fly,226 // based on the initialization list of records in each block.227 Stream.EnterSubblock(ID, BitCodeConstants::SubblockIDSize);228 }229 230 StreamSubBlockGuard(const StreamSubBlockGuard &) = delete;231 StreamSubBlockGuard &operator=(const StreamSubBlockGuard &) = delete;232 233 ~StreamSubBlockGuard() { Stream.ExitBlock(); }234 };235 236 // Emission of validation and overview blocks.237 void emitHeader();238 void emitVersionBlock();239 void emitRecordID(RecordId ID);240 void emitBlockID(BlockId ID);241 void emitBlockInfoBlock();242 void emitBlockInfo(BlockId BID, const std::vector<RecordId> &RIDs);243 244 // Emission of individual record types.245 void emitRecord(StringRef Str, RecordId ID);246 void emitRecord(const SymbolID &Str, RecordId ID);247 void emitRecord(const Location &Loc, RecordId ID);248 void emitRecord(const Reference &Ref, RecordId ID);249 void emitRecord(bool Value, RecordId ID);250 void emitRecord(int Value, RecordId ID);251 void emitRecord(unsigned Value, RecordId ID);252 void emitRecord(const TemplateInfo &Templ);253 bool prepRecordData(RecordId ID, bool ShouldEmit = true);254 255 // Emission of appropriate abbreviation type.256 void emitAbbrev(RecordId ID, BlockId Block);257 258 // Static size is the maximum length of the block/record names we're pushing259 // to this + 1. Longest is currently `MemberTypeBlock` at 15 chars.260 SmallVector<uint32_t, BitCodeConstants::RecordSize> Record;261 llvm::BitstreamWriter &Stream;262 AbbreviationMap Abbrevs;263};264 265} // namespace doc266} // namespace clang267 268#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEWRITER_H269