10b57cec5SDimitry Andric //===- BitcodeAnalyzer.cpp - Internal BitcodeAnalyzer implementation ------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/Bitcode/BitcodeAnalyzer.h" 100b57cec5SDimitry Andric #include "llvm/Bitcode/BitcodeReader.h" 110b57cec5SDimitry Andric #include "llvm/Bitcode/LLVMBitCodes.h" 120b57cec5SDimitry Andric #include "llvm/Bitstream/BitCodes.h" 130b57cec5SDimitry Andric #include "llvm/Bitstream/BitstreamReader.h" 140b57cec5SDimitry Andric #include "llvm/Support/Format.h" 150b57cec5SDimitry Andric #include "llvm/Support/SHA1.h" 16bdd1243dSDimitry Andric #include <optional> 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric using namespace llvm; 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric static Error reportError(StringRef Message) { 210b57cec5SDimitry Andric return createStringError(std::errc::illegal_byte_sequence, Message.data()); 220b57cec5SDimitry Andric } 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric /// Return a symbolic block name if known, otherwise return null. 25bdd1243dSDimitry Andric static std::optional<const char *> 26bdd1243dSDimitry Andric GetBlockName(unsigned BlockID, const BitstreamBlockInfo &BlockInfo, 270b57cec5SDimitry Andric CurStreamTypeType CurStreamType) { 280b57cec5SDimitry Andric // Standard blocks for all bitcode files. 290b57cec5SDimitry Andric if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) { 300b57cec5SDimitry Andric if (BlockID == bitc::BLOCKINFO_BLOCK_ID) 310b57cec5SDimitry Andric return "BLOCKINFO_BLOCK"; 32bdd1243dSDimitry Andric return std::nullopt; 330b57cec5SDimitry Andric } 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric // Check to see if we have a blockinfo record for this block, with a name. 360b57cec5SDimitry Andric if (const BitstreamBlockInfo::BlockInfo *Info = 370b57cec5SDimitry Andric BlockInfo.getBlockInfo(BlockID)) { 380b57cec5SDimitry Andric if (!Info->Name.empty()) 390b57cec5SDimitry Andric return Info->Name.c_str(); 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric if (CurStreamType != LLVMIRBitstream) 43bdd1243dSDimitry Andric return std::nullopt; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric switch (BlockID) { 460b57cec5SDimitry Andric default: 47bdd1243dSDimitry Andric return std::nullopt; 480b57cec5SDimitry Andric case bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID: 490b57cec5SDimitry Andric return "OPERAND_BUNDLE_TAGS_BLOCK"; 500b57cec5SDimitry Andric case bitc::MODULE_BLOCK_ID: 510b57cec5SDimitry Andric return "MODULE_BLOCK"; 520b57cec5SDimitry Andric case bitc::PARAMATTR_BLOCK_ID: 530b57cec5SDimitry Andric return "PARAMATTR_BLOCK"; 540b57cec5SDimitry Andric case bitc::PARAMATTR_GROUP_BLOCK_ID: 550b57cec5SDimitry Andric return "PARAMATTR_GROUP_BLOCK_ID"; 560b57cec5SDimitry Andric case bitc::TYPE_BLOCK_ID_NEW: 570b57cec5SDimitry Andric return "TYPE_BLOCK_ID"; 580b57cec5SDimitry Andric case bitc::CONSTANTS_BLOCK_ID: 590b57cec5SDimitry Andric return "CONSTANTS_BLOCK"; 600b57cec5SDimitry Andric case bitc::FUNCTION_BLOCK_ID: 610b57cec5SDimitry Andric return "FUNCTION_BLOCK"; 620b57cec5SDimitry Andric case bitc::IDENTIFICATION_BLOCK_ID: 630b57cec5SDimitry Andric return "IDENTIFICATION_BLOCK_ID"; 640b57cec5SDimitry Andric case bitc::VALUE_SYMTAB_BLOCK_ID: 650b57cec5SDimitry Andric return "VALUE_SYMTAB"; 660b57cec5SDimitry Andric case bitc::METADATA_BLOCK_ID: 670b57cec5SDimitry Andric return "METADATA_BLOCK"; 680b57cec5SDimitry Andric case bitc::METADATA_KIND_BLOCK_ID: 690b57cec5SDimitry Andric return "METADATA_KIND_BLOCK"; 700b57cec5SDimitry Andric case bitc::METADATA_ATTACHMENT_ID: 710b57cec5SDimitry Andric return "METADATA_ATTACHMENT_BLOCK"; 720b57cec5SDimitry Andric case bitc::USELIST_BLOCK_ID: 730b57cec5SDimitry Andric return "USELIST_BLOCK_ID"; 740b57cec5SDimitry Andric case bitc::GLOBALVAL_SUMMARY_BLOCK_ID: 750b57cec5SDimitry Andric return "GLOBALVAL_SUMMARY_BLOCK"; 760b57cec5SDimitry Andric case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID: 770b57cec5SDimitry Andric return "FULL_LTO_GLOBALVAL_SUMMARY_BLOCK"; 780b57cec5SDimitry Andric case bitc::MODULE_STRTAB_BLOCK_ID: 790b57cec5SDimitry Andric return "MODULE_STRTAB_BLOCK"; 800b57cec5SDimitry Andric case bitc::STRTAB_BLOCK_ID: 810b57cec5SDimitry Andric return "STRTAB_BLOCK"; 820b57cec5SDimitry Andric case bitc::SYMTAB_BLOCK_ID: 830b57cec5SDimitry Andric return "SYMTAB_BLOCK"; 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric /// Return a symbolic code name if known, otherwise return null. 88bdd1243dSDimitry Andric static std::optional<const char *> 89bdd1243dSDimitry Andric GetCodeName(unsigned CodeID, unsigned BlockID, 900b57cec5SDimitry Andric const BitstreamBlockInfo &BlockInfo, 910b57cec5SDimitry Andric CurStreamTypeType CurStreamType) { 920b57cec5SDimitry Andric // Standard blocks for all bitcode files. 930b57cec5SDimitry Andric if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) { 940b57cec5SDimitry Andric if (BlockID == bitc::BLOCKINFO_BLOCK_ID) { 950b57cec5SDimitry Andric switch (CodeID) { 960b57cec5SDimitry Andric default: 97bdd1243dSDimitry Andric return std::nullopt; 980b57cec5SDimitry Andric case bitc::BLOCKINFO_CODE_SETBID: 990b57cec5SDimitry Andric return "SETBID"; 1000b57cec5SDimitry Andric case bitc::BLOCKINFO_CODE_BLOCKNAME: 1010b57cec5SDimitry Andric return "BLOCKNAME"; 1020b57cec5SDimitry Andric case bitc::BLOCKINFO_CODE_SETRECORDNAME: 1030b57cec5SDimitry Andric return "SETRECORDNAME"; 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric } 106bdd1243dSDimitry Andric return std::nullopt; 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric // Check to see if we have a blockinfo record for this record, with a name. 1100b57cec5SDimitry Andric if (const BitstreamBlockInfo::BlockInfo *Info = 1110b57cec5SDimitry Andric BlockInfo.getBlockInfo(BlockID)) { 1120eae32dcSDimitry Andric for (const std::pair<unsigned, std::string> &RN : Info->RecordNames) 1130eae32dcSDimitry Andric if (RN.first == CodeID) 1140eae32dcSDimitry Andric return RN.second.c_str(); 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric if (CurStreamType != LLVMIRBitstream) 118bdd1243dSDimitry Andric return std::nullopt; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric #define STRINGIFY_CODE(PREFIX, CODE) \ 1210b57cec5SDimitry Andric case bitc::PREFIX##_##CODE: \ 1220b57cec5SDimitry Andric return #CODE; 1230b57cec5SDimitry Andric switch (BlockID) { 1240b57cec5SDimitry Andric default: 125bdd1243dSDimitry Andric return std::nullopt; 1260b57cec5SDimitry Andric case bitc::MODULE_BLOCK_ID: 1270b57cec5SDimitry Andric switch (CodeID) { 1280b57cec5SDimitry Andric default: 129bdd1243dSDimitry Andric return std::nullopt; 1300b57cec5SDimitry Andric STRINGIFY_CODE(MODULE_CODE, VERSION) 1310b57cec5SDimitry Andric STRINGIFY_CODE(MODULE_CODE, TRIPLE) 1320b57cec5SDimitry Andric STRINGIFY_CODE(MODULE_CODE, DATALAYOUT) 1330b57cec5SDimitry Andric STRINGIFY_CODE(MODULE_CODE, ASM) 1340b57cec5SDimitry Andric STRINGIFY_CODE(MODULE_CODE, SECTIONNAME) 1355ffd83dbSDimitry Andric STRINGIFY_CODE(MODULE_CODE, DEPLIB) // Deprecated, present in old bitcode 1360b57cec5SDimitry Andric STRINGIFY_CODE(MODULE_CODE, GLOBALVAR) 1370b57cec5SDimitry Andric STRINGIFY_CODE(MODULE_CODE, FUNCTION) 1380b57cec5SDimitry Andric STRINGIFY_CODE(MODULE_CODE, ALIAS) 1390b57cec5SDimitry Andric STRINGIFY_CODE(MODULE_CODE, GCNAME) 140e8d8bef9SDimitry Andric STRINGIFY_CODE(MODULE_CODE, COMDAT) 1410b57cec5SDimitry Andric STRINGIFY_CODE(MODULE_CODE, VSTOFFSET) 1420b57cec5SDimitry Andric STRINGIFY_CODE(MODULE_CODE, METADATA_VALUES_UNUSED) 1430b57cec5SDimitry Andric STRINGIFY_CODE(MODULE_CODE, SOURCE_FILENAME) 1440b57cec5SDimitry Andric STRINGIFY_CODE(MODULE_CODE, HASH) 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric case bitc::IDENTIFICATION_BLOCK_ID: 1470b57cec5SDimitry Andric switch (CodeID) { 1480b57cec5SDimitry Andric default: 149bdd1243dSDimitry Andric return std::nullopt; 1500b57cec5SDimitry Andric STRINGIFY_CODE(IDENTIFICATION_CODE, STRING) 1510b57cec5SDimitry Andric STRINGIFY_CODE(IDENTIFICATION_CODE, EPOCH) 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric case bitc::PARAMATTR_BLOCK_ID: 1540b57cec5SDimitry Andric switch (CodeID) { 1550b57cec5SDimitry Andric default: 156bdd1243dSDimitry Andric return std::nullopt; 1570b57cec5SDimitry Andric // FIXME: Should these be different? 1580b57cec5SDimitry Andric case bitc::PARAMATTR_CODE_ENTRY_OLD: 1590b57cec5SDimitry Andric return "ENTRY"; 1600b57cec5SDimitry Andric case bitc::PARAMATTR_CODE_ENTRY: 1610b57cec5SDimitry Andric return "ENTRY"; 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric case bitc::PARAMATTR_GROUP_BLOCK_ID: 1640b57cec5SDimitry Andric switch (CodeID) { 1650b57cec5SDimitry Andric default: 166bdd1243dSDimitry Andric return std::nullopt; 1670b57cec5SDimitry Andric case bitc::PARAMATTR_GRP_CODE_ENTRY: 1680b57cec5SDimitry Andric return "ENTRY"; 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric case bitc::TYPE_BLOCK_ID_NEW: 1710b57cec5SDimitry Andric switch (CodeID) { 1720b57cec5SDimitry Andric default: 173bdd1243dSDimitry Andric return std::nullopt; 1740b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, NUMENTRY) 1750b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, VOID) 1760b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, FLOAT) 1770b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, DOUBLE) 1780b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, LABEL) 1790b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, OPAQUE) 1800b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, INTEGER) 1810b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, POINTER) 182e8d8bef9SDimitry Andric STRINGIFY_CODE(TYPE_CODE, HALF) 1830b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, ARRAY) 1840b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, VECTOR) 1850b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, X86_FP80) 1860b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, FP128) 1870b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, PPC_FP128) 1880b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, METADATA) 189e8d8bef9SDimitry Andric STRINGIFY_CODE(TYPE_CODE, X86_MMX) 1900b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, STRUCT_ANON) 1910b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, STRUCT_NAME) 1920b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, STRUCT_NAMED) 1930b57cec5SDimitry Andric STRINGIFY_CODE(TYPE_CODE, FUNCTION) 194e8d8bef9SDimitry Andric STRINGIFY_CODE(TYPE_CODE, TOKEN) 195e8d8bef9SDimitry Andric STRINGIFY_CODE(TYPE_CODE, BFLOAT) 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric case bitc::CONSTANTS_BLOCK_ID: 1990b57cec5SDimitry Andric switch (CodeID) { 2000b57cec5SDimitry Andric default: 201bdd1243dSDimitry Andric return std::nullopt; 2020b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, SETTYPE) 2030b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, NULL) 2040b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, UNDEF) 2050b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, INTEGER) 2060b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, WIDE_INTEGER) 2070b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, FLOAT) 2080b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, AGGREGATE) 2090b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, STRING) 2100b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, CSTRING) 2110b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, CE_BINOP) 2120b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, CE_CAST) 2130b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, CE_GEP) 2140b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, CE_INBOUNDS_GEP) 2150b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, CE_SELECT) 2160b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, CE_EXTRACTELT) 2170b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, CE_INSERTELT) 2180b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, CE_SHUFFLEVEC) 2190b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, CE_CMP) 2200b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, INLINEASM) 2210b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, CE_SHUFVEC_EX) 2220b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, CE_UNOP) 223fe6060f1SDimitry Andric STRINGIFY_CODE(CST_CODE, DSO_LOCAL_EQUIVALENT) 2240eae32dcSDimitry Andric STRINGIFY_CODE(CST_CODE, NO_CFI_VALUE) 225*0fca6ea1SDimitry Andric STRINGIFY_CODE(CST_CODE, PTRAUTH) 2260b57cec5SDimitry Andric case bitc::CST_CODE_BLOCKADDRESS: 2270b57cec5SDimitry Andric return "CST_CODE_BLOCKADDRESS"; 2280b57cec5SDimitry Andric STRINGIFY_CODE(CST_CODE, DATA) 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric case bitc::FUNCTION_BLOCK_ID: 2310b57cec5SDimitry Andric switch (CodeID) { 2320b57cec5SDimitry Andric default: 233bdd1243dSDimitry Andric return std::nullopt; 2340b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, DECLAREBLOCKS) 2350b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_BINOP) 2360b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_CAST) 2370b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_GEP_OLD) 2380b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_INBOUNDS_GEP_OLD) 2390b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_SELECT) 2400b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_EXTRACTELT) 2410b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_INSERTELT) 2420b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_SHUFFLEVEC) 2430b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_CMP) 2440b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_RET) 2450b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_BR) 2460b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_SWITCH) 2470b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_INVOKE) 2480b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_UNOP) 2490b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_UNREACHABLE) 2500b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_CLEANUPRET) 2510b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_CATCHRET) 2520b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_CATCHPAD) 2530b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_PHI) 2540b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_ALLOCA) 2550b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_LOAD) 2560b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_VAARG) 2570b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_STORE) 2580b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_EXTRACTVAL) 2590b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_INSERTVAL) 2600b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_CMP2) 2610b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_VSELECT) 2620b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, DEBUG_LOC_AGAIN) 2630b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_CALL) 2640b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, DEBUG_LOC) 2650b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_GEP) 2660b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, OPERAND_BUNDLE) 2670b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_FENCE) 2680b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_ATOMICRMW) 2690b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_LOADATOMIC) 2700b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_STOREATOMIC) 2710b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_CMPXCHG) 2720b57cec5SDimitry Andric STRINGIFY_CODE(FUNC_CODE, INST_CALLBR) 27381ad6265SDimitry Andric STRINGIFY_CODE(FUNC_CODE, BLOCKADDR_USERS) 274*0fca6ea1SDimitry Andric STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_DECLARE) 275*0fca6ea1SDimitry Andric STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_VALUE) 276*0fca6ea1SDimitry Andric STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_ASSIGN) 277*0fca6ea1SDimitry Andric STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_VALUE_SIMPLE) 278*0fca6ea1SDimitry Andric STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_LABEL) 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric case bitc::VALUE_SYMTAB_BLOCK_ID: 2810b57cec5SDimitry Andric switch (CodeID) { 2820b57cec5SDimitry Andric default: 283bdd1243dSDimitry Andric return std::nullopt; 2840b57cec5SDimitry Andric STRINGIFY_CODE(VST_CODE, ENTRY) 2850b57cec5SDimitry Andric STRINGIFY_CODE(VST_CODE, BBENTRY) 2860b57cec5SDimitry Andric STRINGIFY_CODE(VST_CODE, FNENTRY) 2870b57cec5SDimitry Andric STRINGIFY_CODE(VST_CODE, COMBINED_ENTRY) 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric case bitc::MODULE_STRTAB_BLOCK_ID: 2900b57cec5SDimitry Andric switch (CodeID) { 2910b57cec5SDimitry Andric default: 292bdd1243dSDimitry Andric return std::nullopt; 2930b57cec5SDimitry Andric STRINGIFY_CODE(MST_CODE, ENTRY) 2940b57cec5SDimitry Andric STRINGIFY_CODE(MST_CODE, HASH) 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric case bitc::GLOBALVAL_SUMMARY_BLOCK_ID: 2970b57cec5SDimitry Andric case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID: 2980b57cec5SDimitry Andric switch (CodeID) { 2990b57cec5SDimitry Andric default: 300bdd1243dSDimitry Andric return std::nullopt; 3010b57cec5SDimitry Andric STRINGIFY_CODE(FS, PERMODULE) 3020b57cec5SDimitry Andric STRINGIFY_CODE(FS, PERMODULE_PROFILE) 3030b57cec5SDimitry Andric STRINGIFY_CODE(FS, PERMODULE_RELBF) 3040b57cec5SDimitry Andric STRINGIFY_CODE(FS, PERMODULE_GLOBALVAR_INIT_REFS) 3050b57cec5SDimitry Andric STRINGIFY_CODE(FS, PERMODULE_VTABLE_GLOBALVAR_INIT_REFS) 3060b57cec5SDimitry Andric STRINGIFY_CODE(FS, COMBINED) 3070b57cec5SDimitry Andric STRINGIFY_CODE(FS, COMBINED_PROFILE) 3080b57cec5SDimitry Andric STRINGIFY_CODE(FS, COMBINED_GLOBALVAR_INIT_REFS) 3090b57cec5SDimitry Andric STRINGIFY_CODE(FS, ALIAS) 3100b57cec5SDimitry Andric STRINGIFY_CODE(FS, COMBINED_ALIAS) 3110b57cec5SDimitry Andric STRINGIFY_CODE(FS, COMBINED_ORIGINAL_NAME) 3120b57cec5SDimitry Andric STRINGIFY_CODE(FS, VERSION) 3130b57cec5SDimitry Andric STRINGIFY_CODE(FS, FLAGS) 3140b57cec5SDimitry Andric STRINGIFY_CODE(FS, TYPE_TESTS) 3150b57cec5SDimitry Andric STRINGIFY_CODE(FS, TYPE_TEST_ASSUME_VCALLS) 3160b57cec5SDimitry Andric STRINGIFY_CODE(FS, TYPE_CHECKED_LOAD_VCALLS) 3170b57cec5SDimitry Andric STRINGIFY_CODE(FS, TYPE_TEST_ASSUME_CONST_VCALL) 3180b57cec5SDimitry Andric STRINGIFY_CODE(FS, TYPE_CHECKED_LOAD_CONST_VCALL) 3190b57cec5SDimitry Andric STRINGIFY_CODE(FS, VALUE_GUID) 3200b57cec5SDimitry Andric STRINGIFY_CODE(FS, CFI_FUNCTION_DEFS) 3210b57cec5SDimitry Andric STRINGIFY_CODE(FS, CFI_FUNCTION_DECLS) 3220b57cec5SDimitry Andric STRINGIFY_CODE(FS, TYPE_ID) 3230b57cec5SDimitry Andric STRINGIFY_CODE(FS, TYPE_ID_METADATA) 3245ffd83dbSDimitry Andric STRINGIFY_CODE(FS, BLOCK_COUNT) 3255ffd83dbSDimitry Andric STRINGIFY_CODE(FS, PARAM_ACCESS) 326bdd1243dSDimitry Andric STRINGIFY_CODE(FS, PERMODULE_CALLSITE_INFO) 327bdd1243dSDimitry Andric STRINGIFY_CODE(FS, PERMODULE_ALLOC_INFO) 328bdd1243dSDimitry Andric STRINGIFY_CODE(FS, COMBINED_CALLSITE_INFO) 329bdd1243dSDimitry Andric STRINGIFY_CODE(FS, COMBINED_ALLOC_INFO) 330bdd1243dSDimitry Andric STRINGIFY_CODE(FS, STACK_IDS) 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric case bitc::METADATA_ATTACHMENT_ID: 3330b57cec5SDimitry Andric switch (CodeID) { 3340b57cec5SDimitry Andric default: 335bdd1243dSDimitry Andric return std::nullopt; 3360b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, ATTACHMENT) 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric case bitc::METADATA_BLOCK_ID: 3390b57cec5SDimitry Andric switch (CodeID) { 3400b57cec5SDimitry Andric default: 341bdd1243dSDimitry Andric return std::nullopt; 3420b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, STRING_OLD) 3430b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, VALUE) 3440b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, NODE) 3450b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, NAME) 3460b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, DISTINCT_NODE) 3470b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, KIND) // Older bitcode has it in a MODULE_BLOCK 3480b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, LOCATION) 3490b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, OLD_NODE) 3500b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, OLD_FN_NODE) 3510b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, NAMED_NODE) 3520b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, GENERIC_DEBUG) 3530b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, SUBRANGE) 3540b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, ENUMERATOR) 3550b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, BASIC_TYPE) 3560b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, FILE) 3570b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, DERIVED_TYPE) 3580b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, COMPOSITE_TYPE) 3590b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, SUBROUTINE_TYPE) 3600b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, COMPILE_UNIT) 3610b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, SUBPROGRAM) 3620b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, LEXICAL_BLOCK) 3630b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, LEXICAL_BLOCK_FILE) 3640b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, NAMESPACE) 3650b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, TEMPLATE_TYPE) 3660b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, TEMPLATE_VALUE) 3670b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, GLOBAL_VAR) 3680b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, LOCAL_VAR) 3690b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, EXPRESSION) 3700b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, OBJC_PROPERTY) 3710b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, IMPORTED_ENTITY) 3720b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, MODULE) 3730b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, MACRO) 3740b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, MACRO_FILE) 3750b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, STRINGS) 3760b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, GLOBAL_DECL_ATTACHMENT) 3770b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, GLOBAL_VAR_EXPR) 3780b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, INDEX_OFFSET) 3790b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, INDEX) 380fe6060f1SDimitry Andric STRINGIFY_CODE(METADATA, ARG_LIST) 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric case bitc::METADATA_KIND_BLOCK_ID: 3830b57cec5SDimitry Andric switch (CodeID) { 3840b57cec5SDimitry Andric default: 385bdd1243dSDimitry Andric return std::nullopt; 3860b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, KIND) 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric case bitc::USELIST_BLOCK_ID: 3890b57cec5SDimitry Andric switch (CodeID) { 3900b57cec5SDimitry Andric default: 391bdd1243dSDimitry Andric return std::nullopt; 3920b57cec5SDimitry Andric case bitc::USELIST_CODE_DEFAULT: 3930b57cec5SDimitry Andric return "USELIST_CODE_DEFAULT"; 3940b57cec5SDimitry Andric case bitc::USELIST_CODE_BB: 3950b57cec5SDimitry Andric return "USELIST_CODE_BB"; 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric case bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID: 3990b57cec5SDimitry Andric switch (CodeID) { 4000b57cec5SDimitry Andric default: 401bdd1243dSDimitry Andric return std::nullopt; 4020b57cec5SDimitry Andric case bitc::OPERAND_BUNDLE_TAG: 4030b57cec5SDimitry Andric return "OPERAND_BUNDLE_TAG"; 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric case bitc::STRTAB_BLOCK_ID: 4060b57cec5SDimitry Andric switch (CodeID) { 4070b57cec5SDimitry Andric default: 408bdd1243dSDimitry Andric return std::nullopt; 4090b57cec5SDimitry Andric case bitc::STRTAB_BLOB: 4100b57cec5SDimitry Andric return "BLOB"; 4110b57cec5SDimitry Andric } 4120b57cec5SDimitry Andric case bitc::SYMTAB_BLOCK_ID: 4130b57cec5SDimitry Andric switch (CodeID) { 4140b57cec5SDimitry Andric default: 415bdd1243dSDimitry Andric return std::nullopt; 4160b57cec5SDimitry Andric case bitc::SYMTAB_BLOB: 4170b57cec5SDimitry Andric return "BLOB"; 4180b57cec5SDimitry Andric } 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric #undef STRINGIFY_CODE 4210b57cec5SDimitry Andric } 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric static void printSize(raw_ostream &OS, double Bits) { 4240b57cec5SDimitry Andric OS << format("%.2f/%.2fB/%luW", Bits, Bits / 8, (unsigned long)(Bits / 32)); 4250b57cec5SDimitry Andric } 4260b57cec5SDimitry Andric static void printSize(raw_ostream &OS, uint64_t Bits) { 4270b57cec5SDimitry Andric OS << format("%lub/%.2fB/%luW", (unsigned long)Bits, (double)Bits / 8, 4280b57cec5SDimitry Andric (unsigned long)(Bits / 32)); 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric static Expected<CurStreamTypeType> ReadSignature(BitstreamCursor &Stream) { 4320b57cec5SDimitry Andric auto tryRead = [&Stream](char &Dest, size_t size) -> Error { 4330b57cec5SDimitry Andric if (Expected<SimpleBitstreamCursor::word_t> MaybeWord = Stream.Read(size)) 4340b57cec5SDimitry Andric Dest = MaybeWord.get(); 4350b57cec5SDimitry Andric else 4360b57cec5SDimitry Andric return MaybeWord.takeError(); 4370b57cec5SDimitry Andric return Error::success(); 4380b57cec5SDimitry Andric }; 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric char Signature[6]; 4410b57cec5SDimitry Andric if (Error Err = tryRead(Signature[0], 8)) 4420b57cec5SDimitry Andric return std::move(Err); 4430b57cec5SDimitry Andric if (Error Err = tryRead(Signature[1], 8)) 4440b57cec5SDimitry Andric return std::move(Err); 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric // Autodetect the file contents, if it is one we know. 4470b57cec5SDimitry Andric if (Signature[0] == 'C' && Signature[1] == 'P') { 4480b57cec5SDimitry Andric if (Error Err = tryRead(Signature[2], 8)) 4490b57cec5SDimitry Andric return std::move(Err); 4500b57cec5SDimitry Andric if (Error Err = tryRead(Signature[3], 8)) 4510b57cec5SDimitry Andric return std::move(Err); 4520b57cec5SDimitry Andric if (Signature[2] == 'C' && Signature[3] == 'H') 4530b57cec5SDimitry Andric return ClangSerializedASTBitstream; 4540b57cec5SDimitry Andric } else if (Signature[0] == 'D' && Signature[1] == 'I') { 4550b57cec5SDimitry Andric if (Error Err = tryRead(Signature[2], 8)) 4560b57cec5SDimitry Andric return std::move(Err); 4570b57cec5SDimitry Andric if (Error Err = tryRead(Signature[3], 8)) 4580b57cec5SDimitry Andric return std::move(Err); 4590b57cec5SDimitry Andric if (Signature[2] == 'A' && Signature[3] == 'G') 4600b57cec5SDimitry Andric return ClangSerializedDiagnosticsBitstream; 4618bcb0991SDimitry Andric } else if (Signature[0] == 'R' && Signature[1] == 'M') { 4628bcb0991SDimitry Andric if (Error Err = tryRead(Signature[2], 8)) 4638bcb0991SDimitry Andric return std::move(Err); 4648bcb0991SDimitry Andric if (Error Err = tryRead(Signature[3], 8)) 4658bcb0991SDimitry Andric return std::move(Err); 4668bcb0991SDimitry Andric if (Signature[2] == 'R' && Signature[3] == 'K') 4678bcb0991SDimitry Andric return LLVMBitstreamRemarks; 4680b57cec5SDimitry Andric } else { 4690b57cec5SDimitry Andric if (Error Err = tryRead(Signature[2], 4)) 4700b57cec5SDimitry Andric return std::move(Err); 4710b57cec5SDimitry Andric if (Error Err = tryRead(Signature[3], 4)) 4720b57cec5SDimitry Andric return std::move(Err); 4730b57cec5SDimitry Andric if (Error Err = tryRead(Signature[4], 4)) 4740b57cec5SDimitry Andric return std::move(Err); 4750b57cec5SDimitry Andric if (Error Err = tryRead(Signature[5], 4)) 4760b57cec5SDimitry Andric return std::move(Err); 4770b57cec5SDimitry Andric if (Signature[0] == 'B' && Signature[1] == 'C' && Signature[2] == 0x0 && 4780b57cec5SDimitry Andric Signature[3] == 0xC && Signature[4] == 0xE && Signature[5] == 0xD) 4790b57cec5SDimitry Andric return LLVMIRBitstream; 4800b57cec5SDimitry Andric } 4810b57cec5SDimitry Andric return UnknownBitstream; 4820b57cec5SDimitry Andric } 4830b57cec5SDimitry Andric 484bdd1243dSDimitry Andric static Expected<CurStreamTypeType> analyzeHeader(std::optional<BCDumpOptions> O, 4850b57cec5SDimitry Andric BitstreamCursor &Stream) { 4860b57cec5SDimitry Andric ArrayRef<uint8_t> Bytes = Stream.getBitcodeBytes(); 4870b57cec5SDimitry Andric const unsigned char *BufPtr = (const unsigned char *)Bytes.data(); 4880b57cec5SDimitry Andric const unsigned char *EndBufPtr = BufPtr + Bytes.size(); 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric // If we have a wrapper header, parse it and ignore the non-bc file 4910b57cec5SDimitry Andric // contents. The magic number is 0x0B17C0DE stored in little endian. 4920b57cec5SDimitry Andric if (isBitcodeWrapper(BufPtr, EndBufPtr)) { 4930b57cec5SDimitry Andric if (Bytes.size() < BWH_HeaderSize) 4940b57cec5SDimitry Andric return reportError("Invalid bitcode wrapper header"); 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric if (O) { 4970b57cec5SDimitry Andric unsigned Magic = support::endian::read32le(&BufPtr[BWH_MagicField]); 4980b57cec5SDimitry Andric unsigned Version = support::endian::read32le(&BufPtr[BWH_VersionField]); 4990b57cec5SDimitry Andric unsigned Offset = support::endian::read32le(&BufPtr[BWH_OffsetField]); 5000b57cec5SDimitry Andric unsigned Size = support::endian::read32le(&BufPtr[BWH_SizeField]); 5010b57cec5SDimitry Andric unsigned CPUType = support::endian::read32le(&BufPtr[BWH_CPUTypeField]); 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric O->OS << "<BITCODE_WRAPPER_HEADER" 5040b57cec5SDimitry Andric << " Magic=" << format_hex(Magic, 10) 5050b57cec5SDimitry Andric << " Version=" << format_hex(Version, 10) 5060b57cec5SDimitry Andric << " Offset=" << format_hex(Offset, 10) 5070b57cec5SDimitry Andric << " Size=" << format_hex(Size, 10) 5080b57cec5SDimitry Andric << " CPUType=" << format_hex(CPUType, 10) << "/>\n"; 5090b57cec5SDimitry Andric } 5100b57cec5SDimitry Andric 5110b57cec5SDimitry Andric if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr, true)) 5120b57cec5SDimitry Andric return reportError("Invalid bitcode wrapper header"); 5130b57cec5SDimitry Andric } 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric // Use the cursor modified by skipping the wrapper header. 5160b57cec5SDimitry Andric Stream = BitstreamCursor(ArrayRef<uint8_t>(BufPtr, EndBufPtr)); 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric return ReadSignature(Stream); 5190b57cec5SDimitry Andric } 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric static bool canDecodeBlob(unsigned Code, unsigned BlockID) { 5220b57cec5SDimitry Andric return BlockID == bitc::METADATA_BLOCK_ID && Code == bitc::METADATA_STRINGS; 5230b57cec5SDimitry Andric } 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric Error BitcodeAnalyzer::decodeMetadataStringsBlob(StringRef Indent, 5260b57cec5SDimitry Andric ArrayRef<uint64_t> Record, 5270b57cec5SDimitry Andric StringRef Blob, 5280b57cec5SDimitry Andric raw_ostream &OS) { 5290b57cec5SDimitry Andric if (Blob.empty()) 5300b57cec5SDimitry Andric return reportError("Cannot decode empty blob."); 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andric if (Record.size() != 2) 5330b57cec5SDimitry Andric return reportError( 5340b57cec5SDimitry Andric "Decoding metadata strings blob needs two record entries."); 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric unsigned NumStrings = Record[0]; 5370b57cec5SDimitry Andric unsigned StringsOffset = Record[1]; 5380b57cec5SDimitry Andric OS << " num-strings = " << NumStrings << " {\n"; 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric StringRef Lengths = Blob.slice(0, StringsOffset); 5410b57cec5SDimitry Andric SimpleBitstreamCursor R(Lengths); 5420b57cec5SDimitry Andric StringRef Strings = Blob.drop_front(StringsOffset); 5430b57cec5SDimitry Andric do { 5440b57cec5SDimitry Andric if (R.AtEndOfStream()) 5450b57cec5SDimitry Andric return reportError("bad length"); 5460b57cec5SDimitry Andric 547349cc55cSDimitry Andric uint32_t Size; 548349cc55cSDimitry Andric if (Error E = R.ReadVBR(6).moveInto(Size)) 549349cc55cSDimitry Andric return E; 5500b57cec5SDimitry Andric if (Strings.size() < Size) 5510b57cec5SDimitry Andric return reportError("truncated chars"); 5520b57cec5SDimitry Andric 5530b57cec5SDimitry Andric OS << Indent << " '"; 5540b57cec5SDimitry Andric OS.write_escaped(Strings.slice(0, Size), /*hex=*/true); 5550b57cec5SDimitry Andric OS << "'\n"; 5560b57cec5SDimitry Andric Strings = Strings.drop_front(Size); 5570b57cec5SDimitry Andric } while (--NumStrings); 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric OS << Indent << " }"; 5600b57cec5SDimitry Andric return Error::success(); 5610b57cec5SDimitry Andric } 5620b57cec5SDimitry Andric 5630b57cec5SDimitry Andric BitcodeAnalyzer::BitcodeAnalyzer(StringRef Buffer, 564bdd1243dSDimitry Andric std::optional<StringRef> BlockInfoBuffer) 5650b57cec5SDimitry Andric : Stream(Buffer) { 5660b57cec5SDimitry Andric if (BlockInfoBuffer) 5670b57cec5SDimitry Andric BlockInfoStream.emplace(*BlockInfoBuffer); 5680b57cec5SDimitry Andric } 5690b57cec5SDimitry Andric 570bdd1243dSDimitry Andric Error BitcodeAnalyzer::analyze(std::optional<BCDumpOptions> O, 571bdd1243dSDimitry Andric std::optional<StringRef> CheckHash) { 572349cc55cSDimitry Andric if (Error E = analyzeHeader(O, Stream).moveInto(CurStreamType)) 573349cc55cSDimitry Andric return E; 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric Stream.setBlockInfo(&BlockInfo); 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andric // Read block info from BlockInfoStream, if specified. 5780b57cec5SDimitry Andric // The block info must be a top-level block. 5790b57cec5SDimitry Andric if (BlockInfoStream) { 5800b57cec5SDimitry Andric BitstreamCursor BlockInfoCursor(*BlockInfoStream); 581349cc55cSDimitry Andric if (Error E = analyzeHeader(O, BlockInfoCursor).takeError()) 582349cc55cSDimitry Andric return E; 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric while (!BlockInfoCursor.AtEndOfStream()) { 5850b57cec5SDimitry Andric Expected<unsigned> MaybeCode = BlockInfoCursor.ReadCode(); 5860b57cec5SDimitry Andric if (!MaybeCode) 5870b57cec5SDimitry Andric return MaybeCode.takeError(); 5880b57cec5SDimitry Andric if (MaybeCode.get() != bitc::ENTER_SUBBLOCK) 5890b57cec5SDimitry Andric return reportError("Invalid record at top-level in block info file"); 5900b57cec5SDimitry Andric 5910b57cec5SDimitry Andric Expected<unsigned> MaybeBlockID = BlockInfoCursor.ReadSubBlockID(); 5920b57cec5SDimitry Andric if (!MaybeBlockID) 5930b57cec5SDimitry Andric return MaybeBlockID.takeError(); 5940b57cec5SDimitry Andric if (MaybeBlockID.get() == bitc::BLOCKINFO_BLOCK_ID) { 595bdd1243dSDimitry Andric std::optional<BitstreamBlockInfo> NewBlockInfo; 596349cc55cSDimitry Andric if (Error E = 597349cc55cSDimitry Andric BlockInfoCursor.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true) 598349cc55cSDimitry Andric .moveInto(NewBlockInfo)) 599349cc55cSDimitry Andric return E; 6000b57cec5SDimitry Andric if (!NewBlockInfo) 6010b57cec5SDimitry Andric return reportError("Malformed BlockInfoBlock in block info file"); 6020b57cec5SDimitry Andric BlockInfo = std::move(*NewBlockInfo); 6030b57cec5SDimitry Andric break; 6040b57cec5SDimitry Andric } 6050b57cec5SDimitry Andric 6060b57cec5SDimitry Andric if (Error Err = BlockInfoCursor.SkipBlock()) 6070b57cec5SDimitry Andric return Err; 6080b57cec5SDimitry Andric } 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric 6110b57cec5SDimitry Andric // Parse the top-level structure. We only allow blocks at the top-level. 6120b57cec5SDimitry Andric while (!Stream.AtEndOfStream()) { 6130b57cec5SDimitry Andric Expected<unsigned> MaybeCode = Stream.ReadCode(); 6140b57cec5SDimitry Andric if (!MaybeCode) 6150b57cec5SDimitry Andric return MaybeCode.takeError(); 6160b57cec5SDimitry Andric if (MaybeCode.get() != bitc::ENTER_SUBBLOCK) 6170b57cec5SDimitry Andric return reportError("Invalid record at top-level"); 6180b57cec5SDimitry Andric 6190b57cec5SDimitry Andric Expected<unsigned> MaybeBlockID = Stream.ReadSubBlockID(); 6200b57cec5SDimitry Andric if (!MaybeBlockID) 6210b57cec5SDimitry Andric return MaybeBlockID.takeError(); 6220b57cec5SDimitry Andric 6230b57cec5SDimitry Andric if (Error E = parseBlock(MaybeBlockID.get(), 0, O, CheckHash)) 6240b57cec5SDimitry Andric return E; 6250b57cec5SDimitry Andric ++NumTopBlocks; 6260b57cec5SDimitry Andric } 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric return Error::success(); 6290b57cec5SDimitry Andric } 6300b57cec5SDimitry Andric 6310b57cec5SDimitry Andric void BitcodeAnalyzer::printStats(BCDumpOptions O, 632bdd1243dSDimitry Andric std::optional<StringRef> Filename) { 6330b57cec5SDimitry Andric uint64_t BufferSizeBits = Stream.getBitcodeBytes().size() * CHAR_BIT; 6340b57cec5SDimitry Andric // Print a summary of the read file. 6350b57cec5SDimitry Andric O.OS << "Summary "; 6360b57cec5SDimitry Andric if (Filename) 6370b57cec5SDimitry Andric O.OS << "of " << Filename->data() << ":\n"; 6380b57cec5SDimitry Andric O.OS << " Total size: "; 6390b57cec5SDimitry Andric printSize(O.OS, BufferSizeBits); 6400b57cec5SDimitry Andric O.OS << "\n"; 6410b57cec5SDimitry Andric O.OS << " Stream type: "; 6420b57cec5SDimitry Andric switch (CurStreamType) { 6430b57cec5SDimitry Andric case UnknownBitstream: 6440b57cec5SDimitry Andric O.OS << "unknown\n"; 6450b57cec5SDimitry Andric break; 6460b57cec5SDimitry Andric case LLVMIRBitstream: 6470b57cec5SDimitry Andric O.OS << "LLVM IR\n"; 6480b57cec5SDimitry Andric break; 6490b57cec5SDimitry Andric case ClangSerializedASTBitstream: 6500b57cec5SDimitry Andric O.OS << "Clang Serialized AST\n"; 6510b57cec5SDimitry Andric break; 6520b57cec5SDimitry Andric case ClangSerializedDiagnosticsBitstream: 6530b57cec5SDimitry Andric O.OS << "Clang Serialized Diagnostics\n"; 6540b57cec5SDimitry Andric break; 6558bcb0991SDimitry Andric case LLVMBitstreamRemarks: 6568bcb0991SDimitry Andric O.OS << "LLVM Remarks\n"; 6578bcb0991SDimitry Andric break; 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric O.OS << " # Toplevel Blocks: " << NumTopBlocks << "\n"; 6600b57cec5SDimitry Andric O.OS << "\n"; 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric // Emit per-block stats. 6630b57cec5SDimitry Andric O.OS << "Per-block Summary:\n"; 6640eae32dcSDimitry Andric for (const auto &Stat : BlockIDStats) { 6650eae32dcSDimitry Andric O.OS << " Block ID #" << Stat.first; 666bdd1243dSDimitry Andric if (std::optional<const char *> BlockName = 6670eae32dcSDimitry Andric GetBlockName(Stat.first, BlockInfo, CurStreamType)) 6680b57cec5SDimitry Andric O.OS << " (" << *BlockName << ")"; 6690b57cec5SDimitry Andric O.OS << ":\n"; 6700b57cec5SDimitry Andric 6710eae32dcSDimitry Andric const PerBlockIDStats &Stats = Stat.second; 6720b57cec5SDimitry Andric O.OS << " Num Instances: " << Stats.NumInstances << "\n"; 6730b57cec5SDimitry Andric O.OS << " Total Size: "; 6740b57cec5SDimitry Andric printSize(O.OS, Stats.NumBits); 6750b57cec5SDimitry Andric O.OS << "\n"; 6760b57cec5SDimitry Andric double pct = (Stats.NumBits * 100.0) / BufferSizeBits; 6770b57cec5SDimitry Andric O.OS << " Percent of file: " << format("%2.4f%%", pct) << "\n"; 6780b57cec5SDimitry Andric if (Stats.NumInstances > 1) { 6790b57cec5SDimitry Andric O.OS << " Average Size: "; 6800b57cec5SDimitry Andric printSize(O.OS, Stats.NumBits / (double)Stats.NumInstances); 6810b57cec5SDimitry Andric O.OS << "\n"; 6820b57cec5SDimitry Andric O.OS << " Tot/Avg SubBlocks: " << Stats.NumSubBlocks << "/" 6830b57cec5SDimitry Andric << Stats.NumSubBlocks / (double)Stats.NumInstances << "\n"; 6840b57cec5SDimitry Andric O.OS << " Tot/Avg Abbrevs: " << Stats.NumAbbrevs << "/" 6850b57cec5SDimitry Andric << Stats.NumAbbrevs / (double)Stats.NumInstances << "\n"; 6860b57cec5SDimitry Andric O.OS << " Tot/Avg Records: " << Stats.NumRecords << "/" 6870b57cec5SDimitry Andric << Stats.NumRecords / (double)Stats.NumInstances << "\n"; 6880b57cec5SDimitry Andric } else { 6890b57cec5SDimitry Andric O.OS << " Num SubBlocks: " << Stats.NumSubBlocks << "\n"; 6900b57cec5SDimitry Andric O.OS << " Num Abbrevs: " << Stats.NumAbbrevs << "\n"; 6910b57cec5SDimitry Andric O.OS << " Num Records: " << Stats.NumRecords << "\n"; 6920b57cec5SDimitry Andric } 6930b57cec5SDimitry Andric if (Stats.NumRecords) { 6940b57cec5SDimitry Andric double pct = (Stats.NumAbbreviatedRecords * 100.0) / Stats.NumRecords; 6950b57cec5SDimitry Andric O.OS << " Percent Abbrevs: " << format("%2.4f%%", pct) << "\n"; 6960b57cec5SDimitry Andric } 6970b57cec5SDimitry Andric O.OS << "\n"; 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric // Print a histogram of the codes we see. 7000b57cec5SDimitry Andric if (O.Histogram && !Stats.CodeFreq.empty()) { 7010b57cec5SDimitry Andric std::vector<std::pair<unsigned, unsigned>> FreqPairs; // <freq,code> 7020b57cec5SDimitry Andric for (unsigned i = 0, e = Stats.CodeFreq.size(); i != e; ++i) 7030b57cec5SDimitry Andric if (unsigned Freq = Stats.CodeFreq[i].NumInstances) 7040b57cec5SDimitry Andric FreqPairs.push_back(std::make_pair(Freq, i)); 7050b57cec5SDimitry Andric llvm::stable_sort(FreqPairs); 7060b57cec5SDimitry Andric std::reverse(FreqPairs.begin(), FreqPairs.end()); 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric O.OS << "\tRecord Histogram:\n"; 7090b57cec5SDimitry Andric O.OS << "\t\t Count # Bits b/Rec % Abv Record Kind\n"; 7100eae32dcSDimitry Andric for (const auto &FreqPair : FreqPairs) { 7110eae32dcSDimitry Andric const PerRecordStats &RecStats = Stats.CodeFreq[FreqPair.second]; 7120b57cec5SDimitry Andric 7130b57cec5SDimitry Andric O.OS << format("\t\t%7d %9lu", RecStats.NumInstances, 7140b57cec5SDimitry Andric (unsigned long)RecStats.TotalBits); 7150b57cec5SDimitry Andric 7160b57cec5SDimitry Andric if (RecStats.NumInstances > 1) 7170b57cec5SDimitry Andric O.OS << format(" %9.1f", 7180b57cec5SDimitry Andric (double)RecStats.TotalBits / RecStats.NumInstances); 7190b57cec5SDimitry Andric else 7200b57cec5SDimitry Andric O.OS << " "; 7210b57cec5SDimitry Andric 7220b57cec5SDimitry Andric if (RecStats.NumAbbrev) 7230b57cec5SDimitry Andric O.OS << format(" %7.2f", (double)RecStats.NumAbbrev / 7240b57cec5SDimitry Andric RecStats.NumInstances * 100); 7250b57cec5SDimitry Andric else 7260b57cec5SDimitry Andric O.OS << " "; 7270b57cec5SDimitry Andric 7280b57cec5SDimitry Andric O.OS << " "; 729bdd1243dSDimitry Andric if (std::optional<const char *> CodeName = GetCodeName( 7300eae32dcSDimitry Andric FreqPair.second, Stat.first, BlockInfo, CurStreamType)) 7310b57cec5SDimitry Andric O.OS << *CodeName << "\n"; 7320b57cec5SDimitry Andric else 7330eae32dcSDimitry Andric O.OS << "UnknownCode" << FreqPair.second << "\n"; 7340b57cec5SDimitry Andric } 7350b57cec5SDimitry Andric O.OS << "\n"; 7360b57cec5SDimitry Andric } 7370b57cec5SDimitry Andric } 7380b57cec5SDimitry Andric } 7390b57cec5SDimitry Andric 7400b57cec5SDimitry Andric Error BitcodeAnalyzer::parseBlock(unsigned BlockID, unsigned IndentLevel, 741bdd1243dSDimitry Andric std::optional<BCDumpOptions> O, 742bdd1243dSDimitry Andric std::optional<StringRef> CheckHash) { 7430b57cec5SDimitry Andric std::string Indent(IndentLevel * 2, ' '); 7440b57cec5SDimitry Andric uint64_t BlockBitStart = Stream.GetCurrentBitNo(); 7450b57cec5SDimitry Andric 7460b57cec5SDimitry Andric // Get the statistics for this BlockID. 7470b57cec5SDimitry Andric PerBlockIDStats &BlockStats = BlockIDStats[BlockID]; 7480b57cec5SDimitry Andric 7490b57cec5SDimitry Andric BlockStats.NumInstances++; 7500b57cec5SDimitry Andric 7510b57cec5SDimitry Andric // BLOCKINFO is a special part of the stream. 75281ad6265SDimitry Andric bool DumpRecords = O.has_value(); 7530b57cec5SDimitry Andric if (BlockID == bitc::BLOCKINFO_BLOCK_ID) { 754349cc55cSDimitry Andric if (O && !O->DumpBlockinfo) 7550b57cec5SDimitry Andric O->OS << Indent << "<BLOCKINFO_BLOCK/>\n"; 756bdd1243dSDimitry Andric std::optional<BitstreamBlockInfo> NewBlockInfo; 757349cc55cSDimitry Andric if (Error E = Stream.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true) 758349cc55cSDimitry Andric .moveInto(NewBlockInfo)) 759349cc55cSDimitry Andric return E; 7600b57cec5SDimitry Andric if (!NewBlockInfo) 7610b57cec5SDimitry Andric return reportError("Malformed BlockInfoBlock"); 7620b57cec5SDimitry Andric BlockInfo = std::move(*NewBlockInfo); 7630b57cec5SDimitry Andric if (Error Err = Stream.JumpToBit(BlockBitStart)) 7640b57cec5SDimitry Andric return Err; 7650b57cec5SDimitry Andric // It's not really interesting to dump the contents of the blockinfo 766349cc55cSDimitry Andric // block, so only do it if the user explicitly requests it. 767349cc55cSDimitry Andric DumpRecords = O && O->DumpBlockinfo; 7680b57cec5SDimitry Andric } 7690b57cec5SDimitry Andric 7700b57cec5SDimitry Andric unsigned NumWords = 0; 7710b57cec5SDimitry Andric if (Error Err = Stream.EnterSubBlock(BlockID, &NumWords)) 7720b57cec5SDimitry Andric return Err; 7730b57cec5SDimitry Andric 7740b57cec5SDimitry Andric // Keep it for later, when we see a MODULE_HASH record 7750b57cec5SDimitry Andric uint64_t BlockEntryPos = Stream.getCurrentByteNo(); 7760b57cec5SDimitry Andric 777bdd1243dSDimitry Andric std::optional<const char *> BlockName; 7780b57cec5SDimitry Andric if (DumpRecords) { 7790b57cec5SDimitry Andric O->OS << Indent << "<"; 7800b57cec5SDimitry Andric if ((BlockName = GetBlockName(BlockID, BlockInfo, CurStreamType))) 7810b57cec5SDimitry Andric O->OS << *BlockName; 7820b57cec5SDimitry Andric else 7830b57cec5SDimitry Andric O->OS << "UnknownBlock" << BlockID; 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric if (!O->Symbolic && BlockName) 7860b57cec5SDimitry Andric O->OS << " BlockID=" << BlockID; 7870b57cec5SDimitry Andric 7880b57cec5SDimitry Andric O->OS << " NumWords=" << NumWords 7890b57cec5SDimitry Andric << " BlockCodeSize=" << Stream.getAbbrevIDWidth() << ">\n"; 7900b57cec5SDimitry Andric } 7910b57cec5SDimitry Andric 7920b57cec5SDimitry Andric SmallVector<uint64_t, 64> Record; 7930b57cec5SDimitry Andric 7940b57cec5SDimitry Andric // Keep the offset to the metadata index if seen. 7950b57cec5SDimitry Andric uint64_t MetadataIndexOffset = 0; 7960b57cec5SDimitry Andric 7970b57cec5SDimitry Andric // Read all the records for this block. 79804eeddc0SDimitry Andric while (true) { 7990b57cec5SDimitry Andric if (Stream.AtEndOfStream()) 8000b57cec5SDimitry Andric return reportError("Premature end of bitstream"); 8010b57cec5SDimitry Andric 8020b57cec5SDimitry Andric uint64_t RecordStartBit = Stream.GetCurrentBitNo(); 8030b57cec5SDimitry Andric 804349cc55cSDimitry Andric BitstreamEntry Entry; 805349cc55cSDimitry Andric if (Error E = Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs) 806349cc55cSDimitry Andric .moveInto(Entry)) 807349cc55cSDimitry Andric return E; 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric switch (Entry.Kind) { 8100b57cec5SDimitry Andric case BitstreamEntry::Error: 8110b57cec5SDimitry Andric return reportError("malformed bitcode file"); 8120b57cec5SDimitry Andric case BitstreamEntry::EndBlock: { 8130b57cec5SDimitry Andric uint64_t BlockBitEnd = Stream.GetCurrentBitNo(); 8140b57cec5SDimitry Andric BlockStats.NumBits += BlockBitEnd - BlockBitStart; 8150b57cec5SDimitry Andric if (DumpRecords) { 8160b57cec5SDimitry Andric O->OS << Indent << "</"; 8170b57cec5SDimitry Andric if (BlockName) 8180b57cec5SDimitry Andric O->OS << *BlockName << ">\n"; 8190b57cec5SDimitry Andric else 8200b57cec5SDimitry Andric O->OS << "UnknownBlock" << BlockID << ">\n"; 8210b57cec5SDimitry Andric } 8220b57cec5SDimitry Andric return Error::success(); 8230b57cec5SDimitry Andric } 8240b57cec5SDimitry Andric 8250b57cec5SDimitry Andric case BitstreamEntry::SubBlock: { 8260b57cec5SDimitry Andric uint64_t SubBlockBitStart = Stream.GetCurrentBitNo(); 8270b57cec5SDimitry Andric if (Error E = parseBlock(Entry.ID, IndentLevel + 1, O, CheckHash)) 8280b57cec5SDimitry Andric return E; 8290b57cec5SDimitry Andric ++BlockStats.NumSubBlocks; 8300b57cec5SDimitry Andric uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo(); 8310b57cec5SDimitry Andric 8320b57cec5SDimitry Andric // Don't include subblock sizes in the size of this block. 8330b57cec5SDimitry Andric BlockBitStart += SubBlockBitEnd - SubBlockBitStart; 8340b57cec5SDimitry Andric continue; 8350b57cec5SDimitry Andric } 8360b57cec5SDimitry Andric case BitstreamEntry::Record: 8370b57cec5SDimitry Andric // The interesting case. 8380b57cec5SDimitry Andric break; 8390b57cec5SDimitry Andric } 8400b57cec5SDimitry Andric 8410b57cec5SDimitry Andric if (Entry.ID == bitc::DEFINE_ABBREV) { 8420b57cec5SDimitry Andric if (Error Err = Stream.ReadAbbrevRecord()) 8430b57cec5SDimitry Andric return Err; 8440b57cec5SDimitry Andric ++BlockStats.NumAbbrevs; 8450b57cec5SDimitry Andric continue; 8460b57cec5SDimitry Andric } 8470b57cec5SDimitry Andric 8480b57cec5SDimitry Andric Record.clear(); 8490b57cec5SDimitry Andric 8500b57cec5SDimitry Andric ++BlockStats.NumRecords; 8510b57cec5SDimitry Andric 8520b57cec5SDimitry Andric StringRef Blob; 8530b57cec5SDimitry Andric uint64_t CurrentRecordPos = Stream.GetCurrentBitNo(); 854349cc55cSDimitry Andric unsigned Code; 855349cc55cSDimitry Andric if (Error E = Stream.readRecord(Entry.ID, Record, &Blob).moveInto(Code)) 856349cc55cSDimitry Andric return E; 8570b57cec5SDimitry Andric 8580b57cec5SDimitry Andric // Increment the # occurrences of this code. 8590b57cec5SDimitry Andric if (BlockStats.CodeFreq.size() <= Code) 8600b57cec5SDimitry Andric BlockStats.CodeFreq.resize(Code + 1); 8610b57cec5SDimitry Andric BlockStats.CodeFreq[Code].NumInstances++; 8620b57cec5SDimitry Andric BlockStats.CodeFreq[Code].TotalBits += 8630b57cec5SDimitry Andric Stream.GetCurrentBitNo() - RecordStartBit; 8640b57cec5SDimitry Andric if (Entry.ID != bitc::UNABBREV_RECORD) { 8650b57cec5SDimitry Andric BlockStats.CodeFreq[Code].NumAbbrev++; 8660b57cec5SDimitry Andric ++BlockStats.NumAbbreviatedRecords; 8670b57cec5SDimitry Andric } 8680b57cec5SDimitry Andric 8690b57cec5SDimitry Andric if (DumpRecords) { 8700b57cec5SDimitry Andric O->OS << Indent << " <"; 871bdd1243dSDimitry Andric std::optional<const char *> CodeName = 8720b57cec5SDimitry Andric GetCodeName(Code, BlockID, BlockInfo, CurStreamType); 8730b57cec5SDimitry Andric if (CodeName) 8740b57cec5SDimitry Andric O->OS << *CodeName; 8750b57cec5SDimitry Andric else 8760b57cec5SDimitry Andric O->OS << "UnknownCode" << Code; 8770b57cec5SDimitry Andric if (!O->Symbolic && CodeName) 8780b57cec5SDimitry Andric O->OS << " codeid=" << Code; 8790b57cec5SDimitry Andric const BitCodeAbbrev *Abbv = nullptr; 8800b57cec5SDimitry Andric if (Entry.ID != bitc::UNABBREV_RECORD) { 88181ad6265SDimitry Andric Expected<const BitCodeAbbrev *> MaybeAbbv = Stream.getAbbrev(Entry.ID); 88281ad6265SDimitry Andric if (!MaybeAbbv) 88381ad6265SDimitry Andric return MaybeAbbv.takeError(); 88481ad6265SDimitry Andric Abbv = MaybeAbbv.get(); 8850b57cec5SDimitry Andric O->OS << " abbrevid=" << Entry.ID; 8860b57cec5SDimitry Andric } 8870b57cec5SDimitry Andric 8880b57cec5SDimitry Andric for (unsigned i = 0, e = Record.size(); i != e; ++i) 8890b57cec5SDimitry Andric O->OS << " op" << i << "=" << (int64_t)Record[i]; 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andric // If we found a metadata index, let's verify that we had an offset 8920b57cec5SDimitry Andric // before and validate its forward reference offset was correct! 8930b57cec5SDimitry Andric if (BlockID == bitc::METADATA_BLOCK_ID) { 8940b57cec5SDimitry Andric if (Code == bitc::METADATA_INDEX_OFFSET) { 8950b57cec5SDimitry Andric if (Record.size() != 2) 8960b57cec5SDimitry Andric O->OS << "(Invalid record)"; 8970b57cec5SDimitry Andric else { 8980b57cec5SDimitry Andric auto Offset = Record[0] + (Record[1] << 32); 8990b57cec5SDimitry Andric MetadataIndexOffset = Stream.GetCurrentBitNo() + Offset; 9000b57cec5SDimitry Andric } 9010b57cec5SDimitry Andric } 9020b57cec5SDimitry Andric if (Code == bitc::METADATA_INDEX) { 9030b57cec5SDimitry Andric O->OS << " (offset "; 9040b57cec5SDimitry Andric if (MetadataIndexOffset == RecordStartBit) 9050b57cec5SDimitry Andric O->OS << "match)"; 9060b57cec5SDimitry Andric else 9070b57cec5SDimitry Andric O->OS << "mismatch: " << MetadataIndexOffset << " vs " 9080b57cec5SDimitry Andric << RecordStartBit << ")"; 9090b57cec5SDimitry Andric } 9100b57cec5SDimitry Andric } 9110b57cec5SDimitry Andric 9120b57cec5SDimitry Andric // If we found a module hash, let's verify that it matches! 9130b57cec5SDimitry Andric if (BlockID == bitc::MODULE_BLOCK_ID && Code == bitc::MODULE_CODE_HASH && 91481ad6265SDimitry Andric CheckHash) { 9150b57cec5SDimitry Andric if (Record.size() != 5) 9160b57cec5SDimitry Andric O->OS << " (invalid)"; 9170b57cec5SDimitry Andric else { 9180b57cec5SDimitry Andric // Recompute the hash and compare it to the one in the bitcode 9190b57cec5SDimitry Andric SHA1 Hasher; 92081ad6265SDimitry Andric std::array<uint8_t, 20> Hash; 9210b57cec5SDimitry Andric Hasher.update(*CheckHash); 9220b57cec5SDimitry Andric { 9230b57cec5SDimitry Andric int BlockSize = (CurrentRecordPos / 8) - BlockEntryPos; 9240b57cec5SDimitry Andric auto Ptr = Stream.getPointerToByte(BlockEntryPos, BlockSize); 9250b57cec5SDimitry Andric Hasher.update(ArrayRef<uint8_t>(Ptr, BlockSize)); 9260b57cec5SDimitry Andric Hash = Hasher.result(); 9270b57cec5SDimitry Andric } 92881ad6265SDimitry Andric std::array<uint8_t, 20> RecordedHash; 9290b57cec5SDimitry Andric int Pos = 0; 9300b57cec5SDimitry Andric for (auto &Val : Record) { 9310b57cec5SDimitry Andric assert(!(Val >> 32) && "Unexpected high bits set"); 9325ffd83dbSDimitry Andric support::endian::write32be(&RecordedHash[Pos], Val); 9335ffd83dbSDimitry Andric Pos += 4; 9340b57cec5SDimitry Andric } 93581ad6265SDimitry Andric if (Hash == RecordedHash) 9360b57cec5SDimitry Andric O->OS << " (match)"; 9370b57cec5SDimitry Andric else 9380b57cec5SDimitry Andric O->OS << " (!mismatch!)"; 9390b57cec5SDimitry Andric } 9400b57cec5SDimitry Andric } 9410b57cec5SDimitry Andric 9420b57cec5SDimitry Andric O->OS << "/>"; 9430b57cec5SDimitry Andric 9440b57cec5SDimitry Andric if (Abbv) { 9450b57cec5SDimitry Andric for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) { 9460b57cec5SDimitry Andric const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); 9470b57cec5SDimitry Andric if (!Op.isEncoding() || Op.getEncoding() != BitCodeAbbrevOp::Array) 9480b57cec5SDimitry Andric continue; 9490b57cec5SDimitry Andric assert(i + 2 == e && "Array op not second to last"); 9500b57cec5SDimitry Andric std::string Str; 9510b57cec5SDimitry Andric bool ArrayIsPrintable = true; 9520b57cec5SDimitry Andric for (unsigned j = i - 1, je = Record.size(); j != je; ++j) { 9530b57cec5SDimitry Andric if (!isPrint(static_cast<unsigned char>(Record[j]))) { 9540b57cec5SDimitry Andric ArrayIsPrintable = false; 9550b57cec5SDimitry Andric break; 9560b57cec5SDimitry Andric } 9570b57cec5SDimitry Andric Str += (char)Record[j]; 9580b57cec5SDimitry Andric } 9590b57cec5SDimitry Andric if (ArrayIsPrintable) 9600b57cec5SDimitry Andric O->OS << " record string = '" << Str << "'"; 9610b57cec5SDimitry Andric break; 9620b57cec5SDimitry Andric } 9630b57cec5SDimitry Andric } 9640b57cec5SDimitry Andric 9650b57cec5SDimitry Andric if (Blob.data()) { 9660b57cec5SDimitry Andric if (canDecodeBlob(Code, BlockID)) { 9670b57cec5SDimitry Andric if (Error E = decodeMetadataStringsBlob(Indent, Record, Blob, O->OS)) 9680b57cec5SDimitry Andric return E; 9690b57cec5SDimitry Andric } else { 9700b57cec5SDimitry Andric O->OS << " blob data = "; 9710b57cec5SDimitry Andric if (O->ShowBinaryBlobs) { 9720b57cec5SDimitry Andric O->OS << "'"; 9730b57cec5SDimitry Andric O->OS.write_escaped(Blob, /*hex=*/true) << "'"; 9740b57cec5SDimitry Andric } else { 9750b57cec5SDimitry Andric bool BlobIsPrintable = true; 9764824e7fdSDimitry Andric for (char C : Blob) 9774824e7fdSDimitry Andric if (!isPrint(static_cast<unsigned char>(C))) { 9780b57cec5SDimitry Andric BlobIsPrintable = false; 9790b57cec5SDimitry Andric break; 9800b57cec5SDimitry Andric } 9810b57cec5SDimitry Andric 9820b57cec5SDimitry Andric if (BlobIsPrintable) 9830b57cec5SDimitry Andric O->OS << "'" << Blob << "'"; 9840b57cec5SDimitry Andric else 9850b57cec5SDimitry Andric O->OS << "unprintable, " << Blob.size() << " bytes."; 9860b57cec5SDimitry Andric } 9870b57cec5SDimitry Andric } 9880b57cec5SDimitry Andric } 9890b57cec5SDimitry Andric 9900b57cec5SDimitry Andric O->OS << "\n"; 9910b57cec5SDimitry Andric } 9920b57cec5SDimitry Andric 9930b57cec5SDimitry Andric // Make sure that we can skip the current record. 9940b57cec5SDimitry Andric if (Error Err = Stream.JumpToBit(CurrentRecordPos)) 9950b57cec5SDimitry Andric return Err; 9960b57cec5SDimitry Andric if (Expected<unsigned> Skipped = Stream.skipRecord(Entry.ID)) 9970b57cec5SDimitry Andric ; // Do nothing. 9980b57cec5SDimitry Andric else 9990b57cec5SDimitry Andric return Skipped.takeError(); 10000b57cec5SDimitry Andric } 10010b57cec5SDimitry Andric } 10020b57cec5SDimitry Andric 1003