diff --git a/llvm/include/llvm/Bitstream/BitCodes.h b/llvm/include/llvm/Bitstream/BitCodes.h --- a/llvm/include/llvm/Bitstream/BitCodes.h +++ b/llvm/include/llvm/Bitstream/BitCodes.h @@ -95,6 +95,9 @@ [V]; } + static char DecodeChar6Tolerant(unsigned V) { + return DecodeChar6(V & ~unsigned(63)); + } }; /// BitCodeAbbrev - This class represents an abbreviation record. An diff --git a/llvm/include/llvm/Bitstream/BitstreamReader.h b/llvm/include/llvm/Bitstream/BitstreamReader.h --- a/llvm/include/llvm/Bitstream/BitstreamReader.h +++ b/llvm/include/llvm/Bitstream/BitstreamReader.h @@ -73,6 +73,30 @@ } }; +class BitstreamError : public ErrorInfo { +public: + enum ErrKind : unsigned { + UnexpectedEofBits, + UnexpectedEofBytes, + SkipBlockAtEof, + BadSkip, + UnterminatedVBR, + BadAbbrev, + }; + static char ID; + + BitstreamError() = default; + BitstreamError(ErrKind Kind, uint64_t Arg1 = 0, uint64_t Arg2 = 0) + : Kind(Kind){}; + + void log(raw_ostream &OS) const override; + std::error_code convertToErrorCode() const override; + +private: + ErrKind Kind; + size_t Arg1, Arg2; +}; + /// This represents a position within a bitstream. There may be multiple /// independent cursors reading within one bitstream, each maintaining their /// own local state. @@ -95,6 +119,15 @@ /// [0...bits_of(size_t)-1] inclusive. unsigned BitsInCurWord = 0; +protected: + llvm::Optional Err; + llvm::Error err() { + assert(Err); + auto E = make_error(*Err); + Err.reset(); + return E; + } + public: SimpleBitstreamCursor() = default; explicit SimpleBitstreamCursor(ArrayRef BitcodeBytes) @@ -125,6 +158,12 @@ /// Reset the stream to the specified bit number. Error JumpToBit(uint64_t BitNo) { + JumpToBitE(BitNo); + if (Err) + return err(); + return Error::success(); + } + void JumpToBitE(uint64_t BitNo) { size_t ByteNo = size_t(BitNo/8) & ~(sizeof(word_t)-1); unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); assert(canSkipToPos(ByteNo) && "Invalid location"); @@ -134,14 +173,8 @@ BitsInCurWord = 0; // Skip over any bits that are already consumed. - if (WordBitNo) { - if (Expected Res = Read(WordBitNo)) - return Error::success(); - else - return Res.takeError(); - } - - return Error::success(); + if (WordBitNo) + ReadE(WordBitNo); } /// Get a pointer into the bitstream at the specified byte offset. @@ -157,11 +190,12 @@ return getPointerToByte(BitNo / 8, NumBytes); } - Error fillCurWord() { - if (NextChar >= BitcodeBytes.size()) - return createStringError(std::errc::io_error, - "Unexpected end of file reading %u of %u bytes", - NextChar, BitcodeBytes.size()); + void fillCurWordE() { + if (NextChar >= BitcodeBytes.size()) { + Err.emplace(BitstreamError::UnexpectedEofBytes, NextChar, + BitcodeBytes.size()); + return; + } // Read the next word from the stream. const uint8_t *NextCharPtr = BitcodeBytes.data() + NextChar; @@ -180,10 +214,15 @@ } NextChar += BytesRead; BitsInCurWord = BytesRead * 8; - return Error::success(); } Expected Read(unsigned NumBits) { + auto Ret = ReadE(NumBits); + if (Err) + return err(); + return Ret; + } + word_t ReadE(unsigned NumBits) { static const unsigned BitsInWord = sizeof(word_t) * 8; assert(NumBits && NumBits <= BitsInWord && @@ -205,14 +244,10 @@ word_t R = BitsInCurWord ? CurWord : 0; unsigned BitsLeft = NumBits - BitsInCurWord; - if (Error fillResult = fillCurWord()) - return std::move(fillResult); - - // If we run out of data, abort. - if (BitsLeft > BitsInCurWord) - return createStringError(std::errc::io_error, - "Unexpected end of file reading %u of %u bits", - BitsInCurWord, BitsLeft); + fillCurWordE(); + if (!Err && BitsLeft > BitsInCurWord) + Err.emplace(BitstreamError::UnexpectedEofBits, BitsInCurWord, BitsLeft); + // Don't bother branching for errors, just return garbage with Err set. word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft)); @@ -227,10 +262,14 @@ } Expected ReadVBR(const unsigned NumBits) { - Expected MaybeRead = Read(NumBits); - if (!MaybeRead) - return MaybeRead; - uint32_t Piece = MaybeRead.get(); + auto Ret = ReadVBRE(NumBits); + if (Err) + return err(); + return Ret; + } + uint32_t ReadVBRE(const unsigned NumBits) { + uint32_t Piece = ReadE(NumBits); + // Error checked in loop below. assert(NumBits <= 32 && NumBits >= 1 && "Invalid NumBits value"); const uint32_t MaskBitOrder = (NumBits - 1); @@ -241,7 +280,7 @@ uint32_t Result = 0; unsigned NextBit = 0; - while (true) { + while (!Err) { Result |= (Piece & (Mask - 1)) << NextBit; if ((Piece & Mask) == 0) @@ -249,23 +288,23 @@ NextBit += NumBits-1; if (NextBit >= 32) - return createStringError(std::errc::illegal_byte_sequence, - "Unterminated VBR"); - - MaybeRead = Read(NumBits); - if (!MaybeRead) - return MaybeRead; - Piece = MaybeRead.get(); + Err.emplace(BitstreamError::UnterminatedVBR); + else + Piece = ReadE(NumBits); } + return 0; // error } // Read a VBR that may have a value up to 64-bits in size. The chunk size of // the VBR must still be <= 32 bits though. Expected ReadVBR64(const unsigned NumBits) { - Expected MaybeRead = Read(NumBits); - if (!MaybeRead) - return MaybeRead; - uint32_t Piece = MaybeRead.get(); + auto Ret = ReadVBR64E(NumBits); + if (Err) + return err(); + return Ret; + } + uint64_t ReadVBR64E(const unsigned NumBits) { + uint64_t Piece = ReadE(NumBits); assert(NumBits <= 32 && NumBits >= 1 && "Invalid NumBits value"); const uint32_t MaskBitOrder = (NumBits - 1); const uint32_t Mask = 1UL << MaskBitOrder; @@ -275,7 +314,7 @@ uint64_t Result = 0; unsigned NextBit = 0; - while (true) { + while (!Err) { Result |= uint64_t(Piece & (Mask - 1)) << NextBit; if ((Piece & Mask) == 0) @@ -283,14 +322,11 @@ NextBit += NumBits-1; if (NextBit >= 64) - return createStringError(std::errc::illegal_byte_sequence, - "Unterminated VBR"); - - MaybeRead = Read(NumBits); - if (!MaybeRead) - return MaybeRead; - Piece = MaybeRead.get(); + Err.emplace(BitstreamError::UnterminatedVBR); + else + Piece = ReadE(NumBits); } + return 0; // error } void SkipToFourByteBoundary() { @@ -388,7 +424,6 @@ using SimpleBitstreamCursor::AtEndOfStream; using SimpleBitstreamCursor::canSkipToPos; - using SimpleBitstreamCursor::fillCurWord; using SimpleBitstreamCursor::getBitcodeBytes; using SimpleBitstreamCursor::GetCurrentBitNo; using SimpleBitstreamCursor::getCurrentByteNo; @@ -483,31 +518,29 @@ /// of this block. Error SkipBlock() { // Read and ignore the codelen value. - if (Expected Res = ReadVBR(bitc::CodeLenWidth)) - ; // Since we are skipping this block, we don't care what code widths are - // used inside of it. - else - return Res.takeError(); + ReadVBRE(bitc::CodeLenWidth); + // Since we are skipping this block, we don't care what code widths are + // used inside of it. + if (Err) + return err(); SkipToFourByteBoundary(); - Expected MaybeNum = Read(bitc::BlockSizeWidth); - if (!MaybeNum) - return MaybeNum.takeError(); - size_t NumFourBytes = MaybeNum.get(); + size_t NumFourBytes = ReadE(bitc::BlockSizeWidth); + if (Err) + return err(); // Check that the block wasn't partially defined, and that the offset isn't // bogus. size_t SkipTo = GetCurrentBitNo() + NumFourBytes * 4 * 8; if (AtEndOfStream()) - return createStringError(std::errc::illegal_byte_sequence, - "can't skip block: already at end of stream"); + return make_error(BitstreamError::SkipBlockAtEof); if (!canSkipToPos(SkipTo / 8)) - return createStringError(std::errc::illegal_byte_sequence, - "can't skip to bit %zu from %" PRIu64, SkipTo, - GetCurrentBitNo()); + return make_error(BitstreamError::BadSkip, SkipTo, + GetCurrentBitNo()); - if (Error Res = JumpToBit(SkipTo)) - return Res; + JumpToBitE(SkipTo); + if (Err) + return err(); return Error::success(); } @@ -534,6 +567,7 @@ BlockScope.pop_back(); } + uint64_t readAbbreviatedFieldE(const BitCodeAbbrevOp &Op); //===--------------------------------------------------------------------===// // Record Processing //===--------------------------------------------------------------------===// @@ -543,8 +577,7 @@ Expected getAbbrev(unsigned AbbrevID) { unsigned AbbrevNo = AbbrevID - bitc::FIRST_APPLICATION_ABBREV; if (AbbrevNo >= CurAbbrevs.size()) - return createStringError( - std::errc::illegal_byte_sequence, "Invalid abbrev number"); + return make_error(BitstreamError::BadAbbrev); return CurAbbrevs[AbbrevNo].get(); } diff --git a/llvm/lib/Bitstream/Reader/BitstreamReader.cpp b/llvm/lib/Bitstream/Reader/BitstreamReader.cpp --- a/llvm/lib/Bitstream/Reader/BitstreamReader.cpp +++ b/llvm/lib/Bitstream/Reader/BitstreamReader.cpp @@ -36,11 +36,9 @@ } // Get the codesize of this block. - Expected MaybeVBR = ReadVBR(bitc::CodeLenWidth); - if (!MaybeVBR) - return MaybeVBR.takeError(); - CurCodeSize = MaybeVBR.get(); - + CurCodeSize = ReadVBRE(bitc::CodeLenWidth); + if (Err) + return err(); if (CurCodeSize > MaxChunkSize) return llvm::createStringError( std::errc::illegal_byte_sequence, @@ -48,13 +46,12 @@ CurCodeSize); SkipToFourByteBoundary(); - Expected MaybeNum = Read(bitc::BlockSizeWidth); - if (!MaybeNum) - return MaybeNum.takeError(); - word_t NumWords = MaybeNum.get(); + word_t NumWords = ReadE(bitc::BlockSizeWidth); if (NumWordsP) *NumWordsP = NumWords; + if (Err) + return err(); if (CurCodeSize == 0) return llvm::createStringError( std::errc::illegal_byte_sequence, @@ -67,8 +64,7 @@ return Error::success(); } -static Expected readAbbreviatedField(BitstreamCursor &Cursor, - const BitCodeAbbrevOp &Op) { +uint64_t BitstreamCursor::readAbbreviatedFieldE(const BitCodeAbbrevOp &Op) { assert(!Op.isLiteral() && "Not to be used with literals!"); // Decode the value as we are commanded. @@ -77,16 +73,13 @@ case BitCodeAbbrevOp::Blob: llvm_unreachable("Should not reach here"); case BitCodeAbbrevOp::Fixed: - assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); - return Cursor.Read((unsigned)Op.getEncodingData()); + assert((unsigned)Op.getEncodingData() <= MaxChunkSize); + return ReadE((unsigned)Op.getEncodingData()); case BitCodeAbbrevOp::VBR: - assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); - return Cursor.ReadVBR64((unsigned)Op.getEncodingData()); + assert((unsigned)Op.getEncodingData() <= MaxChunkSize); + return ReadVBR64E((unsigned)Op.getEncodingData()); case BitCodeAbbrevOp::Char6: - if (Expected Res = Cursor.Read(6)) - return BitCodeAbbrevOp::DecodeChar6(Res.get()); - else - return Res.takeError(); + return BitCodeAbbrevOp::DecodeChar6Tolerant(ReadE(6)); } llvm_unreachable("invalid abbreviation encoding"); } @@ -95,19 +88,12 @@ Expected BitstreamCursor::skipRecord(unsigned AbbrevID) { // Skip unabbreviated records by reading past their entries. if (AbbrevID == bitc::UNABBREV_RECORD) { - Expected MaybeCode = ReadVBR(6); - if (!MaybeCode) - return MaybeCode.takeError(); - unsigned Code = MaybeCode.get(); - Expected MaybeVBR = ReadVBR(6); - if (!MaybeVBR) - return MaybeVBR.takeError(); - unsigned NumElts = MaybeVBR.get(); - for (unsigned i = 0; i != NumElts; ++i) - if (Expected Res = ReadVBR64(6)) - ; // Skip! - else - return Res.takeError(); + unsigned Code = ReadVBRE(6); + unsigned NumElts = ReadVBRE(6); + for (unsigned i = 0; i != NumElts && !Err; ++i) + ReadVBR64E(6); + if (Err) + return err(); return Code; } @@ -126,31 +112,27 @@ return llvm::createStringError( std::errc::illegal_byte_sequence, "Abbreviation starts with an Array or a Blob"); - Expected MaybeCode = readAbbreviatedField(*this, CodeOp); - if (!MaybeCode) - return MaybeCode.takeError(); - Code = MaybeCode.get(); + Code = readAbbreviatedFieldE(CodeOp); + if (Err) + return err(); } - for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i < e; ++i) { + for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i < e && !Err; ++i) { const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); if (Op.isLiteral()) continue; if (Op.getEncoding() != BitCodeAbbrevOp::Array && Op.getEncoding() != BitCodeAbbrevOp::Blob) { - if (Expected MaybeField = readAbbreviatedField(*this, Op)) - continue; - else - return MaybeField.takeError(); + readAbbreviatedFieldE(Op); + continue; } if (Op.getEncoding() == BitCodeAbbrevOp::Array) { // Array case. Read the number of elements as a vbr6. - Expected MaybeNum = ReadVBR(6); - if (!MaybeNum) - return MaybeNum.takeError(); - unsigned NumElts = MaybeNum.get(); + unsigned NumElts = ReadVBRE(6); + if (Err) + return err(); // Get the element encoding. assert(i+2 == e && "array op not second to last?"); @@ -163,23 +145,16 @@ return error("Array element type can't be an Array or a Blob"); case BitCodeAbbrevOp::Fixed: assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize); - if (Error Err = - JumpToBit(GetCurrentBitNo() + static_cast(NumElts) * - EltEnc.getEncodingData())) - return std::move(Err); + JumpToBitE(GetCurrentBitNo() + + static_cast(NumElts) * EltEnc.getEncodingData()); break; case BitCodeAbbrevOp::VBR: assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize); - for (; NumElts; --NumElts) - if (Expected Res = - ReadVBR64((unsigned)EltEnc.getEncodingData())) - ; // Skip! - else - return Res.takeError(); + for (; NumElts && !Err; --NumElts) + ReadVBR64E((unsigned)EltEnc.getEncodingData()); // Skip! break; case BitCodeAbbrevOp::Char6: - if (Error Err = JumpToBit(GetCurrentBitNo() + NumElts * 6)) - return std::move(Err); + JumpToBitE(GetCurrentBitNo() + NumElts * 6); break; } continue; @@ -187,10 +162,9 @@ assert(Op.getEncoding() == BitCodeAbbrevOp::Blob); // Blob case. Read the number of bytes as a vbr6. - Expected MaybeNum = ReadVBR(6); - if (!MaybeNum) - return MaybeNum.takeError(); - unsigned NumElts = MaybeNum.get(); + unsigned NumElts = ReadVBRE(6); + if (Err) + return err(); SkipToFourByteBoundary(); // 32-bit alignment // Figure out where the end of this blob will be including tail padding. @@ -204,9 +178,10 @@ } // Skip over the blob. - if (Error Err = JumpToBit(NewEnd)) - return std::move(Err); + JumpToBitE(NewEnd); } + if (Err) + return err(); return Code; } @@ -214,25 +189,21 @@ SmallVectorImpl &Vals, StringRef *Blob) { if (AbbrevID == bitc::UNABBREV_RECORD) { - Expected MaybeCode = ReadVBR(6); - if (!MaybeCode) - return MaybeCode.takeError(); - uint32_t Code = MaybeCode.get(); - Expected MaybeNumElts = ReadVBR(6); - if (!MaybeNumElts) - return error( - ("Failed to read size: " + toString(MaybeNumElts.takeError())) - .c_str()); - uint32_t NumElts = MaybeNumElts.get(); + uint32_t Code = ReadVBRE(6); + if (Err) + return err(); + uint32_t NumElts = ReadVBRE(6); + if (Err) + return error(("Failed to read size: " + toString(err())).c_str()); if (!isSizePlausible(NumElts)) return error("Size is not plausible"); Vals.reserve(Vals.size() + NumElts); - for (unsigned i = 0; i != NumElts; ++i) - if (Expected MaybeVal = ReadVBR64(6)) - Vals.push_back(MaybeVal.get()); - else - return MaybeVal.takeError(); + for (unsigned i = 0; i != NumElts; ++i) { + Vals.push_back(ReadVBR64E(6)); + if (Err) + return err(); + } return Code; } @@ -251,10 +222,9 @@ if (CodeOp.getEncoding() == BitCodeAbbrevOp::Array || CodeOp.getEncoding() == BitCodeAbbrevOp::Blob) return error("Abbreviation starts with an Array or a Blob"); - if (Expected MaybeCode = readAbbreviatedField(*this, CodeOp)) - Code = MaybeCode.get(); - else - return MaybeCode.takeError(); + Code = readAbbreviatedFieldE(CodeOp); + if (Err) + return err(); } for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) { @@ -266,21 +236,15 @@ if (Op.getEncoding() != BitCodeAbbrevOp::Array && Op.getEncoding() != BitCodeAbbrevOp::Blob) { - if (Expected MaybeVal = readAbbreviatedField(*this, Op)) - Vals.push_back(MaybeVal.get()); - else - return MaybeVal.takeError(); + Vals.push_back(readAbbreviatedFieldE(Op)); continue; } if (Op.getEncoding() == BitCodeAbbrevOp::Array) { // Array case. Read the number of elements as a vbr6. - Expected MaybeNumElts = ReadVBR(6); - if (!MaybeNumElts) - return error( - ("Failed to read size: " + toString(MaybeNumElts.takeError())) - .c_str()); - uint32_t NumElts = MaybeNumElts.get(); + uint32_t NumElts = ReadVBRE(6); + if (Err) + return error(("Failed to read size: " + toString(err())).c_str()); if (!isSizePlausible(NumElts)) return error("Size is not plausible"); Vals.reserve(Vals.size() + NumElts); @@ -298,37 +262,25 @@ default: return error("Array element type can't be an Array or a Blob"); case BitCodeAbbrevOp::Fixed: - for (; NumElts; --NumElts) - if (Expected MaybeVal = - Read((unsigned)EltEnc.getEncodingData())) - Vals.push_back(MaybeVal.get()); - else - return MaybeVal.takeError(); + for (; NumElts && !Err; --NumElts) + Vals.push_back(ReadE((unsigned)EltEnc.getEncodingData())); break; case BitCodeAbbrevOp::VBR: - for (; NumElts; --NumElts) - if (Expected MaybeVal = - ReadVBR64((unsigned)EltEnc.getEncodingData())) - Vals.push_back(MaybeVal.get()); - else - return MaybeVal.takeError(); + for (; NumElts && !Err; --NumElts) + Vals.push_back(ReadVBR64E((unsigned)EltEnc.getEncodingData())); break; case BitCodeAbbrevOp::Char6: - for (; NumElts; --NumElts) - if (Expected MaybeVal = Read(6)) - Vals.push_back(BitCodeAbbrevOp::DecodeChar6(MaybeVal.get())); - else - return MaybeVal.takeError(); + for (; NumElts && !Err; --NumElts) + Vals.push_back(BitCodeAbbrevOp::DecodeChar6Tolerant(ReadE(6))); } continue; } assert(Op.getEncoding() == BitCodeAbbrevOp::Blob); // Blob case. Read the number of bytes as a vbr6. - Expected MaybeNumElts = ReadVBR(6); - if (!MaybeNumElts) - return MaybeNumElts.takeError(); - uint32_t NumElts = MaybeNumElts.get(); + uint32_t NumElts = ReadVBRE(6); + if (Err) + return err(); SkipToFourByteBoundary(); // 32-bit alignment // Figure out where the end of this blob will be including tail padding. @@ -342,8 +294,9 @@ // Otherwise, inform the streamer that we need these bytes in memory. Skip // over tail padding first, in case jumping to NewEnd invalidates the Blob // pointer. - if (Error Err = JumpToBit(NewEnd)) - return std::move(Err); + JumpToBitE(NewEnd); + if (Err) + return err(); const char *Ptr = (const char *)getPointerToBit(CurBitPos, NumElts); // If we can return a reference to the data, do so to avoid copying it. @@ -355,42 +308,34 @@ Vals.append(UPtr, UPtr + NumElts); } } + if (Err) + return err(); return Code; } Error BitstreamCursor::ReadAbbrevRecord() { auto Abbv = std::make_shared(); - Expected MaybeNumOpInfo = ReadVBR(5); - if (!MaybeNumOpInfo) - return MaybeNumOpInfo.takeError(); - unsigned NumOpInfo = MaybeNumOpInfo.get(); - for (unsigned i = 0; i != NumOpInfo; ++i) { - Expected MaybeIsLiteral = Read(1); - if (!MaybeIsLiteral) - return MaybeIsLiteral.takeError(); - bool IsLiteral = MaybeIsLiteral.get(); + uint32_t NumOpInfo = ReadVBRE(5); + for (unsigned i = 0; i != NumOpInfo && !Err; ++i) { + bool IsLiteral = ReadE(1); + if (Err) + break; if (IsLiteral) { - Expected MaybeOp = ReadVBR64(8); - if (!MaybeOp) - return MaybeOp.takeError(); - Abbv->Add(BitCodeAbbrevOp(MaybeOp.get())); + Abbv->Add(BitCodeAbbrevOp(ReadVBR64E(8))); continue; } - Expected MaybeEncoding = Read(3); - if (!MaybeEncoding) - return MaybeEncoding.takeError(); - if (!BitCodeAbbrevOp::isValidEncoding(MaybeEncoding.get())) + word_t MaybeEncoding = ReadE(3); + if (Err) + return err(); + if (!BitCodeAbbrevOp::isValidEncoding(MaybeEncoding)) return error("Invalid encoding"); BitCodeAbbrevOp::Encoding E = - (BitCodeAbbrevOp::Encoding)MaybeEncoding.get(); + (BitCodeAbbrevOp::Encoding)MaybeEncoding; if (BitCodeAbbrevOp::hasEncodingData(E)) { - Expected MaybeData = ReadVBR64(5); - if (!MaybeData) - return MaybeData.takeError(); - uint64_t Data = MaybeData.get(); + uint64_t Data = ReadVBR64E(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 @@ -402,13 +347,15 @@ } if ((E == BitCodeAbbrevOp::Fixed || E == BitCodeAbbrevOp::VBR) && - Data > MaxChunkSize) + Data > MaxChunkSize && !Err) return error("Fixed or VBR abbrev record with size > MaxChunkData"); Abbv->Add(BitCodeAbbrevOp(E, Data)); } else Abbv->Add(BitCodeAbbrevOp(E)); } + if (Err) + return err(); if (Abbv->getNumOperandInfos() == 0) return error("Abbrev record with no operands"); @@ -491,3 +438,40 @@ } } } + +void llvm::BitstreamError::log(raw_ostream &OS) const { + switch (Kind) { + case UnexpectedEofBits: + case UnexpectedEofBytes: + OS << "Unexpected end of file reading " << Arg1 << " of " << Arg2 + << (Kind == UnexpectedEofBits ? " bits" : " bytes"); + break; + case SkipBlockAtEof: + OS << "can't skip block: already at end of stream"; + break; + case BadSkip: + OS << "can't skip to bit " << Arg1 << " from " << Arg2; + break; + case UnterminatedVBR: + OS << "Unterminated VBR"; + break; + case BadAbbrev: + OS << "Invalid abbrev number"; + break; + } +} + +std::error_code llvm::BitstreamError::convertToErrorCode() const { + switch (Kind) { + case UnexpectedEofBits: + case UnexpectedEofBytes: + return std::make_error_code(std::errc::io_error); + case SkipBlockAtEof: + case BadAbbrev: + case BadSkip: + case UnterminatedVBR: + return std::make_error_code(std::errc::illegal_byte_sequence); + } +} + +char llvm::BitstreamError::ID;