mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
Teach llvm-bcanalyzer to use one stream's BLOCKINFO to read another stream.
This allows streams that only use BLOCKINFO for debugging purposes to omit the block entirely. As long as another stream is available with the correct BLOCKINFO, the first stream can still be analyzed and dumped. As part of this commit, BitstreamReader gets a move constructor and move assignment operator, as well as a takeBlockInfo method. llvm-svn: 216826
This commit is contained in:
parent
57c93cf3ef
commit
799c2d6473
@ -58,15 +58,27 @@ public:
|
|||||||
BitstreamReader() : IgnoreBlockInfoNames(true) {
|
BitstreamReader() : IgnoreBlockInfoNames(true) {
|
||||||
}
|
}
|
||||||
|
|
||||||
BitstreamReader(const unsigned char *Start, const unsigned char *End) {
|
BitstreamReader(const unsigned char *Start, const unsigned char *End)
|
||||||
IgnoreBlockInfoNames = true;
|
: IgnoreBlockInfoNames(true) {
|
||||||
init(Start, End);
|
init(Start, End);
|
||||||
}
|
}
|
||||||
|
|
||||||
BitstreamReader(StreamableMemoryObject *bytes) {
|
BitstreamReader(StreamableMemoryObject *bytes) : IgnoreBlockInfoNames(true) {
|
||||||
BitcodeBytes.reset(bytes);
|
BitcodeBytes.reset(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BitstreamReader(BitstreamReader &&Other) {
|
||||||
|
*this = std::move(Other);
|
||||||
|
}
|
||||||
|
|
||||||
|
BitstreamReader &operator=(BitstreamReader &&Other) {
|
||||||
|
BitcodeBytes = std::move(Other.BitcodeBytes);
|
||||||
|
// Explicitly swap block info, so that nothing gets destroyed twice.
|
||||||
|
std::swap(BlockInfoRecords, Other.BlockInfoRecords);
|
||||||
|
IgnoreBlockInfoNames = Other.IgnoreBlockInfoNames;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
void init(const unsigned char *Start, const unsigned char *End) {
|
void init(const unsigned char *Start, const unsigned char *End) {
|
||||||
assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes");
|
assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes");
|
||||||
BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End));
|
BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End));
|
||||||
@ -123,6 +135,15 @@ public:
|
|||||||
BlockInfoRecords.back().BlockID = BlockID;
|
BlockInfoRecords.back().BlockID = BlockID;
|
||||||
return BlockInfoRecords.back();
|
return BlockInfoRecords.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Takes block info from the other bitstream reader.
|
||||||
|
///
|
||||||
|
/// This is a "take" operation because BlockInfo records are non-trivial, and
|
||||||
|
/// indeed rather expensive.
|
||||||
|
void takeBlockInfo(BitstreamReader &&Other) {
|
||||||
|
assert(!hasBlockInfoRecords());
|
||||||
|
BlockInfoRecords = std::move(Other.BlockInfoRecords);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,3 +48,5 @@ entry:
|
|||||||
%2 = icmp eq i32 %1, %a
|
%2 = icmp eq i32 %1, %a
|
||||||
ret i1 %2
|
ret i1 %2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; CHECK: Stream type: LLVM IR
|
||||||
|
BIN
test/Other/Inputs/block-info-only.bc
Executable file
BIN
test/Other/Inputs/block-info-only.bc
Executable file
Binary file not shown.
BIN
test/Other/Inputs/has-block-info.bc
Normal file
BIN
test/Other/Inputs/has-block-info.bc
Normal file
Binary file not shown.
BIN
test/Other/Inputs/no-block-info.bc
Executable file
BIN
test/Other/Inputs/no-block-info.bc
Executable file
Binary file not shown.
32
test/Other/bcanalyzer-block-info.txt
Normal file
32
test/Other/bcanalyzer-block-info.txt
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
RUN: llvm-bcanalyzer -dump %S/Inputs/has-block-info.bc | FileCheck -check-prefix=CHECK -check-prefix=DATA %s
|
||||||
|
RUN: llvm-bcanalyzer -dump %S/Inputs/no-block-info.bc | FileCheck -check-prefix=UNKNOWN -check-prefix=DATA %s
|
||||||
|
RUN: llvm-bcanalyzer -dump %S/Inputs/no-block-info.bc -block-info %S/Inputs/block-info-only.bc | FileCheck -check-prefix=CHECK -check-prefix=DATA %s
|
||||||
|
|
||||||
|
CHECK: <ABC
|
||||||
|
UNKNOWN: <UnknownBlock8
|
||||||
|
DATA: NumWords=4 BlockCodeSize=2>
|
||||||
|
CHECK: <AAA
|
||||||
|
UNKNOWN: <UnknownCode0
|
||||||
|
DATA: op0=42 op1=43 op2=44/>
|
||||||
|
CHECK: <BBB
|
||||||
|
UNKNOWN: <UnknownCode1
|
||||||
|
DATA: op0=42/>
|
||||||
|
CHECK: <AAA
|
||||||
|
UNKNOWN: <UnknownCode0
|
||||||
|
DATA: op0=42/>
|
||||||
|
CHECK: </ABC>
|
||||||
|
UNKNOWN: </UnknownBlock8>
|
||||||
|
CHECK: <XYZ
|
||||||
|
UNKNOWN: <UnknownBlock9
|
||||||
|
DATA: NumWords=3 BlockCodeSize=3>
|
||||||
|
CHECK: <XXX
|
||||||
|
UNKNOWN: <UnknownCode0
|
||||||
|
DATA: abbrevid=4 op0=50 op1=4/>
|
||||||
|
CHECK: <YYY
|
||||||
|
UNKNOWN: <UnknownCode1
|
||||||
|
DATA: op0=42/>
|
||||||
|
CHECK: <XXX
|
||||||
|
UNKNOWN: <UnknownCode0
|
||||||
|
DATA: abbrevid=4 op0=50 op1=5/>
|
||||||
|
CHECK: </XYZ>
|
||||||
|
UNKNOWN: </UnknownBlock9>
|
@ -31,6 +31,7 @@
|
|||||||
#include "llvm/Bitcode/LLVMBitCodes.h"
|
#include "llvm/Bitcode/LLVMBitCodes.h"
|
||||||
#include "llvm/Bitcode/ReaderWriter.h"
|
#include "llvm/Bitcode/ReaderWriter.h"
|
||||||
#include "llvm/IR/Verifier.h"
|
#include "llvm/IR/Verifier.h"
|
||||||
|
#include "llvm/ADT/Optional.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/Format.h"
|
#include "llvm/Support/Format.h"
|
||||||
#include "llvm/Support/ManagedStatic.h"
|
#include "llvm/Support/ManagedStatic.h"
|
||||||
@ -61,6 +62,10 @@ NonSymbolic("non-symbolic",
|
|||||||
cl::desc("Emit numeric info in dump even if"
|
cl::desc("Emit numeric info in dump even if"
|
||||||
" symbolic info is available"));
|
" symbolic info is available"));
|
||||||
|
|
||||||
|
static cl::opt<std::string>
|
||||||
|
BlockInfoFilename("block-info",
|
||||||
|
cl::desc("Use the BLOCK_INFO from the given file"));
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// CurStreamTypeType - A type for CurStreamType
|
/// CurStreamTypeType - A type for CurStreamType
|
||||||
@ -71,15 +76,11 @@ enum CurStreamTypeType {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CurStreamType - If we can sniff the flavor of this stream, we can produce
|
|
||||||
/// better dump info.
|
|
||||||
static CurStreamTypeType CurStreamType;
|
|
||||||
|
|
||||||
|
|
||||||
/// GetBlockName - Return a symbolic block name if known, otherwise return
|
/// GetBlockName - Return a symbolic block name if known, otherwise return
|
||||||
/// null.
|
/// null.
|
||||||
static const char *GetBlockName(unsigned BlockID,
|
static const char *GetBlockName(unsigned BlockID,
|
||||||
const BitstreamReader &StreamFile) {
|
const BitstreamReader &StreamFile,
|
||||||
|
CurStreamTypeType CurStreamType) {
|
||||||
// Standard blocks for all bitcode files.
|
// Standard blocks for all bitcode files.
|
||||||
if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {
|
if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {
|
||||||
if (BlockID == bitc::BLOCKINFO_BLOCK_ID)
|
if (BlockID == bitc::BLOCKINFO_BLOCK_ID)
|
||||||
@ -115,7 +116,8 @@ static const char *GetBlockName(unsigned BlockID,
|
|||||||
/// GetCodeName - Return a symbolic code name if known, otherwise return
|
/// GetCodeName - Return a symbolic code name if known, otherwise return
|
||||||
/// null.
|
/// null.
|
||||||
static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
|
static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
|
||||||
const BitstreamReader &StreamFile) {
|
const BitstreamReader &StreamFile,
|
||||||
|
CurStreamTypeType CurStreamType) {
|
||||||
// Standard blocks for all bitcode files.
|
// Standard blocks for all bitcode files.
|
||||||
if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {
|
if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {
|
||||||
if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
|
if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
|
||||||
@ -316,14 +318,14 @@ static std::map<unsigned, PerBlockIDStats> BlockIDStats;
|
|||||||
|
|
||||||
/// Error - All bitcode analysis errors go through this function, making this a
|
/// Error - All bitcode analysis errors go through this function, making this a
|
||||||
/// good place to breakpoint if debugging.
|
/// good place to breakpoint if debugging.
|
||||||
static bool Error(const std::string &Err) {
|
static bool Error(const Twine &Err) {
|
||||||
errs() << Err << "\n";
|
errs() << Err << "\n";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ParseBlock - Read a block, updating statistics, etc.
|
/// ParseBlock - Read a block, updating statistics, etc.
|
||||||
static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID,
|
static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID,
|
||||||
unsigned IndentLevel) {
|
unsigned IndentLevel, CurStreamTypeType CurStreamType) {
|
||||||
std::string Indent(IndentLevel*2, ' ');
|
std::string Indent(IndentLevel*2, ' ');
|
||||||
uint64_t BlockBitStart = Stream.GetCurrentBitNo();
|
uint64_t BlockBitStart = Stream.GetCurrentBitNo();
|
||||||
|
|
||||||
@ -349,7 +351,8 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID,
|
|||||||
const char *BlockName = nullptr;
|
const char *BlockName = nullptr;
|
||||||
if (Dump) {
|
if (Dump) {
|
||||||
outs() << Indent << "<";
|
outs() << Indent << "<";
|
||||||
if ((BlockName = GetBlockName(BlockID, *Stream.getBitStreamReader())))
|
if ((BlockName = GetBlockName(BlockID, *Stream.getBitStreamReader(),
|
||||||
|
CurStreamType)))
|
||||||
outs() << BlockName;
|
outs() << BlockName;
|
||||||
else
|
else
|
||||||
outs() << "UnknownBlock" << BlockID;
|
outs() << "UnknownBlock" << BlockID;
|
||||||
@ -391,7 +394,7 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID,
|
|||||||
|
|
||||||
case BitstreamEntry::SubBlock: {
|
case BitstreamEntry::SubBlock: {
|
||||||
uint64_t SubBlockBitStart = Stream.GetCurrentBitNo();
|
uint64_t SubBlockBitStart = Stream.GetCurrentBitNo();
|
||||||
if (ParseBlock(Stream, Entry.ID, IndentLevel+1))
|
if (ParseBlock(Stream, Entry.ID, IndentLevel+1, CurStreamType))
|
||||||
return true;
|
return true;
|
||||||
++BlockStats.NumSubBlocks;
|
++BlockStats.NumSubBlocks;
|
||||||
uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo();
|
uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo();
|
||||||
@ -432,12 +435,14 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID,
|
|||||||
if (Dump) {
|
if (Dump) {
|
||||||
outs() << Indent << " <";
|
outs() << Indent << " <";
|
||||||
if (const char *CodeName =
|
if (const char *CodeName =
|
||||||
GetCodeName(Code, BlockID, *Stream.getBitStreamReader()))
|
GetCodeName(Code, BlockID, *Stream.getBitStreamReader(),
|
||||||
|
CurStreamType))
|
||||||
outs() << CodeName;
|
outs() << CodeName;
|
||||||
else
|
else
|
||||||
outs() << "UnknownCode" << Code;
|
outs() << "UnknownCode" << Code;
|
||||||
if (NonSymbolic &&
|
if (NonSymbolic &&
|
||||||
GetCodeName(Code, BlockID, *Stream.getBitStreamReader()))
|
GetCodeName(Code, BlockID, *Stream.getBitStreamReader(),
|
||||||
|
CurStreamType))
|
||||||
outs() << " codeid=" << Code;
|
outs() << " codeid=" << Code;
|
||||||
if (Entry.ID != bitc::UNABBREV_RECORD)
|
if (Entry.ID != bitc::UNABBREV_RECORD)
|
||||||
outs() << " abbrevid=" << Entry.ID;
|
outs() << " abbrevid=" << Entry.ID;
|
||||||
@ -475,21 +480,23 @@ static void PrintSize(uint64_t Bits) {
|
|||||||
(double)Bits/8, (unsigned long)(Bits/32));
|
(double)Bits/8, (unsigned long)(Bits/32));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool openBitcodeFile(StringRef Path,
|
||||||
/// AnalyzeBitcode - Analyze the bitcode file specified by InputFilename.
|
std::unique_ptr<MemoryBuffer> &MemBuf,
|
||||||
static int AnalyzeBitcode() {
|
BitstreamReader &StreamFile,
|
||||||
|
BitstreamCursor &Stream,
|
||||||
|
CurStreamTypeType &CurStreamType) {
|
||||||
// Read the input file.
|
// Read the input file.
|
||||||
ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr =
|
ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr =
|
||||||
MemoryBuffer::getFileOrSTDIN(InputFilename);
|
MemoryBuffer::getFileOrSTDIN(Path);
|
||||||
if (std::error_code EC = MemBufOrErr.getError())
|
if (std::error_code EC = MemBufOrErr.getError())
|
||||||
return Error("Error reading '" + InputFilename + "': " + EC.message());
|
return Error(Twine("Error reading '") + Path + "': " + EC.message());
|
||||||
MemoryBuffer &MemBuf = *MemBufOrErr.get();
|
MemBuf = std::move(MemBufOrErr.get());
|
||||||
|
|
||||||
if (MemBuf.getBufferSize() & 3)
|
if (MemBuf->getBufferSize() & 3)
|
||||||
return Error("Bitcode stream should be a multiple of 4 bytes in length");
|
return Error("Bitcode stream should be a multiple of 4 bytes in length");
|
||||||
|
|
||||||
const unsigned char *BufPtr = (const unsigned char *)MemBuf.getBufferStart();
|
const unsigned char *BufPtr = (const unsigned char *)MemBuf->getBufferStart();
|
||||||
const unsigned char *EndBufPtr = BufPtr+MemBuf.getBufferSize();
|
const unsigned char *EndBufPtr = BufPtr + MemBuf->getBufferSize();
|
||||||
|
|
||||||
// If we have a wrapper header, parse it and ignore the non-bc file contents.
|
// If we have a wrapper header, parse it and ignore the non-bc file contents.
|
||||||
// The magic number is 0x0B17C0DE stored in little endian.
|
// The magic number is 0x0B17C0DE stored in little endian.
|
||||||
@ -497,8 +504,8 @@ static int AnalyzeBitcode() {
|
|||||||
if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr, true))
|
if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr, true))
|
||||||
return Error("Invalid bitcode wrapper header");
|
return Error("Invalid bitcode wrapper header");
|
||||||
|
|
||||||
BitstreamReader StreamFile(BufPtr, EndBufPtr);
|
StreamFile = BitstreamReader(BufPtr, EndBufPtr);
|
||||||
BitstreamCursor Stream(StreamFile);
|
Stream = BitstreamCursor(StreamFile);
|
||||||
StreamFile.CollectBlockInfoNames();
|
StreamFile.CollectBlockInfoNames();
|
||||||
|
|
||||||
// Read the stream signature.
|
// Read the stream signature.
|
||||||
@ -517,6 +524,48 @@ static int AnalyzeBitcode() {
|
|||||||
Signature[4] == 0xE && Signature[5] == 0xD)
|
Signature[4] == 0xE && Signature[5] == 0xD)
|
||||||
CurStreamType = LLVMIRBitstream;
|
CurStreamType = LLVMIRBitstream;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// AnalyzeBitcode - Analyze the bitcode file specified by InputFilename.
|
||||||
|
static int AnalyzeBitcode() {
|
||||||
|
std::unique_ptr<MemoryBuffer> StreamBuffer;
|
||||||
|
BitstreamReader StreamFile;
|
||||||
|
BitstreamCursor Stream;
|
||||||
|
CurStreamTypeType CurStreamType;
|
||||||
|
if (openBitcodeFile(InputFilename, StreamBuffer, StreamFile, Stream,
|
||||||
|
CurStreamType))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Read block info from BlockInfoFilename, if specified.
|
||||||
|
// The block info must be a top-level block.
|
||||||
|
if (!BlockInfoFilename.empty()) {
|
||||||
|
std::unique_ptr<MemoryBuffer> BlockInfoBuffer;
|
||||||
|
BitstreamReader BlockInfoFile;
|
||||||
|
BitstreamCursor BlockInfoCursor;
|
||||||
|
CurStreamTypeType BlockInfoStreamType;
|
||||||
|
if (openBitcodeFile(BlockInfoFilename, BlockInfoBuffer, BlockInfoFile,
|
||||||
|
BlockInfoCursor, BlockInfoStreamType))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
while (!BlockInfoCursor.AtEndOfStream()) {
|
||||||
|
unsigned Code = BlockInfoCursor.ReadCode();
|
||||||
|
if (Code != bitc::ENTER_SUBBLOCK)
|
||||||
|
return Error("Invalid record at top-level in block info file");
|
||||||
|
|
||||||
|
unsigned BlockID = BlockInfoCursor.ReadSubBlockID();
|
||||||
|
if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
|
||||||
|
if (BlockInfoCursor.ReadBlockInfoBlock())
|
||||||
|
return Error("Malformed BlockInfoBlock in block info file");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockInfoCursor.SkipBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamFile.takeBlockInfo(std::move(BlockInfoFile));
|
||||||
|
}
|
||||||
|
|
||||||
unsigned NumTopBlocks = 0;
|
unsigned NumTopBlocks = 0;
|
||||||
|
|
||||||
// Parse the top-level structure. We only allow blocks at the top-level.
|
// Parse the top-level structure. We only allow blocks at the top-level.
|
||||||
@ -527,14 +576,14 @@ static int AnalyzeBitcode() {
|
|||||||
|
|
||||||
unsigned BlockID = Stream.ReadSubBlockID();
|
unsigned BlockID = Stream.ReadSubBlockID();
|
||||||
|
|
||||||
if (ParseBlock(Stream, BlockID, 0))
|
if (ParseBlock(Stream, BlockID, 0, CurStreamType))
|
||||||
return true;
|
return true;
|
||||||
++NumTopBlocks;
|
++NumTopBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Dump) outs() << "\n\n";
|
if (Dump) outs() << "\n\n";
|
||||||
|
|
||||||
uint64_t BufferSizeBits = (EndBufPtr-BufPtr)*CHAR_BIT;
|
uint64_t BufferSizeBits = StreamFile.getBitcodeBytes().getExtent() * CHAR_BIT;
|
||||||
// Print a summary of the read file.
|
// Print a summary of the read file.
|
||||||
outs() << "Summary of " << InputFilename << ":\n";
|
outs() << "Summary of " << InputFilename << ":\n";
|
||||||
outs() << " Total size: ";
|
outs() << " Total size: ";
|
||||||
@ -553,7 +602,8 @@ static int AnalyzeBitcode() {
|
|||||||
for (std::map<unsigned, PerBlockIDStats>::iterator I = BlockIDStats.begin(),
|
for (std::map<unsigned, PerBlockIDStats>::iterator I = BlockIDStats.begin(),
|
||||||
E = BlockIDStats.end(); I != E; ++I) {
|
E = BlockIDStats.end(); I != E; ++I) {
|
||||||
outs() << " Block ID #" << I->first;
|
outs() << " Block ID #" << I->first;
|
||||||
if (const char *BlockName = GetBlockName(I->first, StreamFile))
|
if (const char *BlockName = GetBlockName(I->first, StreamFile,
|
||||||
|
CurStreamType))
|
||||||
outs() << " (" << BlockName << ")";
|
outs() << " (" << BlockName << ")";
|
||||||
outs() << ":\n";
|
outs() << ":\n";
|
||||||
|
|
||||||
@ -611,7 +661,8 @@ static int AnalyzeBitcode() {
|
|||||||
outs() << " ";
|
outs() << " ";
|
||||||
|
|
||||||
if (const char *CodeName =
|
if (const char *CodeName =
|
||||||
GetCodeName(FreqPairs[i].second, I->first, StreamFile))
|
GetCodeName(FreqPairs[i].second, I->first, StreamFile,
|
||||||
|
CurStreamType))
|
||||||
outs() << CodeName << "\n";
|
outs() << CodeName << "\n";
|
||||||
else
|
else
|
||||||
outs() << "UnknownCode" << FreqPairs[i].second << "\n";
|
outs() << "UnknownCode" << FreqPairs[i].second << "\n";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user