1d0f9a872SJulie Hockett //===-- BitcodeReader.cpp - ClangDoc Bitcode Reader ------------*- C++ -*-===// 2d0f9a872SJulie Hockett // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6d0f9a872SJulie Hockett // 7d0f9a872SJulie Hockett //===----------------------------------------------------------------------===// 8d0f9a872SJulie Hockett 9d0f9a872SJulie Hockett #include "BitcodeReader.h" 10d0f9a872SJulie Hockett #include "llvm/ADT/IndexedMap.h" 1146fc9592SJulie Hockett #include "llvm/Support/Error.h" 12d0f9a872SJulie Hockett #include "llvm/Support/raw_ostream.h" 13c589730aSKrzysztof Parzyszek #include <optional> 14d0f9a872SJulie Hockett 15d0f9a872SJulie Hockett namespace clang { 16d0f9a872SJulie Hockett namespace doc { 17d0f9a872SJulie Hockett 18d0f9a872SJulie Hockett using Record = llvm::SmallVector<uint64_t, 1024>; 19d0f9a872SJulie Hockett 20eaa7b324SBrett Wilson // This implements decode for SmallString. 2145617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, llvm::SmallVectorImpl<char> &Field, 22d0f9a872SJulie Hockett llvm::StringRef Blob) { 23d0f9a872SJulie Hockett Field.assign(Blob.begin(), Blob.end()); 2446fc9592SJulie Hockett return llvm::Error::success(); 25d0f9a872SJulie Hockett } 26d0f9a872SJulie Hockett 2745617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, SymbolID &Field, 2845617e1dSSimon Pilgrim llvm::StringRef Blob) { 29d0f9a872SJulie Hockett if (R[0] != BitCodeConstants::USRHashSize) 3018038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 3118038065SFangrui Song "incorrect USR size"); 32d0f9a872SJulie Hockett 33d0f9a872SJulie Hockett // First position in the record is the length of the following array, so we 34d0f9a872SJulie Hockett // copy the following elements to the field. 35d0f9a872SJulie Hockett for (int I = 0, E = R[0]; I < E; ++I) 36d0f9a872SJulie Hockett Field[I] = R[I + 1]; 3746fc9592SJulie Hockett return llvm::Error::success(); 38d0f9a872SJulie Hockett } 39d0f9a872SJulie Hockett 4045617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, bool &Field, llvm::StringRef Blob) { 41d0f9a872SJulie Hockett Field = R[0] != 0; 4246fc9592SJulie Hockett return llvm::Error::success(); 43d0f9a872SJulie Hockett } 44d0f9a872SJulie Hockett 4545617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, int &Field, llvm::StringRef Blob) { 46d0f9a872SJulie Hockett if (R[0] > INT_MAX) 4718038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 4818038065SFangrui Song "integer too large to parse"); 49d0f9a872SJulie Hockett Field = (int)R[0]; 5046fc9592SJulie Hockett return llvm::Error::success(); 51d0f9a872SJulie Hockett } 52d0f9a872SJulie Hockett 5345617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, AccessSpecifier &Field, 5446fc9592SJulie Hockett llvm::StringRef Blob) { 55d0f9a872SJulie Hockett switch (R[0]) { 56d0f9a872SJulie Hockett case AS_public: 57d0f9a872SJulie Hockett case AS_private: 58d0f9a872SJulie Hockett case AS_protected: 59d0f9a872SJulie Hockett case AS_none: 60d0f9a872SJulie Hockett Field = (AccessSpecifier)R[0]; 6146fc9592SJulie Hockett return llvm::Error::success(); 62d0f9a872SJulie Hockett default: 6318038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 6418038065SFangrui Song "invalid value for AccessSpecifier"); 65d0f9a872SJulie Hockett } 66d0f9a872SJulie Hockett } 67d0f9a872SJulie Hockett 6845617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, TagTypeKind &Field, 6945617e1dSSimon Pilgrim llvm::StringRef Blob) { 70edd690b0SVlad Serebrennikov switch (static_cast<TagTypeKind>(R[0])) { 71edd690b0SVlad Serebrennikov case TagTypeKind::Struct: 72edd690b0SVlad Serebrennikov case TagTypeKind::Interface: 73edd690b0SVlad Serebrennikov case TagTypeKind::Union: 74edd690b0SVlad Serebrennikov case TagTypeKind::Class: 75edd690b0SVlad Serebrennikov case TagTypeKind::Enum: 76edd690b0SVlad Serebrennikov Field = static_cast<TagTypeKind>(R[0]); 7746fc9592SJulie Hockett return llvm::Error::success(); 782b76bdc3SKazu Hirata } 7918038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 8018038065SFangrui Song "invalid value for TagTypeKind"); 81d0f9a872SJulie Hockett } 82d0f9a872SJulie Hockett 83c589730aSKrzysztof Parzyszek llvm::Error decodeRecord(const Record &R, std::optional<Location> &Field, 84d0f9a872SJulie Hockett llvm::StringRef Blob) { 85d0f9a872SJulie Hockett if (R[0] > INT_MAX) 8618038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 8718038065SFangrui Song "integer too large to parse"); 88665e9676SDiego Astiazaran Field.emplace((int)R[0], Blob, (bool)R[1]); 8946fc9592SJulie Hockett return llvm::Error::success(); 90d0f9a872SJulie Hockett } 91d0f9a872SJulie Hockett 9245617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, InfoType &Field, 9345617e1dSSimon Pilgrim llvm::StringRef Blob) { 94d0f9a872SJulie Hockett switch (auto IT = static_cast<InfoType>(R[0])) { 95d0f9a872SJulie Hockett case InfoType::IT_namespace: 96d0f9a872SJulie Hockett case InfoType::IT_record: 97d0f9a872SJulie Hockett case InfoType::IT_function: 98d0f9a872SJulie Hockett case InfoType::IT_default: 99d0f9a872SJulie Hockett case InfoType::IT_enum: 10021fb70c6SBrett Wilson case InfoType::IT_typedef: 101d0f9a872SJulie Hockett Field = IT; 10246fc9592SJulie Hockett return llvm::Error::success(); 103d0f9a872SJulie Hockett } 10418038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 10518038065SFangrui Song "invalid value for InfoType"); 106d0f9a872SJulie Hockett } 107d0f9a872SJulie Hockett 10845617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, FieldId &Field, 10945617e1dSSimon Pilgrim llvm::StringRef Blob) { 110d0f9a872SJulie Hockett switch (auto F = static_cast<FieldId>(R[0])) { 111d0f9a872SJulie Hockett case FieldId::F_namespace: 112d0f9a872SJulie Hockett case FieldId::F_parent: 113d0f9a872SJulie Hockett case FieldId::F_vparent: 114d0f9a872SJulie Hockett case FieldId::F_type: 1158899c29bSJulie Hockett case FieldId::F_child_namespace: 1168899c29bSJulie Hockett case FieldId::F_child_record: 117d0f9a872SJulie Hockett case FieldId::F_default: 118d0f9a872SJulie Hockett Field = F; 11946fc9592SJulie Hockett return llvm::Error::success(); 120d0f9a872SJulie Hockett } 12118038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 12218038065SFangrui Song "invalid value for FieldId"); 123d0f9a872SJulie Hockett } 124d0f9a872SJulie Hockett 12545617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, 12646fc9592SJulie Hockett llvm::SmallVectorImpl<llvm::SmallString<16>> &Field, 127d0f9a872SJulie Hockett llvm::StringRef Blob) { 128d0f9a872SJulie Hockett Field.push_back(Blob); 12946fc9592SJulie Hockett return llvm::Error::success(); 130d0f9a872SJulie Hockett } 131d0f9a872SJulie Hockett 13245617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, 13345617e1dSSimon Pilgrim llvm::SmallVectorImpl<Location> &Field, 134d0f9a872SJulie Hockett llvm::StringRef Blob) { 135d0f9a872SJulie Hockett if (R[0] > INT_MAX) 13618038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 13718038065SFangrui Song "integer too large to parse"); 138665e9676SDiego Astiazaran Field.emplace_back((int)R[0], Blob, (bool)R[1]); 13946fc9592SJulie Hockett return llvm::Error::success(); 140d0f9a872SJulie Hockett } 141d0f9a872SJulie Hockett 14245617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, 143d0f9a872SJulie Hockett const unsigned VersionNo) { 144d0f9a872SJulie Hockett if (ID == VERSION && R[0] == VersionNo) 14546fc9592SJulie Hockett return llvm::Error::success(); 14618038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 14718038065SFangrui Song "mismatched bitcode version number"); 148d0f9a872SJulie Hockett } 149d0f9a872SJulie Hockett 15045617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, 151d0f9a872SJulie Hockett NamespaceInfo *I) { 152d0f9a872SJulie Hockett switch (ID) { 153d0f9a872SJulie Hockett case NAMESPACE_USR: 154d0f9a872SJulie Hockett return decodeRecord(R, I->USR, Blob); 155d0f9a872SJulie Hockett case NAMESPACE_NAME: 156d0f9a872SJulie Hockett return decodeRecord(R, I->Name, Blob); 1572c1c9a24SJulie Hockett case NAMESPACE_PATH: 1582c1c9a24SJulie Hockett return decodeRecord(R, I->Path, Blob); 159d0f9a872SJulie Hockett default: 16018038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 16118038065SFangrui Song "invalid field for NamespaceInfo"); 162d0f9a872SJulie Hockett } 163d0f9a872SJulie Hockett } 164d0f9a872SJulie Hockett 16545617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, 16646fc9592SJulie Hockett RecordInfo *I) { 167d0f9a872SJulie Hockett switch (ID) { 168d0f9a872SJulie Hockett case RECORD_USR: 169d0f9a872SJulie Hockett return decodeRecord(R, I->USR, Blob); 170d0f9a872SJulie Hockett case RECORD_NAME: 171d0f9a872SJulie Hockett return decodeRecord(R, I->Name, Blob); 1722c1c9a24SJulie Hockett case RECORD_PATH: 1732c1c9a24SJulie Hockett return decodeRecord(R, I->Path, Blob); 174d0f9a872SJulie Hockett case RECORD_DEFLOCATION: 175d0f9a872SJulie Hockett return decodeRecord(R, I->DefLoc, Blob); 176d0f9a872SJulie Hockett case RECORD_LOCATION: 177d0f9a872SJulie Hockett return decodeRecord(R, I->Loc, Blob); 178d0f9a872SJulie Hockett case RECORD_TAG_TYPE: 179d0f9a872SJulie Hockett return decodeRecord(R, I->TagType, Blob); 180b1f01e27SJulie Hockett case RECORD_IS_TYPE_DEF: 181b1f01e27SJulie Hockett return decodeRecord(R, I->IsTypeDef, Blob); 182d0f9a872SJulie Hockett default: 18318038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 18418038065SFangrui Song "invalid field for RecordInfo"); 185d0f9a872SJulie Hockett } 186d0f9a872SJulie Hockett } 187d0f9a872SJulie Hockett 18845617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, 189ba3d595fSDiego Astiazaran BaseRecordInfo *I) { 190ba3d595fSDiego Astiazaran switch (ID) { 191ba3d595fSDiego Astiazaran case BASE_RECORD_USR: 192ba3d595fSDiego Astiazaran return decodeRecord(R, I->USR, Blob); 193ba3d595fSDiego Astiazaran case BASE_RECORD_NAME: 194ba3d595fSDiego Astiazaran return decodeRecord(R, I->Name, Blob); 195ba3d595fSDiego Astiazaran case BASE_RECORD_PATH: 196ba3d595fSDiego Astiazaran return decodeRecord(R, I->Path, Blob); 197ba3d595fSDiego Astiazaran case BASE_RECORD_TAG_TYPE: 198ba3d595fSDiego Astiazaran return decodeRecord(R, I->TagType, Blob); 199ba3d595fSDiego Astiazaran case BASE_RECORD_IS_VIRTUAL: 200ba3d595fSDiego Astiazaran return decodeRecord(R, I->IsVirtual, Blob); 201ba3d595fSDiego Astiazaran case BASE_RECORD_ACCESS: 202ba3d595fSDiego Astiazaran return decodeRecord(R, I->Access, Blob); 203ba3d595fSDiego Astiazaran case BASE_RECORD_IS_PARENT: 204ba3d595fSDiego Astiazaran return decodeRecord(R, I->IsParent, Blob); 205ba3d595fSDiego Astiazaran default: 20618038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 20718038065SFangrui Song "invalid field for BaseRecordInfo"); 208ba3d595fSDiego Astiazaran } 209ba3d595fSDiego Astiazaran } 210ba3d595fSDiego Astiazaran 21145617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, 21246fc9592SJulie Hockett EnumInfo *I) { 213d0f9a872SJulie Hockett switch (ID) { 214d0f9a872SJulie Hockett case ENUM_USR: 215d0f9a872SJulie Hockett return decodeRecord(R, I->USR, Blob); 216d0f9a872SJulie Hockett case ENUM_NAME: 217d0f9a872SJulie Hockett return decodeRecord(R, I->Name, Blob); 218d0f9a872SJulie Hockett case ENUM_DEFLOCATION: 219d0f9a872SJulie Hockett return decodeRecord(R, I->DefLoc, Blob); 220d0f9a872SJulie Hockett case ENUM_LOCATION: 221d0f9a872SJulie Hockett return decodeRecord(R, I->Loc, Blob); 222d0f9a872SJulie Hockett case ENUM_SCOPED: 223d0f9a872SJulie Hockett return decodeRecord(R, I->Scoped, Blob); 224d0f9a872SJulie Hockett default: 22518038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 22618038065SFangrui Song "invalid field for EnumInfo"); 227d0f9a872SJulie Hockett } 228d0f9a872SJulie Hockett } 229d0f9a872SJulie Hockett 23045617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, 23121fb70c6SBrett Wilson TypedefInfo *I) { 23221fb70c6SBrett Wilson switch (ID) { 23321fb70c6SBrett Wilson case TYPEDEF_USR: 23421fb70c6SBrett Wilson return decodeRecord(R, I->USR, Blob); 23521fb70c6SBrett Wilson case TYPEDEF_NAME: 23621fb70c6SBrett Wilson return decodeRecord(R, I->Name, Blob); 23721fb70c6SBrett Wilson case TYPEDEF_DEFLOCATION: 23821fb70c6SBrett Wilson return decodeRecord(R, I->DefLoc, Blob); 23921fb70c6SBrett Wilson case TYPEDEF_IS_USING: 24021fb70c6SBrett Wilson return decodeRecord(R, I->IsUsing, Blob); 24121fb70c6SBrett Wilson default: 24221fb70c6SBrett Wilson return llvm::createStringError(llvm::inconvertibleErrorCode(), 24321fb70c6SBrett Wilson "invalid field for TypedefInfo"); 24421fb70c6SBrett Wilson } 24521fb70c6SBrett Wilson } 24621fb70c6SBrett Wilson 24721fb70c6SBrett Wilson llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, 248eaa7b324SBrett Wilson EnumValueInfo *I) { 249eaa7b324SBrett Wilson switch (ID) { 250eaa7b324SBrett Wilson case ENUM_VALUE_NAME: 251eaa7b324SBrett Wilson return decodeRecord(R, I->Name, Blob); 252eaa7b324SBrett Wilson case ENUM_VALUE_VALUE: 253eaa7b324SBrett Wilson return decodeRecord(R, I->Value, Blob); 254eaa7b324SBrett Wilson case ENUM_VALUE_EXPR: 255eaa7b324SBrett Wilson return decodeRecord(R, I->ValueExpr, Blob); 256eaa7b324SBrett Wilson default: 257eaa7b324SBrett Wilson return llvm::createStringError(llvm::inconvertibleErrorCode(), 258eaa7b324SBrett Wilson "invalid field for EnumValueInfo"); 259eaa7b324SBrett Wilson } 260eaa7b324SBrett Wilson } 261eaa7b324SBrett Wilson 262eaa7b324SBrett Wilson llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, 26346fc9592SJulie Hockett FunctionInfo *I) { 264d0f9a872SJulie Hockett switch (ID) { 265d0f9a872SJulie Hockett case FUNCTION_USR: 266d0f9a872SJulie Hockett return decodeRecord(R, I->USR, Blob); 267d0f9a872SJulie Hockett case FUNCTION_NAME: 268d0f9a872SJulie Hockett return decodeRecord(R, I->Name, Blob); 269d0f9a872SJulie Hockett case FUNCTION_DEFLOCATION: 270d0f9a872SJulie Hockett return decodeRecord(R, I->DefLoc, Blob); 271d0f9a872SJulie Hockett case FUNCTION_LOCATION: 272d0f9a872SJulie Hockett return decodeRecord(R, I->Loc, Blob); 273d0f9a872SJulie Hockett case FUNCTION_ACCESS: 274d0f9a872SJulie Hockett return decodeRecord(R, I->Access, Blob); 275d0f9a872SJulie Hockett case FUNCTION_IS_METHOD: 276d0f9a872SJulie Hockett return decodeRecord(R, I->IsMethod, Blob); 277d0f9a872SJulie Hockett default: 27818038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 27918038065SFangrui Song "invalid field for FunctionInfo"); 280d0f9a872SJulie Hockett } 281d0f9a872SJulie Hockett } 282d0f9a872SJulie Hockett 28345617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, 28446fc9592SJulie Hockett TypeInfo *I) { 28546fc9592SJulie Hockett return llvm::Error::success(); 286d0f9a872SJulie Hockett } 287d0f9a872SJulie Hockett 28845617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, 289d0f9a872SJulie Hockett FieldTypeInfo *I) { 290d0f9a872SJulie Hockett switch (ID) { 291d0f9a872SJulie Hockett case FIELD_TYPE_NAME: 292d0f9a872SJulie Hockett return decodeRecord(R, I->Name, Blob); 293e191086bSBrett Wilson case FIELD_DEFAULT_VALUE: 294e191086bSBrett Wilson return decodeRecord(R, I->DefaultValue, Blob); 295d0f9a872SJulie Hockett default: 29618038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 29718038065SFangrui Song "invalid field for TypeInfo"); 298d0f9a872SJulie Hockett } 299d0f9a872SJulie Hockett } 300d0f9a872SJulie Hockett 30145617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, 302d0f9a872SJulie Hockett MemberTypeInfo *I) { 303d0f9a872SJulie Hockett switch (ID) { 304d0f9a872SJulie Hockett case MEMBER_TYPE_NAME: 305d0f9a872SJulie Hockett return decodeRecord(R, I->Name, Blob); 306d0f9a872SJulie Hockett case MEMBER_TYPE_ACCESS: 307d0f9a872SJulie Hockett return decodeRecord(R, I->Access, Blob); 308d0f9a872SJulie Hockett default: 30918038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 31018038065SFangrui Song "invalid field for MemberTypeInfo"); 311d0f9a872SJulie Hockett } 312d0f9a872SJulie Hockett } 313d0f9a872SJulie Hockett 31445617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, 31546fc9592SJulie Hockett CommentInfo *I) { 316d0f9a872SJulie Hockett switch (ID) { 317d0f9a872SJulie Hockett case COMMENT_KIND: 318d0f9a872SJulie Hockett return decodeRecord(R, I->Kind, Blob); 319d0f9a872SJulie Hockett case COMMENT_TEXT: 320d0f9a872SJulie Hockett return decodeRecord(R, I->Text, Blob); 321d0f9a872SJulie Hockett case COMMENT_NAME: 322d0f9a872SJulie Hockett return decodeRecord(R, I->Name, Blob); 323d0f9a872SJulie Hockett case COMMENT_DIRECTION: 324d0f9a872SJulie Hockett return decodeRecord(R, I->Direction, Blob); 325d0f9a872SJulie Hockett case COMMENT_PARAMNAME: 326d0f9a872SJulie Hockett return decodeRecord(R, I->ParamName, Blob); 327d0f9a872SJulie Hockett case COMMENT_CLOSENAME: 328d0f9a872SJulie Hockett return decodeRecord(R, I->CloseName, Blob); 329d0f9a872SJulie Hockett case COMMENT_ATTRKEY: 330d0f9a872SJulie Hockett return decodeRecord(R, I->AttrKeys, Blob); 331d0f9a872SJulie Hockett case COMMENT_ATTRVAL: 332d0f9a872SJulie Hockett return decodeRecord(R, I->AttrValues, Blob); 333d0f9a872SJulie Hockett case COMMENT_ARG: 334d0f9a872SJulie Hockett return decodeRecord(R, I->Args, Blob); 335d0f9a872SJulie Hockett case COMMENT_SELFCLOSING: 336d0f9a872SJulie Hockett return decodeRecord(R, I->SelfClosing, Blob); 337d0f9a872SJulie Hockett case COMMENT_EXPLICIT: 338d0f9a872SJulie Hockett return decodeRecord(R, I->Explicit, Blob); 339d0f9a872SJulie Hockett default: 34018038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 34118038065SFangrui Song "invalid field for CommentInfo"); 342d0f9a872SJulie Hockett } 343d0f9a872SJulie Hockett } 344d0f9a872SJulie Hockett 34545617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, 34646fc9592SJulie Hockett Reference *I, FieldId &F) { 347d0f9a872SJulie Hockett switch (ID) { 348d0f9a872SJulie Hockett case REFERENCE_USR: 349d0f9a872SJulie Hockett return decodeRecord(R, I->USR, Blob); 350d0f9a872SJulie Hockett case REFERENCE_NAME: 351d0f9a872SJulie Hockett return decodeRecord(R, I->Name, Blob); 3524a68babdSBrett Wilson case REFERENCE_QUAL_NAME: 3534a68babdSBrett Wilson return decodeRecord(R, I->QualName, Blob); 354d0f9a872SJulie Hockett case REFERENCE_TYPE: 355d0f9a872SJulie Hockett return decodeRecord(R, I->RefType, Blob); 3562c1c9a24SJulie Hockett case REFERENCE_PATH: 3572c1c9a24SJulie Hockett return decodeRecord(R, I->Path, Blob); 358d0f9a872SJulie Hockett case REFERENCE_FIELD: 359d0f9a872SJulie Hockett return decodeRecord(R, F, Blob); 360d0f9a872SJulie Hockett default: 36118038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 36218038065SFangrui Song "invalid field for Reference"); 363d0f9a872SJulie Hockett } 364d0f9a872SJulie Hockett } 365d0f9a872SJulie Hockett 3664a68babdSBrett Wilson llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, 3674a68babdSBrett Wilson TemplateInfo *I) { 3684a68babdSBrett Wilson // Currently there are no child records of TemplateInfo (only child blocks). 3694a68babdSBrett Wilson return llvm::createStringError(llvm::inconvertibleErrorCode(), 3704a68babdSBrett Wilson "invalid field for TemplateParamInfo"); 3714a68babdSBrett Wilson } 3724a68babdSBrett Wilson 3734a68babdSBrett Wilson llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, 3744a68babdSBrett Wilson TemplateSpecializationInfo *I) { 3754a68babdSBrett Wilson if (ID == TEMPLATE_SPECIALIZATION_OF) 3764a68babdSBrett Wilson return decodeRecord(R, I->SpecializationOf, Blob); 3774a68babdSBrett Wilson return llvm::createStringError(llvm::inconvertibleErrorCode(), 3784a68babdSBrett Wilson "invalid field for TemplateParamInfo"); 3794a68babdSBrett Wilson } 3804a68babdSBrett Wilson 3814a68babdSBrett Wilson llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, 3824a68babdSBrett Wilson TemplateParamInfo *I) { 3834a68babdSBrett Wilson if (ID == TEMPLATE_PARAM_CONTENTS) 3844a68babdSBrett Wilson return decodeRecord(R, I->Contents, Blob); 3854a68babdSBrett Wilson return llvm::createStringError(llvm::inconvertibleErrorCode(), 3864a68babdSBrett Wilson "invalid field for TemplateParamInfo"); 3874a68babdSBrett Wilson } 3884a68babdSBrett Wilson 38946fc9592SJulie Hockett template <typename T> llvm::Expected<CommentInfo *> getCommentInfo(T I) { 39018038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 39118038065SFangrui Song "invalid type cannot contain CommentInfo"); 392d0f9a872SJulie Hockett } 393d0f9a872SJulie Hockett 39446fc9592SJulie Hockett template <> llvm::Expected<CommentInfo *> getCommentInfo(FunctionInfo *I) { 3957231c996SBrett Wilson return &I->Description.emplace_back(); 396d0f9a872SJulie Hockett } 397d0f9a872SJulie Hockett 39846fc9592SJulie Hockett template <> llvm::Expected<CommentInfo *> getCommentInfo(NamespaceInfo *I) { 3997231c996SBrett Wilson return &I->Description.emplace_back(); 400d0f9a872SJulie Hockett } 401d0f9a872SJulie Hockett 40246fc9592SJulie Hockett template <> llvm::Expected<CommentInfo *> getCommentInfo(RecordInfo *I) { 4037231c996SBrett Wilson return &I->Description.emplace_back(); 404d0f9a872SJulie Hockett } 405d0f9a872SJulie Hockett 40699baa10fSBrett Wilson template <> llvm::Expected<CommentInfo *> getCommentInfo(MemberTypeInfo *I) { 4077231c996SBrett Wilson return &I->Description.emplace_back(); 40899baa10fSBrett Wilson } 40999baa10fSBrett Wilson 41046fc9592SJulie Hockett template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumInfo *I) { 4117231c996SBrett Wilson return &I->Description.emplace_back(); 4127231c996SBrett Wilson } 4137231c996SBrett Wilson 4147231c996SBrett Wilson template <> llvm::Expected<CommentInfo *> getCommentInfo(TypedefInfo *I) { 4157231c996SBrett Wilson return &I->Description.emplace_back(); 416d0f9a872SJulie Hockett } 417d0f9a872SJulie Hockett 418*5ef2456aSPeterChou1 template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumValueInfo *I) { 419*5ef2456aSPeterChou1 return &I->Description.emplace_back(); 420*5ef2456aSPeterChou1 } 421*5ef2456aSPeterChou1 42246fc9592SJulie Hockett template <> llvm::Expected<CommentInfo *> getCommentInfo(CommentInfo *I) { 4231c705d9cSJonas Devlieghere I->Children.emplace_back(std::make_unique<CommentInfo>()); 424d0f9a872SJulie Hockett return I->Children.back().get(); 425d0f9a872SJulie Hockett } 426d0f9a872SJulie Hockett 42746fc9592SJulie Hockett template <> 42846fc9592SJulie Hockett llvm::Expected<CommentInfo *> getCommentInfo(std::unique_ptr<CommentInfo> &I) { 429d0f9a872SJulie Hockett return getCommentInfo(I.get()); 430d0f9a872SJulie Hockett } 431d0f9a872SJulie Hockett 432eaa7b324SBrett Wilson // When readSubBlock encounters a TypeInfo sub-block, it calls addTypeInfo on 433eaa7b324SBrett Wilson // the parent block to set it. The template specializations define what to do 434eaa7b324SBrett Wilson // for each supported parent block. 435d0f9a872SJulie Hockett template <typename T, typename TTypeInfo> 43646fc9592SJulie Hockett llvm::Error addTypeInfo(T I, TTypeInfo &&TI) { 43718038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 43818038065SFangrui Song "invalid type cannot contain TypeInfo"); 439d0f9a872SJulie Hockett } 440d0f9a872SJulie Hockett 44146fc9592SJulie Hockett template <> llvm::Error addTypeInfo(RecordInfo *I, MemberTypeInfo &&T) { 442d0f9a872SJulie Hockett I->Members.emplace_back(std::move(T)); 44346fc9592SJulie Hockett return llvm::Error::success(); 444d0f9a872SJulie Hockett } 445d0f9a872SJulie Hockett 446ba3d595fSDiego Astiazaran template <> llvm::Error addTypeInfo(BaseRecordInfo *I, MemberTypeInfo &&T) { 447ba3d595fSDiego Astiazaran I->Members.emplace_back(std::move(T)); 448ba3d595fSDiego Astiazaran return llvm::Error::success(); 449ba3d595fSDiego Astiazaran } 450ba3d595fSDiego Astiazaran 45146fc9592SJulie Hockett template <> llvm::Error addTypeInfo(FunctionInfo *I, TypeInfo &&T) { 452d0f9a872SJulie Hockett I->ReturnType = std::move(T); 45346fc9592SJulie Hockett return llvm::Error::success(); 454d0f9a872SJulie Hockett } 455d0f9a872SJulie Hockett 45646fc9592SJulie Hockett template <> llvm::Error addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) { 457d0f9a872SJulie Hockett I->Params.emplace_back(std::move(T)); 45846fc9592SJulie Hockett return llvm::Error::success(); 459d0f9a872SJulie Hockett } 460d0f9a872SJulie Hockett 461eaa7b324SBrett Wilson template <> llvm::Error addTypeInfo(EnumInfo *I, TypeInfo &&T) { 462eaa7b324SBrett Wilson I->BaseType = std::move(T); 463eaa7b324SBrett Wilson return llvm::Error::success(); 464eaa7b324SBrett Wilson } 465eaa7b324SBrett Wilson 46621fb70c6SBrett Wilson template <> llvm::Error addTypeInfo(TypedefInfo *I, TypeInfo &&T) { 46721fb70c6SBrett Wilson I->Underlying = std::move(T); 46821fb70c6SBrett Wilson return llvm::Error::success(); 46921fb70c6SBrett Wilson } 47021fb70c6SBrett Wilson 47146fc9592SJulie Hockett template <typename T> llvm::Error addReference(T I, Reference &&R, FieldId F) { 47218038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 47318038065SFangrui Song "invalid type cannot contain Reference"); 474d0f9a872SJulie Hockett } 475d0f9a872SJulie Hockett 47646fc9592SJulie Hockett template <> llvm::Error addReference(TypeInfo *I, Reference &&R, FieldId F) { 477d0f9a872SJulie Hockett switch (F) { 478d0f9a872SJulie Hockett case FieldId::F_type: 479d0f9a872SJulie Hockett I->Type = std::move(R); 48046fc9592SJulie Hockett return llvm::Error::success(); 481d0f9a872SJulie Hockett default: 48218038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 48318038065SFangrui Song "invalid type cannot contain Reference"); 484d0f9a872SJulie Hockett } 485d0f9a872SJulie Hockett } 486d0f9a872SJulie Hockett 48746fc9592SJulie Hockett template <> 48846fc9592SJulie Hockett llvm::Error addReference(FieldTypeInfo *I, Reference &&R, FieldId F) { 489d0f9a872SJulie Hockett switch (F) { 490d0f9a872SJulie Hockett case FieldId::F_type: 491d0f9a872SJulie Hockett I->Type = std::move(R); 49246fc9592SJulie Hockett return llvm::Error::success(); 493d0f9a872SJulie Hockett default: 49418038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 49518038065SFangrui Song "invalid type cannot contain Reference"); 496d0f9a872SJulie Hockett } 497d0f9a872SJulie Hockett } 498d0f9a872SJulie Hockett 49946fc9592SJulie Hockett template <> 50046fc9592SJulie Hockett llvm::Error addReference(MemberTypeInfo *I, Reference &&R, FieldId F) { 501d0f9a872SJulie Hockett switch (F) { 502d0f9a872SJulie Hockett case FieldId::F_type: 503d0f9a872SJulie Hockett I->Type = std::move(R); 50446fc9592SJulie Hockett return llvm::Error::success(); 505d0f9a872SJulie Hockett default: 50618038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 50718038065SFangrui Song "invalid type cannot contain Reference"); 508d0f9a872SJulie Hockett } 509d0f9a872SJulie Hockett } 510d0f9a872SJulie Hockett 51146fc9592SJulie Hockett template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F) { 512d0f9a872SJulie Hockett switch (F) { 513d0f9a872SJulie Hockett case FieldId::F_namespace: 514d0f9a872SJulie Hockett I->Namespace.emplace_back(std::move(R)); 51546fc9592SJulie Hockett return llvm::Error::success(); 516d0f9a872SJulie Hockett default: 51718038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 51818038065SFangrui Song "invalid type cannot contain Reference"); 519d0f9a872SJulie Hockett } 520d0f9a872SJulie Hockett } 521d0f9a872SJulie Hockett 52221fb70c6SBrett Wilson template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F) { 52321fb70c6SBrett Wilson switch (F) { 52421fb70c6SBrett Wilson case FieldId::F_namespace: 52521fb70c6SBrett Wilson I->Namespace.emplace_back(std::move(R)); 52621fb70c6SBrett Wilson return llvm::Error::success(); 52721fb70c6SBrett Wilson default: 52821fb70c6SBrett Wilson return llvm::createStringError(llvm::inconvertibleErrorCode(), 52921fb70c6SBrett Wilson "invalid type cannot contain Reference"); 53021fb70c6SBrett Wilson } 53121fb70c6SBrett Wilson } 53221fb70c6SBrett Wilson 53346fc9592SJulie Hockett template <> 53446fc9592SJulie Hockett llvm::Error addReference(NamespaceInfo *I, Reference &&R, FieldId F) { 535d0f9a872SJulie Hockett switch (F) { 536d0f9a872SJulie Hockett case FieldId::F_namespace: 537d0f9a872SJulie Hockett I->Namespace.emplace_back(std::move(R)); 53846fc9592SJulie Hockett return llvm::Error::success(); 5398899c29bSJulie Hockett case FieldId::F_child_namespace: 54021fb70c6SBrett Wilson I->Children.Namespaces.emplace_back(std::move(R)); 54146fc9592SJulie Hockett return llvm::Error::success(); 5428899c29bSJulie Hockett case FieldId::F_child_record: 54321fb70c6SBrett Wilson I->Children.Records.emplace_back(std::move(R)); 54446fc9592SJulie Hockett return llvm::Error::success(); 545d0f9a872SJulie Hockett default: 54618038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 54718038065SFangrui Song "invalid type cannot contain Reference"); 548d0f9a872SJulie Hockett } 549d0f9a872SJulie Hockett } 550d0f9a872SJulie Hockett 55146fc9592SJulie Hockett template <> 55246fc9592SJulie Hockett llvm::Error addReference(FunctionInfo *I, Reference &&R, FieldId F) { 553d0f9a872SJulie Hockett switch (F) { 554d0f9a872SJulie Hockett case FieldId::F_namespace: 555d0f9a872SJulie Hockett I->Namespace.emplace_back(std::move(R)); 55646fc9592SJulie Hockett return llvm::Error::success(); 557d0f9a872SJulie Hockett case FieldId::F_parent: 558d0f9a872SJulie Hockett I->Parent = std::move(R); 55946fc9592SJulie Hockett return llvm::Error::success(); 560d0f9a872SJulie Hockett default: 56118038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 56218038065SFangrui Song "invalid type cannot contain Reference"); 563d0f9a872SJulie Hockett } 564d0f9a872SJulie Hockett } 565d0f9a872SJulie Hockett 56646fc9592SJulie Hockett template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) { 567d0f9a872SJulie Hockett switch (F) { 568d0f9a872SJulie Hockett case FieldId::F_namespace: 569d0f9a872SJulie Hockett I->Namespace.emplace_back(std::move(R)); 57046fc9592SJulie Hockett return llvm::Error::success(); 571d0f9a872SJulie Hockett case FieldId::F_parent: 572d0f9a872SJulie Hockett I->Parents.emplace_back(std::move(R)); 57346fc9592SJulie Hockett return llvm::Error::success(); 574d0f9a872SJulie Hockett case FieldId::F_vparent: 575d0f9a872SJulie Hockett I->VirtualParents.emplace_back(std::move(R)); 57646fc9592SJulie Hockett return llvm::Error::success(); 5778899c29bSJulie Hockett case FieldId::F_child_record: 57821fb70c6SBrett Wilson I->Children.Records.emplace_back(std::move(R)); 57946fc9592SJulie Hockett return llvm::Error::success(); 580d0f9a872SJulie Hockett default: 58118038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 58218038065SFangrui Song "invalid type cannot contain Reference"); 583d0f9a872SJulie Hockett } 584d0f9a872SJulie Hockett } 585d0f9a872SJulie Hockett 5868899c29bSJulie Hockett template <typename T, typename ChildInfoType> 5878899c29bSJulie Hockett void addChild(T I, ChildInfoType &&R) { 58818038065SFangrui Song llvm::errs() << "invalid child type for info"; 5898899c29bSJulie Hockett exit(1); 5908899c29bSJulie Hockett } 5918899c29bSJulie Hockett 59221fb70c6SBrett Wilson // Namespace children: 5938899c29bSJulie Hockett template <> void addChild(NamespaceInfo *I, FunctionInfo &&R) { 59421fb70c6SBrett Wilson I->Children.Functions.emplace_back(std::move(R)); 5958899c29bSJulie Hockett } 5968899c29bSJulie Hockett template <> void addChild(NamespaceInfo *I, EnumInfo &&R) { 59721fb70c6SBrett Wilson I->Children.Enums.emplace_back(std::move(R)); 59821fb70c6SBrett Wilson } 59921fb70c6SBrett Wilson template <> void addChild(NamespaceInfo *I, TypedefInfo &&R) { 60021fb70c6SBrett Wilson I->Children.Typedefs.emplace_back(std::move(R)); 6018899c29bSJulie Hockett } 6028899c29bSJulie Hockett 60321fb70c6SBrett Wilson // Record children: 6048899c29bSJulie Hockett template <> void addChild(RecordInfo *I, FunctionInfo &&R) { 60521fb70c6SBrett Wilson I->Children.Functions.emplace_back(std::move(R)); 6068899c29bSJulie Hockett } 607a7594772SHaowei Wu template <> void addChild(RecordInfo *I, EnumInfo &&R) { 60821fb70c6SBrett Wilson I->Children.Enums.emplace_back(std::move(R)); 60921fb70c6SBrett Wilson } 61021fb70c6SBrett Wilson template <> void addChild(RecordInfo *I, TypedefInfo &&R) { 61121fb70c6SBrett Wilson I->Children.Typedefs.emplace_back(std::move(R)); 612a7594772SHaowei Wu } 613a7594772SHaowei Wu 61421fb70c6SBrett Wilson // Other types of children: 615eaa7b324SBrett Wilson template <> void addChild(EnumInfo *I, EnumValueInfo &&R) { 616eaa7b324SBrett Wilson I->Members.emplace_back(std::move(R)); 617eaa7b324SBrett Wilson } 618ba3d595fSDiego Astiazaran template <> void addChild(RecordInfo *I, BaseRecordInfo &&R) { 619ba3d595fSDiego Astiazaran I->Bases.emplace_back(std::move(R)); 620ba3d595fSDiego Astiazaran } 621ba3d595fSDiego Astiazaran template <> void addChild(BaseRecordInfo *I, FunctionInfo &&R) { 62221fb70c6SBrett Wilson I->Children.Functions.emplace_back(std::move(R)); 623ba3d595fSDiego Astiazaran } 624ba3d595fSDiego Astiazaran 6254a68babdSBrett Wilson // TemplateParam children. These go into either a TemplateInfo (for template 6264a68babdSBrett Wilson // parameters) or TemplateSpecializationInfo (for the specialization's 6274a68babdSBrett Wilson // parameters). 6284a68babdSBrett Wilson template <typename T> void addTemplateParam(T I, TemplateParamInfo &&P) { 6294a68babdSBrett Wilson llvm::errs() << "invalid container for template parameter"; 6304a68babdSBrett Wilson exit(1); 6314a68babdSBrett Wilson } 6324a68babdSBrett Wilson template <> void addTemplateParam(TemplateInfo *I, TemplateParamInfo &&P) { 6334a68babdSBrett Wilson I->Params.emplace_back(std::move(P)); 6344a68babdSBrett Wilson } 6354a68babdSBrett Wilson template <> 6364a68babdSBrett Wilson void addTemplateParam(TemplateSpecializationInfo *I, TemplateParamInfo &&P) { 6374a68babdSBrett Wilson I->Params.emplace_back(std::move(P)); 6384a68babdSBrett Wilson } 6394a68babdSBrett Wilson 6404a68babdSBrett Wilson // Template info. These apply to either records or functions. 6414a68babdSBrett Wilson template <typename T> void addTemplate(T I, TemplateInfo &&P) { 6424a68babdSBrett Wilson llvm::errs() << "invalid container for template info"; 6434a68babdSBrett Wilson exit(1); 6444a68babdSBrett Wilson } 6454a68babdSBrett Wilson template <> void addTemplate(RecordInfo *I, TemplateInfo &&P) { 6464a68babdSBrett Wilson I->Template.emplace(std::move(P)); 6474a68babdSBrett Wilson } 6484a68babdSBrett Wilson template <> void addTemplate(FunctionInfo *I, TemplateInfo &&P) { 6494a68babdSBrett Wilson I->Template.emplace(std::move(P)); 6504a68babdSBrett Wilson } 6514a68babdSBrett Wilson 6524a68babdSBrett Wilson // Template specializations go only into template records. 6534a68babdSBrett Wilson template <typename T> 6544a68babdSBrett Wilson void addTemplateSpecialization(T I, TemplateSpecializationInfo &&TSI) { 6554a68babdSBrett Wilson llvm::errs() << "invalid container for template specialization info"; 6564a68babdSBrett Wilson exit(1); 6574a68babdSBrett Wilson } 6584a68babdSBrett Wilson template <> 6594a68babdSBrett Wilson void addTemplateSpecialization(TemplateInfo *I, 6604a68babdSBrett Wilson TemplateSpecializationInfo &&TSI) { 6614a68babdSBrett Wilson I->Specialization.emplace(std::move(TSI)); 6624a68babdSBrett Wilson } 6634a68babdSBrett Wilson 664d0f9a872SJulie Hockett // Read records from bitcode into a given info. 66546fc9592SJulie Hockett template <typename T> 66646fc9592SJulie Hockett llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, T I) { 667d0f9a872SJulie Hockett Record R; 668d0f9a872SJulie Hockett llvm::StringRef Blob; 6690e828958SJF Bastien llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob); 6700e828958SJF Bastien if (!MaybeRecID) 6710e828958SJF Bastien return MaybeRecID.takeError(); 6720e828958SJF Bastien return parseRecord(R, MaybeRecID.get(), Blob, I); 673d0f9a872SJulie Hockett } 674d0f9a872SJulie Hockett 67546fc9592SJulie Hockett template <> 67646fc9592SJulie Hockett llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) { 677d0f9a872SJulie Hockett Record R; 678d0f9a872SJulie Hockett llvm::StringRef Blob; 6790e828958SJF Bastien llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob); 6800e828958SJF Bastien if (!MaybeRecID) 6810e828958SJF Bastien return MaybeRecID.takeError(); 6820e828958SJF Bastien return parseRecord(R, MaybeRecID.get(), Blob, I, CurrentReferenceField); 683d0f9a872SJulie Hockett } 684d0f9a872SJulie Hockett 685d0f9a872SJulie Hockett // Read a block of records into a single info. 68646fc9592SJulie Hockett template <typename T> 68746fc9592SJulie Hockett llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) { 6880e828958SJF Bastien if (llvm::Error Err = Stream.EnterSubBlock(ID)) 6890e828958SJF Bastien return Err; 690d0f9a872SJulie Hockett 691d0f9a872SJulie Hockett while (true) { 692d0f9a872SJulie Hockett unsigned BlockOrCode = 0; 693d0f9a872SJulie Hockett Cursor Res = skipUntilRecordOrBlock(BlockOrCode); 694d0f9a872SJulie Hockett 695d0f9a872SJulie Hockett switch (Res) { 696d0f9a872SJulie Hockett case Cursor::BadBlock: 69718038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 69818038065SFangrui Song "bad block found"); 699d0f9a872SJulie Hockett case Cursor::BlockEnd: 70046fc9592SJulie Hockett return llvm::Error::success(); 701d0f9a872SJulie Hockett case Cursor::BlockBegin: 7020e828958SJF Bastien if (llvm::Error Err = readSubBlock(BlockOrCode, I)) { 7030e828958SJF Bastien if (llvm::Error Skipped = Stream.SkipBlock()) 7040e828958SJF Bastien return joinErrors(std::move(Err), std::move(Skipped)); 70546fc9592SJulie Hockett return Err; 70646fc9592SJulie Hockett } 707d0f9a872SJulie Hockett continue; 708d0f9a872SJulie Hockett case Cursor::Record: 709d0f9a872SJulie Hockett break; 710d0f9a872SJulie Hockett } 71146fc9592SJulie Hockett if (auto Err = readRecord(BlockOrCode, I)) 71246fc9592SJulie Hockett return Err; 713d0f9a872SJulie Hockett } 714d0f9a872SJulie Hockett } 715d0f9a872SJulie Hockett 716d0f9a872SJulie Hockett template <typename T> 71746fc9592SJulie Hockett llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) { 718d0f9a872SJulie Hockett switch (ID) { 719eaa7b324SBrett Wilson // Blocks can only have certain types of sub blocks. 72046fc9592SJulie Hockett case BI_COMMENT_BLOCK_ID: { 72146fc9592SJulie Hockett auto Comment = getCommentInfo(I); 72246fc9592SJulie Hockett if (!Comment) 72346fc9592SJulie Hockett return Comment.takeError(); 72446fc9592SJulie Hockett if (auto Err = readBlock(ID, Comment.get())) 72546fc9592SJulie Hockett return Err; 72646fc9592SJulie Hockett return llvm::Error::success(); 72746fc9592SJulie Hockett } 728d0f9a872SJulie Hockett case BI_TYPE_BLOCK_ID: { 729d0f9a872SJulie Hockett TypeInfo TI; 73046fc9592SJulie Hockett if (auto Err = readBlock(ID, &TI)) 73146fc9592SJulie Hockett return Err; 73246fc9592SJulie Hockett if (auto Err = addTypeInfo(I, std::move(TI))) 73346fc9592SJulie Hockett return Err; 73446fc9592SJulie Hockett return llvm::Error::success(); 735d0f9a872SJulie Hockett } 736d0f9a872SJulie Hockett case BI_FIELD_TYPE_BLOCK_ID: { 737d0f9a872SJulie Hockett FieldTypeInfo TI; 73846fc9592SJulie Hockett if (auto Err = readBlock(ID, &TI)) 73946fc9592SJulie Hockett return Err; 74046fc9592SJulie Hockett if (auto Err = addTypeInfo(I, std::move(TI))) 74146fc9592SJulie Hockett return Err; 74246fc9592SJulie Hockett return llvm::Error::success(); 743d0f9a872SJulie Hockett } 744d0f9a872SJulie Hockett case BI_MEMBER_TYPE_BLOCK_ID: { 745d0f9a872SJulie Hockett MemberTypeInfo TI; 74646fc9592SJulie Hockett if (auto Err = readBlock(ID, &TI)) 74746fc9592SJulie Hockett return Err; 74846fc9592SJulie Hockett if (auto Err = addTypeInfo(I, std::move(TI))) 74946fc9592SJulie Hockett return Err; 75046fc9592SJulie Hockett return llvm::Error::success(); 751d0f9a872SJulie Hockett } 752d0f9a872SJulie Hockett case BI_REFERENCE_BLOCK_ID: { 753d0f9a872SJulie Hockett Reference R; 75446fc9592SJulie Hockett if (auto Err = readBlock(ID, &R)) 75546fc9592SJulie Hockett return Err; 75646fc9592SJulie Hockett if (auto Err = addReference(I, std::move(R), CurrentReferenceField)) 75746fc9592SJulie Hockett return Err; 75846fc9592SJulie Hockett return llvm::Error::success(); 759d0f9a872SJulie Hockett } 7608899c29bSJulie Hockett case BI_FUNCTION_BLOCK_ID: { 7618899c29bSJulie Hockett FunctionInfo F; 76246fc9592SJulie Hockett if (auto Err = readBlock(ID, &F)) 76346fc9592SJulie Hockett return Err; 7648899c29bSJulie Hockett addChild(I, std::move(F)); 76546fc9592SJulie Hockett return llvm::Error::success(); 7668899c29bSJulie Hockett } 767ba3d595fSDiego Astiazaran case BI_BASE_RECORD_BLOCK_ID: { 768ba3d595fSDiego Astiazaran BaseRecordInfo BR; 769ba3d595fSDiego Astiazaran if (auto Err = readBlock(ID, &BR)) 770ba3d595fSDiego Astiazaran return Err; 771ba3d595fSDiego Astiazaran addChild(I, std::move(BR)); 772ba3d595fSDiego Astiazaran return llvm::Error::success(); 773ba3d595fSDiego Astiazaran } 7748899c29bSJulie Hockett case BI_ENUM_BLOCK_ID: { 7758899c29bSJulie Hockett EnumInfo E; 77646fc9592SJulie Hockett if (auto Err = readBlock(ID, &E)) 77746fc9592SJulie Hockett return Err; 7788899c29bSJulie Hockett addChild(I, std::move(E)); 77946fc9592SJulie Hockett return llvm::Error::success(); 7808899c29bSJulie Hockett } 781eaa7b324SBrett Wilson case BI_ENUM_VALUE_BLOCK_ID: { 782eaa7b324SBrett Wilson EnumValueInfo EV; 783eaa7b324SBrett Wilson if (auto Err = readBlock(ID, &EV)) 784eaa7b324SBrett Wilson return Err; 785eaa7b324SBrett Wilson addChild(I, std::move(EV)); 786eaa7b324SBrett Wilson return llvm::Error::success(); 787eaa7b324SBrett Wilson } 7884a68babdSBrett Wilson case BI_TEMPLATE_BLOCK_ID: { 7894a68babdSBrett Wilson TemplateInfo TI; 7904a68babdSBrett Wilson if (auto Err = readBlock(ID, &TI)) 7914a68babdSBrett Wilson return Err; 7924a68babdSBrett Wilson addTemplate(I, std::move(TI)); 7934a68babdSBrett Wilson return llvm::Error::success(); 7944a68babdSBrett Wilson } 7954a68babdSBrett Wilson case BI_TEMPLATE_SPECIALIZATION_BLOCK_ID: { 7964a68babdSBrett Wilson TemplateSpecializationInfo TSI; 7974a68babdSBrett Wilson if (auto Err = readBlock(ID, &TSI)) 7984a68babdSBrett Wilson return Err; 7994a68babdSBrett Wilson addTemplateSpecialization(I, std::move(TSI)); 8004a68babdSBrett Wilson return llvm::Error::success(); 8014a68babdSBrett Wilson } 8024a68babdSBrett Wilson case BI_TEMPLATE_PARAM_BLOCK_ID: { 8034a68babdSBrett Wilson TemplateParamInfo TPI; 8044a68babdSBrett Wilson if (auto Err = readBlock(ID, &TPI)) 8054a68babdSBrett Wilson return Err; 8064a68babdSBrett Wilson addTemplateParam(I, std::move(TPI)); 8074a68babdSBrett Wilson return llvm::Error::success(); 8084a68babdSBrett Wilson } 80921fb70c6SBrett Wilson case BI_TYPEDEF_BLOCK_ID: { 81021fb70c6SBrett Wilson TypedefInfo TI; 81121fb70c6SBrett Wilson if (auto Err = readBlock(ID, &TI)) 81221fb70c6SBrett Wilson return Err; 81321fb70c6SBrett Wilson addChild(I, std::move(TI)); 81421fb70c6SBrett Wilson return llvm::Error::success(); 81521fb70c6SBrett Wilson } 816d0f9a872SJulie Hockett default: 81718038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 81818038065SFangrui Song "invalid subblock type"); 819d0f9a872SJulie Hockett } 820d0f9a872SJulie Hockett } 821d0f9a872SJulie Hockett 822d0f9a872SJulie Hockett ClangDocBitcodeReader::Cursor 823d0f9a872SJulie Hockett ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) { 824d0f9a872SJulie Hockett BlockOrRecordID = 0; 825d0f9a872SJulie Hockett 826d0f9a872SJulie Hockett while (!Stream.AtEndOfStream()) { 8270e828958SJF Bastien Expected<unsigned> MaybeCode = Stream.ReadCode(); 8280e828958SJF Bastien if (!MaybeCode) { 8290e828958SJF Bastien // FIXME this drops the error on the floor. 8300e828958SJF Bastien consumeError(MaybeCode.takeError()); 8310e828958SJF Bastien return Cursor::BadBlock; 8320e828958SJF Bastien } 833d0f9a872SJulie Hockett 83400922537SBjorn Pettersson unsigned Code = MaybeCode.get(); 83500922537SBjorn Pettersson if (Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) { 83600922537SBjorn Pettersson BlockOrRecordID = Code; 83700922537SBjorn Pettersson return Cursor::Record; 83800922537SBjorn Pettersson } 83900922537SBjorn Pettersson switch (static_cast<llvm::bitc::FixedAbbrevIDs>(Code)) { 840d0f9a872SJulie Hockett case llvm::bitc::ENTER_SUBBLOCK: 8410e828958SJF Bastien if (Expected<unsigned> MaybeID = Stream.ReadSubBlockID()) 8420e828958SJF Bastien BlockOrRecordID = MaybeID.get(); 8430e828958SJF Bastien else { 8440e828958SJF Bastien // FIXME this drops the error on the floor. 8450e828958SJF Bastien consumeError(MaybeID.takeError()); 8460e828958SJF Bastien } 847d0f9a872SJulie Hockett return Cursor::BlockBegin; 848d0f9a872SJulie Hockett case llvm::bitc::END_BLOCK: 849d0f9a872SJulie Hockett if (Stream.ReadBlockEnd()) 850d0f9a872SJulie Hockett return Cursor::BadBlock; 851d0f9a872SJulie Hockett return Cursor::BlockEnd; 852d0f9a872SJulie Hockett case llvm::bitc::DEFINE_ABBREV: 8530e828958SJF Bastien if (llvm::Error Err = Stream.ReadAbbrevRecord()) { 8540e828958SJF Bastien // FIXME this drops the error on the floor. 8550e828958SJF Bastien consumeError(std::move(Err)); 8560e828958SJF Bastien } 857d0f9a872SJulie Hockett continue; 858d0f9a872SJulie Hockett case llvm::bitc::UNABBREV_RECORD: 859d0f9a872SJulie Hockett return Cursor::BadBlock; 86000922537SBjorn Pettersson case llvm::bitc::FIRST_APPLICATION_ABBREV: 86100922537SBjorn Pettersson llvm_unreachable("Unexpected abbrev id."); 862d0f9a872SJulie Hockett } 863d0f9a872SJulie Hockett } 864d0f9a872SJulie Hockett llvm_unreachable("Premature stream end."); 865d0f9a872SJulie Hockett } 866d0f9a872SJulie Hockett 86746fc9592SJulie Hockett llvm::Error ClangDocBitcodeReader::validateStream() { 868d0f9a872SJulie Hockett if (Stream.AtEndOfStream()) 86918038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 87018038065SFangrui Song "premature end of stream"); 871d0f9a872SJulie Hockett 872d0f9a872SJulie Hockett // Sniff for the signature. 8730e828958SJF Bastien for (int Idx = 0; Idx != 4; ++Idx) { 8740e828958SJF Bastien Expected<llvm::SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(8); 8750e828958SJF Bastien if (!MaybeRead) 8760e828958SJF Bastien return MaybeRead.takeError(); 8770e828958SJF Bastien else if (MaybeRead.get() != BitCodeConstants::Signature[Idx]) 87818038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 87918038065SFangrui Song "invalid bitcode signature"); 8800e828958SJF Bastien } 88146fc9592SJulie Hockett return llvm::Error::success(); 882d0f9a872SJulie Hockett } 883d0f9a872SJulie Hockett 88446fc9592SJulie Hockett llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() { 88549e75ebdSKrzysztof Parzyszek Expected<std::optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo = 8860e828958SJF Bastien Stream.ReadBlockInfoBlock(); 8870e828958SJF Bastien if (!MaybeBlockInfo) 8880e828958SJF Bastien return MaybeBlockInfo.takeError(); 8890e828958SJF Bastien else 8900e828958SJF Bastien BlockInfo = MaybeBlockInfo.get(); 891d0f9a872SJulie Hockett if (!BlockInfo) 89218038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 89318038065SFangrui Song "unable to parse BlockInfoBlock"); 894d0f9a872SJulie Hockett Stream.setBlockInfo(&*BlockInfo); 89546fc9592SJulie Hockett return llvm::Error::success(); 896d0f9a872SJulie Hockett } 897d0f9a872SJulie Hockett 898d0f9a872SJulie Hockett template <typename T> 89946fc9592SJulie Hockett llvm::Expected<std::unique_ptr<Info>> 90046fc9592SJulie Hockett ClangDocBitcodeReader::createInfo(unsigned ID) { 9011c705d9cSJonas Devlieghere std::unique_ptr<Info> I = std::make_unique<T>(); 90246fc9592SJulie Hockett if (auto Err = readBlock(ID, static_cast<T *>(I.get()))) 90346fc9592SJulie Hockett return std::move(Err); 9042c1c9a24SJulie Hockett return std::unique_ptr<Info>{std::move(I)}; 905d0f9a872SJulie Hockett } 906d0f9a872SJulie Hockett 90746fc9592SJulie Hockett llvm::Expected<std::unique_ptr<Info>> 90846fc9592SJulie Hockett ClangDocBitcodeReader::readBlockToInfo(unsigned ID) { 909d0f9a872SJulie Hockett switch (ID) { 910d0f9a872SJulie Hockett case BI_NAMESPACE_BLOCK_ID: 911d0f9a872SJulie Hockett return createInfo<NamespaceInfo>(ID); 912d0f9a872SJulie Hockett case BI_RECORD_BLOCK_ID: 913d0f9a872SJulie Hockett return createInfo<RecordInfo>(ID); 914d0f9a872SJulie Hockett case BI_ENUM_BLOCK_ID: 915d0f9a872SJulie Hockett return createInfo<EnumInfo>(ID); 91621fb70c6SBrett Wilson case BI_TYPEDEF_BLOCK_ID: 91721fb70c6SBrett Wilson return createInfo<TypedefInfo>(ID); 918d0f9a872SJulie Hockett case BI_FUNCTION_BLOCK_ID: 919d0f9a872SJulie Hockett return createInfo<FunctionInfo>(ID); 920d0f9a872SJulie Hockett default: 92118038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 92218038065SFangrui Song "cannot create info"); 923d0f9a872SJulie Hockett } 924d0f9a872SJulie Hockett } 925d0f9a872SJulie Hockett 926d0f9a872SJulie Hockett // Entry point 9278899c29bSJulie Hockett llvm::Expected<std::vector<std::unique_ptr<Info>>> 9288899c29bSJulie Hockett ClangDocBitcodeReader::readBitcode() { 929d0f9a872SJulie Hockett std::vector<std::unique_ptr<Info>> Infos; 93046fc9592SJulie Hockett if (auto Err = validateStream()) 93146fc9592SJulie Hockett return std::move(Err); 932d0f9a872SJulie Hockett 933d0f9a872SJulie Hockett // Read the top level blocks. 934d0f9a872SJulie Hockett while (!Stream.AtEndOfStream()) { 9350e828958SJF Bastien Expected<unsigned> MaybeCode = Stream.ReadCode(); 9360e828958SJF Bastien if (!MaybeCode) 9370e828958SJF Bastien return MaybeCode.takeError(); 9380e828958SJF Bastien if (MaybeCode.get() != llvm::bitc::ENTER_SUBBLOCK) 93918038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 94018038065SFangrui Song "no blocks in input"); 9410e828958SJF Bastien Expected<unsigned> MaybeID = Stream.ReadSubBlockID(); 9420e828958SJF Bastien if (!MaybeID) 9430e828958SJF Bastien return MaybeID.takeError(); 9440e828958SJF Bastien unsigned ID = MaybeID.get(); 945d0f9a872SJulie Hockett switch (ID) { 946d0f9a872SJulie Hockett // NamedType and Comment blocks should not appear at the top level 947d0f9a872SJulie Hockett case BI_TYPE_BLOCK_ID: 948d0f9a872SJulie Hockett case BI_FIELD_TYPE_BLOCK_ID: 949d0f9a872SJulie Hockett case BI_MEMBER_TYPE_BLOCK_ID: 950d0f9a872SJulie Hockett case BI_COMMENT_BLOCK_ID: 951d0f9a872SJulie Hockett case BI_REFERENCE_BLOCK_ID: 95218038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 95318038065SFangrui Song "invalid top level block"); 954d0f9a872SJulie Hockett case BI_NAMESPACE_BLOCK_ID: 955d0f9a872SJulie Hockett case BI_RECORD_BLOCK_ID: 956d0f9a872SJulie Hockett case BI_ENUM_BLOCK_ID: 95721fb70c6SBrett Wilson case BI_TYPEDEF_BLOCK_ID: 95846fc9592SJulie Hockett case BI_FUNCTION_BLOCK_ID: { 95946fc9592SJulie Hockett auto InfoOrErr = readBlockToInfo(ID); 96046fc9592SJulie Hockett if (!InfoOrErr) 96146fc9592SJulie Hockett return InfoOrErr.takeError(); 96246fc9592SJulie Hockett Infos.emplace_back(std::move(InfoOrErr.get())); 9638899c29bSJulie Hockett continue; 96446fc9592SJulie Hockett } 965d0f9a872SJulie Hockett case BI_VERSION_BLOCK_ID: 96646fc9592SJulie Hockett if (auto Err = readBlock(ID, VersionNumber)) 96746fc9592SJulie Hockett return std::move(Err); 968d0f9a872SJulie Hockett continue; 969d0f9a872SJulie Hockett case llvm::bitc::BLOCKINFO_BLOCK_ID: 97046fc9592SJulie Hockett if (auto Err = readBlockInfoBlock()) 97146fc9592SJulie Hockett return std::move(Err); 972d0f9a872SJulie Hockett continue; 973d0f9a872SJulie Hockett default: 9740e828958SJF Bastien if (llvm::Error Err = Stream.SkipBlock()) { 9750e828958SJF Bastien // FIXME this drops the error on the floor. 9760e828958SJF Bastien consumeError(std::move(Err)); 9770e828958SJF Bastien } 978d0f9a872SJulie Hockett continue; 979d0f9a872SJulie Hockett } 980d0f9a872SJulie Hockett } 9818899c29bSJulie Hockett return std::move(Infos); 982d0f9a872SJulie Hockett } 983d0f9a872SJulie Hockett 984d0f9a872SJulie Hockett } // namespace doc 985d0f9a872SJulie Hockett } // namespace clang 986