Support: Implement StreamingMemoryObject::getPointer
The implementation is fairly obvious. This is preparation for using
some blobs in bitcode.
For clarity (and perhaps future-proofing?), I moved the call to
JumpToBit in BitstreamCursor::readRecord ahead of calling
MemoryObject::getPointer, since JumpToBit can theoretically (a) read
bytes, which (b) invalidates the blob pointer.
This isn't strictly necessary the two memory objects we have:
- The return of RawMemoryObject::getPointer is valid until the memory
object is destroyed.
- StreamingMemoryObject::getPointer is valid until the next chunk is
read from the stream. Since the JumpToBit call is only going ahead
to a word boundary, we'll never load another chunk.
However, reordering makes it clear by inspection that the blob returned
by BitstreamCursor::readRecord will be valid.
I added some tests for StreamingMemoryObject::getPointer and
BitstreamCursor::readRecord.
llvm-svn: 264549
This commit is contained in:
@@ -7,13 +7,31 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Bitcode/BitstreamReader.h"
|
||||
#include "llvm/Bitcode/BitstreamWriter.h"
|
||||
#include "llvm/Support/StreamingMemoryObject.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
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) {
|
||||
uint8_t Bytes[4] = {
|
||||
0x00, 0x01, 0x02, 0x03
|
||||
@@ -165,4 +183,65 @@ TEST(BitstreamReaderTest, setArtificialByteLimitPastTheEndKnown) {
|
||||
EXPECT_TRUE(Cursor.AtEndOfStream());
|
||||
}
|
||||
|
||||
TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) {
|
||||
SmallVector<uint8_t, 1> BlobData;
|
||||
for (unsigned I = 0, E = 1024; I != E; ++I)
|
||||
BlobData.push_back(I);
|
||||
|
||||
// Try a bunch of different sizes.
|
||||
const unsigned Magic = 0x12345678;
|
||||
const unsigned BlockID = bitc::FIRST_APPLICATION_BLOCKID;
|
||||
const unsigned RecordID = 1;
|
||||
for (unsigned I = 0, BlobSize = 0, E = BlobData.size(); BlobSize < E;
|
||||
BlobSize += ++I) {
|
||||
StringRef BlobIn((const char *)BlobData.begin(), BlobSize);
|
||||
|
||||
// Write the bitcode.
|
||||
SmallVector<char, 1> Buffer;
|
||||
unsigned AbbrevID;
|
||||
{
|
||||
BitstreamWriter Stream(Buffer);
|
||||
Stream.Emit(Magic, 32);
|
||||
Stream.EnterSubblock(BlockID, 3);
|
||||
|
||||
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
|
||||
Abbrev->Add(BitCodeAbbrevOp(RecordID));
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
|
||||
AbbrevID = Stream.EmitAbbrev(Abbrev);
|
||||
unsigned Record[] = {RecordID};
|
||||
Stream.EmitRecordWithBlob(AbbrevID, makeArrayRef(Record), BlobIn);
|
||||
|
||||
Stream.ExitBlock();
|
||||
}
|
||||
|
||||
// Stream the buffer into the reader.
|
||||
BitstreamReader R(make_unique<StreamingMemoryObject>(
|
||||
make_unique<BufferStreamer>(StringRef(Buffer.begin(), Buffer.size()))));
|
||||
BitstreamCursor Stream(R);
|
||||
|
||||
// Header. Included in test so that we can run llvm-bcanalyzer to debug
|
||||
// when there are problems.
|
||||
ASSERT_EQ(Magic, Stream.Read(32));
|
||||
|
||||
// Block.
|
||||
BitstreamEntry Entry =
|
||||
Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
|
||||
ASSERT_EQ(BitstreamEntry::SubBlock, Entry.Kind);
|
||||
ASSERT_EQ(BlockID, Entry.ID);
|
||||
ASSERT_FALSE(Stream.EnterSubBlock(BlockID));
|
||||
|
||||
// Abbreviation.
|
||||
Entry = Stream.advance();
|
||||
ASSERT_EQ(BitstreamEntry::Record, Entry.Kind);
|
||||
ASSERT_EQ(AbbrevID, Entry.ID);
|
||||
|
||||
// Record.
|
||||
StringRef BlobOut;
|
||||
SmallVector<uint64_t, 1> Record;
|
||||
ASSERT_EQ(RecordID, Stream.readRecord(Entry.ID, Record, &BlobOut));
|
||||
EXPECT_TRUE(Record.empty());
|
||||
EXPECT_EQ(BlobIn, BlobOut);
|
||||
}
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
Reference in New Issue
Block a user