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) 133*5ffd83dbSDimitry Andric STRINGIFY_CODE(MODULE_CODE, DEPLIB) // Deprecated, present in old bitcode 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) 308*5ffd83dbSDimitry Andric STRINGIFY_CODE(FS, BLOCK_COUNT) 309*5ffd83dbSDimitry Andric STRINGIFY_CODE(FS, PARAM_ACCESS) 3100b57cec5SDimitry Andric } 3110b57cec5SDimitry Andric case bitc::METADATA_ATTACHMENT_ID: 3120b57cec5SDimitry Andric switch (CodeID) { 3130b57cec5SDimitry Andric default: 3140b57cec5SDimitry Andric return None; 3150b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, ATTACHMENT) 3160b57cec5SDimitry Andric } 3170b57cec5SDimitry Andric case bitc::METADATA_BLOCK_ID: 3180b57cec5SDimitry Andric switch (CodeID) { 3190b57cec5SDimitry Andric default: 3200b57cec5SDimitry Andric return None; 3210b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, STRING_OLD) 3220b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, VALUE) 3230b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, NODE) 3240b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, NAME) 3250b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, DISTINCT_NODE) 3260b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, KIND) // Older bitcode has it in a MODULE_BLOCK 3270b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, LOCATION) 3280b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, OLD_NODE) 3290b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, OLD_FN_NODE) 3300b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, NAMED_NODE) 3310b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, GENERIC_DEBUG) 3320b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, SUBRANGE) 3330b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, ENUMERATOR) 3340b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, BASIC_TYPE) 3350b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, FILE) 3360b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, DERIVED_TYPE) 3370b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, COMPOSITE_TYPE) 3380b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, SUBROUTINE_TYPE) 3390b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, COMPILE_UNIT) 3400b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, SUBPROGRAM) 3410b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, LEXICAL_BLOCK) 3420b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, LEXICAL_BLOCK_FILE) 3430b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, NAMESPACE) 3440b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, TEMPLATE_TYPE) 3450b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, TEMPLATE_VALUE) 3460b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, GLOBAL_VAR) 3470b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, LOCAL_VAR) 3480b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, EXPRESSION) 3490b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, OBJC_PROPERTY) 3500b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, IMPORTED_ENTITY) 3510b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, MODULE) 3520b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, MACRO) 3530b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, MACRO_FILE) 3540b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, STRINGS) 3550b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, GLOBAL_DECL_ATTACHMENT) 3560b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, GLOBAL_VAR_EXPR) 3570b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, INDEX_OFFSET) 3580b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, INDEX) 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric case bitc::METADATA_KIND_BLOCK_ID: 3610b57cec5SDimitry Andric switch (CodeID) { 3620b57cec5SDimitry Andric default: 3630b57cec5SDimitry Andric return None; 3640b57cec5SDimitry Andric STRINGIFY_CODE(METADATA, KIND) 3650b57cec5SDimitry Andric } 3660b57cec5SDimitry Andric case bitc::USELIST_BLOCK_ID: 3670b57cec5SDimitry Andric switch (CodeID) { 3680b57cec5SDimitry Andric default: 3690b57cec5SDimitry Andric return None; 3700b57cec5SDimitry Andric case bitc::USELIST_CODE_DEFAULT: 3710b57cec5SDimitry Andric return "USELIST_CODE_DEFAULT"; 3720b57cec5SDimitry Andric case bitc::USELIST_CODE_BB: 3730b57cec5SDimitry Andric return "USELIST_CODE_BB"; 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric case bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID: 3770b57cec5SDimitry Andric switch (CodeID) { 3780b57cec5SDimitry Andric default: 3790b57cec5SDimitry Andric return None; 3800b57cec5SDimitry Andric case bitc::OPERAND_BUNDLE_TAG: 3810b57cec5SDimitry Andric return "OPERAND_BUNDLE_TAG"; 3820b57cec5SDimitry Andric } 3830b57cec5SDimitry Andric case bitc::STRTAB_BLOCK_ID: 3840b57cec5SDimitry Andric switch (CodeID) { 3850b57cec5SDimitry Andric default: 3860b57cec5SDimitry Andric return None; 3870b57cec5SDimitry Andric case bitc::STRTAB_BLOB: 3880b57cec5SDimitry Andric return "BLOB"; 3890b57cec5SDimitry Andric } 3900b57cec5SDimitry Andric case bitc::SYMTAB_BLOCK_ID: 3910b57cec5SDimitry Andric switch (CodeID) { 3920b57cec5SDimitry Andric default: 3930b57cec5SDimitry Andric return None; 3940b57cec5SDimitry Andric case bitc::SYMTAB_BLOB: 3950b57cec5SDimitry Andric return "BLOB"; 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric } 3980b57cec5SDimitry Andric #undef STRINGIFY_CODE 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric static void printSize(raw_ostream &OS, double Bits) { 4020b57cec5SDimitry Andric OS << format("%.2f/%.2fB/%luW", Bits, Bits / 8, (unsigned long)(Bits / 32)); 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric static void printSize(raw_ostream &OS, uint64_t Bits) { 4050b57cec5SDimitry Andric OS << format("%lub/%.2fB/%luW", (unsigned long)Bits, (double)Bits / 8, 4060b57cec5SDimitry Andric (unsigned long)(Bits / 32)); 4070b57cec5SDimitry Andric } 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric static Expected<CurStreamTypeType> ReadSignature(BitstreamCursor &Stream) { 4100b57cec5SDimitry Andric auto tryRead = [&Stream](char &Dest, size_t size) -> Error { 4110b57cec5SDimitry Andric if (Expected<SimpleBitstreamCursor::word_t> MaybeWord = Stream.Read(size)) 4120b57cec5SDimitry Andric Dest = MaybeWord.get(); 4130b57cec5SDimitry Andric else 4140b57cec5SDimitry Andric return MaybeWord.takeError(); 4150b57cec5SDimitry Andric return Error::success(); 4160b57cec5SDimitry Andric }; 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric char Signature[6]; 4190b57cec5SDimitry Andric if (Error Err = tryRead(Signature[0], 8)) 4200b57cec5SDimitry Andric return std::move(Err); 4210b57cec5SDimitry Andric if (Error Err = tryRead(Signature[1], 8)) 4220b57cec5SDimitry Andric return std::move(Err); 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric // Autodetect the file contents, if it is one we know. 4250b57cec5SDimitry Andric if (Signature[0] == 'C' && Signature[1] == 'P') { 4260b57cec5SDimitry Andric if (Error Err = tryRead(Signature[2], 8)) 4270b57cec5SDimitry Andric return std::move(Err); 4280b57cec5SDimitry Andric if (Error Err = tryRead(Signature[3], 8)) 4290b57cec5SDimitry Andric return std::move(Err); 4300b57cec5SDimitry Andric if (Signature[2] == 'C' && Signature[3] == 'H') 4310b57cec5SDimitry Andric return ClangSerializedASTBitstream; 4320b57cec5SDimitry Andric } else if (Signature[0] == 'D' && Signature[1] == 'I') { 4330b57cec5SDimitry Andric if (Error Err = tryRead(Signature[2], 8)) 4340b57cec5SDimitry Andric return std::move(Err); 4350b57cec5SDimitry Andric if (Error Err = tryRead(Signature[3], 8)) 4360b57cec5SDimitry Andric return std::move(Err); 4370b57cec5SDimitry Andric if (Signature[2] == 'A' && Signature[3] == 'G') 4380b57cec5SDimitry Andric return ClangSerializedDiagnosticsBitstream; 4398bcb0991SDimitry Andric } else if (Signature[0] == 'R' && Signature[1] == 'M') { 4408bcb0991SDimitry Andric if (Error Err = tryRead(Signature[2], 8)) 4418bcb0991SDimitry Andric return std::move(Err); 4428bcb0991SDimitry Andric if (Error Err = tryRead(Signature[3], 8)) 4438bcb0991SDimitry Andric return std::move(Err); 4448bcb0991SDimitry Andric if (Signature[2] == 'R' && Signature[3] == 'K') 4458bcb0991SDimitry Andric return LLVMBitstreamRemarks; 4460b57cec5SDimitry Andric } else { 4470b57cec5SDimitry Andric if (Error Err = tryRead(Signature[2], 4)) 4480b57cec5SDimitry Andric return std::move(Err); 4490b57cec5SDimitry Andric if (Error Err = tryRead(Signature[3], 4)) 4500b57cec5SDimitry Andric return std::move(Err); 4510b57cec5SDimitry Andric if (Error Err = tryRead(Signature[4], 4)) 4520b57cec5SDimitry Andric return std::move(Err); 4530b57cec5SDimitry Andric if (Error Err = tryRead(Signature[5], 4)) 4540b57cec5SDimitry Andric return std::move(Err); 4550b57cec5SDimitry Andric if (Signature[0] == 'B' && Signature[1] == 'C' && Signature[2] == 0x0 && 4560b57cec5SDimitry Andric Signature[3] == 0xC && Signature[4] == 0xE && Signature[5] == 0xD) 4570b57cec5SDimitry Andric return LLVMIRBitstream; 4580b57cec5SDimitry Andric } 4590b57cec5SDimitry Andric return UnknownBitstream; 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric 4620b57cec5SDimitry Andric static Expected<CurStreamTypeType> analyzeHeader(Optional<BCDumpOptions> O, 4630b57cec5SDimitry Andric BitstreamCursor &Stream) { 4640b57cec5SDimitry Andric ArrayRef<uint8_t> Bytes = Stream.getBitcodeBytes(); 4650b57cec5SDimitry Andric const unsigned char *BufPtr = (const unsigned char *)Bytes.data(); 4660b57cec5SDimitry Andric const unsigned char *EndBufPtr = BufPtr + Bytes.size(); 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric // If we have a wrapper header, parse it and ignore the non-bc file 4690b57cec5SDimitry Andric // contents. The magic number is 0x0B17C0DE stored in little endian. 4700b57cec5SDimitry Andric if (isBitcodeWrapper(BufPtr, EndBufPtr)) { 4710b57cec5SDimitry Andric if (Bytes.size() < BWH_HeaderSize) 4720b57cec5SDimitry Andric return reportError("Invalid bitcode wrapper header"); 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric if (O) { 4750b57cec5SDimitry Andric unsigned Magic = support::endian::read32le(&BufPtr[BWH_MagicField]); 4760b57cec5SDimitry Andric unsigned Version = support::endian::read32le(&BufPtr[BWH_VersionField]); 4770b57cec5SDimitry Andric unsigned Offset = support::endian::read32le(&BufPtr[BWH_OffsetField]); 4780b57cec5SDimitry Andric unsigned Size = support::endian::read32le(&BufPtr[BWH_SizeField]); 4790b57cec5SDimitry Andric unsigned CPUType = support::endian::read32le(&BufPtr[BWH_CPUTypeField]); 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric O->OS << "<BITCODE_WRAPPER_HEADER" 4820b57cec5SDimitry Andric << " Magic=" << format_hex(Magic, 10) 4830b57cec5SDimitry Andric << " Version=" << format_hex(Version, 10) 4840b57cec5SDimitry Andric << " Offset=" << format_hex(Offset, 10) 4850b57cec5SDimitry Andric << " Size=" << format_hex(Size, 10) 4860b57cec5SDimitry Andric << " CPUType=" << format_hex(CPUType, 10) << "/>\n"; 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric 4890b57cec5SDimitry Andric if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr, true)) 4900b57cec5SDimitry Andric return reportError("Invalid bitcode wrapper header"); 4910b57cec5SDimitry Andric } 4920b57cec5SDimitry Andric 4930b57cec5SDimitry Andric // Use the cursor modified by skipping the wrapper header. 4940b57cec5SDimitry Andric Stream = BitstreamCursor(ArrayRef<uint8_t>(BufPtr, EndBufPtr)); 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric return ReadSignature(Stream); 4970b57cec5SDimitry Andric } 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric static bool canDecodeBlob(unsigned Code, unsigned BlockID) { 5000b57cec5SDimitry Andric return BlockID == bitc::METADATA_BLOCK_ID && Code == bitc::METADATA_STRINGS; 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric Error BitcodeAnalyzer::decodeMetadataStringsBlob(StringRef Indent, 5040b57cec5SDimitry Andric ArrayRef<uint64_t> Record, 5050b57cec5SDimitry Andric StringRef Blob, 5060b57cec5SDimitry Andric raw_ostream &OS) { 5070b57cec5SDimitry Andric if (Blob.empty()) 5080b57cec5SDimitry Andric return reportError("Cannot decode empty blob."); 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric if (Record.size() != 2) 5110b57cec5SDimitry Andric return reportError( 5120b57cec5SDimitry Andric "Decoding metadata strings blob needs two record entries."); 5130b57cec5SDimitry Andric 5140b57cec5SDimitry Andric unsigned NumStrings = Record[0]; 5150b57cec5SDimitry Andric unsigned StringsOffset = Record[1]; 5160b57cec5SDimitry Andric OS << " num-strings = " << NumStrings << " {\n"; 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric StringRef Lengths = Blob.slice(0, StringsOffset); 5190b57cec5SDimitry Andric SimpleBitstreamCursor R(Lengths); 5200b57cec5SDimitry Andric StringRef Strings = Blob.drop_front(StringsOffset); 5210b57cec5SDimitry Andric do { 5220b57cec5SDimitry Andric if (R.AtEndOfStream()) 5230b57cec5SDimitry Andric return reportError("bad length"); 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric Expected<uint32_t> MaybeSize = R.ReadVBR(6); 5260b57cec5SDimitry Andric if (!MaybeSize) 5270b57cec5SDimitry Andric return MaybeSize.takeError(); 5280b57cec5SDimitry Andric uint32_t Size = MaybeSize.get(); 5290b57cec5SDimitry Andric if (Strings.size() < Size) 5300b57cec5SDimitry Andric return reportError("truncated chars"); 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andric OS << Indent << " '"; 5330b57cec5SDimitry Andric OS.write_escaped(Strings.slice(0, Size), /*hex=*/true); 5340b57cec5SDimitry Andric OS << "'\n"; 5350b57cec5SDimitry Andric Strings = Strings.drop_front(Size); 5360b57cec5SDimitry Andric } while (--NumStrings); 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric OS << Indent << " }"; 5390b57cec5SDimitry Andric return Error::success(); 5400b57cec5SDimitry Andric } 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric BitcodeAnalyzer::BitcodeAnalyzer(StringRef Buffer, 5430b57cec5SDimitry Andric Optional<StringRef> BlockInfoBuffer) 5440b57cec5SDimitry Andric : Stream(Buffer) { 5450b57cec5SDimitry Andric if (BlockInfoBuffer) 5460b57cec5SDimitry Andric BlockInfoStream.emplace(*BlockInfoBuffer); 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric Error BitcodeAnalyzer::analyze(Optional<BCDumpOptions> O, 5500b57cec5SDimitry Andric Optional<StringRef> CheckHash) { 5510b57cec5SDimitry Andric Expected<CurStreamTypeType> MaybeType = analyzeHeader(O, Stream); 5520b57cec5SDimitry Andric if (!MaybeType) 5530b57cec5SDimitry Andric return MaybeType.takeError(); 5540b57cec5SDimitry Andric else 5550b57cec5SDimitry Andric CurStreamType = *MaybeType; 5560b57cec5SDimitry Andric 5570b57cec5SDimitry Andric Stream.setBlockInfo(&BlockInfo); 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric // Read block info from BlockInfoStream, if specified. 5600b57cec5SDimitry Andric // The block info must be a top-level block. 5610b57cec5SDimitry Andric if (BlockInfoStream) { 5620b57cec5SDimitry Andric BitstreamCursor BlockInfoCursor(*BlockInfoStream); 5630b57cec5SDimitry Andric Expected<CurStreamTypeType> H = analyzeHeader(O, BlockInfoCursor); 5640b57cec5SDimitry Andric if (!H) 5650b57cec5SDimitry Andric return H.takeError(); 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric while (!BlockInfoCursor.AtEndOfStream()) { 5680b57cec5SDimitry Andric Expected<unsigned> MaybeCode = BlockInfoCursor.ReadCode(); 5690b57cec5SDimitry Andric if (!MaybeCode) 5700b57cec5SDimitry Andric return MaybeCode.takeError(); 5710b57cec5SDimitry Andric if (MaybeCode.get() != bitc::ENTER_SUBBLOCK) 5720b57cec5SDimitry Andric return reportError("Invalid record at top-level in block info file"); 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric Expected<unsigned> MaybeBlockID = BlockInfoCursor.ReadSubBlockID(); 5750b57cec5SDimitry Andric if (!MaybeBlockID) 5760b57cec5SDimitry Andric return MaybeBlockID.takeError(); 5770b57cec5SDimitry Andric if (MaybeBlockID.get() == bitc::BLOCKINFO_BLOCK_ID) { 5780b57cec5SDimitry Andric Expected<Optional<BitstreamBlockInfo>> MaybeNewBlockInfo = 5790b57cec5SDimitry Andric BlockInfoCursor.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true); 5800b57cec5SDimitry Andric if (!MaybeNewBlockInfo) 5810b57cec5SDimitry Andric return MaybeNewBlockInfo.takeError(); 5820b57cec5SDimitry Andric Optional<BitstreamBlockInfo> NewBlockInfo = 5830b57cec5SDimitry Andric std::move(MaybeNewBlockInfo.get()); 5840b57cec5SDimitry Andric if (!NewBlockInfo) 5850b57cec5SDimitry Andric return reportError("Malformed BlockInfoBlock in block info file"); 5860b57cec5SDimitry Andric BlockInfo = std::move(*NewBlockInfo); 5870b57cec5SDimitry Andric break; 5880b57cec5SDimitry Andric } 5890b57cec5SDimitry Andric 5900b57cec5SDimitry Andric if (Error Err = BlockInfoCursor.SkipBlock()) 5910b57cec5SDimitry Andric return Err; 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric } 5940b57cec5SDimitry Andric 5950b57cec5SDimitry Andric // Parse the top-level structure. We only allow blocks at the top-level. 5960b57cec5SDimitry Andric while (!Stream.AtEndOfStream()) { 5970b57cec5SDimitry Andric Expected<unsigned> MaybeCode = Stream.ReadCode(); 5980b57cec5SDimitry Andric if (!MaybeCode) 5990b57cec5SDimitry Andric return MaybeCode.takeError(); 6000b57cec5SDimitry Andric if (MaybeCode.get() != bitc::ENTER_SUBBLOCK) 6010b57cec5SDimitry Andric return reportError("Invalid record at top-level"); 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric Expected<unsigned> MaybeBlockID = Stream.ReadSubBlockID(); 6040b57cec5SDimitry Andric if (!MaybeBlockID) 6050b57cec5SDimitry Andric return MaybeBlockID.takeError(); 6060b57cec5SDimitry Andric 6070b57cec5SDimitry Andric if (Error E = parseBlock(MaybeBlockID.get(), 0, O, CheckHash)) 6080b57cec5SDimitry Andric return E; 6090b57cec5SDimitry Andric ++NumTopBlocks; 6100b57cec5SDimitry Andric } 6110b57cec5SDimitry Andric 6120b57cec5SDimitry Andric return Error::success(); 6130b57cec5SDimitry Andric } 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric void BitcodeAnalyzer::printStats(BCDumpOptions O, 6160b57cec5SDimitry Andric Optional<StringRef> Filename) { 6170b57cec5SDimitry Andric uint64_t BufferSizeBits = Stream.getBitcodeBytes().size() * CHAR_BIT; 6180b57cec5SDimitry Andric // Print a summary of the read file. 6190b57cec5SDimitry Andric O.OS << "Summary "; 6200b57cec5SDimitry Andric if (Filename) 6210b57cec5SDimitry Andric O.OS << "of " << Filename->data() << ":\n"; 6220b57cec5SDimitry Andric O.OS << " Total size: "; 6230b57cec5SDimitry Andric printSize(O.OS, BufferSizeBits); 6240b57cec5SDimitry Andric O.OS << "\n"; 6250b57cec5SDimitry Andric O.OS << " Stream type: "; 6260b57cec5SDimitry Andric switch (CurStreamType) { 6270b57cec5SDimitry Andric case UnknownBitstream: 6280b57cec5SDimitry Andric O.OS << "unknown\n"; 6290b57cec5SDimitry Andric break; 6300b57cec5SDimitry Andric case LLVMIRBitstream: 6310b57cec5SDimitry Andric O.OS << "LLVM IR\n"; 6320b57cec5SDimitry Andric break; 6330b57cec5SDimitry Andric case ClangSerializedASTBitstream: 6340b57cec5SDimitry Andric O.OS << "Clang Serialized AST\n"; 6350b57cec5SDimitry Andric break; 6360b57cec5SDimitry Andric case ClangSerializedDiagnosticsBitstream: 6370b57cec5SDimitry Andric O.OS << "Clang Serialized Diagnostics\n"; 6380b57cec5SDimitry Andric break; 6398bcb0991SDimitry Andric case LLVMBitstreamRemarks: 6408bcb0991SDimitry Andric O.OS << "LLVM Remarks\n"; 6418bcb0991SDimitry Andric break; 6420b57cec5SDimitry Andric } 6430b57cec5SDimitry Andric O.OS << " # Toplevel Blocks: " << NumTopBlocks << "\n"; 6440b57cec5SDimitry Andric O.OS << "\n"; 6450b57cec5SDimitry Andric 6460b57cec5SDimitry Andric // Emit per-block stats. 6470b57cec5SDimitry Andric O.OS << "Per-block Summary:\n"; 6480b57cec5SDimitry Andric for (std::map<unsigned, PerBlockIDStats>::iterator I = BlockIDStats.begin(), 6490b57cec5SDimitry Andric E = BlockIDStats.end(); 6500b57cec5SDimitry Andric I != E; ++I) { 6510b57cec5SDimitry Andric O.OS << " Block ID #" << I->first; 6520b57cec5SDimitry Andric if (Optional<const char *> BlockName = 6530b57cec5SDimitry Andric GetBlockName(I->first, BlockInfo, CurStreamType)) 6540b57cec5SDimitry Andric O.OS << " (" << *BlockName << ")"; 6550b57cec5SDimitry Andric O.OS << ":\n"; 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric const PerBlockIDStats &Stats = I->second; 6580b57cec5SDimitry Andric O.OS << " Num Instances: " << Stats.NumInstances << "\n"; 6590b57cec5SDimitry Andric O.OS << " Total Size: "; 6600b57cec5SDimitry Andric printSize(O.OS, Stats.NumBits); 6610b57cec5SDimitry Andric O.OS << "\n"; 6620b57cec5SDimitry Andric double pct = (Stats.NumBits * 100.0) / BufferSizeBits; 6630b57cec5SDimitry Andric O.OS << " Percent of file: " << format("%2.4f%%", pct) << "\n"; 6640b57cec5SDimitry Andric if (Stats.NumInstances > 1) { 6650b57cec5SDimitry Andric O.OS << " Average Size: "; 6660b57cec5SDimitry Andric printSize(O.OS, Stats.NumBits / (double)Stats.NumInstances); 6670b57cec5SDimitry Andric O.OS << "\n"; 6680b57cec5SDimitry Andric O.OS << " Tot/Avg SubBlocks: " << Stats.NumSubBlocks << "/" 6690b57cec5SDimitry Andric << Stats.NumSubBlocks / (double)Stats.NumInstances << "\n"; 6700b57cec5SDimitry Andric O.OS << " Tot/Avg Abbrevs: " << Stats.NumAbbrevs << "/" 6710b57cec5SDimitry Andric << Stats.NumAbbrevs / (double)Stats.NumInstances << "\n"; 6720b57cec5SDimitry Andric O.OS << " Tot/Avg Records: " << Stats.NumRecords << "/" 6730b57cec5SDimitry Andric << Stats.NumRecords / (double)Stats.NumInstances << "\n"; 6740b57cec5SDimitry Andric } else { 6750b57cec5SDimitry Andric O.OS << " Num SubBlocks: " << Stats.NumSubBlocks << "\n"; 6760b57cec5SDimitry Andric O.OS << " Num Abbrevs: " << Stats.NumAbbrevs << "\n"; 6770b57cec5SDimitry Andric O.OS << " Num Records: " << Stats.NumRecords << "\n"; 6780b57cec5SDimitry Andric } 6790b57cec5SDimitry Andric if (Stats.NumRecords) { 6800b57cec5SDimitry Andric double pct = (Stats.NumAbbreviatedRecords * 100.0) / Stats.NumRecords; 6810b57cec5SDimitry Andric O.OS << " Percent Abbrevs: " << format("%2.4f%%", pct) << "\n"; 6820b57cec5SDimitry Andric } 6830b57cec5SDimitry Andric O.OS << "\n"; 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric // Print a histogram of the codes we see. 6860b57cec5SDimitry Andric if (O.Histogram && !Stats.CodeFreq.empty()) { 6870b57cec5SDimitry Andric std::vector<std::pair<unsigned, unsigned>> FreqPairs; // <freq,code> 6880b57cec5SDimitry Andric for (unsigned i = 0, e = Stats.CodeFreq.size(); i != e; ++i) 6890b57cec5SDimitry Andric if (unsigned Freq = Stats.CodeFreq[i].NumInstances) 6900b57cec5SDimitry Andric FreqPairs.push_back(std::make_pair(Freq, i)); 6910b57cec5SDimitry Andric llvm::stable_sort(FreqPairs); 6920b57cec5SDimitry Andric std::reverse(FreqPairs.begin(), FreqPairs.end()); 6930b57cec5SDimitry Andric 6940b57cec5SDimitry Andric O.OS << "\tRecord Histogram:\n"; 6950b57cec5SDimitry Andric O.OS << "\t\t Count # Bits b/Rec % Abv Record Kind\n"; 6960b57cec5SDimitry Andric for (unsigned i = 0, e = FreqPairs.size(); i != e; ++i) { 6970b57cec5SDimitry Andric const PerRecordStats &RecStats = Stats.CodeFreq[FreqPairs[i].second]; 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric O.OS << format("\t\t%7d %9lu", RecStats.NumInstances, 7000b57cec5SDimitry Andric (unsigned long)RecStats.TotalBits); 7010b57cec5SDimitry Andric 7020b57cec5SDimitry Andric if (RecStats.NumInstances > 1) 7030b57cec5SDimitry Andric O.OS << format(" %9.1f", 7040b57cec5SDimitry Andric (double)RecStats.TotalBits / RecStats.NumInstances); 7050b57cec5SDimitry Andric else 7060b57cec5SDimitry Andric O.OS << " "; 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric if (RecStats.NumAbbrev) 7090b57cec5SDimitry Andric O.OS << format(" %7.2f", (double)RecStats.NumAbbrev / 7100b57cec5SDimitry Andric RecStats.NumInstances * 100); 7110b57cec5SDimitry Andric else 7120b57cec5SDimitry Andric O.OS << " "; 7130b57cec5SDimitry Andric 7140b57cec5SDimitry Andric O.OS << " "; 7150b57cec5SDimitry Andric if (Optional<const char *> CodeName = GetCodeName( 7160b57cec5SDimitry Andric FreqPairs[i].second, I->first, BlockInfo, CurStreamType)) 7170b57cec5SDimitry Andric O.OS << *CodeName << "\n"; 7180b57cec5SDimitry Andric else 7190b57cec5SDimitry Andric O.OS << "UnknownCode" << FreqPairs[i].second << "\n"; 7200b57cec5SDimitry Andric } 7210b57cec5SDimitry Andric O.OS << "\n"; 7220b57cec5SDimitry Andric } 7230b57cec5SDimitry Andric } 7240b57cec5SDimitry Andric } 7250b57cec5SDimitry Andric 7260b57cec5SDimitry Andric Error BitcodeAnalyzer::parseBlock(unsigned BlockID, unsigned IndentLevel, 7270b57cec5SDimitry Andric Optional<BCDumpOptions> O, 7280b57cec5SDimitry Andric Optional<StringRef> CheckHash) { 7290b57cec5SDimitry Andric std::string Indent(IndentLevel * 2, ' '); 7300b57cec5SDimitry Andric uint64_t BlockBitStart = Stream.GetCurrentBitNo(); 7310b57cec5SDimitry Andric 7320b57cec5SDimitry Andric // Get the statistics for this BlockID. 7330b57cec5SDimitry Andric PerBlockIDStats &BlockStats = BlockIDStats[BlockID]; 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric BlockStats.NumInstances++; 7360b57cec5SDimitry Andric 7370b57cec5SDimitry Andric // BLOCKINFO is a special part of the stream. 7380b57cec5SDimitry Andric bool DumpRecords = O.hasValue(); 7390b57cec5SDimitry Andric if (BlockID == bitc::BLOCKINFO_BLOCK_ID) { 7400b57cec5SDimitry Andric if (O) 7410b57cec5SDimitry Andric O->OS << Indent << "<BLOCKINFO_BLOCK/>\n"; 7420b57cec5SDimitry Andric Expected<Optional<BitstreamBlockInfo>> MaybeNewBlockInfo = 7430b57cec5SDimitry Andric Stream.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true); 7440b57cec5SDimitry Andric if (!MaybeNewBlockInfo) 7450b57cec5SDimitry Andric return MaybeNewBlockInfo.takeError(); 7460b57cec5SDimitry Andric Optional<BitstreamBlockInfo> NewBlockInfo = 7470b57cec5SDimitry Andric std::move(MaybeNewBlockInfo.get()); 7480b57cec5SDimitry Andric if (!NewBlockInfo) 7490b57cec5SDimitry Andric return reportError("Malformed BlockInfoBlock"); 7500b57cec5SDimitry Andric BlockInfo = std::move(*NewBlockInfo); 7510b57cec5SDimitry Andric if (Error Err = Stream.JumpToBit(BlockBitStart)) 7520b57cec5SDimitry Andric return Err; 7530b57cec5SDimitry Andric // It's not really interesting to dump the contents of the blockinfo 7540b57cec5SDimitry Andric // block. 7550b57cec5SDimitry Andric DumpRecords = false; 7560b57cec5SDimitry Andric } 7570b57cec5SDimitry Andric 7580b57cec5SDimitry Andric unsigned NumWords = 0; 7590b57cec5SDimitry Andric if (Error Err = Stream.EnterSubBlock(BlockID, &NumWords)) 7600b57cec5SDimitry Andric return Err; 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric // Keep it for later, when we see a MODULE_HASH record 7630b57cec5SDimitry Andric uint64_t BlockEntryPos = Stream.getCurrentByteNo(); 7640b57cec5SDimitry Andric 7650b57cec5SDimitry Andric Optional<const char *> BlockName = None; 7660b57cec5SDimitry Andric if (DumpRecords) { 7670b57cec5SDimitry Andric O->OS << Indent << "<"; 7680b57cec5SDimitry Andric if ((BlockName = GetBlockName(BlockID, BlockInfo, CurStreamType))) 7690b57cec5SDimitry Andric O->OS << *BlockName; 7700b57cec5SDimitry Andric else 7710b57cec5SDimitry Andric O->OS << "UnknownBlock" << BlockID; 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric if (!O->Symbolic && BlockName) 7740b57cec5SDimitry Andric O->OS << " BlockID=" << BlockID; 7750b57cec5SDimitry Andric 7760b57cec5SDimitry Andric O->OS << " NumWords=" << NumWords 7770b57cec5SDimitry Andric << " BlockCodeSize=" << Stream.getAbbrevIDWidth() << ">\n"; 7780b57cec5SDimitry Andric } 7790b57cec5SDimitry Andric 7800b57cec5SDimitry Andric SmallVector<uint64_t, 64> Record; 7810b57cec5SDimitry Andric 7820b57cec5SDimitry Andric // Keep the offset to the metadata index if seen. 7830b57cec5SDimitry Andric uint64_t MetadataIndexOffset = 0; 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric // Read all the records for this block. 7860b57cec5SDimitry Andric while (1) { 7870b57cec5SDimitry Andric if (Stream.AtEndOfStream()) 7880b57cec5SDimitry Andric return reportError("Premature end of bitstream"); 7890b57cec5SDimitry Andric 7900b57cec5SDimitry Andric uint64_t RecordStartBit = Stream.GetCurrentBitNo(); 7910b57cec5SDimitry Andric 7920b57cec5SDimitry Andric Expected<BitstreamEntry> MaybeEntry = 7930b57cec5SDimitry Andric Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs); 7940b57cec5SDimitry Andric if (!MaybeEntry) 7950b57cec5SDimitry Andric return MaybeEntry.takeError(); 7960b57cec5SDimitry Andric BitstreamEntry Entry = MaybeEntry.get(); 7970b57cec5SDimitry Andric 7980b57cec5SDimitry Andric switch (Entry.Kind) { 7990b57cec5SDimitry Andric case BitstreamEntry::Error: 8000b57cec5SDimitry Andric return reportError("malformed bitcode file"); 8010b57cec5SDimitry Andric case BitstreamEntry::EndBlock: { 8020b57cec5SDimitry Andric uint64_t BlockBitEnd = Stream.GetCurrentBitNo(); 8030b57cec5SDimitry Andric BlockStats.NumBits += BlockBitEnd - BlockBitStart; 8040b57cec5SDimitry Andric if (DumpRecords) { 8050b57cec5SDimitry Andric O->OS << Indent << "</"; 8060b57cec5SDimitry Andric if (BlockName) 8070b57cec5SDimitry Andric O->OS << *BlockName << ">\n"; 8080b57cec5SDimitry Andric else 8090b57cec5SDimitry Andric O->OS << "UnknownBlock" << BlockID << ">\n"; 8100b57cec5SDimitry Andric } 8110b57cec5SDimitry Andric return Error::success(); 8120b57cec5SDimitry Andric } 8130b57cec5SDimitry Andric 8140b57cec5SDimitry Andric case BitstreamEntry::SubBlock: { 8150b57cec5SDimitry Andric uint64_t SubBlockBitStart = Stream.GetCurrentBitNo(); 8160b57cec5SDimitry Andric if (Error E = parseBlock(Entry.ID, IndentLevel + 1, O, CheckHash)) 8170b57cec5SDimitry Andric return E; 8180b57cec5SDimitry Andric ++BlockStats.NumSubBlocks; 8190b57cec5SDimitry Andric uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo(); 8200b57cec5SDimitry Andric 8210b57cec5SDimitry Andric // Don't include subblock sizes in the size of this block. 8220b57cec5SDimitry Andric BlockBitStart += SubBlockBitEnd - SubBlockBitStart; 8230b57cec5SDimitry Andric continue; 8240b57cec5SDimitry Andric } 8250b57cec5SDimitry Andric case BitstreamEntry::Record: 8260b57cec5SDimitry Andric // The interesting case. 8270b57cec5SDimitry Andric break; 8280b57cec5SDimitry Andric } 8290b57cec5SDimitry Andric 8300b57cec5SDimitry Andric if (Entry.ID == bitc::DEFINE_ABBREV) { 8310b57cec5SDimitry Andric if (Error Err = Stream.ReadAbbrevRecord()) 8320b57cec5SDimitry Andric return Err; 8330b57cec5SDimitry Andric ++BlockStats.NumAbbrevs; 8340b57cec5SDimitry Andric continue; 8350b57cec5SDimitry Andric } 8360b57cec5SDimitry Andric 8370b57cec5SDimitry Andric Record.clear(); 8380b57cec5SDimitry Andric 8390b57cec5SDimitry Andric ++BlockStats.NumRecords; 8400b57cec5SDimitry Andric 8410b57cec5SDimitry Andric StringRef Blob; 8420b57cec5SDimitry Andric uint64_t CurrentRecordPos = Stream.GetCurrentBitNo(); 8430b57cec5SDimitry Andric Expected<unsigned> MaybeCode = Stream.readRecord(Entry.ID, Record, &Blob); 8440b57cec5SDimitry Andric if (!MaybeCode) 8450b57cec5SDimitry Andric return MaybeCode.takeError(); 8460b57cec5SDimitry Andric unsigned Code = MaybeCode.get(); 8470b57cec5SDimitry Andric 8480b57cec5SDimitry Andric // Increment the # occurrences of this code. 8490b57cec5SDimitry Andric if (BlockStats.CodeFreq.size() <= Code) 8500b57cec5SDimitry Andric BlockStats.CodeFreq.resize(Code + 1); 8510b57cec5SDimitry Andric BlockStats.CodeFreq[Code].NumInstances++; 8520b57cec5SDimitry Andric BlockStats.CodeFreq[Code].TotalBits += 8530b57cec5SDimitry Andric Stream.GetCurrentBitNo() - RecordStartBit; 8540b57cec5SDimitry Andric if (Entry.ID != bitc::UNABBREV_RECORD) { 8550b57cec5SDimitry Andric BlockStats.CodeFreq[Code].NumAbbrev++; 8560b57cec5SDimitry Andric ++BlockStats.NumAbbreviatedRecords; 8570b57cec5SDimitry Andric } 8580b57cec5SDimitry Andric 8590b57cec5SDimitry Andric if (DumpRecords) { 8600b57cec5SDimitry Andric O->OS << Indent << " <"; 8610b57cec5SDimitry Andric Optional<const char *> CodeName = 8620b57cec5SDimitry Andric GetCodeName(Code, BlockID, BlockInfo, CurStreamType); 8630b57cec5SDimitry Andric if (CodeName) 8640b57cec5SDimitry Andric O->OS << *CodeName; 8650b57cec5SDimitry Andric else 8660b57cec5SDimitry Andric O->OS << "UnknownCode" << Code; 8670b57cec5SDimitry Andric if (!O->Symbolic && CodeName) 8680b57cec5SDimitry Andric O->OS << " codeid=" << Code; 8690b57cec5SDimitry Andric const BitCodeAbbrev *Abbv = nullptr; 8700b57cec5SDimitry Andric if (Entry.ID != bitc::UNABBREV_RECORD) { 8710b57cec5SDimitry Andric Abbv = Stream.getAbbrev(Entry.ID); 8720b57cec5SDimitry Andric O->OS << " abbrevid=" << Entry.ID; 8730b57cec5SDimitry Andric } 8740b57cec5SDimitry Andric 8750b57cec5SDimitry Andric for (unsigned i = 0, e = Record.size(); i != e; ++i) 8760b57cec5SDimitry Andric O->OS << " op" << i << "=" << (int64_t)Record[i]; 8770b57cec5SDimitry Andric 8780b57cec5SDimitry Andric // If we found a metadata index, let's verify that we had an offset 8790b57cec5SDimitry Andric // before and validate its forward reference offset was correct! 8800b57cec5SDimitry Andric if (BlockID == bitc::METADATA_BLOCK_ID) { 8810b57cec5SDimitry Andric if (Code == bitc::METADATA_INDEX_OFFSET) { 8820b57cec5SDimitry Andric if (Record.size() != 2) 8830b57cec5SDimitry Andric O->OS << "(Invalid record)"; 8840b57cec5SDimitry Andric else { 8850b57cec5SDimitry Andric auto Offset = Record[0] + (Record[1] << 32); 8860b57cec5SDimitry Andric MetadataIndexOffset = Stream.GetCurrentBitNo() + Offset; 8870b57cec5SDimitry Andric } 8880b57cec5SDimitry Andric } 8890b57cec5SDimitry Andric if (Code == bitc::METADATA_INDEX) { 8900b57cec5SDimitry Andric O->OS << " (offset "; 8910b57cec5SDimitry Andric if (MetadataIndexOffset == RecordStartBit) 8920b57cec5SDimitry Andric O->OS << "match)"; 8930b57cec5SDimitry Andric else 8940b57cec5SDimitry Andric O->OS << "mismatch: " << MetadataIndexOffset << " vs " 8950b57cec5SDimitry Andric << RecordStartBit << ")"; 8960b57cec5SDimitry Andric } 8970b57cec5SDimitry Andric } 8980b57cec5SDimitry Andric 8990b57cec5SDimitry Andric // If we found a module hash, let's verify that it matches! 9000b57cec5SDimitry Andric if (BlockID == bitc::MODULE_BLOCK_ID && Code == bitc::MODULE_CODE_HASH && 9010b57cec5SDimitry Andric CheckHash.hasValue()) { 9020b57cec5SDimitry Andric if (Record.size() != 5) 9030b57cec5SDimitry Andric O->OS << " (invalid)"; 9040b57cec5SDimitry Andric else { 9050b57cec5SDimitry Andric // Recompute the hash and compare it to the one in the bitcode 9060b57cec5SDimitry Andric SHA1 Hasher; 9070b57cec5SDimitry Andric StringRef Hash; 9080b57cec5SDimitry Andric Hasher.update(*CheckHash); 9090b57cec5SDimitry Andric { 9100b57cec5SDimitry Andric int BlockSize = (CurrentRecordPos / 8) - BlockEntryPos; 9110b57cec5SDimitry Andric auto Ptr = Stream.getPointerToByte(BlockEntryPos, BlockSize); 9120b57cec5SDimitry Andric Hasher.update(ArrayRef<uint8_t>(Ptr, BlockSize)); 9130b57cec5SDimitry Andric Hash = Hasher.result(); 9140b57cec5SDimitry Andric } 915*5ffd83dbSDimitry Andric std::array<char, 20> RecordedHash; 9160b57cec5SDimitry Andric int Pos = 0; 9170b57cec5SDimitry Andric for (auto &Val : Record) { 9180b57cec5SDimitry Andric assert(!(Val >> 32) && "Unexpected high bits set"); 919*5ffd83dbSDimitry Andric support::endian::write32be(&RecordedHash[Pos], Val); 920*5ffd83dbSDimitry Andric Pos += 4; 9210b57cec5SDimitry Andric } 922*5ffd83dbSDimitry Andric if (Hash == StringRef(RecordedHash.data(), RecordedHash.size())) 9230b57cec5SDimitry Andric O->OS << " (match)"; 9240b57cec5SDimitry Andric else 9250b57cec5SDimitry Andric O->OS << " (!mismatch!)"; 9260b57cec5SDimitry Andric } 9270b57cec5SDimitry Andric } 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric O->OS << "/>"; 9300b57cec5SDimitry Andric 9310b57cec5SDimitry Andric if (Abbv) { 9320b57cec5SDimitry Andric for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) { 9330b57cec5SDimitry Andric const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); 9340b57cec5SDimitry Andric if (!Op.isEncoding() || Op.getEncoding() != BitCodeAbbrevOp::Array) 9350b57cec5SDimitry Andric continue; 9360b57cec5SDimitry Andric assert(i + 2 == e && "Array op not second to last"); 9370b57cec5SDimitry Andric std::string Str; 9380b57cec5SDimitry Andric bool ArrayIsPrintable = true; 9390b57cec5SDimitry Andric for (unsigned j = i - 1, je = Record.size(); j != je; ++j) { 9400b57cec5SDimitry Andric if (!isPrint(static_cast<unsigned char>(Record[j]))) { 9410b57cec5SDimitry Andric ArrayIsPrintable = false; 9420b57cec5SDimitry Andric break; 9430b57cec5SDimitry Andric } 9440b57cec5SDimitry Andric Str += (char)Record[j]; 9450b57cec5SDimitry Andric } 9460b57cec5SDimitry Andric if (ArrayIsPrintable) 9470b57cec5SDimitry Andric O->OS << " record string = '" << Str << "'"; 9480b57cec5SDimitry Andric break; 9490b57cec5SDimitry Andric } 9500b57cec5SDimitry Andric } 9510b57cec5SDimitry Andric 9520b57cec5SDimitry Andric if (Blob.data()) { 9530b57cec5SDimitry Andric if (canDecodeBlob(Code, BlockID)) { 9540b57cec5SDimitry Andric if (Error E = decodeMetadataStringsBlob(Indent, Record, Blob, O->OS)) 9550b57cec5SDimitry Andric return E; 9560b57cec5SDimitry Andric } else { 9570b57cec5SDimitry Andric O->OS << " blob data = "; 9580b57cec5SDimitry Andric if (O->ShowBinaryBlobs) { 9590b57cec5SDimitry Andric O->OS << "'"; 9600b57cec5SDimitry Andric O->OS.write_escaped(Blob, /*hex=*/true) << "'"; 9610b57cec5SDimitry Andric } else { 9620b57cec5SDimitry Andric bool BlobIsPrintable = true; 9630b57cec5SDimitry Andric for (unsigned i = 0, e = Blob.size(); i != e; ++i) 9640b57cec5SDimitry Andric if (!isPrint(static_cast<unsigned char>(Blob[i]))) { 9650b57cec5SDimitry Andric BlobIsPrintable = false; 9660b57cec5SDimitry Andric break; 9670b57cec5SDimitry Andric } 9680b57cec5SDimitry Andric 9690b57cec5SDimitry Andric if (BlobIsPrintable) 9700b57cec5SDimitry Andric O->OS << "'" << Blob << "'"; 9710b57cec5SDimitry Andric else 9720b57cec5SDimitry Andric O->OS << "unprintable, " << Blob.size() << " bytes."; 9730b57cec5SDimitry Andric } 9740b57cec5SDimitry Andric } 9750b57cec5SDimitry Andric } 9760b57cec5SDimitry Andric 9770b57cec5SDimitry Andric O->OS << "\n"; 9780b57cec5SDimitry Andric } 9790b57cec5SDimitry Andric 9800b57cec5SDimitry Andric // Make sure that we can skip the current record. 9810b57cec5SDimitry Andric if (Error Err = Stream.JumpToBit(CurrentRecordPos)) 9820b57cec5SDimitry Andric return Err; 9830b57cec5SDimitry Andric if (Expected<unsigned> Skipped = Stream.skipRecord(Entry.ID)) 9840b57cec5SDimitry Andric ; // Do nothing. 9850b57cec5SDimitry Andric else 9860b57cec5SDimitry Andric return Skipped.takeError(); 9870b57cec5SDimitry Andric } 9880b57cec5SDimitry Andric } 9890b57cec5SDimitry Andric 990