14cdb68ebSFrancis Visoiu Mistrih //===- BitcodeAnalyzer.cpp - Internal BitcodeAnalyzer implementation ------===// 24cdb68ebSFrancis Visoiu Mistrih // 34cdb68ebSFrancis Visoiu Mistrih // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 44cdb68ebSFrancis Visoiu Mistrih // See https://llvm.org/LICENSE.txt for license information. 54cdb68ebSFrancis Visoiu Mistrih // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 64cdb68ebSFrancis Visoiu Mistrih // 74cdb68ebSFrancis Visoiu Mistrih //===----------------------------------------------------------------------===// 84cdb68ebSFrancis Visoiu Mistrih 94cdb68ebSFrancis Visoiu Mistrih #include "llvm/Bitcode/BitcodeAnalyzer.h" 104cdb68ebSFrancis Visoiu Mistrih #include "llvm/Bitcode/BitcodeReader.h" 114cdb68ebSFrancis Visoiu Mistrih #include "llvm/Bitcode/LLVMBitCodes.h" 121a697aa6SFrancis Visoiu Mistrih #include "llvm/Bitstream/BitCodes.h" 131a697aa6SFrancis Visoiu Mistrih #include "llvm/Bitstream/BitstreamReader.h" 144cdb68ebSFrancis Visoiu Mistrih #include "llvm/Support/Format.h" 154cdb68ebSFrancis Visoiu Mistrih #include "llvm/Support/SHA1.h" 1649e75ebdSKrzysztof Parzyszek #include <optional> 174cdb68ebSFrancis Visoiu Mistrih 184cdb68ebSFrancis Visoiu Mistrih using namespace llvm; 194cdb68ebSFrancis Visoiu Mistrih 204cdb68ebSFrancis Visoiu Mistrih static Error reportError(StringRef Message) { 214cdb68ebSFrancis Visoiu Mistrih return createStringError(std::errc::illegal_byte_sequence, Message.data()); 224cdb68ebSFrancis Visoiu Mistrih } 234cdb68ebSFrancis Visoiu Mistrih 244cdb68ebSFrancis Visoiu Mistrih /// Return a symbolic block name if known, otherwise return null. 2549e75ebdSKrzysztof Parzyszek static std::optional<const char *> 2649e75ebdSKrzysztof Parzyszek GetBlockName(unsigned BlockID, const BitstreamBlockInfo &BlockInfo, 274cdb68ebSFrancis Visoiu Mistrih CurStreamTypeType CurStreamType) { 284cdb68ebSFrancis Visoiu Mistrih // Standard blocks for all bitcode files. 294cdb68ebSFrancis Visoiu Mistrih if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) { 304cdb68ebSFrancis Visoiu Mistrih if (BlockID == bitc::BLOCKINFO_BLOCK_ID) 314cdb68ebSFrancis Visoiu Mistrih return "BLOCKINFO_BLOCK"; 32e9e64f7cSKazu Hirata return std::nullopt; 334cdb68ebSFrancis Visoiu Mistrih } 344cdb68ebSFrancis Visoiu Mistrih 354cdb68ebSFrancis Visoiu Mistrih // Check to see if we have a blockinfo record for this block, with a name. 364cdb68ebSFrancis Visoiu Mistrih if (const BitstreamBlockInfo::BlockInfo *Info = 374cdb68ebSFrancis Visoiu Mistrih BlockInfo.getBlockInfo(BlockID)) { 384cdb68ebSFrancis Visoiu Mistrih if (!Info->Name.empty()) 394cdb68ebSFrancis Visoiu Mistrih return Info->Name.c_str(); 404cdb68ebSFrancis Visoiu Mistrih } 414cdb68ebSFrancis Visoiu Mistrih 424cdb68ebSFrancis Visoiu Mistrih if (CurStreamType != LLVMIRBitstream) 43e9e64f7cSKazu Hirata return std::nullopt; 444cdb68ebSFrancis Visoiu Mistrih 454cdb68ebSFrancis Visoiu Mistrih switch (BlockID) { 464cdb68ebSFrancis Visoiu Mistrih default: 47e9e64f7cSKazu Hirata return std::nullopt; 484cdb68ebSFrancis Visoiu Mistrih case bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID: 494cdb68ebSFrancis Visoiu Mistrih return "OPERAND_BUNDLE_TAGS_BLOCK"; 504cdb68ebSFrancis Visoiu Mistrih case bitc::MODULE_BLOCK_ID: 514cdb68ebSFrancis Visoiu Mistrih return "MODULE_BLOCK"; 524cdb68ebSFrancis Visoiu Mistrih case bitc::PARAMATTR_BLOCK_ID: 534cdb68ebSFrancis Visoiu Mistrih return "PARAMATTR_BLOCK"; 544cdb68ebSFrancis Visoiu Mistrih case bitc::PARAMATTR_GROUP_BLOCK_ID: 554cdb68ebSFrancis Visoiu Mistrih return "PARAMATTR_GROUP_BLOCK_ID"; 564cdb68ebSFrancis Visoiu Mistrih case bitc::TYPE_BLOCK_ID_NEW: 574cdb68ebSFrancis Visoiu Mistrih return "TYPE_BLOCK_ID"; 584cdb68ebSFrancis Visoiu Mistrih case bitc::CONSTANTS_BLOCK_ID: 594cdb68ebSFrancis Visoiu Mistrih return "CONSTANTS_BLOCK"; 604cdb68ebSFrancis Visoiu Mistrih case bitc::FUNCTION_BLOCK_ID: 614cdb68ebSFrancis Visoiu Mistrih return "FUNCTION_BLOCK"; 624cdb68ebSFrancis Visoiu Mistrih case bitc::IDENTIFICATION_BLOCK_ID: 634cdb68ebSFrancis Visoiu Mistrih return "IDENTIFICATION_BLOCK_ID"; 644cdb68ebSFrancis Visoiu Mistrih case bitc::VALUE_SYMTAB_BLOCK_ID: 654cdb68ebSFrancis Visoiu Mistrih return "VALUE_SYMTAB"; 664cdb68ebSFrancis Visoiu Mistrih case bitc::METADATA_BLOCK_ID: 674cdb68ebSFrancis Visoiu Mistrih return "METADATA_BLOCK"; 684cdb68ebSFrancis Visoiu Mistrih case bitc::METADATA_KIND_BLOCK_ID: 694cdb68ebSFrancis Visoiu Mistrih return "METADATA_KIND_BLOCK"; 704cdb68ebSFrancis Visoiu Mistrih case bitc::METADATA_ATTACHMENT_ID: 714cdb68ebSFrancis Visoiu Mistrih return "METADATA_ATTACHMENT_BLOCK"; 724cdb68ebSFrancis Visoiu Mistrih case bitc::USELIST_BLOCK_ID: 734cdb68ebSFrancis Visoiu Mistrih return "USELIST_BLOCK_ID"; 744cdb68ebSFrancis Visoiu Mistrih case bitc::GLOBALVAL_SUMMARY_BLOCK_ID: 754cdb68ebSFrancis Visoiu Mistrih return "GLOBALVAL_SUMMARY_BLOCK"; 764cdb68ebSFrancis Visoiu Mistrih case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID: 774cdb68ebSFrancis Visoiu Mistrih return "FULL_LTO_GLOBALVAL_SUMMARY_BLOCK"; 784cdb68ebSFrancis Visoiu Mistrih case bitc::MODULE_STRTAB_BLOCK_ID: 794cdb68ebSFrancis Visoiu Mistrih return "MODULE_STRTAB_BLOCK"; 804cdb68ebSFrancis Visoiu Mistrih case bitc::STRTAB_BLOCK_ID: 814cdb68ebSFrancis Visoiu Mistrih return "STRTAB_BLOCK"; 824cdb68ebSFrancis Visoiu Mistrih case bitc::SYMTAB_BLOCK_ID: 834cdb68ebSFrancis Visoiu Mistrih return "SYMTAB_BLOCK"; 844cdb68ebSFrancis Visoiu Mistrih } 854cdb68ebSFrancis Visoiu Mistrih } 864cdb68ebSFrancis Visoiu Mistrih 874cdb68ebSFrancis Visoiu Mistrih /// Return a symbolic code name if known, otherwise return null. 8849e75ebdSKrzysztof Parzyszek static std::optional<const char *> 8949e75ebdSKrzysztof Parzyszek GetCodeName(unsigned CodeID, unsigned BlockID, 904cdb68ebSFrancis Visoiu Mistrih const BitstreamBlockInfo &BlockInfo, 914cdb68ebSFrancis Visoiu Mistrih CurStreamTypeType CurStreamType) { 924cdb68ebSFrancis Visoiu Mistrih // Standard blocks for all bitcode files. 934cdb68ebSFrancis Visoiu Mistrih if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) { 944cdb68ebSFrancis Visoiu Mistrih if (BlockID == bitc::BLOCKINFO_BLOCK_ID) { 954cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 964cdb68ebSFrancis Visoiu Mistrih default: 97e9e64f7cSKazu Hirata return std::nullopt; 984cdb68ebSFrancis Visoiu Mistrih case bitc::BLOCKINFO_CODE_SETBID: 994cdb68ebSFrancis Visoiu Mistrih return "SETBID"; 1004cdb68ebSFrancis Visoiu Mistrih case bitc::BLOCKINFO_CODE_BLOCKNAME: 1014cdb68ebSFrancis Visoiu Mistrih return "BLOCKNAME"; 1024cdb68ebSFrancis Visoiu Mistrih case bitc::BLOCKINFO_CODE_SETRECORDNAME: 1034cdb68ebSFrancis Visoiu Mistrih return "SETRECORDNAME"; 1044cdb68ebSFrancis Visoiu Mistrih } 1054cdb68ebSFrancis Visoiu Mistrih } 106e9e64f7cSKazu Hirata return std::nullopt; 1074cdb68ebSFrancis Visoiu Mistrih } 1084cdb68ebSFrancis Visoiu Mistrih 1094cdb68ebSFrancis Visoiu Mistrih // Check to see if we have a blockinfo record for this record, with a name. 1104cdb68ebSFrancis Visoiu Mistrih if (const BitstreamBlockInfo::BlockInfo *Info = 1114cdb68ebSFrancis Visoiu Mistrih BlockInfo.getBlockInfo(BlockID)) { 1121457e783SKazu Hirata for (const std::pair<unsigned, std::string> &RN : Info->RecordNames) 1131457e783SKazu Hirata if (RN.first == CodeID) 1141457e783SKazu Hirata return RN.second.c_str(); 1154cdb68ebSFrancis Visoiu Mistrih } 1164cdb68ebSFrancis Visoiu Mistrih 1174cdb68ebSFrancis Visoiu Mistrih if (CurStreamType != LLVMIRBitstream) 118e9e64f7cSKazu Hirata return std::nullopt; 1194cdb68ebSFrancis Visoiu Mistrih 1204cdb68ebSFrancis Visoiu Mistrih #define STRINGIFY_CODE(PREFIX, CODE) \ 1214cdb68ebSFrancis Visoiu Mistrih case bitc::PREFIX##_##CODE: \ 1224cdb68ebSFrancis Visoiu Mistrih return #CODE; 1234cdb68ebSFrancis Visoiu Mistrih switch (BlockID) { 1244cdb68ebSFrancis Visoiu Mistrih default: 125e9e64f7cSKazu Hirata return std::nullopt; 1264cdb68ebSFrancis Visoiu Mistrih case bitc::MODULE_BLOCK_ID: 1274cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 1284cdb68ebSFrancis Visoiu Mistrih default: 129e9e64f7cSKazu Hirata return std::nullopt; 1304cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(MODULE_CODE, VERSION) 1314cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(MODULE_CODE, TRIPLE) 1324cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(MODULE_CODE, DATALAYOUT) 1334cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(MODULE_CODE, ASM) 1344cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(MODULE_CODE, SECTIONNAME) 1354abf0243SMehdi Amini STRINGIFY_CODE(MODULE_CODE, DEPLIB) // Deprecated, present in old bitcode 1364cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(MODULE_CODE, GLOBALVAR) 1374cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(MODULE_CODE, FUNCTION) 1384cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(MODULE_CODE, ALIAS) 1394cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(MODULE_CODE, GCNAME) 140a184c758SCraig Topper STRINGIFY_CODE(MODULE_CODE, COMDAT) 1414cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(MODULE_CODE, VSTOFFSET) 1424cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(MODULE_CODE, METADATA_VALUES_UNUSED) 1434cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(MODULE_CODE, SOURCE_FILENAME) 1444cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(MODULE_CODE, HASH) 1454cdb68ebSFrancis Visoiu Mistrih } 1464cdb68ebSFrancis Visoiu Mistrih case bitc::IDENTIFICATION_BLOCK_ID: 1474cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 1484cdb68ebSFrancis Visoiu Mistrih default: 149e9e64f7cSKazu Hirata return std::nullopt; 1504cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(IDENTIFICATION_CODE, STRING) 1514cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(IDENTIFICATION_CODE, EPOCH) 1524cdb68ebSFrancis Visoiu Mistrih } 1534cdb68ebSFrancis Visoiu Mistrih case bitc::PARAMATTR_BLOCK_ID: 1544cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 1554cdb68ebSFrancis Visoiu Mistrih default: 156e9e64f7cSKazu Hirata return std::nullopt; 1574cdb68ebSFrancis Visoiu Mistrih // FIXME: Should these be different? 1584cdb68ebSFrancis Visoiu Mistrih case bitc::PARAMATTR_CODE_ENTRY_OLD: 1594cdb68ebSFrancis Visoiu Mistrih return "ENTRY"; 1604cdb68ebSFrancis Visoiu Mistrih case bitc::PARAMATTR_CODE_ENTRY: 1614cdb68ebSFrancis Visoiu Mistrih return "ENTRY"; 1624cdb68ebSFrancis Visoiu Mistrih } 1634cdb68ebSFrancis Visoiu Mistrih case bitc::PARAMATTR_GROUP_BLOCK_ID: 1644cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 1654cdb68ebSFrancis Visoiu Mistrih default: 166e9e64f7cSKazu Hirata return std::nullopt; 1674cdb68ebSFrancis Visoiu Mistrih case bitc::PARAMATTR_GRP_CODE_ENTRY: 1684cdb68ebSFrancis Visoiu Mistrih return "ENTRY"; 1694cdb68ebSFrancis Visoiu Mistrih } 1704cdb68ebSFrancis Visoiu Mistrih case bitc::TYPE_BLOCK_ID_NEW: 1714cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 1724cdb68ebSFrancis Visoiu Mistrih default: 173e9e64f7cSKazu Hirata return std::nullopt; 1744cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, NUMENTRY) 1754cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, VOID) 1764cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, FLOAT) 1774cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, DOUBLE) 1784cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, LABEL) 1794cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, OPAQUE) 1804cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, INTEGER) 1814cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, POINTER) 182a184c758SCraig Topper STRINGIFY_CODE(TYPE_CODE, HALF) 1834cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, ARRAY) 1844cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, VECTOR) 1854cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, X86_FP80) 1864cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, FP128) 1874cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, PPC_FP128) 1884cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, METADATA) 189a184c758SCraig Topper STRINGIFY_CODE(TYPE_CODE, X86_MMX) 1904cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, STRUCT_ANON) 1914cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, STRUCT_NAME) 1924cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, STRUCT_NAMED) 1934cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(TYPE_CODE, FUNCTION) 194a184c758SCraig Topper STRINGIFY_CODE(TYPE_CODE, TOKEN) 195a184c758SCraig Topper STRINGIFY_CODE(TYPE_CODE, BFLOAT) 1964cdb68ebSFrancis Visoiu Mistrih } 1974cdb68ebSFrancis Visoiu Mistrih 1984cdb68ebSFrancis Visoiu Mistrih case bitc::CONSTANTS_BLOCK_ID: 1994cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 2004cdb68ebSFrancis Visoiu Mistrih default: 201e9e64f7cSKazu Hirata return std::nullopt; 2024cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, SETTYPE) 2034cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, NULL) 2044cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, UNDEF) 2054cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, INTEGER) 2064cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, WIDE_INTEGER) 2074cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, FLOAT) 2084cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, AGGREGATE) 2094cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, STRING) 2104cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, CSTRING) 2114cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, CE_BINOP) 2124cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, CE_CAST) 2134cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, CE_GEP) 2144cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, CE_INBOUNDS_GEP) 2154cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, CE_SELECT) 2164cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, CE_EXTRACTELT) 2174cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, CE_INSERTELT) 2184cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, CE_SHUFFLEVEC) 2194cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, CE_CMP) 2204cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, INLINEASM) 2214cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, CE_SHUFVEC_EX) 2224cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, CE_UNOP) 2231c932baeSLeonard Chan STRINGIFY_CODE(CST_CODE, DSO_LOCAL_EQUIVALENT) 2245dc8aaacSSami Tolvanen STRINGIFY_CODE(CST_CODE, NO_CFI_VALUE) 2250edc97f1SAhmed Bougacha STRINGIFY_CODE(CST_CODE, PTRAUTH) 2264cdb68ebSFrancis Visoiu Mistrih case bitc::CST_CODE_BLOCKADDRESS: 2274cdb68ebSFrancis Visoiu Mistrih return "CST_CODE_BLOCKADDRESS"; 2284cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(CST_CODE, DATA) 2294cdb68ebSFrancis Visoiu Mistrih } 2304cdb68ebSFrancis Visoiu Mistrih case bitc::FUNCTION_BLOCK_ID: 2314cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 2324cdb68ebSFrancis Visoiu Mistrih default: 233e9e64f7cSKazu Hirata return std::nullopt; 2344cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, DECLAREBLOCKS) 2354cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_BINOP) 2364cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_CAST) 2374cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_GEP_OLD) 2384cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_INBOUNDS_GEP_OLD) 2394cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_SELECT) 2404cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_EXTRACTELT) 2414cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_INSERTELT) 2424cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_SHUFFLEVEC) 2434cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_CMP) 2444cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_RET) 2454cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_BR) 2464cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_SWITCH) 2474cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_INVOKE) 2484cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_UNOP) 2494cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_UNREACHABLE) 2504cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_CLEANUPRET) 2514cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_CATCHRET) 2524cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_CATCHPAD) 2534cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_PHI) 2544cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_ALLOCA) 2554cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_LOAD) 2564cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_VAARG) 2574cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_STORE) 2584cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_EXTRACTVAL) 2594cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_INSERTVAL) 2604cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_CMP2) 2614cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_VSELECT) 2624cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, DEBUG_LOC_AGAIN) 2634cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_CALL) 2644cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, DEBUG_LOC) 2654cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_GEP) 2664cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, OPERAND_BUNDLE) 2674cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_FENCE) 2684cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_ATOMICRMW) 2694cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_LOADATOMIC) 2704cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_STOREATOMIC) 2714cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_CMPXCHG) 2724cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FUNC_CODE, INST_CALLBR) 27323ec5782SNick Desaulniers STRINGIFY_CODE(FUNC_CODE, BLOCKADDR_USERS) 274435d4c12SOrlando Cazalet-Hyams STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_DECLARE) 275435d4c12SOrlando Cazalet-Hyams STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_VALUE) 276435d4c12SOrlando Cazalet-Hyams STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_ASSIGN) 277435d4c12SOrlando Cazalet-Hyams STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_VALUE_SIMPLE) 278435d4c12SOrlando Cazalet-Hyams STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_LABEL) 2794cdb68ebSFrancis Visoiu Mistrih } 2804cdb68ebSFrancis Visoiu Mistrih case bitc::VALUE_SYMTAB_BLOCK_ID: 2814cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 2824cdb68ebSFrancis Visoiu Mistrih default: 283e9e64f7cSKazu Hirata return std::nullopt; 2844cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(VST_CODE, ENTRY) 2854cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(VST_CODE, BBENTRY) 2864cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(VST_CODE, FNENTRY) 2874cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(VST_CODE, COMBINED_ENTRY) 2884cdb68ebSFrancis Visoiu Mistrih } 2894cdb68ebSFrancis Visoiu Mistrih case bitc::MODULE_STRTAB_BLOCK_ID: 2904cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 2914cdb68ebSFrancis Visoiu Mistrih default: 292e9e64f7cSKazu Hirata return std::nullopt; 2934cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(MST_CODE, ENTRY) 2944cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(MST_CODE, HASH) 2954cdb68ebSFrancis Visoiu Mistrih } 2964cdb68ebSFrancis Visoiu Mistrih case bitc::GLOBALVAL_SUMMARY_BLOCK_ID: 2974cdb68ebSFrancis Visoiu Mistrih case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID: 2984cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 2994cdb68ebSFrancis Visoiu Mistrih default: 300e9e64f7cSKazu Hirata return std::nullopt; 3014cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, PERMODULE) 3024cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, PERMODULE_PROFILE) 3034cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, PERMODULE_RELBF) 3044cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, PERMODULE_GLOBALVAR_INIT_REFS) 3054cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, PERMODULE_VTABLE_GLOBALVAR_INIT_REFS) 3064cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, COMBINED) 3074cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, COMBINED_PROFILE) 3084cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, COMBINED_GLOBALVAR_INIT_REFS) 3094cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, ALIAS) 3104cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, COMBINED_ALIAS) 3114cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, COMBINED_ORIGINAL_NAME) 3124cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, VERSION) 3134cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, FLAGS) 3144cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, TYPE_TESTS) 3154cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, TYPE_TEST_ASSUME_VCALLS) 3164cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, TYPE_CHECKED_LOAD_VCALLS) 3174cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, TYPE_TEST_ASSUME_CONST_VCALL) 3184cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, TYPE_CHECKED_LOAD_CONST_VCALL) 3194cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, VALUE_GUID) 3204cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, CFI_FUNCTION_DEFS) 3214cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, CFI_FUNCTION_DECLS) 3224cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, TYPE_ID) 3234cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(FS, TYPE_ID_METADATA) 324a7fa35a6SHiroshi Yamauchi STRINGIFY_CODE(FS, BLOCK_COUNT) 3254666953cSVitaly Buka STRINGIFY_CODE(FS, PARAM_ACCESS) 3269eacbba2STeresa Johnson STRINGIFY_CODE(FS, PERMODULE_CALLSITE_INFO) 3279eacbba2STeresa Johnson STRINGIFY_CODE(FS, PERMODULE_ALLOC_INFO) 3289eacbba2STeresa Johnson STRINGIFY_CODE(FS, COMBINED_CALLSITE_INFO) 3299eacbba2STeresa Johnson STRINGIFY_CODE(FS, COMBINED_ALLOC_INFO) 3309eacbba2STeresa Johnson STRINGIFY_CODE(FS, STACK_IDS) 3319513f2fdSTeresa Johnson STRINGIFY_CODE(FS, ALLOC_CONTEXT_IDS) 332*776476c2STeresa Johnson STRINGIFY_CODE(FS, CONTEXT_RADIX_TREE_ARRAY) 3334cdb68ebSFrancis Visoiu Mistrih } 3344cdb68ebSFrancis Visoiu Mistrih case bitc::METADATA_ATTACHMENT_ID: 3354cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 3364cdb68ebSFrancis Visoiu Mistrih default: 337e9e64f7cSKazu Hirata return std::nullopt; 3384cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, ATTACHMENT) 3394cdb68ebSFrancis Visoiu Mistrih } 3404cdb68ebSFrancis Visoiu Mistrih case bitc::METADATA_BLOCK_ID: 3414cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 3424cdb68ebSFrancis Visoiu Mistrih default: 343e9e64f7cSKazu Hirata return std::nullopt; 3444cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, STRING_OLD) 3454cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, VALUE) 3464cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, NODE) 3474cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, NAME) 3484cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, DISTINCT_NODE) 3494cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, KIND) // Older bitcode has it in a MODULE_BLOCK 3504cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, LOCATION) 3514cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, OLD_NODE) 3524cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, OLD_FN_NODE) 3534cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, NAMED_NODE) 3544cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, GENERIC_DEBUG) 3554cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, SUBRANGE) 3564cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, ENUMERATOR) 3574cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, BASIC_TYPE) 3584cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, FILE) 3594cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, DERIVED_TYPE) 3604cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, COMPOSITE_TYPE) 3614cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, SUBROUTINE_TYPE) 3624cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, COMPILE_UNIT) 3634cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, SUBPROGRAM) 3644cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, LEXICAL_BLOCK) 3654cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, LEXICAL_BLOCK_FILE) 3664cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, NAMESPACE) 3674cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, TEMPLATE_TYPE) 3684cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, TEMPLATE_VALUE) 3694cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, GLOBAL_VAR) 3704cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, LOCAL_VAR) 3714cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, EXPRESSION) 3724cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, OBJC_PROPERTY) 3734cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, IMPORTED_ENTITY) 3744cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, MODULE) 3754cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, MACRO) 3764cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, MACRO_FILE) 3774cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, STRINGS) 3784cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, GLOBAL_DECL_ATTACHMENT) 3794cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, GLOBAL_VAR_EXPR) 3804cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, INDEX_OFFSET) 3814cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, INDEX) 38265600cb2Sgbtozers STRINGIFY_CODE(METADATA, ARG_LIST) 3834cdb68ebSFrancis Visoiu Mistrih } 3844cdb68ebSFrancis Visoiu Mistrih case bitc::METADATA_KIND_BLOCK_ID: 3854cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 3864cdb68ebSFrancis Visoiu Mistrih default: 387e9e64f7cSKazu Hirata return std::nullopt; 3884cdb68ebSFrancis Visoiu Mistrih STRINGIFY_CODE(METADATA, KIND) 3894cdb68ebSFrancis Visoiu Mistrih } 3904cdb68ebSFrancis Visoiu Mistrih case bitc::USELIST_BLOCK_ID: 3914cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 3924cdb68ebSFrancis Visoiu Mistrih default: 393e9e64f7cSKazu Hirata return std::nullopt; 3944cdb68ebSFrancis Visoiu Mistrih case bitc::USELIST_CODE_DEFAULT: 3954cdb68ebSFrancis Visoiu Mistrih return "USELIST_CODE_DEFAULT"; 3964cdb68ebSFrancis Visoiu Mistrih case bitc::USELIST_CODE_BB: 3974cdb68ebSFrancis Visoiu Mistrih return "USELIST_CODE_BB"; 3984cdb68ebSFrancis Visoiu Mistrih } 3994cdb68ebSFrancis Visoiu Mistrih 4004cdb68ebSFrancis Visoiu Mistrih case bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID: 4014cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 4024cdb68ebSFrancis Visoiu Mistrih default: 403e9e64f7cSKazu Hirata return std::nullopt; 4044cdb68ebSFrancis Visoiu Mistrih case bitc::OPERAND_BUNDLE_TAG: 4054cdb68ebSFrancis Visoiu Mistrih return "OPERAND_BUNDLE_TAG"; 4064cdb68ebSFrancis Visoiu Mistrih } 4074cdb68ebSFrancis Visoiu Mistrih case bitc::STRTAB_BLOCK_ID: 4084cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 4094cdb68ebSFrancis Visoiu Mistrih default: 410e9e64f7cSKazu Hirata return std::nullopt; 4114cdb68ebSFrancis Visoiu Mistrih case bitc::STRTAB_BLOB: 4124cdb68ebSFrancis Visoiu Mistrih return "BLOB"; 4134cdb68ebSFrancis Visoiu Mistrih } 4144cdb68ebSFrancis Visoiu Mistrih case bitc::SYMTAB_BLOCK_ID: 4154cdb68ebSFrancis Visoiu Mistrih switch (CodeID) { 4164cdb68ebSFrancis Visoiu Mistrih default: 417e9e64f7cSKazu Hirata return std::nullopt; 4184cdb68ebSFrancis Visoiu Mistrih case bitc::SYMTAB_BLOB: 4194cdb68ebSFrancis Visoiu Mistrih return "BLOB"; 4204cdb68ebSFrancis Visoiu Mistrih } 4214cdb68ebSFrancis Visoiu Mistrih } 4224cdb68ebSFrancis Visoiu Mistrih #undef STRINGIFY_CODE 4234cdb68ebSFrancis Visoiu Mistrih } 4244cdb68ebSFrancis Visoiu Mistrih 4254cdb68ebSFrancis Visoiu Mistrih static void printSize(raw_ostream &OS, double Bits) { 4264cdb68ebSFrancis Visoiu Mistrih OS << format("%.2f/%.2fB/%luW", Bits, Bits / 8, (unsigned long)(Bits / 32)); 4274cdb68ebSFrancis Visoiu Mistrih } 4284cdb68ebSFrancis Visoiu Mistrih static void printSize(raw_ostream &OS, uint64_t Bits) { 4294cdb68ebSFrancis Visoiu Mistrih OS << format("%lub/%.2fB/%luW", (unsigned long)Bits, (double)Bits / 8, 4304cdb68ebSFrancis Visoiu Mistrih (unsigned long)(Bits / 32)); 4314cdb68ebSFrancis Visoiu Mistrih } 4324cdb68ebSFrancis Visoiu Mistrih 4334cdb68ebSFrancis Visoiu Mistrih static Expected<CurStreamTypeType> ReadSignature(BitstreamCursor &Stream) { 4344cdb68ebSFrancis Visoiu Mistrih auto tryRead = [&Stream](char &Dest, size_t size) -> Error { 4354cdb68ebSFrancis Visoiu Mistrih if (Expected<SimpleBitstreamCursor::word_t> MaybeWord = Stream.Read(size)) 4364cdb68ebSFrancis Visoiu Mistrih Dest = MaybeWord.get(); 4374cdb68ebSFrancis Visoiu Mistrih else 4384cdb68ebSFrancis Visoiu Mistrih return MaybeWord.takeError(); 4394cdb68ebSFrancis Visoiu Mistrih return Error::success(); 4404cdb68ebSFrancis Visoiu Mistrih }; 4414cdb68ebSFrancis Visoiu Mistrih 4424cdb68ebSFrancis Visoiu Mistrih char Signature[6]; 4434cdb68ebSFrancis Visoiu Mistrih if (Error Err = tryRead(Signature[0], 8)) 444c55cf4afSBill Wendling return std::move(Err); 4454cdb68ebSFrancis Visoiu Mistrih if (Error Err = tryRead(Signature[1], 8)) 446c55cf4afSBill Wendling return std::move(Err); 4474cdb68ebSFrancis Visoiu Mistrih 4484cdb68ebSFrancis Visoiu Mistrih // Autodetect the file contents, if it is one we know. 4494cdb68ebSFrancis Visoiu Mistrih if (Signature[0] == 'C' && Signature[1] == 'P') { 4504cdb68ebSFrancis Visoiu Mistrih if (Error Err = tryRead(Signature[2], 8)) 451c55cf4afSBill Wendling return std::move(Err); 4524cdb68ebSFrancis Visoiu Mistrih if (Error Err = tryRead(Signature[3], 8)) 453c55cf4afSBill Wendling return std::move(Err); 4544cdb68ebSFrancis Visoiu Mistrih if (Signature[2] == 'C' && Signature[3] == 'H') 4554cdb68ebSFrancis Visoiu Mistrih return ClangSerializedASTBitstream; 4564cdb68ebSFrancis Visoiu Mistrih } else if (Signature[0] == 'D' && Signature[1] == 'I') { 4574cdb68ebSFrancis Visoiu Mistrih if (Error Err = tryRead(Signature[2], 8)) 458c55cf4afSBill Wendling return std::move(Err); 4594cdb68ebSFrancis Visoiu Mistrih if (Error Err = tryRead(Signature[3], 8)) 460c55cf4afSBill Wendling return std::move(Err); 4614cdb68ebSFrancis Visoiu Mistrih if (Signature[2] == 'A' && Signature[3] == 'G') 4624cdb68ebSFrancis Visoiu Mistrih return ClangSerializedDiagnosticsBitstream; 46384e80979SFrancis Visoiu Mistrih } else if (Signature[0] == 'R' && Signature[1] == 'M') { 46484e80979SFrancis Visoiu Mistrih if (Error Err = tryRead(Signature[2], 8)) 465c55cf4afSBill Wendling return std::move(Err); 46684e80979SFrancis Visoiu Mistrih if (Error Err = tryRead(Signature[3], 8)) 467c55cf4afSBill Wendling return std::move(Err); 46884e80979SFrancis Visoiu Mistrih if (Signature[2] == 'R' && Signature[3] == 'K') 46984e80979SFrancis Visoiu Mistrih return LLVMBitstreamRemarks; 4704cdb68ebSFrancis Visoiu Mistrih } else { 4714cdb68ebSFrancis Visoiu Mistrih if (Error Err = tryRead(Signature[2], 4)) 472c55cf4afSBill Wendling return std::move(Err); 4734cdb68ebSFrancis Visoiu Mistrih if (Error Err = tryRead(Signature[3], 4)) 474c55cf4afSBill Wendling return std::move(Err); 4754cdb68ebSFrancis Visoiu Mistrih if (Error Err = tryRead(Signature[4], 4)) 476c55cf4afSBill Wendling return std::move(Err); 4774cdb68ebSFrancis Visoiu Mistrih if (Error Err = tryRead(Signature[5], 4)) 478c55cf4afSBill Wendling return std::move(Err); 4794cdb68ebSFrancis Visoiu Mistrih if (Signature[0] == 'B' && Signature[1] == 'C' && Signature[2] == 0x0 && 4804cdb68ebSFrancis Visoiu Mistrih Signature[3] == 0xC && Signature[4] == 0xE && Signature[5] == 0xD) 4814cdb68ebSFrancis Visoiu Mistrih return LLVMIRBitstream; 4824cdb68ebSFrancis Visoiu Mistrih } 4834cdb68ebSFrancis Visoiu Mistrih return UnknownBitstream; 4844cdb68ebSFrancis Visoiu Mistrih } 4854cdb68ebSFrancis Visoiu Mistrih 48649e75ebdSKrzysztof Parzyszek static Expected<CurStreamTypeType> analyzeHeader(std::optional<BCDumpOptions> O, 4874cdb68ebSFrancis Visoiu Mistrih BitstreamCursor &Stream) { 4884cdb68ebSFrancis Visoiu Mistrih ArrayRef<uint8_t> Bytes = Stream.getBitcodeBytes(); 4894cdb68ebSFrancis Visoiu Mistrih const unsigned char *BufPtr = (const unsigned char *)Bytes.data(); 4904cdb68ebSFrancis Visoiu Mistrih const unsigned char *EndBufPtr = BufPtr + Bytes.size(); 4914cdb68ebSFrancis Visoiu Mistrih 4924cdb68ebSFrancis Visoiu Mistrih // If we have a wrapper header, parse it and ignore the non-bc file 4934cdb68ebSFrancis Visoiu Mistrih // contents. The magic number is 0x0B17C0DE stored in little endian. 4944cdb68ebSFrancis Visoiu Mistrih if (isBitcodeWrapper(BufPtr, EndBufPtr)) { 4954cdb68ebSFrancis Visoiu Mistrih if (Bytes.size() < BWH_HeaderSize) 4964cdb68ebSFrancis Visoiu Mistrih return reportError("Invalid bitcode wrapper header"); 4974cdb68ebSFrancis Visoiu Mistrih 4984cdb68ebSFrancis Visoiu Mistrih if (O) { 4994cdb68ebSFrancis Visoiu Mistrih unsigned Magic = support::endian::read32le(&BufPtr[BWH_MagicField]); 5004cdb68ebSFrancis Visoiu Mistrih unsigned Version = support::endian::read32le(&BufPtr[BWH_VersionField]); 5014cdb68ebSFrancis Visoiu Mistrih unsigned Offset = support::endian::read32le(&BufPtr[BWH_OffsetField]); 5024cdb68ebSFrancis Visoiu Mistrih unsigned Size = support::endian::read32le(&BufPtr[BWH_SizeField]); 5034cdb68ebSFrancis Visoiu Mistrih unsigned CPUType = support::endian::read32le(&BufPtr[BWH_CPUTypeField]); 5044cdb68ebSFrancis Visoiu Mistrih 5054cdb68ebSFrancis Visoiu Mistrih O->OS << "<BITCODE_WRAPPER_HEADER" 5064cdb68ebSFrancis Visoiu Mistrih << " Magic=" << format_hex(Magic, 10) 5074cdb68ebSFrancis Visoiu Mistrih << " Version=" << format_hex(Version, 10) 5084cdb68ebSFrancis Visoiu Mistrih << " Offset=" << format_hex(Offset, 10) 5094cdb68ebSFrancis Visoiu Mistrih << " Size=" << format_hex(Size, 10) 5104cdb68ebSFrancis Visoiu Mistrih << " CPUType=" << format_hex(CPUType, 10) << "/>\n"; 5114cdb68ebSFrancis Visoiu Mistrih } 5124cdb68ebSFrancis Visoiu Mistrih 5134cdb68ebSFrancis Visoiu Mistrih if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr, true)) 5144cdb68ebSFrancis Visoiu Mistrih return reportError("Invalid bitcode wrapper header"); 5154cdb68ebSFrancis Visoiu Mistrih } 5164cdb68ebSFrancis Visoiu Mistrih 5174cdb68ebSFrancis Visoiu Mistrih // Use the cursor modified by skipping the wrapper header. 5184cdb68ebSFrancis Visoiu Mistrih Stream = BitstreamCursor(ArrayRef<uint8_t>(BufPtr, EndBufPtr)); 5194cdb68ebSFrancis Visoiu Mistrih 5204cdb68ebSFrancis Visoiu Mistrih return ReadSignature(Stream); 5214cdb68ebSFrancis Visoiu Mistrih } 5224cdb68ebSFrancis Visoiu Mistrih 5234cdb68ebSFrancis Visoiu Mistrih static bool canDecodeBlob(unsigned Code, unsigned BlockID) { 5244cdb68ebSFrancis Visoiu Mistrih return BlockID == bitc::METADATA_BLOCK_ID && Code == bitc::METADATA_STRINGS; 5254cdb68ebSFrancis Visoiu Mistrih } 5264cdb68ebSFrancis Visoiu Mistrih 5274cdb68ebSFrancis Visoiu Mistrih Error BitcodeAnalyzer::decodeMetadataStringsBlob(StringRef Indent, 5284cdb68ebSFrancis Visoiu Mistrih ArrayRef<uint64_t> Record, 5294cdb68ebSFrancis Visoiu Mistrih StringRef Blob, 5304cdb68ebSFrancis Visoiu Mistrih raw_ostream &OS) { 5314cdb68ebSFrancis Visoiu Mistrih if (Blob.empty()) 5324cdb68ebSFrancis Visoiu Mistrih return reportError("Cannot decode empty blob."); 5334cdb68ebSFrancis Visoiu Mistrih 5344cdb68ebSFrancis Visoiu Mistrih if (Record.size() != 2) 5354cdb68ebSFrancis Visoiu Mistrih return reportError( 5364cdb68ebSFrancis Visoiu Mistrih "Decoding metadata strings blob needs two record entries."); 5374cdb68ebSFrancis Visoiu Mistrih 5384cdb68ebSFrancis Visoiu Mistrih unsigned NumStrings = Record[0]; 5394cdb68ebSFrancis Visoiu Mistrih unsigned StringsOffset = Record[1]; 5404cdb68ebSFrancis Visoiu Mistrih OS << " num-strings = " << NumStrings << " {\n"; 5414cdb68ebSFrancis Visoiu Mistrih 5424cdb68ebSFrancis Visoiu Mistrih StringRef Lengths = Blob.slice(0, StringsOffset); 5434cdb68ebSFrancis Visoiu Mistrih SimpleBitstreamCursor R(Lengths); 5444cdb68ebSFrancis Visoiu Mistrih StringRef Strings = Blob.drop_front(StringsOffset); 5454cdb68ebSFrancis Visoiu Mistrih do { 5464cdb68ebSFrancis Visoiu Mistrih if (R.AtEndOfStream()) 5474cdb68ebSFrancis Visoiu Mistrih return reportError("bad length"); 5484cdb68ebSFrancis Visoiu Mistrih 549b12a864cSDuncan P. N. Exon Smith uint32_t Size; 550b12a864cSDuncan P. N. Exon Smith if (Error E = R.ReadVBR(6).moveInto(Size)) 551b12a864cSDuncan P. N. Exon Smith return E; 5524cdb68ebSFrancis Visoiu Mistrih if (Strings.size() < Size) 5534cdb68ebSFrancis Visoiu Mistrih return reportError("truncated chars"); 5544cdb68ebSFrancis Visoiu Mistrih 5554cdb68ebSFrancis Visoiu Mistrih OS << Indent << " '"; 5564cdb68ebSFrancis Visoiu Mistrih OS.write_escaped(Strings.slice(0, Size), /*hex=*/true); 5574cdb68ebSFrancis Visoiu Mistrih OS << "'\n"; 5584cdb68ebSFrancis Visoiu Mistrih Strings = Strings.drop_front(Size); 5594cdb68ebSFrancis Visoiu Mistrih } while (--NumStrings); 5604cdb68ebSFrancis Visoiu Mistrih 5614cdb68ebSFrancis Visoiu Mistrih OS << Indent << " }"; 5624cdb68ebSFrancis Visoiu Mistrih return Error::success(); 5634cdb68ebSFrancis Visoiu Mistrih } 5644cdb68ebSFrancis Visoiu Mistrih 5654cdb68ebSFrancis Visoiu Mistrih BitcodeAnalyzer::BitcodeAnalyzer(StringRef Buffer, 56649e75ebdSKrzysztof Parzyszek std::optional<StringRef> BlockInfoBuffer) 5674cdb68ebSFrancis Visoiu Mistrih : Stream(Buffer) { 5684cdb68ebSFrancis Visoiu Mistrih if (BlockInfoBuffer) 5694cdb68ebSFrancis Visoiu Mistrih BlockInfoStream.emplace(*BlockInfoBuffer); 5704cdb68ebSFrancis Visoiu Mistrih } 5714cdb68ebSFrancis Visoiu Mistrih 57249e75ebdSKrzysztof Parzyszek Error BitcodeAnalyzer::analyze(std::optional<BCDumpOptions> O, 57349e75ebdSKrzysztof Parzyszek std::optional<StringRef> CheckHash) { 574b12a864cSDuncan P. N. Exon Smith if (Error E = analyzeHeader(O, Stream).moveInto(CurStreamType)) 575b12a864cSDuncan P. N. Exon Smith return E; 5764cdb68ebSFrancis Visoiu Mistrih 5774cdb68ebSFrancis Visoiu Mistrih Stream.setBlockInfo(&BlockInfo); 5784cdb68ebSFrancis Visoiu Mistrih 5794cdb68ebSFrancis Visoiu Mistrih // Read block info from BlockInfoStream, if specified. 5804cdb68ebSFrancis Visoiu Mistrih // The block info must be a top-level block. 5814cdb68ebSFrancis Visoiu Mistrih if (BlockInfoStream) { 5824cdb68ebSFrancis Visoiu Mistrih BitstreamCursor BlockInfoCursor(*BlockInfoStream); 583b12a864cSDuncan P. N. Exon Smith if (Error E = analyzeHeader(O, BlockInfoCursor).takeError()) 584b12a864cSDuncan P. N. Exon Smith return E; 5854cdb68ebSFrancis Visoiu Mistrih 5864cdb68ebSFrancis Visoiu Mistrih while (!BlockInfoCursor.AtEndOfStream()) { 5874cdb68ebSFrancis Visoiu Mistrih Expected<unsigned> MaybeCode = BlockInfoCursor.ReadCode(); 5884cdb68ebSFrancis Visoiu Mistrih if (!MaybeCode) 5894cdb68ebSFrancis Visoiu Mistrih return MaybeCode.takeError(); 5904cdb68ebSFrancis Visoiu Mistrih if (MaybeCode.get() != bitc::ENTER_SUBBLOCK) 5914cdb68ebSFrancis Visoiu Mistrih return reportError("Invalid record at top-level in block info file"); 5924cdb68ebSFrancis Visoiu Mistrih 5934cdb68ebSFrancis Visoiu Mistrih Expected<unsigned> MaybeBlockID = BlockInfoCursor.ReadSubBlockID(); 5944cdb68ebSFrancis Visoiu Mistrih if (!MaybeBlockID) 5954cdb68ebSFrancis Visoiu Mistrih return MaybeBlockID.takeError(); 5964cdb68ebSFrancis Visoiu Mistrih if (MaybeBlockID.get() == bitc::BLOCKINFO_BLOCK_ID) { 59749e75ebdSKrzysztof Parzyszek std::optional<BitstreamBlockInfo> NewBlockInfo; 598b12a864cSDuncan P. N. Exon Smith if (Error E = 599b12a864cSDuncan P. N. Exon Smith BlockInfoCursor.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true) 600b12a864cSDuncan P. N. Exon Smith .moveInto(NewBlockInfo)) 601b12a864cSDuncan P. N. Exon Smith return E; 6024cdb68ebSFrancis Visoiu Mistrih if (!NewBlockInfo) 6034cdb68ebSFrancis Visoiu Mistrih return reportError("Malformed BlockInfoBlock in block info file"); 6044cdb68ebSFrancis Visoiu Mistrih BlockInfo = std::move(*NewBlockInfo); 6054cdb68ebSFrancis Visoiu Mistrih break; 6064cdb68ebSFrancis Visoiu Mistrih } 6074cdb68ebSFrancis Visoiu Mistrih 6084cdb68ebSFrancis Visoiu Mistrih if (Error Err = BlockInfoCursor.SkipBlock()) 6094cdb68ebSFrancis Visoiu Mistrih return Err; 6104cdb68ebSFrancis Visoiu Mistrih } 6114cdb68ebSFrancis Visoiu Mistrih } 6124cdb68ebSFrancis Visoiu Mistrih 6134cdb68ebSFrancis Visoiu Mistrih // Parse the top-level structure. We only allow blocks at the top-level. 6144cdb68ebSFrancis Visoiu Mistrih while (!Stream.AtEndOfStream()) { 6154cdb68ebSFrancis Visoiu Mistrih Expected<unsigned> MaybeCode = Stream.ReadCode(); 6164cdb68ebSFrancis Visoiu Mistrih if (!MaybeCode) 6174cdb68ebSFrancis Visoiu Mistrih return MaybeCode.takeError(); 6184cdb68ebSFrancis Visoiu Mistrih if (MaybeCode.get() != bitc::ENTER_SUBBLOCK) 6194cdb68ebSFrancis Visoiu Mistrih return reportError("Invalid record at top-level"); 6204cdb68ebSFrancis Visoiu Mistrih 6214cdb68ebSFrancis Visoiu Mistrih Expected<unsigned> MaybeBlockID = Stream.ReadSubBlockID(); 6224cdb68ebSFrancis Visoiu Mistrih if (!MaybeBlockID) 6234cdb68ebSFrancis Visoiu Mistrih return MaybeBlockID.takeError(); 6244cdb68ebSFrancis Visoiu Mistrih 6254cdb68ebSFrancis Visoiu Mistrih if (Error E = parseBlock(MaybeBlockID.get(), 0, O, CheckHash)) 6264cdb68ebSFrancis Visoiu Mistrih return E; 6274cdb68ebSFrancis Visoiu Mistrih ++NumTopBlocks; 6284cdb68ebSFrancis Visoiu Mistrih } 6294cdb68ebSFrancis Visoiu Mistrih 6304cdb68ebSFrancis Visoiu Mistrih return Error::success(); 6314cdb68ebSFrancis Visoiu Mistrih } 6324cdb68ebSFrancis Visoiu Mistrih 6334cdb68ebSFrancis Visoiu Mistrih void BitcodeAnalyzer::printStats(BCDumpOptions O, 63449e75ebdSKrzysztof Parzyszek std::optional<StringRef> Filename) { 6354cdb68ebSFrancis Visoiu Mistrih uint64_t BufferSizeBits = Stream.getBitcodeBytes().size() * CHAR_BIT; 6364cdb68ebSFrancis Visoiu Mistrih // Print a summary of the read file. 6374cdb68ebSFrancis Visoiu Mistrih O.OS << "Summary "; 6384cdb68ebSFrancis Visoiu Mistrih if (Filename) 6394cdb68ebSFrancis Visoiu Mistrih O.OS << "of " << Filename->data() << ":\n"; 6404cdb68ebSFrancis Visoiu Mistrih O.OS << " Total size: "; 6414cdb68ebSFrancis Visoiu Mistrih printSize(O.OS, BufferSizeBits); 6424cdb68ebSFrancis Visoiu Mistrih O.OS << "\n"; 6434cdb68ebSFrancis Visoiu Mistrih O.OS << " Stream type: "; 6444cdb68ebSFrancis Visoiu Mistrih switch (CurStreamType) { 6454cdb68ebSFrancis Visoiu Mistrih case UnknownBitstream: 6464cdb68ebSFrancis Visoiu Mistrih O.OS << "unknown\n"; 6474cdb68ebSFrancis Visoiu Mistrih break; 6484cdb68ebSFrancis Visoiu Mistrih case LLVMIRBitstream: 6494cdb68ebSFrancis Visoiu Mistrih O.OS << "LLVM IR\n"; 6504cdb68ebSFrancis Visoiu Mistrih break; 6514cdb68ebSFrancis Visoiu Mistrih case ClangSerializedASTBitstream: 6524cdb68ebSFrancis Visoiu Mistrih O.OS << "Clang Serialized AST\n"; 6534cdb68ebSFrancis Visoiu Mistrih break; 6544cdb68ebSFrancis Visoiu Mistrih case ClangSerializedDiagnosticsBitstream: 6554cdb68ebSFrancis Visoiu Mistrih O.OS << "Clang Serialized Diagnostics\n"; 6564cdb68ebSFrancis Visoiu Mistrih break; 65784e80979SFrancis Visoiu Mistrih case LLVMBitstreamRemarks: 65884e80979SFrancis Visoiu Mistrih O.OS << "LLVM Remarks\n"; 65984e80979SFrancis Visoiu Mistrih break; 6604cdb68ebSFrancis Visoiu Mistrih } 6614cdb68ebSFrancis Visoiu Mistrih O.OS << " # Toplevel Blocks: " << NumTopBlocks << "\n"; 6624cdb68ebSFrancis Visoiu Mistrih O.OS << "\n"; 6634cdb68ebSFrancis Visoiu Mistrih 6644cdb68ebSFrancis Visoiu Mistrih // Emit per-block stats. 6654cdb68ebSFrancis Visoiu Mistrih O.OS << "Per-block Summary:\n"; 6661457e783SKazu Hirata for (const auto &Stat : BlockIDStats) { 6671457e783SKazu Hirata O.OS << " Block ID #" << Stat.first; 66849e75ebdSKrzysztof Parzyszek if (std::optional<const char *> BlockName = 6691457e783SKazu Hirata GetBlockName(Stat.first, BlockInfo, CurStreamType)) 6704cdb68ebSFrancis Visoiu Mistrih O.OS << " (" << *BlockName << ")"; 6714cdb68ebSFrancis Visoiu Mistrih O.OS << ":\n"; 6724cdb68ebSFrancis Visoiu Mistrih 6731457e783SKazu Hirata const PerBlockIDStats &Stats = Stat.second; 6744cdb68ebSFrancis Visoiu Mistrih O.OS << " Num Instances: " << Stats.NumInstances << "\n"; 6754cdb68ebSFrancis Visoiu Mistrih O.OS << " Total Size: "; 6764cdb68ebSFrancis Visoiu Mistrih printSize(O.OS, Stats.NumBits); 6774cdb68ebSFrancis Visoiu Mistrih O.OS << "\n"; 6784cdb68ebSFrancis Visoiu Mistrih double pct = (Stats.NumBits * 100.0) / BufferSizeBits; 6794cdb68ebSFrancis Visoiu Mistrih O.OS << " Percent of file: " << format("%2.4f%%", pct) << "\n"; 6804cdb68ebSFrancis Visoiu Mistrih if (Stats.NumInstances > 1) { 6814cdb68ebSFrancis Visoiu Mistrih O.OS << " Average Size: "; 6824cdb68ebSFrancis Visoiu Mistrih printSize(O.OS, Stats.NumBits / (double)Stats.NumInstances); 6834cdb68ebSFrancis Visoiu Mistrih O.OS << "\n"; 6844cdb68ebSFrancis Visoiu Mistrih O.OS << " Tot/Avg SubBlocks: " << Stats.NumSubBlocks << "/" 6854cdb68ebSFrancis Visoiu Mistrih << Stats.NumSubBlocks / (double)Stats.NumInstances << "\n"; 6864cdb68ebSFrancis Visoiu Mistrih O.OS << " Tot/Avg Abbrevs: " << Stats.NumAbbrevs << "/" 6874cdb68ebSFrancis Visoiu Mistrih << Stats.NumAbbrevs / (double)Stats.NumInstances << "\n"; 6884cdb68ebSFrancis Visoiu Mistrih O.OS << " Tot/Avg Records: " << Stats.NumRecords << "/" 6894cdb68ebSFrancis Visoiu Mistrih << Stats.NumRecords / (double)Stats.NumInstances << "\n"; 6904cdb68ebSFrancis Visoiu Mistrih } else { 6914cdb68ebSFrancis Visoiu Mistrih O.OS << " Num SubBlocks: " << Stats.NumSubBlocks << "\n"; 6924cdb68ebSFrancis Visoiu Mistrih O.OS << " Num Abbrevs: " << Stats.NumAbbrevs << "\n"; 6934cdb68ebSFrancis Visoiu Mistrih O.OS << " Num Records: " << Stats.NumRecords << "\n"; 6944cdb68ebSFrancis Visoiu Mistrih } 6954cdb68ebSFrancis Visoiu Mistrih if (Stats.NumRecords) { 6964cdb68ebSFrancis Visoiu Mistrih double pct = (Stats.NumAbbreviatedRecords * 100.0) / Stats.NumRecords; 6974cdb68ebSFrancis Visoiu Mistrih O.OS << " Percent Abbrevs: " << format("%2.4f%%", pct) << "\n"; 6984cdb68ebSFrancis Visoiu Mistrih } 6994cdb68ebSFrancis Visoiu Mistrih O.OS << "\n"; 7004cdb68ebSFrancis Visoiu Mistrih 7014cdb68ebSFrancis Visoiu Mistrih // Print a histogram of the codes we see. 7024cdb68ebSFrancis Visoiu Mistrih if (O.Histogram && !Stats.CodeFreq.empty()) { 7034cdb68ebSFrancis Visoiu Mistrih std::vector<std::pair<unsigned, unsigned>> FreqPairs; // <freq,code> 7044cdb68ebSFrancis Visoiu Mistrih for (unsigned i = 0, e = Stats.CodeFreq.size(); i != e; ++i) 7054cdb68ebSFrancis Visoiu Mistrih if (unsigned Freq = Stats.CodeFreq[i].NumInstances) 7064cdb68ebSFrancis Visoiu Mistrih FreqPairs.push_back(std::make_pair(Freq, i)); 7074cdb68ebSFrancis Visoiu Mistrih llvm::stable_sort(FreqPairs); 7084cdb68ebSFrancis Visoiu Mistrih std::reverse(FreqPairs.begin(), FreqPairs.end()); 7094cdb68ebSFrancis Visoiu Mistrih 7104cdb68ebSFrancis Visoiu Mistrih O.OS << "\tRecord Histogram:\n"; 7114cdb68ebSFrancis Visoiu Mistrih O.OS << "\t\t Count # Bits b/Rec % Abv Record Kind\n"; 7121457e783SKazu Hirata for (const auto &FreqPair : FreqPairs) { 7131457e783SKazu Hirata const PerRecordStats &RecStats = Stats.CodeFreq[FreqPair.second]; 7144cdb68ebSFrancis Visoiu Mistrih 7154cdb68ebSFrancis Visoiu Mistrih O.OS << format("\t\t%7d %9lu", RecStats.NumInstances, 7164cdb68ebSFrancis Visoiu Mistrih (unsigned long)RecStats.TotalBits); 7174cdb68ebSFrancis Visoiu Mistrih 7184cdb68ebSFrancis Visoiu Mistrih if (RecStats.NumInstances > 1) 7194cdb68ebSFrancis Visoiu Mistrih O.OS << format(" %9.1f", 7204cdb68ebSFrancis Visoiu Mistrih (double)RecStats.TotalBits / RecStats.NumInstances); 7214cdb68ebSFrancis Visoiu Mistrih else 7224cdb68ebSFrancis Visoiu Mistrih O.OS << " "; 7234cdb68ebSFrancis Visoiu Mistrih 7244cdb68ebSFrancis Visoiu Mistrih if (RecStats.NumAbbrev) 7254cdb68ebSFrancis Visoiu Mistrih O.OS << format(" %7.2f", (double)RecStats.NumAbbrev / 7264cdb68ebSFrancis Visoiu Mistrih RecStats.NumInstances * 100); 7274cdb68ebSFrancis Visoiu Mistrih else 7284cdb68ebSFrancis Visoiu Mistrih O.OS << " "; 7294cdb68ebSFrancis Visoiu Mistrih 7304cdb68ebSFrancis Visoiu Mistrih O.OS << " "; 73149e75ebdSKrzysztof Parzyszek if (std::optional<const char *> CodeName = GetCodeName( 7321457e783SKazu Hirata FreqPair.second, Stat.first, BlockInfo, CurStreamType)) 7334cdb68ebSFrancis Visoiu Mistrih O.OS << *CodeName << "\n"; 7344cdb68ebSFrancis Visoiu Mistrih else 7351457e783SKazu Hirata O.OS << "UnknownCode" << FreqPair.second << "\n"; 7364cdb68ebSFrancis Visoiu Mistrih } 7374cdb68ebSFrancis Visoiu Mistrih O.OS << "\n"; 7384cdb68ebSFrancis Visoiu Mistrih } 7394cdb68ebSFrancis Visoiu Mistrih } 7404cdb68ebSFrancis Visoiu Mistrih } 7414cdb68ebSFrancis Visoiu Mistrih 7424cdb68ebSFrancis Visoiu Mistrih Error BitcodeAnalyzer::parseBlock(unsigned BlockID, unsigned IndentLevel, 74349e75ebdSKrzysztof Parzyszek std::optional<BCDumpOptions> O, 74449e75ebdSKrzysztof Parzyszek std::optional<StringRef> CheckHash) { 7454cdb68ebSFrancis Visoiu Mistrih std::string Indent(IndentLevel * 2, ' '); 7464cdb68ebSFrancis Visoiu Mistrih uint64_t BlockBitStart = Stream.GetCurrentBitNo(); 7474cdb68ebSFrancis Visoiu Mistrih 7484cdb68ebSFrancis Visoiu Mistrih // Get the statistics for this BlockID. 7494cdb68ebSFrancis Visoiu Mistrih PerBlockIDStats &BlockStats = BlockIDStats[BlockID]; 7504cdb68ebSFrancis Visoiu Mistrih 7514cdb68ebSFrancis Visoiu Mistrih BlockStats.NumInstances++; 7524cdb68ebSFrancis Visoiu Mistrih 7534cdb68ebSFrancis Visoiu Mistrih // BLOCKINFO is a special part of the stream. 7540916d96dSKazu Hirata bool DumpRecords = O.has_value(); 7554cdb68ebSFrancis Visoiu Mistrih if (BlockID == bitc::BLOCKINFO_BLOCK_ID) { 756e7fc2548Swilliam woodruff if (O && !O->DumpBlockinfo) 7574cdb68ebSFrancis Visoiu Mistrih O->OS << Indent << "<BLOCKINFO_BLOCK/>\n"; 75849e75ebdSKrzysztof Parzyszek std::optional<BitstreamBlockInfo> NewBlockInfo; 759b12a864cSDuncan P. N. Exon Smith if (Error E = Stream.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true) 760b12a864cSDuncan P. N. Exon Smith .moveInto(NewBlockInfo)) 761b12a864cSDuncan P. N. Exon Smith return E; 7624cdb68ebSFrancis Visoiu Mistrih if (!NewBlockInfo) 7634cdb68ebSFrancis Visoiu Mistrih return reportError("Malformed BlockInfoBlock"); 7644cdb68ebSFrancis Visoiu Mistrih BlockInfo = std::move(*NewBlockInfo); 7654cdb68ebSFrancis Visoiu Mistrih if (Error Err = Stream.JumpToBit(BlockBitStart)) 7664cdb68ebSFrancis Visoiu Mistrih return Err; 7674cdb68ebSFrancis Visoiu Mistrih // It's not really interesting to dump the contents of the blockinfo 768e7fc2548Swilliam woodruff // block, so only do it if the user explicitly requests it. 769e7fc2548Swilliam woodruff DumpRecords = O && O->DumpBlockinfo; 7704cdb68ebSFrancis Visoiu Mistrih } 7714cdb68ebSFrancis Visoiu Mistrih 7724cdb68ebSFrancis Visoiu Mistrih unsigned NumWords = 0; 7734cdb68ebSFrancis Visoiu Mistrih if (Error Err = Stream.EnterSubBlock(BlockID, &NumWords)) 7744cdb68ebSFrancis Visoiu Mistrih return Err; 7754cdb68ebSFrancis Visoiu Mistrih 7764cdb68ebSFrancis Visoiu Mistrih // Keep it for later, when we see a MODULE_HASH record 7774cdb68ebSFrancis Visoiu Mistrih uint64_t BlockEntryPos = Stream.getCurrentByteNo(); 7784cdb68ebSFrancis Visoiu Mistrih 77949e75ebdSKrzysztof Parzyszek std::optional<const char *> BlockName; 7804cdb68ebSFrancis Visoiu Mistrih if (DumpRecords) { 7814cdb68ebSFrancis Visoiu Mistrih O->OS << Indent << "<"; 7824cdb68ebSFrancis Visoiu Mistrih if ((BlockName = GetBlockName(BlockID, BlockInfo, CurStreamType))) 7834cdb68ebSFrancis Visoiu Mistrih O->OS << *BlockName; 7844cdb68ebSFrancis Visoiu Mistrih else 7854cdb68ebSFrancis Visoiu Mistrih O->OS << "UnknownBlock" << BlockID; 7864cdb68ebSFrancis Visoiu Mistrih 7874cdb68ebSFrancis Visoiu Mistrih if (!O->Symbolic && BlockName) 7884cdb68ebSFrancis Visoiu Mistrih O->OS << " BlockID=" << BlockID; 7894cdb68ebSFrancis Visoiu Mistrih 7904cdb68ebSFrancis Visoiu Mistrih O->OS << " NumWords=" << NumWords 7914cdb68ebSFrancis Visoiu Mistrih << " BlockCodeSize=" << Stream.getAbbrevIDWidth() << ">\n"; 7924cdb68ebSFrancis Visoiu Mistrih } 7934cdb68ebSFrancis Visoiu Mistrih 7944cdb68ebSFrancis Visoiu Mistrih SmallVector<uint64_t, 64> Record; 7954cdb68ebSFrancis Visoiu Mistrih 7964cdb68ebSFrancis Visoiu Mistrih // Keep the offset to the metadata index if seen. 7974cdb68ebSFrancis Visoiu Mistrih uint64_t MetadataIndexOffset = 0; 7984cdb68ebSFrancis Visoiu Mistrih 7994cdb68ebSFrancis Visoiu Mistrih // Read all the records for this block. 8002aed0813SKazu Hirata while (true) { 8014cdb68ebSFrancis Visoiu Mistrih if (Stream.AtEndOfStream()) 8024cdb68ebSFrancis Visoiu Mistrih return reportError("Premature end of bitstream"); 8034cdb68ebSFrancis Visoiu Mistrih 8044cdb68ebSFrancis Visoiu Mistrih uint64_t RecordStartBit = Stream.GetCurrentBitNo(); 8054cdb68ebSFrancis Visoiu Mistrih 806b12a864cSDuncan P. N. Exon Smith BitstreamEntry Entry; 807b12a864cSDuncan P. N. Exon Smith if (Error E = Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs) 808b12a864cSDuncan P. N. Exon Smith .moveInto(Entry)) 809b12a864cSDuncan P. N. Exon Smith return E; 8104cdb68ebSFrancis Visoiu Mistrih 8114cdb68ebSFrancis Visoiu Mistrih switch (Entry.Kind) { 8124cdb68ebSFrancis Visoiu Mistrih case BitstreamEntry::Error: 8134cdb68ebSFrancis Visoiu Mistrih return reportError("malformed bitcode file"); 8144cdb68ebSFrancis Visoiu Mistrih case BitstreamEntry::EndBlock: { 8154cdb68ebSFrancis Visoiu Mistrih uint64_t BlockBitEnd = Stream.GetCurrentBitNo(); 8164cdb68ebSFrancis Visoiu Mistrih BlockStats.NumBits += BlockBitEnd - BlockBitStart; 8174cdb68ebSFrancis Visoiu Mistrih if (DumpRecords) { 8184cdb68ebSFrancis Visoiu Mistrih O->OS << Indent << "</"; 8194cdb68ebSFrancis Visoiu Mistrih if (BlockName) 8204cdb68ebSFrancis Visoiu Mistrih O->OS << *BlockName << ">\n"; 8214cdb68ebSFrancis Visoiu Mistrih else 8224cdb68ebSFrancis Visoiu Mistrih O->OS << "UnknownBlock" << BlockID << ">\n"; 8234cdb68ebSFrancis Visoiu Mistrih } 8244cdb68ebSFrancis Visoiu Mistrih return Error::success(); 8254cdb68ebSFrancis Visoiu Mistrih } 8264cdb68ebSFrancis Visoiu Mistrih 8274cdb68ebSFrancis Visoiu Mistrih case BitstreamEntry::SubBlock: { 8284cdb68ebSFrancis Visoiu Mistrih uint64_t SubBlockBitStart = Stream.GetCurrentBitNo(); 8294cdb68ebSFrancis Visoiu Mistrih if (Error E = parseBlock(Entry.ID, IndentLevel + 1, O, CheckHash)) 8304cdb68ebSFrancis Visoiu Mistrih return E; 8314cdb68ebSFrancis Visoiu Mistrih ++BlockStats.NumSubBlocks; 8324cdb68ebSFrancis Visoiu Mistrih uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo(); 8334cdb68ebSFrancis Visoiu Mistrih 8344cdb68ebSFrancis Visoiu Mistrih // Don't include subblock sizes in the size of this block. 8354cdb68ebSFrancis Visoiu Mistrih BlockBitStart += SubBlockBitEnd - SubBlockBitStart; 8364cdb68ebSFrancis Visoiu Mistrih continue; 8374cdb68ebSFrancis Visoiu Mistrih } 8384cdb68ebSFrancis Visoiu Mistrih case BitstreamEntry::Record: 8394cdb68ebSFrancis Visoiu Mistrih // The interesting case. 8404cdb68ebSFrancis Visoiu Mistrih break; 8414cdb68ebSFrancis Visoiu Mistrih } 8424cdb68ebSFrancis Visoiu Mistrih 8434cdb68ebSFrancis Visoiu Mistrih if (Entry.ID == bitc::DEFINE_ABBREV) { 8444cdb68ebSFrancis Visoiu Mistrih if (Error Err = Stream.ReadAbbrevRecord()) 8454cdb68ebSFrancis Visoiu Mistrih return Err; 8464cdb68ebSFrancis Visoiu Mistrih ++BlockStats.NumAbbrevs; 8474cdb68ebSFrancis Visoiu Mistrih continue; 8484cdb68ebSFrancis Visoiu Mistrih } 8494cdb68ebSFrancis Visoiu Mistrih 8504cdb68ebSFrancis Visoiu Mistrih Record.clear(); 8514cdb68ebSFrancis Visoiu Mistrih 8524cdb68ebSFrancis Visoiu Mistrih ++BlockStats.NumRecords; 8534cdb68ebSFrancis Visoiu Mistrih 8544cdb68ebSFrancis Visoiu Mistrih StringRef Blob; 8554cdb68ebSFrancis Visoiu Mistrih uint64_t CurrentRecordPos = Stream.GetCurrentBitNo(); 856b12a864cSDuncan P. N. Exon Smith unsigned Code; 857b12a864cSDuncan P. N. Exon Smith if (Error E = Stream.readRecord(Entry.ID, Record, &Blob).moveInto(Code)) 858b12a864cSDuncan P. N. Exon Smith return E; 8594cdb68ebSFrancis Visoiu Mistrih 8604cdb68ebSFrancis Visoiu Mistrih // Increment the # occurrences of this code. 8614cdb68ebSFrancis Visoiu Mistrih if (BlockStats.CodeFreq.size() <= Code) 8624cdb68ebSFrancis Visoiu Mistrih BlockStats.CodeFreq.resize(Code + 1); 8634cdb68ebSFrancis Visoiu Mistrih BlockStats.CodeFreq[Code].NumInstances++; 8644cdb68ebSFrancis Visoiu Mistrih BlockStats.CodeFreq[Code].TotalBits += 8654cdb68ebSFrancis Visoiu Mistrih Stream.GetCurrentBitNo() - RecordStartBit; 8664cdb68ebSFrancis Visoiu Mistrih if (Entry.ID != bitc::UNABBREV_RECORD) { 8674cdb68ebSFrancis Visoiu Mistrih BlockStats.CodeFreq[Code].NumAbbrev++; 8684cdb68ebSFrancis Visoiu Mistrih ++BlockStats.NumAbbreviatedRecords; 8694cdb68ebSFrancis Visoiu Mistrih } 8704cdb68ebSFrancis Visoiu Mistrih 8714cdb68ebSFrancis Visoiu Mistrih if (DumpRecords) { 8724cdb68ebSFrancis Visoiu Mistrih O->OS << Indent << " <"; 87349e75ebdSKrzysztof Parzyszek std::optional<const char *> CodeName = 8744cdb68ebSFrancis Visoiu Mistrih GetCodeName(Code, BlockID, BlockInfo, CurStreamType); 8754cdb68ebSFrancis Visoiu Mistrih if (CodeName) 8764cdb68ebSFrancis Visoiu Mistrih O->OS << *CodeName; 8774cdb68ebSFrancis Visoiu Mistrih else 8784cdb68ebSFrancis Visoiu Mistrih O->OS << "UnknownCode" << Code; 8794cdb68ebSFrancis Visoiu Mistrih if (!O->Symbolic && CodeName) 8804cdb68ebSFrancis Visoiu Mistrih O->OS << " codeid=" << Code; 8814cdb68ebSFrancis Visoiu Mistrih const BitCodeAbbrev *Abbv = nullptr; 8824cdb68ebSFrancis Visoiu Mistrih if (Entry.ID != bitc::UNABBREV_RECORD) { 8838a718541SNikita Popov Expected<const BitCodeAbbrev *> MaybeAbbv = Stream.getAbbrev(Entry.ID); 8848a718541SNikita Popov if (!MaybeAbbv) 8858a718541SNikita Popov return MaybeAbbv.takeError(); 8868a718541SNikita Popov Abbv = MaybeAbbv.get(); 8874cdb68ebSFrancis Visoiu Mistrih O->OS << " abbrevid=" << Entry.ID; 8884cdb68ebSFrancis Visoiu Mistrih } 8894cdb68ebSFrancis Visoiu Mistrih 8904cdb68ebSFrancis Visoiu Mistrih for (unsigned i = 0, e = Record.size(); i != e; ++i) 8914cdb68ebSFrancis Visoiu Mistrih O->OS << " op" << i << "=" << (int64_t)Record[i]; 8924cdb68ebSFrancis Visoiu Mistrih 8934cdb68ebSFrancis Visoiu Mistrih // If we found a metadata index, let's verify that we had an offset 8944cdb68ebSFrancis Visoiu Mistrih // before and validate its forward reference offset was correct! 8954cdb68ebSFrancis Visoiu Mistrih if (BlockID == bitc::METADATA_BLOCK_ID) { 8964cdb68ebSFrancis Visoiu Mistrih if (Code == bitc::METADATA_INDEX_OFFSET) { 8974cdb68ebSFrancis Visoiu Mistrih if (Record.size() != 2) 8984cdb68ebSFrancis Visoiu Mistrih O->OS << "(Invalid record)"; 8994cdb68ebSFrancis Visoiu Mistrih else { 9004cdb68ebSFrancis Visoiu Mistrih auto Offset = Record[0] + (Record[1] << 32); 9014cdb68ebSFrancis Visoiu Mistrih MetadataIndexOffset = Stream.GetCurrentBitNo() + Offset; 9024cdb68ebSFrancis Visoiu Mistrih } 9034cdb68ebSFrancis Visoiu Mistrih } 9044cdb68ebSFrancis Visoiu Mistrih if (Code == bitc::METADATA_INDEX) { 9054cdb68ebSFrancis Visoiu Mistrih O->OS << " (offset "; 9064cdb68ebSFrancis Visoiu Mistrih if (MetadataIndexOffset == RecordStartBit) 9074cdb68ebSFrancis Visoiu Mistrih O->OS << "match)"; 9084cdb68ebSFrancis Visoiu Mistrih else 9094cdb68ebSFrancis Visoiu Mistrih O->OS << "mismatch: " << MetadataIndexOffset << " vs " 9104cdb68ebSFrancis Visoiu Mistrih << RecordStartBit << ")"; 9114cdb68ebSFrancis Visoiu Mistrih } 9124cdb68ebSFrancis Visoiu Mistrih } 9134cdb68ebSFrancis Visoiu Mistrih 9144cdb68ebSFrancis Visoiu Mistrih // If we found a module hash, let's verify that it matches! 9154cdb68ebSFrancis Visoiu Mistrih if (BlockID == bitc::MODULE_BLOCK_ID && Code == bitc::MODULE_CODE_HASH && 9160916d96dSKazu Hirata CheckHash) { 9174cdb68ebSFrancis Visoiu Mistrih if (Record.size() != 5) 9184cdb68ebSFrancis Visoiu Mistrih O->OS << " (invalid)"; 9194cdb68ebSFrancis Visoiu Mistrih else { 9204cdb68ebSFrancis Visoiu Mistrih // Recompute the hash and compare it to the one in the bitcode 9214cdb68ebSFrancis Visoiu Mistrih SHA1 Hasher; 922330268baSArgyrios Kyrtzidis std::array<uint8_t, 20> Hash; 9234cdb68ebSFrancis Visoiu Mistrih Hasher.update(*CheckHash); 9244cdb68ebSFrancis Visoiu Mistrih { 9254cdb68ebSFrancis Visoiu Mistrih int BlockSize = (CurrentRecordPos / 8) - BlockEntryPos; 9264cdb68ebSFrancis Visoiu Mistrih auto Ptr = Stream.getPointerToByte(BlockEntryPos, BlockSize); 9274cdb68ebSFrancis Visoiu Mistrih Hasher.update(ArrayRef<uint8_t>(Ptr, BlockSize)); 9284cdb68ebSFrancis Visoiu Mistrih Hash = Hasher.result(); 9294cdb68ebSFrancis Visoiu Mistrih } 930330268baSArgyrios Kyrtzidis std::array<uint8_t, 20> RecordedHash; 9314cdb68ebSFrancis Visoiu Mistrih int Pos = 0; 9324cdb68ebSFrancis Visoiu Mistrih for (auto &Val : Record) { 9334cdb68ebSFrancis Visoiu Mistrih assert(!(Val >> 32) && "Unexpected high bits set"); 9349a9bc236SBenjamin Kramer support::endian::write32be(&RecordedHash[Pos], Val); 9359a9bc236SBenjamin Kramer Pos += 4; 9364cdb68ebSFrancis Visoiu Mistrih } 937330268baSArgyrios Kyrtzidis if (Hash == RecordedHash) 9384cdb68ebSFrancis Visoiu Mistrih O->OS << " (match)"; 9394cdb68ebSFrancis Visoiu Mistrih else 9404cdb68ebSFrancis Visoiu Mistrih O->OS << " (!mismatch!)"; 9414cdb68ebSFrancis Visoiu Mistrih } 9424cdb68ebSFrancis Visoiu Mistrih } 9434cdb68ebSFrancis Visoiu Mistrih 9444cdb68ebSFrancis Visoiu Mistrih O->OS << "/>"; 9454cdb68ebSFrancis Visoiu Mistrih 9464cdb68ebSFrancis Visoiu Mistrih if (Abbv) { 9474cdb68ebSFrancis Visoiu Mistrih for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) { 9484cdb68ebSFrancis Visoiu Mistrih const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); 9494cdb68ebSFrancis Visoiu Mistrih if (!Op.isEncoding() || Op.getEncoding() != BitCodeAbbrevOp::Array) 9504cdb68ebSFrancis Visoiu Mistrih continue; 9514cdb68ebSFrancis Visoiu Mistrih assert(i + 2 == e && "Array op not second to last"); 9524cdb68ebSFrancis Visoiu Mistrih std::string Str; 9534cdb68ebSFrancis Visoiu Mistrih bool ArrayIsPrintable = true; 9544cdb68ebSFrancis Visoiu Mistrih for (unsigned j = i - 1, je = Record.size(); j != je; ++j) { 9554cdb68ebSFrancis Visoiu Mistrih if (!isPrint(static_cast<unsigned char>(Record[j]))) { 9564cdb68ebSFrancis Visoiu Mistrih ArrayIsPrintable = false; 9574cdb68ebSFrancis Visoiu Mistrih break; 9584cdb68ebSFrancis Visoiu Mistrih } 9594cdb68ebSFrancis Visoiu Mistrih Str += (char)Record[j]; 9604cdb68ebSFrancis Visoiu Mistrih } 9614cdb68ebSFrancis Visoiu Mistrih if (ArrayIsPrintable) 9624cdb68ebSFrancis Visoiu Mistrih O->OS << " record string = '" << Str << "'"; 9634cdb68ebSFrancis Visoiu Mistrih break; 9644cdb68ebSFrancis Visoiu Mistrih } 9654cdb68ebSFrancis Visoiu Mistrih } 9664cdb68ebSFrancis Visoiu Mistrih 9674cdb68ebSFrancis Visoiu Mistrih if (Blob.data()) { 9684cdb68ebSFrancis Visoiu Mistrih if (canDecodeBlob(Code, BlockID)) { 9694cdb68ebSFrancis Visoiu Mistrih if (Error E = decodeMetadataStringsBlob(Indent, Record, Blob, O->OS)) 9704cdb68ebSFrancis Visoiu Mistrih return E; 9714cdb68ebSFrancis Visoiu Mistrih } else { 9724cdb68ebSFrancis Visoiu Mistrih O->OS << " blob data = "; 9734cdb68ebSFrancis Visoiu Mistrih if (O->ShowBinaryBlobs) { 9744cdb68ebSFrancis Visoiu Mistrih O->OS << "'"; 9754cdb68ebSFrancis Visoiu Mistrih O->OS.write_escaped(Blob, /*hex=*/true) << "'"; 9764cdb68ebSFrancis Visoiu Mistrih } else { 9774cdb68ebSFrancis Visoiu Mistrih bool BlobIsPrintable = true; 978f6bce30cSKazu Hirata for (char C : Blob) 979f6bce30cSKazu Hirata if (!isPrint(static_cast<unsigned char>(C))) { 9804cdb68ebSFrancis Visoiu Mistrih BlobIsPrintable = false; 9814cdb68ebSFrancis Visoiu Mistrih break; 9824cdb68ebSFrancis Visoiu Mistrih } 9834cdb68ebSFrancis Visoiu Mistrih 9844cdb68ebSFrancis Visoiu Mistrih if (BlobIsPrintable) 9854cdb68ebSFrancis Visoiu Mistrih O->OS << "'" << Blob << "'"; 9864cdb68ebSFrancis Visoiu Mistrih else 9874cdb68ebSFrancis Visoiu Mistrih O->OS << "unprintable, " << Blob.size() << " bytes."; 9884cdb68ebSFrancis Visoiu Mistrih } 9894cdb68ebSFrancis Visoiu Mistrih } 9904cdb68ebSFrancis Visoiu Mistrih } 9914cdb68ebSFrancis Visoiu Mistrih 9924cdb68ebSFrancis Visoiu Mistrih O->OS << "\n"; 9934cdb68ebSFrancis Visoiu Mistrih } 9944cdb68ebSFrancis Visoiu Mistrih 9954cdb68ebSFrancis Visoiu Mistrih // Make sure that we can skip the current record. 9964cdb68ebSFrancis Visoiu Mistrih if (Error Err = Stream.JumpToBit(CurrentRecordPos)) 9974cdb68ebSFrancis Visoiu Mistrih return Err; 9984cdb68ebSFrancis Visoiu Mistrih if (Expected<unsigned> Skipped = Stream.skipRecord(Entry.ID)) 9994cdb68ebSFrancis Visoiu Mistrih ; // Do nothing. 10004cdb68ebSFrancis Visoiu Mistrih else 10014cdb68ebSFrancis Visoiu Mistrih return Skipped.takeError(); 10024cdb68ebSFrancis Visoiu Mistrih } 10034cdb68ebSFrancis Visoiu Mistrih } 10044cdb68ebSFrancis Visoiu Mistrih 1005