Skip to content

Commit 58c7d49

Browse files
committed
Bitcode: Add SimpleBitstreamCursor::setArtificialByteLimit
Allow users of SimpleBitstreamCursor to limit the number of bytes available to the cursor. This is preparation for instantiating a cursor that isn't allowed to load more bytes from a StreamingMemoryObject (just move around the ones already-loaded). llvm-svn: 264547
1 parent d3be62d commit 58c7d49

File tree

2 files changed

+92
-1
lines changed

2 files changed

+92
-1
lines changed

llvm/include/llvm/Bitcode/BitstreamReader.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ class SimpleBitstreamCursor {
171171
if (BitsInCurWord != 0)
172172
return false;
173173
if (Size != 0)
174-
return Size == NextChar;
174+
return Size <= NextChar;
175175
fillCurWord();
176176
return BitsInCurWord == 0;
177177
}
@@ -351,6 +351,28 @@ class SimpleBitstreamCursor {
351351

352352
/// Skip to the end of the file.
353353
void skipToEnd() { NextChar = R->getBitcodeBytes().getExtent(); }
354+
355+
/// Prevent the cursor from reading past a byte boundary.
356+
///
357+
/// Prevent the cursor from requesting byte reads past \c Limit. This is
358+
/// useful when working with a cursor on a StreamingMemoryObject, when it's
359+
/// desirable to avoid invalidating the result of getPointerToByte().
360+
///
361+
/// If \c Limit is on a word boundary, AtEndOfStream() will return true if
362+
/// the cursor position reaches or exceeds \c Limit, regardless of the true
363+
/// number of available bytes. Otherwise, AtEndOfStream() returns true when
364+
/// it reaches or exceeds the next word boundary.
365+
void setArtificialByteLimit(uint64_t Limit) {
366+
assert(getCurrentByteNo() < Limit && "Move cursor before lowering limit");
367+
368+
// Round to word boundary.
369+
if (Limit & (sizeof(word_t) - 1))
370+
Limit += sizeof(word_t) - Limit & (sizeof(word_t) - 1);
371+
372+
// Only change size if the new one is lower.
373+
if (!Size || Size > Limit)
374+
Size = Limit;
375+
}
354376
};
355377

356378
/// When advancing through a bitstream cursor, each advance can discover a few

llvm/unittests/Bitcode/BitstreamReaderTest.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,73 @@ TEST(BitstreamReaderTest, jumpToPointer) {
9696
}
9797
}
9898

99+
TEST(BitstreamReaderTest, setArtificialByteLimit) {
100+
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
101+
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
102+
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
103+
SimpleBitstreamCursor Cursor(Reader);
104+
105+
Cursor.setArtificialByteLimit(8);
106+
while (!Cursor.AtEndOfStream())
107+
(void)Cursor.Read(1);
108+
109+
EXPECT_EQ(8u, Cursor.getCurrentByteNo());
110+
}
111+
112+
TEST(BitstreamReaderTest, setArtificialByteLimitNotWordBoundary) {
113+
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
114+
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
115+
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
116+
SimpleBitstreamCursor Cursor(Reader);
117+
118+
Cursor.setArtificialByteLimit(5);
119+
while (!Cursor.AtEndOfStream())
120+
(void)Cursor.Read(1);
121+
122+
EXPECT_EQ(8u, Cursor.getCurrentByteNo());
123+
}
124+
125+
TEST(BitstreamReaderTest, setArtificialByteLimitNot4ByteBoundary) {
126+
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
127+
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
128+
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
129+
SimpleBitstreamCursor Cursor(Reader);
130+
131+
Cursor.setArtificialByteLimit(5);
132+
while (!Cursor.AtEndOfStream())
133+
(void)Cursor.Read(1);
134+
135+
EXPECT_EQ(8u, Cursor.getCurrentByteNo());
136+
}
137+
138+
TEST(BitstreamReaderTest, setArtificialByteLimitPastTheEnd) {
139+
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
140+
0x08, 0x09, 0x0a, 0x0b};
141+
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
142+
SimpleBitstreamCursor Cursor(Reader);
143+
144+
// The size of the memory object isn't known yet. Set it too high and
145+
// confirm that we don't read too far.
146+
Cursor.setArtificialByteLimit(20);
147+
while (!Cursor.AtEndOfStream())
148+
(void)Cursor.Read(1);
149+
150+
EXPECT_EQ(12u, Cursor.getCurrentByteNo());
151+
}
152+
153+
TEST(BitstreamReaderTest, setArtificialByteLimitPastTheEndKnown) {
154+
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
155+
0x08, 0x09, 0x0a, 0x0b};
156+
BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
157+
SimpleBitstreamCursor Cursor(Reader);
158+
159+
// Save the size of the memory object in the cursor.
160+
while (!Cursor.AtEndOfStream())
161+
(void)Cursor.Read(1);
162+
EXPECT_EQ(12u, Cursor.getCurrentByteNo());
163+
164+
Cursor.setArtificialByteLimit(20);
165+
EXPECT_TRUE(Cursor.AtEndOfStream());
166+
}
167+
99168
} // end anonymous namespace

0 commit comments

Comments
 (0)