123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982 |
- //===-- BitcodeReader.cpp - ClangDoc Bitcode Reader ------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "BitcodeReader.h"
- #include "llvm/ADT/IndexedMap.h"
- #include "llvm/Support/Error.h"
- #include "llvm/Support/raw_ostream.h"
- #include <optional>
- namespace clang {
- namespace doc {
- using Record = llvm::SmallVector<uint64_t, 1024>;
- // This implements decode for SmallString.
- llvm::Error decodeRecord(const Record &R, llvm::SmallVectorImpl<char> &Field,
- llvm::StringRef Blob) {
- Field.assign(Blob.begin(), Blob.end());
- return llvm::Error::success();
- }
- llvm::Error decodeRecord(const Record &R, SymbolID &Field,
- llvm::StringRef Blob) {
- if (R[0] != BitCodeConstants::USRHashSize)
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "incorrect USR size");
- // First position in the record is the length of the following array, so we
- // copy the following elements to the field.
- for (int I = 0, E = R[0]; I < E; ++I)
- Field[I] = R[I + 1];
- return llvm::Error::success();
- }
- llvm::Error decodeRecord(const Record &R, bool &Field, llvm::StringRef Blob) {
- Field = R[0] != 0;
- return llvm::Error::success();
- }
- llvm::Error decodeRecord(const Record &R, int &Field, llvm::StringRef Blob) {
- if (R[0] > INT_MAX)
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "integer too large to parse");
- Field = (int)R[0];
- return llvm::Error::success();
- }
- llvm::Error decodeRecord(const Record &R, AccessSpecifier &Field,
- llvm::StringRef Blob) {
- switch (R[0]) {
- case AS_public:
- case AS_private:
- case AS_protected:
- case AS_none:
- Field = (AccessSpecifier)R[0];
- return llvm::Error::success();
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid value for AccessSpecifier");
- }
- }
- llvm::Error decodeRecord(const Record &R, TagTypeKind &Field,
- llvm::StringRef Blob) {
- switch (R[0]) {
- case TTK_Struct:
- case TTK_Interface:
- case TTK_Union:
- case TTK_Class:
- case TTK_Enum:
- Field = (TagTypeKind)R[0];
- return llvm::Error::success();
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid value for TagTypeKind");
- }
- }
- llvm::Error decodeRecord(const Record &R, std::optional<Location> &Field,
- llvm::StringRef Blob) {
- if (R[0] > INT_MAX)
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "integer too large to parse");
- Field.emplace((int)R[0], Blob, (bool)R[1]);
- return llvm::Error::success();
- }
- llvm::Error decodeRecord(const Record &R, InfoType &Field,
- llvm::StringRef Blob) {
- switch (auto IT = static_cast<InfoType>(R[0])) {
- case InfoType::IT_namespace:
- case InfoType::IT_record:
- case InfoType::IT_function:
- case InfoType::IT_default:
- case InfoType::IT_enum:
- case InfoType::IT_typedef:
- Field = IT;
- return llvm::Error::success();
- }
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid value for InfoType");
- }
- llvm::Error decodeRecord(const Record &R, FieldId &Field,
- llvm::StringRef Blob) {
- switch (auto F = static_cast<FieldId>(R[0])) {
- case FieldId::F_namespace:
- case FieldId::F_parent:
- case FieldId::F_vparent:
- case FieldId::F_type:
- case FieldId::F_child_namespace:
- case FieldId::F_child_record:
- case FieldId::F_default:
- Field = F;
- return llvm::Error::success();
- }
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid value for FieldId");
- }
- llvm::Error decodeRecord(const Record &R,
- llvm::SmallVectorImpl<llvm::SmallString<16>> &Field,
- llvm::StringRef Blob) {
- Field.push_back(Blob);
- return llvm::Error::success();
- }
- llvm::Error decodeRecord(const Record &R,
- llvm::SmallVectorImpl<Location> &Field,
- llvm::StringRef Blob) {
- if (R[0] > INT_MAX)
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "integer too large to parse");
- Field.emplace_back((int)R[0], Blob, (bool)R[1]);
- return llvm::Error::success();
- }
- llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
- const unsigned VersionNo) {
- if (ID == VERSION && R[0] == VersionNo)
- return llvm::Error::success();
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "mismatched bitcode version number");
- }
- llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
- NamespaceInfo *I) {
- switch (ID) {
- case NAMESPACE_USR:
- return decodeRecord(R, I->USR, Blob);
- case NAMESPACE_NAME:
- return decodeRecord(R, I->Name, Blob);
- case NAMESPACE_PATH:
- return decodeRecord(R, I->Path, Blob);
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid field for NamespaceInfo");
- }
- }
- llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
- RecordInfo *I) {
- switch (ID) {
- case RECORD_USR:
- return decodeRecord(R, I->USR, Blob);
- case RECORD_NAME:
- return decodeRecord(R, I->Name, Blob);
- case RECORD_PATH:
- return decodeRecord(R, I->Path, Blob);
- case RECORD_DEFLOCATION:
- return decodeRecord(R, I->DefLoc, Blob);
- case RECORD_LOCATION:
- return decodeRecord(R, I->Loc, Blob);
- case RECORD_TAG_TYPE:
- return decodeRecord(R, I->TagType, Blob);
- case RECORD_IS_TYPE_DEF:
- return decodeRecord(R, I->IsTypeDef, Blob);
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid field for RecordInfo");
- }
- }
- llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
- BaseRecordInfo *I) {
- switch (ID) {
- case BASE_RECORD_USR:
- return decodeRecord(R, I->USR, Blob);
- case BASE_RECORD_NAME:
- return decodeRecord(R, I->Name, Blob);
- case BASE_RECORD_PATH:
- return decodeRecord(R, I->Path, Blob);
- case BASE_RECORD_TAG_TYPE:
- return decodeRecord(R, I->TagType, Blob);
- case BASE_RECORD_IS_VIRTUAL:
- return decodeRecord(R, I->IsVirtual, Blob);
- case BASE_RECORD_ACCESS:
- return decodeRecord(R, I->Access, Blob);
- case BASE_RECORD_IS_PARENT:
- return decodeRecord(R, I->IsParent, Blob);
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid field for BaseRecordInfo");
- }
- }
- llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
- EnumInfo *I) {
- switch (ID) {
- case ENUM_USR:
- return decodeRecord(R, I->USR, Blob);
- case ENUM_NAME:
- return decodeRecord(R, I->Name, Blob);
- case ENUM_DEFLOCATION:
- return decodeRecord(R, I->DefLoc, Blob);
- case ENUM_LOCATION:
- return decodeRecord(R, I->Loc, Blob);
- case ENUM_SCOPED:
- return decodeRecord(R, I->Scoped, Blob);
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid field for EnumInfo");
- }
- }
- llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
- TypedefInfo *I) {
- switch (ID) {
- case TYPEDEF_USR:
- return decodeRecord(R, I->USR, Blob);
- case TYPEDEF_NAME:
- return decodeRecord(R, I->Name, Blob);
- case TYPEDEF_DEFLOCATION:
- return decodeRecord(R, I->DefLoc, Blob);
- case TYPEDEF_IS_USING:
- return decodeRecord(R, I->IsUsing, Blob);
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid field for TypedefInfo");
- }
- }
- llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
- EnumValueInfo *I) {
- switch (ID) {
- case ENUM_VALUE_NAME:
- return decodeRecord(R, I->Name, Blob);
- case ENUM_VALUE_VALUE:
- return decodeRecord(R, I->Value, Blob);
- case ENUM_VALUE_EXPR:
- return decodeRecord(R, I->ValueExpr, Blob);
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid field for EnumValueInfo");
- }
- }
- llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
- FunctionInfo *I) {
- switch (ID) {
- case FUNCTION_USR:
- return decodeRecord(R, I->USR, Blob);
- case FUNCTION_NAME:
- return decodeRecord(R, I->Name, Blob);
- case FUNCTION_DEFLOCATION:
- return decodeRecord(R, I->DefLoc, Blob);
- case FUNCTION_LOCATION:
- return decodeRecord(R, I->Loc, Blob);
- case FUNCTION_ACCESS:
- return decodeRecord(R, I->Access, Blob);
- case FUNCTION_IS_METHOD:
- return decodeRecord(R, I->IsMethod, Blob);
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid field for FunctionInfo");
- }
- }
- llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
- TypeInfo *I) {
- return llvm::Error::success();
- }
- llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
- FieldTypeInfo *I) {
- switch (ID) {
- case FIELD_TYPE_NAME:
- return decodeRecord(R, I->Name, Blob);
- case FIELD_DEFAULT_VALUE:
- return decodeRecord(R, I->DefaultValue, Blob);
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid field for TypeInfo");
- }
- }
- llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
- MemberTypeInfo *I) {
- switch (ID) {
- case MEMBER_TYPE_NAME:
- return decodeRecord(R, I->Name, Blob);
- case MEMBER_TYPE_ACCESS:
- return decodeRecord(R, I->Access, Blob);
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid field for MemberTypeInfo");
- }
- }
- llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
- CommentInfo *I) {
- switch (ID) {
- case COMMENT_KIND:
- return decodeRecord(R, I->Kind, Blob);
- case COMMENT_TEXT:
- return decodeRecord(R, I->Text, Blob);
- case COMMENT_NAME:
- return decodeRecord(R, I->Name, Blob);
- case COMMENT_DIRECTION:
- return decodeRecord(R, I->Direction, Blob);
- case COMMENT_PARAMNAME:
- return decodeRecord(R, I->ParamName, Blob);
- case COMMENT_CLOSENAME:
- return decodeRecord(R, I->CloseName, Blob);
- case COMMENT_ATTRKEY:
- return decodeRecord(R, I->AttrKeys, Blob);
- case COMMENT_ATTRVAL:
- return decodeRecord(R, I->AttrValues, Blob);
- case COMMENT_ARG:
- return decodeRecord(R, I->Args, Blob);
- case COMMENT_SELFCLOSING:
- return decodeRecord(R, I->SelfClosing, Blob);
- case COMMENT_EXPLICIT:
- return decodeRecord(R, I->Explicit, Blob);
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid field for CommentInfo");
- }
- }
- llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
- Reference *I, FieldId &F) {
- switch (ID) {
- case REFERENCE_USR:
- return decodeRecord(R, I->USR, Blob);
- case REFERENCE_NAME:
- return decodeRecord(R, I->Name, Blob);
- case REFERENCE_QUAL_NAME:
- return decodeRecord(R, I->QualName, Blob);
- case REFERENCE_TYPE:
- return decodeRecord(R, I->RefType, Blob);
- case REFERENCE_PATH:
- return decodeRecord(R, I->Path, Blob);
- case REFERENCE_FIELD:
- return decodeRecord(R, F, Blob);
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid field for Reference");
- }
- }
- llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
- TemplateInfo *I) {
- // Currently there are no child records of TemplateInfo (only child blocks).
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid field for TemplateParamInfo");
- }
- llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
- TemplateSpecializationInfo *I) {
- if (ID == TEMPLATE_SPECIALIZATION_OF)
- return decodeRecord(R, I->SpecializationOf, Blob);
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid field for TemplateParamInfo");
- }
- llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
- TemplateParamInfo *I) {
- if (ID == TEMPLATE_PARAM_CONTENTS)
- return decodeRecord(R, I->Contents, Blob);
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid field for TemplateParamInfo");
- }
- template <typename T> llvm::Expected<CommentInfo *> getCommentInfo(T I) {
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid type cannot contain CommentInfo");
- }
- template <> llvm::Expected<CommentInfo *> getCommentInfo(FunctionInfo *I) {
- return &I->Description.emplace_back();
- }
- template <> llvm::Expected<CommentInfo *> getCommentInfo(NamespaceInfo *I) {
- return &I->Description.emplace_back();
- }
- template <> llvm::Expected<CommentInfo *> getCommentInfo(RecordInfo *I) {
- return &I->Description.emplace_back();
- }
- template <> llvm::Expected<CommentInfo *> getCommentInfo(MemberTypeInfo *I) {
- return &I->Description.emplace_back();
- }
- template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumInfo *I) {
- return &I->Description.emplace_back();
- }
- template <> llvm::Expected<CommentInfo *> getCommentInfo(TypedefInfo *I) {
- return &I->Description.emplace_back();
- }
- template <> llvm::Expected<CommentInfo *> getCommentInfo(CommentInfo *I) {
- I->Children.emplace_back(std::make_unique<CommentInfo>());
- return I->Children.back().get();
- }
- template <>
- llvm::Expected<CommentInfo *> getCommentInfo(std::unique_ptr<CommentInfo> &I) {
- return getCommentInfo(I.get());
- }
- // When readSubBlock encounters a TypeInfo sub-block, it calls addTypeInfo on
- // the parent block to set it. The template specializations define what to do
- // for each supported parent block.
- template <typename T, typename TTypeInfo>
- llvm::Error addTypeInfo(T I, TTypeInfo &&TI) {
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid type cannot contain TypeInfo");
- }
- template <> llvm::Error addTypeInfo(RecordInfo *I, MemberTypeInfo &&T) {
- I->Members.emplace_back(std::move(T));
- return llvm::Error::success();
- }
- template <> llvm::Error addTypeInfo(BaseRecordInfo *I, MemberTypeInfo &&T) {
- I->Members.emplace_back(std::move(T));
- return llvm::Error::success();
- }
- template <> llvm::Error addTypeInfo(FunctionInfo *I, TypeInfo &&T) {
- I->ReturnType = std::move(T);
- return llvm::Error::success();
- }
- template <> llvm::Error addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) {
- I->Params.emplace_back(std::move(T));
- return llvm::Error::success();
- }
- template <> llvm::Error addTypeInfo(EnumInfo *I, TypeInfo &&T) {
- I->BaseType = std::move(T);
- return llvm::Error::success();
- }
- template <> llvm::Error addTypeInfo(TypedefInfo *I, TypeInfo &&T) {
- I->Underlying = std::move(T);
- return llvm::Error::success();
- }
- template <typename T> llvm::Error addReference(T I, Reference &&R, FieldId F) {
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid type cannot contain Reference");
- }
- template <> llvm::Error addReference(TypeInfo *I, Reference &&R, FieldId F) {
- switch (F) {
- case FieldId::F_type:
- I->Type = std::move(R);
- return llvm::Error::success();
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid type cannot contain Reference");
- }
- }
- template <>
- llvm::Error addReference(FieldTypeInfo *I, Reference &&R, FieldId F) {
- switch (F) {
- case FieldId::F_type:
- I->Type = std::move(R);
- return llvm::Error::success();
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid type cannot contain Reference");
- }
- }
- template <>
- llvm::Error addReference(MemberTypeInfo *I, Reference &&R, FieldId F) {
- switch (F) {
- case FieldId::F_type:
- I->Type = std::move(R);
- return llvm::Error::success();
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid type cannot contain Reference");
- }
- }
- template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F) {
- switch (F) {
- case FieldId::F_namespace:
- I->Namespace.emplace_back(std::move(R));
- return llvm::Error::success();
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid type cannot contain Reference");
- }
- }
- template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F) {
- switch (F) {
- case FieldId::F_namespace:
- I->Namespace.emplace_back(std::move(R));
- return llvm::Error::success();
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid type cannot contain Reference");
- }
- }
- template <>
- llvm::Error addReference(NamespaceInfo *I, Reference &&R, FieldId F) {
- switch (F) {
- case FieldId::F_namespace:
- I->Namespace.emplace_back(std::move(R));
- return llvm::Error::success();
- case FieldId::F_child_namespace:
- I->Children.Namespaces.emplace_back(std::move(R));
- return llvm::Error::success();
- case FieldId::F_child_record:
- I->Children.Records.emplace_back(std::move(R));
- return llvm::Error::success();
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid type cannot contain Reference");
- }
- }
- template <>
- llvm::Error addReference(FunctionInfo *I, Reference &&R, FieldId F) {
- switch (F) {
- case FieldId::F_namespace:
- I->Namespace.emplace_back(std::move(R));
- return llvm::Error::success();
- case FieldId::F_parent:
- I->Parent = std::move(R);
- return llvm::Error::success();
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid type cannot contain Reference");
- }
- }
- template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) {
- switch (F) {
- case FieldId::F_namespace:
- I->Namespace.emplace_back(std::move(R));
- return llvm::Error::success();
- case FieldId::F_parent:
- I->Parents.emplace_back(std::move(R));
- return llvm::Error::success();
- case FieldId::F_vparent:
- I->VirtualParents.emplace_back(std::move(R));
- return llvm::Error::success();
- case FieldId::F_child_record:
- I->Children.Records.emplace_back(std::move(R));
- return llvm::Error::success();
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid type cannot contain Reference");
- }
- }
- template <typename T, typename ChildInfoType>
- void addChild(T I, ChildInfoType &&R) {
- llvm::errs() << "invalid child type for info";
- exit(1);
- }
- // Namespace children:
- template <> void addChild(NamespaceInfo *I, FunctionInfo &&R) {
- I->Children.Functions.emplace_back(std::move(R));
- }
- template <> void addChild(NamespaceInfo *I, EnumInfo &&R) {
- I->Children.Enums.emplace_back(std::move(R));
- }
- template <> void addChild(NamespaceInfo *I, TypedefInfo &&R) {
- I->Children.Typedefs.emplace_back(std::move(R));
- }
- // Record children:
- template <> void addChild(RecordInfo *I, FunctionInfo &&R) {
- I->Children.Functions.emplace_back(std::move(R));
- }
- template <> void addChild(RecordInfo *I, EnumInfo &&R) {
- I->Children.Enums.emplace_back(std::move(R));
- }
- template <> void addChild(RecordInfo *I, TypedefInfo &&R) {
- I->Children.Typedefs.emplace_back(std::move(R));
- }
- // Other types of children:
- template <> void addChild(EnumInfo *I, EnumValueInfo &&R) {
- I->Members.emplace_back(std::move(R));
- }
- template <> void addChild(RecordInfo *I, BaseRecordInfo &&R) {
- I->Bases.emplace_back(std::move(R));
- }
- template <> void addChild(BaseRecordInfo *I, FunctionInfo &&R) {
- I->Children.Functions.emplace_back(std::move(R));
- }
- // TemplateParam children. These go into either a TemplateInfo (for template
- // parameters) or TemplateSpecializationInfo (for the specialization's
- // parameters).
- template <typename T> void addTemplateParam(T I, TemplateParamInfo &&P) {
- llvm::errs() << "invalid container for template parameter";
- exit(1);
- }
- template <> void addTemplateParam(TemplateInfo *I, TemplateParamInfo &&P) {
- I->Params.emplace_back(std::move(P));
- }
- template <>
- void addTemplateParam(TemplateSpecializationInfo *I, TemplateParamInfo &&P) {
- I->Params.emplace_back(std::move(P));
- }
- // Template info. These apply to either records or functions.
- template <typename T> void addTemplate(T I, TemplateInfo &&P) {
- llvm::errs() << "invalid container for template info";
- exit(1);
- }
- template <> void addTemplate(RecordInfo *I, TemplateInfo &&P) {
- I->Template.emplace(std::move(P));
- }
- template <> void addTemplate(FunctionInfo *I, TemplateInfo &&P) {
- I->Template.emplace(std::move(P));
- }
- // Template specializations go only into template records.
- template <typename T>
- void addTemplateSpecialization(T I, TemplateSpecializationInfo &&TSI) {
- llvm::errs() << "invalid container for template specialization info";
- exit(1);
- }
- template <>
- void addTemplateSpecialization(TemplateInfo *I,
- TemplateSpecializationInfo &&TSI) {
- I->Specialization.emplace(std::move(TSI));
- }
- // Read records from bitcode into a given info.
- template <typename T>
- llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, T I) {
- Record R;
- llvm::StringRef Blob;
- llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
- if (!MaybeRecID)
- return MaybeRecID.takeError();
- return parseRecord(R, MaybeRecID.get(), Blob, I);
- }
- template <>
- llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {
- Record R;
- llvm::StringRef Blob;
- llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
- if (!MaybeRecID)
- return MaybeRecID.takeError();
- return parseRecord(R, MaybeRecID.get(), Blob, I, CurrentReferenceField);
- }
- // Read a block of records into a single info.
- template <typename T>
- llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
- if (llvm::Error Err = Stream.EnterSubBlock(ID))
- return Err;
- while (true) {
- unsigned BlockOrCode = 0;
- Cursor Res = skipUntilRecordOrBlock(BlockOrCode);
- switch (Res) {
- case Cursor::BadBlock:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "bad block found");
- case Cursor::BlockEnd:
- return llvm::Error::success();
- case Cursor::BlockBegin:
- if (llvm::Error Err = readSubBlock(BlockOrCode, I)) {
- if (llvm::Error Skipped = Stream.SkipBlock())
- return joinErrors(std::move(Err), std::move(Skipped));
- return Err;
- }
- continue;
- case Cursor::Record:
- break;
- }
- if (auto Err = readRecord(BlockOrCode, I))
- return Err;
- }
- }
- template <typename T>
- llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
- switch (ID) {
- // Blocks can only have certain types of sub blocks.
- case BI_COMMENT_BLOCK_ID: {
- auto Comment = getCommentInfo(I);
- if (!Comment)
- return Comment.takeError();
- if (auto Err = readBlock(ID, Comment.get()))
- return Err;
- return llvm::Error::success();
- }
- case BI_TYPE_BLOCK_ID: {
- TypeInfo TI;
- if (auto Err = readBlock(ID, &TI))
- return Err;
- if (auto Err = addTypeInfo(I, std::move(TI)))
- return Err;
- return llvm::Error::success();
- }
- case BI_FIELD_TYPE_BLOCK_ID: {
- FieldTypeInfo TI;
- if (auto Err = readBlock(ID, &TI))
- return Err;
- if (auto Err = addTypeInfo(I, std::move(TI)))
- return Err;
- return llvm::Error::success();
- }
- case BI_MEMBER_TYPE_BLOCK_ID: {
- MemberTypeInfo TI;
- if (auto Err = readBlock(ID, &TI))
- return Err;
- if (auto Err = addTypeInfo(I, std::move(TI)))
- return Err;
- return llvm::Error::success();
- }
- case BI_REFERENCE_BLOCK_ID: {
- Reference R;
- if (auto Err = readBlock(ID, &R))
- return Err;
- if (auto Err = addReference(I, std::move(R), CurrentReferenceField))
- return Err;
- return llvm::Error::success();
- }
- case BI_FUNCTION_BLOCK_ID: {
- FunctionInfo F;
- if (auto Err = readBlock(ID, &F))
- return Err;
- addChild(I, std::move(F));
- return llvm::Error::success();
- }
- case BI_BASE_RECORD_BLOCK_ID: {
- BaseRecordInfo BR;
- if (auto Err = readBlock(ID, &BR))
- return Err;
- addChild(I, std::move(BR));
- return llvm::Error::success();
- }
- case BI_ENUM_BLOCK_ID: {
- EnumInfo E;
- if (auto Err = readBlock(ID, &E))
- return Err;
- addChild(I, std::move(E));
- return llvm::Error::success();
- }
- case BI_ENUM_VALUE_BLOCK_ID: {
- EnumValueInfo EV;
- if (auto Err = readBlock(ID, &EV))
- return Err;
- addChild(I, std::move(EV));
- return llvm::Error::success();
- }
- case BI_TEMPLATE_BLOCK_ID: {
- TemplateInfo TI;
- if (auto Err = readBlock(ID, &TI))
- return Err;
- addTemplate(I, std::move(TI));
- return llvm::Error::success();
- }
- case BI_TEMPLATE_SPECIALIZATION_BLOCK_ID: {
- TemplateSpecializationInfo TSI;
- if (auto Err = readBlock(ID, &TSI))
- return Err;
- addTemplateSpecialization(I, std::move(TSI));
- return llvm::Error::success();
- }
- case BI_TEMPLATE_PARAM_BLOCK_ID: {
- TemplateParamInfo TPI;
- if (auto Err = readBlock(ID, &TPI))
- return Err;
- addTemplateParam(I, std::move(TPI));
- return llvm::Error::success();
- }
- case BI_TYPEDEF_BLOCK_ID: {
- TypedefInfo TI;
- if (auto Err = readBlock(ID, &TI))
- return Err;
- addChild(I, std::move(TI));
- return llvm::Error::success();
- }
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid subblock type");
- }
- }
- ClangDocBitcodeReader::Cursor
- ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) {
- BlockOrRecordID = 0;
- while (!Stream.AtEndOfStream()) {
- Expected<unsigned> MaybeCode = Stream.ReadCode();
- if (!MaybeCode) {
- // FIXME this drops the error on the floor.
- consumeError(MaybeCode.takeError());
- return Cursor::BadBlock;
- }
- unsigned Code = MaybeCode.get();
- if (Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) {
- BlockOrRecordID = Code;
- return Cursor::Record;
- }
- switch (static_cast<llvm::bitc::FixedAbbrevIDs>(Code)) {
- case llvm::bitc::ENTER_SUBBLOCK:
- if (Expected<unsigned> MaybeID = Stream.ReadSubBlockID())
- BlockOrRecordID = MaybeID.get();
- else {
- // FIXME this drops the error on the floor.
- consumeError(MaybeID.takeError());
- }
- return Cursor::BlockBegin;
- case llvm::bitc::END_BLOCK:
- if (Stream.ReadBlockEnd())
- return Cursor::BadBlock;
- return Cursor::BlockEnd;
- case llvm::bitc::DEFINE_ABBREV:
- if (llvm::Error Err = Stream.ReadAbbrevRecord()) {
- // FIXME this drops the error on the floor.
- consumeError(std::move(Err));
- }
- continue;
- case llvm::bitc::UNABBREV_RECORD:
- return Cursor::BadBlock;
- case llvm::bitc::FIRST_APPLICATION_ABBREV:
- llvm_unreachable("Unexpected abbrev id.");
- }
- }
- llvm_unreachable("Premature stream end.");
- }
- llvm::Error ClangDocBitcodeReader::validateStream() {
- if (Stream.AtEndOfStream())
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "premature end of stream");
- // Sniff for the signature.
- for (int Idx = 0; Idx != 4; ++Idx) {
- Expected<llvm::SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(8);
- if (!MaybeRead)
- return MaybeRead.takeError();
- else if (MaybeRead.get() != BitCodeConstants::Signature[Idx])
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid bitcode signature");
- }
- return llvm::Error::success();
- }
- llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() {
- Expected<std::optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo =
- Stream.ReadBlockInfoBlock();
- if (!MaybeBlockInfo)
- return MaybeBlockInfo.takeError();
- else
- BlockInfo = MaybeBlockInfo.get();
- if (!BlockInfo)
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "unable to parse BlockInfoBlock");
- Stream.setBlockInfo(&*BlockInfo);
- return llvm::Error::success();
- }
- template <typename T>
- llvm::Expected<std::unique_ptr<Info>>
- ClangDocBitcodeReader::createInfo(unsigned ID) {
- std::unique_ptr<Info> I = std::make_unique<T>();
- if (auto Err = readBlock(ID, static_cast<T *>(I.get())))
- return std::move(Err);
- return std::unique_ptr<Info>{std::move(I)};
- }
- llvm::Expected<std::unique_ptr<Info>>
- ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
- switch (ID) {
- case BI_NAMESPACE_BLOCK_ID:
- return createInfo<NamespaceInfo>(ID);
- case BI_RECORD_BLOCK_ID:
- return createInfo<RecordInfo>(ID);
- case BI_ENUM_BLOCK_ID:
- return createInfo<EnumInfo>(ID);
- case BI_TYPEDEF_BLOCK_ID:
- return createInfo<TypedefInfo>(ID);
- case BI_FUNCTION_BLOCK_ID:
- return createInfo<FunctionInfo>(ID);
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "cannot create info");
- }
- }
- // Entry point
- llvm::Expected<std::vector<std::unique_ptr<Info>>>
- ClangDocBitcodeReader::readBitcode() {
- std::vector<std::unique_ptr<Info>> Infos;
- if (auto Err = validateStream())
- return std::move(Err);
- // Read the top level blocks.
- while (!Stream.AtEndOfStream()) {
- Expected<unsigned> MaybeCode = Stream.ReadCode();
- if (!MaybeCode)
- return MaybeCode.takeError();
- if (MaybeCode.get() != llvm::bitc::ENTER_SUBBLOCK)
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "no blocks in input");
- Expected<unsigned> MaybeID = Stream.ReadSubBlockID();
- if (!MaybeID)
- return MaybeID.takeError();
- unsigned ID = MaybeID.get();
- switch (ID) {
- // NamedType and Comment blocks should not appear at the top level
- case BI_TYPE_BLOCK_ID:
- case BI_FIELD_TYPE_BLOCK_ID:
- case BI_MEMBER_TYPE_BLOCK_ID:
- case BI_COMMENT_BLOCK_ID:
- case BI_REFERENCE_BLOCK_ID:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid top level block");
- case BI_NAMESPACE_BLOCK_ID:
- case BI_RECORD_BLOCK_ID:
- case BI_ENUM_BLOCK_ID:
- case BI_TYPEDEF_BLOCK_ID:
- case BI_FUNCTION_BLOCK_ID: {
- auto InfoOrErr = readBlockToInfo(ID);
- if (!InfoOrErr)
- return InfoOrErr.takeError();
- Infos.emplace_back(std::move(InfoOrErr.get()));
- continue;
- }
- case BI_VERSION_BLOCK_ID:
- if (auto Err = readBlock(ID, VersionNumber))
- return std::move(Err);
- continue;
- case llvm::bitc::BLOCKINFO_BLOCK_ID:
- if (auto Err = readBlockInfoBlock())
- return std::move(Err);
- continue;
- default:
- if (llvm::Error Err = Stream.SkipBlock()) {
- // FIXME this drops the error on the floor.
- consumeError(std::move(Err));
- }
- continue;
- }
- }
- return std::move(Infos);
- }
- } // namespace doc
- } // namespace clang
|