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:
Peter Collingbourne
2016-11-02 00:08:19 +00:00
parent ce898dbb81
commit 028eb5a3f8
20 changed files with 91 additions and 381 deletions

View File

@@ -10,33 +10,17 @@
#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
};
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
BitstreamReader Reader(Bytes);
BitstreamCursor Cursor(Reader);
EXPECT_FALSE(Cursor.AtEndOfStream());
@@ -56,7 +40,7 @@ TEST(BitstreamReaderTest, AtEndOfStreamJump) {
uint8_t Bytes[4] = {
0x00, 0x01, 0x02, 0x03
};
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
BitstreamReader Reader(Bytes);
BitstreamCursor Cursor(Reader);
Cursor.JumpToBit(32);
@@ -64,8 +48,7 @@ TEST(BitstreamReaderTest, AtEndOfStreamJump) {
}
TEST(BitstreamReaderTest, AtEndOfStreamEmpty) {
uint8_t Dummy = 0xFF;
BitstreamReader Reader(&Dummy, &Dummy);
BitstreamReader Reader(ArrayRef<uint8_t>{});
BitstreamCursor Cursor(Reader);
EXPECT_TRUE(Cursor.AtEndOfStream());
@@ -73,10 +56,10 @@ TEST(BitstreamReaderTest, AtEndOfStreamEmpty) {
TEST(BitstreamReaderTest, getCurrentByteNo) {
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03};
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
BitstreamReader Reader(Bytes);
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());
(void)Cursor.Read(1);
}
@@ -85,7 +68,7 @@ TEST(BitstreamReaderTest, getCurrentByteNo) {
TEST(BitstreamReaderTest, getPointerToByte) {
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);
for (unsigned I = 0, E = 8; I != E; ++I) {
@@ -95,7 +78,7 @@ TEST(BitstreamReaderTest, getPointerToByte) {
TEST(BitstreamReaderTest, getPointerToBit) {
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);
for (unsigned I = 0, E = 8; I != E; ++I) {
@@ -105,7 +88,7 @@ TEST(BitstreamReaderTest, getPointerToBit) {
TEST(BitstreamReaderTest, jumpToPointer) {
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);
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) {
SmallVector<uint8_t, 1> BlobData;
for (unsigned I = 0, E = 1024; I != E; ++I)
@@ -208,9 +129,8 @@ TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) {
}
// Stream the buffer into the reader.
BitstreamReader R(llvm::make_unique<StreamingMemoryObject>(
llvm::make_unique<BufferStreamer>(
StringRef(Buffer.begin(), Buffer.size()))));
BitstreamReader R(
ArrayRef<uint8_t>((const uint8_t *)Buffer.begin(), Buffer.size()));
BitstreamCursor Stream(R);
// Header. Included in test so that we can run llvm-bcanalyzer to debug