[llvm] r365286 - [llvm-bcanalyzer] Refactor and move to libLLVMBitReader
Francis Visoiu Mistrih via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 8 09:19:51 PDT 2019
Hi Mikael,
Thanks for pointing this out. Should be fixed in r365340.
> On Jul 8, 2019, at 12:03 AM, Mikael Holmén <mikael.holmen at ericsson.com> wrote:
>
> Hi Francis,
>
> I get a warning from gcc 7.4 on this commit:
>
> ../lib/Bitcode/Reader/BitcodeAnalyzer.cpp: In member function
> 'llvm::Error
> llvm::BitcodeAnalyzer::analyze(llvm::Optional<llvm::BCDumpOptions>,
> llvm::Optional<llvm::StringRef>)':
> ../lib/Bitcode/Reader/BitcodeAnalyzer.cpp:549:23: error: variable
> 'BlockInfoStreamType' set but not used [-Werror=unused-but-set-variable]
> CurStreamTypeType BlockInfoStreamType;
> ^~~~~~~~~~~~~~~~~~~
>
> The code is
>
> BitstreamCursor BlockInfoCursor(*BlockInfoStream);
> CurStreamTypeType BlockInfoStreamType;
> Expected<CurStreamTypeType> H = analyzeHeader(O, BlockInfoCursor);
> if (!H)
> return H.takeError();
> BlockInfoStreamType = *H;
>
> Can BlockInfoStreamType simply be removed or what?
>
> Regards,
> Mikael
>
>
> On 2019-07-08 04:06, Francis Visoiu Mistrih via llvm-commits wrote:
>> Author: thegameg
>> Date: Sun Jul 7 19:06:34 2019
>> New Revision: 365286
>>
>> URL: https://protect2.fireeye.com/url?k=dcf79f9a-80239a25-dcf7df01-868f633dbf25-0101d38e10254b21&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%3Frev%3D365286%26view%3Drev
>> Log:
>> [llvm-bcanalyzer] Refactor and move to libLLVMBitReader
>>
>> This allows us to use the analyzer from unit tests.
>>
>> * Refactor the interface to use proper error handling for most functions
>> after JF's work.
>> * Move everything into a BitstreamAnalyzer class.
>> * Move that to Bitcode/BitcodeAnalyzer.h.
>>
>> Differential Revision: https://protect2.fireeye.com/url?k=84b061e8-d8646457-84b02173-868f633dbf25-ad256f93a833fb9c&q=1&u=https%3A%2F%2Freviews.llvm.org%2FD64116
>>
>> Added:
>> llvm/trunk/include/llvm/Bitcode/BitcodeAnalyzer.h
>> llvm/trunk/lib/Bitcode/Reader/BitcodeAnalyzer.cpp
>> Modified:
>> llvm/trunk/lib/Bitcode/Reader/CMakeLists.txt
>> llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
>>
>> Added: llvm/trunk/include/llvm/Bitcode/BitcodeAnalyzer.h
>> URL: https://protect2.fireeye.com/url?k=e37f6483-bfab613c-e37f2418-868f633dbf25-4c488e8831d42797&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Finclude%2Fllvm%2FBitcode%2FBitcodeAnalyzer.h%3Frev%3D365286%26view%3Dauto
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Bitcode/BitcodeAnalyzer.h (added)
>> +++ llvm/trunk/include/llvm/Bitcode/BitcodeAnalyzer.h Sun Jul 7 19:06:34 2019
>> @@ -0,0 +1,103 @@
>> +//===- llvm/Bitcode/BitcodeAnalyzer.h - Bitcode analyzer --------*- C++ -*-===//
>> +//
>> +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>> +// See https://protect2.fireeye.com/url?k=ec0e1db4-b0da180b-ec0e5d2f-868f633dbf25-3d7fb3b739a8b563&q=1&u=https%3A%2F%2Fllvm.org%2FLICENSE.txt for license information.
>> +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>> +//
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// This header defines interfaces to analyze LLVM bitcode files/streams.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_BITCODE_BITCODE_ANALYZER_H
>> +#define LLVM_BITCODE_BITCODE_ANALYZER_H
>> +
>> +#include "llvm/ADT/ArrayRef.h"
>> +#include "llvm/ADT/Optional.h"
>> +#include "llvm/ADT/StringRef.h"
>> +#include "llvm/Bitstream/BitstreamReader.h"
>> +#include "llvm/Support/Error.h"
>> +#include "llvm/Support/raw_ostream.h"
>> +#include <map>
>> +#include <vector>
>> +
>> +namespace llvm {
>> +
>> +/// CurStreamTypeType - A type for CurStreamType
>> +enum CurStreamTypeType {
>> + UnknownBitstream,
>> + LLVMIRBitstream,
>> + ClangSerializedASTBitstream,
>> + ClangSerializedDiagnosticsBitstream,
>> +};
>> +
>> +struct BCDumpOptions {
>> + /// The stream.
>> + raw_ostream &OS;
>> + /// Print per-code histogram.
>> + bool Histogram = false;
>> + /// Don't emit numeric info in dump if symbolic info is available.
>> + bool Symbolic = false;
>> + /// Print binary blobs using hex escapes.
>> + bool ShowBinaryBlobs = false;
>> +
>> + BCDumpOptions(raw_ostream &OS) : OS(OS) {}
>> +};
>> +
>> +class BitcodeAnalyzer {
>> + BitstreamCursor Stream;
>> + BitstreamBlockInfo BlockInfo;
>> + CurStreamTypeType CurStreamType;
>> + Optional<BitstreamCursor> BlockInfoStream;
>> + unsigned NumTopBlocks = 0;
>> +
>> + struct PerRecordStats {
>> + unsigned NumInstances;
>> + unsigned NumAbbrev;
>> + uint64_t TotalBits;
>> + PerRecordStats() : NumInstances(0), NumAbbrev(0), TotalBits(0) {}
>> + };
>> +
>> + struct PerBlockIDStats {
>> + /// NumInstances - This the number of times this block ID has been seen.
>> + unsigned NumInstances;
>> + /// NumBits - The total size in bits of all of these blocks.
>> + uint64_t NumBits;
>> + /// NumSubBlocks - The total number of blocks these blocks contain.
>> + unsigned NumSubBlocks;
>> + /// NumAbbrevs - The total number of abbreviations.
>> + unsigned NumAbbrevs;
>> + /// NumRecords - The total number of records these blocks contain, and the
>> + /// number that are abbreviated.
>> + unsigned NumRecords, NumAbbreviatedRecords;
>> + /// CodeFreq - Keep track of the number of times we see each code.
>> + std::vector<PerRecordStats> CodeFreq;
>> + PerBlockIDStats()
>> + : NumInstances(0), NumBits(0), NumSubBlocks(0), NumAbbrevs(0),
>> + NumRecords(0), NumAbbreviatedRecords(0) {}
>> + };
>> +
>> + std::map<unsigned, PerBlockIDStats> BlockIDStats;
>> +
>> +public:
>> + BitcodeAnalyzer(StringRef Buffer, Optional<StringRef> BlockInfoBuffer = None);
>> + /// Analyze the bitcode file.
>> + Error analyze(Optional<BCDumpOptions> O = None,
>> + Optional<StringRef> CheckHash = None);
>> + /// Print stats about the bitcode file.
>> + void printStats(BCDumpOptions O, Optional<StringRef> Filename = None);
>> +
>> +private:
>> + /// Read a block, updating statistics, etc.
>> + Error parseBlock(unsigned BlockID, unsigned IndentLevel,
>> + Optional<BCDumpOptions> O = None,
>> + Optional<StringRef> CheckHash = None);
>> +
>> + Error decodeMetadataStringsBlob(StringRef Indent, ArrayRef<uint64_t> Record,
>> + StringRef Blob, raw_ostream &OS);
>> +};
>> +
>> +} // end namespace llvm
>> +
>> +#endif // LLVM_BITCODE_BITCODE_ANALYZER_H
>>
>> Added: llvm/trunk/lib/Bitcode/Reader/BitcodeAnalyzer.cpp
>> URL: https://protect2.fireeye.com/url?k=c6ffb7da-9a2bb265-c6fff741-868f633dbf25-8012c5d226bd697a&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Flib%2FBitcode%2FReader%2FBitcodeAnalyzer.cpp%3Frev%3D365286%26view%3Dauto
>> ==============================================================================
>> --- llvm/trunk/lib/Bitcode/Reader/BitcodeAnalyzer.cpp (added)
>> +++ llvm/trunk/lib/Bitcode/Reader/BitcodeAnalyzer.cpp Sun Jul 7 19:06:34 2019
>> @@ -0,0 +1,977 @@
>> +//===- BitcodeAnalyzer.cpp - Internal BitcodeAnalyzer implementation ------===//
>> +//
>> +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>> +// See https://protect2.fireeye.com/url?k=60ea549e-3c3e5121-60ea1405-868f633dbf25-e3e355f939634f8b&q=1&u=https%3A%2F%2Fllvm.org%2FLICENSE.txt for license information.
>> +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>> +//
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "llvm/Bitcode/BitcodeAnalyzer.h"
>> +#include "llvm/Bitcode/BitcodeReader.h"
>> +#include "llvm/Bitcode/LLVMBitCodes.h"
>> +#include "llvm/Support/Format.h"
>> +#include "llvm/Support/SHA1.h"
>> +
>> +using namespace llvm;
>> +
>> +static Error reportError(StringRef Message) {
>> + return createStringError(std::errc::illegal_byte_sequence, Message.data());
>> +}
>> +
>> +/// Return a symbolic block name if known, otherwise return null.
>> +static Optional<const char *> GetBlockName(unsigned BlockID,
>> + const BitstreamBlockInfo &BlockInfo,
>> + CurStreamTypeType CurStreamType) {
>> + // Standard blocks for all bitcode files.
>> + if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {
>> + if (BlockID == bitc::BLOCKINFO_BLOCK_ID)
>> + return "BLOCKINFO_BLOCK";
>> + return None;
>> + }
>> +
>> + // Check to see if we have a blockinfo record for this block, with a name.
>> + if (const BitstreamBlockInfo::BlockInfo *Info =
>> + BlockInfo.getBlockInfo(BlockID)) {
>> + if (!Info->Name.empty())
>> + return Info->Name.c_str();
>> + }
>> +
>> + if (CurStreamType != LLVMIRBitstream)
>> + return None;
>> +
>> + switch (BlockID) {
>> + default:
>> + return None;
>> + case bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID:
>> + return "OPERAND_BUNDLE_TAGS_BLOCK";
>> + case bitc::MODULE_BLOCK_ID:
>> + return "MODULE_BLOCK";
>> + case bitc::PARAMATTR_BLOCK_ID:
>> + return "PARAMATTR_BLOCK";
>> + case bitc::PARAMATTR_GROUP_BLOCK_ID:
>> + return "PARAMATTR_GROUP_BLOCK_ID";
>> + case bitc::TYPE_BLOCK_ID_NEW:
>> + return "TYPE_BLOCK_ID";
>> + case bitc::CONSTANTS_BLOCK_ID:
>> + return "CONSTANTS_BLOCK";
>> + case bitc::FUNCTION_BLOCK_ID:
>> + return "FUNCTION_BLOCK";
>> + case bitc::IDENTIFICATION_BLOCK_ID:
>> + return "IDENTIFICATION_BLOCK_ID";
>> + case bitc::VALUE_SYMTAB_BLOCK_ID:
>> + return "VALUE_SYMTAB";
>> + case bitc::METADATA_BLOCK_ID:
>> + return "METADATA_BLOCK";
>> + case bitc::METADATA_KIND_BLOCK_ID:
>> + return "METADATA_KIND_BLOCK";
>> + case bitc::METADATA_ATTACHMENT_ID:
>> + return "METADATA_ATTACHMENT_BLOCK";
>> + case bitc::USELIST_BLOCK_ID:
>> + return "USELIST_BLOCK_ID";
>> + case bitc::GLOBALVAL_SUMMARY_BLOCK_ID:
>> + return "GLOBALVAL_SUMMARY_BLOCK";
>> + case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID:
>> + return "FULL_LTO_GLOBALVAL_SUMMARY_BLOCK";
>> + case bitc::MODULE_STRTAB_BLOCK_ID:
>> + return "MODULE_STRTAB_BLOCK";
>> + case bitc::STRTAB_BLOCK_ID:
>> + return "STRTAB_BLOCK";
>> + case bitc::SYMTAB_BLOCK_ID:
>> + return "SYMTAB_BLOCK";
>> + }
>> +}
>> +
>> +/// Return a symbolic code name if known, otherwise return null.
>> +static Optional<const char *> GetCodeName(unsigned CodeID, unsigned BlockID,
>> + const BitstreamBlockInfo &BlockInfo,
>> + CurStreamTypeType CurStreamType) {
>> + // Standard blocks for all bitcode files.
>> + if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {
>> + if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + case bitc::BLOCKINFO_CODE_SETBID:
>> + return "SETBID";
>> + case bitc::BLOCKINFO_CODE_BLOCKNAME:
>> + return "BLOCKNAME";
>> + case bitc::BLOCKINFO_CODE_SETRECORDNAME:
>> + return "SETRECORDNAME";
>> + }
>> + }
>> + return None;
>> + }
>> +
>> + // Check to see if we have a blockinfo record for this record, with a name.
>> + if (const BitstreamBlockInfo::BlockInfo *Info =
>> + BlockInfo.getBlockInfo(BlockID)) {
>> + for (unsigned i = 0, e = Info->RecordNames.size(); i != e; ++i)
>> + if (Info->RecordNames[i].first == CodeID)
>> + return Info->RecordNames[i].second.c_str();
>> + }
>> +
>> + if (CurStreamType != LLVMIRBitstream)
>> + return None;
>> +
>> +#define STRINGIFY_CODE(PREFIX, CODE) \
>> + case bitc::PREFIX##_##CODE: \
>> + return #CODE;
>> + switch (BlockID) {
>> + default:
>> + return None;
>> + case bitc::MODULE_BLOCK_ID:
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + STRINGIFY_CODE(MODULE_CODE, VERSION)
>> + STRINGIFY_CODE(MODULE_CODE, TRIPLE)
>> + STRINGIFY_CODE(MODULE_CODE, DATALAYOUT)
>> + STRINGIFY_CODE(MODULE_CODE, ASM)
>> + STRINGIFY_CODE(MODULE_CODE, SECTIONNAME)
>> + STRINGIFY_CODE(MODULE_CODE, DEPLIB) // FIXME: Remove in 4.0
>> + STRINGIFY_CODE(MODULE_CODE, GLOBALVAR)
>> + STRINGIFY_CODE(MODULE_CODE, FUNCTION)
>> + STRINGIFY_CODE(MODULE_CODE, ALIAS)
>> + STRINGIFY_CODE(MODULE_CODE, GCNAME)
>> + STRINGIFY_CODE(MODULE_CODE, VSTOFFSET)
>> + STRINGIFY_CODE(MODULE_CODE, METADATA_VALUES_UNUSED)
>> + STRINGIFY_CODE(MODULE_CODE, SOURCE_FILENAME)
>> + STRINGIFY_CODE(MODULE_CODE, HASH)
>> + }
>> + case bitc::IDENTIFICATION_BLOCK_ID:
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + STRINGIFY_CODE(IDENTIFICATION_CODE, STRING)
>> + STRINGIFY_CODE(IDENTIFICATION_CODE, EPOCH)
>> + }
>> + case bitc::PARAMATTR_BLOCK_ID:
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + // FIXME: Should these be different?
>> + case bitc::PARAMATTR_CODE_ENTRY_OLD:
>> + return "ENTRY";
>> + case bitc::PARAMATTR_CODE_ENTRY:
>> + return "ENTRY";
>> + }
>> + case bitc::PARAMATTR_GROUP_BLOCK_ID:
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + case bitc::PARAMATTR_GRP_CODE_ENTRY:
>> + return "ENTRY";
>> + }
>> + case bitc::TYPE_BLOCK_ID_NEW:
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + STRINGIFY_CODE(TYPE_CODE, NUMENTRY)
>> + STRINGIFY_CODE(TYPE_CODE, VOID)
>> + STRINGIFY_CODE(TYPE_CODE, FLOAT)
>> + STRINGIFY_CODE(TYPE_CODE, DOUBLE)
>> + STRINGIFY_CODE(TYPE_CODE, LABEL)
>> + STRINGIFY_CODE(TYPE_CODE, OPAQUE)
>> + STRINGIFY_CODE(TYPE_CODE, INTEGER)
>> + STRINGIFY_CODE(TYPE_CODE, POINTER)
>> + STRINGIFY_CODE(TYPE_CODE, ARRAY)
>> + STRINGIFY_CODE(TYPE_CODE, VECTOR)
>> + STRINGIFY_CODE(TYPE_CODE, X86_FP80)
>> + STRINGIFY_CODE(TYPE_CODE, FP128)
>> + STRINGIFY_CODE(TYPE_CODE, PPC_FP128)
>> + STRINGIFY_CODE(TYPE_CODE, METADATA)
>> + STRINGIFY_CODE(TYPE_CODE, STRUCT_ANON)
>> + STRINGIFY_CODE(TYPE_CODE, STRUCT_NAME)
>> + STRINGIFY_CODE(TYPE_CODE, STRUCT_NAMED)
>> + STRINGIFY_CODE(TYPE_CODE, FUNCTION)
>> + }
>> +
>> + case bitc::CONSTANTS_BLOCK_ID:
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + STRINGIFY_CODE(CST_CODE, SETTYPE)
>> + STRINGIFY_CODE(CST_CODE, NULL)
>> + STRINGIFY_CODE(CST_CODE, UNDEF)
>> + STRINGIFY_CODE(CST_CODE, INTEGER)
>> + STRINGIFY_CODE(CST_CODE, WIDE_INTEGER)
>> + STRINGIFY_CODE(CST_CODE, FLOAT)
>> + STRINGIFY_CODE(CST_CODE, AGGREGATE)
>> + STRINGIFY_CODE(CST_CODE, STRING)
>> + STRINGIFY_CODE(CST_CODE, CSTRING)
>> + STRINGIFY_CODE(CST_CODE, CE_BINOP)
>> + STRINGIFY_CODE(CST_CODE, CE_CAST)
>> + STRINGIFY_CODE(CST_CODE, CE_GEP)
>> + STRINGIFY_CODE(CST_CODE, CE_INBOUNDS_GEP)
>> + STRINGIFY_CODE(CST_CODE, CE_SELECT)
>> + STRINGIFY_CODE(CST_CODE, CE_EXTRACTELT)
>> + STRINGIFY_CODE(CST_CODE, CE_INSERTELT)
>> + STRINGIFY_CODE(CST_CODE, CE_SHUFFLEVEC)
>> + STRINGIFY_CODE(CST_CODE, CE_CMP)
>> + STRINGIFY_CODE(CST_CODE, INLINEASM)
>> + STRINGIFY_CODE(CST_CODE, CE_SHUFVEC_EX)
>> + STRINGIFY_CODE(CST_CODE, CE_UNOP)
>> + case bitc::CST_CODE_BLOCKADDRESS:
>> + return "CST_CODE_BLOCKADDRESS";
>> + STRINGIFY_CODE(CST_CODE, DATA)
>> + }
>> + case bitc::FUNCTION_BLOCK_ID:
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + STRINGIFY_CODE(FUNC_CODE, DECLAREBLOCKS)
>> + STRINGIFY_CODE(FUNC_CODE, INST_BINOP)
>> + STRINGIFY_CODE(FUNC_CODE, INST_CAST)
>> + STRINGIFY_CODE(FUNC_CODE, INST_GEP_OLD)
>> + STRINGIFY_CODE(FUNC_CODE, INST_INBOUNDS_GEP_OLD)
>> + STRINGIFY_CODE(FUNC_CODE, INST_SELECT)
>> + STRINGIFY_CODE(FUNC_CODE, INST_EXTRACTELT)
>> + STRINGIFY_CODE(FUNC_CODE, INST_INSERTELT)
>> + STRINGIFY_CODE(FUNC_CODE, INST_SHUFFLEVEC)
>> + STRINGIFY_CODE(FUNC_CODE, INST_CMP)
>> + STRINGIFY_CODE(FUNC_CODE, INST_RET)
>> + STRINGIFY_CODE(FUNC_CODE, INST_BR)
>> + STRINGIFY_CODE(FUNC_CODE, INST_SWITCH)
>> + STRINGIFY_CODE(FUNC_CODE, INST_INVOKE)
>> + STRINGIFY_CODE(FUNC_CODE, INST_UNOP)
>> + STRINGIFY_CODE(FUNC_CODE, INST_UNREACHABLE)
>> + STRINGIFY_CODE(FUNC_CODE, INST_CLEANUPRET)
>> + STRINGIFY_CODE(FUNC_CODE, INST_CATCHRET)
>> + STRINGIFY_CODE(FUNC_CODE, INST_CATCHPAD)
>> + STRINGIFY_CODE(FUNC_CODE, INST_PHI)
>> + STRINGIFY_CODE(FUNC_CODE, INST_ALLOCA)
>> + STRINGIFY_CODE(FUNC_CODE, INST_LOAD)
>> + STRINGIFY_CODE(FUNC_CODE, INST_VAARG)
>> + STRINGIFY_CODE(FUNC_CODE, INST_STORE)
>> + STRINGIFY_CODE(FUNC_CODE, INST_EXTRACTVAL)
>> + STRINGIFY_CODE(FUNC_CODE, INST_INSERTVAL)
>> + STRINGIFY_CODE(FUNC_CODE, INST_CMP2)
>> + STRINGIFY_CODE(FUNC_CODE, INST_VSELECT)
>> + STRINGIFY_CODE(FUNC_CODE, DEBUG_LOC_AGAIN)
>> + STRINGIFY_CODE(FUNC_CODE, INST_CALL)
>> + STRINGIFY_CODE(FUNC_CODE, DEBUG_LOC)
>> + STRINGIFY_CODE(FUNC_CODE, INST_GEP)
>> + STRINGIFY_CODE(FUNC_CODE, OPERAND_BUNDLE)
>> + STRINGIFY_CODE(FUNC_CODE, INST_FENCE)
>> + STRINGIFY_CODE(FUNC_CODE, INST_ATOMICRMW)
>> + STRINGIFY_CODE(FUNC_CODE, INST_LOADATOMIC)
>> + STRINGIFY_CODE(FUNC_CODE, INST_STOREATOMIC)
>> + STRINGIFY_CODE(FUNC_CODE, INST_CMPXCHG)
>> + STRINGIFY_CODE(FUNC_CODE, INST_CALLBR)
>> + }
>> + case bitc::VALUE_SYMTAB_BLOCK_ID:
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + STRINGIFY_CODE(VST_CODE, ENTRY)
>> + STRINGIFY_CODE(VST_CODE, BBENTRY)
>> + STRINGIFY_CODE(VST_CODE, FNENTRY)
>> + STRINGIFY_CODE(VST_CODE, COMBINED_ENTRY)
>> + }
>> + case bitc::MODULE_STRTAB_BLOCK_ID:
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + STRINGIFY_CODE(MST_CODE, ENTRY)
>> + STRINGIFY_CODE(MST_CODE, HASH)
>> + }
>> + case bitc::GLOBALVAL_SUMMARY_BLOCK_ID:
>> + case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID:
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + STRINGIFY_CODE(FS, PERMODULE)
>> + STRINGIFY_CODE(FS, PERMODULE_PROFILE)
>> + STRINGIFY_CODE(FS, PERMODULE_RELBF)
>> + STRINGIFY_CODE(FS, PERMODULE_GLOBALVAR_INIT_REFS)
>> + STRINGIFY_CODE(FS, PERMODULE_VTABLE_GLOBALVAR_INIT_REFS)
>> + STRINGIFY_CODE(FS, COMBINED)
>> + STRINGIFY_CODE(FS, COMBINED_PROFILE)
>> + STRINGIFY_CODE(FS, COMBINED_GLOBALVAR_INIT_REFS)
>> + STRINGIFY_CODE(FS, ALIAS)
>> + STRINGIFY_CODE(FS, COMBINED_ALIAS)
>> + STRINGIFY_CODE(FS, COMBINED_ORIGINAL_NAME)
>> + STRINGIFY_CODE(FS, VERSION)
>> + STRINGIFY_CODE(FS, FLAGS)
>> + STRINGIFY_CODE(FS, TYPE_TESTS)
>> + STRINGIFY_CODE(FS, TYPE_TEST_ASSUME_VCALLS)
>> + STRINGIFY_CODE(FS, TYPE_CHECKED_LOAD_VCALLS)
>> + STRINGIFY_CODE(FS, TYPE_TEST_ASSUME_CONST_VCALL)
>> + STRINGIFY_CODE(FS, TYPE_CHECKED_LOAD_CONST_VCALL)
>> + STRINGIFY_CODE(FS, VALUE_GUID)
>> + STRINGIFY_CODE(FS, CFI_FUNCTION_DEFS)
>> + STRINGIFY_CODE(FS, CFI_FUNCTION_DECLS)
>> + STRINGIFY_CODE(FS, TYPE_ID)
>> + STRINGIFY_CODE(FS, TYPE_ID_METADATA)
>> + }
>> + case bitc::METADATA_ATTACHMENT_ID:
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + STRINGIFY_CODE(METADATA, ATTACHMENT)
>> + }
>> + case bitc::METADATA_BLOCK_ID:
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + STRINGIFY_CODE(METADATA, STRING_OLD)
>> + STRINGIFY_CODE(METADATA, VALUE)
>> + STRINGIFY_CODE(METADATA, NODE)
>> + STRINGIFY_CODE(METADATA, NAME)
>> + STRINGIFY_CODE(METADATA, DISTINCT_NODE)
>> + STRINGIFY_CODE(METADATA, KIND) // Older bitcode has it in a MODULE_BLOCK
>> + STRINGIFY_CODE(METADATA, LOCATION)
>> + STRINGIFY_CODE(METADATA, OLD_NODE)
>> + STRINGIFY_CODE(METADATA, OLD_FN_NODE)
>> + STRINGIFY_CODE(METADATA, NAMED_NODE)
>> + STRINGIFY_CODE(METADATA, GENERIC_DEBUG)
>> + STRINGIFY_CODE(METADATA, SUBRANGE)
>> + STRINGIFY_CODE(METADATA, ENUMERATOR)
>> + STRINGIFY_CODE(METADATA, BASIC_TYPE)
>> + STRINGIFY_CODE(METADATA, FILE)
>> + STRINGIFY_CODE(METADATA, DERIVED_TYPE)
>> + STRINGIFY_CODE(METADATA, COMPOSITE_TYPE)
>> + STRINGIFY_CODE(METADATA, SUBROUTINE_TYPE)
>> + STRINGIFY_CODE(METADATA, COMPILE_UNIT)
>> + STRINGIFY_CODE(METADATA, SUBPROGRAM)
>> + STRINGIFY_CODE(METADATA, LEXICAL_BLOCK)
>> + STRINGIFY_CODE(METADATA, LEXICAL_BLOCK_FILE)
>> + STRINGIFY_CODE(METADATA, NAMESPACE)
>> + STRINGIFY_CODE(METADATA, TEMPLATE_TYPE)
>> + STRINGIFY_CODE(METADATA, TEMPLATE_VALUE)
>> + STRINGIFY_CODE(METADATA, GLOBAL_VAR)
>> + STRINGIFY_CODE(METADATA, LOCAL_VAR)
>> + STRINGIFY_CODE(METADATA, EXPRESSION)
>> + STRINGIFY_CODE(METADATA, OBJC_PROPERTY)
>> + STRINGIFY_CODE(METADATA, IMPORTED_ENTITY)
>> + STRINGIFY_CODE(METADATA, MODULE)
>> + STRINGIFY_CODE(METADATA, MACRO)
>> + STRINGIFY_CODE(METADATA, MACRO_FILE)
>> + STRINGIFY_CODE(METADATA, STRINGS)
>> + STRINGIFY_CODE(METADATA, GLOBAL_DECL_ATTACHMENT)
>> + STRINGIFY_CODE(METADATA, GLOBAL_VAR_EXPR)
>> + STRINGIFY_CODE(METADATA, INDEX_OFFSET)
>> + STRINGIFY_CODE(METADATA, INDEX)
>> + }
>> + case bitc::METADATA_KIND_BLOCK_ID:
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + STRINGIFY_CODE(METADATA, KIND)
>> + }
>> + case bitc::USELIST_BLOCK_ID:
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + case bitc::USELIST_CODE_DEFAULT:
>> + return "USELIST_CODE_DEFAULT";
>> + case bitc::USELIST_CODE_BB:
>> + return "USELIST_CODE_BB";
>> + }
>> +
>> + case bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID:
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + case bitc::OPERAND_BUNDLE_TAG:
>> + return "OPERAND_BUNDLE_TAG";
>> + }
>> + case bitc::STRTAB_BLOCK_ID:
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + case bitc::STRTAB_BLOB:
>> + return "BLOB";
>> + }
>> + case bitc::SYMTAB_BLOCK_ID:
>> + switch (CodeID) {
>> + default:
>> + return None;
>> + case bitc::SYMTAB_BLOB:
>> + return "BLOB";
>> + }
>> + }
>> +#undef STRINGIFY_CODE
>> +}
>> +
>> +static void printSize(raw_ostream &OS, double Bits) {
>> + OS << format("%.2f/%.2fB/%luW", Bits, Bits / 8, (unsigned long)(Bits / 32));
>> +}
>> +static void printSize(raw_ostream &OS, uint64_t Bits) {
>> + OS << format("%lub/%.2fB/%luW", (unsigned long)Bits, (double)Bits / 8,
>> + (unsigned long)(Bits / 32));
>> +}
>> +
>> +static Expected<CurStreamTypeType> ReadSignature(BitstreamCursor &Stream) {
>> + auto tryRead = [&Stream](char &Dest, size_t size) -> Error {
>> + if (Expected<SimpleBitstreamCursor::word_t> MaybeWord = Stream.Read(size))
>> + Dest = MaybeWord.get();
>> + else
>> + return MaybeWord.takeError();
>> + return Error::success();
>> + };
>> +
>> + char Signature[6];
>> + if (Error Err = tryRead(Signature[0], 8))
>> + return std::move(Err);
>> + if (Error Err = tryRead(Signature[1], 8))
>> + return std::move(Err);
>> +
>> + // Autodetect the file contents, if it is one we know.
>> + if (Signature[0] == 'C' && Signature[1] == 'P') {
>> + if (Error Err = tryRead(Signature[2], 8))
>> + return std::move(Err);
>> + if (Error Err = tryRead(Signature[3], 8))
>> + return std::move(Err);
>> + if (Signature[2] == 'C' && Signature[3] == 'H')
>> + return ClangSerializedASTBitstream;
>> + } else if (Signature[0] == 'D' && Signature[1] == 'I') {
>> + if (Error Err = tryRead(Signature[2], 8))
>> + return std::move(Err);
>> + if (Error Err = tryRead(Signature[3], 8))
>> + return std::move(Err);
>> + if (Signature[2] == 'A' && Signature[3] == 'G')
>> + return ClangSerializedDiagnosticsBitstream;
>> + } else {
>> + if (Error Err = tryRead(Signature[2], 4))
>> + return std::move(Err);
>> + if (Error Err = tryRead(Signature[3], 4))
>> + return std::move(Err);
>> + if (Error Err = tryRead(Signature[4], 4))
>> + return std::move(Err);
>> + if (Error Err = tryRead(Signature[5], 4))
>> + return std::move(Err);
>> + if (Signature[0] == 'B' && Signature[1] == 'C' && Signature[2] == 0x0 &&
>> + Signature[3] == 0xC && Signature[4] == 0xE && Signature[5] == 0xD)
>> + return LLVMIRBitstream;
>> + }
>> + return UnknownBitstream;
>> +}
>> +
>> +static Expected<CurStreamTypeType> analyzeHeader(Optional<BCDumpOptions> O,
>> + BitstreamCursor &Stream) {
>> + ArrayRef<uint8_t> Bytes = Stream.getBitcodeBytes();
>> + const unsigned char *BufPtr = (const unsigned char *)Bytes.data();
>> + const unsigned char *EndBufPtr = BufPtr + Bytes.size();
>> +
>> + // If we have a wrapper header, parse it and ignore the non-bc file
>> + // contents. The magic number is 0x0B17C0DE stored in little endian.
>> + if (isBitcodeWrapper(BufPtr, EndBufPtr)) {
>> + if (Bytes.size() < BWH_HeaderSize)
>> + return reportError("Invalid bitcode wrapper header");
>> +
>> + if (O) {
>> + unsigned Magic = support::endian::read32le(&BufPtr[BWH_MagicField]);
>> + unsigned Version = support::endian::read32le(&BufPtr[BWH_VersionField]);
>> + unsigned Offset = support::endian::read32le(&BufPtr[BWH_OffsetField]);
>> + unsigned Size = support::endian::read32le(&BufPtr[BWH_SizeField]);
>> + unsigned CPUType = support::endian::read32le(&BufPtr[BWH_CPUTypeField]);
>> +
>> + O->OS << "<BITCODE_WRAPPER_HEADER"
>> + << " Magic=" << format_hex(Magic, 10)
>> + << " Version=" << format_hex(Version, 10)
>> + << " Offset=" << format_hex(Offset, 10)
>> + << " Size=" << format_hex(Size, 10)
>> + << " CPUType=" << format_hex(CPUType, 10) << "/>\n";
>> + }
>> +
>> + if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr, true))
>> + return reportError("Invalid bitcode wrapper header");
>> + }
>> +
>> + // Use the cursor modified by skipping the wrapper header.
>> + Stream = BitstreamCursor(ArrayRef<uint8_t>(BufPtr, EndBufPtr));
>> +
>> + return ReadSignature(Stream);
>> +}
>> +
>> +static bool canDecodeBlob(unsigned Code, unsigned BlockID) {
>> + return BlockID == bitc::METADATA_BLOCK_ID && Code == bitc::METADATA_STRINGS;
>> +}
>> +
>> +Error BitcodeAnalyzer::decodeMetadataStringsBlob(StringRef Indent,
>> + ArrayRef<uint64_t> Record,
>> + StringRef Blob,
>> + raw_ostream &OS) {
>> + if (Blob.empty())
>> + return reportError("Cannot decode empty blob.");
>> +
>> + if (Record.size() != 2)
>> + return reportError(
>> + "Decoding metadata strings blob needs two record entries.");
>> +
>> + unsigned NumStrings = Record[0];
>> + unsigned StringsOffset = Record[1];
>> + OS << " num-strings = " << NumStrings << " {\n";
>> +
>> + StringRef Lengths = Blob.slice(0, StringsOffset);
>> + SimpleBitstreamCursor R(Lengths);
>> + StringRef Strings = Blob.drop_front(StringsOffset);
>> + do {
>> + if (R.AtEndOfStream())
>> + return reportError("bad length");
>> +
>> + Expected<uint32_t> MaybeSize = R.ReadVBR(6);
>> + if (!MaybeSize)
>> + return MaybeSize.takeError();
>> + uint32_t Size = MaybeSize.get();
>> + if (Strings.size() < Size)
>> + return reportError("truncated chars");
>> +
>> + OS << Indent << " '";
>> + OS.write_escaped(Strings.slice(0, Size), /*hex=*/true);
>> + OS << "'\n";
>> + Strings = Strings.drop_front(Size);
>> + } while (--NumStrings);
>> +
>> + OS << Indent << " }";
>> + return Error::success();
>> +}
>> +
>> +BitcodeAnalyzer::BitcodeAnalyzer(StringRef Buffer,
>> + Optional<StringRef> BlockInfoBuffer)
>> + : Stream(Buffer) {
>> + if (BlockInfoBuffer)
>> + BlockInfoStream.emplace(*BlockInfoBuffer);
>> +}
>> +
>> +Error BitcodeAnalyzer::analyze(Optional<BCDumpOptions> O,
>> + Optional<StringRef> CheckHash) {
>> + if (Expected<CurStreamTypeType> H = analyzeHeader(O, Stream))
>> + CurStreamType = *H;
>> +
>> + Stream.setBlockInfo(&BlockInfo);
>> +
>> + // Read block info from BlockInfoStream, if specified.
>> + // The block info must be a top-level block.
>> + if (BlockInfoStream) {
>> + BitstreamCursor BlockInfoCursor(*BlockInfoStream);
>> + CurStreamTypeType BlockInfoStreamType;
>> + Expected<CurStreamTypeType> H = analyzeHeader(O, BlockInfoCursor);
>> + if (!H)
>> + return H.takeError();
>> + BlockInfoStreamType = *H;
>> +
>> + while (!BlockInfoCursor.AtEndOfStream()) {
>> + Expected<unsigned> MaybeCode = BlockInfoCursor.ReadCode();
>> + if (!MaybeCode)
>> + return MaybeCode.takeError();
>> + if (MaybeCode.get() != bitc::ENTER_SUBBLOCK)
>> + return reportError("Invalid record at top-level in block info file");
>> +
>> + Expected<unsigned> MaybeBlockID = BlockInfoCursor.ReadSubBlockID();
>> + if (!MaybeBlockID)
>> + return MaybeBlockID.takeError();
>> + if (MaybeBlockID.get() == bitc::BLOCKINFO_BLOCK_ID) {
>> + Expected<Optional<BitstreamBlockInfo>> MaybeNewBlockInfo =
>> + BlockInfoCursor.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true);
>> + if (!MaybeNewBlockInfo)
>> + return MaybeNewBlockInfo.takeError();
>> + Optional<BitstreamBlockInfo> NewBlockInfo =
>> + std::move(MaybeNewBlockInfo.get());
>> + if (!NewBlockInfo)
>> + return reportError("Malformed BlockInfoBlock in block info file");
>> + BlockInfo = std::move(*NewBlockInfo);
>> + break;
>> + }
>> +
>> + if (Error Err = BlockInfoCursor.SkipBlock())
>> + return Err;
>> + }
>> + }
>> +
>> + // Parse the top-level structure. We only allow blocks at the top-level.
>> + while (!Stream.AtEndOfStream()) {
>> + Expected<unsigned> MaybeCode = Stream.ReadCode();
>> + if (!MaybeCode)
>> + return MaybeCode.takeError();
>> + if (MaybeCode.get() != bitc::ENTER_SUBBLOCK)
>> + return reportError("Invalid record at top-level");
>> +
>> + Expected<unsigned> MaybeBlockID = Stream.ReadSubBlockID();
>> + if (!MaybeBlockID)
>> + return MaybeBlockID.takeError();
>> +
>> + if (Error E = parseBlock(MaybeBlockID.get(), 0, O, CheckHash))
>> + return E;
>> + ++NumTopBlocks;
>> + }
>> +
>> + return Error::success();
>> +}
>> +
>> +void BitcodeAnalyzer::printStats(BCDumpOptions O,
>> + Optional<StringRef> Filename) {
>> + uint64_t BufferSizeBits = Stream.getBitcodeBytes().size() * CHAR_BIT;
>> + // Print a summary of the read file.
>> + O.OS << "Summary ";
>> + if (Filename)
>> + O.OS << "of " << Filename->data() << ":\n";
>> + O.OS << " Total size: ";
>> + printSize(O.OS, BufferSizeBits);
>> + O.OS << "\n";
>> + O.OS << " Stream type: ";
>> + switch (CurStreamType) {
>> + case UnknownBitstream:
>> + O.OS << "unknown\n";
>> + break;
>> + case LLVMIRBitstream:
>> + O.OS << "LLVM IR\n";
>> + break;
>> + case ClangSerializedASTBitstream:
>> + O.OS << "Clang Serialized AST\n";
>> + break;
>> + case ClangSerializedDiagnosticsBitstream:
>> + O.OS << "Clang Serialized Diagnostics\n";
>> + break;
>> + }
>> + O.OS << " # Toplevel Blocks: " << NumTopBlocks << "\n";
>> + O.OS << "\n";
>> +
>> + // Emit per-block stats.
>> + O.OS << "Per-block Summary:\n";
>> + for (std::map<unsigned, PerBlockIDStats>::iterator I = BlockIDStats.begin(),
>> + E = BlockIDStats.end();
>> + I != E; ++I) {
>> + O.OS << " Block ID #" << I->first;
>> + if (Optional<const char *> BlockName =
>> + GetBlockName(I->first, BlockInfo, CurStreamType))
>> + O.OS << " (" << *BlockName << ")";
>> + O.OS << ":\n";
>> +
>> + const PerBlockIDStats &Stats = I->second;
>> + O.OS << " Num Instances: " << Stats.NumInstances << "\n";
>> + O.OS << " Total Size: ";
>> + printSize(O.OS, Stats.NumBits);
>> + O.OS << "\n";
>> + double pct = (Stats.NumBits * 100.0) / BufferSizeBits;
>> + O.OS << " Percent of file: " << format("%2.4f%%", pct) << "\n";
>> + if (Stats.NumInstances > 1) {
>> + O.OS << " Average Size: ";
>> + printSize(O.OS, Stats.NumBits / (double)Stats.NumInstances);
>> + O.OS << "\n";
>> + O.OS << " Tot/Avg SubBlocks: " << Stats.NumSubBlocks << "/"
>> + << Stats.NumSubBlocks / (double)Stats.NumInstances << "\n";
>> + O.OS << " Tot/Avg Abbrevs: " << Stats.NumAbbrevs << "/"
>> + << Stats.NumAbbrevs / (double)Stats.NumInstances << "\n";
>> + O.OS << " Tot/Avg Records: " << Stats.NumRecords << "/"
>> + << Stats.NumRecords / (double)Stats.NumInstances << "\n";
>> + } else {
>> + O.OS << " Num SubBlocks: " << Stats.NumSubBlocks << "\n";
>> + O.OS << " Num Abbrevs: " << Stats.NumAbbrevs << "\n";
>> + O.OS << " Num Records: " << Stats.NumRecords << "\n";
>> + }
>> + if (Stats.NumRecords) {
>> + double pct = (Stats.NumAbbreviatedRecords * 100.0) / Stats.NumRecords;
>> + O.OS << " Percent Abbrevs: " << format("%2.4f%%", pct) << "\n";
>> + }
>> + O.OS << "\n";
>> +
>> + // Print a histogram of the codes we see.
>> + if (O.Histogram && !Stats.CodeFreq.empty()) {
>> + std::vector<std::pair<unsigned, unsigned>> FreqPairs; // <freq,code>
>> + for (unsigned i = 0, e = Stats.CodeFreq.size(); i != e; ++i)
>> + if (unsigned Freq = Stats.CodeFreq[i].NumInstances)
>> + FreqPairs.push_back(std::make_pair(Freq, i));
>> + llvm::stable_sort(FreqPairs);
>> + std::reverse(FreqPairs.begin(), FreqPairs.end());
>> +
>> + O.OS << "\tRecord Histogram:\n";
>> + O.OS << "\t\t Count # Bits b/Rec % Abv Record Kind\n";
>> + for (unsigned i = 0, e = FreqPairs.size(); i != e; ++i) {
>> + const PerRecordStats &RecStats = Stats.CodeFreq[FreqPairs[i].second];
>> +
>> + O.OS << format("\t\t%7d %9lu", RecStats.NumInstances,
>> + (unsigned long)RecStats.TotalBits);
>> +
>> + if (RecStats.NumInstances > 1)
>> + O.OS << format(" %9.1f",
>> + (double)RecStats.TotalBits / RecStats.NumInstances);
>> + else
>> + O.OS << " ";
>> +
>> + if (RecStats.NumAbbrev)
>> + O.OS << format(" %7.2f", (double)RecStats.NumAbbrev /
>> + RecStats.NumInstances * 100);
>> + else
>> + O.OS << " ";
>> +
>> + O.OS << " ";
>> + if (Optional<const char *> CodeName = GetCodeName(
>> + FreqPairs[i].second, I->first, BlockInfo, CurStreamType))
>> + O.OS << *CodeName << "\n";
>> + else
>> + O.OS << "UnknownCode" << FreqPairs[i].second << "\n";
>> + }
>> + O.OS << "\n";
>> + }
>> + }
>> +}
>> +
>> +Error BitcodeAnalyzer::parseBlock(unsigned BlockID, unsigned IndentLevel,
>> + Optional<BCDumpOptions> O,
>> + Optional<StringRef> CheckHash) {
>> + std::string Indent(IndentLevel * 2, ' ');
>> + uint64_t BlockBitStart = Stream.GetCurrentBitNo();
>> +
>> + // Get the statistics for this BlockID.
>> + PerBlockIDStats &BlockStats = BlockIDStats[BlockID];
>> +
>> + BlockStats.NumInstances++;
>> +
>> + // BLOCKINFO is a special part of the stream.
>> + bool DumpRecords = O.hasValue();
>> + if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
>> + if (O)
>> + O->OS << Indent << "<BLOCKINFO_BLOCK/>\n";
>> + Expected<Optional<BitstreamBlockInfo>> MaybeNewBlockInfo =
>> + Stream.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true);
>> + if (!MaybeNewBlockInfo)
>> + return MaybeNewBlockInfo.takeError();
>> + Optional<BitstreamBlockInfo> NewBlockInfo =
>> + std::move(MaybeNewBlockInfo.get());
>> + if (!NewBlockInfo)
>> + return reportError("Malformed BlockInfoBlock");
>> + BlockInfo = std::move(*NewBlockInfo);
>> + if (Error Err = Stream.JumpToBit(BlockBitStart))
>> + return Err;
>> + // It's not really interesting to dump the contents of the blockinfo
>> + // block.
>> + DumpRecords = false;
>> + }
>> +
>> + unsigned NumWords = 0;
>> + if (Error Err = Stream.EnterSubBlock(BlockID, &NumWords))
>> + return Err;
>> +
>> + // Keep it for later, when we see a MODULE_HASH record
>> + uint64_t BlockEntryPos = Stream.getCurrentByteNo();
>> +
>> + Optional<const char *> BlockName = None;
>> + if (DumpRecords) {
>> + O->OS << Indent << "<";
>> + if ((BlockName = GetBlockName(BlockID, BlockInfo, CurStreamType)))
>> + O->OS << *BlockName;
>> + else
>> + O->OS << "UnknownBlock" << BlockID;
>> +
>> + if (!O->Symbolic && BlockName)
>> + O->OS << " BlockID=" << BlockID;
>> +
>> + O->OS << " NumWords=" << NumWords
>> + << " BlockCodeSize=" << Stream.getAbbrevIDWidth() << ">\n";
>> + }
>> +
>> + SmallVector<uint64_t, 64> Record;
>> +
>> + // Keep the offset to the metadata index if seen.
>> + uint64_t MetadataIndexOffset = 0;
>> +
>> + // Read all the records for this block.
>> + while (1) {
>> + if (Stream.AtEndOfStream())
>> + return reportError("Premature end of bitstream");
>> +
>> + uint64_t RecordStartBit = Stream.GetCurrentBitNo();
>> +
>> + Expected<BitstreamEntry> MaybeEntry =
>> + Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
>> + if (!MaybeEntry)
>> + return MaybeEntry.takeError();
>> + BitstreamEntry Entry = MaybeEntry.get();
>> +
>> + switch (Entry.Kind) {
>> + case BitstreamEntry::Error:
>> + return reportError("malformed bitcode file");
>> + case BitstreamEntry::EndBlock: {
>> + uint64_t BlockBitEnd = Stream.GetCurrentBitNo();
>> + BlockStats.NumBits += BlockBitEnd - BlockBitStart;
>> + if (DumpRecords) {
>> + O->OS << Indent << "</";
>> + if (BlockName)
>> + O->OS << *BlockName << ">\n";
>> + else
>> + O->OS << "UnknownBlock" << BlockID << ">\n";
>> + }
>> + return Error::success();
>> + }
>> +
>> + case BitstreamEntry::SubBlock: {
>> + uint64_t SubBlockBitStart = Stream.GetCurrentBitNo();
>> + if (Error E = parseBlock(Entry.ID, IndentLevel + 1, O, CheckHash))
>> + return E;
>> + ++BlockStats.NumSubBlocks;
>> + uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo();
>> +
>> + // Don't include subblock sizes in the size of this block.
>> + BlockBitStart += SubBlockBitEnd - SubBlockBitStart;
>> + continue;
>> + }
>> + case BitstreamEntry::Record:
>> + // The interesting case.
>> + break;
>> + }
>> +
>> + if (Entry.ID == bitc::DEFINE_ABBREV) {
>> + if (Error Err = Stream.ReadAbbrevRecord())
>> + return Err;
>> + ++BlockStats.NumAbbrevs;
>> + continue;
>> + }
>> +
>> + Record.clear();
>> +
>> + ++BlockStats.NumRecords;
>> +
>> + StringRef Blob;
>> + uint64_t CurrentRecordPos = Stream.GetCurrentBitNo();
>> + Expected<unsigned> MaybeCode = Stream.readRecord(Entry.ID, Record, &Blob);
>> + if (!MaybeCode)
>> + return MaybeCode.takeError();
>> + unsigned Code = MaybeCode.get();
>> +
>> + // Increment the # occurrences of this code.
>> + if (BlockStats.CodeFreq.size() <= Code)
>> + BlockStats.CodeFreq.resize(Code + 1);
>> + BlockStats.CodeFreq[Code].NumInstances++;
>> + BlockStats.CodeFreq[Code].TotalBits +=
>> + Stream.GetCurrentBitNo() - RecordStartBit;
>> + if (Entry.ID != bitc::UNABBREV_RECORD) {
>> + BlockStats.CodeFreq[Code].NumAbbrev++;
>> + ++BlockStats.NumAbbreviatedRecords;
>> + }
>> +
>> + if (DumpRecords) {
>> + O->OS << Indent << " <";
>> + Optional<const char *> CodeName =
>> + GetCodeName(Code, BlockID, BlockInfo, CurStreamType);
>> + if (CodeName)
>> + O->OS << *CodeName;
>> + else
>> + O->OS << "UnknownCode" << Code;
>> + if (!O->Symbolic && CodeName)
>> + O->OS << " codeid=" << Code;
>> + const BitCodeAbbrev *Abbv = nullptr;
>> + if (Entry.ID != bitc::UNABBREV_RECORD) {
>> + Abbv = Stream.getAbbrev(Entry.ID);
>> + O->OS << " abbrevid=" << Entry.ID;
>> + }
>> +
>> + for (unsigned i = 0, e = Record.size(); i != e; ++i)
>> + O->OS << " op" << i << "=" << (int64_t)Record[i];
>> +
>> + // If we found a metadata index, let's verify that we had an offset
>> + // before and validate its forward reference offset was correct!
>> + if (BlockID == bitc::METADATA_BLOCK_ID) {
>> + if (Code == bitc::METADATA_INDEX_OFFSET) {
>> + if (Record.size() != 2)
>> + O->OS << "(Invalid record)";
>> + else {
>> + auto Offset = Record[0] + (Record[1] << 32);
>> + MetadataIndexOffset = Stream.GetCurrentBitNo() + Offset;
>> + }
>> + }
>> + if (Code == bitc::METADATA_INDEX) {
>> + O->OS << " (offset ";
>> + if (MetadataIndexOffset == RecordStartBit)
>> + O->OS << "match)";
>> + else
>> + O->OS << "mismatch: " << MetadataIndexOffset << " vs "
>> + << RecordStartBit << ")";
>> + }
>> + }
>> +
>> + // If we found a module hash, let's verify that it matches!
>> + if (BlockID == bitc::MODULE_BLOCK_ID && Code == bitc::MODULE_CODE_HASH &&
>> + CheckHash.hasValue()) {
>> + if (Record.size() != 5)
>> + O->OS << " (invalid)";
>> + else {
>> + // Recompute the hash and compare it to the one in the bitcode
>> + SHA1 Hasher;
>> + StringRef Hash;
>> + Hasher.update(*CheckHash);
>> + {
>> + int BlockSize = (CurrentRecordPos / 8) - BlockEntryPos;
>> + auto Ptr = Stream.getPointerToByte(BlockEntryPos, BlockSize);
>> + Hasher.update(ArrayRef<uint8_t>(Ptr, BlockSize));
>> + Hash = Hasher.result();
>> + }
>> + SmallString<20> RecordedHash;
>> + RecordedHash.resize(20);
>> + int Pos = 0;
>> + for (auto &Val : Record) {
>> + assert(!(Val >> 32) && "Unexpected high bits set");
>> + RecordedHash[Pos++] = (Val >> 24) & 0xFF;
>> + RecordedHash[Pos++] = (Val >> 16) & 0xFF;
>> + RecordedHash[Pos++] = (Val >> 8) & 0xFF;
>> + RecordedHash[Pos++] = (Val >> 0) & 0xFF;
>> + }
>> + if (Hash == RecordedHash)
>> + O->OS << " (match)";
>> + else
>> + O->OS << " (!mismatch!)";
>> + }
>> + }
>> +
>> + O->OS << "/>";
>> +
>> + if (Abbv) {
>> + for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) {
>> + const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
>> + if (!Op.isEncoding() || Op.getEncoding() != BitCodeAbbrevOp::Array)
>> + continue;
>> + assert(i + 2 == e && "Array op not second to last");
>> + std::string Str;
>> + bool ArrayIsPrintable = true;
>> + for (unsigned j = i - 1, je = Record.size(); j != je; ++j) {
>> + if (!isPrint(static_cast<unsigned char>(Record[j]))) {
>> + ArrayIsPrintable = false;
>> + break;
>> + }
>> + Str += (char)Record[j];
>> + }
>> + if (ArrayIsPrintable)
>> + O->OS << " record string = '" << Str << "'";
>> + break;
>> + }
>> + }
>> +
>> + if (Blob.data()) {
>> + if (canDecodeBlob(Code, BlockID)) {
>> + if (Error E = decodeMetadataStringsBlob(Indent, Record, Blob, O->OS))
>> + return E;
>> + } else {
>> + O->OS << " blob data = ";
>> + if (O->ShowBinaryBlobs) {
>> + O->OS << "'";
>> + O->OS.write_escaped(Blob, /*hex=*/true) << "'";
>> + } else {
>> + bool BlobIsPrintable = true;
>> + for (unsigned i = 0, e = Blob.size(); i != e; ++i)
>> + if (!isPrint(static_cast<unsigned char>(Blob[i]))) {
>> + BlobIsPrintable = false;
>> + break;
>> + }
>> +
>> + if (BlobIsPrintable)
>> + O->OS << "'" << Blob << "'";
>> + else
>> + O->OS << "unprintable, " << Blob.size() << " bytes.";
>> + }
>> + }
>> + }
>> +
>> + O->OS << "\n";
>> + }
>> +
>> + // Make sure that we can skip the current record.
>> + if (Error Err = Stream.JumpToBit(CurrentRecordPos))
>> + return Err;
>> + if (Expected<unsigned> Skipped = Stream.skipRecord(Entry.ID))
>> + ; // Do nothing.
>> + else
>> + return Skipped.takeError();
>> + }
>> +}
>> +
>>
>> Modified: llvm/trunk/lib/Bitcode/Reader/CMakeLists.txt
>> URL: https://protect2.fireeye.com/url?k=0e70e826-52a4ed99-0e70a8bd-868f633dbf25-fe9d8de334d62f09&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Flib%2FBitcode%2FReader%2FCMakeLists.txt%3Frev%3D365286%26r1%3D365285%26r2%3D365286%26view%3Ddiff
>> ==============================================================================
>> --- llvm/trunk/lib/Bitcode/Reader/CMakeLists.txt (original)
>> +++ llvm/trunk/lib/Bitcode/Reader/CMakeLists.txt Sun Jul 7 19:06:34 2019
>> @@ -1,4 +1,5 @@
>> add_llvm_library(LLVMBitReader
>> + BitcodeAnalyzer.cpp
>> BitReader.cpp
>> BitcodeReader.cpp
>> MetadataLoader.cpp
>>
>> Modified: llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
>> URL: https://protect2.fireeye.com/url?k=fb8a0d29-a75e0896-fb8a4db2-868f633dbf25-b3d67ade52c9b5c2&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftools%2Fllvm-bcanalyzer%2Fllvm-bcanalyzer.cpp%3Frev%3D365286%26r1%3D365285%26r2%3D365286%26view%3Ddiff
>> ==============================================================================
>> --- llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp (original)
>> +++ llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp Sun Jul 7 19:06:34 2019
>> @@ -26,22 +26,18 @@
>> //
>> //===----------------------------------------------------------------------===//
>>
>> -#include "llvm/ADT/StringExtras.h"
>> -#include "llvm/Bitcode/BitcodeReader.h"
>> -#include "llvm/Bitstream/BitstreamReader.h"
>> -#include "llvm/Bitcode/LLVMBitCodes.h"
>> +#include "llvm/ADT/Optional.h"
>> +#include "llvm/Bitcode/BitcodeAnalyzer.h"
>> #include "llvm/Support/CommandLine.h"
>> -#include "llvm/Support/Format.h"
>> +#include "llvm/Support/Error.h"
>> #include "llvm/Support/InitLLVM.h"
>> -#include "llvm/Support/ManagedStatic.h"
>> #include "llvm/Support/MemoryBuffer.h"
>> -#include "llvm/Support/SHA1.h"
>> -#include "llvm/Support/WithColor.h"
>> #include "llvm/Support/raw_ostream.h"
>> +#include <memory>
>> using namespace llvm;
>>
>> static cl::opt<std::string>
>> - InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
>> + InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
>>
>> static cl::opt<bool> Dump("dump", cl::desc("Dump low level bitcode trace"));
>>
>> @@ -52,1009 +48,66 @@ static cl::opt<bool> Dump("dump", cl::de
>> static cl::opt<bool> NoHistogram("disable-histogram",
>> cl::desc("Do not print per-code histogram"));
>>
>> -static cl::opt<bool>
>> -NonSymbolic("non-symbolic",
>> - cl::desc("Emit numeric info in dump even if"
>> - " symbolic info is available"));
>> +static cl::opt<bool> NonSymbolic("non-symbolic",
>> + cl::desc("Emit numeric info in dump even if"
>> + " symbolic info is available"));
>>
>> static cl::opt<std::string>
>> - BlockInfoFilename("block-info",
>> - cl::desc("Use the BLOCK_INFO from the given file"));
>> + BlockInfoFilename("block-info",
>> + cl::desc("Use the BLOCK_INFO from the given file"));
>>
>> static cl::opt<bool>
>> - ShowBinaryBlobs("show-binary-blobs",
>> - cl::desc("Print binary blobs using hex escapes"));
>> + ShowBinaryBlobs("show-binary-blobs",
>> + cl::desc("Print binary blobs using hex escapes"));
>>
>> static cl::opt<std::string> CheckHash(
>> "check-hash",
>> cl::desc("Check module hash using the argument as a string table"));
>>
>> -namespace {
>> -
>> -/// CurStreamTypeType - A type for CurStreamType
>> -enum CurStreamTypeType {
>> - UnknownBitstream,
>> - LLVMIRBitstream,
>> - ClangSerializedASTBitstream,
>> - ClangSerializedDiagnosticsBitstream,
>> -};
>> -
>> -}
>> -
>> -/// GetBlockName - Return a symbolic block name if known, otherwise return
>> -/// null.
>> -static const char *GetBlockName(unsigned BlockID,
>> - const BitstreamBlockInfo &BlockInfo,
>> - CurStreamTypeType CurStreamType) {
>> - // Standard blocks for all bitcode files.
>> - if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {
>> - if (BlockID == bitc::BLOCKINFO_BLOCK_ID)
>> - return "BLOCKINFO_BLOCK";
>> - return nullptr;
>> - }
>> -
>> - // Check to see if we have a blockinfo record for this block, with a name.
>> - if (const BitstreamBlockInfo::BlockInfo *Info =
>> - BlockInfo.getBlockInfo(BlockID)) {
>> - if (!Info->Name.empty())
>> - return Info->Name.c_str();
>> - }
>> -
>> -
>> - if (CurStreamType != LLVMIRBitstream) return nullptr;
>> -
>> - switch (BlockID) {
>> - default: return nullptr;
>> - case bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID: return "OPERAND_BUNDLE_TAGS_BLOCK";
>> - case bitc::MODULE_BLOCK_ID: return "MODULE_BLOCK";
>> - case bitc::PARAMATTR_BLOCK_ID: return "PARAMATTR_BLOCK";
>> - case bitc::PARAMATTR_GROUP_BLOCK_ID: return "PARAMATTR_GROUP_BLOCK_ID";
>> - case bitc::TYPE_BLOCK_ID_NEW: return "TYPE_BLOCK_ID";
>> - case bitc::CONSTANTS_BLOCK_ID: return "CONSTANTS_BLOCK";
>> - case bitc::FUNCTION_BLOCK_ID: return "FUNCTION_BLOCK";
>> - case bitc::IDENTIFICATION_BLOCK_ID:
>> - return "IDENTIFICATION_BLOCK_ID";
>> - case bitc::VALUE_SYMTAB_BLOCK_ID: return "VALUE_SYMTAB";
>> - case bitc::METADATA_BLOCK_ID: return "METADATA_BLOCK";
>> - case bitc::METADATA_KIND_BLOCK_ID: return "METADATA_KIND_BLOCK";
>> - case bitc::METADATA_ATTACHMENT_ID: return "METADATA_ATTACHMENT_BLOCK";
>> - case bitc::USELIST_BLOCK_ID: return "USELIST_BLOCK_ID";
>> - case bitc::GLOBALVAL_SUMMARY_BLOCK_ID:
>> - return "GLOBALVAL_SUMMARY_BLOCK";
>> - case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID:
>> - return "FULL_LTO_GLOBALVAL_SUMMARY_BLOCK";
>> - case bitc::MODULE_STRTAB_BLOCK_ID: return "MODULE_STRTAB_BLOCK";
>> - case bitc::STRTAB_BLOCK_ID: return "STRTAB_BLOCK";
>> - case bitc::SYMTAB_BLOCK_ID: return "SYMTAB_BLOCK";
>> - }
>> -}
>> -
>> -/// GetCodeName - Return a symbolic code name if known, otherwise return
>> -/// null.
>> -static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
>> - const BitstreamBlockInfo &BlockInfo,
>> - CurStreamTypeType CurStreamType) {
>> - // Standard blocks for all bitcode files.
>> - if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {
>> - if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
>> - switch (CodeID) {
>> - default: return nullptr;
>> - case bitc::BLOCKINFO_CODE_SETBID: return "SETBID";
>> - case bitc::BLOCKINFO_CODE_BLOCKNAME: return "BLOCKNAME";
>> - case bitc::BLOCKINFO_CODE_SETRECORDNAME: return "SETRECORDNAME";
>> - }
>> - }
>> - return nullptr;
>> - }
>> -
>> - // Check to see if we have a blockinfo record for this record, with a name.
>> - if (const BitstreamBlockInfo::BlockInfo *Info =
>> - BlockInfo.getBlockInfo(BlockID)) {
>> - for (unsigned i = 0, e = Info->RecordNames.size(); i != e; ++i)
>> - if (Info->RecordNames[i].first == CodeID)
>> - return Info->RecordNames[i].second.c_str();
>> - }
>> -
>> -
>> - if (CurStreamType != LLVMIRBitstream) return nullptr;
>> -
>> -#define STRINGIFY_CODE(PREFIX, CODE) \
>> - case bitc::PREFIX##_##CODE: \
>> - return #CODE;
>> - switch (BlockID) {
>> - default: return nullptr;
>> - case bitc::MODULE_BLOCK_ID:
>> - switch (CodeID) {
>> - default: return nullptr;
>> - STRINGIFY_CODE(MODULE_CODE, VERSION)
>> - STRINGIFY_CODE(MODULE_CODE, TRIPLE)
>> - STRINGIFY_CODE(MODULE_CODE, DATALAYOUT)
>> - STRINGIFY_CODE(MODULE_CODE, ASM)
>> - STRINGIFY_CODE(MODULE_CODE, SECTIONNAME)
>> - STRINGIFY_CODE(MODULE_CODE, DEPLIB) // FIXME: Remove in 4.0
>> - STRINGIFY_CODE(MODULE_CODE, GLOBALVAR)
>> - STRINGIFY_CODE(MODULE_CODE, FUNCTION)
>> - STRINGIFY_CODE(MODULE_CODE, ALIAS)
>> - STRINGIFY_CODE(MODULE_CODE, GCNAME)
>> - STRINGIFY_CODE(MODULE_CODE, VSTOFFSET)
>> - STRINGIFY_CODE(MODULE_CODE, METADATA_VALUES_UNUSED)
>> - STRINGIFY_CODE(MODULE_CODE, SOURCE_FILENAME)
>> - STRINGIFY_CODE(MODULE_CODE, HASH)
>> - }
>> - case bitc::IDENTIFICATION_BLOCK_ID:
>> - switch (CodeID) {
>> - default:
>> - return nullptr;
>> - STRINGIFY_CODE(IDENTIFICATION_CODE, STRING)
>> - STRINGIFY_CODE(IDENTIFICATION_CODE, EPOCH)
>> - }
>> - case bitc::PARAMATTR_BLOCK_ID:
>> - switch (CodeID) {
>> - default: return nullptr;
>> - // FIXME: Should these be different?
>> - case bitc::PARAMATTR_CODE_ENTRY_OLD: return "ENTRY";
>> - case bitc::PARAMATTR_CODE_ENTRY: return "ENTRY";
>> - }
>> - case bitc::PARAMATTR_GROUP_BLOCK_ID:
>> - switch (CodeID) {
>> - default: return nullptr;
>> - case bitc::PARAMATTR_GRP_CODE_ENTRY: return "ENTRY";
>> - }
>> - case bitc::TYPE_BLOCK_ID_NEW:
>> - switch (CodeID) {
>> - default: return nullptr;
>> - STRINGIFY_CODE(TYPE_CODE, NUMENTRY)
>> - STRINGIFY_CODE(TYPE_CODE, VOID)
>> - STRINGIFY_CODE(TYPE_CODE, FLOAT)
>> - STRINGIFY_CODE(TYPE_CODE, DOUBLE)
>> - STRINGIFY_CODE(TYPE_CODE, LABEL)
>> - STRINGIFY_CODE(TYPE_CODE, OPAQUE)
>> - STRINGIFY_CODE(TYPE_CODE, INTEGER)
>> - STRINGIFY_CODE(TYPE_CODE, POINTER)
>> - STRINGIFY_CODE(TYPE_CODE, ARRAY)
>> - STRINGIFY_CODE(TYPE_CODE, VECTOR)
>> - STRINGIFY_CODE(TYPE_CODE, X86_FP80)
>> - STRINGIFY_CODE(TYPE_CODE, FP128)
>> - STRINGIFY_CODE(TYPE_CODE, PPC_FP128)
>> - STRINGIFY_CODE(TYPE_CODE, METADATA)
>> - STRINGIFY_CODE(TYPE_CODE, STRUCT_ANON)
>> - STRINGIFY_CODE(TYPE_CODE, STRUCT_NAME)
>> - STRINGIFY_CODE(TYPE_CODE, STRUCT_NAMED)
>> - STRINGIFY_CODE(TYPE_CODE, FUNCTION)
>> - }
>> -
>> - case bitc::CONSTANTS_BLOCK_ID:
>> - switch (CodeID) {
>> - default: return nullptr;
>> - STRINGIFY_CODE(CST_CODE, SETTYPE)
>> - STRINGIFY_CODE(CST_CODE, NULL)
>> - STRINGIFY_CODE(CST_CODE, UNDEF)
>> - STRINGIFY_CODE(CST_CODE, INTEGER)
>> - STRINGIFY_CODE(CST_CODE, WIDE_INTEGER)
>> - STRINGIFY_CODE(CST_CODE, FLOAT)
>> - STRINGIFY_CODE(CST_CODE, AGGREGATE)
>> - STRINGIFY_CODE(CST_CODE, STRING)
>> - STRINGIFY_CODE(CST_CODE, CSTRING)
>> - STRINGIFY_CODE(CST_CODE, CE_BINOP)
>> - STRINGIFY_CODE(CST_CODE, CE_CAST)
>> - STRINGIFY_CODE(CST_CODE, CE_GEP)
>> - STRINGIFY_CODE(CST_CODE, CE_INBOUNDS_GEP)
>> - STRINGIFY_CODE(CST_CODE, CE_SELECT)
>> - STRINGIFY_CODE(CST_CODE, CE_EXTRACTELT)
>> - STRINGIFY_CODE(CST_CODE, CE_INSERTELT)
>> - STRINGIFY_CODE(CST_CODE, CE_SHUFFLEVEC)
>> - STRINGIFY_CODE(CST_CODE, CE_CMP)
>> - STRINGIFY_CODE(CST_CODE, INLINEASM)
>> - STRINGIFY_CODE(CST_CODE, CE_SHUFVEC_EX)
>> - STRINGIFY_CODE(CST_CODE, CE_UNOP)
>> - case bitc::CST_CODE_BLOCKADDRESS: return "CST_CODE_BLOCKADDRESS";
>> - STRINGIFY_CODE(CST_CODE, DATA)
>> - }
>> - case bitc::FUNCTION_BLOCK_ID:
>> - switch (CodeID) {
>> - default: return nullptr;
>> - STRINGIFY_CODE(FUNC_CODE, DECLAREBLOCKS)
>> - STRINGIFY_CODE(FUNC_CODE, INST_BINOP)
>> - STRINGIFY_CODE(FUNC_CODE, INST_CAST)
>> - STRINGIFY_CODE(FUNC_CODE, INST_GEP_OLD)
>> - STRINGIFY_CODE(FUNC_CODE, INST_INBOUNDS_GEP_OLD)
>> - STRINGIFY_CODE(FUNC_CODE, INST_SELECT)
>> - STRINGIFY_CODE(FUNC_CODE, INST_EXTRACTELT)
>> - STRINGIFY_CODE(FUNC_CODE, INST_INSERTELT)
>> - STRINGIFY_CODE(FUNC_CODE, INST_SHUFFLEVEC)
>> - STRINGIFY_CODE(FUNC_CODE, INST_CMP)
>> - STRINGIFY_CODE(FUNC_CODE, INST_RET)
>> - STRINGIFY_CODE(FUNC_CODE, INST_BR)
>> - STRINGIFY_CODE(FUNC_CODE, INST_SWITCH)
>> - STRINGIFY_CODE(FUNC_CODE, INST_INVOKE)
>> - STRINGIFY_CODE(FUNC_CODE, INST_UNOP)
>> - STRINGIFY_CODE(FUNC_CODE, INST_UNREACHABLE)
>> - STRINGIFY_CODE(FUNC_CODE, INST_CLEANUPRET)
>> - STRINGIFY_CODE(FUNC_CODE, INST_CATCHRET)
>> - STRINGIFY_CODE(FUNC_CODE, INST_CATCHPAD)
>> - STRINGIFY_CODE(FUNC_CODE, INST_PHI)
>> - STRINGIFY_CODE(FUNC_CODE, INST_ALLOCA)
>> - STRINGIFY_CODE(FUNC_CODE, INST_LOAD)
>> - STRINGIFY_CODE(FUNC_CODE, INST_VAARG)
>> - STRINGIFY_CODE(FUNC_CODE, INST_STORE)
>> - STRINGIFY_CODE(FUNC_CODE, INST_EXTRACTVAL)
>> - STRINGIFY_CODE(FUNC_CODE, INST_INSERTVAL)
>> - STRINGIFY_CODE(FUNC_CODE, INST_CMP2)
>> - STRINGIFY_CODE(FUNC_CODE, INST_VSELECT)
>> - STRINGIFY_CODE(FUNC_CODE, DEBUG_LOC_AGAIN)
>> - STRINGIFY_CODE(FUNC_CODE, INST_CALL)
>> - STRINGIFY_CODE(FUNC_CODE, DEBUG_LOC)
>> - STRINGIFY_CODE(FUNC_CODE, INST_GEP)
>> - STRINGIFY_CODE(FUNC_CODE, OPERAND_BUNDLE)
>> - STRINGIFY_CODE(FUNC_CODE, INST_FENCE)
>> - STRINGIFY_CODE(FUNC_CODE, INST_ATOMICRMW)
>> - STRINGIFY_CODE(FUNC_CODE, INST_LOADATOMIC)
>> - STRINGIFY_CODE(FUNC_CODE, INST_STOREATOMIC)
>> - STRINGIFY_CODE(FUNC_CODE, INST_CMPXCHG)
>> - STRINGIFY_CODE(FUNC_CODE, INST_CALLBR)
>> - }
>> - case bitc::VALUE_SYMTAB_BLOCK_ID:
>> - switch (CodeID) {
>> - default: return nullptr;
>> - STRINGIFY_CODE(VST_CODE, ENTRY)
>> - STRINGIFY_CODE(VST_CODE, BBENTRY)
>> - STRINGIFY_CODE(VST_CODE, FNENTRY)
>> - STRINGIFY_CODE(VST_CODE, COMBINED_ENTRY)
>> - }
>> - case bitc::MODULE_STRTAB_BLOCK_ID:
>> - switch (CodeID) {
>> - default:
>> - return nullptr;
>> - STRINGIFY_CODE(MST_CODE, ENTRY)
>> - STRINGIFY_CODE(MST_CODE, HASH)
>> - }
>> - case bitc::GLOBALVAL_SUMMARY_BLOCK_ID:
>> - case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID:
>> - switch (CodeID) {
>> - default:
>> - return nullptr;
>> - STRINGIFY_CODE(FS, PERMODULE)
>> - STRINGIFY_CODE(FS, PERMODULE_PROFILE)
>> - STRINGIFY_CODE(FS, PERMODULE_RELBF)
>> - STRINGIFY_CODE(FS, PERMODULE_GLOBALVAR_INIT_REFS)
>> - STRINGIFY_CODE(FS, PERMODULE_VTABLE_GLOBALVAR_INIT_REFS)
>> - STRINGIFY_CODE(FS, COMBINED)
>> - STRINGIFY_CODE(FS, COMBINED_PROFILE)
>> - STRINGIFY_CODE(FS, COMBINED_GLOBALVAR_INIT_REFS)
>> - STRINGIFY_CODE(FS, ALIAS)
>> - STRINGIFY_CODE(FS, COMBINED_ALIAS)
>> - STRINGIFY_CODE(FS, COMBINED_ORIGINAL_NAME)
>> - STRINGIFY_CODE(FS, VERSION)
>> - STRINGIFY_CODE(FS, FLAGS)
>> - STRINGIFY_CODE(FS, TYPE_TESTS)
>> - STRINGIFY_CODE(FS, TYPE_TEST_ASSUME_VCALLS)
>> - STRINGIFY_CODE(FS, TYPE_CHECKED_LOAD_VCALLS)
>> - STRINGIFY_CODE(FS, TYPE_TEST_ASSUME_CONST_VCALL)
>> - STRINGIFY_CODE(FS, TYPE_CHECKED_LOAD_CONST_VCALL)
>> - STRINGIFY_CODE(FS, VALUE_GUID)
>> - STRINGIFY_CODE(FS, CFI_FUNCTION_DEFS)
>> - STRINGIFY_CODE(FS, CFI_FUNCTION_DECLS)
>> - STRINGIFY_CODE(FS, TYPE_ID)
>> - STRINGIFY_CODE(FS, TYPE_ID_METADATA)
>> - }
>> - case bitc::METADATA_ATTACHMENT_ID:
>> - switch(CodeID) {
>> - default:return nullptr;
>> - STRINGIFY_CODE(METADATA, ATTACHMENT)
>> - }
>> - case bitc::METADATA_BLOCK_ID:
>> - switch(CodeID) {
>> - default:return nullptr;
>> - STRINGIFY_CODE(METADATA, STRING_OLD)
>> - STRINGIFY_CODE(METADATA, VALUE)
>> - STRINGIFY_CODE(METADATA, NODE)
>> - STRINGIFY_CODE(METADATA, NAME)
>> - STRINGIFY_CODE(METADATA, DISTINCT_NODE)
>> - STRINGIFY_CODE(METADATA, KIND) // Older bitcode has it in a MODULE_BLOCK
>> - STRINGIFY_CODE(METADATA, LOCATION)
>> - STRINGIFY_CODE(METADATA, OLD_NODE)
>> - STRINGIFY_CODE(METADATA, OLD_FN_NODE)
>> - STRINGIFY_CODE(METADATA, NAMED_NODE)
>> - STRINGIFY_CODE(METADATA, GENERIC_DEBUG)
>> - STRINGIFY_CODE(METADATA, SUBRANGE)
>> - STRINGIFY_CODE(METADATA, ENUMERATOR)
>> - STRINGIFY_CODE(METADATA, BASIC_TYPE)
>> - STRINGIFY_CODE(METADATA, FILE)
>> - STRINGIFY_CODE(METADATA, DERIVED_TYPE)
>> - STRINGIFY_CODE(METADATA, COMPOSITE_TYPE)
>> - STRINGIFY_CODE(METADATA, SUBROUTINE_TYPE)
>> - STRINGIFY_CODE(METADATA, COMPILE_UNIT)
>> - STRINGIFY_CODE(METADATA, SUBPROGRAM)
>> - STRINGIFY_CODE(METADATA, LEXICAL_BLOCK)
>> - STRINGIFY_CODE(METADATA, LEXICAL_BLOCK_FILE)
>> - STRINGIFY_CODE(METADATA, NAMESPACE)
>> - STRINGIFY_CODE(METADATA, TEMPLATE_TYPE)
>> - STRINGIFY_CODE(METADATA, TEMPLATE_VALUE)
>> - STRINGIFY_CODE(METADATA, GLOBAL_VAR)
>> - STRINGIFY_CODE(METADATA, LOCAL_VAR)
>> - STRINGIFY_CODE(METADATA, EXPRESSION)
>> - STRINGIFY_CODE(METADATA, OBJC_PROPERTY)
>> - STRINGIFY_CODE(METADATA, IMPORTED_ENTITY)
>> - STRINGIFY_CODE(METADATA, MODULE)
>> - STRINGIFY_CODE(METADATA, MACRO)
>> - STRINGIFY_CODE(METADATA, MACRO_FILE)
>> - STRINGIFY_CODE(METADATA, STRINGS)
>> - STRINGIFY_CODE(METADATA, GLOBAL_DECL_ATTACHMENT)
>> - STRINGIFY_CODE(METADATA, GLOBAL_VAR_EXPR)
>> - STRINGIFY_CODE(METADATA, INDEX_OFFSET)
>> - STRINGIFY_CODE(METADATA, INDEX)
>> - }
>> - case bitc::METADATA_KIND_BLOCK_ID:
>> - switch (CodeID) {
>> - default:
>> - return nullptr;
>> - STRINGIFY_CODE(METADATA, KIND)
>> - }
>> - case bitc::USELIST_BLOCK_ID:
>> - switch(CodeID) {
>> - default:return nullptr;
>> - case bitc::USELIST_CODE_DEFAULT: return "USELIST_CODE_DEFAULT";
>> - case bitc::USELIST_CODE_BB: return "USELIST_CODE_BB";
>> - }
>> -
>> - case bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID:
>> - switch(CodeID) {
>> - default: return nullptr;
>> - case bitc::OPERAND_BUNDLE_TAG: return "OPERAND_BUNDLE_TAG";
>> - }
>> - case bitc::STRTAB_BLOCK_ID:
>> - switch(CodeID) {
>> - default: return nullptr;
>> - case bitc::STRTAB_BLOB: return "BLOB";
>> - }
>> - case bitc::SYMTAB_BLOCK_ID:
>> - switch(CodeID) {
>> - default: return nullptr;
>> - case bitc::SYMTAB_BLOB: return "BLOB";
>> - }
>> - }
>> -#undef STRINGIFY_CODE
>> +static Error reportError(StringRef Message) {
>> + return createStringError(std::errc::illegal_byte_sequence, Message.data());
>> }
>>
>> -struct PerRecordStats {
>> - unsigned NumInstances;
>> - unsigned NumAbbrev;
>> - uint64_t TotalBits;
>> -
>> - PerRecordStats() : NumInstances(0), NumAbbrev(0), TotalBits(0) {}
>> -};
>> -
>> -struct PerBlockIDStats {
>> - /// NumInstances - This the number of times this block ID has been seen.
>> - unsigned NumInstances;
>> -
>> - /// NumBits - The total size in bits of all of these blocks.
>> - uint64_t NumBits;
>> -
>> - /// NumSubBlocks - The total number of blocks these blocks contain.
>> - unsigned NumSubBlocks;
>> -
>> - /// NumAbbrevs - The total number of abbreviations.
>> - unsigned NumAbbrevs;
>> -
>> - /// NumRecords - The total number of records these blocks contain, and the
>> - /// number that are abbreviated.
>> - unsigned NumRecords, NumAbbreviatedRecords;
>> -
>> - /// CodeFreq - Keep track of the number of times we see each code.
>> - std::vector<PerRecordStats> CodeFreq;
>> -
>> - PerBlockIDStats()
>> - : NumInstances(0), NumBits(0),
>> - NumSubBlocks(0), NumAbbrevs(0), NumRecords(0), NumAbbreviatedRecords(0) {}
>> -};
>> -
>> -static std::map<unsigned, PerBlockIDStats> BlockIDStats;
>> -
>> -/// All bitcode analysis errors go through this function, making this a good
>> -/// place to breakpoint if debugging.
>> -static bool ReportError(const Twine &Err) {
>> - WithColor::error() << Err << "\n";
>> - return true;
>> -}
>> -
>> -static bool ReportError(Error &&Err) {
>> - return ReportError(toString(std::move(Err)));
>> -}
>> -
>> -static bool decodeMetadataStringsBlob(StringRef Indent,
>> - ArrayRef<uint64_t> Record,
>> - StringRef Blob) {
>> - if (Blob.empty())
>> - return true;
>> -
>> - if (Record.size() != 2)
>> - return true;
>> -
>> - unsigned NumStrings = Record[0];
>> - unsigned StringsOffset = Record[1];
>> - outs() << " num-strings = " << NumStrings << " {\n";
>> -
>> - StringRef Lengths = Blob.slice(0, StringsOffset);
>> - SimpleBitstreamCursor R(Lengths);
>> - StringRef Strings = Blob.drop_front(StringsOffset);
>> - do {
>> - if (R.AtEndOfStream())
>> - return ReportError("bad length");
>> -
>> - Expected<uint32_t> MaybeSize = R.ReadVBR(6);
>> - if (!MaybeSize)
>> - return ReportError(MaybeSize.takeError());
>> - uint32_t Size = MaybeSize.get();
>> - if (Strings.size() < Size)
>> - return ReportError("truncated chars");
>> -
>> - outs() << Indent << " '";
>> - outs().write_escaped(Strings.slice(0, Size), /*hex=*/true);
>> - outs() << "'\n";
>> - Strings = Strings.drop_front(Size);
>> - } while (--NumStrings);
>> -
>> - outs() << Indent << " }";
>> - return false;
>> -}
>> -
>> -static bool decodeBlob(unsigned Code, unsigned BlockID, StringRef Indent,
>> - ArrayRef<uint64_t> Record, StringRef Blob) {
>> - if (BlockID != bitc::METADATA_BLOCK_ID)
>> - return true;
>> - if (Code != bitc::METADATA_STRINGS)
>> - return true;
>> -
>> - return decodeMetadataStringsBlob(Indent, Record, Blob);
>> -}
>> -
>> -/// ParseBlock - Read a block, updating statistics, etc.
>> -static bool ParseBlock(BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo,
>> - unsigned BlockID, unsigned IndentLevel,
>> - CurStreamTypeType CurStreamType) {
>> - std::string Indent(IndentLevel*2, ' ');
>> - uint64_t BlockBitStart = Stream.GetCurrentBitNo();
>> -
>> - // Get the statistics for this BlockID.
>> - PerBlockIDStats &BlockStats = BlockIDStats[BlockID];
>> -
>> - BlockStats.NumInstances++;
>> -
>> - // BLOCKINFO is a special part of the stream.
>> - bool DumpRecords = Dump;
>> - if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
>> - if (Dump) outs() << Indent << "<BLOCKINFO_BLOCK/>\n";
>> - Expected<Optional<BitstreamBlockInfo>> MaybeNewBlockInfo =
>> - Stream.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true);
>> - if (!MaybeNewBlockInfo)
>> - return ReportError(MaybeNewBlockInfo.takeError());
>> - Optional<BitstreamBlockInfo> NewBlockInfo =
>> - std::move(MaybeNewBlockInfo.get());
>> - if (!NewBlockInfo)
>> - return ReportError("Malformed BlockInfoBlock");
>> - BlockInfo = std::move(*NewBlockInfo);
>> - if (Error Err = Stream.JumpToBit(BlockBitStart))
>> - return ReportError(std::move(Err));
>> - // It's not really interesting to dump the contents of the blockinfo block.
>> - DumpRecords = false;
>> - }
>> -
>> - unsigned NumWords = 0;
>> - if (Error Err = Stream.EnterSubBlock(BlockID, &NumWords))
>> - return ReportError(std::move(Err));
>> -
>> - // Keep it for later, when we see a MODULE_HASH record
>> - uint64_t BlockEntryPos = Stream.getCurrentByteNo();
>> -
>> - const char *BlockName = nullptr;
>> - if (DumpRecords) {
>> - outs() << Indent << "<";
>> - if ((BlockName = GetBlockName(BlockID, BlockInfo, CurStreamType)))
>> - outs() << BlockName;
>> - else
>> - outs() << "UnknownBlock" << BlockID;
>> -
>> - if (NonSymbolic && BlockName)
>> - outs() << " BlockID=" << BlockID;
>> -
>> - outs() << " NumWords=" << NumWords
>> - << " BlockCodeSize=" << Stream.getAbbrevIDWidth() << ">\n";
>> - }
>> -
>> - SmallVector<uint64_t, 64> Record;
>> -
>> - // Keep the offset to the metadata index if seen.
>> - uint64_t MetadataIndexOffset = 0;
>> -
>> - // Read all the records for this block.
>> - while (1) {
>> - if (Stream.AtEndOfStream())
>> - return ReportError("Premature end of bitstream");
>> -
>> - uint64_t RecordStartBit = Stream.GetCurrentBitNo();
>> -
>> - Expected<BitstreamEntry> MaybeEntry =
>> - Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
>> - if (!MaybeEntry)
>> - return ReportError(MaybeEntry.takeError());
>> - BitstreamEntry Entry = MaybeEntry.get();
>> -
>> - switch (Entry.Kind) {
>> - case BitstreamEntry::Error:
>> - return ReportError("malformed bitcode file");
>> - case BitstreamEntry::EndBlock: {
>> - uint64_t BlockBitEnd = Stream.GetCurrentBitNo();
>> - BlockStats.NumBits += BlockBitEnd-BlockBitStart;
>> - if (DumpRecords) {
>> - outs() << Indent << "</";
>> - if (BlockName)
>> - outs() << BlockName << ">\n";
>> - else
>> - outs() << "UnknownBlock" << BlockID << ">\n";
>> - }
>> - return false;
>> - }
>> -
>> - case BitstreamEntry::SubBlock: {
>> - uint64_t SubBlockBitStart = Stream.GetCurrentBitNo();
>> - if (ParseBlock(Stream, BlockInfo, Entry.ID, IndentLevel + 1,
>> - CurStreamType))
>> - return true;
>> - ++BlockStats.NumSubBlocks;
>> - uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo();
>> -
>> - // Don't include subblock sizes in the size of this block.
>> - BlockBitStart += SubBlockBitEnd-SubBlockBitStart;
>> - continue;
>> - }
>> - case BitstreamEntry::Record:
>> - // The interesting case.
>> - break;
>> - }
>> -
>> - if (Entry.ID == bitc::DEFINE_ABBREV) {
>> - if (Error Err = Stream.ReadAbbrevRecord())
>> - return ReportError(std::move(Err));
>> - ++BlockStats.NumAbbrevs;
>> - continue;
>> - }
>> -
>> - Record.clear();
>> -
>> - ++BlockStats.NumRecords;
>> -
>> - StringRef Blob;
>> - uint64_t CurrentRecordPos = Stream.GetCurrentBitNo();
>> - Expected<unsigned> MaybeCode = Stream.readRecord(Entry.ID, Record, &Blob);
>> - if (!MaybeCode)
>> - return ReportError(MaybeCode.takeError());
>> - unsigned Code = MaybeCode.get();
>> -
>> - // Increment the # occurrences of this code.
>> - if (BlockStats.CodeFreq.size() <= Code)
>> - BlockStats.CodeFreq.resize(Code+1);
>> - BlockStats.CodeFreq[Code].NumInstances++;
>> - BlockStats.CodeFreq[Code].TotalBits +=
>> - Stream.GetCurrentBitNo()-RecordStartBit;
>> - if (Entry.ID != bitc::UNABBREV_RECORD) {
>> - BlockStats.CodeFreq[Code].NumAbbrev++;
>> - ++BlockStats.NumAbbreviatedRecords;
>> - }
>> -
>> - if (DumpRecords) {
>> - outs() << Indent << " <";
>> - if (const char *CodeName =
>> - GetCodeName(Code, BlockID, BlockInfo, CurStreamType))
>> - outs() << CodeName;
>> - else
>> - outs() << "UnknownCode" << Code;
>> - if (NonSymbolic && GetCodeName(Code, BlockID, BlockInfo, CurStreamType))
>> - outs() << " codeid=" << Code;
>> - const BitCodeAbbrev *Abbv = nullptr;
>> - if (Entry.ID != bitc::UNABBREV_RECORD) {
>> - Abbv = Stream.getAbbrev(Entry.ID);
>> - outs() << " abbrevid=" << Entry.ID;
>> - }
>> -
>> - for (unsigned i = 0, e = Record.size(); i != e; ++i)
>> - outs() << " op" << i << "=" << (int64_t)Record[i];
>> -
>> - // If we found a metadata index, let's verify that we had an offset before
>> - // and validate its forward reference offset was correct!
>> - if (BlockID == bitc::METADATA_BLOCK_ID) {
>> - if (Code == bitc::METADATA_INDEX_OFFSET) {
>> - if (Record.size() != 2)
>> - outs() << "(Invalid record)";
>> - else {
>> - auto Offset = Record[0] + (Record[1] << 32);
>> - MetadataIndexOffset = Stream.GetCurrentBitNo() + Offset;
>> - }
>> - }
>> - if (Code == bitc::METADATA_INDEX) {
>> - outs() << " (offset ";
>> - if (MetadataIndexOffset == RecordStartBit)
>> - outs() << "match)";
>> - else
>> - outs() << "mismatch: " << MetadataIndexOffset << " vs "
>> - << RecordStartBit << ")";
>> - }
>> - }
>> -
>> - // If we found a module hash, let's verify that it matches!
>> - if (BlockID == bitc::MODULE_BLOCK_ID && Code == bitc::MODULE_CODE_HASH &&
>> - !CheckHash.empty()) {
>> - if (Record.size() != 5)
>> - outs() << " (invalid)";
>> - else {
>> - // Recompute the hash and compare it to the one in the bitcode
>> - SHA1 Hasher;
>> - StringRef Hash;
>> - Hasher.update(CheckHash);
>> - {
>> - int BlockSize = (CurrentRecordPos / 8) - BlockEntryPos;
>> - auto Ptr = Stream.getPointerToByte(BlockEntryPos, BlockSize);
>> - Hasher.update(ArrayRef<uint8_t>(Ptr, BlockSize));
>> - Hash = Hasher.result();
>> - }
>> - SmallString<20> RecordedHash;
>> - RecordedHash.resize(20);
>> - int Pos = 0;
>> - for (auto &Val : Record) {
>> - assert(!(Val >> 32) && "Unexpected high bits set");
>> - RecordedHash[Pos++] = (Val >> 24) & 0xFF;
>> - RecordedHash[Pos++] = (Val >> 16) & 0xFF;
>> - RecordedHash[Pos++] = (Val >> 8) & 0xFF;
>> - RecordedHash[Pos++] = (Val >> 0) & 0xFF;
>> - }
>> - if (Hash == RecordedHash)
>> - outs() << " (match)";
>> - else
>> - outs() << " (!mismatch!)";
>> - }
>> - }
>> -
>> - outs() << "/>";
>> -
>> - if (Abbv) {
>> - for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) {
>> - const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
>> - if (!Op.isEncoding() || Op.getEncoding() != BitCodeAbbrevOp::Array)
>> - continue;
>> - assert(i + 2 == e && "Array op not second to last");
>> - std::string Str;
>> - bool ArrayIsPrintable = true;
>> - for (unsigned j = i - 1, je = Record.size(); j != je; ++j) {
>> - if (!isPrint(static_cast<unsigned char>(Record[j]))) {
>> - ArrayIsPrintable = false;
>> - break;
>> - }
>> - Str += (char)Record[j];
>> - }
>> - if (ArrayIsPrintable)
>> - outs() << " record string = '" << Str << "'";
>> - break;
>> - }
>> - }
>> -
>> - if (Blob.data() && decodeBlob(Code, BlockID, Indent, Record, Blob)) {
>> - outs() << " blob data = ";
>> - if (ShowBinaryBlobs) {
>> - outs() << "'";
>> - outs().write_escaped(Blob, /*hex=*/true) << "'";
>> - } else {
>> - bool BlobIsPrintable = true;
>> - for (unsigned i = 0, e = Blob.size(); i != e; ++i)
>> - if (!isPrint(static_cast<unsigned char>(Blob[i]))) {
>> - BlobIsPrintable = false;
>> - break;
>> - }
>> -
>> - if (BlobIsPrintable)
>> - outs() << "'" << Blob << "'";
>> - else
>> - outs() << "unprintable, " << Blob.size() << " bytes.";
>> - }
>> - }
>> -
>> - outs() << "\n";
>> - }
>> -
>> - // Make sure that we can skip the current record.
>> - if (Error Err = Stream.JumpToBit(CurrentRecordPos))
>> - return ReportError(std::move(Err));
>> - if (Expected<unsigned> Skipped = Stream.skipRecord(Entry.ID))
>> - ; // Do nothing.
>> - else
>> - return ReportError(Skipped.takeError());
>> - }
>> -}
>> -
>> -static void PrintSize(double Bits) {
>> - outs() << format("%.2f/%.2fB/%luW", Bits, Bits/8,(unsigned long)(Bits/32));
>> -}
>> -static void PrintSize(uint64_t Bits) {
>> - outs() << format("%lub/%.2fB/%luW", (unsigned long)Bits,
>> - (double)Bits/8, (unsigned long)(Bits/32));
>> -}
>> -
>> -static Expected<CurStreamTypeType> ReadSignature(BitstreamCursor &Stream) {
>> - auto tryRead = [&Stream](char &Dest, size_t size) -> Error {
>> - if (Expected<SimpleBitstreamCursor::word_t> MaybeWord = Stream.Read(size))
>> - Dest = MaybeWord.get();
>> - else
>> - return MaybeWord.takeError();
>> - return Error::success();
>> - };
>> -
>> - char Signature[6];
>> - if (Error Err = tryRead(Signature[0], 8))
>> - return std::move(Err);
>> - if (Error Err = tryRead(Signature[1], 8))
>> - return std::move(Err);
>> -
>> - // Autodetect the file contents, if it is one we know.
>> - if (Signature[0] == 'C' && Signature[1] == 'P') {
>> - if (Error Err = tryRead(Signature[2], 8))
>> - return std::move(Err);
>> - if (Error Err = tryRead(Signature[3], 8))
>> - return std::move(Err);
>> - if (Signature[2] == 'C' && Signature[3] == 'H')
>> - return ClangSerializedASTBitstream;
>> - } else if (Signature[0] == 'D' && Signature[1] == 'I') {
>> - if (Error Err = tryRead(Signature[2], 8))
>> - return std::move(Err);
>> - if (Error Err = tryRead(Signature[3], 8))
>> - return std::move(Err);
>> - if (Signature[2] == 'A' && Signature[3] == 'G')
>> - return ClangSerializedDiagnosticsBitstream;
>> - } else {
>> - if (Error Err = tryRead(Signature[2], 4))
>> - return std::move(Err);
>> - if (Error Err = tryRead(Signature[3], 4))
>> - return std::move(Err);
>> - if (Error Err = tryRead(Signature[4], 4))
>> - return std::move(Err);
>> - if (Error Err = tryRead(Signature[5], 4))
>> - return std::move(Err);
>> - if (Signature[0] == 'B' && Signature[1] == 'C' &&
>> - Signature[2] == 0x0 && Signature[3] == 0xC &&
>> - Signature[4] == 0xE && Signature[5] == 0xD)
>> - return LLVMIRBitstream;
>> - }
>> - return UnknownBitstream;
>> -}
>> -
>> -static bool openBitcodeFile(StringRef Path,
>> - std::unique_ptr<MemoryBuffer> &MemBuf,
>> - BitstreamCursor &Stream,
>> - CurStreamTypeType &CurStreamType) {
>> +static Expected<std::unique_ptr<MemoryBuffer>> openBitcodeFile(StringRef Path) {
>> // Read the input file.
>> - ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr =
>> - MemoryBuffer::getFileOrSTDIN(Path);
>> - if (std::error_code EC = MemBufOrErr.getError())
>> - return ReportError(Twine("ReportError reading '") + Path + "': " + EC.message());
>> - MemBuf = std::move(MemBufOrErr.get());
>> -
>> - if (MemBuf->getBufferSize() & 3)
>> - return ReportError("Bitcode stream should be a multiple of 4 bytes in length");
>> -
>> - const unsigned char *BufPtr = (const unsigned char *)MemBuf->getBufferStart();
>> - const unsigned char *EndBufPtr = BufPtr + MemBuf->getBufferSize();
>> + Expected<std::unique_ptr<MemoryBuffer>> MemBufOrErr =
>> + errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Path));
>> + if (Error E = MemBufOrErr.takeError())
>> + return std::move(E);
>>
>> - // If we have a wrapper header, parse it and ignore the non-bc file contents.
>> - // The magic number is 0x0B17C0DE stored in little endian.
>> - if (isBitcodeWrapper(BufPtr, EndBufPtr)) {
>> - if (MemBuf->getBufferSize() < BWH_HeaderSize)
>> - return ReportError("Invalid bitcode wrapper header");
>> + std::unique_ptr<MemoryBuffer> MemBuf = std::move(*MemBufOrErr);
>>
>> - if (Dump) {
>> - unsigned Magic = support::endian::read32le(&BufPtr[BWH_MagicField]);
>> - unsigned Version = support::endian::read32le(&BufPtr[BWH_VersionField]);
>> - unsigned Offset = support::endian::read32le(&BufPtr[BWH_OffsetField]);
>> - unsigned Size = support::endian::read32le(&BufPtr[BWH_SizeField]);
>> - unsigned CPUType = support::endian::read32le(&BufPtr[BWH_CPUTypeField]);
>> -
>> - outs() << "<BITCODE_WRAPPER_HEADER"
>> - << " Magic=" << format_hex(Magic, 10)
>> - << " Version=" << format_hex(Version, 10)
>> - << " Offset=" << format_hex(Offset, 10)
>> - << " Size=" << format_hex(Size, 10)
>> - << " CPUType=" << format_hex(CPUType, 10) << "/>\n";
>> - }
>> -
>> - if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr, true))
>> - return ReportError("Invalid bitcode wrapper header");
>> - }
>> -
>> - Stream = BitstreamCursor(ArrayRef<uint8_t>(BufPtr, EndBufPtr));
>> - Expected<CurStreamTypeType> MaybeSignature = ReadSignature(Stream);
>> - if (!MaybeSignature)
>> - return ReportError(MaybeSignature.takeError());
>> - CurStreamType = std::move(MaybeSignature.get());
>> -
>> - return false;
>> + if (MemBuf->getBufferSize() & 3)
>> + return reportError(
>> + "Bitcode stream should be a multiple of 4 bytes in length");
>> + return std::move(MemBuf);
>> }
>>
>> -/// AnalyzeBitcode - Analyze the bitcode file specified by InputFilename.
>> -static int AnalyzeBitcode() {
>> - std::unique_ptr<MemoryBuffer> StreamBuffer;
>> - BitstreamCursor Stream;
>> - BitstreamBlockInfo BlockInfo;
>> - CurStreamTypeType CurStreamType;
>> - if (openBitcodeFile(InputFilename, StreamBuffer, Stream, CurStreamType))
>> - return true;
>> - Stream.setBlockInfo(&BlockInfo);
>> -
>> - // Read block info from BlockInfoFilename, if specified.
>> - // The block info must be a top-level block.
>> - if (!BlockInfoFilename.empty()) {
>> - std::unique_ptr<MemoryBuffer> BlockInfoBuffer;
>> - BitstreamCursor BlockInfoCursor;
>> - CurStreamTypeType BlockInfoStreamType;
>> - if (openBitcodeFile(BlockInfoFilename, BlockInfoBuffer, BlockInfoCursor,
>> - BlockInfoStreamType))
>> - return true;
>> -
>> - while (!BlockInfoCursor.AtEndOfStream()) {
>> - Expected<unsigned> MaybeCode = BlockInfoCursor.ReadCode();
>> - if (!MaybeCode)
>> - return ReportError(MaybeCode.takeError());
>> - if (MaybeCode.get() != bitc::ENTER_SUBBLOCK)
>> - return ReportError("Invalid record at top-level in block info file");
>> -
>> - Expected<unsigned> MaybeBlockID = BlockInfoCursor.ReadSubBlockID();
>> - if (!MaybeBlockID)
>> - return ReportError(MaybeBlockID.takeError());
>> - if (MaybeBlockID.get() == bitc::BLOCKINFO_BLOCK_ID) {
>> - Expected<Optional<BitstreamBlockInfo>> MaybeNewBlockInfo =
>> - BlockInfoCursor.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true);
>> - if (!MaybeNewBlockInfo)
>> - return ReportError(MaybeNewBlockInfo.takeError());
>> - Optional<BitstreamBlockInfo> NewBlockInfo =
>> - std::move(MaybeNewBlockInfo.get());
>> - if (!NewBlockInfo)
>> - return ReportError("Malformed BlockInfoBlock in block info file");
>> - BlockInfo = std::move(*NewBlockInfo);
>> - break;
>> - }
>> -
>> - if (Error Err = BlockInfoCursor.SkipBlock())
>> - return ReportError(std::move(Err));
>> - }
>> - }
>> -
>> - unsigned NumTopBlocks = 0;
>> -
>> - // Parse the top-level structure. We only allow blocks at the top-level.
>> - while (!Stream.AtEndOfStream()) {
>> - Expected<unsigned> MaybeCode = Stream.ReadCode();
>> - if (!MaybeCode)
>> - return ReportError(MaybeCode.takeError());
>> - if (MaybeCode.get() != bitc::ENTER_SUBBLOCK)
>> - return ReportError("Invalid record at top-level");
>> -
>> - Expected<unsigned> MaybeBlockID = Stream.ReadSubBlockID();
>> - if (!MaybeBlockID)
>> - return ReportError(MaybeBlockID.takeError());
>> -
>> - if (ParseBlock(Stream, BlockInfo, MaybeBlockID.get(), 0, CurStreamType))
>> - return true;
>> - ++NumTopBlocks;
>> - }
>> -
>> - if (Dump) outs() << "\n\n";
>> -
>> - uint64_t BufferSizeBits = Stream.getBitcodeBytes().size() * CHAR_BIT;
>> - // Print a summary of the read file.
>> - outs() << "Summary of " << InputFilename << ":\n";
>> - outs() << " Total size: ";
>> - PrintSize(BufferSizeBits);
>> - outs() << "\n";
>> - outs() << " Stream type: ";
>> - switch (CurStreamType) {
>> - case UnknownBitstream:
>> - outs() << "unknown\n";
>> - break;
>> - case LLVMIRBitstream:
>> - outs() << "LLVM IR\n";
>> - break;
>> - case ClangSerializedASTBitstream:
>> - outs() << "Clang Serialized AST\n";
>> - break;
>> - case ClangSerializedDiagnosticsBitstream:
>> - outs() << "Clang Serialized Diagnostics\n";
>> - break;
>> - }
>> - outs() << " # Toplevel Blocks: " << NumTopBlocks << "\n";
>> - outs() << "\n";
>> -
>> - // Emit per-block stats.
>> - outs() << "Per-block Summary:\n";
>> - for (std::map<unsigned, PerBlockIDStats>::iterator I = BlockIDStats.begin(),
>> - E = BlockIDStats.end(); I != E; ++I) {
>> - outs() << " Block ID #" << I->first;
>> - if (const char *BlockName =
>> - GetBlockName(I->first, BlockInfo, CurStreamType))
>> - outs() << " (" << BlockName << ")";
>> - outs() << ":\n";
>> -
>> - const PerBlockIDStats &Stats = I->second;
>> - outs() << " Num Instances: " << Stats.NumInstances << "\n";
>> - outs() << " Total Size: ";
>> - PrintSize(Stats.NumBits);
>> - outs() << "\n";
>> - double pct = (Stats.NumBits * 100.0) / BufferSizeBits;
>> - outs() << " Percent of file: " << format("%2.4f%%", pct) << "\n";
>> - if (Stats.NumInstances > 1) {
>> - outs() << " Average Size: ";
>> - PrintSize(Stats.NumBits/(double)Stats.NumInstances);
>> - outs() << "\n";
>> - outs() << " Tot/Avg SubBlocks: " << Stats.NumSubBlocks << "/"
>> - << Stats.NumSubBlocks/(double)Stats.NumInstances << "\n";
>> - outs() << " Tot/Avg Abbrevs: " << Stats.NumAbbrevs << "/"
>> - << Stats.NumAbbrevs/(double)Stats.NumInstances << "\n";
>> - outs() << " Tot/Avg Records: " << Stats.NumRecords << "/"
>> - << Stats.NumRecords/(double)Stats.NumInstances << "\n";
>> - } else {
>> - outs() << " Num SubBlocks: " << Stats.NumSubBlocks << "\n";
>> - outs() << " Num Abbrevs: " << Stats.NumAbbrevs << "\n";
>> - outs() << " Num Records: " << Stats.NumRecords << "\n";
>> - }
>> - if (Stats.NumRecords) {
>> - double pct = (Stats.NumAbbreviatedRecords * 100.0) / Stats.NumRecords;
>> - outs() << " Percent Abbrevs: " << format("%2.4f%%", pct) << "\n";
>> - }
>> - outs() << "\n";
>> -
>> - // Print a histogram of the codes we see.
>> - if (!NoHistogram && !Stats.CodeFreq.empty()) {
>> - std::vector<std::pair<unsigned, unsigned> > FreqPairs; // <freq,code>
>> - for (unsigned i = 0, e = Stats.CodeFreq.size(); i != e; ++i)
>> - if (unsigned Freq = Stats.CodeFreq[i].NumInstances)
>> - FreqPairs.push_back(std::make_pair(Freq, i));
>> - llvm::stable_sort(FreqPairs);
>> - std::reverse(FreqPairs.begin(), FreqPairs.end());
>> +int main(int argc, char **argv) {
>> + InitLLVM X(argc, argv);
>> + cl::ParseCommandLineOptions(argc, argv, "llvm-bcanalyzer file analyzer\n");
>> + ExitOnError ExitOnErr("llvm-bcanalyzer: ");
>>
>> - outs() << "\tRecord Histogram:\n";
>> - outs() << "\t\t Count # Bits b/Rec % Abv Record Kind\n";
>> - for (unsigned i = 0, e = FreqPairs.size(); i != e; ++i) {
>> - const PerRecordStats &RecStats = Stats.CodeFreq[FreqPairs[i].second];
>> + std::unique_ptr<MemoryBuffer> MB = ExitOnErr(openBitcodeFile(InputFilename));
>> + std::unique_ptr<MemoryBuffer> BlockInfoMB = nullptr;
>> + if (!BlockInfoFilename.empty())
>> + BlockInfoMB = ExitOnErr(openBitcodeFile(BlockInfoFilename));
>>
>> - outs() << format("\t\t%7d %9lu",
>> - RecStats.NumInstances,
>> - (unsigned long)RecStats.TotalBits);
>> + BitcodeAnalyzer BA(MB->getBuffer(),
>> + BlockInfoMB ? Optional<StringRef>(BlockInfoMB->getBuffer())
>> + : None);
>>
>> - if (RecStats.NumInstances > 1)
>> - outs() << format(" %9.1f",
>> - (double)RecStats.TotalBits/RecStats.NumInstances);
>> - else
>> - outs() << " ";
>> + BCDumpOptions O(outs());
>> + O.Histogram = !NoHistogram;
>> + O.Symbolic = !NonSymbolic;
>> + O.ShowBinaryBlobs = ShowBinaryBlobs;
>>
>> - if (RecStats.NumAbbrev)
>> - outs() <<
>> - format(" %7.2f",
>> - (double)RecStats.NumAbbrev/RecStats.NumInstances*100);
>> - else
>> - outs() << " ";
>> + ExitOnErr(
>> + BA.analyze(O, CheckHash.empty() ? None : Optional<StringRef>(CheckHash)));
>>
>> - outs() << " ";
>> - if (const char *CodeName = GetCodeName(FreqPairs[i].second, I->first,
>> - BlockInfo, CurStreamType))
>> - outs() << CodeName << "\n";
>> - else
>> - outs() << "UnknownCode" << FreqPairs[i].second << "\n";
>> - }
>> - outs() << "\n";
>> + if (Dump)
>> + outs() << "\n\n";
>>
>> - }
>> - }
>> + BA.printStats(O, StringRef(InputFilename.getValue()));
>> return 0;
>> }
>> -
>> -
>> -int main(int argc, char **argv) {
>> - InitLLVM X(argc, argv);
>> - cl::ParseCommandLineOptions(argc, argv, "llvm-bcanalyzer file analyzer\n");
>> - return AnalyzeBitcode();
>> -}
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> https://protect2.fireeye.com/url?k=b1ff8776-ed2b82c9-b1ffc7ed-868f633dbf25-7b7ee54d102d2638&q=1&u=https%3A%2F%2Flists.llvm.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fllvm-commits
>>
More information about the llvm-commits
mailing list