2007-07-05 05:55:50 +08:00
|
|
|
//===-- llvm-bcanalyzer.cpp - Bitcode Analyzer --------------------------===//
|
2005-04-22 08:00:37 +08:00
|
|
|
//
|
2004-06-08 01:53:43 +08:00
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 04:44:31 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2005-04-22 08:00:37 +08:00
|
|
|
//
|
2004-06-08 01:53:43 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2004-06-08 13:56:58 +08:00
|
|
|
// This tool may be invoked in the following manner:
|
2007-07-05 05:55:50 +08:00
|
|
|
// llvm-bcanalyzer [options] - Read LLVM bitcode from stdin
|
|
|
|
// llvm-bcanalyzer [options] x.bc - Read LLVM bitcode from the x.bc file
|
2004-06-08 13:56:58 +08:00
|
|
|
//
|
2004-06-08 01:53:43 +08:00
|
|
|
// Options:
|
2004-06-11 02:38:44 +08:00
|
|
|
// --help - Output information about command line switches
|
2007-07-05 05:55:50 +08:00
|
|
|
// --dump - Dump low-level bitcode structure in readable format
|
2004-06-08 01:53:43 +08:00
|
|
|
//
|
2007-07-05 05:55:50 +08:00
|
|
|
// This tool provides analytical information about a bitcode file. It is
|
|
|
|
// intended as an aid to developers of bitcode reading and writing software. It
|
|
|
|
// produces on std::out a summary of the bitcode file that shows various
|
2004-06-11 02:38:44 +08:00
|
|
|
// statistics about the contents of the file. By default this information is
|
2007-07-05 05:55:50 +08:00
|
|
|
// detailed and contains information about individual bitcode blocks and the
|
2009-09-26 00:03:57 +08:00
|
|
|
// functions in the module.
|
2007-07-05 05:55:50 +08:00
|
|
|
// The tool is also able to print a bitcode file in a straight forward text
|
2005-04-22 08:00:37 +08:00
|
|
|
// format that shows the containment and relationships of the information in
|
2007-07-05 05:55:50 +08:00
|
|
|
// the bitcode file (-dump option).
|
2007-04-29 13:51:00 +08:00
|
|
|
//
|
2004-06-08 01:53:43 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2016-04-01 13:33:11 +08:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2016-11-11 13:34:58 +08:00
|
|
|
#include "llvm/Bitcode/BitcodeReader.h"
|
2016-04-18 17:17:29 +08:00
|
|
|
#include "llvm/Bitcode/BitstreamReader.h"
|
2007-04-30 04:00:02 +08:00
|
|
|
#include "llvm/Bitcode/LLVMBitCodes.h"
|
2004-09-02 06:55:40 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2009-09-26 00:04:21 +08:00
|
|
|
#include "llvm/Support/Format.h"
|
2018-04-14 02:26:06 +08:00
|
|
|
#include "llvm/Support/InitLLVM.h"
|
2006-12-06 09:18:01 +08:00
|
|
|
#include "llvm/Support/ManagedStatic.h"
|
2007-04-29 16:12:22 +08:00
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
2016-04-01 13:33:11 +08:00
|
|
|
#include "llvm/Support/SHA1.h"
|
2018-04-22 05:11:59 +08:00
|
|
|
#include "llvm/Support/WithColor.h"
|
2012-12-04 18:44:52 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2004-06-08 01:53:43 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
static cl::opt<std::string>
|
2007-07-05 05:55:50 +08:00
|
|
|
InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
|
2004-06-08 01:53:43 +08:00
|
|
|
|
2007-07-05 05:55:50 +08:00
|
|
|
static cl::opt<bool> Dump("dump", cl::desc("Dump low level bitcode trace"));
|
2007-04-29 16:31:14 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Bitcode specific analysis.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2007-05-05 09:46:49 +08:00
|
|
|
static cl::opt<bool> NoHistogram("disable-histogram",
|
|
|
|
cl::desc("Do not print per-code histogram"));
|
2007-04-29 16:12:22 +08:00
|
|
|
|
2007-04-30 05:48:19 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
NonSymbolic("non-symbolic",
|
2010-12-16 11:29:14 +08:00
|
|
|
cl::desc("Emit numeric info in dump even if"
|
2007-04-30 05:48:19 +08:00
|
|
|
" symbolic info is available"));
|
|
|
|
|
2014-08-31 01:07:55 +08:00
|
|
|
static cl::opt<std::string>
|
|
|
|
BlockInfoFilename("block-info",
|
|
|
|
cl::desc("Use the BLOCK_INFO from the given file"));
|
|
|
|
|
2015-05-14 02:51:49 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
ShowBinaryBlobs("show-binary-blobs",
|
|
|
|
cl::desc("Print binary blobs using hex escapes"));
|
|
|
|
|
2017-07-07 01:56:01 +08:00
|
|
|
static cl::opt<std::string> CheckHash(
|
|
|
|
"check-hash",
|
|
|
|
cl::desc("Check module hash using the argument as a string table"));
|
|
|
|
|
2010-12-10 04:35:40 +08:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
/// CurStreamTypeType - A type for CurStreamType
|
|
|
|
enum CurStreamTypeType {
|
2007-04-29 16:12:22 +08:00
|
|
|
UnknownBitstream,
|
[bcanalyzer] Recognize more stream types
Summary:
`llvm-bcanalyzer` prints out the stream type of the file it is
analyzing. If the file begins with the LLVM IR magic number, it reports
a stream type of "LLVM IR". However, any other bitstream format is
reported as "unknown".
Add some checks for two other common bitstream formats: Clang AST
files, which begin with 'CPCH', and Clang serialized diagnostics, which
begin with 'DIAG'.
Test Plan: `check-llvm`
Reviewers: pcc, aprantl, mehdi_amini, davide, george.karpenkov, JDevlieghere
Reviewed By: JDevlieghere
Subscribers: JDevlieghere, bruno, davide, llvm-commits
Differential Revision: https://reviews.llvm.org/D41979
llvm-svn: 330529
2018-04-22 07:52:04 +08:00
|
|
|
LLVMIRBitstream,
|
|
|
|
ClangSerializedASTBitstream,
|
|
|
|
ClangSerializedDiagnosticsBitstream,
|
2010-12-10 04:35:40 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2007-04-30 04:00:02 +08:00
|
|
|
/// GetBlockName - Return a symbolic block name if known, otherwise return
|
2007-04-30 05:48:19 +08:00
|
|
|
/// null.
|
2009-04-27 06:21:57 +08:00
|
|
|
static const char *GetBlockName(unsigned BlockID,
|
2016-11-08 12:17:11 +08:00
|
|
|
const BitstreamBlockInfo &BlockInfo,
|
2014-08-31 01:07:55 +08:00
|
|
|
CurStreamTypeType CurStreamType) {
|
2007-05-05 08:17:42 +08:00
|
|
|
// Standard blocks for all bitcode files.
|
|
|
|
if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {
|
|
|
|
if (BlockID == bitc::BLOCKINFO_BLOCK_ID)
|
|
|
|
return "BLOCKINFO_BLOCK";
|
2014-04-25 12:24:47 +08:00
|
|
|
return nullptr;
|
2007-05-05 08:17:42 +08:00
|
|
|
}
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2009-04-27 06:21:57 +08:00
|
|
|
// Check to see if we have a blockinfo record for this block, with a name.
|
2016-11-08 12:17:11 +08:00
|
|
|
if (const BitstreamBlockInfo::BlockInfo *Info =
|
|
|
|
BlockInfo.getBlockInfo(BlockID)) {
|
2009-04-27 06:21:57 +08:00
|
|
|
if (!Info->Name.empty())
|
|
|
|
return Info->Name.c_str();
|
|
|
|
}
|
2009-09-26 00:03:57 +08:00
|
|
|
|
|
|
|
|
2014-04-25 12:24:47 +08:00
|
|
|
if (CurStreamType != LLVMIRBitstream) return nullptr;
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2007-04-30 04:00:02 +08:00
|
|
|
switch (BlockID) {
|
2016-04-26 13:59:14 +08:00
|
|
|
default: return nullptr;
|
2016-04-26 13:59:08 +08:00
|
|
|
case bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID: return "OPERAND_BUNDLE_TAGS_BLOCK";
|
2016-04-26 13:59:14 +08:00
|
|
|
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";
|
2015-10-27 02:37:00 +08:00
|
|
|
case bitc::IDENTIFICATION_BLOCK_ID:
|
2016-04-26 13:59:14 +08:00
|
|
|
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";
|
[ThinLTO] Support for reference graph in per-module and combined summary.
Summary:
This patch adds support for including a full reference graph including
call graph edges and other GV references in the summary.
The reference graph edges can be used to make importing decisions
without materializing any source modules, can be used in the plugin
to make file staging decisions for distributed build systems, and is
expected to have other uses.
The call graph edges are recorded in each function summary in the
bitcode via a list of <CalleeValueIds, StaticCount> tuples when no PGO
data exists, or <CalleeValueId, StaticCount, ProfileCount> pairs when
there is PGO, where the ValueId can be mapped to the function GUID via
the ValueSymbolTable. In the function index in memory, the call graph
edges reference the target via the CalleeGUID instead of the
CalleeValueId.
The reference graph edges are recorded in each summary record with a
list of referenced value IDs, which can be mapped to value GUID via the
ValueSymbolTable.
Addtionally, a new summary record type is added to record references
from global variable initializers. A number of bitcode records and data
structures have been renamed to reflect the newly expanded scope of the
summary beyond functions. More cleanup will follow.
Reviewers: joker.eph, davidxl
Subscribers: joker.eph, llvm-commits
Differential Revision: http://reviews.llvm.org/D17212
llvm-svn: 263275
2016-03-12 02:52:24 +08:00
|
|
|
case bitc::GLOBALVAL_SUMMARY_BLOCK_ID:
|
2016-04-26 13:59:14 +08:00
|
|
|
return "GLOBALVAL_SUMMARY_BLOCK";
|
2017-06-09 07:01:49 +08:00
|
|
|
case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID:
|
|
|
|
return "FULL_LTO_GLOBALVAL_SUMMARY_BLOCK";
|
2016-04-26 13:59:14 +08:00
|
|
|
case bitc::MODULE_STRTAB_BLOCK_ID: return "MODULE_STRTAB_BLOCK";
|
2017-04-18 01:51:36 +08:00
|
|
|
case bitc::STRTAB_BLOCK_ID: return "STRTAB_BLOCK";
|
2017-06-28 07:50:11 +08:00
|
|
|
case bitc::SYMTAB_BLOCK_ID: return "SYMTAB_BLOCK";
|
2007-04-30 04:00:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-30 05:48:19 +08:00
|
|
|
/// GetCodeName - Return a symbolic code name if known, otherwise return
|
|
|
|
/// null.
|
2009-04-27 06:21:57 +08:00
|
|
|
static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
|
2016-11-08 12:17:11 +08:00
|
|
|
const BitstreamBlockInfo &BlockInfo,
|
2014-08-31 01:07:55 +08:00
|
|
|
CurStreamTypeType CurStreamType) {
|
2007-05-05 08:17:42 +08:00
|
|
|
// Standard blocks for all bitcode files.
|
|
|
|
if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {
|
|
|
|
if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
|
|
|
|
switch (CodeID) {
|
2014-04-25 12:24:47 +08:00
|
|
|
default: return nullptr;
|
2009-04-27 06:21:57 +08:00
|
|
|
case bitc::BLOCKINFO_CODE_SETBID: return "SETBID";
|
|
|
|
case bitc::BLOCKINFO_CODE_BLOCKNAME: return "BLOCKNAME";
|
|
|
|
case bitc::BLOCKINFO_CODE_SETRECORDNAME: return "SETRECORDNAME";
|
2007-05-05 08:17:42 +08:00
|
|
|
}
|
|
|
|
}
|
2014-04-25 12:24:47 +08:00
|
|
|
return nullptr;
|
2007-05-05 08:17:42 +08:00
|
|
|
}
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2009-04-27 06:21:57 +08:00
|
|
|
// Check to see if we have a blockinfo record for this record, with a name.
|
2016-11-08 12:17:11 +08:00
|
|
|
if (const BitstreamBlockInfo::BlockInfo *Info =
|
|
|
|
BlockInfo.getBlockInfo(BlockID)) {
|
2009-04-27 06:21:57 +08:00
|
|
|
for (unsigned i = 0, e = Info->RecordNames.size(); i != e; ++i)
|
|
|
|
if (Info->RecordNames[i].first == CodeID)
|
|
|
|
return Info->RecordNames[i].second.c_str();
|
|
|
|
}
|
2009-09-26 00:03:57 +08:00
|
|
|
|
|
|
|
|
2014-04-25 12:24:47 +08:00
|
|
|
if (CurStreamType != LLVMIRBitstream) return nullptr;
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2015-06-30 06:50:32 +08:00
|
|
|
#define STRINGIFY_CODE(PREFIX, CODE) \
|
|
|
|
case bitc::PREFIX##_##CODE: \
|
|
|
|
return #CODE;
|
2007-04-30 05:48:19 +08:00
|
|
|
switch (BlockID) {
|
2014-04-25 12:24:47 +08:00
|
|
|
default: return nullptr;
|
2007-04-30 05:48:19 +08:00
|
|
|
case bitc::MODULE_BLOCK_ID:
|
|
|
|
switch (CodeID) {
|
2014-04-25 12:24:47 +08:00
|
|
|
default: return nullptr;
|
2015-06-30 06:50:32 +08:00
|
|
|
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)
|
2015-09-18 04:12:00 +08:00
|
|
|
STRINGIFY_CODE(MODULE_CODE, VSTOFFSET)
|
2016-03-25 09:29:50 +08:00
|
|
|
STRINGIFY_CODE(MODULE_CODE, METADATA_VALUES_UNUSED)
|
2016-02-11 05:55:02 +08:00
|
|
|
STRINGIFY_CODE(MODULE_CODE, SOURCE_FILENAME)
|
2016-04-01 13:33:11 +08:00
|
|
|
STRINGIFY_CODE(MODULE_CODE, HASH)
|
2007-04-30 05:48:19 +08:00
|
|
|
}
|
2015-10-27 02:37:00 +08:00
|
|
|
case bitc::IDENTIFICATION_BLOCK_ID:
|
|
|
|
switch (CodeID) {
|
|
|
|
default:
|
|
|
|
return nullptr;
|
|
|
|
STRINGIFY_CODE(IDENTIFICATION_CODE, STRING)
|
|
|
|
STRINGIFY_CODE(IDENTIFICATION_CODE, EPOCH)
|
|
|
|
}
|
2007-05-04 11:01:41 +08:00
|
|
|
case bitc::PARAMATTR_BLOCK_ID:
|
|
|
|
switch (CodeID) {
|
2014-04-25 12:24:47 +08:00
|
|
|
default: return nullptr;
|
2015-06-30 06:50:32 +08:00
|
|
|
// FIXME: Should these be different?
|
2013-02-11 07:17:10 +08:00
|
|
|
case bitc::PARAMATTR_CODE_ENTRY_OLD: return "ENTRY";
|
|
|
|
case bitc::PARAMATTR_CODE_ENTRY: return "ENTRY";
|
2016-03-16 06:37:25 +08:00
|
|
|
}
|
|
|
|
case bitc::PARAMATTR_GROUP_BLOCK_ID:
|
|
|
|
switch (CodeID) {
|
|
|
|
default: return nullptr;
|
2013-02-11 07:17:10 +08:00
|
|
|
case bitc::PARAMATTR_GRP_CODE_ENTRY: return "ENTRY";
|
2007-05-04 11:01:41 +08:00
|
|
|
}
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
case bitc::TYPE_BLOCK_ID_NEW:
|
2007-04-30 05:48:19 +08:00
|
|
|
switch (CodeID) {
|
2014-04-25 12:24:47 +08:00
|
|
|
default: return nullptr;
|
2015-06-30 06:50:32 +08:00
|
|
|
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)
|
2007-04-30 05:48:19 +08:00
|
|
|
}
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2007-04-30 05:48:19 +08:00
|
|
|
case bitc::CONSTANTS_BLOCK_ID:
|
|
|
|
switch (CodeID) {
|
2014-04-25 12:24:47 +08:00
|
|
|
default: return nullptr;
|
2015-06-30 06:50:32 +08:00
|
|
|
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)
|
2012-01-30 08:51:16 +08:00
|
|
|
case bitc::CST_CODE_BLOCKADDRESS: return "CST_CODE_BLOCKADDRESS";
|
2015-06-30 06:50:32 +08:00
|
|
|
STRINGIFY_CODE(CST_CODE, DATA)
|
2009-09-26 00:03:57 +08:00
|
|
|
}
|
2007-04-30 05:48:19 +08:00
|
|
|
case bitc::FUNCTION_BLOCK_ID:
|
|
|
|
switch (CodeID) {
|
2014-04-25 12:24:47 +08:00
|
|
|
default: return nullptr;
|
2015-06-30 06:50:32 +08:00
|
|
|
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_UNREACHABLE)
|
2015-08-01 01:58:14 +08:00
|
|
|
STRINGIFY_CODE(FUNC_CODE, INST_CLEANUPRET)
|
|
|
|
STRINGIFY_CODE(FUNC_CODE, INST_CATCHRET)
|
|
|
|
STRINGIFY_CODE(FUNC_CODE, INST_CATCHPAD)
|
2015-06-30 06:50:32 +08:00
|
|
|
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)
|
2016-04-26 13:59:08 +08:00
|
|
|
STRINGIFY_CODE(FUNC_CODE, OPERAND_BUNDLE)
|
2018-09-24 20:47:17 +08:00
|
|
|
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)
|
2007-04-30 05:48:19 +08:00
|
|
|
}
|
|
|
|
case bitc::VALUE_SYMTAB_BLOCK_ID:
|
|
|
|
switch (CodeID) {
|
2014-04-25 12:24:47 +08:00
|
|
|
default: return nullptr;
|
2015-06-30 06:50:32 +08:00
|
|
|
STRINGIFY_CODE(VST_CODE, ENTRY)
|
|
|
|
STRINGIFY_CODE(VST_CODE, BBENTRY)
|
2015-09-18 04:12:00 +08:00
|
|
|
STRINGIFY_CODE(VST_CODE, FNENTRY)
|
[ThinLTO] Support for reference graph in per-module and combined summary.
Summary:
This patch adds support for including a full reference graph including
call graph edges and other GV references in the summary.
The reference graph edges can be used to make importing decisions
without materializing any source modules, can be used in the plugin
to make file staging decisions for distributed build systems, and is
expected to have other uses.
The call graph edges are recorded in each function summary in the
bitcode via a list of <CalleeValueIds, StaticCount> tuples when no PGO
data exists, or <CalleeValueId, StaticCount, ProfileCount> pairs when
there is PGO, where the ValueId can be mapped to the function GUID via
the ValueSymbolTable. In the function index in memory, the call graph
edges reference the target via the CalleeGUID instead of the
CalleeValueId.
The reference graph edges are recorded in each summary record with a
list of referenced value IDs, which can be mapped to value GUID via the
ValueSymbolTable.
Addtionally, a new summary record type is added to record references
from global variable initializers. A number of bitcode records and data
structures have been renamed to reflect the newly expanded scope of the
summary beyond functions. More cleanup will follow.
Reviewers: joker.eph, davidxl
Subscribers: joker.eph, llvm-commits
Differential Revision: http://reviews.llvm.org/D17212
llvm-svn: 263275
2016-03-12 02:52:24 +08:00
|
|
|
STRINGIFY_CODE(VST_CODE, COMBINED_ENTRY)
|
2015-10-04 22:33:43 +08:00
|
|
|
}
|
|
|
|
case bitc::MODULE_STRTAB_BLOCK_ID:
|
|
|
|
switch (CodeID) {
|
2015-11-03 02:02:11 +08:00
|
|
|
default:
|
|
|
|
return nullptr;
|
|
|
|
STRINGIFY_CODE(MST_CODE, ENTRY)
|
2016-04-01 13:33:11 +08:00
|
|
|
STRINGIFY_CODE(MST_CODE, HASH)
|
2015-10-04 22:33:43 +08:00
|
|
|
}
|
[ThinLTO] Support for reference graph in per-module and combined summary.
Summary:
This patch adds support for including a full reference graph including
call graph edges and other GV references in the summary.
The reference graph edges can be used to make importing decisions
without materializing any source modules, can be used in the plugin
to make file staging decisions for distributed build systems, and is
expected to have other uses.
The call graph edges are recorded in each function summary in the
bitcode via a list of <CalleeValueIds, StaticCount> tuples when no PGO
data exists, or <CalleeValueId, StaticCount, ProfileCount> pairs when
there is PGO, where the ValueId can be mapped to the function GUID via
the ValueSymbolTable. In the function index in memory, the call graph
edges reference the target via the CalleeGUID instead of the
CalleeValueId.
The reference graph edges are recorded in each summary record with a
list of referenced value IDs, which can be mapped to value GUID via the
ValueSymbolTable.
Addtionally, a new summary record type is added to record references
from global variable initializers. A number of bitcode records and data
structures have been renamed to reflect the newly expanded scope of the
summary beyond functions. More cleanup will follow.
Reviewers: joker.eph, davidxl
Subscribers: joker.eph, llvm-commits
Differential Revision: http://reviews.llvm.org/D17212
llvm-svn: 263275
2016-03-12 02:52:24 +08:00
|
|
|
case bitc::GLOBALVAL_SUMMARY_BLOCK_ID:
|
2017-06-09 07:01:49 +08:00
|
|
|
case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID:
|
2015-10-04 22:33:43 +08:00
|
|
|
switch (CodeID) {
|
2015-11-03 02:02:11 +08:00
|
|
|
default:
|
|
|
|
return nullptr;
|
[ThinLTO] Support for reference graph in per-module and combined summary.
Summary:
This patch adds support for including a full reference graph including
call graph edges and other GV references in the summary.
The reference graph edges can be used to make importing decisions
without materializing any source modules, can be used in the plugin
to make file staging decisions for distributed build systems, and is
expected to have other uses.
The call graph edges are recorded in each function summary in the
bitcode via a list of <CalleeValueIds, StaticCount> tuples when no PGO
data exists, or <CalleeValueId, StaticCount, ProfileCount> pairs when
there is PGO, where the ValueId can be mapped to the function GUID via
the ValueSymbolTable. In the function index in memory, the call graph
edges reference the target via the CalleeGUID instead of the
CalleeValueId.
The reference graph edges are recorded in each summary record with a
list of referenced value IDs, which can be mapped to value GUID via the
ValueSymbolTable.
Addtionally, a new summary record type is added to record references
from global variable initializers. A number of bitcode records and data
structures have been renamed to reflect the newly expanded scope of the
summary beyond functions. More cleanup will follow.
Reviewers: joker.eph, davidxl
Subscribers: joker.eph, llvm-commits
Differential Revision: http://reviews.llvm.org/D17212
llvm-svn: 263275
2016-03-12 02:52:24 +08:00
|
|
|
STRINGIFY_CODE(FS, PERMODULE)
|
|
|
|
STRINGIFY_CODE(FS, PERMODULE_PROFILE)
|
2018-01-26 03:27:17 +08:00
|
|
|
STRINGIFY_CODE(FS, PERMODULE_RELBF)
|
[ThinLTO] Support for reference graph in per-module and combined summary.
Summary:
This patch adds support for including a full reference graph including
call graph edges and other GV references in the summary.
The reference graph edges can be used to make importing decisions
without materializing any source modules, can be used in the plugin
to make file staging decisions for distributed build systems, and is
expected to have other uses.
The call graph edges are recorded in each function summary in the
bitcode via a list of <CalleeValueIds, StaticCount> tuples when no PGO
data exists, or <CalleeValueId, StaticCount, ProfileCount> pairs when
there is PGO, where the ValueId can be mapped to the function GUID via
the ValueSymbolTable. In the function index in memory, the call graph
edges reference the target via the CalleeGUID instead of the
CalleeValueId.
The reference graph edges are recorded in each summary record with a
list of referenced value IDs, which can be mapped to value GUID via the
ValueSymbolTable.
Addtionally, a new summary record type is added to record references
from global variable initializers. A number of bitcode records and data
structures have been renamed to reflect the newly expanded scope of the
summary beyond functions. More cleanup will follow.
Reviewers: joker.eph, davidxl
Subscribers: joker.eph, llvm-commits
Differential Revision: http://reviews.llvm.org/D17212
llvm-svn: 263275
2016-03-12 02:52:24 +08:00
|
|
|
STRINGIFY_CODE(FS, PERMODULE_GLOBALVAR_INIT_REFS)
|
|
|
|
STRINGIFY_CODE(FS, COMBINED)
|
|
|
|
STRINGIFY_CODE(FS, COMBINED_PROFILE)
|
|
|
|
STRINGIFY_CODE(FS, COMBINED_GLOBALVAR_INIT_REFS)
|
2016-04-16 14:56:44 +08:00
|
|
|
STRINGIFY_CODE(FS, ALIAS)
|
|
|
|
STRINGIFY_CODE(FS, COMBINED_ALIAS)
|
2016-04-24 07:38:17 +08:00
|
|
|
STRINGIFY_CODE(FS, COMBINED_ORIGINAL_NAME)
|
2016-04-24 11:18:11 +08:00
|
|
|
STRINGIFY_CODE(FS, VERSION)
|
2018-02-07 12:05:59 +08:00
|
|
|
STRINGIFY_CODE(FS, FLAGS)
|
2016-12-22 07:03:45 +08:00
|
|
|
STRINGIFY_CODE(FS, TYPE_TESTS)
|
2017-02-11 06:29:38 +08:00
|
|
|
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)
|
2017-04-18 01:51:36 +08:00
|
|
|
STRINGIFY_CODE(FS, VALUE_GUID)
|
2017-06-16 08:18:29 +08:00
|
|
|
STRINGIFY_CODE(FS, CFI_FUNCTION_DEFS)
|
|
|
|
STRINGIFY_CODE(FS, CFI_FUNCTION_DECLS)
|
2018-02-15 06:41:15 +08:00
|
|
|
STRINGIFY_CODE(FS, TYPE_ID)
|
2007-04-30 05:48:19 +08:00
|
|
|
}
|
2009-09-19 03:26:43 +08:00
|
|
|
case bitc::METADATA_ATTACHMENT_ID:
|
|
|
|
switch(CodeID) {
|
2014-04-25 12:24:47 +08:00
|
|
|
default:return nullptr;
|
2015-06-30 06:50:35 +08:00
|
|
|
STRINGIFY_CODE(METADATA, ATTACHMENT)
|
2009-09-19 03:26:43 +08:00
|
|
|
}
|
2009-07-23 01:43:22 +08:00
|
|
|
case bitc::METADATA_BLOCK_ID:
|
|
|
|
switch(CodeID) {
|
2014-04-25 12:24:47 +08:00
|
|
|
default:return nullptr;
|
Reapply ~"Bitcode: Collect all MDString records into a single blob"
Spiritually reapply commit r264409 (reverted in r264410), albeit with a
bit of a redesign.
Firstly, avoid splitting the big blob into multiple chunks of strings.
r264409 imposed an arbitrary limit to avoid a massive allocation on the
shared 'Record' SmallVector. The bug with that commit only reproduced
when there were more than "chunk-size" strings. A test for this would
have been useless long-term, since we're liable to adjust the chunk-size
in the future.
Thus, eliminate the motivation for chunk-ing by storing the string sizes
in the blob. Here's the layout:
vbr6: # of strings
vbr6: offset-to-blob
blob:
[vbr6]: string lengths
[char]: concatenated strings
Secondly, make the output of llvm-bcanalyzer readable.
I noticed when debugging r264409 that llvm-bcanalyzer was outputting a
massive blob all in one line. Past a small number, the strings were
impossible to split in my head, and the lines were way too long. This
version adds support in llvm-bcanalyzer for pretty-printing.
<STRINGS abbrevid=4 op0=3 op1=9/> num-strings = 3 {
'abc'
'def'
'ghi'
}
From the original commit:
Inspired by Mehdi's similar patch, http://reviews.llvm.org/D18342, this
should (a) slightly reduce bitcode size, since there is less record
overhead, and (b) greatly improve reading speed, since blobs are super
cheap to deserialize.
llvm-svn: 264551
2016-03-28 07:17:54 +08:00
|
|
|
STRINGIFY_CODE(METADATA, STRING_OLD)
|
2017-01-04 03:17:49 +08:00
|
|
|
STRINGIFY_CODE(METADATA, VALUE)
|
|
|
|
STRINGIFY_CODE(METADATA, NODE)
|
2015-06-30 06:50:35 +08:00
|
|
|
STRINGIFY_CODE(METADATA, NAME)
|
2017-01-04 03:17:49 +08:00
|
|
|
STRINGIFY_CODE(METADATA, DISTINCT_NODE)
|
2015-11-15 10:00:09 +08:00
|
|
|
STRINGIFY_CODE(METADATA, KIND) // Older bitcode has it in a MODULE_BLOCK
|
2017-01-04 03:17:49 +08:00
|
|
|
STRINGIFY_CODE(METADATA, LOCATION)
|
2015-06-30 06:50:35 +08:00
|
|
|
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)
|
2015-06-30 08:25:41 +08:00
|
|
|
STRINGIFY_CODE(METADATA, MODULE)
|
2017-01-04 03:17:49 +08:00
|
|
|
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)
|
2016-12-29 06:30:28 +08:00
|
|
|
STRINGIFY_CODE(METADATA, INDEX_OFFSET)
|
|
|
|
STRINGIFY_CODE(METADATA, INDEX)
|
2009-07-23 01:43:22 +08:00
|
|
|
}
|
2015-11-15 10:00:09 +08:00
|
|
|
case bitc::METADATA_KIND_BLOCK_ID:
|
|
|
|
switch (CodeID) {
|
|
|
|
default:
|
|
|
|
return nullptr;
|
|
|
|
STRINGIFY_CODE(METADATA, KIND)
|
|
|
|
}
|
2011-12-08 05:45:13 +08:00
|
|
|
case bitc::USELIST_BLOCK_ID:
|
|
|
|
switch(CodeID) {
|
2014-04-25 12:24:47 +08:00
|
|
|
default:return nullptr;
|
2014-07-29 05:19:41 +08:00
|
|
|
case bitc::USELIST_CODE_DEFAULT: return "USELIST_CODE_DEFAULT";
|
|
|
|
case bitc::USELIST_CODE_BB: return "USELIST_CODE_BB";
|
2011-12-08 05:45:13 +08:00
|
|
|
}
|
2016-04-26 13:59:08 +08:00
|
|
|
|
|
|
|
case bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID:
|
|
|
|
switch(CodeID) {
|
|
|
|
default: return nullptr;
|
|
|
|
case bitc::OPERAND_BUNDLE_TAG: return "OPERAND_BUNDLE_TAG";
|
|
|
|
}
|
2017-04-18 01:51:36 +08:00
|
|
|
case bitc::STRTAB_BLOCK_ID:
|
|
|
|
switch(CodeID) {
|
|
|
|
default: return nullptr;
|
|
|
|
case bitc::STRTAB_BLOB: return "BLOB";
|
|
|
|
}
|
2017-06-28 07:50:11 +08:00
|
|
|
case bitc::SYMTAB_BLOCK_ID:
|
|
|
|
switch(CodeID) {
|
|
|
|
default: return nullptr;
|
|
|
|
case bitc::SYMTAB_BLOB: return "BLOB";
|
|
|
|
}
|
2007-04-30 05:48:19 +08:00
|
|
|
}
|
2015-06-30 06:50:32 +08:00
|
|
|
#undef STRINGIFY_CODE
|
2007-04-30 05:48:19 +08:00
|
|
|
}
|
|
|
|
|
2009-04-28 01:59:34 +08:00
|
|
|
struct PerRecordStats {
|
|
|
|
unsigned NumInstances;
|
2009-04-28 02:15:27 +08:00
|
|
|
unsigned NumAbbrev;
|
|
|
|
uint64_t TotalBits;
|
2015-10-21 14:10:55 +08:00
|
|
|
|
|
|
|
PerRecordStats() : NumInstances(0), NumAbbrev(0), TotalBits(0) {}
|
2009-04-28 01:59:34 +08:00
|
|
|
};
|
2007-04-30 04:00:02 +08:00
|
|
|
|
|
|
|
struct PerBlockIDStats {
|
|
|
|
/// NumInstances - This the number of times this block ID has been seen.
|
|
|
|
unsigned NumInstances;
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2007-04-30 04:00:02 +08:00
|
|
|
/// NumBits - The total size in bits of all of these blocks.
|
|
|
|
uint64_t NumBits;
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2007-04-30 04:00:02 +08:00
|
|
|
/// NumSubBlocks - The total number of blocks these blocks contain.
|
|
|
|
unsigned NumSubBlocks;
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2007-04-30 04:00:02 +08:00
|
|
|
/// NumAbbrevs - The total number of abbreviations.
|
|
|
|
unsigned NumAbbrevs;
|
2009-09-26 00:03:57 +08:00
|
|
|
|
|
|
|
/// NumRecords - The total number of records these blocks contain, and the
|
2007-04-30 04:00:02 +08:00
|
|
|
/// number that are abbreviated.
|
|
|
|
unsigned NumRecords, NumAbbreviatedRecords;
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2007-05-05 09:46:49 +08:00
|
|
|
/// CodeFreq - Keep track of the number of times we see each code.
|
2009-04-28 01:59:34 +08:00
|
|
|
std::vector<PerRecordStats> CodeFreq;
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2007-04-30 04:00:02 +08:00
|
|
|
PerBlockIDStats()
|
|
|
|
: NumInstances(0), NumBits(0),
|
|
|
|
NumSubBlocks(0), NumAbbrevs(0), NumRecords(0), NumAbbreviatedRecords(0) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
static std::map<unsigned, PerBlockIDStats> BlockIDStats;
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-10-04 02:17:18 +08:00
|
|
|
/// ReportError - All bitcode analysis errors go through this function, making this a
|
2007-04-29 16:31:14 +08:00
|
|
|
/// good place to breakpoint if debugging.
|
2016-10-04 02:17:18 +08:00
|
|
|
static bool ReportError(const Twine &Err) {
|
2018-04-22 05:11:59 +08:00
|
|
|
WithColor::error() << Err << "\n";
|
2007-04-29 16:31:14 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-11-08 12:17:11 +08:00
|
|
|
static bool decodeMetadataStringsBlob(StringRef Indent,
|
Reapply ~"Bitcode: Collect all MDString records into a single blob"
Spiritually reapply commit r264409 (reverted in r264410), albeit with a
bit of a redesign.
Firstly, avoid splitting the big blob into multiple chunks of strings.
r264409 imposed an arbitrary limit to avoid a massive allocation on the
shared 'Record' SmallVector. The bug with that commit only reproduced
when there were more than "chunk-size" strings. A test for this would
have been useless long-term, since we're liable to adjust the chunk-size
in the future.
Thus, eliminate the motivation for chunk-ing by storing the string sizes
in the blob. Here's the layout:
vbr6: # of strings
vbr6: offset-to-blob
blob:
[vbr6]: string lengths
[char]: concatenated strings
Secondly, make the output of llvm-bcanalyzer readable.
I noticed when debugging r264409 that llvm-bcanalyzer was outputting a
massive blob all in one line. Past a small number, the strings were
impossible to split in my head, and the lines were way too long. This
version adds support in llvm-bcanalyzer for pretty-printing.
<STRINGS abbrevid=4 op0=3 op1=9/> num-strings = 3 {
'abc'
'def'
'ghi'
}
From the original commit:
Inspired by Mehdi's similar patch, http://reviews.llvm.org/D18342, this
should (a) slightly reduce bitcode size, since there is less record
overhead, and (b) greatly improve reading speed, since blobs are super
cheap to deserialize.
llvm-svn: 264551
2016-03-28 07:17:54 +08:00
|
|
|
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);
|
2016-11-08 12:17:11 +08:00
|
|
|
SimpleBitstreamCursor R(Lengths);
|
Reapply ~"Bitcode: Collect all MDString records into a single blob"
Spiritually reapply commit r264409 (reverted in r264410), albeit with a
bit of a redesign.
Firstly, avoid splitting the big blob into multiple chunks of strings.
r264409 imposed an arbitrary limit to avoid a massive allocation on the
shared 'Record' SmallVector. The bug with that commit only reproduced
when there were more than "chunk-size" strings. A test for this would
have been useless long-term, since we're liable to adjust the chunk-size
in the future.
Thus, eliminate the motivation for chunk-ing by storing the string sizes
in the blob. Here's the layout:
vbr6: # of strings
vbr6: offset-to-blob
blob:
[vbr6]: string lengths
[char]: concatenated strings
Secondly, make the output of llvm-bcanalyzer readable.
I noticed when debugging r264409 that llvm-bcanalyzer was outputting a
massive blob all in one line. Past a small number, the strings were
impossible to split in my head, and the lines were way too long. This
version adds support in llvm-bcanalyzer for pretty-printing.
<STRINGS abbrevid=4 op0=3 op1=9/> num-strings = 3 {
'abc'
'def'
'ghi'
}
From the original commit:
Inspired by Mehdi's similar patch, http://reviews.llvm.org/D18342, this
should (a) slightly reduce bitcode size, since there is less record
overhead, and (b) greatly improve reading speed, since blobs are super
cheap to deserialize.
llvm-svn: 264551
2016-03-28 07:17:54 +08:00
|
|
|
StringRef Strings = Blob.drop_front(StringsOffset);
|
|
|
|
do {
|
|
|
|
if (R.AtEndOfStream())
|
2016-10-04 02:17:18 +08:00
|
|
|
return ReportError("bad length");
|
Reapply ~"Bitcode: Collect all MDString records into a single blob"
Spiritually reapply commit r264409 (reverted in r264410), albeit with a
bit of a redesign.
Firstly, avoid splitting the big blob into multiple chunks of strings.
r264409 imposed an arbitrary limit to avoid a massive allocation on the
shared 'Record' SmallVector. The bug with that commit only reproduced
when there were more than "chunk-size" strings. A test for this would
have been useless long-term, since we're liable to adjust the chunk-size
in the future.
Thus, eliminate the motivation for chunk-ing by storing the string sizes
in the blob. Here's the layout:
vbr6: # of strings
vbr6: offset-to-blob
blob:
[vbr6]: string lengths
[char]: concatenated strings
Secondly, make the output of llvm-bcanalyzer readable.
I noticed when debugging r264409 that llvm-bcanalyzer was outputting a
massive blob all in one line. Past a small number, the strings were
impossible to split in my head, and the lines were way too long. This
version adds support in llvm-bcanalyzer for pretty-printing.
<STRINGS abbrevid=4 op0=3 op1=9/> num-strings = 3 {
'abc'
'def'
'ghi'
}
From the original commit:
Inspired by Mehdi's similar patch, http://reviews.llvm.org/D18342, this
should (a) slightly reduce bitcode size, since there is less record
overhead, and (b) greatly improve reading speed, since blobs are super
cheap to deserialize.
llvm-svn: 264551
2016-03-28 07:17:54 +08:00
|
|
|
|
|
|
|
unsigned Size = R.ReadVBR(6);
|
|
|
|
if (Strings.size() < Size)
|
2016-10-04 02:17:18 +08:00
|
|
|
return ReportError("truncated chars");
|
Reapply ~"Bitcode: Collect all MDString records into a single blob"
Spiritually reapply commit r264409 (reverted in r264410), albeit with a
bit of a redesign.
Firstly, avoid splitting the big blob into multiple chunks of strings.
r264409 imposed an arbitrary limit to avoid a massive allocation on the
shared 'Record' SmallVector. The bug with that commit only reproduced
when there were more than "chunk-size" strings. A test for this would
have been useless long-term, since we're liable to adjust the chunk-size
in the future.
Thus, eliminate the motivation for chunk-ing by storing the string sizes
in the blob. Here's the layout:
vbr6: # of strings
vbr6: offset-to-blob
blob:
[vbr6]: string lengths
[char]: concatenated strings
Secondly, make the output of llvm-bcanalyzer readable.
I noticed when debugging r264409 that llvm-bcanalyzer was outputting a
massive blob all in one line. Past a small number, the strings were
impossible to split in my head, and the lines were way too long. This
version adds support in llvm-bcanalyzer for pretty-printing.
<STRINGS abbrevid=4 op0=3 op1=9/> num-strings = 3 {
'abc'
'def'
'ghi'
}
From the original commit:
Inspired by Mehdi's similar patch, http://reviews.llvm.org/D18342, this
should (a) slightly reduce bitcode size, since there is less record
overhead, and (b) greatly improve reading speed, since blobs are super
cheap to deserialize.
llvm-svn: 264551
2016-03-28 07:17:54 +08:00
|
|
|
|
|
|
|
outs() << Indent << " '";
|
|
|
|
outs().write_escaped(Strings.slice(0, Size), /*hex=*/true);
|
|
|
|
outs() << "'\n";
|
|
|
|
Strings = Strings.drop_front(Size);
|
|
|
|
} while (--NumStrings);
|
|
|
|
|
|
|
|
outs() << Indent << " }";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-11-08 12:17:11 +08:00
|
|
|
static bool decodeBlob(unsigned Code, unsigned BlockID, StringRef Indent,
|
|
|
|
ArrayRef<uint64_t> Record, StringRef Blob) {
|
Reapply ~"Bitcode: Collect all MDString records into a single blob"
Spiritually reapply commit r264409 (reverted in r264410), albeit with a
bit of a redesign.
Firstly, avoid splitting the big blob into multiple chunks of strings.
r264409 imposed an arbitrary limit to avoid a massive allocation on the
shared 'Record' SmallVector. The bug with that commit only reproduced
when there were more than "chunk-size" strings. A test for this would
have been useless long-term, since we're liable to adjust the chunk-size
in the future.
Thus, eliminate the motivation for chunk-ing by storing the string sizes
in the blob. Here's the layout:
vbr6: # of strings
vbr6: offset-to-blob
blob:
[vbr6]: string lengths
[char]: concatenated strings
Secondly, make the output of llvm-bcanalyzer readable.
I noticed when debugging r264409 that llvm-bcanalyzer was outputting a
massive blob all in one line. Past a small number, the strings were
impossible to split in my head, and the lines were way too long. This
version adds support in llvm-bcanalyzer for pretty-printing.
<STRINGS abbrevid=4 op0=3 op1=9/> num-strings = 3 {
'abc'
'def'
'ghi'
}
From the original commit:
Inspired by Mehdi's similar patch, http://reviews.llvm.org/D18342, this
should (a) slightly reduce bitcode size, since there is less record
overhead, and (b) greatly improve reading speed, since blobs are super
cheap to deserialize.
llvm-svn: 264551
2016-03-28 07:17:54 +08:00
|
|
|
if (BlockID != bitc::METADATA_BLOCK_ID)
|
|
|
|
return true;
|
|
|
|
if (Code != bitc::METADATA_STRINGS)
|
|
|
|
return true;
|
|
|
|
|
2016-11-08 12:17:11 +08:00
|
|
|
return decodeMetadataStringsBlob(Indent, Record, Blob);
|
Reapply ~"Bitcode: Collect all MDString records into a single blob"
Spiritually reapply commit r264409 (reverted in r264410), albeit with a
bit of a redesign.
Firstly, avoid splitting the big blob into multiple chunks of strings.
r264409 imposed an arbitrary limit to avoid a massive allocation on the
shared 'Record' SmallVector. The bug with that commit only reproduced
when there were more than "chunk-size" strings. A test for this would
have been useless long-term, since we're liable to adjust the chunk-size
in the future.
Thus, eliminate the motivation for chunk-ing by storing the string sizes
in the blob. Here's the layout:
vbr6: # of strings
vbr6: offset-to-blob
blob:
[vbr6]: string lengths
[char]: concatenated strings
Secondly, make the output of llvm-bcanalyzer readable.
I noticed when debugging r264409 that llvm-bcanalyzer was outputting a
massive blob all in one line. Past a small number, the strings were
impossible to split in my head, and the lines were way too long. This
version adds support in llvm-bcanalyzer for pretty-printing.
<STRINGS abbrevid=4 op0=3 op1=9/> num-strings = 3 {
'abc'
'def'
'ghi'
}
From the original commit:
Inspired by Mehdi's similar patch, http://reviews.llvm.org/D18342, this
should (a) slightly reduce bitcode size, since there is less record
overhead, and (b) greatly improve reading speed, since blobs are super
cheap to deserialize.
llvm-svn: 264551
2016-03-28 07:17:54 +08:00
|
|
|
}
|
|
|
|
|
2007-04-29 16:31:14 +08:00
|
|
|
/// ParseBlock - Read a block, updating statistics, etc.
|
2016-11-08 12:17:11 +08:00
|
|
|
static bool ParseBlock(BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo,
|
|
|
|
unsigned BlockID, unsigned IndentLevel,
|
|
|
|
CurStreamTypeType CurStreamType) {
|
2007-05-05 08:17:42 +08:00
|
|
|
std::string Indent(IndentLevel*2, ' ');
|
2007-04-30 04:00:02 +08:00
|
|
|
uint64_t BlockBitStart = Stream.GetCurrentBitNo();
|
2007-04-30 05:48:19 +08:00
|
|
|
|
2007-04-30 04:00:02 +08:00
|
|
|
// Get the statistics for this BlockID.
|
|
|
|
PerBlockIDStats &BlockStats = BlockIDStats[BlockID];
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2007-04-30 04:00:02 +08:00
|
|
|
BlockStats.NumInstances++;
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2007-05-05 08:17:42 +08:00
|
|
|
// BLOCKINFO is a special part of the stream.
|
2016-02-06 08:46:09 +08:00
|
|
|
bool DumpRecords = Dump;
|
2007-05-05 08:17:42 +08:00
|
|
|
if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
|
2012-03-20 07:40:48 +08:00
|
|
|
if (Dump) outs() << Indent << "<BLOCKINFO_BLOCK/>\n";
|
2016-11-08 12:17:11 +08:00
|
|
|
Optional<BitstreamBlockInfo> NewBlockInfo =
|
|
|
|
Stream.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true);
|
|
|
|
if (!NewBlockInfo)
|
2016-10-04 02:17:18 +08:00
|
|
|
return ReportError("Malformed BlockInfoBlock");
|
2016-11-08 12:17:11 +08:00
|
|
|
BlockInfo = std::move(*NewBlockInfo);
|
|
|
|
Stream.JumpToBit(BlockBitStart);
|
2016-02-06 08:46:09 +08:00
|
|
|
// It's not really interesting to dump the contents of the blockinfo block.
|
|
|
|
DumpRecords = false;
|
2007-05-05 08:17:42 +08:00
|
|
|
}
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2007-04-30 05:48:19 +08:00
|
|
|
unsigned NumWords = 0;
|
2007-05-05 08:17:42 +08:00
|
|
|
if (Stream.EnterSubBlock(BlockID, &NumWords))
|
2016-10-04 02:17:18 +08:00
|
|
|
return ReportError("Malformed block record");
|
2007-04-29 16:31:14 +08:00
|
|
|
|
2016-04-01 13:33:11 +08:00
|
|
|
// Keep it for later, when we see a MODULE_HASH record
|
|
|
|
uint64_t BlockEntryPos = Stream.getCurrentByteNo();
|
|
|
|
|
2014-04-25 12:24:47 +08:00
|
|
|
const char *BlockName = nullptr;
|
2016-02-06 08:46:09 +08:00
|
|
|
if (DumpRecords) {
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << Indent << "<";
|
2016-11-08 12:17:11 +08:00
|
|
|
if ((BlockName = GetBlockName(BlockID, BlockInfo, CurStreamType)))
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << BlockName;
|
2007-04-30 05:48:19 +08:00
|
|
|
else
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << "UnknownBlock" << BlockID;
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2007-04-30 05:48:19 +08:00
|
|
|
if (NonSymbolic && BlockName)
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << " BlockID=" << BlockID;
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << " NumWords=" << NumWords
|
2013-01-20 05:37:14 +08:00
|
|
|
<< " BlockCodeSize=" << Stream.getAbbrevIDWidth() << ">\n";
|
2007-04-30 05:48:19 +08:00
|
|
|
}
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2007-04-29 16:31:14 +08:00
|
|
|
SmallVector<uint64_t, 64> Record;
|
|
|
|
|
2016-12-29 06:30:28 +08:00
|
|
|
// Keep the offset to the metadata index if seen.
|
|
|
|
uint64_t MetadataIndexOffset = 0;
|
|
|
|
|
2007-04-29 16:31:14 +08:00
|
|
|
// Read all the records for this block.
|
|
|
|
while (1) {
|
|
|
|
if (Stream.AtEndOfStream())
|
2016-10-04 02:17:18 +08:00
|
|
|
return ReportError("Premature end of bitstream");
|
2007-04-29 16:31:14 +08:00
|
|
|
|
2009-04-28 02:15:27 +08:00
|
|
|
uint64_t RecordStartBit = Stream.GetCurrentBitNo();
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2013-01-20 10:50:32 +08:00
|
|
|
BitstreamEntry Entry =
|
|
|
|
Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
|
|
|
|
|
|
|
|
switch (Entry.Kind) {
|
|
|
|
case BitstreamEntry::Error:
|
2016-10-04 02:17:18 +08:00
|
|
|
return ReportError("malformed bitcode file");
|
2013-01-20 10:50:32 +08:00
|
|
|
case BitstreamEntry::EndBlock: {
|
2007-04-30 04:00:02 +08:00
|
|
|
uint64_t BlockBitEnd = Stream.GetCurrentBitNo();
|
|
|
|
BlockStats.NumBits += BlockBitEnd-BlockBitStart;
|
2016-02-06 08:46:09 +08:00
|
|
|
if (DumpRecords) {
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << Indent << "</";
|
2007-04-30 05:48:19 +08:00
|
|
|
if (BlockName)
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << BlockName << ">\n";
|
2007-04-30 05:48:19 +08:00
|
|
|
else
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << "UnknownBlock" << BlockID << ">\n";
|
2007-04-30 05:48:19 +08:00
|
|
|
}
|
2007-04-29 16:31:14 +08:00
|
|
|
return false;
|
2009-09-26 00:03:57 +08:00
|
|
|
}
|
2013-01-20 10:50:32 +08:00
|
|
|
|
|
|
|
case BitstreamEntry::SubBlock: {
|
2007-05-05 09:29:31 +08:00
|
|
|
uint64_t SubBlockBitStart = Stream.GetCurrentBitNo();
|
2016-11-08 12:17:11 +08:00
|
|
|
if (ParseBlock(Stream, BlockInfo, Entry.ID, IndentLevel + 1,
|
|
|
|
CurStreamType))
|
2007-04-29 16:31:14 +08:00
|
|
|
return true;
|
2007-04-30 04:00:02 +08:00
|
|
|
++BlockStats.NumSubBlocks;
|
2007-05-05 09:29:31 +08:00
|
|
|
uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo();
|
2013-01-20 10:50:32 +08:00
|
|
|
|
2007-05-05 09:29:31 +08:00
|
|
|
// Don't include subblock sizes in the size of this block.
|
|
|
|
BlockBitStart += SubBlockBitEnd-SubBlockBitStart;
|
2013-01-20 10:50:32 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
case BitstreamEntry::Record:
|
|
|
|
// The interesting case.
|
2007-04-29 16:31:14 +08:00
|
|
|
break;
|
2007-05-05 09:29:31 +08:00
|
|
|
}
|
2013-01-20 10:50:32 +08:00
|
|
|
|
|
|
|
if (Entry.ID == bitc::DEFINE_ABBREV) {
|
2007-04-29 16:31:14 +08:00
|
|
|
Stream.ReadAbbrevRecord();
|
2007-04-30 04:00:02 +08:00
|
|
|
++BlockStats.NumAbbrevs;
|
2013-01-20 10:50:32 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
Record.clear();
|
|
|
|
|
|
|
|
++BlockStats.NumRecords;
|
|
|
|
|
|
|
|
StringRef Blob;
|
2018-06-05 03:20:02 +08:00
|
|
|
uint64_t CurrentRecordPos = Stream.GetCurrentBitNo();
|
2013-01-20 10:50:32 +08:00
|
|
|
unsigned Code = Stream.readRecord(Entry.ID, Record, &Blob);
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2016-02-06 08:46:09 +08:00
|
|
|
if (DumpRecords) {
|
2013-01-20 10:50:32 +08:00
|
|
|
outs() << Indent << " <";
|
|
|
|
if (const char *CodeName =
|
2016-11-08 12:17:11 +08:00
|
|
|
GetCodeName(Code, BlockID, BlockInfo, CurStreamType))
|
2013-01-20 10:50:32 +08:00
|
|
|
outs() << CodeName;
|
|
|
|
else
|
|
|
|
outs() << "UnknownCode" << Code;
|
2016-11-08 12:17:11 +08:00
|
|
|
if (NonSymbolic && GetCodeName(Code, BlockID, BlockInfo, CurStreamType))
|
2013-01-20 10:50:32 +08:00
|
|
|
outs() << " codeid=" << Code;
|
2015-10-08 23:56:24 +08:00
|
|
|
const BitCodeAbbrev *Abbv = nullptr;
|
|
|
|
if (Entry.ID != bitc::UNABBREV_RECORD) {
|
|
|
|
Abbv = Stream.getAbbrev(Entry.ID);
|
2013-01-20 10:50:32 +08:00
|
|
|
outs() << " abbrevid=" << Entry.ID;
|
2015-10-08 23:56:24 +08:00
|
|
|
}
|
2013-01-20 10:50:32 +08:00
|
|
|
|
|
|
|
for (unsigned i = 0, e = Record.size(); i != e; ++i)
|
|
|
|
outs() << " op" << i << "=" << (int64_t)Record[i];
|
|
|
|
|
2016-12-29 06:30:28 +08:00
|
|
|
// 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) {
|
2016-12-29 07:45:54 +08:00
|
|
|
if (Record.size() != 2)
|
|
|
|
outs() << "(Invalid record)";
|
|
|
|
else {
|
|
|
|
auto Offset = Record[0] + (Record[1] << 32);
|
|
|
|
MetadataIndexOffset = Stream.GetCurrentBitNo() + Offset;
|
|
|
|
}
|
2016-12-29 06:30:28 +08:00
|
|
|
}
|
|
|
|
if (Code == bitc::METADATA_INDEX) {
|
|
|
|
outs() << " (offset ";
|
|
|
|
if (MetadataIndexOffset == RecordStartBit)
|
|
|
|
outs() << "match)";
|
|
|
|
else
|
|
|
|
outs() << "mismatch: " << MetadataIndexOffset << " vs "
|
|
|
|
<< RecordStartBit << ")";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-01 13:33:11 +08:00
|
|
|
// If we found a module hash, let's verify that it matches!
|
2017-07-07 01:56:01 +08:00
|
|
|
if (BlockID == bitc::MODULE_BLOCK_ID && Code == bitc::MODULE_CODE_HASH &&
|
|
|
|
!CheckHash.empty()) {
|
2016-04-01 13:33:11 +08:00
|
|
|
if (Record.size() != 5)
|
|
|
|
outs() << " (invalid)";
|
|
|
|
else {
|
|
|
|
// Recompute the hash and compare it to the one in the bitcode
|
|
|
|
SHA1 Hasher;
|
|
|
|
StringRef Hash;
|
2017-07-07 01:56:01 +08:00
|
|
|
Hasher.update(CheckHash);
|
2016-04-01 13:33:11 +08:00
|
|
|
{
|
2016-12-01 13:47:58 +08:00
|
|
|
int BlockSize = (CurrentRecordPos / 8) - BlockEntryPos;
|
2016-04-01 13:33:11 +08:00
|
|
|
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!)";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-20 10:50:32 +08:00
|
|
|
outs() << "/>";
|
|
|
|
|
2015-10-08 23:56:24 +08:00
|
|
|
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) {
|
2018-07-26 23:31:41 +08:00
|
|
|
if (!isPrint(static_cast<unsigned char>(Record[j]))) {
|
2015-10-08 23:56:24 +08:00
|
|
|
ArrayIsPrintable = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Str += (char)Record[j];
|
|
|
|
}
|
2015-11-03 02:02:11 +08:00
|
|
|
if (ArrayIsPrintable)
|
|
|
|
outs() << " record string = '" << Str << "'";
|
2015-10-08 23:56:24 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-08 12:17:11 +08:00
|
|
|
if (Blob.data() && decodeBlob(Code, BlockID, Indent, Record, Blob)) {
|
2013-01-20 10:50:32 +08:00
|
|
|
outs() << " blob data = ";
|
2015-05-14 02:51:49 +08:00
|
|
|
if (ShowBinaryBlobs) {
|
|
|
|
outs() << "'";
|
|
|
|
outs().write_escaped(Blob, /*hex=*/true) << "'";
|
|
|
|
} else {
|
|
|
|
bool BlobIsPrintable = true;
|
|
|
|
for (unsigned i = 0, e = Blob.size(); i != e; ++i)
|
2018-07-26 23:31:41 +08:00
|
|
|
if (!isPrint(static_cast<unsigned char>(Blob[i]))) {
|
2015-05-14 02:51:49 +08:00
|
|
|
BlobIsPrintable = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (BlobIsPrintable)
|
|
|
|
outs() << "'" << Blob << "'";
|
|
|
|
else
|
|
|
|
outs() << "unprintable, " << Blob.size() << " bytes.";
|
|
|
|
}
|
2007-04-30 05:48:19 +08:00
|
|
|
}
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2013-01-20 10:50:32 +08:00
|
|
|
outs() << "\n";
|
2007-04-29 16:31:14 +08:00
|
|
|
}
|
2016-12-01 13:47:58 +08:00
|
|
|
|
|
|
|
// Make sure that we can skip the current record.
|
|
|
|
Stream.JumpToBit(CurrentRecordPos);
|
|
|
|
Stream.skipRecord(Entry.ID);
|
2007-04-29 16:31:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-30 04:00:02 +08:00
|
|
|
static void PrintSize(double Bits) {
|
2012-09-06 04:55:54 +08:00
|
|
|
outs() << format("%.2f/%.2fB/%luW", Bits, Bits/8,(unsigned long)(Bits/32));
|
2009-04-28 01:59:34 +08:00
|
|
|
}
|
|
|
|
static void PrintSize(uint64_t Bits) {
|
2012-09-06 04:55:54 +08:00
|
|
|
outs() << format("%lub/%.2fB/%luW", (unsigned long)Bits,
|
|
|
|
(double)Bits/8, (unsigned long)(Bits/32));
|
2007-04-30 04:00:02 +08:00
|
|
|
}
|
|
|
|
|
[bcanalyzer] Recognize more stream types
Summary:
`llvm-bcanalyzer` prints out the stream type of the file it is
analyzing. If the file begins with the LLVM IR magic number, it reports
a stream type of "LLVM IR". However, any other bitstream format is
reported as "unknown".
Add some checks for two other common bitstream formats: Clang AST
files, which begin with 'CPCH', and Clang serialized diagnostics, which
begin with 'DIAG'.
Test Plan: `check-llvm`
Reviewers: pcc, aprantl, mehdi_amini, davide, george.karpenkov, JDevlieghere
Reviewed By: JDevlieghere
Subscribers: JDevlieghere, bruno, davide, llvm-commits
Differential Revision: https://reviews.llvm.org/D41979
llvm-svn: 330529
2018-04-22 07:52:04 +08:00
|
|
|
static CurStreamTypeType ReadSignature(BitstreamCursor &Stream) {
|
|
|
|
char Signature[6];
|
|
|
|
Signature[0] = Stream.Read(8);
|
|
|
|
Signature[1] = Stream.Read(8);
|
|
|
|
|
|
|
|
// Autodetect the file contents, if it is one we know.
|
|
|
|
if (Signature[0] == 'C' && Signature[1] == 'P') {
|
|
|
|
Signature[2] = Stream.Read(8);
|
|
|
|
Signature[3] = Stream.Read(8);
|
|
|
|
if (Signature[2] == 'C' && Signature[3] == 'H')
|
|
|
|
return ClangSerializedASTBitstream;
|
|
|
|
} else if (Signature[0] == 'D' && Signature[1] == 'I') {
|
|
|
|
Signature[2] = Stream.Read(8);
|
|
|
|
Signature[3] = Stream.Read(8);
|
|
|
|
if (Signature[2] == 'A' && Signature[3] == 'G')
|
|
|
|
return ClangSerializedDiagnosticsBitstream;
|
|
|
|
} else {
|
|
|
|
Signature[2] = Stream.Read(4);
|
|
|
|
Signature[3] = Stream.Read(4);
|
|
|
|
Signature[4] = Stream.Read(4);
|
|
|
|
Signature[5] = Stream.Read(4);
|
|
|
|
if (Signature[0] == 'B' && Signature[1] == 'C' &&
|
|
|
|
Signature[2] == 0x0 && Signature[3] == 0xC &&
|
|
|
|
Signature[4] == 0xE && Signature[5] == 0xD)
|
|
|
|
return LLVMIRBitstream;
|
|
|
|
}
|
|
|
|
return UnknownBitstream;
|
|
|
|
}
|
|
|
|
|
2014-08-31 01:07:55 +08:00
|
|
|
static bool openBitcodeFile(StringRef Path,
|
|
|
|
std::unique_ptr<MemoryBuffer> &MemBuf,
|
|
|
|
BitstreamCursor &Stream,
|
|
|
|
CurStreamTypeType &CurStreamType) {
|
2007-04-29 16:12:22 +08:00
|
|
|
// Read the input file.
|
2014-07-07 01:43:13 +08:00
|
|
|
ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr =
|
2014-08-31 01:07:55 +08:00
|
|
|
MemoryBuffer::getFileOrSTDIN(Path);
|
2014-07-07 01:43:13 +08:00
|
|
|
if (std::error_code EC = MemBufOrErr.getError())
|
2016-10-04 02:17:18 +08:00
|
|
|
return ReportError(Twine("ReportError reading '") + Path + "': " + EC.message());
|
2014-08-31 01:07:55 +08:00
|
|
|
MemBuf = std::move(MemBufOrErr.get());
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2014-08-31 01:07:55 +08:00
|
|
|
if (MemBuf->getBufferSize() & 3)
|
2016-10-04 02:17:18 +08:00
|
|
|
return ReportError("Bitcode stream should be a multiple of 4 bytes in length");
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2014-08-31 01:07:55 +08:00
|
|
|
const unsigned char *BufPtr = (const unsigned char *)MemBuf->getBufferStart();
|
|
|
|
const unsigned char *EndBufPtr = BufPtr + MemBuf->getBufferSize();
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2009-04-07 04:54:32 +08:00
|
|
|
// If we have a wrapper header, parse it and ignore the non-bc file contents.
|
|
|
|
// The magic number is 0x0B17C0DE stored in little endian.
|
2016-01-29 13:55:09 +08:00
|
|
|
if (isBitcodeWrapper(BufPtr, EndBufPtr)) {
|
2016-04-01 13:19:14 +08:00
|
|
|
if (MemBuf->getBufferSize() < BWH_HeaderSize)
|
2016-10-04 02:17:18 +08:00
|
|
|
return ReportError("Invalid bitcode wrapper header");
|
2016-01-29 13:55:09 +08:00
|
|
|
|
|
|
|
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";
|
|
|
|
}
|
|
|
|
|
2012-02-07 06:30:29 +08:00
|
|
|
if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr, true))
|
2016-10-04 02:17:18 +08:00
|
|
|
return ReportError("Invalid bitcode wrapper header");
|
2016-01-29 13:55:09 +08:00
|
|
|
}
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2016-11-08 12:17:11 +08:00
|
|
|
Stream = BitstreamCursor(ArrayRef<uint8_t>(BufPtr, EndBufPtr));
|
[bcanalyzer] Recognize more stream types
Summary:
`llvm-bcanalyzer` prints out the stream type of the file it is
analyzing. If the file begins with the LLVM IR magic number, it reports
a stream type of "LLVM IR". However, any other bitstream format is
reported as "unknown".
Add some checks for two other common bitstream formats: Clang AST
files, which begin with 'CPCH', and Clang serialized diagnostics, which
begin with 'DIAG'.
Test Plan: `check-llvm`
Reviewers: pcc, aprantl, mehdi_amini, davide, george.karpenkov, JDevlieghere
Reviewed By: JDevlieghere
Subscribers: JDevlieghere, bruno, davide, llvm-commits
Differential Revision: https://reviews.llvm.org/D41979
llvm-svn: 330529
2018-04-22 07:52:04 +08:00
|
|
|
CurStreamType = ReadSignature(Stream);
|
2007-04-29 16:12:22 +08:00
|
|
|
|
2014-08-31 01:07:55 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// AnalyzeBitcode - Analyze the bitcode file specified by InputFilename.
|
|
|
|
static int AnalyzeBitcode() {
|
|
|
|
std::unique_ptr<MemoryBuffer> StreamBuffer;
|
|
|
|
BitstreamCursor Stream;
|
2016-11-08 12:17:11 +08:00
|
|
|
BitstreamBlockInfo BlockInfo;
|
2014-08-31 01:07:55 +08:00
|
|
|
CurStreamTypeType CurStreamType;
|
2016-11-08 12:17:11 +08:00
|
|
|
if (openBitcodeFile(InputFilename, StreamBuffer, Stream, CurStreamType))
|
2014-08-31 01:07:55 +08:00
|
|
|
return true;
|
2016-11-08 12:17:11 +08:00
|
|
|
Stream.setBlockInfo(&BlockInfo);
|
2014-08-31 01:07:55 +08:00
|
|
|
|
|
|
|
// 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;
|
2016-11-08 12:17:11 +08:00
|
|
|
if (openBitcodeFile(BlockInfoFilename, BlockInfoBuffer, BlockInfoCursor,
|
|
|
|
BlockInfoStreamType))
|
2014-08-31 01:07:55 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
while (!BlockInfoCursor.AtEndOfStream()) {
|
|
|
|
unsigned Code = BlockInfoCursor.ReadCode();
|
|
|
|
if (Code != bitc::ENTER_SUBBLOCK)
|
2016-10-04 02:17:18 +08:00
|
|
|
return ReportError("Invalid record at top-level in block info file");
|
2014-08-31 01:07:55 +08:00
|
|
|
|
|
|
|
unsigned BlockID = BlockInfoCursor.ReadSubBlockID();
|
|
|
|
if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
|
2016-11-08 12:17:11 +08:00
|
|
|
Optional<BitstreamBlockInfo> NewBlockInfo =
|
|
|
|
BlockInfoCursor.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true);
|
|
|
|
if (!NewBlockInfo)
|
2016-10-04 02:17:18 +08:00
|
|
|
return ReportError("Malformed BlockInfoBlock in block info file");
|
2016-11-08 12:17:11 +08:00
|
|
|
BlockInfo = std::move(*NewBlockInfo);
|
2014-08-31 01:07:55 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockInfoCursor.SkipBlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-30 04:00:02 +08:00
|
|
|
unsigned NumTopBlocks = 0;
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2007-04-29 16:31:14 +08:00
|
|
|
// Parse the top-level structure. We only allow blocks at the top-level.
|
|
|
|
while (!Stream.AtEndOfStream()) {
|
|
|
|
unsigned Code = Stream.ReadCode();
|
|
|
|
if (Code != bitc::ENTER_SUBBLOCK)
|
2016-10-04 02:17:18 +08:00
|
|
|
return ReportError("Invalid record at top-level");
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2013-01-20 10:50:32 +08:00
|
|
|
unsigned BlockID = Stream.ReadSubBlockID();
|
|
|
|
|
2016-11-08 12:17:11 +08:00
|
|
|
if (ParseBlock(Stream, BlockInfo, BlockID, 0, CurStreamType))
|
2007-04-29 16:31:14 +08:00
|
|
|
return true;
|
2007-04-30 04:00:02 +08:00
|
|
|
++NumTopBlocks;
|
2007-04-29 16:31:14 +08:00
|
|
|
}
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2012-03-20 07:40:48 +08:00
|
|
|
if (Dump) outs() << "\n\n";
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2016-11-08 12:17:11 +08:00
|
|
|
uint64_t BufferSizeBits = Stream.getBitcodeBytes().size() * CHAR_BIT;
|
2007-04-29 16:31:14 +08:00
|
|
|
// Print a summary of the read file.
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << "Summary of " << InputFilename << ":\n";
|
|
|
|
outs() << " Total size: ";
|
2007-05-01 10:43:46 +08:00
|
|
|
PrintSize(BufferSizeBits);
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << "\n";
|
|
|
|
outs() << " Stream type: ";
|
2007-04-29 16:12:22 +08:00
|
|
|
switch (CurStreamType) {
|
[bcanalyzer] Recognize more stream types
Summary:
`llvm-bcanalyzer` prints out the stream type of the file it is
analyzing. If the file begins with the LLVM IR magic number, it reports
a stream type of "LLVM IR". However, any other bitstream format is
reported as "unknown".
Add some checks for two other common bitstream formats: Clang AST
files, which begin with 'CPCH', and Clang serialized diagnostics, which
begin with 'DIAG'.
Test Plan: `check-llvm`
Reviewers: pcc, aprantl, mehdi_amini, davide, george.karpenkov, JDevlieghere
Reviewed By: JDevlieghere
Subscribers: JDevlieghere, bruno, davide, llvm-commits
Differential Revision: https://reviews.llvm.org/D41979
llvm-svn: 330529
2018-04-22 07:52:04 +08:00
|
|
|
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;
|
2007-04-29 16:12:22 +08:00
|
|
|
}
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << " # Toplevel Blocks: " << NumTopBlocks << "\n";
|
|
|
|
outs() << "\n";
|
2007-04-30 04:00:02 +08:00
|
|
|
|
|
|
|
// Emit per-block stats.
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << "Per-block Summary:\n";
|
2007-04-30 04:00:02 +08:00
|
|
|
for (std::map<unsigned, PerBlockIDStats>::iterator I = BlockIDStats.begin(),
|
|
|
|
E = BlockIDStats.end(); I != E; ++I) {
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << " Block ID #" << I->first;
|
2016-11-08 12:17:11 +08:00
|
|
|
if (const char *BlockName =
|
|
|
|
GetBlockName(I->first, BlockInfo, CurStreamType))
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << " (" << BlockName << ")";
|
|
|
|
outs() << ":\n";
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2007-04-30 04:00:02 +08:00
|
|
|
const PerBlockIDStats &Stats = I->second;
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << " Num Instances: " << Stats.NumInstances << "\n";
|
|
|
|
outs() << " Total Size: ";
|
2007-04-30 04:00:02 +08:00
|
|
|
PrintSize(Stats.NumBits);
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << "\n";
|
2009-09-26 00:04:21 +08:00
|
|
|
double pct = (Stats.NumBits * 100.0) / BufferSizeBits;
|
2012-09-06 04:55:54 +08:00
|
|
|
outs() << " Percent of file: " << format("%2.4f%%", pct) << "\n";
|
2007-05-05 09:46:49 +08:00
|
|
|
if (Stats.NumInstances > 1) {
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << " Average Size: ";
|
2007-05-05 09:46:49 +08:00
|
|
|
PrintSize(Stats.NumBits/(double)Stats.NumInstances);
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << "\n";
|
|
|
|
outs() << " Tot/Avg SubBlocks: " << Stats.NumSubBlocks << "/"
|
2009-07-16 00:35:29 +08:00
|
|
|
<< Stats.NumSubBlocks/(double)Stats.NumInstances << "\n";
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << " Tot/Avg Abbrevs: " << Stats.NumAbbrevs << "/"
|
2009-07-16 00:35:29 +08:00
|
|
|
<< Stats.NumAbbrevs/(double)Stats.NumInstances << "\n";
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << " Tot/Avg Records: " << Stats.NumRecords << "/"
|
2009-07-16 00:35:29 +08:00
|
|
|
<< Stats.NumRecords/(double)Stats.NumInstances << "\n";
|
2007-05-05 09:46:49 +08:00
|
|
|
} else {
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << " Num SubBlocks: " << Stats.NumSubBlocks << "\n";
|
|
|
|
outs() << " Num Abbrevs: " << Stats.NumAbbrevs << "\n";
|
|
|
|
outs() << " Num Records: " << Stats.NumRecords << "\n";
|
2007-05-05 09:46:49 +08:00
|
|
|
}
|
2009-09-26 00:04:21 +08:00
|
|
|
if (Stats.NumRecords) {
|
|
|
|
double pct = (Stats.NumAbbreviatedRecords * 100.0) / Stats.NumRecords;
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << " Percent Abbrevs: " << format("%2.4f%%", pct) << "\n";
|
2009-09-26 00:04:21 +08:00
|
|
|
}
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << "\n";
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2007-05-05 09:46:49 +08:00
|
|
|
// Print a histogram of the codes we see.
|
|
|
|
if (!NoHistogram && !Stats.CodeFreq.empty()) {
|
2015-10-21 14:10:55 +08:00
|
|
|
std::vector<std::pair<unsigned, unsigned> > FreqPairs; // <freq,code>
|
2007-05-05 09:46:49 +08:00
|
|
|
for (unsigned i = 0, e = Stats.CodeFreq.size(); i != e; ++i)
|
2015-10-21 14:10:55 +08:00
|
|
|
if (unsigned Freq = Stats.CodeFreq[i].NumInstances)
|
2007-05-05 09:46:49 +08:00
|
|
|
FreqPairs.push_back(std::make_pair(Freq, i));
|
|
|
|
std::stable_sort(FreqPairs.begin(), FreqPairs.end());
|
|
|
|
std::reverse(FreqPairs.begin(), FreqPairs.end());
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << "\tRecord Histogram:\n";
|
2016-02-06 08:46:09 +08:00
|
|
|
outs() << "\t\t Count # Bits b/Rec % Abv Record Kind\n";
|
2007-05-05 09:46:49 +08:00
|
|
|
for (unsigned i = 0, e = FreqPairs.size(); i != e; ++i) {
|
2009-04-28 02:15:27 +08:00
|
|
|
const PerRecordStats &RecStats = Stats.CodeFreq[FreqPairs[i].second];
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2015-10-21 14:10:55 +08:00
|
|
|
outs() << format("\t\t%7d %9lu",
|
2012-09-06 04:55:57 +08:00
|
|
|
RecStats.NumInstances,
|
|
|
|
(unsigned long)RecStats.TotalBits);
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2016-02-06 08:46:09 +08:00
|
|
|
if (RecStats.NumInstances > 1)
|
|
|
|
outs() << format(" %9.1f",
|
|
|
|
(double)RecStats.TotalBits/RecStats.NumInstances);
|
|
|
|
else
|
|
|
|
outs() << " ";
|
|
|
|
|
2009-04-28 02:15:27 +08:00
|
|
|
if (RecStats.NumAbbrev)
|
2012-09-06 04:55:54 +08:00
|
|
|
outs() <<
|
2016-02-06 08:46:09 +08:00
|
|
|
format(" %7.2f",
|
2012-09-06 04:55:54 +08:00
|
|
|
(double)RecStats.NumAbbrev/RecStats.NumInstances*100);
|
2009-04-28 02:15:27 +08:00
|
|
|
else
|
2016-02-06 08:46:09 +08:00
|
|
|
outs() << " ";
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2016-02-06 08:46:09 +08:00
|
|
|
outs() << " ";
|
2016-11-08 12:17:11 +08:00
|
|
|
if (const char *CodeName = GetCodeName(FreqPairs[i].second, I->first,
|
|
|
|
BlockInfo, CurStreamType))
|
2012-09-06 04:55:54 +08:00
|
|
|
outs() << CodeName << "\n";
|
2007-05-05 09:46:49 +08:00
|
|
|
else
|
2012-09-06 04:55:54 +08:00
|
|
|
outs() << "UnknownCode" << FreqPairs[i].second << "\n";
|
2007-05-05 09:46:49 +08:00
|
|
|
}
|
2012-03-20 07:40:48 +08:00
|
|
|
outs() << "\n";
|
2009-09-26 00:03:57 +08:00
|
|
|
|
2007-05-05 09:46:49 +08:00
|
|
|
}
|
2007-04-30 04:00:02 +08:00
|
|
|
}
|
2007-04-29 16:12:22 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2004-06-08 01:53:43 +08:00
|
|
|
|
2007-04-29 16:31:14 +08:00
|
|
|
|
2006-12-06 09:18:01 +08:00
|
|
|
int main(int argc, char **argv) {
|
2018-04-14 02:26:06 +08:00
|
|
|
InitLLVM X(argc, argv);
|
2009-03-06 13:34:10 +08:00
|
|
|
cl::ParseCommandLineOptions(argc, argv, "llvm-bcanalyzer file analyzer\n");
|
2007-05-06 17:29:57 +08:00
|
|
|
return AnalyzeBitcode();
|
2004-06-08 01:53:43 +08:00
|
|
|
}
|