Index: include/llvm/Bitcode/NaCl/NaClBitstreamReader.h |
diff --git a/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h b/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h |
index 97e216441939906f33f1c2d1f48585005bf51e8f..d56018d065421ec82f69fae5001aafd7275343e8 100644 |
--- a/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h |
+++ b/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h |
@@ -19,13 +19,13 @@ |
#include "llvm/ADT/SmallVector.h" |
#include "llvm/Bitcode/NaCl/NaClLLVMBitCodes.h" |
#include "llvm/Support/Endian.h" |
-#include "llvm/Support/StreamableMemoryObject.h" |
+#include "llvm/Support/StreamingMemoryObject.h" |
#include <climits> |
#include <vector> |
namespace llvm { |
- class Deserializer; |
+class Deserializer; |
/// NaClBitstreamReader - This class is used to read from a NaCl |
/// bitcode wire format stream, maintaining information that is global |
@@ -41,7 +41,7 @@ public: |
std::vector<NaClBitCodeAbbrev*> Abbrevs; |
}; |
private: |
- std::unique_ptr<StreamableMemoryObject> BitcodeBytes; |
+ std::unique_ptr<MemoryObject> BitcodeBytes; |
std::vector<BlockInfo> BlockInfoRecords; |
@@ -59,10 +59,8 @@ public: |
init(Start, End); |
} |
- NaClBitstreamReader(StreamableMemoryObject *Bytes, |
- size_t MyInitialAddress=0) |
- : InitialAddress(MyInitialAddress) |
- { |
+ NaClBitstreamReader(MemoryObject *Bytes, size_t MyInitialAddress=0) |
+ : InitialAddress(MyInitialAddress) { |
BitcodeBytes.reset(Bytes); |
} |
@@ -71,7 +69,7 @@ public: |
BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End)); |
} |
- StreamableMemoryObject &getBitcodeBytes() { return *BitcodeBytes; } |
+ MemoryObject &getBitcodeBytes() { return *BitcodeBytes; } |
~NaClBitstreamReader() { |
// Free the BlockInfoRecords. |
@@ -124,7 +122,7 @@ public: |
} |
}; |
- |
+ |
/// NaClBitstreamEntry - When advancing through a bitstream cursor, |
/// each advance can discover a few different kinds of entries: |
/// Error - Malformed bitcode was found. |
@@ -140,7 +138,7 @@ struct NaClBitstreamEntry { |
SubBlock, |
Record |
} Kind; |
- |
+ |
unsigned ID; |
static NaClBitstreamEntry getError() { |
@@ -213,6 +211,9 @@ class NaClBitstreamCursor { |
NaClBitstreamReader *BitStream; |
size_t NextChar; |
+ // The size of the bitcode. 0 if we don't know it yet. |
+ size_t Size; |
+ |
/// CurWord/word_t - 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 follow the word size of the host machine for |
@@ -235,7 +236,7 @@ class NaClBitstreamCursor { |
struct Block { |
NaClBitcodeSelectorAbbrev PrevCodeSize; |
std::vector<NaClBitCodeAbbrev*> PrevAbbrevs; |
- explicit Block() : PrevCodeSize() {} |
+ Block() : PrevCodeSize() {} |
explicit Block(const NaClBitcodeSelectorAbbrev& PCS) |
: PrevCodeSize(PCS) {} |
}; |
@@ -247,7 +248,6 @@ class NaClBitstreamCursor { |
NaClBitstreamCursor &operator=(const NaClBitstreamCursor &) LLVM_DELETED_FUNCTION; |
public: |
- |
NaClBitstreamCursor() { |
init(nullptr); |
} |
@@ -258,7 +258,7 @@ public: |
freeState(); |
BitStream = R; |
NextChar = (BitStream == nullptr) ? 0 : BitStream->getInitialAddress(); |
- CurWord = 0; |
+ Size = 0; |
BitsInCurWord = 0; |
} |
@@ -268,10 +268,6 @@ public: |
void freeState(); |
- 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( |
@@ -279,7 +275,12 @@ public: |
} |
bool AtEndOfStream() { |
- return BitsInCurWord == 0 && isEndPos(NextChar); |
+ if (BitsInCurWord != 0) |
+ return false; |
+ if (Size != 0 && Size == NextChar) |
+ return true; |
+ fillCurWord(); |
+ return BitsInCurWord == 0; |
} |
/// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #. |
@@ -308,7 +309,7 @@ public: |
/// returned just like normal records. |
AF_DontAutoprocessAbbrevs = 2 |
}; |
- |
+ |
/// advance - Advance the current bitstream, returning the next entry in the |
/// stream. Use the given abbreviation listener (if provided). |
NaClBitstreamEntry advance(unsigned Flags, NaClAbbrevListener *Listener) { |
@@ -320,10 +321,10 @@ public: |
return NaClBitstreamEntry::getError(); |
return NaClBitstreamEntry::getEndBlock(); |
} |
- |
+ |
if (Code == naclbitc::ENTER_SUBBLOCK) |
return NaClBitstreamEntry::getSubBlock(ReadSubBlockID()); |
- |
+ |
if (Code == naclbitc::DEFINE_ABBREV && |
!(Flags & AF_DontAutoprocessAbbrevs)) { |
// We read and accumulate abbrev's, the client can't do anything with |
@@ -344,7 +345,7 @@ public: |
NaClBitstreamEntry Entry = advance(Flags, 0); |
if (Entry.Kind != NaClBitstreamEntry::SubBlock) |
return Entry; |
- |
+ |
// If we found a sub-block, just skip over it and check the next entry. |
if (SkipBlock()) |
return NaClBitstreamEntry::getError(); |
@@ -360,7 +361,6 @@ public: |
// Move the cursor to the right word. |
NextChar = ByteNo; |
BitsInCurWord = 0; |
- CurWord = 0; |
// Skip over any bits that are already consumed. |
if (WordBitNo) { |
@@ -371,55 +371,65 @@ public: |
} |
} |
+ void fillCurWord() { |
+ assert(Size == 0 || NextChar < (unsigned)Size); |
+ |
+ // Read the next word from the stream. |
+ uint8_t Array[sizeof(word_t)] = {0}; |
+ |
+ uint64_t BytesRead = |
+ BitStream->getBitcodeBytes().readBytes(Array, sizeof(Array), NextChar); |
+ |
+ // If we run out of data, stop at the end of the stream. |
+ if (BytesRead == 0) { |
+ Size = NextChar; |
+ return; |
+ } |
+ assert(BytesRead == sizeof(Array)); |
Karl
2015/02/20 17:07:02
Should this be an assert (i.e. has the length been
jvoung (off chromium)
2015/02/20 17:38:21
Hmm looks like the assert is gone in the new Bitst
|
+ |
+ // Handle big-endian byte-swapping if necessary. |
+ support::detail::packed_endian_specific_integral< |
+ word_t, support::little, support::unaligned> EndianValue; |
+ memcpy(&EndianValue, Array, sizeof(Array)); |
+ |
+ CurWord = EndianValue; |
+ NextChar += sizeof(word_t); |
+ BitsInCurWord = sizeof(word_t) * 8; |
+ } |
+ |
uint32_t Read(unsigned NumBits) { |
assert(NumBits && NumBits <= 32 && |
"Cannot return zero or more than 32 bits!"); |
- |
+ |
// If the field is fully contained by CurWord, return it quickly. |
if (BitsInCurWord >= NumBits) { |
uint32_t R = uint32_t(CurWord) & (~0U >> (32-NumBits)); |
- CurWord >>= NumBits; |
+ |
+ // Use a mask to avoid undefined behavior. |
+ CurWord >>= (NumBits & 0x1f); |
Karl
2015/02/20 17:07:02
Is the mask necessary? Doesn't the assert above gu
jvoung (off chromium)
2015/02/20 17:38:21
Yes, in case asserts are turned off.
Otherwise it
|
+ |
BitsInCurWord -= NumBits; |
return R; |
} |
+ uint32_t R = BitsInCurWord ? uint32_t(CurWord) : 0; |
+ unsigned BitsLeft = NumBits - BitsInCurWord; |
+ |
+ fillCurWord(); |
+ |
// If we run out of data, stop at the end of the stream. |
- if (isEndPos(NextChar)) { |
- CurWord = 0; |
- BitsInCurWord = 0; |
+ if (BitsLeft > BitsInCurWord) |
return 0; |
- } |
- uint32_t R = uint32_t(CurWord); |
+ uint32_t R2 = uint32_t(CurWord) & (~0U >> (sizeof(word_t) * 8 - BitsLeft)); |
- // Read the next word from the stream. |
- uint8_t Array[sizeof(word_t)] = {0}; |
- |
- BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(Array), Array); |
- |
- // Handle big-endian byte-swapping if necessary. |
- support::detail::packed_endian_specific_integral |
- <word_t, support::little, support::unaligned> EndianValue; |
- memcpy(&EndianValue, Array, sizeof(Array)); |
- |
- CurWord = EndianValue; |
+ // Use a mask to avoid undefined behavior. |
+ CurWord >>= (BitsLeft & 0x1f); |
- NextChar += sizeof(word_t); |
- |
- // Extract NumBits-BitsInCurWord from what we just read. |
- unsigned BitsLeft = NumBits-BitsInCurWord; |
+ BitsInCurWord -= BitsLeft; |
- // Be careful here, BitsLeft is in the range [1..32]/[1..64] inclusive. |
- R |= uint32_t((CurWord & (word_t(~0ULL) >> (sizeof(word_t)*8-BitsLeft))) |
- << BitsInCurWord); |
+ R |= uint32_t(R2 << (NumBits - BitsLeft)); |
- // BitsLeft bits have just been used up from CurWord. BitsLeft is in the |
- // range [1..32]/[1..64] so be careful how we shift. |
- if (BitsLeft != sizeof(word_t)*8) |
- CurWord >>= BitsLeft; |
- else |
- CurWord = 0; |
- BitsInCurWord = sizeof(word_t)*8-BitsLeft; |
return R; |
} |
@@ -478,9 +488,8 @@ private: |
BitsInCurWord = 32; |
return; |
} |
- |
+ |
BitsInCurWord = 0; |
- CurWord = 0; |
} |
public: |
@@ -522,7 +531,7 @@ public: |
/// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter |
/// the block, and return true if the block has an error. |
bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = 0); |
- |
+ |
bool ReadBlockEnd() { |
if (BlockScope.empty()) return true; |