Enable streaming of bitcode

This CL delays reading of function bodies from initial parse until
materialization, allowing overlap of compilation with bitcode download.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@149918 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Derek Schuff 2012-02-06 22:30:29 +00:00
parent 06d7e1b52b
commit 2ea93875b2
26 changed files with 748 additions and 163 deletions

View File

@ -15,10 +15,12 @@
#ifndef BITSTREAM_READER_H
#define BITSTREAM_READER_H
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Bitcode/BitCodes.h"
#include <climits>
#include <string>
#include <vector>
#include "llvm/Support/StreamableMemoryObject.h"
namespace llvm {
@ -36,9 +38,7 @@ public:
std::vector<std::pair<unsigned, std::string> > RecordNames;
};
private:
/// FirstChar/LastChar - This remembers the first and last bytes of the
/// stream.
const unsigned char *FirstChar, *LastChar;
OwningPtr<StreamableMemoryObject> BitcodeBytes;
std::vector<BlockInfo> BlockInfoRecords;
@ -47,10 +47,10 @@ private:
/// uses this.
bool IgnoreBlockInfoNames;
BitstreamReader(const BitstreamReader&); // NOT IMPLEMENTED
void operator=(const BitstreamReader&); // NOT IMPLEMENTED
BitstreamReader(const BitstreamReader&); // DO NOT IMPLEMENT
void operator=(const BitstreamReader&); // DO NOT IMPLEMENT
public:
BitstreamReader() : FirstChar(0), LastChar(0), IgnoreBlockInfoNames(true) {
BitstreamReader() : IgnoreBlockInfoNames(true) {
}
BitstreamReader(const unsigned char *Start, const unsigned char *End) {
@ -58,12 +58,17 @@ public:
init(Start, End);
}
void init(const unsigned char *Start, const unsigned char *End) {
FirstChar = Start;
LastChar = End;
assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes");
BitstreamReader(StreamableMemoryObject *bytes) {
BitcodeBytes.reset(bytes);
}
void init(const unsigned char *Start, const unsigned char *End) {
assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes");
BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End));
}
StreamableMemoryObject &getBitcodeBytes() { return *BitcodeBytes; }
~BitstreamReader() {
// Free the BlockInfoRecords.
while (!BlockInfoRecords.empty()) {
@ -75,9 +80,6 @@ public:
BlockInfoRecords.pop_back();
}
}
const unsigned char *getFirstChar() const { return FirstChar; }
const unsigned char *getLastChar() const { return LastChar; }
/// CollectBlockInfoNames - This is called by clients that want block/record
/// name information.
@ -122,7 +124,7 @@ public:
class BitstreamCursor {
friend class Deserializer;
BitstreamReader *BitStream;
const unsigned char *NextChar;
size_t NextChar;
/// CurWord - This is the current data we have pulled from the stream but have
/// not returned to the client.
@ -156,8 +158,7 @@ public:
}
explicit BitstreamCursor(BitstreamReader &R) : BitStream(&R) {
NextChar = R.getFirstChar();
assert(NextChar && "Bitstream not initialized yet");
NextChar = 0;
CurWord = 0;
BitsInCurWord = 0;
CurCodeSize = 2;
@ -167,8 +168,7 @@ public:
freeState();
BitStream = &R;
NextChar = R.getFirstChar();
assert(NextChar && "Bitstream not initialized yet");
NextChar = 0;
CurWord = 0;
BitsInCurWord = 0;
CurCodeSize = 2;
@ -225,13 +225,38 @@ public:
/// GetAbbrevIDWidth - Return the number of bits used to encode an abbrev #.
unsigned GetAbbrevIDWidth() const { return CurCodeSize; }
bool AtEndOfStream() const {
return NextChar == BitStream->getLastChar() && BitsInCurWord == 0;
bool isEndPos(size_t pos) {
return BitStream->getBitcodeBytes().isObjectEnd(static_cast<uint64_t>(pos));
}
bool canSkipToPos(size_t pos) const {
// pos can be skipped to if it is a valid address or one byte past the end.
return pos == 0 || BitStream->getBitcodeBytes().isValidAddress(
static_cast<uint64_t>(pos - 1));
}
unsigned char getByte(size_t pos) {
uint8_t byte = -1;
BitStream->getBitcodeBytes().readByte(pos, &byte);
return byte;
}
uint32_t getWord(size_t pos) {
uint32_t word = -1;
BitStream->getBitcodeBytes().readBytes(pos,
sizeof(word),
reinterpret_cast<uint8_t *>(&word),
NULL);
return word;
}
bool AtEndOfStream() {
return isEndPos(NextChar) && BitsInCurWord == 0;
}
/// GetCurrentBitNo - Return the bit # of the bit we are reading.
uint64_t GetCurrentBitNo() const {
return (NextChar-BitStream->getFirstChar())*CHAR_BIT - BitsInCurWord;
return NextChar*CHAR_BIT - BitsInCurWord;
}
BitstreamReader *getBitStreamReader() {
@ -246,12 +271,10 @@ public:
void JumpToBit(uint64_t BitNo) {
uintptr_t ByteNo = uintptr_t(BitNo/8) & ~3;
uintptr_t WordBitNo = uintptr_t(BitNo) & 31;
assert(ByteNo <= (uintptr_t)(BitStream->getLastChar()-
BitStream->getFirstChar()) &&
"Invalid location");
assert(canSkipToPos(ByteNo) && "Invalid location");
// Move the cursor to the right word.
NextChar = BitStream->getFirstChar()+ByteNo;
NextChar = ByteNo;
BitsInCurWord = 0;
CurWord = 0;
@ -272,7 +295,7 @@ public:
}
// If we run out of data, stop at the end of the stream.
if (NextChar == BitStream->getLastChar()) {
if (isEndPos(NextChar)) {
CurWord = 0;
BitsInCurWord = 0;
return 0;
@ -281,8 +304,7 @@ public:
unsigned R = CurWord;
// Read the next word from the stream.
CurWord = (NextChar[0] << 0) | (NextChar[1] << 8) |
(NextChar[2] << 16) | (NextChar[3] << 24);
CurWord = getWord(NextChar);
NextChar += 4;
// Extract NumBits-BitsInCurWord from what we just read.
@ -376,9 +398,8 @@ public:
// Check that the block wasn't partially defined, and that the offset isn't
// bogus.
const unsigned char *const SkipTo = NextChar + NumWords*4;
if (AtEndOfStream() || SkipTo > BitStream->getLastChar() ||
SkipTo < BitStream->getFirstChar())
size_t SkipTo = NextChar + NumWords*4;
if (AtEndOfStream() || !canSkipToPos(SkipTo))
return true;
NextChar = SkipTo;
@ -409,8 +430,7 @@ public:
if (NumWordsP) *NumWordsP = NumWords;
// Validate that this block is sane.
if (CurCodeSize == 0 || AtEndOfStream() ||
NextChar+NumWords*4 > BitStream->getLastChar())
if (CurCodeSize == 0 || AtEndOfStream())
return true;
return false;
@ -512,24 +532,25 @@ public:
SkipToWord(); // 32-bit alignment
// Figure out where the end of this blob will be including tail padding.
const unsigned char *NewEnd = NextChar+((NumElts+3)&~3);
size_t NewEnd = NextChar+((NumElts+3)&~3);
// If this would read off the end of the bitcode file, just set the
// record to empty and return.
if (NewEnd > BitStream->getLastChar()) {
if (!canSkipToPos(NewEnd)) {
Vals.append(NumElts, 0);
NextChar = BitStream->getLastChar();
NextChar = BitStream->getBitcodeBytes().getExtent();
break;
}
// Otherwise, read the number of bytes. If we can return a reference to
// the data, do so to avoid copying it.
if (BlobStart) {
*BlobStart = (const char*)NextChar;
*BlobStart = (const char*)BitStream->getBitcodeBytes().getPointer(
NextChar, NumElts);
*BlobLen = NumElts;
} else {
for (; NumElts; ++NextChar, --NumElts)
Vals.push_back(*NextChar);
Vals.push_back(getByte(NextChar));
}
// Skip over tail padding.
NextChar = NewEnd;

View File

@ -17,35 +17,45 @@
#include <string>
namespace llvm {
class Module;
class MemoryBuffer;
class ModulePass;
class BitstreamWriter;
class MemoryBuffer;
class DataStreamer;
class LLVMContext;
class Module;
class ModulePass;
class raw_ostream;
/// getLazyBitcodeModule - Read the header of the specified bitcode buffer
/// and prepare for lazy deserialization of function bodies. If successful,
/// this takes ownership of 'buffer' and returns a non-null pointer. On
/// error, this returns null, *does not* take ownership of Buffer, and fills
/// in *ErrMsg with an error description if ErrMsg is non-null.
Module *getLazyBitcodeModule(MemoryBuffer *Buffer,
LLVMContext& Context,
LLVMContext &Context,
std::string *ErrMsg = 0);
/// getStreamedBitcodeModule - Read the header of the specified stream
/// and prepare for lazy deserialization and streaming of function bodies.
/// On error, this returns null, and fills in *ErrMsg with an error
/// description if ErrMsg is non-null.
Module *getStreamedBitcodeModule(const std::string &name,
DataStreamer *streamer,
LLVMContext &Context,
std::string *ErrMsg = 0);
/// getBitcodeTargetTriple - Read the header of the specified bitcode
/// buffer and extract just the triple information. If successful,
/// this returns a string and *does not* take ownership
/// of 'buffer'. On error, this returns "", and fills in *ErrMsg
/// if ErrMsg is non-null.
std::string getBitcodeTargetTriple(MemoryBuffer *Buffer,
LLVMContext& Context,
LLVMContext &Context,
std::string *ErrMsg = 0);
/// ParseBitcodeFile - Read the specified bitcode file, returning the module.
/// If an error occurs, this returns null and fills in *ErrMsg if it is
/// non-null. This method *never* takes ownership of Buffer.
Module *ParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext& Context,
Module *ParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext &Context,
std::string *ErrMsg = 0);
/// WriteBitcodeToFile - Write the specified module to the specified
@ -60,8 +70,8 @@ namespace llvm {
/// createBitcodeWriterPass - Create and return a pass that writes the module
/// to the specified ostream.
ModulePass *createBitcodeWriterPass(raw_ostream &Str);
/// isBitcodeWrapper - Return true if the given bytes are the magic bytes
/// for an LLVM IR bitcode wrapper.
///
@ -109,21 +119,24 @@ namespace llvm {
/// uint32_t BitcodeSize; // Size of traditional bitcode file.
/// ... potentially other gunk ...
/// };
///
///
/// This function is called when we find a file with a matching magic number.
/// In this case, skip down to the subsection of the file that is actually a
/// BC file.
static inline bool SkipBitcodeWrapperHeader(unsigned char *&BufPtr,
unsigned char *&BufEnd) {
/// If 'VerifyBufferSize' is true, check that the buffer is large enough to
/// contain the whole bitcode file.
static inline bool SkipBitcodeWrapperHeader(const unsigned char *&BufPtr,
const unsigned char *&BufEnd,
bool VerifyBufferSize) {
enum {
KnownHeaderSize = 4*4, // Size of header we read.
OffsetField = 2*4, // Offset in bytes to Offset field.
SizeField = 3*4 // Offset in bytes to Size field.
};
// Must contain the header!
if (BufEnd-BufPtr < KnownHeaderSize) return true;
unsigned Offset = ( BufPtr[OffsetField ] |
(BufPtr[OffsetField+1] << 8) |
(BufPtr[OffsetField+2] << 16) |
@ -132,9 +145,9 @@ namespace llvm {
(BufPtr[SizeField +1] << 8) |
(BufPtr[SizeField +2] << 16) |
(BufPtr[SizeField +3] << 24));
// Verify that Offset+Size fits in the file.
if (Offset+Size > unsigned(BufEnd-BufPtr))
if (VerifyBufferSize && Offset+Size > unsigned(BufEnd-BufPtr))
return true;
BufPtr += Offset;
BufEnd = BufPtr+Size;

View File

@ -79,7 +79,7 @@ public:
/// MCDisassembler::Fail if the instruction was invalid.
virtual DecodeStatus getInstruction(MCInst& instr,
uint64_t& size,
const MemoryObject &region,
MemoryObject &region,
uint64_t address,
raw_ostream &vStream,
raw_ostream &cStream) const = 0;

View File

@ -0,0 +1,38 @@
//===---- llvm/Support/DataStream.h - Lazy bitcode streaming -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This header defines DataStreamer, which fetches bytes of data from
// a stream source. It provides support for streaming (lazy reading) of
// data, e.g. bitcode
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_DATASTREAM_H_
#define LLVM_SUPPORT_DATASTREAM_H_
#include <string>
namespace llvm {
class DataStreamer {
public:
/// Fetch bytes [start-end) from the stream, and write them to the
/// buffer pointed to by buf. Returns the number of bytes actually written.
virtual size_t GetBytes(unsigned char *buf, size_t len) = 0;
virtual ~DataStreamer();
};
DataStreamer *getDataFileStreamer(const std::string &Filename,
std::string *Err);
}
#endif // LLVM_SUPPORT_DATASTREAM_H_

View File

@ -34,7 +34,7 @@ public:
/// is getBase() + getExtent() - 1).
///
/// @result - The size of the region.
virtual uint64_t getExtent() const = 0;
virtual uint64_t getExtent() = 0;
/// readByte - Tries to read a single byte from the region.
///
@ -42,7 +42,7 @@ public:
/// @param ptr - A pointer to a byte to be filled in. Must be non-NULL.
/// @result - 0 if successful; -1 if not. Failure may be due to a
/// bounds violation or an implementation-specific error.
virtual int readByte(uint64_t address, uint8_t* ptr) const = 0;
virtual int readByte(uint64_t address, uint8_t* ptr) = 0;
/// readBytes - Tries to read a contiguous range of bytes from the
/// region, up to the end of the region.
@ -61,7 +61,7 @@ public:
virtual int readBytes(uint64_t address,
uint64_t size,
uint8_t* buf,
uint64_t* copied) const;
uint64_t* copied);
};
}

View File

@ -0,0 +1,181 @@
//===- StreamableMemoryObject.h - Streamable data interface - -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef STREAMABLEMEMORYOBJECT_H_
#define STREAMABLEMEMORYOBJECT_H_
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/MemoryObject.h"
#include "llvm/Support/DataStream.h"
#include <vector>
namespace llvm {
/// StreamableMemoryObject - Interface to data which might be streamed.
/// Streamability has 2 important implications/restrictions. First, the data
/// might not yet exist in memory when the request is made. This just means
/// that readByte/readBytes might have to block or do some work to get it.
/// More significantly, the exact size of the object might not be known until
/// it has all been fetched. This means that to return the right result,
/// getExtent must also wait for all the data to arrive; therefore it should
/// not be called on objects which are actually streamed (this would defeat
/// the purpose of streaming). Instead, isValidAddress and isObjectEnd can be
/// used to test addresses without knowing the exact size of the stream.
/// Finally, getPointer can be used instead of readBytes to avoid extra copying.
class StreamableMemoryObject : public MemoryObject {
public:
/// Destructor - Override as necessary.
virtual ~StreamableMemoryObject();
/// getBase - Returns the lowest valid address in the region.
///
/// @result - The lowest valid address.
virtual uint64_t getBase() const = 0;
/// getExtent - Returns the size of the region in bytes. (The region is
/// contiguous, so the highest valid address of the region
/// is getBase() + getExtent() - 1).
/// May block until all bytes in the stream have been read
///
/// @result - The size of the region.
virtual uint64_t getExtent() = 0;
/// readByte - Tries to read a single byte from the region.
/// May block until (address - base) bytes have been read
/// @param address - The address of the byte, in the same space as getBase().
/// @param ptr - A pointer to a byte to be filled in. Must be non-NULL.
/// @result - 0 if successful; -1 if not. Failure may be due to a
/// bounds violation or an implementation-specific error.
virtual int readByte(uint64_t address, uint8_t* ptr) = 0;
/// readBytes - Tries to read a contiguous range of bytes from the
/// region, up to the end of the region.
/// May block until (address - base + size) bytes have
/// been read. Additionally, StreamableMemoryObjects will
/// not do partial reads - if size bytes cannot be read,
/// readBytes will fail.
///
/// @param address - The address of the first byte, in the same space as
/// getBase().
/// @param size - The maximum number of bytes to copy.
/// @param buf - A pointer to a buffer to be filled in. Must be non-NULL
/// and large enough to hold size bytes.
/// @param copied - A pointer to a nunber that is filled in with the number
/// of bytes actually read. May be NULL.
/// @result - 0 if successful; -1 if not. Failure may be due to a
/// bounds violation or an implementation-specific error.
virtual int readBytes(uint64_t address,
uint64_t size,
uint8_t* buf,
uint64_t* copied) = 0;
/// getPointer - Ensures that the requested data is in memory, and returns
/// A pointer to it. More efficient than using readBytes if the
/// data is already in memory.
/// May block until (address - base + size) bytes have been read
/// @param address - address of the byte, in the same space as getBase()
/// @param size - amount of data that must be available on return
/// @result - valid pointer to the requested data
virtual const uint8_t *getPointer(uint64_t address, uint64_t size) = 0;
/// isValidAddress - Returns true if the address is within the object
/// (i.e. between base and base + extent - 1 inclusive)
/// May block until (address - base) bytes have been read
/// @param address - address of the byte, in the same space as getBase()
/// @result - true if the address may be read with readByte()
virtual bool isValidAddress(uint64_t address) = 0;
/// isObjectEnd - Returns true if the address is one past the end of the
/// object (i.e. if it is equal to base + extent)
/// May block until (address - base) bytes have been read
/// @param address - address of the byte, in the same space as getBase()
/// @result - true if the address is equal to base + extent
virtual bool isObjectEnd(uint64_t address) = 0;
};
/// StreamingMemoryObject - interface to data which is actually streamed from
/// a DataStreamer. In addition to inherited members, it has the
/// dropLeadingBytes and setKnownObjectSize methods which are not applicable
/// to non-streamed objects.
class StreamingMemoryObject : public StreamableMemoryObject {
public:
StreamingMemoryObject(DataStreamer *streamer);
virtual uint64_t getBase() const { return 0; }
virtual uint64_t getExtent();
virtual int readByte(uint64_t address, uint8_t* ptr);
virtual int readBytes(uint64_t address,
uint64_t size,
uint8_t* buf,
uint64_t* copied);
virtual const uint8_t *getPointer(uint64_t address, uint64_t size) {
// This could be fixed by ensuring the bytes are fetched and making a copy,
// requiring that the bitcode size be known, or otherwise ensuring that
// the memory doesn't go away/get reallocated, but it's
// not currently necessary. Users that need the pointer don't stream.
assert(0 && "getPointer in streaming memory objects not allowed");
return NULL;
}
virtual bool isValidAddress(uint64_t address);
virtual bool isObjectEnd(uint64_t address);
/// Drop s bytes from the front of the stream, pushing the positions of the
/// remaining bytes down by s. This is used to skip past the bitcode header,
/// since we don't know a priori if it's present, and we can't put bytes
/// back into the stream once we've read them.
bool dropLeadingBytes(size_t s);
/// If the data object size is known in advance, many of the operations can
/// be made more efficient, so this method should be called before reading
/// starts (although it can be called anytime).
void setKnownObjectSize(size_t size);
private:
const static uint32_t kChunkSize = 4096 * 4;
std::vector<unsigned char> Bytes;
OwningPtr<DataStreamer> Streamer;
size_t BytesRead; // Bytes read from stream
size_t BytesSkipped;// Bytes skipped at start of stream (e.g. wrapper/header)
size_t ObjectSize; // 0 if unknown, set if wrapper was seen or EOF reached
bool EOFReached;
// Fetch enough bytes such that Pos can be read or EOF is reached
// (i.e. BytesRead > Pos). Return true if Pos can be read.
// Unlike most of the functions in BitcodeReader, returns true on success.
// Most of the requests will be small, but we fetch at kChunkSize bytes
// at a time to avoid making too many potentially expensive GetBytes calls
bool fetchToPos(size_t Pos) {
if (EOFReached) return Pos < ObjectSize;
while (Pos >= BytesRead) {
Bytes.resize(BytesRead + kChunkSize);
size_t bytes = Streamer->GetBytes(&Bytes[BytesRead + BytesSkipped],
kChunkSize);
BytesRead += bytes;
if (bytes < kChunkSize) {
if (ObjectSize && BytesRead < Pos)
assert(0 && "Unexpected short read fetching bitcode");
if (BytesRead <= Pos) { // reached EOF/ran out of bytes
ObjectSize = BytesRead;
EOFReached = true;
return false;
}
}
}
return true;
}
StreamingMemoryObject(const StreamingMemoryObject&); // DO NOT IMPLEMENT
void operator=(const StreamingMemoryObject&); // DO NOT IMPLEMENT
};
StreamableMemoryObject *getNonStreamedMemoryObject(
const unsigned char *Start, const unsigned char *End);
}
#endif // STREAMABLEMEMORYOBJECT_H_

View File

@ -22,6 +22,7 @@
#include "llvm/AutoUpgrade.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/DataStream.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/OperandTraits.h"
@ -1409,8 +1410,36 @@ bool BitcodeReader::RememberAndSkipFunctionBody() {
return false;
}
bool BitcodeReader::ParseModule() {
if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
bool BitcodeReader::GlobalCleanup() {
// Patch the initializers for globals and aliases up.
ResolveGlobalAndAliasInits();
if (!GlobalInits.empty() || !AliasInits.empty())
return Error("Malformed global initializer set");
// Look for intrinsic functions which need to be upgraded at some point
for (Module::iterator FI = TheModule->begin(), FE = TheModule->end();
FI != FE; ++FI) {
Function *NewFn;
if (UpgradeIntrinsicFunction(FI, NewFn))
UpgradedIntrinsics.push_back(std::make_pair(FI, NewFn));
}
// Look for global variables which need to be renamed.
for (Module::global_iterator
GI = TheModule->global_begin(), GE = TheModule->global_end();
GI != GE; ++GI)
UpgradeGlobalVariable(GI);
// Force deallocation of memory for these vectors to favor the client that
// want lazy deserialization.
std::vector<std::pair<GlobalVariable*, unsigned> >().swap(GlobalInits);
std::vector<std::pair<GlobalAlias*, unsigned> >().swap(AliasInits);
return false;
}
bool BitcodeReader::ParseModule(bool Resume) {
if (Resume)
Stream.JumpToBit(NextUnreadBit);
else if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
return Error("Malformed block record");
SmallVector<uint64_t, 64> Record;
@ -1424,33 +1453,7 @@ bool BitcodeReader::ParseModule() {
if (Stream.ReadBlockEnd())
return Error("Error at end of module block");
// Patch the initializers for globals and aliases up.
ResolveGlobalAndAliasInits();
if (!GlobalInits.empty() || !AliasInits.empty())
return Error("Malformed global initializer set");
if (!FunctionsWithBodies.empty())
return Error("Too few function bodies found");
// Look for intrinsic functions which need to be upgraded at some point
for (Module::iterator FI = TheModule->begin(), FE = TheModule->end();
FI != FE; ++FI) {
Function* NewFn;
if (UpgradeIntrinsicFunction(FI, NewFn))
UpgradedIntrinsics.push_back(std::make_pair(FI, NewFn));
}
// Look for global variables which need to be renamed.
for (Module::global_iterator
GI = TheModule->global_begin(), GE = TheModule->global_end();
GI != GE; ++GI)
UpgradeGlobalVariable(GI);
// Force deallocation of memory for these vectors to favor the client that
// want lazy deserialization.
std::vector<std::pair<GlobalVariable*, unsigned> >().swap(GlobalInits);
std::vector<std::pair<GlobalAlias*, unsigned> >().swap(AliasInits);
std::vector<Function*>().swap(FunctionsWithBodies);
return false;
return GlobalCleanup();
}
if (Code == bitc::ENTER_SUBBLOCK) {
@ -1474,6 +1477,7 @@ bool BitcodeReader::ParseModule() {
case bitc::VALUE_SYMTAB_BLOCK_ID:
if (ParseValueSymbolTable())
return true;
SeenValueSymbolTable = true;
break;
case bitc::CONSTANTS_BLOCK_ID:
if (ParseConstants() || ResolveGlobalAndAliasInits())
@ -1486,13 +1490,25 @@ bool BitcodeReader::ParseModule() {
case bitc::FUNCTION_BLOCK_ID:
// If this is the first function body we've seen, reverse the
// FunctionsWithBodies list.
if (!HasReversedFunctionsWithBodies) {
if (!SeenFirstFunctionBody) {
std::reverse(FunctionsWithBodies.begin(), FunctionsWithBodies.end());
HasReversedFunctionsWithBodies = true;
if (GlobalCleanup())
return true;
SeenFirstFunctionBody = true;
}
if (RememberAndSkipFunctionBody())
return true;
// For streaming bitcode, suspend parsing when we reach the function
// bodies. Subsequent materialization calls will resume it when
// necessary. For streaming, the function bodies must be at the end of
// the bitcode. If the bitcode file is old, the symbol table will be
// at the end instead and will not have been seen yet. In this case,
// just finish the parse now.
if (LazyStreamer && SeenValueSymbolTable) {
NextUnreadBit = Stream.GetCurrentBitNo();
return false;
}
break;
case bitc::USELIST_BLOCK_ID:
if (ParseUseLists())
@ -1651,8 +1667,10 @@ bool BitcodeReader::ParseModule() {
// If this is a function with a body, remember the prototype we are
// creating now, so that we can match up the body with them later.
if (!isProto)
if (!isProto) {
FunctionsWithBodies.push_back(Func);
if (LazyStreamer) DeferredFunctionInfo[Func] = 0;
}
break;
}
// ALIAS: [alias type, aliasee val#, linkage]
@ -1691,24 +1709,7 @@ bool BitcodeReader::ParseModule() {
bool BitcodeReader::ParseBitcodeInto(Module *M) {
TheModule = 0;
unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart();
unsigned char *BufEnd = BufPtr+Buffer->getBufferSize();
if (Buffer->getBufferSize() & 3) {
if (!isRawBitcode(BufPtr, BufEnd) && !isBitcodeWrapper(BufPtr, BufEnd))
return Error("Invalid bitcode signature");
else
return Error("Bitcode stream should be a multiple of 4 bytes in length");
}
// 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, BufEnd))
if (SkipBitcodeWrapperHeader(BufPtr, BufEnd))
return Error("Invalid bitcode wrapper header");
StreamFile.init(BufPtr, BufEnd);
Stream.init(StreamFile);
if (InitStream()) return true;
// Sniff for the signature.
if (Stream.Read(8) != 'B' ||
@ -1750,8 +1751,9 @@ bool BitcodeReader::ParseBitcodeInto(Module *M) {
if (TheModule)
return Error("Multiple MODULE_BLOCKs in same stream");
TheModule = M;
if (ParseModule())
if (ParseModule(false))
return true;
if (LazyStreamer) return false;
break;
default:
if (Stream.SkipBlock())
@ -1819,20 +1821,7 @@ bool BitcodeReader::ParseModuleTriple(std::string &Triple) {
}
bool BitcodeReader::ParseTriple(std::string &Triple) {
if (Buffer->getBufferSize() & 3)
return Error("Bitcode stream should be a multiple of 4 bytes in length");
unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart();
unsigned char *BufEnd = BufPtr+Buffer->getBufferSize();
// 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, BufEnd))
if (SkipBitcodeWrapperHeader(BufPtr, BufEnd))
return Error("Invalid bitcode wrapper header");
StreamFile.init(BufPtr, BufEnd);
Stream.init(StreamFile);
if (InitStream()) return true;
// Sniff for the signature.
if (Stream.Read(8) != 'B' ||
@ -2708,6 +2697,19 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
return false;
}
/// FindFunctionInStream - Find the function body in the bitcode stream
bool BitcodeReader::FindFunctionInStream(Function *F,
DenseMap<Function*, uint64_t>::iterator DeferredFunctionInfoIterator) {
while (DeferredFunctionInfoIterator->second == 0) {
if (Stream.AtEndOfStream())
return Error("Could not find Function in stream");
// ParseModule will parse the next body in the stream and set its
// position in the DeferredFunctionInfo map.
if (ParseModule(true)) return true;
}
return false;
}
//===----------------------------------------------------------------------===//
// GVMaterializer implementation
//===----------------------------------------------------------------------===//
@ -2728,6 +2730,10 @@ bool BitcodeReader::Materialize(GlobalValue *GV, std::string *ErrInfo) {
DenseMap<Function*, uint64_t>::iterator DFII = DeferredFunctionInfo.find(F);
assert(DFII != DeferredFunctionInfo.end() && "Deferred function not found!");
// If its position is recorded as 0, its body is somewhere in the stream
// but we haven't seen it yet.
if (DFII->second == 0)
if (LazyStreamer && FindFunctionInStream(F, DFII)) return true;
// Move the bit stream to the saved position of the deferred function body.
Stream.JumpToBit(DFII->second);
@ -2805,6 +2811,57 @@ bool BitcodeReader::MaterializeModule(Module *M, std::string *ErrInfo) {
return false;
}
bool BitcodeReader::InitStream() {
if (LazyStreamer) return InitLazyStream();
return InitStreamFromBuffer();
}
bool BitcodeReader::InitStreamFromBuffer() {
const unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart();
const unsigned char *BufEnd = BufPtr+Buffer->getBufferSize();
if (Buffer->getBufferSize() & 3) {
if (!isRawBitcode(BufPtr, BufEnd) && !isBitcodeWrapper(BufPtr, BufEnd))
return Error("Invalid bitcode signature");
else
return Error("Bitcode stream should be a multiple of 4 bytes in length");
}
// 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, BufEnd))
if (SkipBitcodeWrapperHeader(BufPtr, BufEnd, true))
return Error("Invalid bitcode wrapper header");
StreamFile.reset(new BitstreamReader(BufPtr, BufEnd));
Stream.init(*StreamFile);
return false;
}
bool BitcodeReader::InitLazyStream() {
// Check and strip off the bitcode wrapper; BitstreamReader expects never to
// see it.
StreamingMemoryObject *Bytes = new StreamingMemoryObject(LazyStreamer);
StreamFile.reset(new BitstreamReader(Bytes));
Stream.init(*StreamFile);
unsigned char buf[16];
if (Bytes->readBytes(0, 16, buf, NULL) == -1)
return Error("Bitcode stream must be at least 16 bytes in length");
if (!isBitcode(buf, buf + 16))
return Error("Invalid bitcode signature");
if (isBitcodeWrapper(buf, buf + 4)) {
const unsigned char *bitcodeStart = buf;
const unsigned char *bitcodeEnd = buf + 16;
SkipBitcodeWrapperHeader(bitcodeStart, bitcodeEnd, false);
Bytes->dropLeadingBytes(bitcodeStart - buf);
Bytes->setKnownObjectSize(bitcodeEnd - bitcodeStart);
}
return false;
}
//===----------------------------------------------------------------------===//
// External interface
@ -2833,6 +2890,24 @@ Module *llvm::getLazyBitcodeModule(MemoryBuffer *Buffer,
return M;
}
Module *llvm::getStreamedBitcodeModule(const std::string &name,
DataStreamer *streamer,
LLVMContext &Context,
std::string *ErrMsg) {
Module *M = new Module(name, Context);
BitcodeReader *R = new BitcodeReader(streamer, Context);
M->setMaterializer(R);
if (R->ParseBitcodeInto(M)) {
if (ErrMsg)
*ErrMsg = R->getErrorString();
delete M; // Also deletes R.
return 0;
}
R->setBufferOwned(false); // no buffer to delete
return M;
}
/// ParseBitcodeFile - Read the specified bitcode file, returning the module.
/// If an error occurs, return null and fill in *ErrMsg if non-null.
Module *llvm::ParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext& Context,

View File

@ -126,8 +126,11 @@ class BitcodeReader : public GVMaterializer {
Module *TheModule;
MemoryBuffer *Buffer;
bool BufferOwned;
BitstreamReader StreamFile;
OwningPtr<BitstreamReader> StreamFile;
BitstreamCursor Stream;
DataStreamer *LazyStreamer;
uint64_t NextUnreadBit;
bool SeenValueSymbolTable;
const char *ErrorString;
@ -161,9 +164,10 @@ class BitcodeReader : public GVMaterializer {
// Map the bitcode's custom MDKind ID to the Module's MDKind ID.
DenseMap<unsigned, unsigned> MDKindMap;
// After the module header has been read, the FunctionsWithBodies list is
// reversed. This keeps track of whether we've done this yet.
bool HasReversedFunctionsWithBodies;
// Several operations happen after the module header has been read, but
// before function bodies are processed. This keeps track of whether
// we've done this yet.
bool SeenFirstFunctionBody;
/// DeferredFunctionInfo - When function bodies are initially scanned, this
/// map contains info about where to find deferred function body in the
@ -178,8 +182,13 @@ class BitcodeReader : public GVMaterializer {
public:
explicit BitcodeReader(MemoryBuffer *buffer, LLVMContext &C)
: Context(C), TheModule(0), Buffer(buffer), BufferOwned(false),
ErrorString(0), ValueList(C), MDValueList(C) {
HasReversedFunctionsWithBodies = false;
LazyStreamer(0), SeenValueSymbolTable(false), ErrorString(0),
ValueList(C), MDValueList(C), SeenFirstFunctionBody(false) {
}
explicit BitcodeReader(DataStreamer *streamer, LLVMContext &C)
: Context(C), TheModule(0), Buffer(0), BufferOwned(false),
LazyStreamer(streamer), SeenValueSymbolTable(false), ErrorString(0),
ValueList(C), MDValueList(C), SeenFirstFunctionBody(false) {
}
~BitcodeReader() {
FreeState();
@ -258,7 +267,7 @@ private:
}
bool ParseModule();
bool ParseModule(bool Resume);
bool ParseAttributeBlock();
bool ParseTypeTable();
bool ParseTypeTableBody();
@ -267,11 +276,17 @@ private:
bool ParseConstants();
bool RememberAndSkipFunctionBody();
bool ParseFunctionBody(Function *F);
bool GlobalCleanup();
bool ResolveGlobalAndAliasInits();
bool ParseMetadata();
bool ParseMetadataAttachment();
bool ParseModuleTriple(std::string &Triple);
bool ParseUseLists();
bool InitStream();
bool InitStreamFromBuffer();
bool InitLazyStream();
bool FindFunctionInStream(Function *F,
DenseMap<Function*, uint64_t>::iterator DeferredFunctionInfoIterator);
};
} // End llvm namespace

View File

@ -1738,11 +1738,6 @@ static void WriteModule(const Module *M, BitstreamWriter &Stream) {
// Emit metadata.
WriteModuleMetadata(M, VE, Stream);
// Emit function bodies.
for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F)
if (!F->isDeclaration())
WriteFunction(*F, VE, Stream);
// Emit metadata.
WriteModuleMetadataStore(M, Stream);
@ -1753,6 +1748,11 @@ static void WriteModule(const Module *M, BitstreamWriter &Stream) {
if (EnablePreserveUseListOrdering)
WriteModuleUseLists(M, VE, Stream);
// Emit function bodies.
for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F)
if (!F->isDeclaration())
WriteFunction(*F, VE, Stream);
Stream.ExitBlock();
}

View File

@ -100,9 +100,9 @@ public:
Bytes(bytes), Size(size), BasePC(basePC) {}
uint64_t getBase() const { return BasePC; }
uint64_t getExtent() const { return Size; }
uint64_t getExtent() { return Size; }
int readByte(uint64_t Addr, uint8_t *Byte) const {
int readByte(uint64_t Addr, uint8_t *Byte) {
if (Addr - BasePC >= Size)
return -1;
*Byte = Bytes[Addr - BasePC];

View File

@ -207,8 +207,8 @@ namespace {
void *arg) : Callback(callback), Arg(arg) { }
~EDMemoryObject() { }
uint64_t getBase() const { return 0x0; }
uint64_t getExtent() const { return (uint64_t)-1; }
int readByte(uint64_t address, uint8_t *ptr) const {
uint64_t getExtent() { return (uint64_t)-1; }
int readByte(uint64_t address, uint8_t *ptr) {
if (!Callback)
return -1;

View File

@ -16,6 +16,7 @@ add_llvm_library(LLVMSupport
ConstantRange.cpp
CrashRecoveryContext.cpp
DataExtractor.cpp
DataStream.cpp
Debug.cpp
DeltaAlgorithm.cpp
DAGDeltaAlgorithm.cpp
@ -42,6 +43,7 @@ add_llvm_library(LLVMSupport
SmallVector.cpp
SourceMgr.cpp
Statistic.cpp
StreamableMemoryObject.cpp
StringExtras.cpp
StringMap.cpp
StringPool.cpp

View File

@ -0,0 +1,96 @@
//===--- llvm/Support/DataStream.cpp - Lazy streamed Data ---===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements DataStreamer, which fetches bytes of Data from
// a stream source. It provides support for streaming (lazy reading) of
// bitcode. An example implementation of streaming from a file or stdin
// is included.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "Data-stream"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/DataStream.h"
#include "llvm/Support/system_error.h"
#include <string>
#include <cerrno>
#include <cstdio>
#if !defined(_MSC_VER) && !defined(__MINGW32__)
#include <unistd.h>
#else
#include <io.h>
#endif
#include <fcntl.h>
using namespace llvm;
// Interface goals:
// * StreamableMemoryObject doesn't care about complexities like using
// threads/async callbacks to actually overlap download+compile
// * Don't want to duplicate Data in memory
// * Don't need to know total Data len in advance
// Non-goals:
// StreamableMemoryObject already has random access so this interface only does
// in-order streaming (no arbitrary seeking, else we'd have to buffer all the
// Data here in addition to MemoryObject). This also means that if we want
// to be able to to free Data, BitstreamBytes/BitcodeReader will implement it
STATISTIC(NumStreamFetches, "Number of calls to Data stream fetch");
namespace llvm {
DataStreamer::~DataStreamer() {}
}
namespace {
const static error_code success;
// Very simple stream backed by a file. Mostly useful for stdin and debugging;
// actual file access is probably still best done with mmap.
class DataFileStreamer : public DataStreamer {
int Fd;
public:
DataFileStreamer() : Fd(0) {}
virtual ~DataFileStreamer() {
close(Fd);
}
virtual size_t GetBytes(unsigned char *buf, size_t len) {
NumStreamFetches++;
return read(Fd, buf, len);
}
error_code OpenFile(const std::string &Filename) {
int OpenFlags = O_RDONLY;
#ifdef O_BINARY
OpenFlags |= O_BINARY; // Open input file in binary mode on win32.
#endif
if (Filename == "-")
Fd = 0;
else
Fd = ::open(Filename.c_str(), OpenFlags);
if (Fd == -1) return error_code(errno, posix_category());
return success;
}
};
}
namespace llvm {
DataStreamer *getDataFileStreamer(const std::string &Filename,
std::string *StrError) {
DataFileStreamer *s = new DataFileStreamer();
error_code e = s->OpenFile(Filename);
if (e != success) {
*StrError = std::string("Could not open ") + Filename + ": " +
e.message() + "\n";
return NULL;
}
return s;
}
}

View File

@ -16,7 +16,7 @@ MemoryObject::~MemoryObject() {
int MemoryObject::readBytes(uint64_t address,
uint64_t size,
uint8_t* buf,
uint64_t* copied) const {
uint64_t* copied) {
uint64_t current = address;
uint64_t limit = getBase() + getExtent();

View File

@ -0,0 +1,137 @@
//===- StreamableMemoryObject.cpp - Streamable data interface - -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/StreamableMemoryObject.h"
#include <cassert>
#include <cstring>
using namespace llvm;
namespace {
class RawMemoryObject : public StreamableMemoryObject {
public:
RawMemoryObject(const unsigned char *Start, const unsigned char *End) :
FirstChar(Start), LastChar(End) {
assert(LastChar > FirstChar && "Invalid start/end range");
}
virtual uint64_t getBase() const { return 0; }
virtual uint64_t getExtent() { return LastChar - FirstChar; }
virtual int readByte(uint64_t address, uint8_t* ptr);
virtual int readBytes(uint64_t address,
uint64_t size,
uint8_t* buf,
uint64_t* copied);
virtual const uint8_t *getPointer(uint64_t address, uint64_t size);
virtual bool isValidAddress(uint64_t address) {return validAddress(address);}
virtual bool isObjectEnd(uint64_t address) {return objectEnd(address);}
private:
const uint8_t* const FirstChar;
const uint8_t* const LastChar;
// These are implemented as inline functions here to avoid multiple virtual
// calls per public function
bool validAddress(uint64_t address) {
return static_cast<ptrdiff_t>(address) < LastChar - FirstChar;
}
bool objectEnd(uint64_t address) {
return static_cast<ptrdiff_t>(address) == LastChar - FirstChar;
}
RawMemoryObject(const RawMemoryObject&); // DO NOT IMPLEMENT
void operator=(const RawMemoryObject&); // DO NOT IMPLEMENT
};
int RawMemoryObject::readByte(uint64_t address, uint8_t* ptr) {
if (!validAddress(address)) return -1;
*ptr = *((uint8_t *)(uintptr_t)(address + FirstChar));
return 0;
}
int RawMemoryObject::readBytes(uint64_t address,
uint64_t size,
uint8_t* buf,
uint64_t* copied) {
if (!validAddress(address) || !validAddress(address + size - 1)) return -1;
memcpy(buf, (uint8_t *)(uintptr_t)(address + FirstChar), size);
if (copied) *copied = size;
return size;
}
const uint8_t *RawMemoryObject::getPointer(uint64_t address, uint64_t size) {
return FirstChar + address;
}
} // anonymous namespace
namespace llvm {
// If the bitcode has a header, then its size is known, and we don't have to
// block until we actually want to read it.
bool StreamingMemoryObject::isValidAddress(uint64_t address) {
if (ObjectSize && address < ObjectSize) return true;
return fetchToPos(address);
}
bool StreamingMemoryObject::isObjectEnd(uint64_t address) {
if (ObjectSize) return address == ObjectSize;
fetchToPos(address);
return address == ObjectSize && address != 0;
}
uint64_t StreamingMemoryObject::getExtent() {
if (ObjectSize) return ObjectSize;
size_t pos = BytesRead + kChunkSize;
// keep fetching until we run out of bytes
while (fetchToPos(pos)) pos += kChunkSize;
return ObjectSize;
}
int StreamingMemoryObject::readByte(uint64_t address, uint8_t* ptr) {
if (!fetchToPos(address)) return -1;
*ptr = Bytes[address + BytesSkipped];
return 0;
}
int StreamingMemoryObject::readBytes(uint64_t address,
uint64_t size,
uint8_t* buf,
uint64_t* copied) {
if (!fetchToPos(address + size - 1)) return -1;
memcpy(buf, &Bytes[address + BytesSkipped], size);
if (copied) *copied = size;
return 0;
}
bool StreamingMemoryObject::dropLeadingBytes(size_t s) {
if (BytesRead < s) return true;
BytesSkipped = s;
BytesRead -= s;
return false;
}
void StreamingMemoryObject::setKnownObjectSize(size_t size) {
ObjectSize = size;
Bytes.reserve(size);
}
StreamableMemoryObject *getNonStreamedMemoryObject(
const unsigned char *Start, const unsigned char *End) {
return new RawMemoryObject(Start, End);
}
StreamableMemoryObject::~StreamableMemoryObject() { }
StreamingMemoryObject::StreamingMemoryObject(DataStreamer *streamer) :
Bytes(kChunkSize), Streamer(streamer), BytesRead(0), BytesSkipped(0),
ObjectSize(0), EOFReached(false) {
BytesRead = streamer->GetBytes(&Bytes[0], kChunkSize);
}
}

View File

@ -46,7 +46,7 @@ public:
/// getInstruction - See MCDisassembler.
DecodeStatus getInstruction(MCInst &instr,
uint64_t &size,
const MemoryObject &region,
MemoryObject &region,
uint64_t address,
raw_ostream &vStream,
raw_ostream &cStream) const;
@ -71,7 +71,7 @@ public:
/// getInstruction - See MCDisassembler.
DecodeStatus getInstruction(MCInst &instr,
uint64_t &size,
const MemoryObject &region,
MemoryObject &region,
uint64_t address,
raw_ostream &vStream,
raw_ostream &cStream) const;
@ -341,7 +341,7 @@ EDInstInfo *ThumbDisassembler::getEDInfo() const {
}
DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
const MemoryObject &Region,
MemoryObject &Region,
uint64_t Address,
raw_ostream &os,
raw_ostream &cs) const {
@ -691,7 +691,7 @@ void ThumbDisassembler::UpdateThumbVFPPredicate(MCInst &MI) const {
}
DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
const MemoryObject &Region,
MemoryObject &Region,
uint64_t Address,
raw_ostream &os,
raw_ostream &cs) const {

View File

@ -502,7 +502,7 @@ EDInstInfo *MBlazeDisassembler::getEDInfo() const {
MCDisassembler::DecodeStatus MBlazeDisassembler::getInstruction(MCInst &instr,
uint64_t &size,
const MemoryObject &region,
MemoryObject &region,
uint64_t address,
raw_ostream &vStream,
raw_ostream &cStream) const {

View File

@ -40,7 +40,7 @@ public:
/// getInstruction - See MCDisassembler.
MCDisassembler::DecodeStatus getInstruction(MCInst &instr,
uint64_t &size,
const MemoryObject &region,
MemoryObject &region,
uint64_t address,
raw_ostream &vStream,
raw_ostream &cStream) const;

View File

@ -112,7 +112,7 @@ static void logger(void* arg, const char* log) {
MCDisassembler::DecodeStatus
X86GenericDisassembler::getInstruction(MCInst &instr,
uint64_t &size,
const MemoryObject &region,
MemoryObject &region,
uint64_t address,
raw_ostream &vStream,
raw_ostream &cStream) const {

View File

@ -114,7 +114,7 @@ public:
/// getInstruction - See MCDisassembler.
DecodeStatus getInstruction(MCInst &instr,
uint64_t &size,
const MemoryObject &region,
MemoryObject &region,
uint64_t address,
raw_ostream &vStream,
raw_ostream &cStream) const;

View File

@ -483,13 +483,13 @@ static int AnalyzeBitcode() {
if (MemBuf->getBufferSize() & 3)
return Error("Bitcode stream should be a multiple of 4 bytes in length");
unsigned char *BufPtr = (unsigned char *)MemBuf->getBufferStart();
unsigned char *EndBufPtr = BufPtr+MemBuf->getBufferSize();
const unsigned char *BufPtr = (unsigned char *)MemBuf->getBufferStart();
const unsigned char *EndBufPtr = BufPtr+MemBuf->getBufferSize();
// 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 (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr))
if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr, true))
return Error("Invalid bitcode wrapper header");
BitstreamReader StreamFile(BufPtr, EndBufPtr);

View File

@ -24,6 +24,7 @@
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Assembly/AssemblyAnnotationWriter.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/DataStream.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
@ -126,12 +127,19 @@ int main(int argc, char **argv) {
std::string ErrorMessage;
std::auto_ptr<Module> M;
{
OwningPtr<MemoryBuffer> BufferPtr;
if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr))
ErrorMessage = ec.message();
// Use the bitcode streaming interface
DataStreamer *streamer = getDataFileStreamer(InputFilename, &ErrorMessage);
if (streamer) {
std::string DisplayFilename;
if (InputFilename == "-")
DisplayFilename = "<stdin>";
else
M.reset(ParseBitcodeFile(BufferPtr.get(), Context, &ErrorMessage));
DisplayFilename = InputFilename;
M.reset(getStreamedBitcodeModule(DisplayFilename, streamer, Context,
&ErrorMessage));
if(M.get() != 0 && M->MaterializeAllPermanently(&ErrorMessage)) {
M.reset();
}
}
if (M.get() == 0) {
@ -183,4 +191,3 @@ int main(int argc, char **argv) {
return 0;
}

View File

@ -42,9 +42,9 @@ public:
VectorMemoryObject(const ByteArrayTy &bytes) : Bytes(bytes) {}
uint64_t getBase() const { return 0; }
uint64_t getExtent() const { return Bytes.size(); }
uint64_t getExtent() { return Bytes.size(); }
int readByte(uint64_t Addr, uint8_t *Byte) const {
int readByte(uint64_t Addr, uint8_t *Byte) {
if (Addr >= getExtent())
return -1;
*Byte = Bytes[Addr].first;

View File

@ -28,7 +28,7 @@ using namespace llvm;
MCFunction
MCFunction::createFunctionFromMC(StringRef Name, const MCDisassembler *DisAsm,
const MemoryObject &Region, uint64_t Start,
MemoryObject &Region, uint64_t Start,
uint64_t End, const MCInstrAnalysis *Ana,
raw_ostream &DebugOut,
SmallVectorImpl<uint64_t> &Calls) {

View File

@ -79,7 +79,7 @@ public:
// Create an MCFunction from a region of binary machine code.
static MCFunction
createFunctionFromMC(StringRef Name, const MCDisassembler *DisAsm,
const MemoryObject &Region, uint64_t Start, uint64_t End,
MemoryObject &Region, uint64_t Start, uint64_t End,
const MCInstrAnalysis *Ana, raw_ostream &DebugOut,
SmallVectorImpl<uint64_t> &Calls);

View File

@ -31,9 +31,9 @@ public:
StringRefMemoryObject(StringRef bytes) : Bytes(bytes) {}
uint64_t getBase() const { return 0; }
uint64_t getExtent() const { return Bytes.size(); }
uint64_t getExtent() { return Bytes.size(); }
int readByte(uint64_t Addr, uint8_t *Byte) const {
int readByte(uint64_t Addr, uint8_t *Byte) {
if (Addr >= getExtent())
return -1;
*Byte = Bytes[Addr];