forked from OSchip/llvm-project
Bitcode: Change reader interface to take memory buffers.
As proposed on llvm-dev: http://lists.llvm.org/pipermail/llvm-dev/2016-October/106595.html This change also fixes an API oddity where BitstreamCursor::Read() would return zero for the first read past the end of the bitstream, but would report_fatal_error for subsequent reads. Now we always report_fatal_error for all reads past the end. Updated clients to check for the end of the bitstream before reading from it. I also needed to add padding to the invalid bitcode tests in test/Bitcode/. This is because the streaming interface was not checking that the file size is a multiple of 4. Differential Revision: https://reviews.llvm.org/D26219 llvm-svn: 285773
This commit is contained in:
parent
ce898dbb81
commit
028eb5a3f8
|
@ -325,8 +325,8 @@ void ObjectFilePCHContainerReader::ExtractPCH(
|
||||||
if ((!IsCOFF && Name == "__clangast") || (IsCOFF && Name == "clangast")) {
|
if ((!IsCOFF && Name == "__clangast") || (IsCOFF && Name == "clangast")) {
|
||||||
StringRef Buf;
|
StringRef Buf;
|
||||||
Section.getContents(Buf);
|
Section.getContents(Buf);
|
||||||
return StreamFile.init((const unsigned char *)Buf.begin(),
|
StreamFile = llvm::BitstreamReader(Buf);
|
||||||
(const unsigned char *)Buf.end());
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -334,8 +334,7 @@ void ObjectFilePCHContainerReader::ExtractPCH(
|
||||||
if (EIB.convertToErrorCode() ==
|
if (EIB.convertToErrorCode() ==
|
||||||
llvm::object::object_error::invalid_file_type)
|
llvm::object::object_error::invalid_file_type)
|
||||||
// As a fallback, treat the buffer as a raw AST.
|
// As a fallback, treat the buffer as a raw AST.
|
||||||
StreamFile.init((const unsigned char *)Buffer.getBufferStart(),
|
StreamFile = llvm::BitstreamReader(Buffer);
|
||||||
(const unsigned char *)Buffer.getBufferEnd());
|
|
||||||
else
|
else
|
||||||
EIB.log(llvm::errs());
|
EIB.log(llvm::errs());
|
||||||
});
|
});
|
||||||
|
|
|
@ -60,8 +60,7 @@ std::unique_ptr<ASTConsumer> RawPCHContainerWriter::CreatePCHContainerGenerator(
|
||||||
|
|
||||||
void RawPCHContainerReader::ExtractPCH(
|
void RawPCHContainerReader::ExtractPCH(
|
||||||
llvm::MemoryBufferRef Buffer, llvm::BitstreamReader &StreamFile) const {
|
llvm::MemoryBufferRef Buffer, llvm::BitstreamReader &StreamFile) const {
|
||||||
StreamFile.init((const unsigned char *)Buffer.getBufferStart(),
|
StreamFile = llvm::BitstreamReader(Buffer);
|
||||||
(const unsigned char *)Buffer.getBufferEnd());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PCHContainerOperations::PCHContainerOperations() {
|
PCHContainerOperations::PCHContainerOperations() {
|
||||||
|
|
|
@ -24,10 +24,7 @@ std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) {
|
||||||
if (!Buffer)
|
if (!Buffer)
|
||||||
return SDError::CouldNotLoad;
|
return SDError::CouldNotLoad;
|
||||||
|
|
||||||
llvm::BitstreamReader StreamFile;
|
llvm::BitstreamReader StreamFile(**Buffer);
|
||||||
StreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(),
|
|
||||||
(const unsigned char *)(*Buffer)->getBufferEnd());
|
|
||||||
|
|
||||||
llvm::BitstreamCursor Stream(StreamFile);
|
llvm::BitstreamCursor Stream(StreamFile);
|
||||||
|
|
||||||
// Sniff for the signature.
|
// Sniff for the signature.
|
||||||
|
|
|
@ -3802,7 +3802,8 @@ static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile);
|
||||||
|
|
||||||
/// \brief Whether \p Stream starts with the AST/PCH file magic number 'CPCH'.
|
/// \brief Whether \p Stream starts with the AST/PCH file magic number 'CPCH'.
|
||||||
static bool startsWithASTFileMagic(BitstreamCursor &Stream) {
|
static bool startsWithASTFileMagic(BitstreamCursor &Stream) {
|
||||||
return Stream.Read(8) == 'C' &&
|
return Stream.canSkipToPos(4) &&
|
||||||
|
Stream.Read(8) == 'C' &&
|
||||||
Stream.Read(8) == 'P' &&
|
Stream.Read(8) == 'P' &&
|
||||||
Stream.Read(8) == 'C' &&
|
Stream.Read(8) == 'C' &&
|
||||||
Stream.Read(8) == 'H';
|
Stream.Read(8) == 'H';
|
||||||
|
|
|
@ -246,8 +246,7 @@ GlobalModuleIndex::readIndex(StringRef Path) {
|
||||||
std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(BufferOrErr.get());
|
std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(BufferOrErr.get());
|
||||||
|
|
||||||
/// \brief The bitstream reader from which we'll read the AST file.
|
/// \brief The bitstream reader from which we'll read the AST file.
|
||||||
llvm::BitstreamReader Reader((const unsigned char *)Buffer->getBufferStart(),
|
llvm::BitstreamReader Reader(*Buffer);
|
||||||
(const unsigned char *)Buffer->getBufferEnd());
|
|
||||||
|
|
||||||
/// \brief The main bitstream cursor for the main block.
|
/// \brief The main bitstream cursor for the main block.
|
||||||
llvm::BitstreamCursor Cursor(Reader);
|
llvm::BitstreamCursor Cursor(Reader);
|
||||||
|
|
|
@ -15,13 +15,14 @@
|
||||||
#ifndef LLVM_BITCODE_BITSTREAMREADER_H
|
#ifndef LLVM_BITCODE_BITSTREAMREADER_H
|
||||||
#define LLVM_BITCODE_BITSTREAMREADER_H
|
#define LLVM_BITCODE_BITSTREAMREADER_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/Bitcode/BitCodes.h"
|
#include "llvm/Bitcode/BitCodes.h"
|
||||||
#include "llvm/Support/Endian.h"
|
#include "llvm/Support/Endian.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/MathExtras.h"
|
#include "llvm/Support/MathExtras.h"
|
||||||
#include "llvm/Support/StreamingMemoryObject.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
@ -50,32 +51,25 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<MemoryObject> BitcodeBytes;
|
ArrayRef<uint8_t> BitcodeBytes;
|
||||||
|
|
||||||
std::vector<BlockInfo> BlockInfoRecords;
|
std::vector<BlockInfo> BlockInfoRecords;
|
||||||
|
|
||||||
/// This is set to true if we don't care about the block/record name
|
/// This is set to true if we don't care about the block/record name
|
||||||
/// information in the BlockInfo block. Only llvm-bcanalyzer uses this.
|
/// information in the BlockInfo block. Only llvm-bcanalyzer uses this.
|
||||||
bool IgnoreBlockInfoNames;
|
bool IgnoreBlockInfoNames = true;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BitstreamReader() : IgnoreBlockInfoNames(true) {
|
BitstreamReader() = default;
|
||||||
}
|
BitstreamReader(ArrayRef<uint8_t> BitcodeBytes)
|
||||||
|
: BitcodeBytes(BitcodeBytes) {}
|
||||||
|
BitstreamReader(StringRef BitcodeBytes)
|
||||||
|
: BitcodeBytes(reinterpret_cast<const uint8_t *>(BitcodeBytes.data()),
|
||||||
|
BitcodeBytes.size()) {}
|
||||||
|
BitstreamReader(MemoryBufferRef BitcodeBytes)
|
||||||
|
: BitstreamReader(BitcodeBytes.getBuffer()) {}
|
||||||
|
|
||||||
BitstreamReader(const unsigned char *Start, const unsigned char *End)
|
ArrayRef<uint8_t> getBitcodeBytes() { return BitcodeBytes; }
|
||||||
: IgnoreBlockInfoNames(true) {
|
|
||||||
init(Start, End);
|
|
||||||
}
|
|
||||||
|
|
||||||
BitstreamReader(std::unique_ptr<MemoryObject> BitcodeBytes)
|
|
||||||
: BitcodeBytes(std::move(BitcodeBytes)), IgnoreBlockInfoNames(true) {}
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryObject &getBitcodeBytes() { return *BitcodeBytes; }
|
|
||||||
|
|
||||||
/// This is called by clients that want block/record name information.
|
/// This is called by clients that want block/record name information.
|
||||||
void CollectBlockInfoNames() { IgnoreBlockInfoNames = false; }
|
void CollectBlockInfoNames() { IgnoreBlockInfoNames = false; }
|
||||||
|
@ -131,9 +125,6 @@ class SimpleBitstreamCursor {
|
||||||
BitstreamReader *R = nullptr;
|
BitstreamReader *R = nullptr;
|
||||||
size_t NextChar = 0;
|
size_t NextChar = 0;
|
||||||
|
|
||||||
// The size of the bicode. 0 if we don't know it yet.
|
|
||||||
size_t Size = 0;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// This is the current data we have pulled from the stream but have not
|
/// This is the current data we have pulled from the stream but have not
|
||||||
/// returned to the client. This is specifically and intentionally defined to
|
/// returned to the client. This is specifically and intentionally defined to
|
||||||
|
@ -159,17 +150,11 @@ public:
|
||||||
|
|
||||||
bool canSkipToPos(size_t pos) const {
|
bool canSkipToPos(size_t pos) const {
|
||||||
// pos can be skipped to if it is a valid address or one byte past the end.
|
// pos can be skipped to if it is a valid address or one byte past the end.
|
||||||
return pos == 0 ||
|
return pos <= R->getBitcodeBytes().size();
|
||||||
R->getBitcodeBytes().isValidAddress(static_cast<uint64_t>(pos - 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AtEndOfStream() {
|
bool AtEndOfStream() {
|
||||||
if (BitsInCurWord != 0)
|
return BitsInCurWord == 0 && R->getBitcodeBytes().size() <= NextChar;
|
||||||
return false;
|
|
||||||
if (Size != 0)
|
|
||||||
return Size <= NextChar;
|
|
||||||
fillCurWord();
|
|
||||||
return BitsInCurWord == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the bit # of the bit we are reading.
|
/// Return the bit # of the bit we are reading.
|
||||||
|
@ -218,7 +203,7 @@ public:
|
||||||
|
|
||||||
/// Get a pointer into the bitstream at the specified byte offset.
|
/// Get a pointer into the bitstream at the specified byte offset.
|
||||||
const uint8_t *getPointerToByte(uint64_t ByteNo, uint64_t NumBytes) {
|
const uint8_t *getPointerToByte(uint64_t ByteNo, uint64_t NumBytes) {
|
||||||
return R->getBitcodeBytes().getPointer(ByteNo, NumBytes);
|
return R->getBitcodeBytes().data() + ByteNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a pointer into the bitstream at the specified bit offset.
|
/// Get a pointer into the bitstream at the specified bit offset.
|
||||||
|
@ -230,26 +215,25 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void fillCurWord() {
|
void fillCurWord() {
|
||||||
if (Size != 0 && NextChar >= Size)
|
ArrayRef<uint8_t> Buf = R->getBitcodeBytes();
|
||||||
|
if (NextChar >= Buf.size())
|
||||||
report_fatal_error("Unexpected end of file");
|
report_fatal_error("Unexpected end of file");
|
||||||
|
|
||||||
// Read the next word from the stream.
|
// Read the next word from the stream.
|
||||||
uint8_t Array[sizeof(word_t)] = {0};
|
const uint8_t *NextCharPtr = Buf.data() + NextChar;
|
||||||
|
unsigned BytesRead;
|
||||||
uint64_t BytesRead =
|
if (Buf.size() >= NextChar + sizeof(word_t)) {
|
||||||
R->getBitcodeBytes().readBytes(Array, sizeof(Array), NextChar);
|
BytesRead = sizeof(word_t);
|
||||||
|
CurWord =
|
||||||
// If we run out of data, stop at the end of the stream.
|
support::endian::read<word_t, support::little, support::unaligned>(
|
||||||
if (BytesRead == 0) {
|
NextCharPtr);
|
||||||
|
} else {
|
||||||
|
// Short read.
|
||||||
|
BytesRead = Buf.size() - NextChar;
|
||||||
CurWord = 0;
|
CurWord = 0;
|
||||||
BitsInCurWord = 0;
|
for (unsigned B = 0; B != BytesRead; ++B)
|
||||||
Size = NextChar;
|
CurWord |= NextCharPtr[B] << (B * 8);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CurWord =
|
|
||||||
support::endian::read<word_t, support::little, support::unaligned>(
|
|
||||||
Array);
|
|
||||||
NextChar += BytesRead;
|
NextChar += BytesRead;
|
||||||
BitsInCurWord = BytesRead * 8;
|
BitsInCurWord = BytesRead * 8;
|
||||||
}
|
}
|
||||||
|
@ -278,9 +262,9 @@ public:
|
||||||
|
|
||||||
fillCurWord();
|
fillCurWord();
|
||||||
|
|
||||||
// If we run out of data, stop at the end of the stream.
|
// If we run out of data, abort.
|
||||||
if (BitsLeft > BitsInCurWord)
|
if (BitsLeft > BitsInCurWord)
|
||||||
return 0;
|
report_fatal_error("Unexpected end of file");
|
||||||
|
|
||||||
word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft));
|
word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft));
|
||||||
|
|
||||||
|
@ -346,31 +330,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Skip to the end of the file.
|
/// Skip to the end of the file.
|
||||||
void skipToEnd() { NextChar = R->getBitcodeBytes().getExtent(); }
|
void skipToEnd() { NextChar = R->getBitcodeBytes().size(); }
|
||||||
|
|
||||||
/// Prevent the cursor from reading past a byte boundary.
|
|
||||||
///
|
|
||||||
/// Prevent the cursor from requesting byte reads past \c Limit. This is
|
|
||||||
/// useful when working with a cursor on a StreamingMemoryObject, when it's
|
|
||||||
/// desirable to avoid invalidating the result of getPointerToByte().
|
|
||||||
///
|
|
||||||
/// If \c Limit is on a word boundary, AtEndOfStream() will return true if
|
|
||||||
/// the cursor position reaches or exceeds \c Limit, regardless of the true
|
|
||||||
/// number of available bytes. Otherwise, AtEndOfStream() returns true when
|
|
||||||
/// it reaches or exceeds the next word boundary.
|
|
||||||
void setArtificialByteLimit(uint64_t Limit) {
|
|
||||||
assert(getCurrentByteNo() < Limit && "Move cursor before lowering limit");
|
|
||||||
|
|
||||||
// Round to word boundary.
|
|
||||||
Limit = alignTo(Limit, sizeof(word_t));
|
|
||||||
|
|
||||||
// Only change size if the new one is lower.
|
|
||||||
if (!Size || Size > Limit)
|
|
||||||
Size = Limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the Size, if known.
|
|
||||||
uint64_t getSizeIfKnown() const { return Size; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// When advancing through a bitstream cursor, each advance can discover a few
|
/// When advancing through a bitstream cursor, each advance can discover a few
|
||||||
|
@ -470,6 +430,9 @@ public:
|
||||||
/// Advance the current bitstream, returning the next entry in the stream.
|
/// Advance the current bitstream, returning the next entry in the stream.
|
||||||
BitstreamEntry advance(unsigned Flags = 0) {
|
BitstreamEntry advance(unsigned Flags = 0) {
|
||||||
while (true) {
|
while (true) {
|
||||||
|
if (AtEndOfStream())
|
||||||
|
return BitstreamEntry::getError();
|
||||||
|
|
||||||
unsigned Code = ReadCode();
|
unsigned Code = ReadCode();
|
||||||
if (Code == bitc::END_BLOCK) {
|
if (Code == bitc::END_BLOCK) {
|
||||||
// Pop the end of the block unless Flags tells us not to.
|
// Pop the end of the block unless Flags tells us not to.
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class BitstreamWriter;
|
class BitstreamWriter;
|
||||||
class DataStreamer;
|
|
||||||
class LLVMContext;
|
class LLVMContext;
|
||||||
class Module;
|
class Module;
|
||||||
class ModulePass;
|
class ModulePass;
|
||||||
|
@ -47,13 +46,6 @@ namespace llvm {
|
||||||
LLVMContext &Context,
|
LLVMContext &Context,
|
||||||
bool ShouldLazyLoadMetadata = false);
|
bool ShouldLazyLoadMetadata = false);
|
||||||
|
|
||||||
/// Read the header of the specified stream and prepare for lazy
|
|
||||||
/// deserialization and streaming of function bodies.
|
|
||||||
ErrorOr<std::unique_ptr<Module>>
|
|
||||||
getStreamedBitcodeModule(StringRef Name,
|
|
||||||
std::unique_ptr<DataStreamer> Streamer,
|
|
||||||
LLVMContext &Context);
|
|
||||||
|
|
||||||
/// Read the header of the specified bitcode buffer and extract just the
|
/// Read the header of the specified bitcode buffer and extract just the
|
||||||
/// triple information. If successful, this returns a string. On error, this
|
/// triple information. If successful, this returns a string. On error, this
|
||||||
/// returns "".
|
/// returns "".
|
||||||
|
|
|
@ -61,14 +61,12 @@
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
#include "llvm/Support/DataStream.h"
|
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/ErrorOr.h"
|
#include "llvm/Support/ErrorOr.h"
|
||||||
#include "llvm/Support/ManagedStatic.h"
|
#include "llvm/Support/ManagedStatic.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include "llvm/Support/StreamingMemoryObject.h"
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
@ -232,29 +230,19 @@ private:
|
||||||
|
|
||||||
class BitcodeReaderBase {
|
class BitcodeReaderBase {
|
||||||
protected:
|
protected:
|
||||||
BitcodeReaderBase() = default;
|
|
||||||
BitcodeReaderBase(MemoryBuffer *Buffer) : Buffer(Buffer) {}
|
BitcodeReaderBase(MemoryBuffer *Buffer) : Buffer(Buffer) {}
|
||||||
|
|
||||||
std::unique_ptr<MemoryBuffer> Buffer;
|
std::unique_ptr<MemoryBuffer> Buffer;
|
||||||
std::unique_ptr<BitstreamReader> StreamFile;
|
std::unique_ptr<BitstreamReader> StreamFile;
|
||||||
BitstreamCursor Stream;
|
BitstreamCursor Stream;
|
||||||
|
|
||||||
std::error_code initStream(std::unique_ptr<DataStreamer> Streamer);
|
std::error_code initStream();
|
||||||
std::error_code initStreamFromBuffer();
|
|
||||||
std::error_code initLazyStream(std::unique_ptr<DataStreamer> Streamer);
|
|
||||||
|
|
||||||
virtual std::error_code error(const Twine &Message) = 0;
|
virtual std::error_code error(const Twine &Message) = 0;
|
||||||
virtual ~BitcodeReaderBase() = default;
|
virtual ~BitcodeReaderBase() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::error_code
|
std::error_code BitcodeReaderBase::initStream() {
|
||||||
BitcodeReaderBase::initStream(std::unique_ptr<DataStreamer> Streamer) {
|
|
||||||
if (Streamer)
|
|
||||||
return initLazyStream(std::move(Streamer));
|
|
||||||
return initStreamFromBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::error_code BitcodeReaderBase::initStreamFromBuffer() {
|
|
||||||
const unsigned char *BufPtr = (const unsigned char*)Buffer->getBufferStart();
|
const unsigned char *BufPtr = (const unsigned char*)Buffer->getBufferStart();
|
||||||
const unsigned char *BufEnd = BufPtr+Buffer->getBufferSize();
|
const unsigned char *BufEnd = BufPtr+Buffer->getBufferSize();
|
||||||
|
|
||||||
|
@ -267,39 +255,12 @@ std::error_code BitcodeReaderBase::initStreamFromBuffer() {
|
||||||
if (SkipBitcodeWrapperHeader(BufPtr, BufEnd, true))
|
if (SkipBitcodeWrapperHeader(BufPtr, BufEnd, true))
|
||||||
return error("Invalid bitcode wrapper header");
|
return error("Invalid bitcode wrapper header");
|
||||||
|
|
||||||
StreamFile.reset(new BitstreamReader(BufPtr, BufEnd));
|
StreamFile.reset(new BitstreamReader(ArrayRef<uint8_t>(BufPtr, BufEnd)));
|
||||||
Stream.init(&*StreamFile);
|
Stream.init(&*StreamFile);
|
||||||
|
|
||||||
return std::error_code();
|
return std::error_code();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::error_code
|
|
||||||
BitcodeReaderBase::initLazyStream(std::unique_ptr<DataStreamer> Streamer) {
|
|
||||||
// Check and strip off the bitcode wrapper; BitstreamReader expects never to
|
|
||||||
// see it.
|
|
||||||
auto OwnedBytes =
|
|
||||||
llvm::make_unique<StreamingMemoryObject>(std::move(Streamer));
|
|
||||||
StreamingMemoryObject &Bytes = *OwnedBytes;
|
|
||||||
StreamFile = llvm::make_unique<BitstreamReader>(std::move(OwnedBytes));
|
|
||||||
Stream.init(&*StreamFile);
|
|
||||||
|
|
||||||
unsigned char buf[16];
|
|
||||||
if (Bytes.readBytes(buf, 16, 0) != 16)
|
|
||||||
return error("Invalid bitcode signature");
|
|
||||||
|
|
||||||
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 std::error_code();
|
|
||||||
}
|
|
||||||
|
|
||||||
class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
|
class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
|
||||||
LLVMContext &Context;
|
LLVMContext &Context;
|
||||||
Module *TheModule = nullptr;
|
Module *TheModule = nullptr;
|
||||||
|
@ -399,7 +360,6 @@ public:
|
||||||
std::error_code error(const Twine &Message) override;
|
std::error_code error(const Twine &Message) override;
|
||||||
|
|
||||||
BitcodeReader(MemoryBuffer *Buffer, LLVMContext &Context);
|
BitcodeReader(MemoryBuffer *Buffer, LLVMContext &Context);
|
||||||
BitcodeReader(LLVMContext &Context);
|
|
||||||
~BitcodeReader() override { freeState(); }
|
~BitcodeReader() override { freeState(); }
|
||||||
|
|
||||||
std::error_code materializeForwardReferencedFunctions();
|
std::error_code materializeForwardReferencedFunctions();
|
||||||
|
@ -414,8 +374,7 @@ public:
|
||||||
|
|
||||||
/// \brief Main interface to parsing a bitcode buffer.
|
/// \brief Main interface to parsing a bitcode buffer.
|
||||||
/// \returns true if an error occurred.
|
/// \returns true if an error occurred.
|
||||||
std::error_code parseBitcodeInto(std::unique_ptr<DataStreamer> Streamer,
|
std::error_code parseBitcodeInto(Module *M,
|
||||||
Module *M,
|
|
||||||
bool ShouldLazyLoadMetadata = false);
|
bool ShouldLazyLoadMetadata = false);
|
||||||
|
|
||||||
/// \brief Cheap mechanism to just extract module triple
|
/// \brief Cheap mechanism to just extract module triple
|
||||||
|
@ -638,8 +597,7 @@ public:
|
||||||
|
|
||||||
/// \brief Main interface to parsing a bitcode buffer.
|
/// \brief Main interface to parsing a bitcode buffer.
|
||||||
/// \returns true if an error occurred.
|
/// \returns true if an error occurred.
|
||||||
std::error_code parseSummaryIndexInto(std::unique_ptr<DataStreamer> Streamer,
|
std::error_code parseSummaryIndexInto(ModuleSummaryIndex *I);
|
||||||
ModuleSummaryIndex *I);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::error_code parseModule();
|
std::error_code parseModule();
|
||||||
|
@ -706,9 +664,6 @@ BitcodeReader::BitcodeReader(MemoryBuffer *Buffer, LLVMContext &Context)
|
||||||
: BitcodeReaderBase(Buffer), Context(Context), ValueList(Context),
|
: BitcodeReaderBase(Buffer), Context(Context), ValueList(Context),
|
||||||
MetadataList(Context) {}
|
MetadataList(Context) {}
|
||||||
|
|
||||||
BitcodeReader::BitcodeReader(LLVMContext &Context)
|
|
||||||
: Context(Context), ValueList(Context), MetadataList(Context) {}
|
|
||||||
|
|
||||||
std::error_code BitcodeReader::materializeForwardReferencedFunctions() {
|
std::error_code BitcodeReader::materializeForwardReferencedFunctions() {
|
||||||
if (WillMaterializeAllForwardRefs)
|
if (WillMaterializeAllForwardRefs)
|
||||||
return std::error_code();
|
return std::error_code();
|
||||||
|
@ -2166,10 +2121,6 @@ std::error_code BitcodeReader::parseMetadataStrings(ArrayRef<uint64_t> Record,
|
||||||
SimpleBitstreamCursor R(*StreamFile);
|
SimpleBitstreamCursor R(*StreamFile);
|
||||||
R.jumpToPointer(Lengths.begin());
|
R.jumpToPointer(Lengths.begin());
|
||||||
|
|
||||||
// Ensure that Blob doesn't get invalidated, even if this is reading from
|
|
||||||
// a StreamingMemoryObject with corrupt data.
|
|
||||||
R.setArtificialByteLimit(R.getCurrentByteNo() + StringsOffset);
|
|
||||||
|
|
||||||
StringRef Strings = Blob.drop_front(StringsOffset);
|
StringRef Strings = Blob.drop_front(StringsOffset);
|
||||||
do {
|
do {
|
||||||
if (R.AtEndOfStream())
|
if (R.AtEndOfStream())
|
||||||
|
@ -4203,12 +4154,11 @@ static bool hasValidBitcodeHeader(BitstreamCursor &Stream) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::error_code
|
std::error_code BitcodeReader::parseBitcodeInto(Module *M,
|
||||||
BitcodeReader::parseBitcodeInto(std::unique_ptr<DataStreamer> Streamer,
|
bool ShouldLazyLoadMetadata) {
|
||||||
Module *M, bool ShouldLazyLoadMetadata) {
|
|
||||||
TheModule = M;
|
TheModule = M;
|
||||||
|
|
||||||
if (std::error_code EC = initStream(std::move(Streamer)))
|
if (std::error_code EC = initStream())
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
// Sniff for the signature.
|
// Sniff for the signature.
|
||||||
|
@ -4282,7 +4232,7 @@ ErrorOr<std::string> BitcodeReader::parseModuleTriple() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<std::string> BitcodeReader::parseTriple() {
|
ErrorOr<std::string> BitcodeReader::parseTriple() {
|
||||||
if (std::error_code EC = initStream(nullptr))
|
if (std::error_code EC = initStream())
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
// Sniff for the signature.
|
// Sniff for the signature.
|
||||||
|
@ -4317,7 +4267,7 @@ ErrorOr<std::string> BitcodeReader::parseTriple() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<std::string> BitcodeReader::parseIdentificationBlock() {
|
ErrorOr<std::string> BitcodeReader::parseIdentificationBlock() {
|
||||||
if (std::error_code EC = initStream(nullptr))
|
if (std::error_code EC = initStream())
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
// Sniff for the signature.
|
// Sniff for the signature.
|
||||||
|
@ -4367,7 +4317,7 @@ std::error_code BitcodeReader::parseGlobalObjectAttachment(
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<bool> BitcodeReader::hasObjCCategory() {
|
ErrorOr<bool> BitcodeReader::hasObjCCategory() {
|
||||||
if (std::error_code EC = initStream(nullptr))
|
if (std::error_code EC = initStream())
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
// Sniff for the signature.
|
// Sniff for the signature.
|
||||||
|
@ -5955,7 +5905,8 @@ std::error_code ModuleSummaryIndexBitcodeReader::error(const Twine &Message) {
|
||||||
ModuleSummaryIndexBitcodeReader::ModuleSummaryIndexBitcodeReader(
|
ModuleSummaryIndexBitcodeReader::ModuleSummaryIndexBitcodeReader(
|
||||||
MemoryBuffer *Buffer, DiagnosticHandlerFunction DiagnosticHandler,
|
MemoryBuffer *Buffer, DiagnosticHandlerFunction DiagnosticHandler,
|
||||||
bool CheckGlobalValSummaryPresenceOnly)
|
bool CheckGlobalValSummaryPresenceOnly)
|
||||||
: BitcodeReaderBase(Buffer), DiagnosticHandler(std::move(DiagnosticHandler)),
|
: BitcodeReaderBase(Buffer),
|
||||||
|
DiagnosticHandler(std::move(DiagnosticHandler)),
|
||||||
CheckGlobalValSummaryPresenceOnly(CheckGlobalValSummaryPresenceOnly) {}
|
CheckGlobalValSummaryPresenceOnly(CheckGlobalValSummaryPresenceOnly) {}
|
||||||
|
|
||||||
void ModuleSummaryIndexBitcodeReader::freeState() { Buffer = nullptr; }
|
void ModuleSummaryIndexBitcodeReader::freeState() { Buffer = nullptr; }
|
||||||
|
@ -6555,11 +6506,11 @@ std::error_code ModuleSummaryIndexBitcodeReader::parseModuleStringTable() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the function info index from the bitcode streamer into the given index.
|
// Parse the function info index from the bitcode streamer into the given index.
|
||||||
std::error_code ModuleSummaryIndexBitcodeReader::parseSummaryIndexInto(
|
std::error_code
|
||||||
std::unique_ptr<DataStreamer> Streamer, ModuleSummaryIndex *I) {
|
ModuleSummaryIndexBitcodeReader::parseSummaryIndexInto(ModuleSummaryIndex *I) {
|
||||||
TheIndex = I;
|
TheIndex = I;
|
||||||
|
|
||||||
if (std::error_code EC = initStream(std::move(Streamer)))
|
if (std::error_code EC = initStream())
|
||||||
return EC;
|
return EC;
|
||||||
|
|
||||||
// Sniff for the signature.
|
// Sniff for the signature.
|
||||||
|
@ -6624,8 +6575,7 @@ const std::error_category &llvm::BitcodeErrorCategory() {
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
static ErrorOr<std::unique_ptr<Module>>
|
static ErrorOr<std::unique_ptr<Module>>
|
||||||
getBitcodeModuleImpl(std::unique_ptr<DataStreamer> Streamer, StringRef Name,
|
getBitcodeModuleImpl(StringRef Name, BitcodeReader *R, LLVMContext &Context,
|
||||||
BitcodeReader *R, LLVMContext &Context,
|
|
||||||
bool MaterializeAll, bool ShouldLazyLoadMetadata) {
|
bool MaterializeAll, bool ShouldLazyLoadMetadata) {
|
||||||
std::unique_ptr<Module> M = llvm::make_unique<Module>(Name, Context);
|
std::unique_ptr<Module> M = llvm::make_unique<Module>(Name, Context);
|
||||||
M->setMaterializer(R);
|
M->setMaterializer(R);
|
||||||
|
@ -6636,8 +6586,7 @@ getBitcodeModuleImpl(std::unique_ptr<DataStreamer> Streamer, StringRef Name,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Delay parsing Metadata if ShouldLazyLoadMetadata is true.
|
// Delay parsing Metadata if ShouldLazyLoadMetadata is true.
|
||||||
if (std::error_code EC = R->parseBitcodeInto(std::move(Streamer), M.get(),
|
if (std::error_code EC = R->parseBitcodeInto(M.get(), ShouldLazyLoadMetadata))
|
||||||
ShouldLazyLoadMetadata))
|
|
||||||
return cleanupOnError(EC);
|
return cleanupOnError(EC);
|
||||||
|
|
||||||
if (MaterializeAll) {
|
if (MaterializeAll) {
|
||||||
|
@ -6667,7 +6616,7 @@ getLazyBitcodeModuleImpl(std::unique_ptr<MemoryBuffer> &&Buffer,
|
||||||
BitcodeReader *R = new BitcodeReader(Buffer.get(), Context);
|
BitcodeReader *R = new BitcodeReader(Buffer.get(), Context);
|
||||||
|
|
||||||
ErrorOr<std::unique_ptr<Module>> Ret =
|
ErrorOr<std::unique_ptr<Module>> Ret =
|
||||||
getBitcodeModuleImpl(nullptr, Buffer->getBufferIdentifier(), R, Context,
|
getBitcodeModuleImpl(Buffer->getBufferIdentifier(), R, Context,
|
||||||
MaterializeAll, ShouldLazyLoadMetadata);
|
MaterializeAll, ShouldLazyLoadMetadata);
|
||||||
if (!Ret)
|
if (!Ret)
|
||||||
return Ret;
|
return Ret;
|
||||||
|
@ -6683,17 +6632,6 @@ llvm::getLazyBitcodeModule(std::unique_ptr<MemoryBuffer> &&Buffer,
|
||||||
ShouldLazyLoadMetadata);
|
ShouldLazyLoadMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<std::unique_ptr<Module>>
|
|
||||||
llvm::getStreamedBitcodeModule(StringRef Name,
|
|
||||||
std::unique_ptr<DataStreamer> Streamer,
|
|
||||||
LLVMContext &Context) {
|
|
||||||
std::unique_ptr<Module> M = llvm::make_unique<Module>(Name, Context);
|
|
||||||
BitcodeReader *R = new BitcodeReader(Context);
|
|
||||||
|
|
||||||
return getBitcodeModuleImpl(std::move(Streamer), Name, R, Context, false,
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorOr<std::unique_ptr<Module>> llvm::parseBitcodeFile(MemoryBufferRef Buffer,
|
ErrorOr<std::unique_ptr<Module>> llvm::parseBitcodeFile(MemoryBufferRef Buffer,
|
||||||
LLVMContext &Context) {
|
LLVMContext &Context) {
|
||||||
std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);
|
std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);
|
||||||
|
@ -6746,7 +6684,7 @@ ErrorOr<std::unique_ptr<ModuleSummaryIndex>> llvm::getModuleSummaryIndex(
|
||||||
return EC;
|
return EC;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (std::error_code EC = R.parseSummaryIndexInto(nullptr, Index.get()))
|
if (std::error_code EC = R.parseSummaryIndexInto(Index.get()))
|
||||||
return cleanupOnError(EC);
|
return cleanupOnError(EC);
|
||||||
|
|
||||||
Buf.release(); // The ModuleSummaryIndexBitcodeReader owns it now.
|
Buf.release(); // The ModuleSummaryIndexBitcodeReader owns it now.
|
||||||
|
@ -6765,7 +6703,7 @@ bool llvm::hasGlobalValueSummary(
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (std::error_code EC = R.parseSummaryIndexInto(nullptr, nullptr))
|
if (std::error_code EC = R.parseSummaryIndexInto(nullptr))
|
||||||
return cleanupOnError(EC);
|
return cleanupOnError(EC);
|
||||||
|
|
||||||
Buf.release(); // The ModuleSummaryIndexBitcodeReader owns it now.
|
Buf.release(); // The ModuleSummaryIndexBitcodeReader owns it now.
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1 +1 @@
|
||||||
BCダ!00000000000000000000
|
BCダ!000000000000000000000
|
|
@ -436,10 +436,6 @@ static bool decodeMetadataStringsBlob(BitstreamReader &Reader, StringRef Indent,
|
||||||
SimpleBitstreamCursor R(Reader);
|
SimpleBitstreamCursor R(Reader);
|
||||||
R.jumpToPointer(Lengths.begin());
|
R.jumpToPointer(Lengths.begin());
|
||||||
|
|
||||||
// Ensure that Blob doesn't get invalidated, even if this is reading from a
|
|
||||||
// StreamingMemoryObject with corrupt data.
|
|
||||||
R.setArtificialByteLimit(R.getCurrentByteNo() + StringsOffset);
|
|
||||||
|
|
||||||
StringRef Strings = Blob.drop_front(StringsOffset);
|
StringRef Strings = Blob.drop_front(StringsOffset);
|
||||||
do {
|
do {
|
||||||
if (R.AtEndOfStream())
|
if (R.AtEndOfStream())
|
||||||
|
@ -735,7 +731,7 @@ static bool openBitcodeFile(StringRef Path,
|
||||||
return ReportError("Invalid bitcode wrapper header");
|
return ReportError("Invalid bitcode wrapper header");
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamFile = BitstreamReader(BufPtr, EndBufPtr);
|
StreamFile = BitstreamReader(ArrayRef<uint8_t>(BufPtr, EndBufPtr));
|
||||||
Stream = BitstreamCursor(StreamFile);
|
Stream = BitstreamCursor(StreamFile);
|
||||||
StreamFile.CollectBlockInfoNames();
|
StreamFile.CollectBlockInfoNames();
|
||||||
|
|
||||||
|
@ -814,7 +810,7 @@ static int AnalyzeBitcode() {
|
||||||
|
|
||||||
if (Dump) outs() << "\n\n";
|
if (Dump) outs() << "\n\n";
|
||||||
|
|
||||||
uint64_t BufferSizeBits = StreamFile.getBitcodeBytes().getExtent() * CHAR_BIT;
|
uint64_t BufferSizeBits = StreamFile.getBitcodeBytes().size() * 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: ";
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "llvm/IR/Module.h"
|
#include "llvm/IR/Module.h"
|
||||||
#include "llvm/IR/Type.h"
|
#include "llvm/IR/Type.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/DataStream.h"
|
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
#include "llvm/Support/FileSystem.h"
|
#include "llvm/Support/FileSystem.h"
|
||||||
#include "llvm/Support/FormattedStream.h"
|
#include "llvm/Support/FormattedStream.h"
|
||||||
|
@ -139,34 +138,20 @@ static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Expected<std::unique_ptr<Module>> openInputFile(LLVMContext &Context) {
|
static Expected<std::unique_ptr<Module>> openInputFile(LLVMContext &Context) {
|
||||||
if (MaterializeMetadata) {
|
ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
|
||||||
ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
|
MemoryBuffer::getFileOrSTDIN(InputFilename);
|
||||||
MemoryBuffer::getFileOrSTDIN(InputFilename);
|
if (!MBOrErr)
|
||||||
if (!MBOrErr)
|
return errorCodeToError(MBOrErr.getError());
|
||||||
return errorCodeToError(MBOrErr.getError());
|
ErrorOr<std::unique_ptr<Module>> MOrErr =
|
||||||
ErrorOr<std::unique_ptr<Module>> MOrErr =
|
getLazyBitcodeModule(std::move(*MBOrErr), Context,
|
||||||
getLazyBitcodeModule(std::move(*MBOrErr), Context,
|
/*ShouldLazyLoadMetadata=*/true);
|
||||||
/*ShouldLazyLoadMetadata=*/true);
|
if (!MOrErr)
|
||||||
if (!MOrErr)
|
return errorCodeToError(MOrErr.getError());
|
||||||
return errorCodeToError(MOrErr.getError());
|
if (MaterializeMetadata)
|
||||||
(*MOrErr)->materializeMetadata();
|
(*MOrErr)->materializeMetadata();
|
||||||
return std::move(*MOrErr);
|
else
|
||||||
} else {
|
|
||||||
std::string ErrorMessage;
|
|
||||||
std::unique_ptr<DataStreamer> Streamer =
|
|
||||||
getDataFileStreamer(InputFilename, &ErrorMessage);
|
|
||||||
if (!Streamer)
|
|
||||||
return make_error<StringError>(ErrorMessage, inconvertibleErrorCode());
|
|
||||||
std::string DisplayFilename;
|
|
||||||
if (InputFilename == "-")
|
|
||||||
DisplayFilename = "<stdin>";
|
|
||||||
else
|
|
||||||
DisplayFilename = InputFilename;
|
|
||||||
ErrorOr<std::unique_ptr<Module>> MOrErr =
|
|
||||||
getStreamedBitcodeModule(DisplayFilename, std::move(Streamer), Context);
|
|
||||||
(*MOrErr)->materializeAll();
|
(*MOrErr)->materializeAll();
|
||||||
return std::move(*MOrErr);
|
return std::move(*MOrErr);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
|
|
@ -18,11 +18,9 @@
|
||||||
#include "llvm/IR/LLVMContext.h"
|
#include "llvm/IR/LLVMContext.h"
|
||||||
#include "llvm/IR/Module.h"
|
#include "llvm/IR/Module.h"
|
||||||
#include "llvm/IR/Verifier.h"
|
#include "llvm/IR/Verifier.h"
|
||||||
#include "llvm/Support/DataStream.h"
|
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
#include "llvm/Support/SourceMgr.h"
|
#include "llvm/Support/SourceMgr.h"
|
||||||
#include "llvm/Support/StreamingMemoryObject.h"
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
@ -62,84 +60,6 @@ static std::unique_ptr<Module> getLazyModuleFromAssembly(LLVMContext &Context,
|
||||||
return std::move(ModuleOrErr.get());
|
return std::move(ModuleOrErr.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
class BufferDataStreamer : public DataStreamer {
|
|
||||||
std::unique_ptr<MemoryBuffer> Buffer;
|
|
||||||
unsigned Pos = 0;
|
|
||||||
size_t GetBytes(unsigned char *Out, size_t Len) override {
|
|
||||||
StringRef Buf = Buffer->getBuffer();
|
|
||||||
size_t Left = Buf.size() - Pos;
|
|
||||||
Len = std::min(Left, Len);
|
|
||||||
memcpy(Out, Buffer->getBuffer().substr(Pos).data(), Len);
|
|
||||||
Pos += Len;
|
|
||||||
return Len;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
BufferDataStreamer(std::unique_ptr<MemoryBuffer> Buffer)
|
|
||||||
: Buffer(std::move(Buffer)) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::unique_ptr<Module>
|
|
||||||
getStreamedModuleFromAssembly(LLVMContext &Context, SmallString<1024> &Mem,
|
|
||||||
const char *Assembly) {
|
|
||||||
writeModuleToBuffer(parseAssembly(Context, Assembly), Mem);
|
|
||||||
std::unique_ptr<MemoryBuffer> Buffer =
|
|
||||||
MemoryBuffer::getMemBuffer(Mem.str(), "test", false);
|
|
||||||
auto Streamer = llvm::make_unique<BufferDataStreamer>(std::move(Buffer));
|
|
||||||
ErrorOr<std::unique_ptr<Module>> ModuleOrErr =
|
|
||||||
getStreamedBitcodeModule("test", std::move(Streamer), Context);
|
|
||||||
return std::move(ModuleOrErr.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks if we correctly detect eof if we try to read N bits when there are not
|
|
||||||
// enough bits left on the input stream to read N bits, and we are using a data
|
|
||||||
// streamer. In particular, it checks if we properly set the object size when
|
|
||||||
// the eof is reached under such conditions.
|
|
||||||
TEST(BitReaderTest, TestForEofAfterReadFailureOnDataStreamer) {
|
|
||||||
// Note: Because StreamingMemoryObject does a call to method GetBytes in it's
|
|
||||||
// constructor, using internal constant kChunkSize, we must fill the input
|
|
||||||
// with more characters than that amount.
|
|
||||||
static size_t InputSize = StreamingMemoryObject::kChunkSize + 5;
|
|
||||||
char *Text = new char[InputSize];
|
|
||||||
std::memset(Text, 'a', InputSize);
|
|
||||||
Text[InputSize - 1] = '\0';
|
|
||||||
StringRef Input(Text);
|
|
||||||
|
|
||||||
// Build bitsteam reader using data streamer.
|
|
||||||
auto MemoryBuf = MemoryBuffer::getMemBuffer(Input);
|
|
||||||
std::unique_ptr<DataStreamer> Streamer(
|
|
||||||
new BufferDataStreamer(std::move(MemoryBuf)));
|
|
||||||
auto OwnedBytes =
|
|
||||||
llvm::make_unique<StreamingMemoryObject>(std::move(Streamer));
|
|
||||||
auto Reader = llvm::make_unique<BitstreamReader>(std::move(OwnedBytes));
|
|
||||||
BitstreamCursor Cursor;
|
|
||||||
Cursor.init(Reader.get());
|
|
||||||
|
|
||||||
// Jump to two bytes before end of stream.
|
|
||||||
Cursor.JumpToBit((InputSize - 4) * CHAR_BIT);
|
|
||||||
// Try to read 4 bytes when only 2 are present, resulting in error value 0.
|
|
||||||
const size_t ReadErrorValue = 0;
|
|
||||||
EXPECT_EQ(ReadErrorValue, Cursor.Read(32));
|
|
||||||
// Should be at eof now.
|
|
||||||
EXPECT_TRUE(Cursor.AtEndOfStream());
|
|
||||||
|
|
||||||
delete[] Text;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(BitReaderTest, MateralizeForwardRefWithStream) {
|
|
||||||
SmallString<1024> Mem;
|
|
||||||
|
|
||||||
LLVMContext Context;
|
|
||||||
std::unique_ptr<Module> M = getStreamedModuleFromAssembly(
|
|
||||||
Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n"
|
|
||||||
"define void @func() {\n"
|
|
||||||
" unreachable\n"
|
|
||||||
"bb:\n"
|
|
||||||
" unreachable\n"
|
|
||||||
"}\n");
|
|
||||||
EXPECT_FALSE(M->getFunction("func")->empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests that lazy evaluation can parse functions out of order.
|
// Tests that lazy evaluation can parse functions out of order.
|
||||||
TEST(BitReaderTest, MaterializeFunctionsOutOfOrder) {
|
TEST(BitReaderTest, MaterializeFunctionsOutOfOrder) {
|
||||||
SmallString<1024> Mem;
|
SmallString<1024> Mem;
|
||||||
|
@ -216,6 +136,7 @@ TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677
|
||||||
" unreachable\n"
|
" unreachable\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
EXPECT_FALSE(verifyModule(*M, &dbgs()));
|
EXPECT_FALSE(verifyModule(*M, &dbgs()));
|
||||||
|
EXPECT_FALSE(M->getFunction("func")->empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) {
|
TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) {
|
||||||
|
|
|
@ -10,33 +10,17 @@
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/Bitcode/BitstreamReader.h"
|
#include "llvm/Bitcode/BitstreamReader.h"
|
||||||
#include "llvm/Bitcode/BitstreamWriter.h"
|
#include "llvm/Bitcode/BitstreamWriter.h"
|
||||||
#include "llvm/Support/StreamingMemoryObject.h"
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class BufferStreamer : public DataStreamer {
|
|
||||||
StringRef Buffer;
|
|
||||||
|
|
||||||
public:
|
|
||||||
BufferStreamer(StringRef Buffer) : Buffer(Buffer) {}
|
|
||||||
size_t GetBytes(unsigned char *OutBuffer, size_t Length) override {
|
|
||||||
if (Length >= Buffer.size())
|
|
||||||
Length = Buffer.size();
|
|
||||||
|
|
||||||
std::copy(Buffer.begin(), Buffer.begin() + Length, OutBuffer);
|
|
||||||
Buffer = Buffer.drop_front(Length);
|
|
||||||
return Length;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST(BitstreamReaderTest, AtEndOfStream) {
|
TEST(BitstreamReaderTest, AtEndOfStream) {
|
||||||
uint8_t Bytes[4] = {
|
uint8_t Bytes[4] = {
|
||||||
0x00, 0x01, 0x02, 0x03
|
0x00, 0x01, 0x02, 0x03
|
||||||
};
|
};
|
||||||
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
|
BitstreamReader Reader(Bytes);
|
||||||
BitstreamCursor Cursor(Reader);
|
BitstreamCursor Cursor(Reader);
|
||||||
|
|
||||||
EXPECT_FALSE(Cursor.AtEndOfStream());
|
EXPECT_FALSE(Cursor.AtEndOfStream());
|
||||||
|
@ -56,7 +40,7 @@ TEST(BitstreamReaderTest, AtEndOfStreamJump) {
|
||||||
uint8_t Bytes[4] = {
|
uint8_t Bytes[4] = {
|
||||||
0x00, 0x01, 0x02, 0x03
|
0x00, 0x01, 0x02, 0x03
|
||||||
};
|
};
|
||||||
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
|
BitstreamReader Reader(Bytes);
|
||||||
BitstreamCursor Cursor(Reader);
|
BitstreamCursor Cursor(Reader);
|
||||||
|
|
||||||
Cursor.JumpToBit(32);
|
Cursor.JumpToBit(32);
|
||||||
|
@ -64,8 +48,7 @@ TEST(BitstreamReaderTest, AtEndOfStreamJump) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BitstreamReaderTest, AtEndOfStreamEmpty) {
|
TEST(BitstreamReaderTest, AtEndOfStreamEmpty) {
|
||||||
uint8_t Dummy = 0xFF;
|
BitstreamReader Reader(ArrayRef<uint8_t>{});
|
||||||
BitstreamReader Reader(&Dummy, &Dummy);
|
|
||||||
BitstreamCursor Cursor(Reader);
|
BitstreamCursor Cursor(Reader);
|
||||||
|
|
||||||
EXPECT_TRUE(Cursor.AtEndOfStream());
|
EXPECT_TRUE(Cursor.AtEndOfStream());
|
||||||
|
@ -73,10 +56,10 @@ TEST(BitstreamReaderTest, AtEndOfStreamEmpty) {
|
||||||
|
|
||||||
TEST(BitstreamReaderTest, getCurrentByteNo) {
|
TEST(BitstreamReaderTest, getCurrentByteNo) {
|
||||||
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03};
|
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03};
|
||||||
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
|
BitstreamReader Reader(Bytes);
|
||||||
SimpleBitstreamCursor Cursor(Reader);
|
SimpleBitstreamCursor Cursor(Reader);
|
||||||
|
|
||||||
for (unsigned I = 0, E = 33; I != E; ++I) {
|
for (unsigned I = 0, E = 32; I != E; ++I) {
|
||||||
EXPECT_EQ(I / 8, Cursor.getCurrentByteNo());
|
EXPECT_EQ(I / 8, Cursor.getCurrentByteNo());
|
||||||
(void)Cursor.Read(1);
|
(void)Cursor.Read(1);
|
||||||
}
|
}
|
||||||
|
@ -85,7 +68,7 @@ TEST(BitstreamReaderTest, getCurrentByteNo) {
|
||||||
|
|
||||||
TEST(BitstreamReaderTest, getPointerToByte) {
|
TEST(BitstreamReaderTest, getPointerToByte) {
|
||||||
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
|
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
|
||||||
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
|
BitstreamReader Reader(Bytes);
|
||||||
SimpleBitstreamCursor Cursor(Reader);
|
SimpleBitstreamCursor Cursor(Reader);
|
||||||
|
|
||||||
for (unsigned I = 0, E = 8; I != E; ++I) {
|
for (unsigned I = 0, E = 8; I != E; ++I) {
|
||||||
|
@ -95,7 +78,7 @@ TEST(BitstreamReaderTest, getPointerToByte) {
|
||||||
|
|
||||||
TEST(BitstreamReaderTest, getPointerToBit) {
|
TEST(BitstreamReaderTest, getPointerToBit) {
|
||||||
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
|
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
|
||||||
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
|
BitstreamReader Reader(Bytes);
|
||||||
SimpleBitstreamCursor Cursor(Reader);
|
SimpleBitstreamCursor Cursor(Reader);
|
||||||
|
|
||||||
for (unsigned I = 0, E = 8; I != E; ++I) {
|
for (unsigned I = 0, E = 8; I != E; ++I) {
|
||||||
|
@ -105,7 +88,7 @@ TEST(BitstreamReaderTest, getPointerToBit) {
|
||||||
|
|
||||||
TEST(BitstreamReaderTest, jumpToPointer) {
|
TEST(BitstreamReaderTest, jumpToPointer) {
|
||||||
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
|
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
|
||||||
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
|
BitstreamReader Reader(Bytes);
|
||||||
SimpleBitstreamCursor Cursor(Reader);
|
SimpleBitstreamCursor Cursor(Reader);
|
||||||
|
|
||||||
for (unsigned I : {0, 6, 2, 7}) {
|
for (unsigned I : {0, 6, 2, 7}) {
|
||||||
|
@ -114,68 +97,6 @@ TEST(BitstreamReaderTest, jumpToPointer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BitstreamReaderTest, setArtificialByteLimit) {
|
|
||||||
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
||||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
|
|
||||||
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
|
|
||||||
SimpleBitstreamCursor Cursor(Reader);
|
|
||||||
|
|
||||||
Cursor.setArtificialByteLimit(8);
|
|
||||||
EXPECT_EQ(8u, Cursor.getSizeIfKnown());
|
|
||||||
while (!Cursor.AtEndOfStream())
|
|
||||||
(void)Cursor.Read(1);
|
|
||||||
|
|
||||||
EXPECT_EQ(8u, Cursor.getCurrentByteNo());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(BitstreamReaderTest, setArtificialByteLimitNotWordBoundary) {
|
|
||||||
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
||||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
|
|
||||||
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
|
|
||||||
SimpleBitstreamCursor Cursor(Reader);
|
|
||||||
|
|
||||||
Cursor.setArtificialByteLimit(5);
|
|
||||||
EXPECT_EQ(8u, Cursor.getSizeIfKnown());
|
|
||||||
while (!Cursor.AtEndOfStream())
|
|
||||||
(void)Cursor.Read(1);
|
|
||||||
|
|
||||||
EXPECT_EQ(8u, Cursor.getCurrentByteNo());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(BitstreamReaderTest, setArtificialByteLimitPastTheEnd) {
|
|
||||||
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
||||||
0x08, 0x09, 0x0a, 0x0b};
|
|
||||||
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
|
|
||||||
SimpleBitstreamCursor Cursor(Reader);
|
|
||||||
|
|
||||||
// The size of the memory object isn't known yet. Set it too high and
|
|
||||||
// confirm that we don't read too far.
|
|
||||||
Cursor.setArtificialByteLimit(24);
|
|
||||||
EXPECT_EQ(24u, Cursor.getSizeIfKnown());
|
|
||||||
while (!Cursor.AtEndOfStream())
|
|
||||||
(void)Cursor.Read(1);
|
|
||||||
|
|
||||||
EXPECT_EQ(12u, Cursor.getCurrentByteNo());
|
|
||||||
EXPECT_EQ(12u, Cursor.getSizeIfKnown());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(BitstreamReaderTest, setArtificialByteLimitPastTheEndKnown) {
|
|
||||||
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
||||||
0x08, 0x09, 0x0a, 0x0b};
|
|
||||||
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
|
|
||||||
SimpleBitstreamCursor Cursor(Reader);
|
|
||||||
|
|
||||||
// Save the size of the memory object in the cursor.
|
|
||||||
while (!Cursor.AtEndOfStream())
|
|
||||||
(void)Cursor.Read(1);
|
|
||||||
EXPECT_EQ(12u, Cursor.getCurrentByteNo());
|
|
||||||
EXPECT_EQ(12u, Cursor.getSizeIfKnown());
|
|
||||||
|
|
||||||
Cursor.setArtificialByteLimit(20);
|
|
||||||
EXPECT_TRUE(Cursor.AtEndOfStream());
|
|
||||||
EXPECT_EQ(12u, Cursor.getSizeIfKnown());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) {
|
TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) {
|
||||||
SmallVector<uint8_t, 1> BlobData;
|
SmallVector<uint8_t, 1> BlobData;
|
||||||
for (unsigned I = 0, E = 1024; I != E; ++I)
|
for (unsigned I = 0, E = 1024; I != E; ++I)
|
||||||
|
@ -208,9 +129,8 @@ TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stream the buffer into the reader.
|
// Stream the buffer into the reader.
|
||||||
BitstreamReader R(llvm::make_unique<StreamingMemoryObject>(
|
BitstreamReader R(
|
||||||
llvm::make_unique<BufferStreamer>(
|
ArrayRef<uint8_t>((const uint8_t *)Buffer.begin(), Buffer.size()));
|
||||||
StringRef(Buffer.begin(), Buffer.size()))));
|
|
||||||
BitstreamCursor Stream(R);
|
BitstreamCursor Stream(R);
|
||||||
|
|
||||||
// Header. Included in test so that we can run llvm-bcanalyzer to debug
|
// Header. Included in test so that we can run llvm-bcanalyzer to debug
|
||||||
|
|
Loading…
Reference in New Issue