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