From 312c7d9dc126e90ca1f40d30ba9a3ba22ade35c4 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 19 Jan 2013 18:19:39 +0000 Subject: BitstreamReader hasn't aged well. It's been hacked on by various people and has past the point of making sense. Lets tidy things up: first step, moving a ton of big functions out of line. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172904 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 238 ++------------------------------- 1 file changed, 12 insertions(+), 226 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 3a81de81a4..bdc71ae406 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -179,50 +179,10 @@ public: freeState(); } - void operator=(const BitstreamCursor &RHS) { - freeState(); - - BitStream = RHS.BitStream; - NextChar = RHS.NextChar; - CurWord = RHS.CurWord; - BitsInCurWord = RHS.BitsInCurWord; - CurCodeSize = RHS.CurCodeSize; - - // Copy abbreviations, and bump ref counts. - CurAbbrevs = RHS.CurAbbrevs; - for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); - i != e; ++i) - CurAbbrevs[i]->addRef(); - - // Copy block scope and bump ref counts. - BlockScope = RHS.BlockScope; - for (unsigned S = 0, e = static_cast(BlockScope.size()); - S != e; ++S) { - std::vector &Abbrevs = BlockScope[S].PrevAbbrevs; - for (unsigned i = 0, e = static_cast(Abbrevs.size()); - i != e; ++i) - Abbrevs[i]->addRef(); - } - } - - void freeState() { - // Free all the Abbrevs. - for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); - i != e; ++i) - CurAbbrevs[i]->dropRef(); - CurAbbrevs.clear(); - - // Free all the Abbrevs in the block scope. - for (unsigned S = 0, e = static_cast(BlockScope.size()); - S != e; ++S) { - std::vector &Abbrevs = BlockScope[S].PrevAbbrevs; - for (unsigned i = 0, e = static_cast(Abbrevs.size()); - i != e; ++i) - Abbrevs[i]->dropRef(); - } - BlockScope.clear(); - } + void operator=(const BitstreamCursor &RHS); + void freeState(); + /// GetAbbrevIDWidth - Return the number of bits used to encode an abbrev #. unsigned GetAbbrevIDWidth() const { return CurCodeSize; } @@ -243,12 +203,8 @@ public: } uint32_t getWord(size_t pos) { - uint8_t buf[sizeof(uint32_t)]; - memset(buf, 0xFF, sizeof(buf)); - BitStream->getBitcodeBytes().readBytes(pos, - sizeof(buf), - buf, - NULL); + uint8_t buf[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; + BitStream->getBitcodeBytes().readBytes(pos, sizeof(buf), buf, NULL); return *reinterpret_cast(buf); } @@ -410,34 +366,8 @@ 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) { - // Save the current block's state on BlockScope. - BlockScope.push_back(Block(CurCodeSize)); - BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); - - // Add the abbrevs specific to this block to the CurAbbrevs list. - if (const BitstreamReader::BlockInfo *Info = - BitStream->getBlockInfo(BlockID)) { - for (unsigned i = 0, e = static_cast(Info->Abbrevs.size()); - i != e; ++i) { - CurAbbrevs.push_back(Info->Abbrevs[i]); - CurAbbrevs.back()->addRef(); - } - } - - // Get the codesize of this block. - CurCodeSize = ReadVBR(bitc::CodeLenWidth); - SkipToWord(); - unsigned NumWords = Read(bitc::BlockSizeWidth); - if (NumWordsP) *NumWordsP = NumWords; - - // Validate that this block is sane. - if (CurCodeSize == 0 || AtEndOfStream()) - return true; - - return false; - } - + bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = 0); + bool ReadBlockEnd() { if (BlockScope.empty()) return true; @@ -502,70 +432,8 @@ public: } unsigned ReadRecord(unsigned AbbrevID, SmallVectorImpl &Vals, - const char **BlobStart = 0, unsigned *BlobLen = 0) { - if (AbbrevID == bitc::UNABBREV_RECORD) { - unsigned Code = ReadVBR(6); - unsigned NumElts = ReadVBR(6); - for (unsigned i = 0; i != NumElts; ++i) - Vals.push_back(ReadVBR64(6)); - return Code; - } - - const BitCodeAbbrev *Abbv = getAbbrev(AbbrevID); - - for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) { - const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); - if (Op.isLiteral()) { - ReadAbbreviatedLiteral(Op, Vals); - } else if (Op.getEncoding() == BitCodeAbbrevOp::Array) { - // Array case. Read the number of elements as a vbr6. - unsigned NumElts = ReadVBR(6); - - // Get the element encoding. - assert(i+2 == e && "array op not second to last?"); - const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i); - - // Read all the elements. - for (; NumElts; --NumElts) - ReadAbbreviatedField(EltEnc, Vals); - } else if (Op.getEncoding() == BitCodeAbbrevOp::Blob) { - // Blob case. Read the number of bytes as a vbr6. - unsigned NumElts = ReadVBR(6); - SkipToWord(); // 32-bit alignment - - // Figure out where the end of this blob will be including tail padding. - size_t NewEnd = NextChar+((NumElts+3)&~3); - - // If this would read off the end of the bitcode file, just set the - // record to empty and return. - if (!canSkipToPos(NewEnd)) { - Vals.append(NumElts, 0); - NextChar = BitStream->getBitcodeBytes().getExtent(); - break; - } - - // Otherwise, read the number of bytes. If we can return a reference to - // the data, do so to avoid copying it. - if (BlobStart) { - *BlobStart = (const char*)BitStream->getBitcodeBytes().getPointer( - NextChar, NumElts); - *BlobLen = NumElts; - } else { - for (; NumElts; ++NextChar, --NumElts) - Vals.push_back(getByte(NextChar)); - } - // Skip over tail padding. - NextChar = NewEnd; - } else { - ReadAbbreviatedField(Op, Vals); - } - } - - unsigned Code = (unsigned)Vals[0]; - Vals.erase(Vals.begin()); - return Code; - } - + const char **BlobStart = 0, unsigned *BlobLen = 0); + unsigned ReadRecord(unsigned AbbrevID, SmallVectorImpl &Vals, const char *&BlobStart, unsigned &BlobLen) { return ReadRecord(AbbrevID, Vals, &BlobStart, &BlobLen); @@ -576,91 +444,9 @@ public: // Abbrev Processing //===--------------------------------------------------------------------===// - void ReadAbbrevRecord() { - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); - unsigned NumOpInfo = ReadVBR(5); - for (unsigned i = 0; i != NumOpInfo; ++i) { - bool IsLiteral = Read(1) ? true : false; - if (IsLiteral) { - Abbv->Add(BitCodeAbbrevOp(ReadVBR64(8))); - continue; - } - - BitCodeAbbrevOp::Encoding E = (BitCodeAbbrevOp::Encoding)Read(3); - if (BitCodeAbbrevOp::hasEncodingData(E)) - Abbv->Add(BitCodeAbbrevOp(E, ReadVBR64(5))); - else - Abbv->Add(BitCodeAbbrevOp(E)); - } - CurAbbrevs.push_back(Abbv); - } - -public: - - bool ReadBlockInfoBlock() { - // If this is the second stream to get to the block info block, skip it. - if (BitStream->hasBlockInfoRecords()) - return SkipBlock(); - - if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return true; - - SmallVector Record; - BitstreamReader::BlockInfo *CurBlockInfo = 0; - - // Read all the records for this module. - while (1) { - unsigned Code = ReadCode(); - if (Code == bitc::END_BLOCK) - return ReadBlockEnd(); - if (Code == bitc::ENTER_SUBBLOCK) { - ReadSubBlockID(); - if (SkipBlock()) return true; - continue; - } - - // Read abbrev records, associate them with CurBID. - if (Code == bitc::DEFINE_ABBREV) { - if (!CurBlockInfo) return true; - ReadAbbrevRecord(); - - // ReadAbbrevRecord installs the abbrev in CurAbbrevs. Move it to the - // appropriate BlockInfo. - BitCodeAbbrev *Abbv = CurAbbrevs.back(); - CurAbbrevs.pop_back(); - CurBlockInfo->Abbrevs.push_back(Abbv); - continue; - } - - // Read a record. - Record.clear(); - switch (ReadRecord(Code, Record)) { - default: break; // Default behavior, ignore unknown content. - case bitc::BLOCKINFO_CODE_SETBID: - if (Record.size() < 1) return true; - CurBlockInfo = &BitStream->getOrCreateBlockInfo((unsigned)Record[0]); - break; - case bitc::BLOCKINFO_CODE_BLOCKNAME: { - if (!CurBlockInfo) return true; - if (BitStream->isIgnoringBlockInfoNames()) break; // Ignore name. - std::string Name; - for (unsigned i = 0, e = Record.size(); i != e; ++i) - Name += (char)Record[i]; - CurBlockInfo->Name = Name; - break; - } - case bitc::BLOCKINFO_CODE_SETRECORDNAME: { - if (!CurBlockInfo) return true; - if (BitStream->isIgnoringBlockInfoNames()) break; // Ignore name. - std::string Name; - for (unsigned i = 1, e = Record.size(); i != e; ++i) - Name += (char)Record[i]; - CurBlockInfo->RecordNames.push_back(std::make_pair((unsigned)Record[0], - Name)); - break; - } - } - } - } + void ReadAbbrevRecord(); + + bool ReadBlockInfoBlock(); }; } // End llvm namespace -- cgit v1.2.3-18-g5258 From 63246aa04f23767875bfe6f533285915a766b82d Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 19 Jan 2013 21:35:24 +0000 Subject: Add a new BitstreamEntry concept, and add two helper methods for walking through a BitstreamCursor that produce it: advance() and advanceSkippingSubblocks(), representing the two most common ways clients want to walk through bitcode. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172919 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 97 +++++++++++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 6 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index bdc71ae406..2ca92081e3 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -27,6 +27,11 @@ namespace llvm { class Deserializer; +/// BitstreamReader - This class is used to read from an LLVM bitcode stream, +/// maintaining information that is global to decoding the entire file. While +/// a file is being read, multiple cursors can be independently advanced or +/// skipped around within the file. These are represented by the +/// BitstreamCursor class. class BitstreamReader { public: /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. @@ -119,9 +124,48 @@ public: BlockInfoRecords.back().BlockID = BlockID; return BlockInfoRecords.back(); } +}; + + +/// BitstreamEntry - When advancing through a bitstream cursor, each advance can +/// discover a few different kinds of entries: +/// Error - Malformed bitcode was found. +/// EndBlock - We've reached the end of the current block, (or the end of the +/// file, which is treated like a series of EndBlock records. +/// SubBlock - This is the start of a new subblock of a specific ID. +/// Record - This is a record with a specific AbbrevID. +/// +struct BitstreamEntry { + enum { + Error, + EndBlock, + SubBlock, + Record + } Kind; + + unsigned ID; + static BitstreamEntry getError() { + BitstreamEntry E; E.Kind = Error; return E; + } + static BitstreamEntry getEndBlock() { + BitstreamEntry E; E.Kind = EndBlock; return E; + } + static BitstreamEntry getSubBlock(unsigned ID) { + BitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E; + } + static BitstreamEntry getRecord(unsigned AbbrevID) { + BitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E; + } }; + +/// BitstreamCursor - This represents a position within a bitcode file. There +/// may be multiple independent cursors reading within one bitstream, each +/// maintaining their own local state. +/// +/// Unlike iterators, BitstreamCursors are heavy-weight objects that should not +/// be passed by value. class BitstreamCursor { friend class Deserializer; BitstreamReader *BitStream; @@ -151,6 +195,7 @@ class BitstreamCursor { /// BlockScope - This tracks the codesize of parent blocks. SmallVector BlockScope; + public: BitstreamCursor() : BitStream(0), NextChar(0) { } @@ -183,9 +228,6 @@ public: void freeState(); - /// GetAbbrevIDWidth - Return the number of bits used to encode an abbrev #. - unsigned GetAbbrevIDWidth() const { return CurCodeSize; } - bool isEndPos(size_t pos) { return BitStream->getBitcodeBytes().isObjectEnd(static_cast(pos)); } @@ -212,6 +254,9 @@ public: return isEndPos(NextChar) && BitsInCurWord == 0; } + /// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #. + unsigned getAbbrevIDWidth() const { return CurCodeSize; } + /// GetCurrentBitNo - Return the bit # of the bit we are reading. uint64_t GetCurrentBitNo() const { return NextChar*CHAR_BIT - BitsInCurWord; @@ -224,6 +269,46 @@ public: return BitStream; } + + /// advance - Advance the current bitstream, returning the next entry in the + /// stream. + BitstreamEntry advance() { + while (1) { + unsigned Code = ReadCode(); + if (Code == bitc::END_BLOCK) { + if (ReadBlockEnd()) + return BitstreamEntry::getError(); + return BitstreamEntry::getEndBlock(); + } + + if (Code == bitc::ENTER_SUBBLOCK) + return BitstreamEntry::getSubBlock(ReadSubBlockID()); + + if (Code == bitc::DEFINE_ABBREV) { + // We read and accumulate abbrev's, the client can't do anything with + // them anyway. + ReadAbbrevRecord(); + continue; + } + + return BitstreamEntry::getRecord(Code); + } + } + + /// advanceSkippingSubblocks - This is a convenience function for clients that + /// don't expect any subblocks. This just skips over them automatically. + BitstreamEntry advanceSkippingSubblocks() { + while (1) { + // If we found a normal entry, return it. + BitstreamEntry Entry = advance(); + if (Entry.Kind != BitstreamEntry::SubBlock) + return Entry; + + // If we found a sub-block, just skip over it and check the next entry. + if (SkipBlock()) + return BitstreamEntry::getError(); + } + } /// JumpToBit - Reset the stream to the specified bit number. void JumpToBit(uint64_t BitNo) { @@ -375,12 +460,13 @@ public: // [END_BLOCK, ] SkipToWord(); - PopBlockScope(); + popBlockScope(); return false; } private: - void PopBlockScope() { + + void popBlockScope() { CurCodeSize = BlockScope.back().PrevCodeSize; // Delete abbrevs from popped scope. @@ -443,7 +529,6 @@ public: //===--------------------------------------------------------------------===// // Abbrev Processing //===--------------------------------------------------------------------===// - void ReadAbbrevRecord(); bool ReadBlockInfoBlock(); -- cgit v1.2.3-18-g5258 From 344fc23d23c969043f8f146b17cb7d2f47a98384 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 19 Jan 2013 23:31:15 +0000 Subject: add some optional flags to affect the way advance works. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172928 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 2ca92081e3..ae3d472c6b 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -269,14 +269,19 @@ public: return BitStream; } + /// Flags that modify the behavior of advance(). + enum { + AF_DontPopBlockAtEnd = 1 + }; /// advance - Advance the current bitstream, returning the next entry in the /// stream. - BitstreamEntry advance() { + BitstreamEntry advance(unsigned Flags = 0) { while (1) { unsigned Code = ReadCode(); if (Code == bitc::END_BLOCK) { - if (ReadBlockEnd()) + // Pop the end of the block unless Flags tells us not to. + if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd()) return BitstreamEntry::getError(); return BitstreamEntry::getEndBlock(); } @@ -297,10 +302,10 @@ public: /// advanceSkippingSubblocks - This is a convenience function for clients that /// don't expect any subblocks. This just skips over them automatically. - BitstreamEntry advanceSkippingSubblocks() { + BitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) { while (1) { // If we found a normal entry, return it. - BitstreamEntry Entry = advance(); + BitstreamEntry Entry = advance(Flags); if (Entry.Kind != BitstreamEntry::SubBlock) return Entry; -- cgit v1.2.3-18-g5258 From f9147c41d8101dbd98662d6d7be78278d53f690f Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 20 Jan 2013 00:00:00 +0000 Subject: move some private methods out of line, add a skipRecord() method. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172931 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 35 +++++++++------------------------- 1 file changed, 9 insertions(+), 26 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index ae3d472c6b..d6d9e34868 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -488,31 +488,12 @@ private: //===--------------------------------------------------------------------===// private: - void ReadAbbreviatedLiteral(const BitCodeAbbrevOp &Op, - SmallVectorImpl &Vals) { - assert(Op.isLiteral() && "Not a literal"); - // If the abbrev specifies the literal value to use, use it. - Vals.push_back(Op.getLiteralValue()); - } - - void ReadAbbreviatedField(const BitCodeAbbrevOp &Op, - SmallVectorImpl &Vals) { - assert(!Op.isLiteral() && "Use ReadAbbreviatedLiteral for literals!"); - - // Decode the value as we are commanded. - switch (Op.getEncoding()) { - default: llvm_unreachable("Unknown encoding!"); - case BitCodeAbbrevOp::Fixed: - Vals.push_back(Read((unsigned)Op.getEncodingData())); - break; - case BitCodeAbbrevOp::VBR: - Vals.push_back(ReadVBR64((unsigned)Op.getEncodingData())); - break; - case BitCodeAbbrevOp::Char6: - Vals.push_back(BitCodeAbbrevOp::DecodeChar6(Read(6))); - break; - } - } + void readAbbreviatedLiteral(const BitCodeAbbrevOp &Op, + SmallVectorImpl &Vals); + void readAbbreviatedField(const BitCodeAbbrevOp &Op, + SmallVectorImpl &Vals); + void skipAbbreviatedField(const BitCodeAbbrevOp &Op); + public: /// getAbbrev - Return the abbreviation for the specified AbbrevId. @@ -522,6 +503,9 @@ public: return CurAbbrevs[AbbrevNo]; } + /// skipRecord - Read the current record and discard it. + void skipRecord(unsigned AbbrevID); + unsigned ReadRecord(unsigned AbbrevID, SmallVectorImpl &Vals, const char **BlobStart = 0, unsigned *BlobLen = 0); @@ -530,7 +514,6 @@ public: return ReadRecord(AbbrevID, Vals, &BlobStart, &BlobLen); } - //===--------------------------------------------------------------------===// // Abbrev Processing //===--------------------------------------------------------------------===// -- cgit v1.2.3-18-g5258 From 194ef24dfedf62642c853a851db4d7e528d27460 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 20 Jan 2013 01:06:48 +0000 Subject: stringref'ize readRecord and properly capitalize it. Add a compatibility method to easy the transition. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172940 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index d6d9e34868..3e8d880da4 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -506,9 +506,20 @@ public: /// skipRecord - Read the current record and discard it. void skipRecord(unsigned AbbrevID); + unsigned readRecord(unsigned AbbrevID, SmallVectorImpl &Vals, + StringRef *Blob = 0); + unsigned ReadRecord(unsigned AbbrevID, SmallVectorImpl &Vals, - const char **BlobStart = 0, unsigned *BlobLen = 0); - + const char **BlobStart = 0, unsigned *BlobLen = 0) { + if (!BlobStart) + return readRecord(AbbrevID, Vals); + StringRef S; + unsigned X = readRecord(AbbrevID, Vals, &S); + *BlobStart = S.data(); + *BlobLen = S.size(); + return X; + } + unsigned ReadRecord(unsigned AbbrevID, SmallVectorImpl &Vals, const char *&BlobStart, unsigned &BlobLen) { return ReadRecord(AbbrevID, Vals, &BlobStart, &BlobLen); -- cgit v1.2.3-18-g5258 From 099b636562a83dc9acc6bf36ca32d710ac6d62c9 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 20 Jan 2013 02:12:39 +0000 Subject: add an option to not auto-process abbreviations in advance() git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172946 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 3e8d880da4..3e299e9e4c 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -159,7 +159,6 @@ struct BitstreamEntry { } }; - /// BitstreamCursor - This represents a position within a bitcode file. There /// may be multiple independent cursors reading within one bitstream, each /// maintaining their own local state. @@ -271,7 +270,14 @@ public: /// Flags that modify the behavior of advance(). enum { - AF_DontPopBlockAtEnd = 1 + /// AF_DontPopBlockAtEnd - If this flag is used, the advance() method does + /// not automatically pop the block scope when the end of a block is + /// reached. + AF_DontPopBlockAtEnd = 1, + + /// AF_DontAutoprocessAbbrevs - If this flag is used, abbrev entries are + /// returned just like normal records. + AF_DontAutoprocessAbbrevs = 2 }; /// advance - Advance the current bitstream, returning the next entry in the @@ -289,7 +295,8 @@ public: if (Code == bitc::ENTER_SUBBLOCK) return BitstreamEntry::getSubBlock(ReadSubBlockID()); - if (Code == bitc::DEFINE_ABBREV) { + if (Code == bitc::DEFINE_ABBREV && + !(Flags & AF_DontAutoprocessAbbrevs)) { // We read and accumulate abbrev's, the client can't do anything with // them anyway. ReadAbbrevRecord(); @@ -483,7 +490,7 @@ private: BlockScope.pop_back(); } - //===--------------------------------------------------------------------===// + //===--------------------------------------------------------------------===// // Record Processing //===--------------------------------------------------------------------===// -- cgit v1.2.3-18-g5258 From 4156ca76e31877b17063a6e01fb7f1dad771c5aa Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 20 Jan 2013 02:50:32 +0000 Subject: switch llvm-bcanalyzer onto the new cursor APIs, allowing deletion of the old ReadRecord methods. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172952 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 3e299e9e4c..0d9bd3e466 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -158,6 +158,7 @@ struct BitstreamEntry { BitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E; } }; + /// BitstreamCursor - This represents a position within a bitcode file. There /// may be multiple independent cursors reading within one bitstream, each @@ -516,22 +517,6 @@ public: unsigned readRecord(unsigned AbbrevID, SmallVectorImpl &Vals, StringRef *Blob = 0); - unsigned ReadRecord(unsigned AbbrevID, SmallVectorImpl &Vals, - const char **BlobStart = 0, unsigned *BlobLen = 0) { - if (!BlobStart) - return readRecord(AbbrevID, Vals); - StringRef S; - unsigned X = readRecord(AbbrevID, Vals, &S); - *BlobStart = S.data(); - *BlobLen = S.size(); - return X; - } - - unsigned ReadRecord(unsigned AbbrevID, SmallVectorImpl &Vals, - const char *&BlobStart, unsigned &BlobLen) { - return ReadRecord(AbbrevID, Vals, &BlobStart, &BlobLen); - } - //===--------------------------------------------------------------------===// // Abbrev Processing //===--------------------------------------------------------------------===// -- cgit v1.2.3-18-g5258 From 1ca114a66b666f932741d00d74636dc35ea1d466 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 20 Jan 2013 02:54:05 +0000 Subject: trivial micro-optimization: lazily call the virtual method instead of eagerly calling it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172953 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 0d9bd3e466..847aaade76 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -158,7 +158,6 @@ struct BitstreamEntry { BitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E; } }; - /// BitstreamCursor - This represents a position within a bitcode file. There /// may be multiple independent cursors reading within one bitstream, each @@ -251,7 +250,7 @@ public: } bool AtEndOfStream() { - return isEndPos(NextChar) && BitsInCurWord == 0; + return BitsInCurWord == 0 && isEndPos(NextChar); } /// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #. -- cgit v1.2.3-18-g5258 From fd0543d9be9886398628e411aba8c392b28d17b6 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 21 Jan 2013 18:04:19 +0000 Subject: rename "SkipToWord" to "SkipToFourByteBoundary" since a word is not always 4 bytes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@173062 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 847aaade76..16f9686a93 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -422,7 +422,7 @@ public: } } - void SkipToWord() { + void SkipToFourByteBoundary() { BitsInCurWord = 0; CurWord = 0; } @@ -448,7 +448,7 @@ public: // Read and ignore the codelen value. Since we are skipping this block, we // don't care what code widths are used inside of it. ReadVBR(bitc::CodeLenWidth); - SkipToWord(); + SkipToFourByteBoundary(); unsigned NumWords = Read(bitc::BlockSizeWidth); // Check that the block wasn't partially defined, and that the offset isn't @@ -470,7 +470,7 @@ public: // Block tail: // [END_BLOCK, ] - SkipToWord(); + SkipToFourByteBoundary(); popBlockScope(); return false; -- cgit v1.2.3-18-g5258 From 69582cf6c46456ad542df5aa09c47700c9525645 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 21 Jan 2013 18:24:49 +0000 Subject: Fix a heinous inefficiency introduced in r149918, wherein reading each byte of a BLOB (i.e., large, performance intensive data) in a bitcode file was switched to invoking one virtual method call per byte read. Now we do one virtual call per BLOB. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@173065 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 16f9686a93..c143886b2c 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -237,12 +237,6 @@ public: static_cast(pos - 1)); } - unsigned char getByte(size_t pos) { - uint8_t byte = -1; - BitStream->getBitcodeBytes().readByte(pos, &byte); - return byte; - } - uint32_t getWord(size_t pos) { uint8_t buf[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; BitStream->getBitcodeBytes().readBytes(pos, sizeof(buf), buf, NULL); -- cgit v1.2.3-18-g5258 From 02b206f6d817b005799cbeca119376c034679212 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 21 Jan 2013 18:48:26 +0000 Subject: rework the Bitstream reader to actually work a machine word at a time, instead of 32-bits at a time. This cuts in half the number of virtual methods called to refill that word when compiling on a 64-bit host, and will make 64-bit read operations faster. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@173072 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 70 ++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 21 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index c143886b2c..5e5c64bdd1 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -170,12 +170,17 @@ class BitstreamCursor { BitstreamReader *BitStream; size_t NextChar; - /// CurWord - This is the current data we have pulled from the stream but have - /// not returned to the client. - uint32_t CurWord; + + /// 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 + /// efficiency. We use word_t in places that are aware of this to make it + /// perfectly explicit what is going on. + typedef size_t word_t; + word_t CurWord; /// BitsInCurWord - This is the number of bits in CurWord that are valid. This - /// is always from [0...31] inclusive. + /// is always from [0...31/63] inclusive (depending on word size). unsigned BitsInCurWord; // CurCodeSize - This is the declared size of code values used for the current @@ -318,8 +323,8 @@ public: /// JumpToBit - Reset the stream to the specified bit number. void JumpToBit(uint64_t BitNo) { - uintptr_t ByteNo = uintptr_t(BitNo/8) & ~3; - uintptr_t WordBitNo = uintptr_t(BitNo) & 31; + uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); + unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); assert(canSkipToPos(ByteNo) && "Invalid location"); // Move the cursor to the right word. @@ -328,8 +333,12 @@ public: CurWord = 0; // Skip over any bits that are already consumed. - if (WordBitNo) - Read(static_cast(WordBitNo)); + if (WordBitNo) { + if (sizeof(word_t) > 4) + Read64(WordBitNo); + else + Read(WordBitNo); + } } @@ -337,7 +346,7 @@ public: assert(NumBits <= 32 && "Cannot return more than 32 bits!"); // If the field is fully contained by CurWord, return it quickly. if (BitsInCurWord >= NumBits) { - uint32_t R = CurWord & ((1U << NumBits)-1); + uint32_t R = uint32_t(CurWord) & (~0U >> (32-NumBits)); CurWord >>= NumBits; BitsInCurWord -= NumBits; return R; @@ -350,24 +359,32 @@ public: return 0; } - unsigned R = CurWord; + uint32_t R = uint32_t(CurWord); // Read the next word from the stream. - CurWord = getWord(NextChar); - NextChar += 4; + uint8_t buf[sizeof(word_t)] = {0}; + BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(buf), buf, NULL); + + typedef support::detail::packed_endian_specific_integral + Endian_T; + CurWord = *reinterpret_cast(buf); + + NextChar += sizeof(word_t); // Extract NumBits-BitsInCurWord from what we just read. unsigned BitsLeft = NumBits-BitsInCurWord; - // Be careful here, BitsLeft is in the range [1..32] inclusive. - R |= (CurWord & (~0U >> (32-BitsLeft))) << BitsInCurWord; + // 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); - // BitsLeft bits have just been used up from CurWord. - if (BitsLeft != 32) + // 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 = 32-BitsLeft; + BitsInCurWord = sizeof(word_t)*8-BitsLeft; return R; } @@ -416,10 +433,21 @@ public: } } +private: void SkipToFourByteBoundary() { + // If word_t is 64-bits and if we've read less than 32 bits, just dump + // the bits we have up to the next 32-bit boundary. + if (sizeof(word_t) > 4 && + BitsInCurWord > 32) { + CurWord >>= BitsInCurWord-32; + BitsInCurWord = 32; + return; + } + BitsInCurWord = 0; CurWord = 0; } +public: unsigned ReadCode() { return Read(CurCodeSize); @@ -443,15 +471,15 @@ public: // don't care what code widths are used inside of it. ReadVBR(bitc::CodeLenWidth); SkipToFourByteBoundary(); - unsigned NumWords = Read(bitc::BlockSizeWidth); + unsigned NumFourBytes = Read(bitc::BlockSizeWidth); // Check that the block wasn't partially defined, and that the offset isn't // bogus. - size_t SkipTo = NextChar + NumWords*4; - if (AtEndOfStream() || !canSkipToPos(SkipTo)) + size_t SkipTo = GetCurrentBitNo() + NumFourBytes*4*8; + if (AtEndOfStream() || !canSkipToPos(SkipTo/8)) return true; - NextChar = SkipTo; + JumpToBit(SkipTo); return false; } -- cgit v1.2.3-18-g5258 From dc60fc1aa710812be17c5b01f34ef251c87b42b4 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 21 Jan 2013 19:08:15 +0000 Subject: r173072 is causing some regressions on big endian hosts, I don't have time to debug it so revert it for now. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@173074 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 70 ++++++++++------------------------ 1 file changed, 21 insertions(+), 49 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 5e5c64bdd1..c143886b2c 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -170,17 +170,12 @@ class BitstreamCursor { BitstreamReader *BitStream; size_t NextChar; - - /// 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 - /// efficiency. We use word_t in places that are aware of this to make it - /// perfectly explicit what is going on. - typedef size_t word_t; - word_t CurWord; + /// CurWord - This is the current data we have pulled from the stream but have + /// not returned to the client. + uint32_t CurWord; /// BitsInCurWord - This is the number of bits in CurWord that are valid. This - /// is always from [0...31/63] inclusive (depending on word size). + /// is always from [0...31] inclusive. unsigned BitsInCurWord; // CurCodeSize - This is the declared size of code values used for the current @@ -323,8 +318,8 @@ public: /// JumpToBit - Reset the stream to the specified bit number. void JumpToBit(uint64_t BitNo) { - uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); - unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); + uintptr_t ByteNo = uintptr_t(BitNo/8) & ~3; + uintptr_t WordBitNo = uintptr_t(BitNo) & 31; assert(canSkipToPos(ByteNo) && "Invalid location"); // Move the cursor to the right word. @@ -333,12 +328,8 @@ public: CurWord = 0; // Skip over any bits that are already consumed. - if (WordBitNo) { - if (sizeof(word_t) > 4) - Read64(WordBitNo); - else - Read(WordBitNo); - } + if (WordBitNo) + Read(static_cast(WordBitNo)); } @@ -346,7 +337,7 @@ public: assert(NumBits <= 32 && "Cannot return 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)); + uint32_t R = CurWord & ((1U << NumBits)-1); CurWord >>= NumBits; BitsInCurWord -= NumBits; return R; @@ -359,32 +350,24 @@ public: return 0; } - uint32_t R = uint32_t(CurWord); + unsigned R = CurWord; // Read the next word from the stream. - uint8_t buf[sizeof(word_t)] = {0}; - BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(buf), buf, NULL); - - typedef support::detail::packed_endian_specific_integral - Endian_T; - CurWord = *reinterpret_cast(buf); - - NextChar += sizeof(word_t); + CurWord = getWord(NextChar); + NextChar += 4; // Extract NumBits-BitsInCurWord from what we just read. unsigned BitsLeft = NumBits-BitsInCurWord; - // 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); + // Be careful here, BitsLeft is in the range [1..32] inclusive. + R |= (CurWord & (~0U >> (32-BitsLeft))) << BitsInCurWord; - // 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) + // BitsLeft bits have just been used up from CurWord. + if (BitsLeft != 32) CurWord >>= BitsLeft; else CurWord = 0; - BitsInCurWord = sizeof(word_t)*8-BitsLeft; + BitsInCurWord = 32-BitsLeft; return R; } @@ -433,21 +416,10 @@ public: } } -private: void SkipToFourByteBoundary() { - // If word_t is 64-bits and if we've read less than 32 bits, just dump - // the bits we have up to the next 32-bit boundary. - if (sizeof(word_t) > 4 && - BitsInCurWord > 32) { - CurWord >>= BitsInCurWord-32; - BitsInCurWord = 32; - return; - } - BitsInCurWord = 0; CurWord = 0; } -public: unsigned ReadCode() { return Read(CurCodeSize); @@ -471,15 +443,15 @@ public: // don't care what code widths are used inside of it. ReadVBR(bitc::CodeLenWidth); SkipToFourByteBoundary(); - unsigned NumFourBytes = Read(bitc::BlockSizeWidth); + unsigned NumWords = Read(bitc::BlockSizeWidth); // Check that the block wasn't partially defined, and that the offset isn't // bogus. - size_t SkipTo = GetCurrentBitNo() + NumFourBytes*4*8; - if (AtEndOfStream() || !canSkipToPos(SkipTo/8)) + size_t SkipTo = NextChar + NumWords*4; + if (AtEndOfStream() || !canSkipToPos(SkipTo)) return true; - JumpToBit(SkipTo); + NextChar = SkipTo; return false; } -- cgit v1.2.3-18-g5258 From e001f27e5ebc325b5b142f3661d04ba39251e07b Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 9 Feb 2013 06:52:14 +0000 Subject: recommit r173072 (preparing bitstream reader to read a machine word at a time, instead of always 32-bits at a time) with two changes: 1. Make Read(0) always return zero without affecting the state of our cursor. 2. Hack word_t to always be 32 bits, as staging. These two caveats will change shortly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174800 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 72 ++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 21 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index c143886b2c..1b29c3e639 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -170,12 +170,17 @@ class BitstreamCursor { BitstreamReader *BitStream; size_t NextChar; - /// CurWord - This is the current data we have pulled from the stream but have - /// not returned to the client. - uint32_t CurWord; + + /// 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 + /// efficiency. We use word_t in places that are aware of this to make it + /// perfectly explicit what is going on. + typedef uint32_t word_t; + word_t CurWord; /// BitsInCurWord - This is the number of bits in CurWord that are valid. This - /// is always from [0...31] inclusive. + /// is always from [0...31/63] inclusive (depending on word size). unsigned BitsInCurWord; // CurCodeSize - This is the declared size of code values used for the current @@ -318,8 +323,8 @@ public: /// JumpToBit - Reset the stream to the specified bit number. void JumpToBit(uint64_t BitNo) { - uintptr_t ByteNo = uintptr_t(BitNo/8) & ~3; - uintptr_t WordBitNo = uintptr_t(BitNo) & 31; + uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); + unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); assert(canSkipToPos(ByteNo) && "Invalid location"); // Move the cursor to the right word. @@ -328,16 +333,22 @@ public: CurWord = 0; // Skip over any bits that are already consumed. - if (WordBitNo) - Read(static_cast(WordBitNo)); + if (WordBitNo) { + if (sizeof(word_t) > 4) + Read64(WordBitNo); + else + Read(WordBitNo); + } } uint32_t Read(unsigned NumBits) { assert(NumBits <= 32 && "Cannot return more than 32 bits!"); + if (NumBits == 0) return 0; + // If the field is fully contained by CurWord, return it quickly. if (BitsInCurWord >= NumBits) { - uint32_t R = CurWord & ((1U << NumBits)-1); + uint32_t R = uint32_t(CurWord) & (~0U >> (32-NumBits)); CurWord >>= NumBits; BitsInCurWord -= NumBits; return R; @@ -350,24 +361,32 @@ public: return 0; } - unsigned R = CurWord; + uint32_t R = uint32_t(CurWord); // Read the next word from the stream. - CurWord = getWord(NextChar); - NextChar += 4; + uint8_t buf[sizeof(word_t)] = {0}; + BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(buf), buf, NULL); + + typedef support::detail::packed_endian_specific_integral + Endian_T; + CurWord = *reinterpret_cast(buf); + + NextChar += sizeof(word_t); // Extract NumBits-BitsInCurWord from what we just read. unsigned BitsLeft = NumBits-BitsInCurWord; - // Be careful here, BitsLeft is in the range [1..32] inclusive. - R |= (CurWord & (~0U >> (32-BitsLeft))) << BitsInCurWord; + // 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); - // BitsLeft bits have just been used up from CurWord. - if (BitsLeft != 32) + // 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 = 32-BitsLeft; + BitsInCurWord = sizeof(word_t)*8-BitsLeft; return R; } @@ -416,10 +435,21 @@ public: } } +private: void SkipToFourByteBoundary() { + // If word_t is 64-bits and if we've read less than 32 bits, just dump + // the bits we have up to the next 32-bit boundary. + if (sizeof(word_t) > 4 && + BitsInCurWord > 32) { + CurWord >>= BitsInCurWord-32; + BitsInCurWord = 32; + return; + } + BitsInCurWord = 0; CurWord = 0; } +public: unsigned ReadCode() { return Read(CurCodeSize); @@ -443,15 +473,15 @@ public: // don't care what code widths are used inside of it. ReadVBR(bitc::CodeLenWidth); SkipToFourByteBoundary(); - unsigned NumWords = Read(bitc::BlockSizeWidth); + unsigned NumFourBytes = Read(bitc::BlockSizeWidth); // Check that the block wasn't partially defined, and that the offset isn't // bogus. - size_t SkipTo = NextChar + NumWords*4; - if (AtEndOfStream() || !canSkipToPos(SkipTo)) + size_t SkipTo = GetCurrentBitNo() + NumFourBytes*4*8; + if (AtEndOfStream() || !canSkipToPos(SkipTo/8)) return true; - NextChar = SkipTo; + JumpToBit(SkipTo); return false; } -- cgit v1.2.3-18-g5258 From b24f5b7c0838f22abc6f1ba5de2a17d25293cd17 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 9 Feb 2013 07:07:29 +0000 Subject: Fix the underlying problem that was causing read(0) to be called: sometimes the bitcode writer would generate abbrev records saying that the abbrev should be filled with fixed zero-bit bitfields (this happens in the .bc writer when the number of types used in a module is exactly one, since log2(1) == 0). In this case, just handle it as a literal zero. We can't "just fix" the writer without breaking compatibility with existing bc files, so have the abbrev reader do the substitution. Strengthen the assert in read to reject reads of zero bits so we catch such crimes in the future, and remove the special case designed to handle this. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174801 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 1b29c3e639..56a610883b 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -343,8 +343,8 @@ public: uint32_t Read(unsigned NumBits) { - assert(NumBits <= 32 && "Cannot return more than 32 bits!"); - if (NumBits == 0) return 0; + 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) { -- cgit v1.2.3-18-g5258 From a32bd682a0ba4878b89c4d70b189ee3feaa01452 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 9 Feb 2013 07:37:26 +0000 Subject: Fix a nasty off-by one error that only manifests with 64-bit word size (which is not enabled yet). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174803 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 56a610883b..dabee54732 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -334,7 +334,7 @@ public: // Skip over any bits that are already consumed. if (WordBitNo) { - if (sizeof(word_t) > 4) + if (sizeof(word_t) >= 4) Read64(WordBitNo); else Read(WordBitNo); -- cgit v1.2.3-18-g5258 From db5e50ddafa3903e9ca9ee4008d6e6fa82f780ea Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 9 Feb 2013 07:37:59 +0000 Subject: This is the correct version of r174802. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174804 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index dabee54732..dfbb5e2a65 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -334,7 +334,7 @@ public: // Skip over any bits that are already consumed. if (WordBitNo) { - if (sizeof(word_t) >= 4) + if (sizeof(word_t) > 4) Read64(WordBitNo); else Read(WordBitNo); @@ -440,7 +440,7 @@ private: // If word_t is 64-bits and if we've read less than 32 bits, just dump // the bits we have up to the next 32-bit boundary. if (sizeof(word_t) > 4 && - BitsInCurWord > 32) { + BitsInCurWord >= 32) { CurWord >>= BitsInCurWord-32; BitsInCurWord = 32; return; -- cgit v1.2.3-18-g5258 From bf8f4cb0d5edc30854be46ec394d267b0c6013cd Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 10 Feb 2013 05:45:34 +0000 Subject: attempt to defeat a gcc warning that is breaking a -Werror buildbot. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174825 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index dfbb5e2a65..9a8c370f00 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -369,7 +369,7 @@ public: typedef support::detail::packed_endian_specific_integral Endian_T; - CurWord = *reinterpret_cast(buf); + CurWord = *(Endian_T*)(void*)buf; NextChar += sizeof(word_t); -- cgit v1.2.3-18-g5258 From 10b043e2ab08f234780b9b5dec39f5478e211f60 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 10 Feb 2013 06:07:16 +0000 Subject: hopefully "really" fix a type punning warning by defining the buffer as type char, which can't have TBAA tags. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174826 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 9a8c370f00..48a6989deb 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -364,12 +364,13 @@ public: uint32_t R = uint32_t(CurWord); // Read the next word from the stream. - uint8_t buf[sizeof(word_t)] = {0}; - BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(buf), buf, NULL); + char buf[sizeof(word_t)] = {0}; + BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(buf), + (uint8_t*)buf, NULL); typedef support::detail::packed_endian_specific_integral Endian_T; - CurWord = *(Endian_T*)(void*)buf; + CurWord = *(Endian_T*)buf; NextChar += sizeof(word_t); -- cgit v1.2.3-18-g5258 From e9288fbe4df5c912f5bb42c33a675b61d45c0a99 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 10 Feb 2013 06:36:29 +0000 Subject: ok, ok, stop fighting type punning warnings by just using a union. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174827 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 48a6989deb..edec6e1da5 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -364,13 +364,16 @@ public: uint32_t R = uint32_t(CurWord); // Read the next word from the stream. - char buf[sizeof(word_t)] = {0}; - BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(buf), - (uint8_t*)buf, NULL); + union { + uint8_t ArrayMember[sizeof(word_t)]; + support::detail::packed_endian_specific_integral + EndianMember; + } buf = { { 0 } }; - typedef support::detail::packed_endian_specific_integral - Endian_T; - CurWord = *(Endian_T*)buf; + BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(buf), + buf.ArrayMember, NULL); + // Handle big-endian byte-swapping if necessary. + CurWord = buf.EndianMember; NextChar += sizeof(word_t); -- cgit v1.2.3-18-g5258 From 519e1475d64d80f4632296318b3a5240d4f70a72 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 13 Feb 2013 04:53:40 +0000 Subject: use memcpy instead of dubious union to type pun two values, thanks to David Blaike for pointing this out. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@175032 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/BitstreamReader.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'include/llvm/Bitcode/BitstreamReader.h') diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index edec6e1da5..2d2976cde1 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -364,16 +364,17 @@ public: uint32_t R = uint32_t(CurWord); // Read the next word from the stream. - union { - uint8_t ArrayMember[sizeof(word_t)]; - support::detail::packed_endian_specific_integral - EndianMember; - } buf = { { 0 } }; + uint8_t Array[sizeof(word_t)] = {0}; + + BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(Array), + Array, NULL); - BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(buf), - buf.ArrayMember, NULL); // Handle big-endian byte-swapping if necessary. - CurWord = buf.EndianMember; + support::detail::packed_endian_specific_integral + EndianValue; + memcpy(&EndianValue, Array, sizeof(Array)); + + CurWord = EndianValue; NextChar += sizeof(word_t); -- cgit v1.2.3-18-g5258