brintos

brintos / llvm-project-archived public Read only

0
0
Text · 38.6 KiB · dd5bbcd Raw
1163 lines · cpp
1//===--  BitcodeReader.cpp - ClangDoc Bitcode Reader ------------*- 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 "BitcodeReader.h"10#include "llvm/Support/Error.h"11#include "llvm/Support/TimeProfiler.h"12#include "llvm/Support/raw_ostream.h"13#include <optional>14 15namespace clang {16namespace doc {17 18using Record = llvm::SmallVector<uint64_t, 1024>;19 20// This implements decode for SmallString.21static llvm::Error decodeRecord(const Record &R,22                                llvm::SmallVectorImpl<char> &Field,23                                llvm::StringRef Blob) {24  Field.assign(Blob.begin(), Blob.end());25  return llvm::Error::success();26}27 28static llvm::Error decodeRecord(const Record &R, SymbolID &Field,29                                llvm::StringRef Blob) {30  if (R[0] != BitCodeConstants::USRHashSize)31    return llvm::createStringError(llvm::inconvertibleErrorCode(),32                                   "incorrect USR size");33 34  // First position in the record is the length of the following array, so we35  // copy the following elements to the field.36  for (int I = 0, E = R[0]; I < E; ++I)37    Field[I] = R[I + 1];38  return llvm::Error::success();39}40 41static llvm::Error decodeRecord(const Record &R, bool &Field,42                                llvm::StringRef Blob) {43  Field = R[0] != 0;44  return llvm::Error::success();45}46 47static llvm::Error decodeRecord(const Record &R, AccessSpecifier &Field,48                                llvm::StringRef Blob) {49  switch (R[0]) {50  case AS_public:51  case AS_private:52  case AS_protected:53  case AS_none:54    Field = (AccessSpecifier)R[0];55    return llvm::Error::success();56  }57  llvm_unreachable("invalid value for AccessSpecifier");58}59 60static llvm::Error decodeRecord(const Record &R, TagTypeKind &Field,61                                llvm::StringRef Blob) {62  switch (static_cast<TagTypeKind>(R[0])) {63  case TagTypeKind::Struct:64  case TagTypeKind::Interface:65  case TagTypeKind::Union:66  case TagTypeKind::Class:67  case TagTypeKind::Enum:68    Field = static_cast<TagTypeKind>(R[0]);69    return llvm::Error::success();70  }71  return llvm::createStringError(llvm::inconvertibleErrorCode(),72                                 "invalid value for TagTypeKind");73}74 75static llvm::Error decodeRecord(const Record &R, std::optional<Location> &Field,76                                llvm::StringRef Blob) {77  if (R[0] > INT_MAX)78    return llvm::createStringError(llvm::inconvertibleErrorCode(),79                                   "integer too large to parse");80  Field.emplace(static_cast<int>(R[0]), static_cast<int>(R[1]), Blob,81                static_cast<bool>(R[2]));82  return llvm::Error::success();83}84 85static llvm::Error decodeRecord(const Record &R, InfoType &Field,86                                llvm::StringRef Blob) {87  switch (auto IT = static_cast<InfoType>(R[0])) {88  case InfoType::IT_namespace:89  case InfoType::IT_record:90  case InfoType::IT_function:91  case InfoType::IT_default:92  case InfoType::IT_enum:93  case InfoType::IT_typedef:94  case InfoType::IT_concept:95  case InfoType::IT_variable:96  case InfoType::IT_friend:97    Field = IT;98    return llvm::Error::success();99  }100  return llvm::createStringError(llvm::inconvertibleErrorCode(),101                                 "invalid value for InfoType");102}103 104static llvm::Error decodeRecord(const Record &R, FieldId &Field,105                                llvm::StringRef Blob) {106  switch (auto F = static_cast<FieldId>(R[0])) {107  case FieldId::F_namespace:108  case FieldId::F_parent:109  case FieldId::F_vparent:110  case FieldId::F_type:111  case FieldId::F_child_namespace:112  case FieldId::F_child_record:113  case FieldId::F_concept:114  case FieldId::F_friend:115  case FieldId::F_default:116    Field = F;117    return llvm::Error::success();118  }119  return llvm::createStringError(llvm::inconvertibleErrorCode(),120                                 "invalid value for FieldId");121}122 123static llvm::Error124decodeRecord(const Record &R,125             llvm::SmallVectorImpl<llvm::SmallString<16>> &Field,126             llvm::StringRef Blob) {127  Field.push_back(Blob);128  return llvm::Error::success();129}130 131static llvm::Error decodeRecord(const Record &R,132                                llvm::SmallVectorImpl<Location> &Field,133                                llvm::StringRef Blob) {134  if (R[0] > INT_MAX)135    return llvm::createStringError(llvm::inconvertibleErrorCode(),136                                   "integer too large to parse");137  Field.emplace_back(static_cast<int>(R[0]), static_cast<int>(R[1]), Blob,138                     static_cast<bool>(R[2]));139  return llvm::Error::success();140}141 142static llvm::Error parseRecord(const Record &R, unsigned ID,143                               llvm::StringRef Blob, const unsigned VersionNo) {144  if (ID == VERSION && R[0] == VersionNo)145    return llvm::Error::success();146  return llvm::createStringError(llvm::inconvertibleErrorCode(),147                                 "mismatched bitcode version number");148}149 150static llvm::Error parseRecord(const Record &R, unsigned ID,151                               llvm::StringRef Blob, NamespaceInfo *I) {152  switch (ID) {153  case NAMESPACE_USR:154    return decodeRecord(R, I->USR, Blob);155  case NAMESPACE_NAME:156    return decodeRecord(R, I->Name, Blob);157  case NAMESPACE_PATH:158    return decodeRecord(R, I->Path, Blob);159  default:160    return llvm::createStringError(llvm::inconvertibleErrorCode(),161                                   "invalid field for NamespaceInfo");162  }163}164 165static llvm::Error parseRecord(const Record &R, unsigned ID,166                               llvm::StringRef Blob, RecordInfo *I) {167  switch (ID) {168  case RECORD_USR:169    return decodeRecord(R, I->USR, Blob);170  case RECORD_NAME:171    return decodeRecord(R, I->Name, Blob);172  case RECORD_PATH:173    return decodeRecord(R, I->Path, Blob);174  case RECORD_DEFLOCATION:175    return decodeRecord(R, I->DefLoc, Blob);176  case RECORD_LOCATION:177    return decodeRecord(R, I->Loc, Blob);178  case RECORD_TAG_TYPE:179    return decodeRecord(R, I->TagType, Blob);180  case RECORD_IS_TYPE_DEF:181    return decodeRecord(R, I->IsTypeDef, Blob);182  case RECORD_MANGLED_NAME:183    return decodeRecord(R, I->MangledName, Blob);184  default:185    return llvm::createStringError(llvm::inconvertibleErrorCode(),186                                   "invalid field for RecordInfo");187  }188}189 190static llvm::Error parseRecord(const Record &R, unsigned ID,191                               llvm::StringRef Blob, BaseRecordInfo *I) {192  switch (ID) {193  case BASE_RECORD_USR:194    return decodeRecord(R, I->USR, Blob);195  case BASE_RECORD_NAME:196    return decodeRecord(R, I->Name, Blob);197  case BASE_RECORD_PATH:198    return decodeRecord(R, I->Path, Blob);199  case BASE_RECORD_TAG_TYPE:200    return decodeRecord(R, I->TagType, Blob);201  case BASE_RECORD_IS_VIRTUAL:202    return decodeRecord(R, I->IsVirtual, Blob);203  case BASE_RECORD_ACCESS:204    return decodeRecord(R, I->Access, Blob);205  case BASE_RECORD_IS_PARENT:206    return decodeRecord(R, I->IsParent, Blob);207  default:208    return llvm::createStringError(llvm::inconvertibleErrorCode(),209                                   "invalid field for BaseRecordInfo");210  }211}212 213static llvm::Error parseRecord(const Record &R, unsigned ID,214                               llvm::StringRef Blob, EnumInfo *I) {215  switch (ID) {216  case ENUM_USR:217    return decodeRecord(R, I->USR, Blob);218  case ENUM_NAME:219    return decodeRecord(R, I->Name, Blob);220  case ENUM_DEFLOCATION:221    return decodeRecord(R, I->DefLoc, Blob);222  case ENUM_LOCATION:223    return decodeRecord(R, I->Loc, Blob);224  case ENUM_SCOPED:225    return decodeRecord(R, I->Scoped, Blob);226  default:227    return llvm::createStringError(llvm::inconvertibleErrorCode(),228                                   "invalid field for EnumInfo");229  }230}231 232static llvm::Error parseRecord(const Record &R, unsigned ID,233                               llvm::StringRef Blob, TypedefInfo *I) {234  switch (ID) {235  case TYPEDEF_USR:236    return decodeRecord(R, I->USR, Blob);237  case TYPEDEF_NAME:238    return decodeRecord(R, I->Name, Blob);239  case TYPEDEF_DEFLOCATION:240    return decodeRecord(R, I->DefLoc, Blob);241  case TYPEDEF_IS_USING:242    return decodeRecord(R, I->IsUsing, Blob);243  default:244    return llvm::createStringError(llvm::inconvertibleErrorCode(),245                                   "invalid field for TypedefInfo");246  }247}248 249static llvm::Error parseRecord(const Record &R, unsigned ID,250                               llvm::StringRef Blob, EnumValueInfo *I) {251  switch (ID) {252  case ENUM_VALUE_NAME:253    return decodeRecord(R, I->Name, Blob);254  case ENUM_VALUE_VALUE:255    return decodeRecord(R, I->Value, Blob);256  case ENUM_VALUE_EXPR:257    return decodeRecord(R, I->ValueExpr, Blob);258  default:259    return llvm::createStringError(llvm::inconvertibleErrorCode(),260                                   "invalid field for EnumValueInfo");261  }262}263 264static llvm::Error parseRecord(const Record &R, unsigned ID,265                               llvm::StringRef Blob, FunctionInfo *I) {266  switch (ID) {267  case FUNCTION_USR:268    return decodeRecord(R, I->USR, Blob);269  case FUNCTION_NAME:270    return decodeRecord(R, I->Name, Blob);271  case FUNCTION_DEFLOCATION:272    return decodeRecord(R, I->DefLoc, Blob);273  case FUNCTION_LOCATION:274    return decodeRecord(R, I->Loc, Blob);275  case FUNCTION_ACCESS:276    return decodeRecord(R, I->Access, Blob);277  case FUNCTION_IS_METHOD:278    return decodeRecord(R, I->IsMethod, Blob);279  case FUNCTION_IS_STATIC:280    return decodeRecord(R, I->IsStatic, Blob);281  default:282    return llvm::createStringError(llvm::inconvertibleErrorCode(),283                                   "invalid field for FunctionInfo");284  }285}286 287static llvm::Error parseRecord(const Record &R, unsigned ID,288                               llvm::StringRef Blob, TypeInfo *I) {289  switch (ID) {290  case TYPE_IS_BUILTIN:291    return decodeRecord(R, I->IsBuiltIn, Blob);292  case TYPE_IS_TEMPLATE:293    return decodeRecord(R, I->IsTemplate, Blob);294  default:295    return llvm::createStringError(llvm::inconvertibleErrorCode(),296                                   "invalid field for TypeInfo");297  }298}299 300static llvm::Error parseRecord(const Record &R, unsigned ID,301                               llvm::StringRef Blob, FieldTypeInfo *I) {302  switch (ID) {303  case FIELD_TYPE_NAME:304    return decodeRecord(R, I->Name, Blob);305  case FIELD_DEFAULT_VALUE:306    return decodeRecord(R, I->DefaultValue, Blob);307  case FIELD_TYPE_IS_BUILTIN:308    return decodeRecord(R, I->IsBuiltIn, Blob);309  case FIELD_TYPE_IS_TEMPLATE:310    return decodeRecord(R, I->IsTemplate, Blob);311  default:312    return llvm::createStringError(llvm::inconvertibleErrorCode(),313                                   "invalid field for TypeInfo");314  }315}316 317static llvm::Error parseRecord(const Record &R, unsigned ID,318                               llvm::StringRef Blob, MemberTypeInfo *I) {319  switch (ID) {320  case MEMBER_TYPE_NAME:321    return decodeRecord(R, I->Name, Blob);322  case MEMBER_TYPE_ACCESS:323    return decodeRecord(R, I->Access, Blob);324  case MEMBER_TYPE_IS_STATIC:325    return decodeRecord(R, I->IsStatic, Blob);326  case MEMBER_TYPE_IS_BUILTIN:327    return decodeRecord(R, I->IsBuiltIn, Blob);328  case MEMBER_TYPE_IS_TEMPLATE:329    return decodeRecord(R, I->IsTemplate, Blob);330  default:331    return llvm::createStringError(llvm::inconvertibleErrorCode(),332                                   "invalid field for MemberTypeInfo");333  }334}335 336static llvm::Error parseRecord(const Record &R, unsigned ID,337                               llvm::StringRef Blob, CommentInfo *I) {338  llvm::SmallString<16> KindStr;339  switch (ID) {340  case COMMENT_KIND:341    if (llvm::Error Err = decodeRecord(R, KindStr, Blob))342      return Err;343    I->Kind = stringToCommentKind(KindStr);344    return llvm::Error::success();345  case COMMENT_TEXT:346    return decodeRecord(R, I->Text, Blob);347  case COMMENT_NAME:348    return decodeRecord(R, I->Name, Blob);349  case COMMENT_DIRECTION:350    return decodeRecord(R, I->Direction, Blob);351  case COMMENT_PARAMNAME:352    return decodeRecord(R, I->ParamName, Blob);353  case COMMENT_CLOSENAME:354    return decodeRecord(R, I->CloseName, Blob);355  case COMMENT_ATTRKEY:356    return decodeRecord(R, I->AttrKeys, Blob);357  case COMMENT_ATTRVAL:358    return decodeRecord(R, I->AttrValues, Blob);359  case COMMENT_ARG:360    return decodeRecord(R, I->Args, Blob);361  case COMMENT_SELFCLOSING:362    return decodeRecord(R, I->SelfClosing, Blob);363  case COMMENT_EXPLICIT:364    return decodeRecord(R, I->Explicit, Blob);365  default:366    return llvm::createStringError(llvm::inconvertibleErrorCode(),367                                   "invalid field for CommentInfo");368  }369}370 371static llvm::Error parseRecord(const Record &R, unsigned ID,372                               llvm::StringRef Blob, Reference *I, FieldId &F) {373  switch (ID) {374  case REFERENCE_USR:375    return decodeRecord(R, I->USR, Blob);376  case REFERENCE_NAME:377    return decodeRecord(R, I->Name, Blob);378  case REFERENCE_QUAL_NAME:379    return decodeRecord(R, I->QualName, Blob);380  case REFERENCE_TYPE:381    return decodeRecord(R, I->RefType, Blob);382  case REFERENCE_PATH:383    return decodeRecord(R, I->Path, Blob);384  case REFERENCE_FIELD:385    return decodeRecord(R, F, Blob);386  case REFERENCE_FILE:387    return decodeRecord(R, I->DocumentationFileName, Blob);388  default:389    return llvm::createStringError(llvm::inconvertibleErrorCode(),390                                   "invalid field for Reference");391  }392}393 394static llvm::Error parseRecord(const Record &R, unsigned ID,395                               llvm::StringRef Blob, TemplateInfo *I) {396  // Currently there are no child records of TemplateInfo (only child blocks).397  return llvm::createStringError(llvm::inconvertibleErrorCode(),398                                 "invalid field for TemplateParamInfo");399}400 401static llvm::Error parseRecord(const Record &R, unsigned ID,402                               llvm::StringRef Blob,403                               TemplateSpecializationInfo *I) {404  if (ID == TEMPLATE_SPECIALIZATION_OF)405    return decodeRecord(R, I->SpecializationOf, Blob);406  return llvm::createStringError(llvm::inconvertibleErrorCode(),407                                 "invalid field for TemplateParamInfo");408}409 410static llvm::Error parseRecord(const Record &R, unsigned ID,411                               llvm::StringRef Blob, TemplateParamInfo *I) {412  if (ID == TEMPLATE_PARAM_CONTENTS)413    return decodeRecord(R, I->Contents, Blob);414  return llvm::createStringError(llvm::inconvertibleErrorCode(),415                                 "invalid field for TemplateParamInfo");416}417 418static llvm::Error parseRecord(const Record &R, unsigned ID,419                               llvm::StringRef Blob, ConceptInfo *I) {420  switch (ID) {421  case CONCEPT_USR:422    return decodeRecord(R, I->USR, Blob);423  case CONCEPT_NAME:424    return decodeRecord(R, I->Name, Blob);425  case CONCEPT_IS_TYPE:426    return decodeRecord(R, I->IsType, Blob);427  case CONCEPT_CONSTRAINT_EXPRESSION:428    return decodeRecord(R, I->ConstraintExpression, Blob);429  }430  llvm_unreachable("invalid field for ConceptInfo");431}432 433static llvm::Error parseRecord(const Record &R, unsigned ID,434                               llvm::StringRef Blob, ConstraintInfo *I) {435  if (ID == CONSTRAINT_EXPRESSION)436    return decodeRecord(R, I->ConstraintExpr, Blob);437  return llvm::createStringError(llvm::inconvertibleErrorCode(),438                                 "invalid field for ConstraintInfo");439}440 441static llvm::Error parseRecord(const Record &R, unsigned ID,442                               llvm::StringRef Blob, VarInfo *I) {443  switch (ID) {444  case VAR_USR:445    return decodeRecord(R, I->USR, Blob);446  case VAR_NAME:447    return decodeRecord(R, I->Name, Blob);448  case VAR_DEFLOCATION:449    return decodeRecord(R, I->DefLoc, Blob);450  case VAR_IS_STATIC:451    return decodeRecord(R, I->IsStatic, Blob);452  default:453    return llvm::createStringError(llvm::inconvertibleErrorCode(),454                                   "invalid field for VarInfo");455  }456}457 458static llvm::Error parseRecord(const Record &R, unsigned ID, StringRef Blob,459                               FriendInfo *F) {460  if (ID == FRIEND_IS_CLASS) {461    return decodeRecord(R, F->IsClass, Blob);462  }463  return llvm::createStringError(llvm::inconvertibleErrorCode(),464                                 "invalid field for Friend");465}466 467template <typename T> static llvm::Expected<CommentInfo *> getCommentInfo(T I) {468  return llvm::createStringError(llvm::inconvertibleErrorCode(),469                                 "invalid type cannot contain CommentInfo");470}471 472template <> llvm::Expected<CommentInfo *> getCommentInfo(FunctionInfo *I) {473  return &I->Description.emplace_back();474}475 476template <> llvm::Expected<CommentInfo *> getCommentInfo(NamespaceInfo *I) {477  return &I->Description.emplace_back();478}479 480template <> llvm::Expected<CommentInfo *> getCommentInfo(RecordInfo *I) {481  return &I->Description.emplace_back();482}483 484template <> llvm::Expected<CommentInfo *> getCommentInfo(MemberTypeInfo *I) {485  return &I->Description.emplace_back();486}487 488template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumInfo *I) {489  return &I->Description.emplace_back();490}491 492template <> llvm::Expected<CommentInfo *> getCommentInfo(TypedefInfo *I) {493  return &I->Description.emplace_back();494}495 496template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumValueInfo *I) {497  return &I->Description.emplace_back();498}499 500template <> llvm::Expected<CommentInfo *> getCommentInfo(CommentInfo *I) {501  I->Children.emplace_back(std::make_unique<CommentInfo>());502  return I->Children.back().get();503}504 505template <> llvm::Expected<CommentInfo *> getCommentInfo(ConceptInfo *I) {506  return &I->Description.emplace_back();507}508 509template <> Expected<CommentInfo *> getCommentInfo(VarInfo *I) {510  return &I->Description.emplace_back();511}512 513// When readSubBlock encounters a TypeInfo sub-block, it calls addTypeInfo on514// the parent block to set it. The template specializations define what to do515// for each supported parent block.516template <typename T, typename TTypeInfo>517static llvm::Error addTypeInfo(T I, TTypeInfo &&TI) {518  return llvm::createStringError(llvm::inconvertibleErrorCode(),519                                 "invalid type cannot contain TypeInfo");520}521 522template <> llvm::Error addTypeInfo(RecordInfo *I, MemberTypeInfo &&T) {523  I->Members.emplace_back(std::move(T));524  return llvm::Error::success();525}526 527template <> llvm::Error addTypeInfo(BaseRecordInfo *I, MemberTypeInfo &&T) {528  I->Members.emplace_back(std::move(T));529  return llvm::Error::success();530}531 532template <> llvm::Error addTypeInfo(FunctionInfo *I, TypeInfo &&T) {533  I->ReturnType = std::move(T);534  return llvm::Error::success();535}536 537template <> llvm::Error addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) {538  I->Params.emplace_back(std::move(T));539  return llvm::Error::success();540}541 542template <> llvm::Error addTypeInfo(FriendInfo *I, FieldTypeInfo &&T) {543  if (!I->Params)544    I->Params.emplace();545  I->Params->emplace_back(std::move(T));546  return llvm::Error::success();547}548 549template <> llvm::Error addTypeInfo(FriendInfo *I, TypeInfo &&T) {550  I->ReturnType.emplace(std::move(T));551  return llvm::Error::success();552}553 554template <> llvm::Error addTypeInfo(EnumInfo *I, TypeInfo &&T) {555  I->BaseType = std::move(T);556  return llvm::Error::success();557}558 559template <> llvm::Error addTypeInfo(TypedefInfo *I, TypeInfo &&T) {560  I->Underlying = std::move(T);561  return llvm::Error::success();562}563 564template <> llvm::Error addTypeInfo(VarInfo *I, TypeInfo &&T) {565  I->Type = std::move(T);566  return llvm::Error::success();567}568 569template <typename T>570static llvm::Error addReference(T I, Reference &&R, FieldId F) {571  return llvm::createStringError(llvm::inconvertibleErrorCode(),572                                 "invalid type cannot contain Reference");573}574 575template <> llvm::Error addReference(VarInfo *I, Reference &&R, FieldId F) {576  switch (F) {577  case FieldId::F_namespace:578    I->Namespace.emplace_back(std::move(R));579    return llvm::Error::success();580  default:581    return llvm::createStringError(llvm::inconvertibleErrorCode(),582                                   "VarInfo cannot contain this Reference");583  }584}585 586template <> llvm::Error addReference(TypeInfo *I, Reference &&R, FieldId F) {587  switch (F) {588  case FieldId::F_type:589    I->Type = std::move(R);590    return llvm::Error::success();591  default:592    return llvm::createStringError(llvm::inconvertibleErrorCode(),593                                   "invalid type cannot contain Reference");594  }595}596 597template <>598llvm::Error addReference(FieldTypeInfo *I, Reference &&R, FieldId F) {599  switch (F) {600  case FieldId::F_type:601    I->Type = std::move(R);602    return llvm::Error::success();603  default:604    return llvm::createStringError(llvm::inconvertibleErrorCode(),605                                   "invalid type cannot contain Reference");606  }607}608 609template <>610llvm::Error addReference(MemberTypeInfo *I, Reference &&R, FieldId F) {611  switch (F) {612  case FieldId::F_type:613    I->Type = std::move(R);614    return llvm::Error::success();615  default:616    return llvm::createStringError(llvm::inconvertibleErrorCode(),617                                   "invalid type cannot contain Reference");618  }619}620 621template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F) {622  switch (F) {623  case FieldId::F_namespace:624    I->Namespace.emplace_back(std::move(R));625    return llvm::Error::success();626  default:627    return llvm::createStringError(llvm::inconvertibleErrorCode(),628                                   "invalid type cannot contain Reference");629  }630}631 632template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F) {633  switch (F) {634  case FieldId::F_namespace:635    I->Namespace.emplace_back(std::move(R));636    return llvm::Error::success();637  default:638    return llvm::createStringError(llvm::inconvertibleErrorCode(),639                                   "invalid type cannot contain Reference");640  }641}642 643template <>644llvm::Error addReference(NamespaceInfo *I, Reference &&R, FieldId F) {645  switch (F) {646  case FieldId::F_namespace:647    I->Namespace.emplace_back(std::move(R));648    return llvm::Error::success();649  case FieldId::F_child_namespace:650    I->Children.Namespaces.emplace_back(std::move(R));651    return llvm::Error::success();652  case FieldId::F_child_record:653    I->Children.Records.emplace_back(std::move(R));654    return llvm::Error::success();655  default:656    return llvm::createStringError(llvm::inconvertibleErrorCode(),657                                   "invalid type cannot contain Reference");658  }659}660 661template <>662llvm::Error addReference(FunctionInfo *I, Reference &&R, FieldId F) {663  switch (F) {664  case FieldId::F_namespace:665    I->Namespace.emplace_back(std::move(R));666    return llvm::Error::success();667  case FieldId::F_parent:668    I->Parent = std::move(R);669    return llvm::Error::success();670  default:671    return llvm::createStringError(llvm::inconvertibleErrorCode(),672                                   "invalid type cannot contain Reference");673  }674}675 676template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) {677  switch (F) {678  case FieldId::F_namespace:679    I->Namespace.emplace_back(std::move(R));680    return llvm::Error::success();681  case FieldId::F_parent:682    I->Parents.emplace_back(std::move(R));683    return llvm::Error::success();684  case FieldId::F_vparent:685    I->VirtualParents.emplace_back(std::move(R));686    return llvm::Error::success();687  case FieldId::F_child_record:688    I->Children.Records.emplace_back(std::move(R));689    return llvm::Error::success();690  default:691    return llvm::createStringError(llvm::inconvertibleErrorCode(),692                                   "invalid type cannot contain Reference");693  }694}695 696template <>697llvm::Error addReference(ConstraintInfo *I, Reference &&R, FieldId F) {698  if (F == FieldId::F_concept) {699    I->ConceptRef = std::move(R);700    return llvm::Error::success();701  }702  return llvm::createStringError(703      llvm::inconvertibleErrorCode(),704      "ConstraintInfo cannot contain this Reference");705}706 707template <>708llvm::Error addReference(FriendInfo *Friend, Reference &&R, FieldId F) {709  if (F == FieldId::F_friend) {710    Friend->Ref = std::move(R);711    return llvm::Error::success();712  }713  return llvm::createStringError(llvm::inconvertibleErrorCode(),714                                 "Friend cannot contain this Reference");715}716 717template <typename T, typename ChildInfoType>718static void addChild(T I, ChildInfoType &&R) {719  llvm::errs() << "invalid child type for info";720  exit(1);721}722 723// Namespace children:724template <> void addChild(NamespaceInfo *I, FunctionInfo &&R) {725  I->Children.Functions.emplace_back(std::move(R));726}727template <> void addChild(NamespaceInfo *I, EnumInfo &&R) {728  I->Children.Enums.emplace_back(std::move(R));729}730template <> void addChild(NamespaceInfo *I, TypedefInfo &&R) {731  I->Children.Typedefs.emplace_back(std::move(R));732}733template <> void addChild(NamespaceInfo *I, ConceptInfo &&R) {734  I->Children.Concepts.emplace_back(std::move(R));735}736template <> void addChild(NamespaceInfo *I, VarInfo &&R) {737  I->Children.Variables.emplace_back(std::move(R));738}739 740// Record children:741template <> void addChild(RecordInfo *I, FunctionInfo &&R) {742  I->Children.Functions.emplace_back(std::move(R));743}744template <> void addChild(RecordInfo *I, EnumInfo &&R) {745  I->Children.Enums.emplace_back(std::move(R));746}747template <> void addChild(RecordInfo *I, TypedefInfo &&R) {748  I->Children.Typedefs.emplace_back(std::move(R));749}750template <> void addChild(RecordInfo *I, FriendInfo &&R) {751  I->Friends.emplace_back(std::move(R));752}753 754// Other types of children:755template <> void addChild(EnumInfo *I, EnumValueInfo &&R) {756  I->Members.emplace_back(std::move(R));757}758template <> void addChild(RecordInfo *I, BaseRecordInfo &&R) {759  I->Bases.emplace_back(std::move(R));760}761template <> void addChild(BaseRecordInfo *I, FunctionInfo &&R) {762  I->Children.Functions.emplace_back(std::move(R));763}764 765// TemplateParam children. These go into either a TemplateInfo (for template766// parameters) or TemplateSpecializationInfo (for the specialization's767// parameters).768template <typename T> static void addTemplateParam(T I, TemplateParamInfo &&P) {769  llvm::errs() << "invalid container for template parameter";770  exit(1);771}772template <> void addTemplateParam(TemplateInfo *I, TemplateParamInfo &&P) {773  I->Params.emplace_back(std::move(P));774}775template <>776void addTemplateParam(TemplateSpecializationInfo *I, TemplateParamInfo &&P) {777  I->Params.emplace_back(std::move(P));778}779 780// Template info. These apply to either records or functions.781template <typename T> static void addTemplate(T I, TemplateInfo &&P) {782  llvm::errs() << "invalid container for template info";783  exit(1);784}785template <> void addTemplate(RecordInfo *I, TemplateInfo &&P) {786  I->Template.emplace(std::move(P));787}788template <> void addTemplate(FunctionInfo *I, TemplateInfo &&P) {789  I->Template.emplace(std::move(P));790}791template <> void addTemplate(ConceptInfo *I, TemplateInfo &&P) {792  I->Template = std::move(P);793}794template <> void addTemplate(FriendInfo *I, TemplateInfo &&P) {795  I->Template.emplace(std::move(P));796}797 798// Template specializations go only into template records.799template <typename T>800static void addTemplateSpecialization(T I, TemplateSpecializationInfo &&TSI) {801  llvm::errs() << "invalid container for template specialization info";802  exit(1);803}804template <>805void addTemplateSpecialization(TemplateInfo *I,806                               TemplateSpecializationInfo &&TSI) {807  I->Specialization.emplace(std::move(TSI));808}809 810template <typename T> static void addConstraint(T I, ConstraintInfo &&C) {811  llvm::errs() << "invalid container for constraint info";812  exit(1);813}814template <> void addConstraint(TemplateInfo *I, ConstraintInfo &&C) {815  I->Constraints.emplace_back(std::move(C));816}817 818// Read records from bitcode into a given info.819template <typename T>820llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, T I) {821  Record R;822  llvm::StringRef Blob;823  llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);824  if (!MaybeRecID)825    return MaybeRecID.takeError();826  return parseRecord(R, MaybeRecID.get(), Blob, I);827}828 829template <>830llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {831  llvm::TimeTraceScope("Reducing infos", "readRecord");832  Record R;833  llvm::StringRef Blob;834  llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);835  if (!MaybeRecID)836    return MaybeRecID.takeError();837  return parseRecord(R, MaybeRecID.get(), Blob, I, CurrentReferenceField);838}839 840// Read a block of records into a single info.841template <typename T>842llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {843  llvm::TimeTraceScope("Reducing infos", "readBlock");844  if (llvm::Error Err = Stream.EnterSubBlock(ID))845    return Err;846 847  while (true) {848    unsigned BlockOrCode = 0;849    Cursor Res = skipUntilRecordOrBlock(BlockOrCode);850 851    switch (Res) {852    case Cursor::BadBlock:853      return llvm::createStringError(llvm::inconvertibleErrorCode(),854                                     "bad block found");855    case Cursor::BlockEnd:856      return llvm::Error::success();857    case Cursor::BlockBegin:858      if (llvm::Error Err = readSubBlock(BlockOrCode, I)) {859        if (llvm::Error Skipped = Stream.SkipBlock())860          return joinErrors(std::move(Err), std::move(Skipped));861        return Err;862      }863      continue;864    case Cursor::Record:865      break;866    }867    if (auto Err = readRecord(BlockOrCode, I))868      return Err;869  }870}871 872// TODO: fix inconsistentent returning of errors in add callbacks.873// Once that's fixed, we only need one handleSubBlock.874template <typename InfoType, typename T, typename Callback>875llvm::Error ClangDocBitcodeReader::handleSubBlock(unsigned ID, T Parent,876                                                  Callback Function) {877  InfoType Info;878  if (auto Err = readBlock(ID, &Info))879    return Err;880  Function(Parent, std::move(Info));881  return llvm::Error::success();882}883 884template <typename InfoType, typename T, typename Callback>885llvm::Error ClangDocBitcodeReader::handleTypeSubBlock(unsigned ID, T Parent,886                                                      Callback Function) {887  InfoType Info;888  if (auto Err = readBlock(ID, &Info))889    return Err;890  if (auto Err = Function(Parent, std::move(Info)))891    return Err;892  return llvm::Error::success();893}894 895template <typename T>896llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {897  llvm::TimeTraceScope("Reducing infos", "readSubBlock");898 899  static auto CreateAddFunc = [](auto AddFunc) {900    return [AddFunc](auto Parent, auto Child) {901      return AddFunc(Parent, std::move(Child));902    };903  };904 905  switch (ID) {906  // Blocks can only have certain types of sub blocks.907  case BI_COMMENT_BLOCK_ID: {908    auto Comment = getCommentInfo(I);909    if (!Comment)910      return Comment.takeError();911    if (auto Err = readBlock(ID, Comment.get()))912      return Err;913    return llvm::Error::success();914  }915  case BI_TYPE_BLOCK_ID: {916    return handleTypeSubBlock<TypeInfo>(917        ID, I, CreateAddFunc(addTypeInfo<T, TypeInfo>));918  }919  case BI_FIELD_TYPE_BLOCK_ID: {920    return handleTypeSubBlock<FieldTypeInfo>(921        ID, I, CreateAddFunc(addTypeInfo<T, FieldTypeInfo>));922  }923  case BI_MEMBER_TYPE_BLOCK_ID: {924    return handleTypeSubBlock<MemberTypeInfo>(925        ID, I, CreateAddFunc(addTypeInfo<T, MemberTypeInfo>));926  }927  case BI_REFERENCE_BLOCK_ID: {928    Reference R;929    if (auto Err = readBlock(ID, &R))930      return Err;931    if (auto Err = addReference(I, std::move(R), CurrentReferenceField))932      return Err;933    return llvm::Error::success();934  }935  case BI_FUNCTION_BLOCK_ID: {936    return handleSubBlock<FunctionInfo>(937        ID, I, CreateAddFunc(addChild<T, FunctionInfo>));938  }939  case BI_BASE_RECORD_BLOCK_ID: {940    return handleSubBlock<BaseRecordInfo>(941        ID, I, CreateAddFunc(addChild<T, BaseRecordInfo>));942  }943  case BI_ENUM_BLOCK_ID: {944    return handleSubBlock<EnumInfo>(ID, I,945                                    CreateAddFunc(addChild<T, EnumInfo>));946  }947  case BI_ENUM_VALUE_BLOCK_ID: {948    return handleSubBlock<EnumValueInfo>(949        ID, I, CreateAddFunc(addChild<T, EnumValueInfo>));950  }951  case BI_TEMPLATE_BLOCK_ID: {952    return handleSubBlock<TemplateInfo>(ID, I, CreateAddFunc(addTemplate<T>));953  }954  case BI_TEMPLATE_SPECIALIZATION_BLOCK_ID: {955    return handleSubBlock<TemplateSpecializationInfo>(956        ID, I, CreateAddFunc(addTemplateSpecialization<T>));957  }958  case BI_TEMPLATE_PARAM_BLOCK_ID: {959    return handleSubBlock<TemplateParamInfo>(960        ID, I, CreateAddFunc(addTemplateParam<T>));961  }962  case BI_TYPEDEF_BLOCK_ID: {963    return handleSubBlock<TypedefInfo>(ID, I,964                                       CreateAddFunc(addChild<T, TypedefInfo>));965  }966  case BI_CONSTRAINT_BLOCK_ID: {967    return handleSubBlock<ConstraintInfo>(ID, I,968                                          CreateAddFunc(addConstraint<T>));969  }970  case BI_CONCEPT_BLOCK_ID: {971    return handleSubBlock<ConceptInfo>(ID, I,972                                       CreateAddFunc(addChild<T, ConceptInfo>));973  }974  case BI_VAR_BLOCK_ID: {975    return handleSubBlock<VarInfo>(ID, I, CreateAddFunc(addChild<T, VarInfo>));976  }977  case BI_FRIEND_BLOCK_ID: {978    return handleSubBlock<FriendInfo>(ID, I,979                                      CreateAddFunc(addChild<T, FriendInfo>));980  }981  default:982    return llvm::createStringError(llvm::inconvertibleErrorCode(),983                                   "invalid subblock type");984  }985}986 987ClangDocBitcodeReader::Cursor988ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) {989  llvm::TimeTraceScope("Reducing infos", "skipUntilRecordOrBlock");990  BlockOrRecordID = 0;991 992  while (!Stream.AtEndOfStream()) {993    Expected<unsigned> MaybeCode = Stream.ReadCode();994    if (!MaybeCode) {995      // FIXME this drops the error on the floor.996      consumeError(MaybeCode.takeError());997      return Cursor::BadBlock;998    }999 1000    unsigned Code = MaybeCode.get();1001    if (Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) {1002      BlockOrRecordID = Code;1003      return Cursor::Record;1004    }1005    switch (static_cast<llvm::bitc::FixedAbbrevIDs>(Code)) {1006    case llvm::bitc::ENTER_SUBBLOCK:1007      if (Expected<unsigned> MaybeID = Stream.ReadSubBlockID())1008        BlockOrRecordID = MaybeID.get();1009      else {1010        // FIXME this drops the error on the floor.1011        consumeError(MaybeID.takeError());1012      }1013      return Cursor::BlockBegin;1014    case llvm::bitc::END_BLOCK:1015      if (Stream.ReadBlockEnd())1016        return Cursor::BadBlock;1017      return Cursor::BlockEnd;1018    case llvm::bitc::DEFINE_ABBREV:1019      if (llvm::Error Err = Stream.ReadAbbrevRecord()) {1020        // FIXME this drops the error on the floor.1021        consumeError(std::move(Err));1022      }1023      continue;1024    case llvm::bitc::UNABBREV_RECORD:1025      return Cursor::BadBlock;1026    case llvm::bitc::FIRST_APPLICATION_ABBREV:1027      llvm_unreachable("Unexpected abbrev id.");1028    }1029  }1030  llvm_unreachable("Premature stream end.");1031}1032 1033llvm::Error ClangDocBitcodeReader::validateStream() {1034  if (Stream.AtEndOfStream())1035    return llvm::createStringError(llvm::inconvertibleErrorCode(),1036                                   "premature end of stream");1037 1038  // Sniff for the signature.1039  for (int Idx = 0; Idx != 4; ++Idx) {1040    Expected<llvm::SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(8);1041    if (!MaybeRead)1042      return MaybeRead.takeError();1043    if (MaybeRead.get() != BitCodeConstants::Signature[Idx])1044      return llvm::createStringError(llvm::inconvertibleErrorCode(),1045                                     "invalid bitcode signature");1046  }1047  return llvm::Error::success();1048}1049 1050llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() {1051  llvm::TimeTraceScope("Reducing infos", "readBlockInfoBlock");1052  Expected<std::optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo =1053      Stream.ReadBlockInfoBlock();1054  if (!MaybeBlockInfo)1055    return MaybeBlockInfo.takeError();1056  BlockInfo = MaybeBlockInfo.get();1057  if (!BlockInfo)1058    return llvm::createStringError(llvm::inconvertibleErrorCode(),1059                                   "unable to parse BlockInfoBlock");1060  Stream.setBlockInfo(&*BlockInfo);1061  return llvm::Error::success();1062}1063 1064template <typename T>1065llvm::Expected<std::unique_ptr<Info>>1066ClangDocBitcodeReader::createInfo(unsigned ID) {1067  llvm::TimeTraceScope("Reducing infos", "createInfo");1068  std::unique_ptr<Info> I = std::make_unique<T>();1069  if (auto Err = readBlock(ID, static_cast<T *>(I.get())))1070    return std::move(Err);1071  return std::unique_ptr<Info>{std::move(I)};1072}1073 1074llvm::Expected<std::unique_ptr<Info>>1075ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {1076  llvm::TimeTraceScope("Reducing infos", "readBlockToInfo");1077  switch (ID) {1078  case BI_NAMESPACE_BLOCK_ID:1079    return createInfo<NamespaceInfo>(ID);1080  case BI_RECORD_BLOCK_ID:1081    return createInfo<RecordInfo>(ID);1082  case BI_ENUM_BLOCK_ID:1083    return createInfo<EnumInfo>(ID);1084  case BI_TYPEDEF_BLOCK_ID:1085    return createInfo<TypedefInfo>(ID);1086  case BI_CONCEPT_BLOCK_ID:1087    return createInfo<ConceptInfo>(ID);1088  case BI_FUNCTION_BLOCK_ID:1089    return createInfo<FunctionInfo>(ID);1090  case BI_VAR_BLOCK_ID:1091    return createInfo<VarInfo>(ID);1092  case BI_FRIEND_BLOCK_ID:1093    return createInfo<FriendInfo>(ID);1094  default:1095    return llvm::createStringError(llvm::inconvertibleErrorCode(),1096                                   "cannot create info");1097  }1098}1099 1100// Entry point1101llvm::Expected<std::vector<std::unique_ptr<Info>>>1102ClangDocBitcodeReader::readBitcode() {1103  std::vector<std::unique_ptr<Info>> Infos;1104  if (auto Err = validateStream())1105    return std::move(Err);1106 1107  // Read the top level blocks.1108  while (!Stream.AtEndOfStream()) {1109    Expected<unsigned> MaybeCode = Stream.ReadCode();1110    if (!MaybeCode)1111      return MaybeCode.takeError();1112    if (MaybeCode.get() != llvm::bitc::ENTER_SUBBLOCK)1113      return llvm::createStringError(llvm::inconvertibleErrorCode(),1114                                     "no blocks in input");1115    Expected<unsigned> MaybeID = Stream.ReadSubBlockID();1116    if (!MaybeID)1117      return MaybeID.takeError();1118    unsigned ID = MaybeID.get();1119    switch (ID) {1120    // NamedType and Comment blocks should not appear at the top level1121    case BI_TYPE_BLOCK_ID:1122    case BI_FIELD_TYPE_BLOCK_ID:1123    case BI_MEMBER_TYPE_BLOCK_ID:1124    case BI_COMMENT_BLOCK_ID:1125    case BI_REFERENCE_BLOCK_ID:1126      return llvm::createStringError(llvm::inconvertibleErrorCode(),1127                                     "invalid top level block");1128    case BI_NAMESPACE_BLOCK_ID:1129    case BI_RECORD_BLOCK_ID:1130    case BI_ENUM_BLOCK_ID:1131    case BI_TYPEDEF_BLOCK_ID:1132    case BI_CONCEPT_BLOCK_ID:1133    case BI_VAR_BLOCK_ID:1134    case BI_FRIEND_BLOCK_ID:1135    case BI_FUNCTION_BLOCK_ID: {1136      auto InfoOrErr = readBlockToInfo(ID);1137      if (!InfoOrErr)1138        return InfoOrErr.takeError();1139      Infos.emplace_back(std::move(InfoOrErr.get()));1140      continue;1141    }1142    case BI_VERSION_BLOCK_ID:1143      if (auto Err = readBlock(ID, VersionNumber))1144        return std::move(Err);1145      continue;1146    case llvm::bitc::BLOCKINFO_BLOCK_ID:1147      if (auto Err = readBlockInfoBlock())1148        return std::move(Err);1149      continue;1150    default:1151      if (llvm::Error Err = Stream.SkipBlock()) {1152        // FIXME this drops the error on the floor.1153        consumeError(std::move(Err));1154      }1155      continue;1156    }1157  }1158  return std::move(Infos);1159}1160 1161} // namespace doc1162} // namespace clang1163