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 --- lib/Bitcode/Reader/BitstreamReader.cpp | 253 +++++++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 lib/Bitcode/Reader/BitstreamReader.cpp (limited to 'lib/Bitcode/Reader/BitstreamReader.cpp') diff --git a/lib/Bitcode/Reader/BitstreamReader.cpp b/lib/Bitcode/Reader/BitstreamReader.cpp new file mode 100644 index 0000000000..abc78acce7 --- /dev/null +++ b/lib/Bitcode/Reader/BitstreamReader.cpp @@ -0,0 +1,253 @@ +//===- BitstreamReader.cpp - BitstreamReader implementation ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Bitcode/BitstreamReader.h" + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// BitstreamCursor implementation +//===----------------------------------------------------------------------===// + +void BitstreamCursor::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 BitstreamCursor::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(); +} + +/// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter +/// the block, and return true if the block has an error. +bool BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) { + // 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; +} + + +unsigned BitstreamCursor::ReadRecord(unsigned AbbrevID, + SmallVectorImpl &Vals, + const char **BlobStart, unsigned *BlobLen){ + 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); + continue; + } + + if (Op.getEncoding() != BitCodeAbbrevOp::Array && + Op.getEncoding() != BitCodeAbbrevOp::Blob) { + ReadAbbreviatedField(Op, Vals); + continue; + } + + 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); + continue; + } + + assert(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; + } + + unsigned Code = (unsigned)Vals[0]; + Vals.erase(Vals.begin()); + return Code; +} + + +void BitstreamCursor::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); +} + +bool BitstreamCursor::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; + } + } + } +} + + -- 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 --- lib/Bitcode/Reader/BitstreamReader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/Bitcode/Reader/BitstreamReader.cpp') diff --git a/lib/Bitcode/Reader/BitstreamReader.cpp b/lib/Bitcode/Reader/BitstreamReader.cpp index abc78acce7..a5a7c0b8ee 100644 --- a/lib/Bitcode/Reader/BitstreamReader.cpp +++ b/lib/Bitcode/Reader/BitstreamReader.cpp @@ -150,7 +150,7 @@ unsigned BitstreamCursor::ReadRecord(unsigned AbbrevID, // the data, do so to avoid copying it. if (BlobStart) { *BlobStart = (const char*)BitStream->getBitcodeBytes().getPointer( - NextChar, NumElts); + NextChar, NumElts); *BlobLen = NumElts; } else { for (; NumElts; ++NextChar, --NumElts) -- 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 --- lib/Bitcode/Reader/BitstreamReader.cpp | 114 ++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 3 deletions(-) (limited to 'lib/Bitcode/Reader/BitstreamReader.cpp') diff --git a/lib/Bitcode/Reader/BitstreamReader.cpp b/lib/Bitcode/Reader/BitstreamReader.cpp index a5a7c0b8ee..be70f5213b 100644 --- a/lib/Bitcode/Reader/BitstreamReader.cpp +++ b/lib/Bitcode/Reader/BitstreamReader.cpp @@ -89,6 +89,114 @@ bool BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) { return false; } +void BitstreamCursor::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 BitstreamCursor::readAbbreviatedField(const BitCodeAbbrevOp &Op, + SmallVectorImpl &Vals) { + assert(!Op.isLiteral() && "Use ReadAbbreviatedLiteral for literals!"); + + // Decode the value as we are commanded. + switch (Op.getEncoding()) { + case BitCodeAbbrevOp::Array: + case BitCodeAbbrevOp::Blob: + assert(0 && "Should not reach here"); + 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 BitstreamCursor::skipAbbreviatedField(const BitCodeAbbrevOp &Op) { + assert(!Op.isLiteral() && "Use ReadAbbreviatedLiteral for literals!"); + + // Decode the value as we are commanded. + switch (Op.getEncoding()) { + case BitCodeAbbrevOp::Array: + case BitCodeAbbrevOp::Blob: + assert(0 && "Should not reach here"); + case BitCodeAbbrevOp::Fixed: + (void)Read((unsigned)Op.getEncodingData()); + break; + case BitCodeAbbrevOp::VBR: + (void)ReadVBR64((unsigned)Op.getEncodingData()); + break; + case BitCodeAbbrevOp::Char6: + (void)Read(6); + break; + } +} + + + +/// skipRecord - Read the current record and discard it. +void BitstreamCursor::skipRecord(unsigned AbbrevID) { + // Skip unabbreviated records by reading past their entries. + if (AbbrevID == bitc::UNABBREV_RECORD) { + unsigned Code = ReadVBR(6); + (void)Code; + unsigned NumElts = ReadVBR(6); + for (unsigned i = 0; i != NumElts; ++i) + (void)ReadVBR64(6); + return; + } + + const BitCodeAbbrev *Abbv = getAbbrev(AbbrevID); + + for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) { + const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); + if (Op.isLiteral()) + continue; + + if (Op.getEncoding() != BitCodeAbbrevOp::Array && + Op.getEncoding() != BitCodeAbbrevOp::Blob) { + skipAbbreviatedField(Op); + continue; + } + + 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) + skipAbbreviatedField(EltEnc); + continue; + } + + assert(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)) { + NextChar = BitStream->getBitcodeBytes().getExtent(); + break; + } + + // Skip over the blob. + NextChar = NewEnd; + } +} unsigned BitstreamCursor::ReadRecord(unsigned AbbrevID, SmallVectorImpl &Vals, @@ -106,13 +214,13 @@ unsigned BitstreamCursor::ReadRecord(unsigned AbbrevID, for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) { const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); if (Op.isLiteral()) { - ReadAbbreviatedLiteral(Op, Vals); + readAbbreviatedLiteral(Op, Vals); continue; } if (Op.getEncoding() != BitCodeAbbrevOp::Array && Op.getEncoding() != BitCodeAbbrevOp::Blob) { - ReadAbbreviatedField(Op, Vals); + readAbbreviatedField(Op, Vals); continue; } @@ -126,7 +234,7 @@ unsigned BitstreamCursor::ReadRecord(unsigned AbbrevID, // Read all the elements. for (; NumElts; --NumElts) - ReadAbbreviatedField(EltEnc, Vals); + readAbbreviatedField(EltEnc, Vals); continue; } -- 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 --- lib/Bitcode/Reader/BitstreamReader.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'lib/Bitcode/Reader/BitstreamReader.cpp') diff --git a/lib/Bitcode/Reader/BitstreamReader.cpp b/lib/Bitcode/Reader/BitstreamReader.cpp index be70f5213b..84d5ca6150 100644 --- a/lib/Bitcode/Reader/BitstreamReader.cpp +++ b/lib/Bitcode/Reader/BitstreamReader.cpp @@ -198,9 +198,9 @@ void BitstreamCursor::skipRecord(unsigned AbbrevID) { } } -unsigned BitstreamCursor::ReadRecord(unsigned AbbrevID, +unsigned BitstreamCursor::readRecord(unsigned AbbrevID, SmallVectorImpl &Vals, - const char **BlobStart, unsigned *BlobLen){ + StringRef *Blob) { if (AbbrevID == bitc::UNABBREV_RECORD) { unsigned Code = ReadVBR(6); unsigned NumElts = ReadVBR(6); @@ -256,10 +256,11 @@ unsigned BitstreamCursor::ReadRecord(unsigned AbbrevID, // 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; + if (Blob) { + *Blob = + StringRef((const char*)BitStream->getBitcodeBytes().getPointer( + NextChar, NumElts), + NumElts); } else { for (; NumElts; ++NextChar, --NumElts) Vals.push_back(getByte(NextChar)); -- cgit v1.2.3-18-g5258 From 5a4251c767adb7a47ad7a53719398ee1342cc400 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 20 Jan 2013 02:13:19 +0000 Subject: convert the bitstream reader itself and the IR .bc file parser to use the new advance() APIs, simplifying things and making a bunch of details more private to BitstreamCursor. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172947 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Bitcode/Reader/BitstreamReader.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'lib/Bitcode/Reader/BitstreamReader.cpp') diff --git a/lib/Bitcode/Reader/BitstreamReader.cpp b/lib/Bitcode/Reader/BitstreamReader.cpp index 84d5ca6150..83df57b8fb 100644 --- a/lib/Bitcode/Reader/BitstreamReader.cpp +++ b/lib/Bitcode/Reader/BitstreamReader.cpp @@ -306,17 +306,21 @@ bool BitstreamCursor::ReadBlockInfoBlock() { // 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; - } + BitstreamEntry Entry = advanceSkippingSubblocks(AF_DontAutoprocessAbbrevs); + switch (Entry.Kind) { + case llvm::BitstreamEntry::SubBlock: // Handled for us already. + case llvm::BitstreamEntry::Error: + return true; + case llvm::BitstreamEntry::EndBlock: + return false; + case llvm::BitstreamEntry::Record: + // The interesting case. + break; + } + // Read abbrev records, associate them with CurBID. - if (Code == bitc::DEFINE_ABBREV) { + if (Entry.ID == bitc::DEFINE_ABBREV) { if (!CurBlockInfo) return true; ReadAbbrevRecord(); @@ -330,7 +334,7 @@ bool BitstreamCursor::ReadBlockInfoBlock() { // Read a record. Record.clear(); - switch (ReadRecord(Code, Record)) { + switch (readRecord(Entry.ID, Record)) { default: break; // Default behavior, ignore unknown content. case bitc::BLOCKINFO_CODE_SETBID: if (Record.size() < 1) return true; -- 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 --- lib/Bitcode/Reader/BitstreamReader.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/Bitcode/Reader/BitstreamReader.cpp') diff --git a/lib/Bitcode/Reader/BitstreamReader.cpp b/lib/Bitcode/Reader/BitstreamReader.cpp index 83df57b8fb..eb8b5dea72 100644 --- a/lib/Bitcode/Reader/BitstreamReader.cpp +++ b/lib/Bitcode/Reader/BitstreamReader.cpp @@ -78,7 +78,7 @@ bool BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) { // Get the codesize of this block. CurCodeSize = ReadVBR(bitc::CodeLenWidth); - SkipToWord(); + SkipToFourByteBoundary(); unsigned NumWords = Read(bitc::BlockSizeWidth); if (NumWordsP) *NumWordsP = NumWords; @@ -181,7 +181,7 @@ void BitstreamCursor::skipRecord(unsigned AbbrevID) { assert(Op.getEncoding() == BitCodeAbbrevOp::Blob); // Blob case. Read the number of bytes as a vbr6. unsigned NumElts = ReadVBR(6); - SkipToWord(); // 32-bit alignment + SkipToFourByteBoundary(); // 32-bit alignment // Figure out where the end of this blob will be including tail padding. size_t NewEnd = NextChar+((NumElts+3)&~3); @@ -241,7 +241,7 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID, assert(Op.getEncoding() == BitCodeAbbrevOp::Blob); // Blob case. Read the number of bytes as a vbr6. unsigned NumElts = ReadVBR(6); - SkipToWord(); // 32-bit alignment + SkipToFourByteBoundary(); // 32-bit alignment // Figure out where the end of this blob will be including tail padding. size_t NewEnd = NextChar+((NumElts+3)&~3); -- cgit v1.2.3-18-g5258 From 47543a8a66fb9451126f134808b55853aca57e1c Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 21 Jan 2013 18:18:25 +0000 Subject: wean Blob handling logic off of banging on NextChar directly. Instead, make it reason about the current bit position, which is always independent of the underlying cursors word size. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@173063 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Bitcode/Reader/BitstreamReader.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'lib/Bitcode/Reader/BitstreamReader.cpp') diff --git a/lib/Bitcode/Reader/BitstreamReader.cpp b/lib/Bitcode/Reader/BitstreamReader.cpp index eb8b5dea72..92133bb969 100644 --- a/lib/Bitcode/Reader/BitstreamReader.cpp +++ b/lib/Bitcode/Reader/BitstreamReader.cpp @@ -184,17 +184,17 @@ void BitstreamCursor::skipRecord(unsigned AbbrevID) { SkipToFourByteBoundary(); // 32-bit alignment // Figure out where the end of this blob will be including tail padding. - size_t NewEnd = NextChar+((NumElts+3)&~3); + size_t NewEnd = GetCurrentBitNo()+((NumElts+3)&~3)*8; // If this would read off the end of the bitcode file, just set the // record to empty and return. - if (!canSkipToPos(NewEnd)) { + if (!canSkipToPos(NewEnd/8)) { NextChar = BitStream->getBitcodeBytes().getExtent(); break; } // Skip over the blob. - NextChar = NewEnd; + JumpToBit(NewEnd); } } @@ -244,11 +244,12 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID, SkipToFourByteBoundary(); // 32-bit alignment // Figure out where the end of this blob will be including tail padding. - size_t NewEnd = NextChar+((NumElts+3)&~3); + size_t CurBitPos = GetCurrentBitNo(); + size_t NewEnd = CurBitPos+((NumElts+3)&~3)*8; // If this would read off the end of the bitcode file, just set the // record to empty and return. - if (!canSkipToPos(NewEnd)) { + if (!canSkipToPos(NewEnd/8)) { Vals.append(NumElts, 0); NextChar = BitStream->getBitcodeBytes().getExtent(); break; @@ -259,14 +260,16 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID, if (Blob) { *Blob = StringRef((const char*)BitStream->getBitcodeBytes().getPointer( - NextChar, NumElts), - NumElts); + CurBitPos/8, NumElts), + NumElts); } else { - for (; NumElts; ++NextChar, --NumElts) - Vals.push_back(getByte(NextChar)); + // FIXME: This is a brutally inefficient way to do this. Why isn't this + // just using getPointer? + for (; NumElts; --NumElts) + Vals.push_back(Read(8)); } // Skip over tail padding. - NextChar = NewEnd; + JumpToBit(NewEnd); } unsigned Code = (unsigned)Vals[0]; -- 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 --- lib/Bitcode/Reader/BitstreamReader.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'lib/Bitcode/Reader/BitstreamReader.cpp') diff --git a/lib/Bitcode/Reader/BitstreamReader.cpp b/lib/Bitcode/Reader/BitstreamReader.cpp index 92133bb969..7984512b4b 100644 --- a/lib/Bitcode/Reader/BitstreamReader.cpp +++ b/lib/Bitcode/Reader/BitstreamReader.cpp @@ -255,18 +255,17 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID, break; } - // Otherwise, read the number of bytes. If we can return a reference to - // the data, do so to avoid copying it. + // Otherwise, inform the streamer that we need these bytes in memory. + const char *Ptr = (const char*) + BitStream->getBitcodeBytes().getPointer(CurBitPos/8, NumElts); + + // If we can return a reference to the data, do so to avoid copying it. if (Blob) { - *Blob = - StringRef((const char*)BitStream->getBitcodeBytes().getPointer( - CurBitPos/8, NumElts), - NumElts); + *Blob = StringRef(Ptr, NumElts); } else { - // FIXME: This is a brutally inefficient way to do this. Why isn't this - // just using getPointer? + // Otherwise, unpack into Vals with zero extension. for (; NumElts; --NumElts) - Vals.push_back(Read(8)); + Vals.push_back((unsigned char)*Ptr++); } // Skip over tail padding. JumpToBit(NewEnd); -- cgit v1.2.3-18-g5258 From acb6194f93440425776cdd730a2726fd95499505 Mon Sep 17 00:00:00 2001 From: Joe Abbey Date: Wed, 6 Feb 2013 22:14:06 +0000 Subject: Code Custodian (trivial whitespace cleanup) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174550 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Bitcode/Reader/BitstreamReader.cpp | 77 +++++++++++++++++----------------- 1 file changed, 38 insertions(+), 39 deletions(-) (limited to 'lib/Bitcode/Reader/BitstreamReader.cpp') diff --git a/lib/Bitcode/Reader/BitstreamReader.cpp b/lib/Bitcode/Reader/BitstreamReader.cpp index 7984512b4b..85076f3502 100644 --- a/lib/Bitcode/Reader/BitstreamReader.cpp +++ b/lib/Bitcode/Reader/BitstreamReader.cpp @@ -17,19 +17,19 @@ using namespace llvm; void BitstreamCursor::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()); @@ -47,7 +47,7 @@ void BitstreamCursor::freeState() { 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) { @@ -65,7 +65,7 @@ bool BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) { // 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)) { @@ -75,17 +75,17 @@ bool BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) { CurAbbrevs.back()->addRef(); } } - + // Get the codesize of this block. CurCodeSize = ReadVBR(bitc::CodeLenWidth); SkipToFourByteBoundary(); unsigned NumWords = Read(bitc::BlockSizeWidth); if (NumWordsP) *NumWordsP = NumWords; - + // Validate that this block is sane. if (CurCodeSize == 0 || AtEndOfStream()) return true; - + return false; } @@ -99,7 +99,7 @@ void BitstreamCursor::readAbbreviatedLiteral(const BitCodeAbbrevOp &Op, void BitstreamCursor::readAbbreviatedField(const BitCodeAbbrevOp &Op, SmallVectorImpl &Vals) { assert(!Op.isLiteral() && "Use ReadAbbreviatedLiteral for literals!"); - + // Decode the value as we are commanded. switch (Op.getEncoding()) { case BitCodeAbbrevOp::Array: @@ -119,7 +119,7 @@ void BitstreamCursor::readAbbreviatedField(const BitCodeAbbrevOp &Op, void BitstreamCursor::skipAbbreviatedField(const BitCodeAbbrevOp &Op) { assert(!Op.isLiteral() && "Use ReadAbbreviatedLiteral for literals!"); - + // Decode the value as we are commanded. switch (Op.getEncoding()) { case BitCodeAbbrevOp::Array: @@ -152,47 +152,47 @@ void BitstreamCursor::skipRecord(unsigned AbbrevID) { } const BitCodeAbbrev *Abbv = getAbbrev(AbbrevID); - + for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) { const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); if (Op.isLiteral()) continue; - + if (Op.getEncoding() != BitCodeAbbrevOp::Array && Op.getEncoding() != BitCodeAbbrevOp::Blob) { skipAbbreviatedField(Op); continue; } - + 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) skipAbbreviatedField(EltEnc); continue; } - + assert(Op.getEncoding() == BitCodeAbbrevOp::Blob); // Blob case. Read the number of bytes as a vbr6. unsigned NumElts = ReadVBR(6); SkipToFourByteBoundary(); // 32-bit alignment - + // Figure out where the end of this blob will be including tail padding. size_t NewEnd = GetCurrentBitNo()+((NumElts+3)&~3)*8; - + // If this would read off the end of the bitcode file, just set the // record to empty and return. if (!canSkipToPos(NewEnd/8)) { NextChar = BitStream->getBitcodeBytes().getExtent(); break; } - + // Skip over the blob. JumpToBit(NewEnd); } @@ -208,45 +208,45 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID, 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); continue; } - + if (Op.getEncoding() != BitCodeAbbrevOp::Array && Op.getEncoding() != BitCodeAbbrevOp::Blob) { readAbbreviatedField(Op, Vals); continue; } - + 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); continue; } - + assert(Op.getEncoding() == BitCodeAbbrevOp::Blob); // Blob case. Read the number of bytes as a vbr6. unsigned NumElts = ReadVBR(6); SkipToFourByteBoundary(); // 32-bit alignment - + // Figure out where the end of this blob will be including tail padding. size_t CurBitPos = GetCurrentBitNo(); size_t NewEnd = CurBitPos+((NumElts+3)&~3)*8; - + // If this would read off the end of the bitcode file, just set the // record to empty and return. if (!canSkipToPos(NewEnd/8)) { @@ -254,11 +254,11 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID, NextChar = BitStream->getBitcodeBytes().getExtent(); break; } - + // Otherwise, inform the streamer that we need these bytes in memory. const char *Ptr = (const char*) BitStream->getBitcodeBytes().getPointer(CurBitPos/8, NumElts); - + // If we can return a reference to the data, do so to avoid copying it. if (Blob) { *Blob = StringRef(Ptr, NumElts); @@ -270,7 +270,7 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID, // Skip over tail padding. JumpToBit(NewEnd); } - + unsigned Code = (unsigned)Vals[0]; Vals.erase(Vals.begin()); return Code; @@ -286,7 +286,7 @@ void BitstreamCursor::ReadAbbrevRecord() { Abbv->Add(BitCodeAbbrevOp(ReadVBR64(8))); continue; } - + BitCodeAbbrevOp::Encoding E = (BitCodeAbbrevOp::Encoding)Read(3); if (BitCodeAbbrevOp::hasEncodingData(E)) Abbv->Add(BitCodeAbbrevOp(E, ReadVBR64(5))); @@ -300,16 +300,16 @@ bool BitstreamCursor::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) { BitstreamEntry Entry = advanceSkippingSubblocks(AF_DontAutoprocessAbbrevs); - + switch (Entry.Kind) { case llvm::BitstreamEntry::SubBlock: // Handled for us already. case llvm::BitstreamEntry::Error: @@ -325,7 +325,7 @@ bool BitstreamCursor::ReadBlockInfoBlock() { if (Entry.ID == bitc::DEFINE_ABBREV) { if (!CurBlockInfo) return true; ReadAbbrevRecord(); - + // ReadAbbrevRecord installs the abbrev in CurAbbrevs. Move it to the // appropriate BlockInfo. BitCodeAbbrev *Abbv = CurAbbrevs.back(); @@ -333,7 +333,7 @@ bool BitstreamCursor::ReadBlockInfoBlock() { CurBlockInfo->Abbrevs.push_back(Abbv); continue; } - + // Read a record. Record.clear(); switch (readRecord(Entry.ID, Record)) { @@ -365,4 +365,3 @@ bool BitstreamCursor::ReadBlockInfoBlock() { } } - -- 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 --- lib/Bitcode/Reader/BitstreamReader.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'lib/Bitcode/Reader/BitstreamReader.cpp') diff --git a/lib/Bitcode/Reader/BitstreamReader.cpp b/lib/Bitcode/Reader/BitstreamReader.cpp index 85076f3502..b1335029a7 100644 --- a/lib/Bitcode/Reader/BitstreamReader.cpp +++ b/lib/Bitcode/Reader/BitstreamReader.cpp @@ -288,9 +288,20 @@ void BitstreamCursor::ReadAbbrevRecord() { } BitCodeAbbrevOp::Encoding E = (BitCodeAbbrevOp::Encoding)Read(3); - if (BitCodeAbbrevOp::hasEncodingData(E)) - Abbv->Add(BitCodeAbbrevOp(E, ReadVBR64(5))); - else + if (BitCodeAbbrevOp::hasEncodingData(E)) { + unsigned Data = ReadVBR64(5); + + // As a special case, handle fixed(0) (i.e., a fixed field with zero bits) + // and vbr(0) as a literal zero. This is decoded the same way, and avoids + // a slow path in Read() to have to handle reading zero bits. + if ((E == BitCodeAbbrevOp::Fixed || E == BitCodeAbbrevOp::VBR) && + Data == 0) { + Abbv->Add(BitCodeAbbrevOp(0)); + continue; + } + + Abbv->Add(BitCodeAbbrevOp(E, Data)); + } else Abbv->Add(BitCodeAbbrevOp(E)); } CurAbbrevs.push_back(Abbv); -- cgit v1.2.3-18-g5258 From c61e83e6de778e5bd937e401564fe6bd0836b727 Mon Sep 17 00:00:00 2001 From: Jakub Staszak Date: Tue, 19 Feb 2013 09:48:30 +0000 Subject: Simplify code. No functionality change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@175501 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Bitcode/Reader/BitstreamReader.cpp | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'lib/Bitcode/Reader/BitstreamReader.cpp') diff --git a/lib/Bitcode/Reader/BitstreamReader.cpp b/lib/Bitcode/Reader/BitstreamReader.cpp index b1335029a7..942346b44e 100644 --- a/lib/Bitcode/Reader/BitstreamReader.cpp +++ b/lib/Bitcode/Reader/BitstreamReader.cpp @@ -26,34 +26,28 @@ void BitstreamCursor::operator=(const BitstreamCursor &RHS) { // Copy abbreviations, and bump ref counts. CurAbbrevs = RHS.CurAbbrevs; - for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); - i != e; ++i) + for (size_t i = 0, e = 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) { + for (size_t S = 0, e = BlockScope.size(); S != e; ++S) { std::vector &Abbrevs = BlockScope[S].PrevAbbrevs; - for (unsigned i = 0, e = static_cast(Abbrevs.size()); - i != e; ++i) + for (size_t i = 0, e = Abbrevs.size(); i != e; ++i) Abbrevs[i]->addRef(); } } void BitstreamCursor::freeState() { // Free all the Abbrevs. - for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); - i != e; ++i) + for (size_t i = 0, e = 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) { + for (size_t S = 0, e = BlockScope.size(); S != e; ++S) { std::vector &Abbrevs = BlockScope[S].PrevAbbrevs; - for (unsigned i = 0, e = static_cast(Abbrevs.size()); - i != e; ++i) + for (size_t i = 0, e = Abbrevs.size(); i != e; ++i) Abbrevs[i]->dropRef(); } BlockScope.clear(); @@ -69,8 +63,7 @@ bool BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) { // 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) { + for (size_t i = 0, e = Info->Abbrevs.size(); i != e; ++i) { CurAbbrevs.push_back(Info->Abbrevs[i]); CurAbbrevs.back()->addRef(); } -- cgit v1.2.3-18-g5258