Path: blob/main/contrib/llvm-project/llvm/lib/Bitstream/Reader/BitstreamReader.cpp
35266 views
//===- BitstreamReader.cpp - BitstreamReader implementation ---------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/Bitstream/BitstreamReader.h"9#include "llvm/ADT/StringRef.h"10#include <cassert>11#include <optional>12#include <string>1314using namespace llvm;1516//===----------------------------------------------------------------------===//17// BitstreamCursor implementation18//===----------------------------------------------------------------------===//19//20static Error error(const char *Message) {21return createStringError(std::errc::illegal_byte_sequence, Message);22}2324/// Having read the ENTER_SUBBLOCK abbrevid, enter the block.25Error BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) {26// Save the current block's state on BlockScope.27BlockScope.push_back(Block(CurCodeSize));28BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);2930// Add the abbrevs specific to this block to the CurAbbrevs list.31if (BlockInfo) {32if (const BitstreamBlockInfo::BlockInfo *Info =33BlockInfo->getBlockInfo(BlockID)) {34llvm::append_range(CurAbbrevs, Info->Abbrevs);35}36}3738// Get the codesize of this block.39Expected<uint32_t> MaybeVBR = ReadVBR(bitc::CodeLenWidth);40if (!MaybeVBR)41return MaybeVBR.takeError();42CurCodeSize = MaybeVBR.get();4344if (CurCodeSize > MaxChunkSize)45return llvm::createStringError(46std::errc::illegal_byte_sequence,47"can't read more than %zu at a time, trying to read %u", +MaxChunkSize,48CurCodeSize);4950SkipToFourByteBoundary();51Expected<word_t> MaybeNum = Read(bitc::BlockSizeWidth);52if (!MaybeNum)53return MaybeNum.takeError();54word_t NumWords = MaybeNum.get();55if (NumWordsP)56*NumWordsP = NumWords;5758if (CurCodeSize == 0)59return llvm::createStringError(60std::errc::illegal_byte_sequence,61"can't enter sub-block: current code size is 0");62if (AtEndOfStream())63return llvm::createStringError(64std::errc::illegal_byte_sequence,65"can't enter sub block: already at end of stream");6667return Error::success();68}6970static Expected<uint64_t> readAbbreviatedField(BitstreamCursor &Cursor,71const BitCodeAbbrevOp &Op) {72assert(!Op.isLiteral() && "Not to be used with literals!");7374// Decode the value as we are commanded.75switch (Op.getEncoding()) {76case BitCodeAbbrevOp::Array:77case BitCodeAbbrevOp::Blob:78llvm_unreachable("Should not reach here");79case BitCodeAbbrevOp::Fixed:80assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize);81return Cursor.Read((unsigned)Op.getEncodingData());82case BitCodeAbbrevOp::VBR:83assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize);84return Cursor.ReadVBR64((unsigned)Op.getEncodingData());85case BitCodeAbbrevOp::Char6:86if (Expected<unsigned> Res = Cursor.Read(6))87return BitCodeAbbrevOp::DecodeChar6(Res.get());88else89return Res.takeError();90}91llvm_unreachable("invalid abbreviation encoding");92}9394/// skipRecord - Read the current record and discard it.95Expected<unsigned> BitstreamCursor::skipRecord(unsigned AbbrevID) {96// Skip unabbreviated records by reading past their entries.97if (AbbrevID == bitc::UNABBREV_RECORD) {98Expected<uint32_t> MaybeCode = ReadVBR(6);99if (!MaybeCode)100return MaybeCode.takeError();101unsigned Code = MaybeCode.get();102Expected<uint32_t> MaybeVBR = ReadVBR(6);103if (!MaybeVBR)104return MaybeVBR.takeError();105unsigned NumElts = MaybeVBR.get();106for (unsigned i = 0; i != NumElts; ++i)107if (Expected<uint64_t> Res = ReadVBR64(6))108; // Skip!109else110return Res.takeError();111return Code;112}113114Expected<const BitCodeAbbrev *> MaybeAbbv = getAbbrev(AbbrevID);115if (!MaybeAbbv)116return MaybeAbbv.takeError();117118const BitCodeAbbrev *Abbv = MaybeAbbv.get();119const BitCodeAbbrevOp &CodeOp = Abbv->getOperandInfo(0);120unsigned Code;121if (CodeOp.isLiteral())122Code = CodeOp.getLiteralValue();123else {124if (CodeOp.getEncoding() == BitCodeAbbrevOp::Array ||125CodeOp.getEncoding() == BitCodeAbbrevOp::Blob)126return llvm::createStringError(127std::errc::illegal_byte_sequence,128"Abbreviation starts with an Array or a Blob");129Expected<uint64_t> MaybeCode = readAbbreviatedField(*this, CodeOp);130if (!MaybeCode)131return MaybeCode.takeError();132Code = MaybeCode.get();133}134135for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i < e; ++i) {136const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);137if (Op.isLiteral())138continue;139140if (Op.getEncoding() != BitCodeAbbrevOp::Array &&141Op.getEncoding() != BitCodeAbbrevOp::Blob) {142if (Expected<uint64_t> MaybeField = readAbbreviatedField(*this, Op))143continue;144else145return MaybeField.takeError();146}147148if (Op.getEncoding() == BitCodeAbbrevOp::Array) {149// Array case. Read the number of elements as a vbr6.150Expected<uint32_t> MaybeNum = ReadVBR(6);151if (!MaybeNum)152return MaybeNum.takeError();153unsigned NumElts = MaybeNum.get();154155// Get the element encoding.156assert(i+2 == e && "array op not second to last?");157const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i);158159// Read all the elements.160// Decode the value as we are commanded.161switch (EltEnc.getEncoding()) {162default:163return error("Array element type can't be an Array or a Blob");164case BitCodeAbbrevOp::Fixed:165assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize);166if (Error Err =167JumpToBit(GetCurrentBitNo() + static_cast<uint64_t>(NumElts) *168EltEnc.getEncodingData()))169return Err;170break;171case BitCodeAbbrevOp::VBR:172assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize);173for (; NumElts; --NumElts)174if (Expected<uint64_t> Res =175ReadVBR64((unsigned)EltEnc.getEncodingData()))176; // Skip!177else178return Res.takeError();179break;180case BitCodeAbbrevOp::Char6:181if (Error Err = JumpToBit(GetCurrentBitNo() + NumElts * 6))182return Err;183break;184}185continue;186}187188assert(Op.getEncoding() == BitCodeAbbrevOp::Blob);189// Blob case. Read the number of bytes as a vbr6.190Expected<uint32_t> MaybeNum = ReadVBR(6);191if (!MaybeNum)192return MaybeNum.takeError();193unsigned NumElts = MaybeNum.get();194SkipToFourByteBoundary(); // 32-bit alignment195196// Figure out where the end of this blob will be including tail padding.197const size_t NewEnd = GetCurrentBitNo() + alignTo(NumElts, 4) * 8;198199// If this would read off the end of the bitcode file, just set the200// record to empty and return.201if (!canSkipToPos(NewEnd/8)) {202skipToEnd();203break;204}205206// Skip over the blob.207if (Error Err = JumpToBit(NewEnd))208return Err;209}210return Code;211}212213Expected<unsigned> BitstreamCursor::readRecord(unsigned AbbrevID,214SmallVectorImpl<uint64_t> &Vals,215StringRef *Blob) {216if (AbbrevID == bitc::UNABBREV_RECORD) {217Expected<uint32_t> MaybeCode = ReadVBR(6);218if (!MaybeCode)219return MaybeCode.takeError();220uint32_t Code = MaybeCode.get();221Expected<uint32_t> MaybeNumElts = ReadVBR(6);222if (!MaybeNumElts)223return error(224("Failed to read size: " + toString(MaybeNumElts.takeError()))225.c_str());226uint32_t NumElts = MaybeNumElts.get();227if (!isSizePlausible(NumElts))228return error("Size is not plausible");229Vals.reserve(Vals.size() + NumElts);230231for (unsigned i = 0; i != NumElts; ++i)232if (Expected<uint64_t> MaybeVal = ReadVBR64(6))233Vals.push_back(MaybeVal.get());234else235return MaybeVal.takeError();236return Code;237}238239Expected<const BitCodeAbbrev *> MaybeAbbv = getAbbrev(AbbrevID);240if (!MaybeAbbv)241return MaybeAbbv.takeError();242const BitCodeAbbrev *Abbv = MaybeAbbv.get();243244// Read the record code first.245assert(Abbv->getNumOperandInfos() != 0 && "no record code in abbreviation?");246const BitCodeAbbrevOp &CodeOp = Abbv->getOperandInfo(0);247unsigned Code;248if (CodeOp.isLiteral())249Code = CodeOp.getLiteralValue();250else {251if (CodeOp.getEncoding() == BitCodeAbbrevOp::Array ||252CodeOp.getEncoding() == BitCodeAbbrevOp::Blob)253return error("Abbreviation starts with an Array or a Blob");254if (Expected<uint64_t> MaybeCode = readAbbreviatedField(*this, CodeOp))255Code = MaybeCode.get();256else257return MaybeCode.takeError();258}259260for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) {261const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);262if (Op.isLiteral()) {263Vals.push_back(Op.getLiteralValue());264continue;265}266267if (Op.getEncoding() != BitCodeAbbrevOp::Array &&268Op.getEncoding() != BitCodeAbbrevOp::Blob) {269if (Expected<uint64_t> MaybeVal = readAbbreviatedField(*this, Op))270Vals.push_back(MaybeVal.get());271else272return MaybeVal.takeError();273continue;274}275276if (Op.getEncoding() == BitCodeAbbrevOp::Array) {277// Array case. Read the number of elements as a vbr6.278Expected<uint32_t> MaybeNumElts = ReadVBR(6);279if (!MaybeNumElts)280return error(281("Failed to read size: " + toString(MaybeNumElts.takeError()))282.c_str());283uint32_t NumElts = MaybeNumElts.get();284if (!isSizePlausible(NumElts))285return error("Size is not plausible");286Vals.reserve(Vals.size() + NumElts);287288// Get the element encoding.289if (i + 2 != e)290return error("Array op not second to last");291const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i);292if (!EltEnc.isEncoding())293return error(294"Array element type has to be an encoding of a type");295296// Read all the elements.297switch (EltEnc.getEncoding()) {298default:299return error("Array element type can't be an Array or a Blob");300case BitCodeAbbrevOp::Fixed:301for (; NumElts; --NumElts)302if (Expected<SimpleBitstreamCursor::word_t> MaybeVal =303Read((unsigned)EltEnc.getEncodingData()))304Vals.push_back(MaybeVal.get());305else306return MaybeVal.takeError();307break;308case BitCodeAbbrevOp::VBR:309for (; NumElts; --NumElts)310if (Expected<uint64_t> MaybeVal =311ReadVBR64((unsigned)EltEnc.getEncodingData()))312Vals.push_back(MaybeVal.get());313else314return MaybeVal.takeError();315break;316case BitCodeAbbrevOp::Char6:317for (; NumElts; --NumElts)318if (Expected<SimpleBitstreamCursor::word_t> MaybeVal = Read(6))319Vals.push_back(BitCodeAbbrevOp::DecodeChar6(MaybeVal.get()));320else321return MaybeVal.takeError();322}323continue;324}325326assert(Op.getEncoding() == BitCodeAbbrevOp::Blob);327// Blob case. Read the number of bytes as a vbr6.328Expected<uint32_t> MaybeNumElts = ReadVBR(6);329if (!MaybeNumElts)330return MaybeNumElts.takeError();331uint32_t NumElts = MaybeNumElts.get();332SkipToFourByteBoundary(); // 32-bit alignment333334// Figure out where the end of this blob will be including tail padding.335size_t CurBitPos = GetCurrentBitNo();336const size_t NewEnd = CurBitPos + alignTo(NumElts, 4) * 8;337338// Make sure the bitstream is large enough to contain the blob.339if (!canSkipToPos(NewEnd/8))340return error("Blob ends too soon");341342// Otherwise, inform the streamer that we need these bytes in memory. Skip343// over tail padding first, in case jumping to NewEnd invalidates the Blob344// pointer.345if (Error Err = JumpToBit(NewEnd))346return Err;347const char *Ptr = (const char *)getPointerToBit(CurBitPos, NumElts);348349// If we can return a reference to the data, do so to avoid copying it.350if (Blob) {351*Blob = StringRef(Ptr, NumElts);352} else {353// Otherwise, unpack into Vals with zero extension.354auto *UPtr = reinterpret_cast<const unsigned char *>(Ptr);355Vals.append(UPtr, UPtr + NumElts);356}357}358359return Code;360}361362Error BitstreamCursor::ReadAbbrevRecord() {363auto Abbv = std::make_shared<BitCodeAbbrev>();364Expected<uint32_t> MaybeNumOpInfo = ReadVBR(5);365if (!MaybeNumOpInfo)366return MaybeNumOpInfo.takeError();367unsigned NumOpInfo = MaybeNumOpInfo.get();368for (unsigned i = 0; i != NumOpInfo; ++i) {369Expected<word_t> MaybeIsLiteral = Read(1);370if (!MaybeIsLiteral)371return MaybeIsLiteral.takeError();372bool IsLiteral = MaybeIsLiteral.get();373if (IsLiteral) {374Expected<uint64_t> MaybeOp = ReadVBR64(8);375if (!MaybeOp)376return MaybeOp.takeError();377Abbv->Add(BitCodeAbbrevOp(MaybeOp.get()));378continue;379}380381Expected<word_t> MaybeEncoding = Read(3);382if (!MaybeEncoding)383return MaybeEncoding.takeError();384if (!BitCodeAbbrevOp::isValidEncoding(MaybeEncoding.get()))385return error("Invalid encoding");386387BitCodeAbbrevOp::Encoding E =388(BitCodeAbbrevOp::Encoding)MaybeEncoding.get();389if (BitCodeAbbrevOp::hasEncodingData(E)) {390Expected<uint64_t> MaybeData = ReadVBR64(5);391if (!MaybeData)392return MaybeData.takeError();393uint64_t Data = MaybeData.get();394395// As a special case, handle fixed(0) (i.e., a fixed field with zero bits)396// and vbr(0) as a literal zero. This is decoded the same way, and avoids397// a slow path in Read() to have to handle reading zero bits.398if ((E == BitCodeAbbrevOp::Fixed || E == BitCodeAbbrevOp::VBR) &&399Data == 0) {400Abbv->Add(BitCodeAbbrevOp(0));401continue;402}403404if ((E == BitCodeAbbrevOp::Fixed || E == BitCodeAbbrevOp::VBR) &&405Data > MaxChunkSize)406return error("Fixed or VBR abbrev record with size > MaxChunkData");407408Abbv->Add(BitCodeAbbrevOp(E, Data));409} else410Abbv->Add(BitCodeAbbrevOp(E));411}412413if (Abbv->getNumOperandInfos() == 0)414return error("Abbrev record with no operands");415CurAbbrevs.push_back(std::move(Abbv));416417return Error::success();418}419420Expected<std::optional<BitstreamBlockInfo>>421BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) {422if (llvm::Error Err = EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID))423return Err;424425BitstreamBlockInfo NewBlockInfo;426427SmallVector<uint64_t, 64> Record;428BitstreamBlockInfo::BlockInfo *CurBlockInfo = nullptr;429430// Read all the records for this module.431while (true) {432Expected<BitstreamEntry> MaybeEntry =433advanceSkippingSubblocks(AF_DontAutoprocessAbbrevs);434if (!MaybeEntry)435return MaybeEntry.takeError();436BitstreamEntry Entry = MaybeEntry.get();437438switch (Entry.Kind) {439case llvm::BitstreamEntry::SubBlock: // Handled for us already.440case llvm::BitstreamEntry::Error:441return std::nullopt;442case llvm::BitstreamEntry::EndBlock:443return std::move(NewBlockInfo);444case llvm::BitstreamEntry::Record:445// The interesting case.446break;447}448449// Read abbrev records, associate them with CurBID.450if (Entry.ID == bitc::DEFINE_ABBREV) {451if (!CurBlockInfo)452return std::nullopt;453if (Error Err = ReadAbbrevRecord())454return Err;455456// ReadAbbrevRecord installs the abbrev in CurAbbrevs. Move it to the457// appropriate BlockInfo.458CurBlockInfo->Abbrevs.push_back(std::move(CurAbbrevs.back()));459CurAbbrevs.pop_back();460continue;461}462463// Read a record.464Record.clear();465Expected<unsigned> MaybeBlockInfo = readRecord(Entry.ID, Record);466if (!MaybeBlockInfo)467return MaybeBlockInfo.takeError();468switch (MaybeBlockInfo.get()) {469default:470break; // Default behavior, ignore unknown content.471case bitc::BLOCKINFO_CODE_SETBID:472if (Record.size() < 1)473return std::nullopt;474CurBlockInfo = &NewBlockInfo.getOrCreateBlockInfo((unsigned)Record[0]);475break;476case bitc::BLOCKINFO_CODE_BLOCKNAME: {477if (!CurBlockInfo)478return std::nullopt;479if (!ReadBlockInfoNames)480break; // Ignore name.481CurBlockInfo->Name = std::string(Record.begin(), Record.end());482break;483}484case bitc::BLOCKINFO_CODE_SETRECORDNAME: {485if (!CurBlockInfo)486return std::nullopt;487if (!ReadBlockInfoNames)488break; // Ignore name.489CurBlockInfo->RecordNames.emplace_back(490(unsigned)Record[0], std::string(Record.begin() + 1, Record.end()));491break;492}493}494}495}496497498