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