brintos

brintos / llvm-project-archived public Read only

0
0
Text · 29.7 KiB · 3a7ac6e Raw
780 lines · cpp
1//===--  BitcodeWriter.cpp - 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#include "BitcodeWriter.h"10#include "llvm/ADT/IndexedMap.h"11#include <initializer_list>12 13namespace clang {14namespace doc {15 16// Empty SymbolID for comparison, so we don't have to construct one every time.17static const SymbolID EmptySID = SymbolID();18 19// Since id enums are not zero-indexed, we need to transform the given id into20// its associated index.21struct BlockIdToIndexFunctor {22  using argument_type = unsigned;23  unsigned operator()(unsigned ID) const { return ID - BI_FIRST; }24};25 26struct RecordIdToIndexFunctor {27  using argument_type = unsigned;28  unsigned operator()(unsigned ID) const { return ID - RI_FIRST; }29};30 31using AbbrevDsc = void (*)(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev);32 33static void34generateAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev,35               const std::initializer_list<llvm::BitCodeAbbrevOp> Ops) {36  for (const auto &Op : Ops)37    Abbrev->Add(Op);38}39 40static void genBoolAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {41  generateAbbrev(Abbrev,42                 {// 0. Boolean43                  llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,44                                        BitCodeConstants::BoolSize)});45}46 47static void genIntAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {48  generateAbbrev(Abbrev,49                 {// 0. Fixed-size integer50                  llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,51                                        BitCodeConstants::IntSize)});52}53 54static void genSymbolIdAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {55  generateAbbrev(Abbrev,56                 {// 0. Fixed-size integer (length of the sha1'd USR)57                  llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,58                                        BitCodeConstants::USRLengthSize),59                  // 1. Fixed-size array of Char6 (USR)60                  llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Array),61                  llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,62                                        BitCodeConstants::USRBitLengthSize)});63}64 65static void genStringAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {66  generateAbbrev(Abbrev,67                 {// 0. Fixed-size integer (length of the following string)68                  llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,69                                        BitCodeConstants::StringLengthSize),70                  // 1. The string blob71                  llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)});72}73 74// Assumes that the file will not have more than 65535 lines.75static void genLocationAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {76  generateAbbrev(77      Abbrev,78      {// 0. Fixed-size integer (line number)79       llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,80                             BitCodeConstants::LineNumberSize),81       // 1. Fixed-size integer (start line number)82       llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,83                             BitCodeConstants::LineNumberSize),84       // 2. Boolean (IsFileInRootDir)85       llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,86                             BitCodeConstants::BoolSize),87       // 3. Fixed-size integer (length of the following string (filename))88       llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,89                             BitCodeConstants::StringLengthSize),90       // 4. The string blob91       llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)});92}93 94struct RecordIdDsc {95  llvm::StringRef Name;96  AbbrevDsc Abbrev = nullptr;97 98  RecordIdDsc() = default;99  RecordIdDsc(llvm::StringRef Name, AbbrevDsc Abbrev)100      : Name(Name), Abbrev(Abbrev) {}101 102  // Is this 'description' valid?103  operator bool() const {104    return Abbrev != nullptr && Name.data() != nullptr && !Name.empty();105  }106};107 108static const llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor>109    BlockIdNameMap = []() {110      llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor> BlockIdNameMap;111      BlockIdNameMap.resize(BlockIdCount);112 113      // There is no init-list constructor for the IndexedMap, so have to114      // improvise115      static const std::vector<std::pair<BlockId, const char *const>> Inits = {116          {BI_VERSION_BLOCK_ID, "VersionBlock"},117          {BI_NAMESPACE_BLOCK_ID, "NamespaceBlock"},118          {BI_ENUM_BLOCK_ID, "EnumBlock"},119          {BI_ENUM_VALUE_BLOCK_ID, "EnumValueBlock"},120          {BI_TYPEDEF_BLOCK_ID, "TypedefBlock"},121          {BI_TYPE_BLOCK_ID, "TypeBlock"},122          {BI_FIELD_TYPE_BLOCK_ID, "FieldTypeBlock"},123          {BI_MEMBER_TYPE_BLOCK_ID, "MemberTypeBlock"},124          {BI_RECORD_BLOCK_ID, "RecordBlock"},125          {BI_BASE_RECORD_BLOCK_ID, "BaseRecordBlock"},126          {BI_FUNCTION_BLOCK_ID, "FunctionBlock"},127          {BI_COMMENT_BLOCK_ID, "CommentBlock"},128          {BI_REFERENCE_BLOCK_ID, "ReferenceBlock"},129          {BI_TEMPLATE_BLOCK_ID, "TemplateBlock"},130          {BI_TEMPLATE_SPECIALIZATION_BLOCK_ID, "TemplateSpecializationBlock"},131          {BI_TEMPLATE_PARAM_BLOCK_ID, "TemplateParamBlock"},132          {BI_CONSTRAINT_BLOCK_ID, "ConstraintBlock"},133          {BI_CONCEPT_BLOCK_ID, "ConceptBlock"},134          {BI_VAR_BLOCK_ID, "VarBlock"},135          {BI_FRIEND_BLOCK_ID, "FriendBlock"}};136      assert(Inits.size() == BlockIdCount);137      for (const auto &Init : Inits)138        BlockIdNameMap[Init.first] = Init.second;139      assert(BlockIdNameMap.size() == BlockIdCount);140      return BlockIdNameMap;141    }();142 143static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor>144    RecordIdNameMap = []() {145      llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor> RecordIdNameMap;146      RecordIdNameMap.resize(RecordIdCount);147 148      // There is no init-list constructor for the IndexedMap, so have to149      // improvise150      static const std::vector<std::pair<RecordId, RecordIdDsc>> Inits = {151          {VERSION, {"Version", &genIntAbbrev}},152          {COMMENT_KIND, {"Kind", &genStringAbbrev}},153          {COMMENT_TEXT, {"Text", &genStringAbbrev}},154          {COMMENT_NAME, {"Name", &genStringAbbrev}},155          {COMMENT_DIRECTION, {"Direction", &genStringAbbrev}},156          {COMMENT_PARAMNAME, {"ParamName", &genStringAbbrev}},157          {COMMENT_CLOSENAME, {"CloseName", &genStringAbbrev}},158          {COMMENT_SELFCLOSING, {"SelfClosing", &genBoolAbbrev}},159          {COMMENT_EXPLICIT, {"Explicit", &genBoolAbbrev}},160          {COMMENT_ATTRKEY, {"AttrKey", &genStringAbbrev}},161          {COMMENT_ATTRVAL, {"AttrVal", &genStringAbbrev}},162          {COMMENT_ARG, {"Arg", &genStringAbbrev}},163          {FIELD_TYPE_NAME, {"Name", &genStringAbbrev}},164          {FIELD_DEFAULT_VALUE, {"DefaultValue", &genStringAbbrev}},165          {FIELD_TYPE_IS_BUILTIN, {"IsBuiltin", &genBoolAbbrev}},166          {FIELD_TYPE_IS_TEMPLATE, {"IsTemplate", &genBoolAbbrev}},167          {MEMBER_TYPE_NAME, {"Name", &genStringAbbrev}},168          {MEMBER_TYPE_ACCESS, {"Access", &genIntAbbrev}},169          {MEMBER_TYPE_IS_STATIC, {"IsStatic", &genBoolAbbrev}},170          {MEMBER_TYPE_IS_BUILTIN, {"IsBuiltin", &genBoolAbbrev}},171          {MEMBER_TYPE_IS_TEMPLATE, {"IsTemplate", &genBoolAbbrev}},172          {TYPE_IS_BUILTIN, {"IsBuiltin", &genBoolAbbrev}},173          {TYPE_IS_TEMPLATE, {"IsTemplate", &genBoolAbbrev}},174          {NAMESPACE_USR, {"USR", &genSymbolIdAbbrev}},175          {NAMESPACE_NAME, {"Name", &genStringAbbrev}},176          {NAMESPACE_PATH, {"Path", &genStringAbbrev}},177          {ENUM_USR, {"USR", &genSymbolIdAbbrev}},178          {ENUM_NAME, {"Name", &genStringAbbrev}},179          {ENUM_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},180          {ENUM_LOCATION, {"Location", &genLocationAbbrev}},181          {ENUM_SCOPED, {"Scoped", &genBoolAbbrev}},182          {ENUM_VALUE_NAME, {"Name", &genStringAbbrev}},183          {ENUM_VALUE_VALUE, {"Value", &genStringAbbrev}},184          {ENUM_VALUE_EXPR, {"Expr", &genStringAbbrev}},185          {RECORD_USR, {"USR", &genSymbolIdAbbrev}},186          {RECORD_NAME, {"Name", &genStringAbbrev}},187          {RECORD_PATH, {"Path", &genStringAbbrev}},188          {RECORD_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},189          {RECORD_LOCATION, {"Location", &genLocationAbbrev}},190          {RECORD_TAG_TYPE, {"TagType", &genIntAbbrev}},191          {RECORD_IS_TYPE_DEF, {"IsTypeDef", &genBoolAbbrev}},192          {RECORD_MANGLED_NAME, {"MangledName", &genStringAbbrev}},193          {BASE_RECORD_USR, {"USR", &genSymbolIdAbbrev}},194          {BASE_RECORD_NAME, {"Name", &genStringAbbrev}},195          {BASE_RECORD_PATH, {"Path", &genStringAbbrev}},196          {BASE_RECORD_TAG_TYPE, {"TagType", &genIntAbbrev}},197          {BASE_RECORD_IS_VIRTUAL, {"IsVirtual", &genBoolAbbrev}},198          {BASE_RECORD_ACCESS, {"Access", &genIntAbbrev}},199          {BASE_RECORD_IS_PARENT, {"IsParent", &genBoolAbbrev}},200          {FUNCTION_USR, {"USR", &genSymbolIdAbbrev}},201          {FUNCTION_NAME, {"Name", &genStringAbbrev}},202          {FUNCTION_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},203          {FUNCTION_LOCATION, {"Location", &genLocationAbbrev}},204          {FUNCTION_ACCESS, {"Access", &genIntAbbrev}},205          {FUNCTION_IS_METHOD, {"IsMethod", &genBoolAbbrev}},206          {FUNCTION_IS_STATIC, {"IsStatic", &genBoolAbbrev}},207          {REFERENCE_USR, {"USR", &genSymbolIdAbbrev}},208          {REFERENCE_NAME, {"Name", &genStringAbbrev}},209          {REFERENCE_QUAL_NAME, {"QualName", &genStringAbbrev}},210          {REFERENCE_TYPE, {"RefType", &genIntAbbrev}},211          {REFERENCE_PATH, {"Path", &genStringAbbrev}},212          {REFERENCE_FIELD, {"Field", &genIntAbbrev}},213          {REFERENCE_FILE, {"File", &genStringAbbrev}},214          {TEMPLATE_PARAM_CONTENTS, {"Contents", &genStringAbbrev}},215          {TEMPLATE_SPECIALIZATION_OF,216           {"SpecializationOf", &genSymbolIdAbbrev}},217          {TYPEDEF_USR, {"USR", &genSymbolIdAbbrev}},218          {TYPEDEF_NAME, {"Name", &genStringAbbrev}},219          {TYPEDEF_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},220          {TYPEDEF_IS_USING, {"IsUsing", &genBoolAbbrev}},221          {CONCEPT_USR, {"USR", &genSymbolIdAbbrev}},222          {CONCEPT_NAME, {"Name", &genStringAbbrev}},223          {CONCEPT_IS_TYPE, {"IsType", &genBoolAbbrev}},224          {CONCEPT_CONSTRAINT_EXPRESSION,225           {"ConstraintExpression", &genStringAbbrev}},226          {CONSTRAINT_EXPRESSION, {"Expression", &genStringAbbrev}},227          {VAR_USR, {"USR", &genSymbolIdAbbrev}},228          {VAR_NAME, {"Name", &genStringAbbrev}},229          {VAR_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},230          {VAR_IS_STATIC, {"IsStatic", &genBoolAbbrev}},231          {FRIEND_IS_CLASS, {"IsClass", &genBoolAbbrev}}};232 233      assert(Inits.size() == RecordIdCount);234      for (const auto &Init : Inits) {235        RecordIdNameMap[Init.first] = Init.second;236        assert((Init.second.Name.size() + 1) <= BitCodeConstants::RecordSize);237      }238      assert(RecordIdNameMap.size() == RecordIdCount);239      return RecordIdNameMap;240    }();241 242static const std::vector<std::pair<BlockId, std::vector<RecordId>>>243    RecordsByBlock{244        // Version Block245        {BI_VERSION_BLOCK_ID, {VERSION}},246        // Comment Block247        {BI_COMMENT_BLOCK_ID,248         {COMMENT_KIND, COMMENT_TEXT, COMMENT_NAME, COMMENT_DIRECTION,249          COMMENT_PARAMNAME, COMMENT_CLOSENAME, COMMENT_SELFCLOSING,250          COMMENT_EXPLICIT, COMMENT_ATTRKEY, COMMENT_ATTRVAL, COMMENT_ARG}},251        // Type Block252        {BI_TYPE_BLOCK_ID, {TYPE_IS_BUILTIN, TYPE_IS_TEMPLATE}},253        // FieldType Block254        {BI_FIELD_TYPE_BLOCK_ID,255         {FIELD_TYPE_NAME, FIELD_DEFAULT_VALUE, FIELD_TYPE_IS_BUILTIN,256          FIELD_TYPE_IS_TEMPLATE}},257        // MemberType Block258        {BI_MEMBER_TYPE_BLOCK_ID,259         {MEMBER_TYPE_NAME, MEMBER_TYPE_ACCESS, MEMBER_TYPE_IS_STATIC,260          MEMBER_TYPE_IS_BUILTIN, MEMBER_TYPE_IS_TEMPLATE}},261        // Enum Block262        {BI_ENUM_BLOCK_ID,263         {ENUM_USR, ENUM_NAME, ENUM_DEFLOCATION, ENUM_LOCATION, ENUM_SCOPED}},264        // Enum Value Block265        {BI_ENUM_VALUE_BLOCK_ID,266         {ENUM_VALUE_NAME, ENUM_VALUE_VALUE, ENUM_VALUE_EXPR}},267        // Typedef Block268        {BI_TYPEDEF_BLOCK_ID,269         {TYPEDEF_USR, TYPEDEF_NAME, TYPEDEF_DEFLOCATION, TYPEDEF_IS_USING}},270        // Namespace Block271        {BI_NAMESPACE_BLOCK_ID,272         {NAMESPACE_USR, NAMESPACE_NAME, NAMESPACE_PATH}},273        // Record Block274        {BI_RECORD_BLOCK_ID,275         {RECORD_USR, RECORD_NAME, RECORD_PATH, RECORD_DEFLOCATION,276          RECORD_LOCATION, RECORD_TAG_TYPE, RECORD_IS_TYPE_DEF,277          RECORD_MANGLED_NAME}},278        // BaseRecord Block279        {BI_BASE_RECORD_BLOCK_ID,280         {BASE_RECORD_USR, BASE_RECORD_NAME, BASE_RECORD_PATH,281          BASE_RECORD_TAG_TYPE, BASE_RECORD_IS_VIRTUAL, BASE_RECORD_ACCESS,282          BASE_RECORD_IS_PARENT}},283        // Function Block284        {BI_FUNCTION_BLOCK_ID,285         {FUNCTION_USR, FUNCTION_NAME, FUNCTION_DEFLOCATION, FUNCTION_LOCATION,286          FUNCTION_ACCESS, FUNCTION_IS_METHOD, FUNCTION_IS_STATIC}},287        // Reference Block288        {BI_REFERENCE_BLOCK_ID,289         {REFERENCE_USR, REFERENCE_NAME, REFERENCE_QUAL_NAME, REFERENCE_TYPE,290          REFERENCE_PATH, REFERENCE_FIELD, REFERENCE_FILE}},291        // Template Blocks.292        {BI_TEMPLATE_BLOCK_ID, {}},293        {BI_TEMPLATE_PARAM_BLOCK_ID, {TEMPLATE_PARAM_CONTENTS}},294        {BI_TEMPLATE_SPECIALIZATION_BLOCK_ID, {TEMPLATE_SPECIALIZATION_OF}},295        // Concept Block296        {BI_CONCEPT_BLOCK_ID,297         {CONCEPT_USR, CONCEPT_NAME, CONCEPT_IS_TYPE,298          CONCEPT_CONSTRAINT_EXPRESSION}},299        // Constraint Block300        {BI_CONSTRAINT_BLOCK_ID, {CONSTRAINT_EXPRESSION}},301        {BI_VAR_BLOCK_ID, {VAR_NAME, VAR_USR, VAR_DEFLOCATION, VAR_IS_STATIC}},302        {BI_FRIEND_BLOCK_ID, {FRIEND_IS_CLASS}}};303 304// AbbreviationMap305 306void ClangDocBitcodeWriter::AbbreviationMap::add(RecordId RID,307                                                 unsigned AbbrevID) {308  assert(RecordIdNameMap[RID] && "Unknown RecordId.");309  assert(!Abbrevs.contains(RID) && "Abbreviation already added.");310  Abbrevs[RID] = AbbrevID;311}312 313unsigned ClangDocBitcodeWriter::AbbreviationMap::get(RecordId RID) const {314  assert(RecordIdNameMap[RID] && "Unknown RecordId.");315  assert(Abbrevs.contains(RID) && "Unknown abbreviation.");316  return Abbrevs.lookup(RID);317}318 319// Validation and Overview Blocks320 321/// Emits the magic number header to check that its the right format,322/// in this case, 'DOCS'.323void ClangDocBitcodeWriter::emitHeader() {324  for (char C : BitCodeConstants::Signature)325    Stream.Emit((unsigned)C, BitCodeConstants::SignatureBitSize);326}327 328void ClangDocBitcodeWriter::emitVersionBlock() {329  StreamSubBlockGuard Block(Stream, BI_VERSION_BLOCK_ID);330  emitRecord(VersionNumber, VERSION);331}332 333/// Emits a block ID and the block name to the BLOCKINFO block.334void ClangDocBitcodeWriter::emitBlockID(BlockId BID) {335  const auto &BlockIdName = BlockIdNameMap[BID];336  assert(BlockIdName.data() && BlockIdName.size() && "Unknown BlockId.");337 338  Record.clear();339  Record.push_back(BID);340  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);341  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,342                    ArrayRef<unsigned char>(BlockIdName.bytes_begin(),343                                            BlockIdName.bytes_end()));344}345 346/// Emits a record name to the BLOCKINFO block.347void ClangDocBitcodeWriter::emitRecordID(RecordId ID) {348  assert(RecordIdNameMap[ID] && "Unknown RecordId.");349  prepRecordData(ID);350  Record.append(RecordIdNameMap[ID].Name.begin(),351                RecordIdNameMap[ID].Name.end());352  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);353}354 355// Abbreviations356 357void ClangDocBitcodeWriter::emitAbbrev(RecordId ID, BlockId Block) {358  assert(RecordIdNameMap[ID] && "Unknown abbreviation.");359  auto Abbrev = std::make_shared<llvm::BitCodeAbbrev>();360  Abbrev->Add(llvm::BitCodeAbbrevOp(ID));361  RecordIdNameMap[ID].Abbrev(Abbrev);362  Abbrevs.add(ID, Stream.EmitBlockInfoAbbrev(Block, std::move(Abbrev)));363}364 365// Records366 367void ClangDocBitcodeWriter::emitRecord(const SymbolID &Sym, RecordId ID) {368  assert(RecordIdNameMap[ID] && "Unknown RecordId.");369  assert(RecordIdNameMap[ID].Abbrev == &genSymbolIdAbbrev &&370         "Abbrev type mismatch.");371  if (!prepRecordData(ID, Sym != EmptySID))372    return;373  assert(Sym.size() == 20);374  Record.push_back(Sym.size());375  Record.append(Sym.begin(), Sym.end());376  Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);377}378 379void ClangDocBitcodeWriter::emitRecord(llvm::StringRef Str, RecordId ID) {380  assert(RecordIdNameMap[ID] && "Unknown RecordId.");381  assert(RecordIdNameMap[ID].Abbrev == &genStringAbbrev &&382         "Abbrev type mismatch.");383  if (!prepRecordData(ID, !Str.empty()))384    return;385  assert(Str.size() < (1U << BitCodeConstants::StringLengthSize));386  Record.push_back(Str.size());387  Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Str);388}389 390void ClangDocBitcodeWriter::emitRecord(const Location &Loc, RecordId ID) {391  assert(RecordIdNameMap[ID] && "Unknown RecordId.");392  assert(RecordIdNameMap[ID].Abbrev == &genLocationAbbrev &&393         "Abbrev type mismatch.");394  if (!prepRecordData(ID, true))395    return;396  // FIXME: Assert that the line number is of the appropriate size.397  Record.push_back(Loc.StartLineNumber);398  Record.push_back(Loc.EndLineNumber);399  assert(Loc.Filename.size() < (1U << BitCodeConstants::StringLengthSize));400  Record.push_back(Loc.IsFileInRootDir);401  Record.push_back(Loc.Filename.size());402  Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Loc.Filename);403}404 405void ClangDocBitcodeWriter::emitRecord(bool Val, RecordId ID) {406  assert(RecordIdNameMap[ID] && "Unknown RecordId.");407  assert(RecordIdNameMap[ID].Abbrev == &genBoolAbbrev &&408         "Abbrev type mismatch.");409  if (!prepRecordData(ID, Val))410    return;411  Record.push_back(Val);412  Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);413}414 415void ClangDocBitcodeWriter::emitRecord(int Val, RecordId ID) {416  assert(RecordIdNameMap[ID] && "Unknown RecordId.");417  assert(RecordIdNameMap[ID].Abbrev == &genIntAbbrev &&418         "Abbrev type mismatch.");419  if (!prepRecordData(ID, Val))420    return;421  // FIXME: Assert that the integer is of the appropriate size.422  Record.push_back(Val);423  Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);424}425 426void ClangDocBitcodeWriter::emitRecord(unsigned Val, RecordId ID) {427  assert(RecordIdNameMap[ID] && "Unknown RecordId.");428  assert(RecordIdNameMap[ID].Abbrev == &genIntAbbrev &&429         "Abbrev type mismatch.");430  if (!prepRecordData(ID, Val))431    return;432  assert(Val < (1U << BitCodeConstants::IntSize));433  Record.push_back(Val);434  Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);435}436 437void ClangDocBitcodeWriter::emitRecord(const TemplateInfo &Templ) {}438 439bool ClangDocBitcodeWriter::prepRecordData(RecordId ID, bool ShouldEmit) {440  assert(RecordIdNameMap[ID] && "Unknown RecordId.");441  if (!ShouldEmit)442    return false;443  Record.clear();444  Record.push_back(ID);445  return true;446}447 448// BlockInfo Block449 450void ClangDocBitcodeWriter::emitBlockInfoBlock() {451  Stream.EnterBlockInfoBlock();452  for (const auto &Block : RecordsByBlock) {453    assert(Block.second.size() < (1U << BitCodeConstants::SubblockIDSize));454    emitBlockInfo(Block.first, Block.second);455  }456  Stream.ExitBlock();457}458 459void ClangDocBitcodeWriter::emitBlockInfo(BlockId BID,460                                          const std::vector<RecordId> &RIDs) {461  assert(RIDs.size() < (1U << BitCodeConstants::SubblockIDSize));462  emitBlockID(BID);463  for (RecordId RID : RIDs) {464    emitRecordID(RID);465    emitAbbrev(RID, BID);466  }467}468 469// Block emission470 471void ClangDocBitcodeWriter::emitBlock(const Reference &R, FieldId Field) {472  if (R.USR == EmptySID && R.Name.empty())473    return;474  StreamSubBlockGuard Block(Stream, BI_REFERENCE_BLOCK_ID);475  emitRecord(R.USR, REFERENCE_USR);476  emitRecord(R.Name, REFERENCE_NAME);477  emitRecord(R.QualName, REFERENCE_QUAL_NAME);478  emitRecord((unsigned)R.RefType, REFERENCE_TYPE);479  emitRecord(R.Path, REFERENCE_PATH);480  emitRecord((unsigned)Field, REFERENCE_FIELD);481  emitRecord(R.DocumentationFileName, REFERENCE_FILE);482}483 484void ClangDocBitcodeWriter::emitBlock(const FriendInfo &R) {485  StreamSubBlockGuard Block(Stream, BI_FRIEND_BLOCK_ID);486  emitBlock(R.Ref, FieldId::F_friend);487  emitRecord(R.IsClass, FRIEND_IS_CLASS);488  if (R.Template)489    emitBlock(*R.Template);490  if (R.Params)491    for (const auto &P : *R.Params)492      emitBlock(P);493  if (R.ReturnType)494    emitBlock(*R.ReturnType);495}496 497void ClangDocBitcodeWriter::emitBlock(const TypeInfo &T) {498  StreamSubBlockGuard Block(Stream, BI_TYPE_BLOCK_ID);499  emitBlock(T.Type, FieldId::F_type);500  emitRecord(T.IsBuiltIn, TYPE_IS_BUILTIN);501  emitRecord(T.IsTemplate, TYPE_IS_TEMPLATE);502}503 504void ClangDocBitcodeWriter::emitBlock(const TypedefInfo &T) {505  StreamSubBlockGuard Block(Stream, BI_TYPEDEF_BLOCK_ID);506  emitRecord(T.USR, TYPEDEF_USR);507  emitRecord(T.Name, TYPEDEF_NAME);508  for (const auto &N : T.Namespace)509    emitBlock(N, FieldId::F_namespace);510  for (const auto &CI : T.Description)511    emitBlock(CI);512  if (T.DefLoc)513    emitRecord(*T.DefLoc, TYPEDEF_DEFLOCATION);514  emitRecord(T.IsUsing, TYPEDEF_IS_USING);515  emitBlock(T.Underlying);516}517 518void ClangDocBitcodeWriter::emitBlock(const FieldTypeInfo &T) {519  StreamSubBlockGuard Block(Stream, BI_FIELD_TYPE_BLOCK_ID);520  emitBlock(T.Type, FieldId::F_type);521  emitRecord(T.Name, FIELD_TYPE_NAME);522  emitRecord(T.DefaultValue, FIELD_DEFAULT_VALUE);523  emitRecord(T.IsBuiltIn, FIELD_TYPE_IS_BUILTIN);524  emitRecord(T.IsTemplate, FIELD_TYPE_IS_TEMPLATE);525}526 527void ClangDocBitcodeWriter::emitBlock(const MemberTypeInfo &T) {528  StreamSubBlockGuard Block(Stream, BI_MEMBER_TYPE_BLOCK_ID);529  emitBlock(T.Type, FieldId::F_type);530  emitRecord(T.Name, MEMBER_TYPE_NAME);531  emitRecord(T.Access, MEMBER_TYPE_ACCESS);532  emitRecord(T.IsStatic, MEMBER_TYPE_IS_STATIC);533  emitRecord(T.IsBuiltIn, MEMBER_TYPE_IS_BUILTIN);534  emitRecord(T.IsTemplate, MEMBER_TYPE_IS_TEMPLATE);535  emitRecord(T.IsTemplate, MEMBER_TYPE_IS_TEMPLATE);536  for (const auto &CI : T.Description)537    emitBlock(CI);538}539 540void ClangDocBitcodeWriter::emitBlock(const CommentInfo &I) {541  StreamSubBlockGuard Block(Stream, BI_COMMENT_BLOCK_ID);542  // Handle Kind (enum) separately, since it is not a string.543  emitRecord(commentKindToString(I.Kind), COMMENT_KIND);544  for (const auto &L : std::vector<std::pair<llvm::StringRef, RecordId>>{545           {I.Text, COMMENT_TEXT},546           {I.Name, COMMENT_NAME},547           {I.Direction, COMMENT_DIRECTION},548           {I.ParamName, COMMENT_PARAMNAME},549           {I.CloseName, COMMENT_CLOSENAME}})550    emitRecord(L.first, L.second);551  emitRecord(I.SelfClosing, COMMENT_SELFCLOSING);552  emitRecord(I.Explicit, COMMENT_EXPLICIT);553  for (const auto &A : I.AttrKeys)554    emitRecord(A, COMMENT_ATTRKEY);555  for (const auto &A : I.AttrValues)556    emitRecord(A, COMMENT_ATTRVAL);557  for (const auto &A : I.Args)558    emitRecord(A, COMMENT_ARG);559  for (const auto &C : I.Children)560    emitBlock(*C);561}562 563void ClangDocBitcodeWriter::emitBlock(const NamespaceInfo &I) {564  StreamSubBlockGuard Block(Stream, BI_NAMESPACE_BLOCK_ID);565  emitRecord(I.USR, NAMESPACE_USR);566  emitRecord(I.Name, NAMESPACE_NAME);567  emitRecord(I.Path, NAMESPACE_PATH);568  for (const auto &N : I.Namespace)569    emitBlock(N, FieldId::F_namespace);570  for (const auto &CI : I.Description)571    emitBlock(CI);572  for (const auto &C : I.Children.Namespaces)573    emitBlock(C, FieldId::F_child_namespace);574  for (const auto &C : I.Children.Records)575    emitBlock(C, FieldId::F_child_record);576  for (const auto &C : I.Children.Functions)577    emitBlock(C);578  for (const auto &C : I.Children.Enums)579    emitBlock(C);580  for (const auto &C : I.Children.Typedefs)581    emitBlock(C);582  for (const auto &C : I.Children.Concepts)583    emitBlock(C);584  for (const auto &C : I.Children.Variables)585    emitBlock(C);586}587 588void ClangDocBitcodeWriter::emitBlock(const EnumInfo &I) {589  StreamSubBlockGuard Block(Stream, BI_ENUM_BLOCK_ID);590  emitRecord(I.USR, ENUM_USR);591  emitRecord(I.Name, ENUM_NAME);592  for (const auto &N : I.Namespace)593    emitBlock(N, FieldId::F_namespace);594  for (const auto &CI : I.Description)595    emitBlock(CI);596  if (I.DefLoc)597    emitRecord(*I.DefLoc, ENUM_DEFLOCATION);598  for (const auto &L : I.Loc)599    emitRecord(L, ENUM_LOCATION);600  emitRecord(I.Scoped, ENUM_SCOPED);601  if (I.BaseType)602    emitBlock(*I.BaseType);603  for (const auto &N : I.Members)604    emitBlock(N);605}606 607void ClangDocBitcodeWriter::emitBlock(const EnumValueInfo &I) {608  StreamSubBlockGuard Block(Stream, BI_ENUM_VALUE_BLOCK_ID);609  emitRecord(I.Name, ENUM_VALUE_NAME);610  emitRecord(I.Value, ENUM_VALUE_VALUE);611  emitRecord(I.ValueExpr, ENUM_VALUE_EXPR);612  for (const auto &CI : I.Description)613    emitBlock(CI);614}615 616void ClangDocBitcodeWriter::emitBlock(const RecordInfo &I) {617  StreamSubBlockGuard Block(Stream, BI_RECORD_BLOCK_ID);618  emitRecord(I.USR, RECORD_USR);619  emitRecord(I.Name, RECORD_NAME);620  emitRecord(I.Path, RECORD_PATH);621  emitRecord(I.MangledName, RECORD_MANGLED_NAME);622  for (const auto &N : I.Namespace)623    emitBlock(N, FieldId::F_namespace);624  for (const auto &CI : I.Description)625    emitBlock(CI);626  if (I.DefLoc)627    emitRecord(*I.DefLoc, RECORD_DEFLOCATION);628  for (const auto &L : I.Loc)629    emitRecord(L, RECORD_LOCATION);630  emitRecord(llvm::to_underlying(I.TagType), RECORD_TAG_TYPE);631  emitRecord(I.IsTypeDef, RECORD_IS_TYPE_DEF);632  for (const auto &N : I.Members)633    emitBlock(N);634  for (const auto &P : I.Parents)635    emitBlock(P, FieldId::F_parent);636  for (const auto &P : I.VirtualParents)637    emitBlock(P, FieldId::F_vparent);638  for (const auto &PB : I.Bases)639    emitBlock(PB);640  for (const auto &C : I.Children.Records)641    emitBlock(C, FieldId::F_child_record);642  for (const auto &C : I.Children.Functions)643    emitBlock(C);644  for (const auto &C : I.Children.Enums)645    emitBlock(C);646  for (const auto &C : I.Children.Typedefs)647    emitBlock(C);648  if (I.Template)649    emitBlock(*I.Template);650  for (const auto &C : I.Friends)651    emitBlock(C);652}653 654void ClangDocBitcodeWriter::emitBlock(const BaseRecordInfo &I) {655  StreamSubBlockGuard Block(Stream, BI_BASE_RECORD_BLOCK_ID);656  emitRecord(I.USR, BASE_RECORD_USR);657  emitRecord(I.Name, BASE_RECORD_NAME);658  emitRecord(I.Path, BASE_RECORD_PATH);659  emitRecord(llvm::to_underlying(I.TagType), BASE_RECORD_TAG_TYPE);660  emitRecord(I.IsVirtual, BASE_RECORD_IS_VIRTUAL);661  emitRecord(I.Access, BASE_RECORD_ACCESS);662  emitRecord(I.IsParent, BASE_RECORD_IS_PARENT);663  for (const auto &M : I.Members)664    emitBlock(M);665  for (const auto &C : I.Children.Functions)666    emitBlock(C);667}668 669void ClangDocBitcodeWriter::emitBlock(const FunctionInfo &I) {670  StreamSubBlockGuard Block(Stream, BI_FUNCTION_BLOCK_ID);671  emitRecord(I.USR, FUNCTION_USR);672  emitRecord(I.Name, FUNCTION_NAME);673  for (const auto &N : I.Namespace)674    emitBlock(N, FieldId::F_namespace);675  for (const auto &CI : I.Description)676    emitBlock(CI);677  emitRecord(I.Access, FUNCTION_ACCESS);678  emitRecord(I.IsMethod, FUNCTION_IS_METHOD);679  emitRecord(I.IsStatic, FUNCTION_IS_STATIC);680  if (I.DefLoc)681    emitRecord(*I.DefLoc, FUNCTION_DEFLOCATION);682  for (const auto &L : I.Loc)683    emitRecord(L, FUNCTION_LOCATION);684  emitBlock(I.Parent, FieldId::F_parent);685  emitBlock(I.ReturnType);686  for (const auto &N : I.Params)687    emitBlock(N);688  if (I.Template)689    emitBlock(*I.Template);690}691 692void ClangDocBitcodeWriter::emitBlock(const ConceptInfo &I) {693  StreamSubBlockGuard Block(Stream, BI_CONCEPT_BLOCK_ID);694  emitRecord(I.USR, CONCEPT_USR);695  emitRecord(I.Name, CONCEPT_NAME);696  for (const auto &CI : I.Description)697    emitBlock(CI);698  emitRecord(I.IsType, CONCEPT_IS_TYPE);699  emitRecord(I.ConstraintExpression, CONCEPT_CONSTRAINT_EXPRESSION);700  emitBlock(I.Template);701}702 703void ClangDocBitcodeWriter::emitBlock(const TemplateInfo &T) {704  StreamSubBlockGuard Block(Stream, BI_TEMPLATE_BLOCK_ID);705  for (const auto &P : T.Params)706    emitBlock(P);707  if (T.Specialization)708    emitBlock(*T.Specialization);709  for (const auto &C : T.Constraints)710    emitBlock(C);711}712 713void ClangDocBitcodeWriter::emitBlock(const TemplateSpecializationInfo &T) {714  StreamSubBlockGuard Block(Stream, BI_TEMPLATE_SPECIALIZATION_BLOCK_ID);715  emitRecord(T.SpecializationOf, TEMPLATE_SPECIALIZATION_OF);716  for (const auto &P : T.Params)717    emitBlock(P);718}719 720void ClangDocBitcodeWriter::emitBlock(const TemplateParamInfo &T) {721  StreamSubBlockGuard Block(Stream, BI_TEMPLATE_PARAM_BLOCK_ID);722  emitRecord(T.Contents, TEMPLATE_PARAM_CONTENTS);723}724 725void ClangDocBitcodeWriter::emitBlock(const ConstraintInfo &C) {726  StreamSubBlockGuard Block(Stream, BI_CONSTRAINT_BLOCK_ID);727  emitRecord(C.ConstraintExpr, CONSTRAINT_EXPRESSION);728  emitBlock(C.ConceptRef, FieldId::F_concept);729}730 731void ClangDocBitcodeWriter::emitBlock(const VarInfo &I) {732  StreamSubBlockGuard Block(Stream, BI_VAR_BLOCK_ID);733  emitRecord(I.USR, VAR_USR);734  emitRecord(I.Name, VAR_NAME);735  for (const auto &N : I.Namespace)736    emitBlock(N, FieldId::F_namespace);737  for (const auto &CI : I.Description)738    emitBlock(CI);739  if (I.DefLoc)740    emitRecord(*I.DefLoc, VAR_DEFLOCATION);741  emitRecord(I.IsStatic, VAR_IS_STATIC);742  emitBlock(I.Type);743}744 745bool ClangDocBitcodeWriter::dispatchInfoForWrite(Info *I) {746  switch (I->IT) {747  case InfoType::IT_namespace:748    emitBlock(*static_cast<clang::doc::NamespaceInfo *>(I));749    break;750  case InfoType::IT_record:751    emitBlock(*static_cast<clang::doc::RecordInfo *>(I));752    break;753  case InfoType::IT_enum:754    emitBlock(*static_cast<clang::doc::EnumInfo *>(I));755    break;756  case InfoType::IT_function:757    emitBlock(*static_cast<clang::doc::FunctionInfo *>(I));758    break;759  case InfoType::IT_typedef:760    emitBlock(*static_cast<clang::doc::TypedefInfo *>(I));761    break;762  case InfoType::IT_concept:763    emitBlock(*static_cast<clang::doc::ConceptInfo *>(I));764    break;765  case InfoType::IT_variable:766    emitBlock(*static_cast<VarInfo *>(I));767    break;768  case InfoType::IT_friend:769    emitBlock(*static_cast<FriendInfo *>(I));770    break;771  case InfoType::IT_default:772    llvm::errs() << "Unexpected info, unable to write.\n";773    return true;774  }775  return false;776}777 778} // namespace doc779} // namespace clang780