//===- BitstreamReader.cpp - BitstreamReader implementation ---------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/Bitstream/BitstreamReader.h" #include "llvm/ADT/StringRef.h" #include #include #include using namespace llvm; //===----------------------------------------------------------------------===// // BitstreamCursor implementation //===----------------------------------------------------------------------===// // static Error error(const char *Message) { return createStringError(std::errc::illegal_byte_sequence, Message); } /// Having read the ENTER_SUBBLOCK abbrevid, enter the block. Error 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 (BlockInfo) { if (const BitstreamBlockInfo::BlockInfo *Info = BlockInfo->getBlockInfo(BlockID)) { llvm::append_range(CurAbbrevs, Info->Abbrevs); } } // Get the codesize of this block. Expected MaybeVBR = ReadVBR(bitc::CodeLenWidth); if (!MaybeVBR) return MaybeVBR.takeError(); CurCodeSize = MaybeVBR.get(); if (CurCodeSize > MaxChunkSize) return llvm::createStringError( std::errc::illegal_byte_sequence, "can't read more than %zu at a time, trying to read %u", +MaxChunkSize, CurCodeSize); SkipToFourByteBoundary(); Expected MaybeNum = Read(bitc::BlockSizeWidth); if (!MaybeNum) return MaybeNum.takeError(); word_t NumWords = MaybeNum.get(); if (NumWordsP) *NumWordsP = NumWords; if (CurCodeSize == 0) return llvm::createStringError( std::errc::illegal_byte_sequence, "can't enter sub-block: current code size is 0"); if (AtEndOfStream()) return llvm::createStringError( std::errc::illegal_byte_sequence, "can't enter sub block: already at end of stream"); return Error::success(); } static Expected readAbbreviatedField(BitstreamCursor &Cursor, const BitCodeAbbrevOp &Op) { assert(!Op.isLiteral() && "Not to be used with literals!"); // Decode the value as we are commanded. switch (Op.getEncoding()) { case BitCodeAbbrevOp::Array: case BitCodeAbbrevOp::Blob: llvm_unreachable("Should not reach here"); case BitCodeAbbrevOp::Fixed: assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); return Cursor.Read((unsigned)Op.getEncodingData()); case BitCodeAbbrevOp::VBR: assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); return Cursor.ReadVBR64((unsigned)Op.getEncodingData()); case BitCodeAbbrevOp::Char6: if (Expected Res = Cursor.Read(6)) return BitCodeAbbrevOp::DecodeChar6(Res.get()); else return Res.takeError(); } llvm_unreachable("invalid abbreviation encoding"); } /// skipRecord - Read the current record and discard it. 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(); return Code; } Expected MaybeAbbv = getAbbrev(AbbrevID); if (!MaybeAbbv) return MaybeAbbv.takeError(); const BitCodeAbbrev *Abbv = MaybeAbbv.get(); const BitCodeAbbrevOp &CodeOp = Abbv->getOperandInfo(0); unsigned Code; if (CodeOp.isLiteral()) Code = CodeOp.getLiteralValue(); else { if (CodeOp.getEncoding() == BitCodeAbbrevOp::Array || CodeOp.getEncoding() == BitCodeAbbrevOp::Blob) 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(); } for (unsigned i = 1, 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) { if (Expected MaybeField = readAbbreviatedField(*this, Op)) continue; else return MaybeField.takeError(); } 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(); // Get the element encoding. assert(i+2 == e && "array op not second to last?"); const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i); // Read all the elements. // Decode the value as we are commanded. switch (EltEnc.getEncoding()) { default: 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 Err; break; case BitCodeAbbrevOp::VBR: assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize); for (; NumElts; --NumElts) if (Expected Res = ReadVBR64((unsigned)EltEnc.getEncodingData())) ; // Skip! else return Res.takeError(); break; case BitCodeAbbrevOp::Char6: if (Error Err = JumpToBit(GetCurrentBitNo() + NumElts * 6)) return Err; break; } continue; } 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(); SkipToFourByteBoundary(); // 32-bit alignment // Figure out where the end of this blob will be including tail padding. const size_t NewEnd = GetCurrentBitNo() + alignTo(NumElts, 4) * 8; // If this would read off the end of the bitcode file, just set the // record to empty and return. if (!canSkipToPos(NewEnd/8)) { skipToEnd(); break; } // Skip over the blob. if (Error Err = JumpToBit(NewEnd)) return Err; } return Code; } Expected BitstreamCursor::readRecord(unsigned AbbrevID, 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(); 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(); return Code; } Expected MaybeAbbv = getAbbrev(AbbrevID); if (!MaybeAbbv) return MaybeAbbv.takeError(); const BitCodeAbbrev *Abbv = MaybeAbbv.get(); // Read the record code first. assert(Abbv->getNumOperandInfos() != 0 && "no record code in abbreviation?"); const BitCodeAbbrevOp &CodeOp = Abbv->getOperandInfo(0); unsigned Code; if (CodeOp.isLiteral()) Code = CodeOp.getLiteralValue(); else { 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(); } for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) { const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); if (Op.isLiteral()) { Vals.push_back(Op.getLiteralValue()); continue; } if (Op.getEncoding() != BitCodeAbbrevOp::Array && Op.getEncoding() != BitCodeAbbrevOp::Blob) { if (Expected MaybeVal = readAbbreviatedField(*this, Op)) Vals.push_back(MaybeVal.get()); else return MaybeVal.takeError(); 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(); if (!isSizePlausible(NumElts)) return error("Size is not plausible"); Vals.reserve(Vals.size() + NumElts); // Get the element encoding. if (i + 2 != e) return error("Array op not second to last"); const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i); if (!EltEnc.isEncoding()) return error( "Array element type has to be an encoding of a type"); // Read all the elements. switch (EltEnc.getEncoding()) { 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(); break; case BitCodeAbbrevOp::VBR: for (; NumElts; --NumElts) if (Expected MaybeVal = ReadVBR64((unsigned)EltEnc.getEncodingData())) Vals.push_back(MaybeVal.get()); else return MaybeVal.takeError(); break; case BitCodeAbbrevOp::Char6: for (; NumElts; --NumElts) if (Expected MaybeVal = Read(6)) Vals.push_back(BitCodeAbbrevOp::DecodeChar6(MaybeVal.get())); else return MaybeVal.takeError(); } 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(); SkipToFourByteBoundary(); // 32-bit alignment // Figure out where the end of this blob will be including tail padding. size_t CurBitPos = GetCurrentBitNo(); const size_t NewEnd = CurBitPos + alignTo(NumElts, 4) * 8; // Make sure the bitstream is large enough to contain the blob. if (!canSkipToPos(NewEnd/8)) return error("Blob ends too soon"); // 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 Err; const char *Ptr = (const char *)getPointerToBit(CurBitPos, NumElts); // If we can return a reference to the data, do so to avoid copying it. if (Blob) { *Blob = StringRef(Ptr, NumElts); } else { // Otherwise, unpack into Vals with zero extension. auto *UPtr = reinterpret_cast(Ptr); Vals.append(UPtr, UPtr + NumElts); } } 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(); if (IsLiteral) { Expected MaybeOp = ReadVBR64(8); if (!MaybeOp) return MaybeOp.takeError(); Abbv->Add(BitCodeAbbrevOp(MaybeOp.get())); continue; } Expected MaybeEncoding = Read(3); if (!MaybeEncoding) return MaybeEncoding.takeError(); if (!BitCodeAbbrevOp::isValidEncoding(MaybeEncoding.get())) return error("Invalid encoding"); BitCodeAbbrevOp::Encoding E = (BitCodeAbbrevOp::Encoding)MaybeEncoding.get(); if (BitCodeAbbrevOp::hasEncodingData(E)) { Expected MaybeData = ReadVBR64(5); if (!MaybeData) return MaybeData.takeError(); uint64_t Data = MaybeData.get(); // 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; } if ((E == BitCodeAbbrevOp::Fixed || E == BitCodeAbbrevOp::VBR) && Data > MaxChunkSize) return error("Fixed or VBR abbrev record with size > MaxChunkData"); Abbv->Add(BitCodeAbbrevOp(E, Data)); } else Abbv->Add(BitCodeAbbrevOp(E)); } if (Abbv->getNumOperandInfos() == 0) return error("Abbrev record with no operands"); CurAbbrevs.push_back(std::move(Abbv)); return Error::success(); } Expected> BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) { if (llvm::Error Err = EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return Err; BitstreamBlockInfo NewBlockInfo; SmallVector Record; BitstreamBlockInfo::BlockInfo *CurBlockInfo = nullptr; // Read all the records for this module. while (true) { Expected MaybeEntry = advanceSkippingSubblocks(AF_DontAutoprocessAbbrevs); if (!MaybeEntry) return MaybeEntry.takeError(); BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case llvm::BitstreamEntry::SubBlock: // Handled for us already. case llvm::BitstreamEntry::Error: return std::nullopt; case llvm::BitstreamEntry::EndBlock: return std::move(NewBlockInfo); case llvm::BitstreamEntry::Record: // The interesting case. break; } // Read abbrev records, associate them with CurBID. if (Entry.ID == bitc::DEFINE_ABBREV) { if (!CurBlockInfo) return std::nullopt; if (Error Err = ReadAbbrevRecord()) return Err; // ReadAbbrevRecord installs the abbrev in CurAbbrevs. Move it to the // appropriate BlockInfo. CurBlockInfo->Abbrevs.push_back(std::move(CurAbbrevs.back())); CurAbbrevs.pop_back(); continue; } // Read a record. Record.clear(); Expected MaybeBlockInfo = readRecord(Entry.ID, Record); if (!MaybeBlockInfo) return MaybeBlockInfo.takeError(); switch (MaybeBlockInfo.get()) { default: break; // Default behavior, ignore unknown content. case bitc::BLOCKINFO_CODE_SETBID: if (Record.size() < 1) return std::nullopt; CurBlockInfo = &NewBlockInfo.getOrCreateBlockInfo((unsigned)Record[0]); break; case bitc::BLOCKINFO_CODE_BLOCKNAME: { if (!CurBlockInfo) return std::nullopt; if (!ReadBlockInfoNames) break; // Ignore name. CurBlockInfo->Name = std::string(Record.begin(), Record.end()); break; } case bitc::BLOCKINFO_CODE_SETRECORDNAME: { if (!CurBlockInfo) return std::nullopt; if (!ReadBlockInfoNames) break; // Ignore name. CurBlockInfo->RecordNames.emplace_back( (unsigned)Record[0], std::string(Record.begin() + 1, Record.end())); break; } } } }