[llvm] r365091 - [Bitcode] Move Bitstream to a separate library
Francis Visoiu Mistrih via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 3 15:40:07 PDT 2019
Author: thegameg
Date: Wed Jul 3 15:40:07 2019
New Revision: 365091
URL: http://llvm.org/viewvc/llvm-project?rev=365091&view=rev
Log:
[Bitcode] Move Bitstream to a separate library
This moves Bitcode/Bitstream*, Bitcode/BitCodes.h to Bitstream/.
This is needed to avoid a circular dependency when using the bitstream
code for parsing optimization remarks.
Since Bitcode uses Core for the IR part:
libLLVMRemarks -> Bitcode -> Core
and Core uses libLLVMRemarks to generate remarks (see
IR/RemarkStreamer.cpp):
Core -> libLLVMRemarks
we need to separate the Bitstream and Bitcode part.
For clang-doc, it seems that it doesn't need the whole bitcode layer, so
I updated the CMake to only use the bitstream part.
Differential Revision: https://reviews.llvm.org/D63899
Added:
llvm/trunk/include/llvm/Bitstream/
llvm/trunk/include/llvm/Bitstream/BitCodes.h
llvm/trunk/include/llvm/Bitstream/BitstreamReader.h
llvm/trunk/include/llvm/Bitstream/BitstreamWriter.h
llvm/trunk/lib/Bitstream/
llvm/trunk/lib/Bitstream/CMakeLists.txt
llvm/trunk/lib/Bitstream/LLVMBuild.txt
llvm/trunk/lib/Bitstream/Reader/
llvm/trunk/lib/Bitstream/Reader/BitstreamReader.cpp
llvm/trunk/lib/Bitstream/Reader/CMakeLists.txt
llvm/trunk/lib/Bitstream/Reader/LLVMBuild.txt
llvm/trunk/unittests/Bitstream/
llvm/trunk/unittests/Bitstream/BitstreamReaderTest.cpp
llvm/trunk/unittests/Bitstream/BitstreamWriterTest.cpp
llvm/trunk/unittests/Bitstream/CMakeLists.txt
Removed:
llvm/trunk/include/llvm/Bitcode/BitCodes.h
llvm/trunk/include/llvm/Bitcode/BitstreamReader.h
llvm/trunk/include/llvm/Bitcode/BitstreamWriter.h
llvm/trunk/lib/Bitcode/Reader/BitstreamReader.cpp
llvm/trunk/unittests/Bitcode/BitstreamReaderTest.cpp
llvm/trunk/unittests/Bitcode/BitstreamWriterTest.cpp
Modified:
llvm/trunk/include/llvm/Bitcode/BitcodeReader.h
llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
llvm/trunk/include/llvm/Support/JSON.h
llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
llvm/trunk/lib/Bitcode/Reader/CMakeLists.txt
llvm/trunk/lib/Bitcode/Reader/LLVMBuild.txt
llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp
llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
llvm/trunk/lib/CMakeLists.txt
llvm/trunk/lib/LLVMBuild.txt
llvm/trunk/tools/llvm-bcanalyzer/CMakeLists.txt
llvm/trunk/tools/llvm-bcanalyzer/LLVMBuild.txt
llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
llvm/trunk/unittests/Bitcode/CMakeLists.txt
llvm/trunk/unittests/CMakeLists.txt
llvm/trunk/utils/GenLibDeps.pl
Removed: llvm/trunk/include/llvm/Bitcode/BitCodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/BitCodes.h?rev=365090&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Bitcode/BitCodes.h (original)
+++ llvm/trunk/include/llvm/Bitcode/BitCodes.h (removed)
@@ -1,182 +0,0 @@
-//===- BitCodes.h - Enum values for the bitcode format ----------*- C++ -*-===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-// This header Bitcode enum values.
-//
-// The enum values defined in this file should be considered permanent. If
-// new features are added, they should have values added at the end of the
-// respective lists.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_BITCODE_BITCODES_H
-#define LLVM_BITCODE_BITCODES_H
-
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <cassert>
-
-namespace llvm {
-/// Offsets of the 32-bit fields of bitcode wrapper header.
-static const unsigned BWH_MagicField = 0 * 4;
-static const unsigned BWH_VersionField = 1 * 4;
-static const unsigned BWH_OffsetField = 2 * 4;
-static const unsigned BWH_SizeField = 3 * 4;
-static const unsigned BWH_CPUTypeField = 4 * 4;
-static const unsigned BWH_HeaderSize = 5 * 4;
-
-namespace bitc {
- enum StandardWidths {
- BlockIDWidth = 8, // We use VBR-8 for block IDs.
- CodeLenWidth = 4, // Codelen are VBR-4.
- BlockSizeWidth = 32 // BlockSize up to 2^32 32-bit words = 16GB per block.
- };
-
- // The standard abbrev namespace always has a way to exit a block, enter a
- // nested block, define abbrevs, and define an unabbreviated record.
- enum FixedAbbrevIDs {
- END_BLOCK = 0, // Must be zero to guarantee termination for broken bitcode.
- ENTER_SUBBLOCK = 1,
-
- /// DEFINE_ABBREV - Defines an abbrev for the current block. It consists
- /// of a vbr5 for # operand infos. Each operand info is emitted with a
- /// single bit to indicate if it is a literal encoding. If so, the value is
- /// emitted with a vbr8. If not, the encoding is emitted as 3 bits followed
- /// by the info value as a vbr5 if needed.
- DEFINE_ABBREV = 2,
-
- // UNABBREV_RECORDs are emitted with a vbr6 for the record code, followed by
- // a vbr6 for the # operands, followed by vbr6's for each operand.
- UNABBREV_RECORD = 3,
-
- // This is not a code, this is a marker for the first abbrev assignment.
- FIRST_APPLICATION_ABBREV = 4
- };
-
- /// StandardBlockIDs - All bitcode files can optionally include a BLOCKINFO
- /// block, which contains metadata about other blocks in the file.
- enum StandardBlockIDs {
- /// BLOCKINFO_BLOCK is used to define metadata about blocks, for example,
- /// standard abbrevs that should be available to all blocks of a specified
- /// ID.
- BLOCKINFO_BLOCK_ID = 0,
-
- // Block IDs 1-7 are reserved for future expansion.
- FIRST_APPLICATION_BLOCKID = 8
- };
-
- /// BlockInfoCodes - The blockinfo block contains metadata about user-defined
- /// blocks.
- enum BlockInfoCodes {
- // DEFINE_ABBREV has magic semantics here, applying to the current SETBID'd
- // block, instead of the BlockInfo block.
-
- BLOCKINFO_CODE_SETBID = 1, // SETBID: [blockid#]
- BLOCKINFO_CODE_BLOCKNAME = 2, // BLOCKNAME: [name]
- BLOCKINFO_CODE_SETRECORDNAME = 3 // BLOCKINFO_CODE_SETRECORDNAME:
- // [id, name]
- };
-
-} // End bitc namespace
-
-/// BitCodeAbbrevOp - This describes one or more operands in an abbreviation.
-/// This is actually a union of two different things:
-/// 1. It could be a literal integer value ("the operand is always 17").
-/// 2. It could be an encoding specification ("this operand encoded like so").
-///
-class BitCodeAbbrevOp {
- uint64_t Val; // A literal value or data for an encoding.
- bool IsLiteral : 1; // Indicate whether this is a literal value or not.
- unsigned Enc : 3; // The encoding to use.
-public:
- enum Encoding {
- Fixed = 1, // A fixed width field, Val specifies number of bits.
- VBR = 2, // A VBR field where Val specifies the width of each chunk.
- Array = 3, // A sequence of fields, next field species elt encoding.
- Char6 = 4, // A 6-bit fixed field which maps to [a-zA-Z0-9._].
- Blob = 5 // 32-bit aligned array of 8-bit characters.
- };
-
- explicit BitCodeAbbrevOp(uint64_t V) : Val(V), IsLiteral(true) {}
- explicit BitCodeAbbrevOp(Encoding E, uint64_t Data = 0)
- : Val(Data), IsLiteral(false), Enc(E) {}
-
- bool isLiteral() const { return IsLiteral; }
- bool isEncoding() const { return !IsLiteral; }
-
- // Accessors for literals.
- uint64_t getLiteralValue() const { assert(isLiteral()); return Val; }
-
- // Accessors for encoding info.
- Encoding getEncoding() const { assert(isEncoding()); return (Encoding)Enc; }
- uint64_t getEncodingData() const {
- assert(isEncoding() && hasEncodingData());
- return Val;
- }
-
- bool hasEncodingData() const { return hasEncodingData(getEncoding()); }
- static bool hasEncodingData(Encoding E) {
- switch (E) {
- case Fixed:
- case VBR:
- return true;
- case Array:
- case Char6:
- case Blob:
- return false;
- }
- report_fatal_error("Invalid encoding");
- }
-
- /// isChar6 - Return true if this character is legal in the Char6 encoding.
- static bool isChar6(char C) {
- if (C >= 'a' && C <= 'z') return true;
- if (C >= 'A' && C <= 'Z') return true;
- if (C >= '0' && C <= '9') return true;
- if (C == '.' || C == '_') return true;
- return false;
- }
- static unsigned EncodeChar6(char C) {
- if (C >= 'a' && C <= 'z') return C-'a';
- if (C >= 'A' && C <= 'Z') return C-'A'+26;
- if (C >= '0' && C <= '9') return C-'0'+26+26;
- if (C == '.') return 62;
- if (C == '_') return 63;
- llvm_unreachable("Not a value Char6 character!");
- }
-
- static char DecodeChar6(unsigned V) {
- assert((V & ~63) == 0 && "Not a Char6 encoded character!");
- return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._"
- [V];
- }
-
-};
-
-/// BitCodeAbbrev - This class represents an abbreviation record. An
-/// abbreviation allows a complex record that has redundancy to be stored in a
-/// specialized format instead of the fully-general, fully-vbr, format.
-class BitCodeAbbrev {
- SmallVector<BitCodeAbbrevOp, 32> OperandList;
-
-public:
- unsigned getNumOperandInfos() const {
- return static_cast<unsigned>(OperandList.size());
- }
- const BitCodeAbbrevOp &getOperandInfo(unsigned N) const {
- return OperandList[N];
- }
-
- void Add(const BitCodeAbbrevOp &OpInfo) {
- OperandList.push_back(OpInfo);
- }
-};
-} // End llvm namespace
-
-#endif
Modified: llvm/trunk/include/llvm/Bitcode/BitcodeReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/BitcodeReader.h?rev=365091&r1=365090&r2=365091&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Bitcode/BitcodeReader.h (original)
+++ llvm/trunk/include/llvm/Bitcode/BitcodeReader.h Wed Jul 3 15:40:07 2019
@@ -15,7 +15,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/Bitcode/BitCodes.h"
+#include "llvm/Bitstream/BitCodes.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
Removed: llvm/trunk/include/llvm/Bitcode/BitstreamReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/BitstreamReader.h?rev=365090&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Bitcode/BitstreamReader.h (original)
+++ llvm/trunk/include/llvm/Bitcode/BitstreamReader.h (removed)
@@ -1,553 +0,0 @@
-//===- BitstreamReader.h - Low-level bitstream reader interface -*- C++ -*-===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-// This header defines the BitstreamReader class. This class can be used to
-// read an arbitrary bitstream, regardless of its contents.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_BITCODE_BITSTREAMREADER_H
-#define LLVM_BITCODE_BITSTREAMREADER_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Bitcode/BitCodes.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include <algorithm>
-#include <cassert>
-#include <climits>
-#include <cstddef>
-#include <cstdint>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-namespace llvm {
-
-/// This class maintains the abbreviations read from a block info block.
-class BitstreamBlockInfo {
-public:
- /// This contains information emitted to BLOCKINFO_BLOCK blocks. These
- /// describe abbreviations that all blocks of the specified ID inherit.
- struct BlockInfo {
- unsigned BlockID;
- std::vector<std::shared_ptr<BitCodeAbbrev>> Abbrevs;
- std::string Name;
- std::vector<std::pair<unsigned, std::string>> RecordNames;
- };
-
-private:
- std::vector<BlockInfo> BlockInfoRecords;
-
-public:
- /// If there is block info for the specified ID, return it, otherwise return
- /// null.
- const BlockInfo *getBlockInfo(unsigned BlockID) const {
- // Common case, the most recent entry matches BlockID.
- if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID)
- return &BlockInfoRecords.back();
-
- for (unsigned i = 0, e = static_cast<unsigned>(BlockInfoRecords.size());
- i != e; ++i)
- if (BlockInfoRecords[i].BlockID == BlockID)
- return &BlockInfoRecords[i];
- return nullptr;
- }
-
- BlockInfo &getOrCreateBlockInfo(unsigned BlockID) {
- if (const BlockInfo *BI = getBlockInfo(BlockID))
- return *const_cast<BlockInfo*>(BI);
-
- // Otherwise, add a new record.
- BlockInfoRecords.emplace_back();
- BlockInfoRecords.back().BlockID = BlockID;
- return BlockInfoRecords.back();
- }
-};
-
-/// This represents a position within a bitstream. There may be multiple
-/// independent cursors reading within one bitstream, each maintaining their
-/// own local state.
-class SimpleBitstreamCursor {
- ArrayRef<uint8_t> BitcodeBytes;
- size_t NextChar = 0;
-
-public:
- /// 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.
- using word_t = size_t;
-
-private:
- word_t CurWord = 0;
-
- /// This is the number of bits in CurWord that are valid. This is always from
- /// [0...bits_of(size_t)-1] inclusive.
- unsigned BitsInCurWord = 0;
-
-public:
- static const constexpr size_t MaxChunkSize = sizeof(word_t) * 8;
-
- SimpleBitstreamCursor() = default;
- explicit SimpleBitstreamCursor(ArrayRef<uint8_t> BitcodeBytes)
- : BitcodeBytes(BitcodeBytes) {}
- explicit SimpleBitstreamCursor(StringRef BitcodeBytes)
- : BitcodeBytes(arrayRefFromStringRef(BitcodeBytes)) {}
- explicit SimpleBitstreamCursor(MemoryBufferRef BitcodeBytes)
- : SimpleBitstreamCursor(BitcodeBytes.getBuffer()) {}
-
- bool canSkipToPos(size_t pos) const {
- // pos can be skipped to if it is a valid address or one byte past the end.
- return pos <= BitcodeBytes.size();
- }
-
- bool AtEndOfStream() {
- return BitsInCurWord == 0 && BitcodeBytes.size() <= NextChar;
- }
-
- /// Return the bit # of the bit we are reading.
- uint64_t GetCurrentBitNo() const {
- return NextChar*CHAR_BIT - BitsInCurWord;
- }
-
- // Return the byte # of the current bit.
- uint64_t getCurrentByteNo() const { return GetCurrentBitNo() / 8; }
-
- ArrayRef<uint8_t> getBitcodeBytes() const { return BitcodeBytes; }
-
- /// Reset the stream to the specified bit number.
- Error JumpToBit(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");
-
- // Move the cursor to the right word.
- NextChar = ByteNo;
- BitsInCurWord = 0;
-
- // Skip over any bits that are already consumed.
- if (WordBitNo) {
- if (Expected<word_t> Res = Read(WordBitNo))
- return Error::success();
- else
- return Res.takeError();
- }
-
- return Error::success();
- }
-
- /// Get a pointer into the bitstream at the specified byte offset.
- const uint8_t *getPointerToByte(uint64_t ByteNo, uint64_t NumBytes) {
- return BitcodeBytes.data() + ByteNo;
- }
-
- /// Get a pointer into the bitstream at the specified bit offset.
- ///
- /// The bit offset must be on a byte boundary.
- const uint8_t *getPointerToBit(uint64_t BitNo, uint64_t NumBytes) {
- assert(!(BitNo % 8) && "Expected bit on byte boundary");
- 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());
-
- // Read the next word from the stream.
- const uint8_t *NextCharPtr = BitcodeBytes.data() + NextChar;
- unsigned BytesRead;
- if (BitcodeBytes.size() >= NextChar + sizeof(word_t)) {
- BytesRead = sizeof(word_t);
- CurWord =
- support::endian::read<word_t, support::little, support::unaligned>(
- NextCharPtr);
- } else {
- // Short read.
- BytesRead = BitcodeBytes.size() - NextChar;
- CurWord = 0;
- for (unsigned B = 0; B != BytesRead; ++B)
- CurWord |= uint64_t(NextCharPtr[B]) << (B * 8);
- }
- NextChar += BytesRead;
- BitsInCurWord = BytesRead * 8;
- return Error::success();
- }
-
- Expected<word_t> Read(unsigned NumBits) {
- static const unsigned BitsInWord = MaxChunkSize;
-
- assert(NumBits && NumBits <= BitsInWord &&
- "Cannot return zero or more than BitsInWord bits!");
-
- static const unsigned Mask = sizeof(word_t) > 4 ? 0x3f : 0x1f;
-
- // If the field is fully contained by CurWord, return it quickly.
- if (BitsInCurWord >= NumBits) {
- word_t R = CurWord & (~word_t(0) >> (BitsInWord - NumBits));
-
- // Use a mask to avoid undefined behavior.
- CurWord >>= (NumBits & Mask);
-
- BitsInCurWord -= NumBits;
- return R;
- }
-
- 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);
-
- word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft));
-
- // Use a mask to avoid undefined behavior.
- CurWord >>= (BitsLeft & Mask);
-
- BitsInCurWord -= BitsLeft;
-
- R |= R2 << (NumBits - BitsLeft);
-
- return R;
- }
-
- Expected<uint32_t> ReadVBR(unsigned NumBits) {
- Expected<unsigned> MaybeRead = Read(NumBits);
- if (!MaybeRead)
- return MaybeRead;
- uint32_t Piece = MaybeRead.get();
-
- if ((Piece & (1U << (NumBits-1))) == 0)
- return Piece;
-
- uint32_t Result = 0;
- unsigned NextBit = 0;
- while (true) {
- Result |= (Piece & ((1U << (NumBits-1))-1)) << NextBit;
-
- if ((Piece & (1U << (NumBits-1))) == 0)
- return Result;
-
- NextBit += NumBits-1;
- MaybeRead = Read(NumBits);
- if (!MaybeRead)
- return MaybeRead;
- Piece = MaybeRead.get();
- }
- }
-
- // 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<uint64_t> ReadVBR64(unsigned NumBits) {
- Expected<uint64_t> MaybeRead = Read(NumBits);
- if (!MaybeRead)
- return MaybeRead;
- uint32_t Piece = MaybeRead.get();
-
- if ((Piece & (1U << (NumBits-1))) == 0)
- return uint64_t(Piece);
-
- uint64_t Result = 0;
- unsigned NextBit = 0;
- while (true) {
- Result |= uint64_t(Piece & ((1U << (NumBits-1))-1)) << NextBit;
-
- if ((Piece & (1U << (NumBits-1))) == 0)
- return Result;
-
- NextBit += NumBits-1;
- MaybeRead = Read(NumBits);
- if (!MaybeRead)
- return MaybeRead;
- Piece = MaybeRead.get();
- }
- }
-
- 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;
- }
-
- /// Skip to the end of the file.
- void skipToEnd() { NextChar = BitcodeBytes.size(); }
-};
-
-/// When advancing through a bitstream cursor, each advance can discover a few
-/// different kinds of entries:
-struct BitstreamEntry {
- enum {
- 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.
- } 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;
- }
-};
-
-/// This represents a position within a bitcode file, implemented on top of a
-/// SimpleBitstreamCursor.
-///
-/// Unlike iterators, BitstreamCursors are heavy-weight objects that should not
-/// be passed by value.
-class BitstreamCursor : SimpleBitstreamCursor {
- // This is the declared size of code values used for the current block, in
- // bits.
- unsigned CurCodeSize = 2;
-
- /// Abbrevs installed at in this block.
- std::vector<std::shared_ptr<BitCodeAbbrev>> CurAbbrevs;
-
- struct Block {
- unsigned PrevCodeSize;
- std::vector<std::shared_ptr<BitCodeAbbrev>> PrevAbbrevs;
-
- explicit Block(unsigned PCS) : PrevCodeSize(PCS) {}
- };
-
- /// This tracks the codesize of parent blocks.
- SmallVector<Block, 8> BlockScope;
-
- BitstreamBlockInfo *BlockInfo = nullptr;
-
-public:
- static const size_t MaxChunkSize = sizeof(word_t) * 8;
-
- BitstreamCursor() = default;
- explicit BitstreamCursor(ArrayRef<uint8_t> BitcodeBytes)
- : SimpleBitstreamCursor(BitcodeBytes) {}
- explicit BitstreamCursor(StringRef BitcodeBytes)
- : SimpleBitstreamCursor(BitcodeBytes) {}
- explicit BitstreamCursor(MemoryBufferRef BitcodeBytes)
- : SimpleBitstreamCursor(BitcodeBytes) {}
-
- using SimpleBitstreamCursor::canSkipToPos;
- using SimpleBitstreamCursor::AtEndOfStream;
- using SimpleBitstreamCursor::getBitcodeBytes;
- using SimpleBitstreamCursor::GetCurrentBitNo;
- using SimpleBitstreamCursor::getCurrentByteNo;
- using SimpleBitstreamCursor::getPointerToByte;
- using SimpleBitstreamCursor::JumpToBit;
- using SimpleBitstreamCursor::fillCurWord;
- using SimpleBitstreamCursor::Read;
- using SimpleBitstreamCursor::ReadVBR;
- using SimpleBitstreamCursor::ReadVBR64;
-
- /// Return the number of bits used to encode an abbrev #.
- unsigned getAbbrevIDWidth() const { return CurCodeSize; }
-
- /// Flags that modify the behavior of advance().
- enum {
- /// 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,
-
- /// If this flag is used, abbrev entries are returned just like normal
- /// records.
- AF_DontAutoprocessAbbrevs = 2
- };
-
- /// Advance the current bitstream, returning the next entry in the stream.
- Expected<BitstreamEntry> advance(unsigned Flags = 0) {
- while (true) {
- if (AtEndOfStream())
- return BitstreamEntry::getError();
-
- Expected<unsigned> MaybeCode = ReadCode();
- if (!MaybeCode)
- return MaybeCode.takeError();
- unsigned Code = MaybeCode.get();
-
- if (Code == bitc::END_BLOCK) {
- // Pop the end of the block unless Flags tells us not to.
- if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd())
- return BitstreamEntry::getError();
- return BitstreamEntry::getEndBlock();
- }
-
- if (Code == bitc::ENTER_SUBBLOCK) {
- if (Expected<unsigned> MaybeSubBlock = ReadSubBlockID())
- return BitstreamEntry::getSubBlock(MaybeSubBlock.get());
- else
- return MaybeSubBlock.takeError();
- }
-
- if (Code == bitc::DEFINE_ABBREV &&
- !(Flags & AF_DontAutoprocessAbbrevs)) {
- // We read and accumulate abbrev's, the client can't do anything with
- // them anyway.
- if (Error Err = ReadAbbrevRecord())
- return std::move(Err);
- continue;
- }
-
- return BitstreamEntry::getRecord(Code);
- }
- }
-
- /// This is a convenience function for clients that don't expect any
- /// subblocks. This just skips over them automatically.
- Expected<BitstreamEntry> advanceSkippingSubblocks(unsigned Flags = 0) {
- while (true) {
- // If we found a normal entry, return it.
- Expected<BitstreamEntry> MaybeEntry = advance(Flags);
- if (!MaybeEntry)
- return MaybeEntry;
- BitstreamEntry Entry = MaybeEntry.get();
-
- if (Entry.Kind != BitstreamEntry::SubBlock)
- return Entry;
-
- // If we found a sub-block, just skip over it and check the next entry.
- if (Error Err = SkipBlock())
- return std::move(Err);
- }
- }
-
- Expected<unsigned> ReadCode() { return Read(CurCodeSize); }
-
- // Block header:
- // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
-
- /// Having read the ENTER_SUBBLOCK code, read the BlockID for the block.
- Expected<unsigned> ReadSubBlockID() { return ReadVBR(bitc::BlockIDWidth); }
-
- /// Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body
- /// of this block.
- Error SkipBlock() {
- // Read and ignore the codelen value.
- if (Expected<uint32_t> 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();
-
- SkipToFourByteBoundary();
- Expected<unsigned> MaybeNum = Read(bitc::BlockSizeWidth);
- if (!MaybeNum)
- return MaybeNum.takeError();
- size_t NumFourBytes = MaybeNum.get();
-
- // 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");
- if (!canSkipToPos(SkipTo / 8))
- return createStringError(std::errc::illegal_byte_sequence,
- "can't skip to bit %zu from %" PRIu64, SkipTo,
- GetCurrentBitNo());
-
- if (Error Res = JumpToBit(SkipTo))
- return Res;
-
- return Error::success();
- }
-
- /// Having read the ENTER_SUBBLOCK abbrevid, and enter the block.
- Error EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr);
-
- bool ReadBlockEnd() {
- if (BlockScope.empty()) return true;
-
- // Block tail:
- // [END_BLOCK, <align4bytes>]
- SkipToFourByteBoundary();
-
- popBlockScope();
- return false;
- }
-
-private:
- void popBlockScope() {
- CurCodeSize = BlockScope.back().PrevCodeSize;
-
- CurAbbrevs = std::move(BlockScope.back().PrevAbbrevs);
- BlockScope.pop_back();
- }
-
- //===--------------------------------------------------------------------===//
- // Record Processing
- //===--------------------------------------------------------------------===//
-
-public:
- /// Return the abbreviation for the specified AbbrevId.
- const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) {
- unsigned AbbrevNo = AbbrevID - bitc::FIRST_APPLICATION_ABBREV;
- if (AbbrevNo >= CurAbbrevs.size())
- report_fatal_error("Invalid abbrev number");
- return CurAbbrevs[AbbrevNo].get();
- }
-
- /// Read the current record and discard it, returning the code for the record.
- Expected<unsigned> skipRecord(unsigned AbbrevID);
-
- Expected<unsigned> readRecord(unsigned AbbrevID,
- SmallVectorImpl<uint64_t> &Vals,
- StringRef *Blob = nullptr);
-
- //===--------------------------------------------------------------------===//
- // Abbrev Processing
- //===--------------------------------------------------------------------===//
- Error ReadAbbrevRecord();
-
- /// Read and return a block info block from the bitstream. If an error was
- /// encountered, return None.
- ///
- /// \param ReadBlockInfoNames Whether to read block/record name information in
- /// the BlockInfo block. Only llvm-bcanalyzer uses this.
- Expected<Optional<BitstreamBlockInfo>>
- ReadBlockInfoBlock(bool ReadBlockInfoNames = false);
-
- /// Set the block info to be used by this BitstreamCursor to interpret
- /// abbreviated records.
- void setBlockInfo(BitstreamBlockInfo *BI) { BlockInfo = BI; }
-};
-
-} // end llvm namespace
-
-#endif // LLVM_BITCODE_BITSTREAMREADER_H
Removed: llvm/trunk/include/llvm/Bitcode/BitstreamWriter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/BitstreamWriter.h?rev=365090&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Bitcode/BitstreamWriter.h (original)
+++ llvm/trunk/include/llvm/Bitcode/BitstreamWriter.h (removed)
@@ -1,547 +0,0 @@
-//===- BitstreamWriter.h - Low-level bitstream writer interface -*- C++ -*-===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-// This header defines the BitstreamWriter class. This class can be used to
-// write an arbitrary bitstream, regardless of its contents.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_BITCODE_BITSTREAMWRITER_H
-#define LLVM_BITCODE_BITSTREAMWRITER_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Bitcode/BitCodes.h"
-#include "llvm/Support/Endian.h"
-#include <vector>
-
-namespace llvm {
-
-class BitstreamWriter {
- SmallVectorImpl<char> &Out;
-
- /// CurBit - Always between 0 and 31 inclusive, specifies the next bit to use.
- unsigned CurBit;
-
- /// CurValue - The current value. Only bits < CurBit are valid.
- uint32_t CurValue;
-
- /// CurCodeSize - This is the declared size of code values used for the
- /// current block, in bits.
- unsigned CurCodeSize;
-
- /// BlockInfoCurBID - When emitting a BLOCKINFO_BLOCK, this is the currently
- /// selected BLOCK ID.
- unsigned BlockInfoCurBID;
-
- /// CurAbbrevs - Abbrevs installed at in this block.
- std::vector<std::shared_ptr<BitCodeAbbrev>> CurAbbrevs;
-
- struct Block {
- unsigned PrevCodeSize;
- size_t StartSizeWord;
- std::vector<std::shared_ptr<BitCodeAbbrev>> PrevAbbrevs;
- Block(unsigned PCS, size_t SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {}
- };
-
- /// BlockScope - This tracks the current blocks that we have entered.
- std::vector<Block> BlockScope;
-
- /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks.
- /// These describe abbreviations that all blocks of the specified ID inherit.
- struct BlockInfo {
- unsigned BlockID;
- std::vector<std::shared_ptr<BitCodeAbbrev>> Abbrevs;
- };
- std::vector<BlockInfo> BlockInfoRecords;
-
- void WriteByte(unsigned char Value) {
- Out.push_back(Value);
- }
-
- void WriteWord(unsigned Value) {
- Value = support::endian::byte_swap<uint32_t, support::little>(Value);
- Out.append(reinterpret_cast<const char *>(&Value),
- reinterpret_cast<const char *>(&Value + 1));
- }
-
- size_t GetBufferOffset() const { return Out.size(); }
-
- size_t GetWordIndex() const {
- size_t Offset = GetBufferOffset();
- assert((Offset & 3) == 0 && "Not 32-bit aligned");
- return Offset / 4;
- }
-
-public:
- explicit BitstreamWriter(SmallVectorImpl<char> &O)
- : Out(O), CurBit(0), CurValue(0), CurCodeSize(2) {}
-
- ~BitstreamWriter() {
- assert(CurBit == 0 && "Unflushed data remaining");
- assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance");
- }
-
- /// Retrieve the current position in the stream, in bits.
- uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 + CurBit; }
-
- /// Retrieve the number of bits currently used to encode an abbrev ID.
- unsigned GetAbbrevIDWidth() const { return CurCodeSize; }
-
- //===--------------------------------------------------------------------===//
- // Basic Primitives for emitting bits to the stream.
- //===--------------------------------------------------------------------===//
-
- /// Backpatch a 32-bit word in the output at the given bit offset
- /// with the specified value.
- void BackpatchWord(uint64_t BitNo, unsigned NewWord) {
- using namespace llvm::support;
- unsigned ByteNo = BitNo / 8;
- assert((!endian::readAtBitAlignment<uint32_t, little, unaligned>(
- &Out[ByteNo], BitNo & 7)) &&
- "Expected to be patching over 0-value placeholders");
- endian::writeAtBitAlignment<uint32_t, little, unaligned>(
- &Out[ByteNo], NewWord, BitNo & 7);
- }
-
- void BackpatchWord64(uint64_t BitNo, uint64_t Val) {
- BackpatchWord(BitNo, (uint32_t)Val);
- BackpatchWord(BitNo + 32, (uint32_t)(Val >> 32));
- }
-
- void Emit(uint32_t Val, unsigned NumBits) {
- assert(NumBits && NumBits <= 32 && "Invalid value size!");
- assert((Val & ~(~0U >> (32-NumBits))) == 0 && "High bits set!");
- CurValue |= Val << CurBit;
- if (CurBit + NumBits < 32) {
- CurBit += NumBits;
- return;
- }
-
- // Add the current word.
- WriteWord(CurValue);
-
- if (CurBit)
- CurValue = Val >> (32-CurBit);
- else
- CurValue = 0;
- CurBit = (CurBit+NumBits) & 31;
- }
-
- void FlushToWord() {
- if (CurBit) {
- WriteWord(CurValue);
- CurBit = 0;
- CurValue = 0;
- }
- }
-
- void EmitVBR(uint32_t Val, unsigned NumBits) {
- assert(NumBits <= 32 && "Too many bits to emit!");
- uint32_t Threshold = 1U << (NumBits-1);
-
- // Emit the bits with VBR encoding, NumBits-1 bits at a time.
- while (Val >= Threshold) {
- Emit((Val & ((1 << (NumBits-1))-1)) | (1 << (NumBits-1)), NumBits);
- Val >>= NumBits-1;
- }
-
- Emit(Val, NumBits);
- }
-
- void EmitVBR64(uint64_t Val, unsigned NumBits) {
- assert(NumBits <= 32 && "Too many bits to emit!");
- if ((uint32_t)Val == Val)
- return EmitVBR((uint32_t)Val, NumBits);
-
- uint32_t Threshold = 1U << (NumBits-1);
-
- // Emit the bits with VBR encoding, NumBits-1 bits at a time.
- while (Val >= Threshold) {
- Emit(((uint32_t)Val & ((1 << (NumBits-1))-1)) |
- (1 << (NumBits-1)), NumBits);
- Val >>= NumBits-1;
- }
-
- Emit((uint32_t)Val, NumBits);
- }
-
- /// EmitCode - Emit the specified code.
- void EmitCode(unsigned Val) {
- Emit(Val, CurCodeSize);
- }
-
- //===--------------------------------------------------------------------===//
- // Block Manipulation
- //===--------------------------------------------------------------------===//
-
- /// getBlockInfo - If there is block info for the specified ID, return it,
- /// otherwise return null.
- BlockInfo *getBlockInfo(unsigned BlockID) {
- // Common case, the most recent entry matches BlockID.
- if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID)
- return &BlockInfoRecords.back();
-
- for (unsigned i = 0, e = static_cast<unsigned>(BlockInfoRecords.size());
- i != e; ++i)
- if (BlockInfoRecords[i].BlockID == BlockID)
- return &BlockInfoRecords[i];
- return nullptr;
- }
-
- void EnterSubblock(unsigned BlockID, unsigned CodeLen) {
- // Block header:
- // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
- EmitCode(bitc::ENTER_SUBBLOCK);
- EmitVBR(BlockID, bitc::BlockIDWidth);
- EmitVBR(CodeLen, bitc::CodeLenWidth);
- FlushToWord();
-
- size_t BlockSizeWordIndex = GetWordIndex();
- unsigned OldCodeSize = CurCodeSize;
-
- // Emit a placeholder, which will be replaced when the block is popped.
- Emit(0, bitc::BlockSizeWidth);
-
- CurCodeSize = CodeLen;
-
- // Push the outer block's abbrev set onto the stack, start out with an
- // empty abbrev set.
- BlockScope.emplace_back(OldCodeSize, BlockSizeWordIndex);
- BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
-
- // If there is a blockinfo for this BlockID, add all the predefined abbrevs
- // to the abbrev list.
- if (BlockInfo *Info = getBlockInfo(BlockID)) {
- CurAbbrevs.insert(CurAbbrevs.end(), Info->Abbrevs.begin(),
- Info->Abbrevs.end());
- }
- }
-
- void ExitBlock() {
- assert(!BlockScope.empty() && "Block scope imbalance!");
- const Block &B = BlockScope.back();
-
- // Block tail:
- // [END_BLOCK, <align4bytes>]
- EmitCode(bitc::END_BLOCK);
- FlushToWord();
-
- // Compute the size of the block, in words, not counting the size field.
- size_t SizeInWords = GetWordIndex() - B.StartSizeWord - 1;
- uint64_t BitNo = uint64_t(B.StartSizeWord) * 32;
-
- // Update the block size field in the header of this sub-block.
- BackpatchWord(BitNo, SizeInWords);
-
- // Restore the inner block's code size and abbrev table.
- CurCodeSize = B.PrevCodeSize;
- CurAbbrevs = std::move(B.PrevAbbrevs);
- BlockScope.pop_back();
- }
-
- //===--------------------------------------------------------------------===//
- // Record Emission
- //===--------------------------------------------------------------------===//
-
-private:
- /// EmitAbbreviatedLiteral - Emit a literal value according to its abbrev
- /// record. This is a no-op, since the abbrev specifies the literal to use.
- template<typename uintty>
- void EmitAbbreviatedLiteral(const BitCodeAbbrevOp &Op, uintty V) {
- assert(Op.isLiteral() && "Not a literal");
- // If the abbrev specifies the literal value to use, don't emit
- // anything.
- assert(V == Op.getLiteralValue() &&
- "Invalid abbrev for record!");
- }
-
- /// EmitAbbreviatedField - Emit a single scalar field value with the specified
- /// encoding.
- template<typename uintty>
- void EmitAbbreviatedField(const BitCodeAbbrevOp &Op, uintty V) {
- assert(!Op.isLiteral() && "Literals should use EmitAbbreviatedLiteral!");
-
- // Encode the value as we are commanded.
- switch (Op.getEncoding()) {
- default: llvm_unreachable("Unknown encoding!");
- case BitCodeAbbrevOp::Fixed:
- if (Op.getEncodingData())
- Emit((unsigned)V, (unsigned)Op.getEncodingData());
- break;
- case BitCodeAbbrevOp::VBR:
- if (Op.getEncodingData())
- EmitVBR64(V, (unsigned)Op.getEncodingData());
- break;
- case BitCodeAbbrevOp::Char6:
- Emit(BitCodeAbbrevOp::EncodeChar6((char)V), 6);
- break;
- }
- }
-
- /// EmitRecordWithAbbrevImpl - This is the core implementation of the record
- /// emission code. If BlobData is non-null, then it specifies an array of
- /// data that should be emitted as part of the Blob or Array operand that is
- /// known to exist at the end of the record. If Code is specified, then
- /// it is the record code to emit before the Vals, which must not contain
- /// the code.
- template <typename uintty>
- void EmitRecordWithAbbrevImpl(unsigned Abbrev, ArrayRef<uintty> Vals,
- StringRef Blob, Optional<unsigned> Code) {
- const char *BlobData = Blob.data();
- unsigned BlobLen = (unsigned) Blob.size();
- unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV;
- assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!");
- const BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo].get();
-
- EmitCode(Abbrev);
-
- unsigned i = 0, e = static_cast<unsigned>(Abbv->getNumOperandInfos());
- if (Code) {
- assert(e && "Expected non-empty abbreviation");
- const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i++);
-
- if (Op.isLiteral())
- EmitAbbreviatedLiteral(Op, Code.getValue());
- else {
- assert(Op.getEncoding() != BitCodeAbbrevOp::Array &&
- Op.getEncoding() != BitCodeAbbrevOp::Blob &&
- "Expected literal or scalar");
- EmitAbbreviatedField(Op, Code.getValue());
- }
- }
-
- unsigned RecordIdx = 0;
- for (; i != e; ++i) {
- const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
- if (Op.isLiteral()) {
- assert(RecordIdx < Vals.size() && "Invalid abbrev/record");
- EmitAbbreviatedLiteral(Op, Vals[RecordIdx]);
- ++RecordIdx;
- } else if (Op.getEncoding() == BitCodeAbbrevOp::Array) {
- // Array case.
- assert(i + 2 == e && "array op not second to last?");
- const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i);
-
- // If this record has blob data, emit it, otherwise we must have record
- // entries to encode this way.
- if (BlobData) {
- assert(RecordIdx == Vals.size() &&
- "Blob data and record entries specified for array!");
- // Emit a vbr6 to indicate the number of elements present.
- EmitVBR(static_cast<uint32_t>(BlobLen), 6);
-
- // Emit each field.
- for (unsigned i = 0; i != BlobLen; ++i)
- EmitAbbreviatedField(EltEnc, (unsigned char)BlobData[i]);
-
- // Know that blob data is consumed for assertion below.
- BlobData = nullptr;
- } else {
- // Emit a vbr6 to indicate the number of elements present.
- EmitVBR(static_cast<uint32_t>(Vals.size()-RecordIdx), 6);
-
- // Emit each field.
- for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx)
- EmitAbbreviatedField(EltEnc, Vals[RecordIdx]);
- }
- } else if (Op.getEncoding() == BitCodeAbbrevOp::Blob) {
- // If this record has blob data, emit it, otherwise we must have record
- // entries to encode this way.
-
- if (BlobData) {
- assert(RecordIdx == Vals.size() &&
- "Blob data and record entries specified for blob operand!");
-
- assert(Blob.data() == BlobData && "BlobData got moved");
- assert(Blob.size() == BlobLen && "BlobLen got changed");
- emitBlob(Blob);
- BlobData = nullptr;
- } else {
- emitBlob(Vals.slice(RecordIdx));
- }
- } else { // Single scalar field.
- assert(RecordIdx < Vals.size() && "Invalid abbrev/record");
- EmitAbbreviatedField(Op, Vals[RecordIdx]);
- ++RecordIdx;
- }
- }
- assert(RecordIdx == Vals.size() && "Not all record operands emitted!");
- assert(BlobData == nullptr &&
- "Blob data specified for record that doesn't use it!");
- }
-
-public:
- /// Emit a blob, including flushing before and tail-padding.
- template <class UIntTy>
- void emitBlob(ArrayRef<UIntTy> Bytes, bool ShouldEmitSize = true) {
- // Emit a vbr6 to indicate the number of elements present.
- if (ShouldEmitSize)
- EmitVBR(static_cast<uint32_t>(Bytes.size()), 6);
-
- // Flush to a 32-bit alignment boundary.
- FlushToWord();
-
- // Emit literal bytes.
- for (const auto &B : Bytes) {
- assert(isUInt<8>(B) && "Value too large to emit as byte");
- WriteByte((unsigned char)B);
- }
-
- // Align end to 32-bits.
- while (GetBufferOffset() & 3)
- WriteByte(0);
- }
- void emitBlob(StringRef Bytes, bool ShouldEmitSize = true) {
- emitBlob(makeArrayRef((const uint8_t *)Bytes.data(), Bytes.size()),
- ShouldEmitSize);
- }
-
- /// EmitRecord - Emit the specified record to the stream, using an abbrev if
- /// we have one to compress the output.
- template <typename Container>
- void EmitRecord(unsigned Code, const Container &Vals, unsigned Abbrev = 0) {
- if (!Abbrev) {
- // If we don't have an abbrev to use, emit this in its fully unabbreviated
- // form.
- auto Count = static_cast<uint32_t>(makeArrayRef(Vals).size());
- EmitCode(bitc::UNABBREV_RECORD);
- EmitVBR(Code, 6);
- EmitVBR(Count, 6);
- for (unsigned i = 0, e = Count; i != e; ++i)
- EmitVBR64(Vals[i], 6);
- return;
- }
-
- EmitRecordWithAbbrevImpl(Abbrev, makeArrayRef(Vals), StringRef(), Code);
- }
-
- /// EmitRecordWithAbbrev - Emit a record with the specified abbreviation.
- /// Unlike EmitRecord, the code for the record should be included in Vals as
- /// the first entry.
- template <typename Container>
- void EmitRecordWithAbbrev(unsigned Abbrev, const Container &Vals) {
- EmitRecordWithAbbrevImpl(Abbrev, makeArrayRef(Vals), StringRef(), None);
- }
-
- /// EmitRecordWithBlob - Emit the specified record to the stream, using an
- /// abbrev that includes a blob at the end. The blob data to emit is
- /// specified by the pointer and length specified at the end. In contrast to
- /// EmitRecord, this routine expects that the first entry in Vals is the code
- /// of the record.
- template <typename Container>
- void EmitRecordWithBlob(unsigned Abbrev, const Container &Vals,
- StringRef Blob) {
- EmitRecordWithAbbrevImpl(Abbrev, makeArrayRef(Vals), Blob, None);
- }
- template <typename Container>
- void EmitRecordWithBlob(unsigned Abbrev, const Container &Vals,
- const char *BlobData, unsigned BlobLen) {
- return EmitRecordWithAbbrevImpl(Abbrev, makeArrayRef(Vals),
- StringRef(BlobData, BlobLen), None);
- }
-
- /// EmitRecordWithArray - Just like EmitRecordWithBlob, works with records
- /// that end with an array.
- template <typename Container>
- void EmitRecordWithArray(unsigned Abbrev, const Container &Vals,
- StringRef Array) {
- EmitRecordWithAbbrevImpl(Abbrev, makeArrayRef(Vals), Array, None);
- }
- template <typename Container>
- void EmitRecordWithArray(unsigned Abbrev, const Container &Vals,
- const char *ArrayData, unsigned ArrayLen) {
- return EmitRecordWithAbbrevImpl(Abbrev, makeArrayRef(Vals),
- StringRef(ArrayData, ArrayLen), None);
- }
-
- //===--------------------------------------------------------------------===//
- // Abbrev Emission
- //===--------------------------------------------------------------------===//
-
-private:
- // Emit the abbreviation as a DEFINE_ABBREV record.
- void EncodeAbbrev(const BitCodeAbbrev &Abbv) {
- EmitCode(bitc::DEFINE_ABBREV);
- EmitVBR(Abbv.getNumOperandInfos(), 5);
- for (unsigned i = 0, e = static_cast<unsigned>(Abbv.getNumOperandInfos());
- i != e; ++i) {
- const BitCodeAbbrevOp &Op = Abbv.getOperandInfo(i);
- Emit(Op.isLiteral(), 1);
- if (Op.isLiteral()) {
- EmitVBR64(Op.getLiteralValue(), 8);
- } else {
- Emit(Op.getEncoding(), 3);
- if (Op.hasEncodingData())
- EmitVBR64(Op.getEncodingData(), 5);
- }
- }
- }
-public:
-
- /// Emits the abbreviation \p Abbv to the stream.
- unsigned EmitAbbrev(std::shared_ptr<BitCodeAbbrev> Abbv) {
- EncodeAbbrev(*Abbv);
- CurAbbrevs.push_back(std::move(Abbv));
- return static_cast<unsigned>(CurAbbrevs.size())-1 +
- bitc::FIRST_APPLICATION_ABBREV;
- }
-
- //===--------------------------------------------------------------------===//
- // BlockInfo Block Emission
- //===--------------------------------------------------------------------===//
-
- /// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK.
- void EnterBlockInfoBlock() {
- EnterSubblock(bitc::BLOCKINFO_BLOCK_ID, 2);
- BlockInfoCurBID = ~0U;
- BlockInfoRecords.clear();
- }
-private:
- /// SwitchToBlockID - If we aren't already talking about the specified block
- /// ID, emit a BLOCKINFO_CODE_SETBID record.
- void SwitchToBlockID(unsigned BlockID) {
- if (BlockInfoCurBID == BlockID) return;
- SmallVector<unsigned, 2> V;
- V.push_back(BlockID);
- EmitRecord(bitc::BLOCKINFO_CODE_SETBID, V);
- BlockInfoCurBID = BlockID;
- }
-
- BlockInfo &getOrCreateBlockInfo(unsigned BlockID) {
- if (BlockInfo *BI = getBlockInfo(BlockID))
- return *BI;
-
- // Otherwise, add a new record.
- BlockInfoRecords.emplace_back();
- BlockInfoRecords.back().BlockID = BlockID;
- return BlockInfoRecords.back();
- }
-
-public:
-
- /// EmitBlockInfoAbbrev - Emit a DEFINE_ABBREV record for the specified
- /// BlockID.
- unsigned EmitBlockInfoAbbrev(unsigned BlockID, std::shared_ptr<BitCodeAbbrev> Abbv) {
- SwitchToBlockID(BlockID);
- EncodeAbbrev(*Abbv);
-
- // Add the abbrev to the specified block record.
- BlockInfo &Info = getOrCreateBlockInfo(BlockID);
- Info.Abbrevs.push_back(std::move(Abbv));
-
- return Info.Abbrevs.size()-1+bitc::FIRST_APPLICATION_ABBREV;
- }
-};
-
-
-} // End llvm namespace
-
-#endif
Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=365091&r1=365090&r2=365091&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
+++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Wed Jul 3 15:40:07 2019
@@ -17,7 +17,7 @@
#ifndef LLVM_BITCODE_LLVMBITCODES_H
#define LLVM_BITCODE_LLVMBITCODES_H
-#include "llvm/Bitcode/BitCodes.h"
+#include "llvm/Bitstream/BitCodes.h"
namespace llvm {
namespace bitc {
Added: llvm/trunk/include/llvm/Bitstream/BitCodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitstream/BitCodes.h?rev=365091&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Bitstream/BitCodes.h (added)
+++ llvm/trunk/include/llvm/Bitstream/BitCodes.h Wed Jul 3 15:40:07 2019
@@ -0,0 +1,182 @@
+//===- BitCodes.h - Enum values for the bitstream format --------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines bitstream enum values.
+//
+// The enum values defined in this file should be considered permanent. If
+// new features are added, they should have values added at the end of the
+// respective lists.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_BITSTREAM_BITCODES_H
+#define LLVM_BITSTREAM_BITCODES_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+
+namespace llvm {
+/// Offsets of the 32-bit fields of bitstream wrapper header.
+static const unsigned BWH_MagicField = 0 * 4;
+static const unsigned BWH_VersionField = 1 * 4;
+static const unsigned BWH_OffsetField = 2 * 4;
+static const unsigned BWH_SizeField = 3 * 4;
+static const unsigned BWH_CPUTypeField = 4 * 4;
+static const unsigned BWH_HeaderSize = 5 * 4;
+
+namespace bitc {
+ enum StandardWidths {
+ BlockIDWidth = 8, // We use VBR-8 for block IDs.
+ CodeLenWidth = 4, // Codelen are VBR-4.
+ BlockSizeWidth = 32 // BlockSize up to 2^32 32-bit words = 16GB per block.
+ };
+
+ // The standard abbrev namespace always has a way to exit a block, enter a
+ // nested block, define abbrevs, and define an unabbreviated record.
+ enum FixedAbbrevIDs {
+ END_BLOCK = 0, // Must be zero to guarantee termination for broken bitcode.
+ ENTER_SUBBLOCK = 1,
+
+ /// DEFINE_ABBREV - Defines an abbrev for the current block. It consists
+ /// of a vbr5 for # operand infos. Each operand info is emitted with a
+ /// single bit to indicate if it is a literal encoding. If so, the value is
+ /// emitted with a vbr8. If not, the encoding is emitted as 3 bits followed
+ /// by the info value as a vbr5 if needed.
+ DEFINE_ABBREV = 2,
+
+ // UNABBREV_RECORDs are emitted with a vbr6 for the record code, followed by
+ // a vbr6 for the # operands, followed by vbr6's for each operand.
+ UNABBREV_RECORD = 3,
+
+ // This is not a code, this is a marker for the first abbrev assignment.
+ FIRST_APPLICATION_ABBREV = 4
+ };
+
+ /// StandardBlockIDs - All bitcode files can optionally include a BLOCKINFO
+ /// block, which contains metadata about other blocks in the file.
+ enum StandardBlockIDs {
+ /// BLOCKINFO_BLOCK is used to define metadata about blocks, for example,
+ /// standard abbrevs that should be available to all blocks of a specified
+ /// ID.
+ BLOCKINFO_BLOCK_ID = 0,
+
+ // Block IDs 1-7 are reserved for future expansion.
+ FIRST_APPLICATION_BLOCKID = 8
+ };
+
+ /// BlockInfoCodes - The blockinfo block contains metadata about user-defined
+ /// blocks.
+ enum BlockInfoCodes {
+ // DEFINE_ABBREV has magic semantics here, applying to the current SETBID'd
+ // block, instead of the BlockInfo block.
+
+ BLOCKINFO_CODE_SETBID = 1, // SETBID: [blockid#]
+ BLOCKINFO_CODE_BLOCKNAME = 2, // BLOCKNAME: [name]
+ BLOCKINFO_CODE_SETRECORDNAME = 3 // BLOCKINFO_CODE_SETRECORDNAME:
+ // [id, name]
+ };
+
+} // End bitc namespace
+
+/// BitCodeAbbrevOp - This describes one or more operands in an abbreviation.
+/// This is actually a union of two different things:
+/// 1. It could be a literal integer value ("the operand is always 17").
+/// 2. It could be an encoding specification ("this operand encoded like so").
+///
+class BitCodeAbbrevOp {
+ uint64_t Val; // A literal value or data for an encoding.
+ bool IsLiteral : 1; // Indicate whether this is a literal value or not.
+ unsigned Enc : 3; // The encoding to use.
+public:
+ enum Encoding {
+ Fixed = 1, // A fixed width field, Val specifies number of bits.
+ VBR = 2, // A VBR field where Val specifies the width of each chunk.
+ Array = 3, // A sequence of fields, next field species elt encoding.
+ Char6 = 4, // A 6-bit fixed field which maps to [a-zA-Z0-9._].
+ Blob = 5 // 32-bit aligned array of 8-bit characters.
+ };
+
+ explicit BitCodeAbbrevOp(uint64_t V) : Val(V), IsLiteral(true) {}
+ explicit BitCodeAbbrevOp(Encoding E, uint64_t Data = 0)
+ : Val(Data), IsLiteral(false), Enc(E) {}
+
+ bool isLiteral() const { return IsLiteral; }
+ bool isEncoding() const { return !IsLiteral; }
+
+ // Accessors for literals.
+ uint64_t getLiteralValue() const { assert(isLiteral()); return Val; }
+
+ // Accessors for encoding info.
+ Encoding getEncoding() const { assert(isEncoding()); return (Encoding)Enc; }
+ uint64_t getEncodingData() const {
+ assert(isEncoding() && hasEncodingData());
+ return Val;
+ }
+
+ bool hasEncodingData() const { return hasEncodingData(getEncoding()); }
+ static bool hasEncodingData(Encoding E) {
+ switch (E) {
+ case Fixed:
+ case VBR:
+ return true;
+ case Array:
+ case Char6:
+ case Blob:
+ return false;
+ }
+ report_fatal_error("Invalid encoding");
+ }
+
+ /// isChar6 - Return true if this character is legal in the Char6 encoding.
+ static bool isChar6(char C) {
+ if (C >= 'a' && C <= 'z') return true;
+ if (C >= 'A' && C <= 'Z') return true;
+ if (C >= '0' && C <= '9') return true;
+ if (C == '.' || C == '_') return true;
+ return false;
+ }
+ static unsigned EncodeChar6(char C) {
+ if (C >= 'a' && C <= 'z') return C-'a';
+ if (C >= 'A' && C <= 'Z') return C-'A'+26;
+ if (C >= '0' && C <= '9') return C-'0'+26+26;
+ if (C == '.') return 62;
+ if (C == '_') return 63;
+ llvm_unreachable("Not a value Char6 character!");
+ }
+
+ static char DecodeChar6(unsigned V) {
+ assert((V & ~63) == 0 && "Not a Char6 encoded character!");
+ return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._"
+ [V];
+ }
+
+};
+
+/// BitCodeAbbrev - This class represents an abbreviation record. An
+/// abbreviation allows a complex record that has redundancy to be stored in a
+/// specialized format instead of the fully-general, fully-vbr, format.
+class BitCodeAbbrev {
+ SmallVector<BitCodeAbbrevOp, 32> OperandList;
+
+public:
+ unsigned getNumOperandInfos() const {
+ return static_cast<unsigned>(OperandList.size());
+ }
+ const BitCodeAbbrevOp &getOperandInfo(unsigned N) const {
+ return OperandList[N];
+ }
+
+ void Add(const BitCodeAbbrevOp &OpInfo) {
+ OperandList.push_back(OpInfo);
+ }
+};
+} // End llvm namespace
+
+#endif
Added: llvm/trunk/include/llvm/Bitstream/BitstreamReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitstream/BitstreamReader.h?rev=365091&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Bitstream/BitstreamReader.h (added)
+++ llvm/trunk/include/llvm/Bitstream/BitstreamReader.h Wed Jul 3 15:40:07 2019
@@ -0,0 +1,553 @@
+//===- BitstreamReader.h - Low-level bitstream reader interface -*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines the BitstreamReader class. This class can be used to
+// read an arbitrary bitstream, regardless of its contents.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_BITSTREAM_BITSTREAMREADER_H
+#define LLVM_BITSTREAM_BITSTREAMREADER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Bitstream/BitCodes.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <algorithm>
+#include <cassert>
+#include <climits>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+/// This class maintains the abbreviations read from a block info block.
+class BitstreamBlockInfo {
+public:
+ /// This contains information emitted to BLOCKINFO_BLOCK blocks. These
+ /// describe abbreviations that all blocks of the specified ID inherit.
+ struct BlockInfo {
+ unsigned BlockID;
+ std::vector<std::shared_ptr<BitCodeAbbrev>> Abbrevs;
+ std::string Name;
+ std::vector<std::pair<unsigned, std::string>> RecordNames;
+ };
+
+private:
+ std::vector<BlockInfo> BlockInfoRecords;
+
+public:
+ /// If there is block info for the specified ID, return it, otherwise return
+ /// null.
+ const BlockInfo *getBlockInfo(unsigned BlockID) const {
+ // Common case, the most recent entry matches BlockID.
+ if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID)
+ return &BlockInfoRecords.back();
+
+ for (unsigned i = 0, e = static_cast<unsigned>(BlockInfoRecords.size());
+ i != e; ++i)
+ if (BlockInfoRecords[i].BlockID == BlockID)
+ return &BlockInfoRecords[i];
+ return nullptr;
+ }
+
+ BlockInfo &getOrCreateBlockInfo(unsigned BlockID) {
+ if (const BlockInfo *BI = getBlockInfo(BlockID))
+ return *const_cast<BlockInfo*>(BI);
+
+ // Otherwise, add a new record.
+ BlockInfoRecords.emplace_back();
+ BlockInfoRecords.back().BlockID = BlockID;
+ return BlockInfoRecords.back();
+ }
+};
+
+/// This represents a position within a bitstream. There may be multiple
+/// independent cursors reading within one bitstream, each maintaining their
+/// own local state.
+class SimpleBitstreamCursor {
+ ArrayRef<uint8_t> BitcodeBytes;
+ size_t NextChar = 0;
+
+public:
+ /// 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.
+ using word_t = size_t;
+
+private:
+ word_t CurWord = 0;
+
+ /// This is the number of bits in CurWord that are valid. This is always from
+ /// [0...bits_of(size_t)-1] inclusive.
+ unsigned BitsInCurWord = 0;
+
+public:
+ static const constexpr size_t MaxChunkSize = sizeof(word_t) * 8;
+
+ SimpleBitstreamCursor() = default;
+ explicit SimpleBitstreamCursor(ArrayRef<uint8_t> BitcodeBytes)
+ : BitcodeBytes(BitcodeBytes) {}
+ explicit SimpleBitstreamCursor(StringRef BitcodeBytes)
+ : BitcodeBytes(arrayRefFromStringRef(BitcodeBytes)) {}
+ explicit SimpleBitstreamCursor(MemoryBufferRef BitcodeBytes)
+ : SimpleBitstreamCursor(BitcodeBytes.getBuffer()) {}
+
+ bool canSkipToPos(size_t pos) const {
+ // pos can be skipped to if it is a valid address or one byte past the end.
+ return pos <= BitcodeBytes.size();
+ }
+
+ bool AtEndOfStream() {
+ return BitsInCurWord == 0 && BitcodeBytes.size() <= NextChar;
+ }
+
+ /// Return the bit # of the bit we are reading.
+ uint64_t GetCurrentBitNo() const {
+ return NextChar*CHAR_BIT - BitsInCurWord;
+ }
+
+ // Return the byte # of the current bit.
+ uint64_t getCurrentByteNo() const { return GetCurrentBitNo() / 8; }
+
+ ArrayRef<uint8_t> getBitcodeBytes() const { return BitcodeBytes; }
+
+ /// Reset the stream to the specified bit number.
+ Error JumpToBit(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");
+
+ // Move the cursor to the right word.
+ NextChar = ByteNo;
+ BitsInCurWord = 0;
+
+ // Skip over any bits that are already consumed.
+ if (WordBitNo) {
+ if (Expected<word_t> Res = Read(WordBitNo))
+ return Error::success();
+ else
+ return Res.takeError();
+ }
+
+ return Error::success();
+ }
+
+ /// Get a pointer into the bitstream at the specified byte offset.
+ const uint8_t *getPointerToByte(uint64_t ByteNo, uint64_t NumBytes) {
+ return BitcodeBytes.data() + ByteNo;
+ }
+
+ /// Get a pointer into the bitstream at the specified bit offset.
+ ///
+ /// The bit offset must be on a byte boundary.
+ const uint8_t *getPointerToBit(uint64_t BitNo, uint64_t NumBytes) {
+ assert(!(BitNo % 8) && "Expected bit on byte boundary");
+ 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());
+
+ // Read the next word from the stream.
+ const uint8_t *NextCharPtr = BitcodeBytes.data() + NextChar;
+ unsigned BytesRead;
+ if (BitcodeBytes.size() >= NextChar + sizeof(word_t)) {
+ BytesRead = sizeof(word_t);
+ CurWord =
+ support::endian::read<word_t, support::little, support::unaligned>(
+ NextCharPtr);
+ } else {
+ // Short read.
+ BytesRead = BitcodeBytes.size() - NextChar;
+ CurWord = 0;
+ for (unsigned B = 0; B != BytesRead; ++B)
+ CurWord |= uint64_t(NextCharPtr[B]) << (B * 8);
+ }
+ NextChar += BytesRead;
+ BitsInCurWord = BytesRead * 8;
+ return Error::success();
+ }
+
+ Expected<word_t> Read(unsigned NumBits) {
+ static const unsigned BitsInWord = MaxChunkSize;
+
+ assert(NumBits && NumBits <= BitsInWord &&
+ "Cannot return zero or more than BitsInWord bits!");
+
+ static const unsigned Mask = sizeof(word_t) > 4 ? 0x3f : 0x1f;
+
+ // If the field is fully contained by CurWord, return it quickly.
+ if (BitsInCurWord >= NumBits) {
+ word_t R = CurWord & (~word_t(0) >> (BitsInWord - NumBits));
+
+ // Use a mask to avoid undefined behavior.
+ CurWord >>= (NumBits & Mask);
+
+ BitsInCurWord -= NumBits;
+ return R;
+ }
+
+ 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);
+
+ word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft));
+
+ // Use a mask to avoid undefined behavior.
+ CurWord >>= (BitsLeft & Mask);
+
+ BitsInCurWord -= BitsLeft;
+
+ R |= R2 << (NumBits - BitsLeft);
+
+ return R;
+ }
+
+ Expected<uint32_t> ReadVBR(unsigned NumBits) {
+ Expected<unsigned> MaybeRead = Read(NumBits);
+ if (!MaybeRead)
+ return MaybeRead;
+ uint32_t Piece = MaybeRead.get();
+
+ if ((Piece & (1U << (NumBits-1))) == 0)
+ return Piece;
+
+ uint32_t Result = 0;
+ unsigned NextBit = 0;
+ while (true) {
+ Result |= (Piece & ((1U << (NumBits-1))-1)) << NextBit;
+
+ if ((Piece & (1U << (NumBits-1))) == 0)
+ return Result;
+
+ NextBit += NumBits-1;
+ MaybeRead = Read(NumBits);
+ if (!MaybeRead)
+ return MaybeRead;
+ Piece = MaybeRead.get();
+ }
+ }
+
+ // 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<uint64_t> ReadVBR64(unsigned NumBits) {
+ Expected<uint64_t> MaybeRead = Read(NumBits);
+ if (!MaybeRead)
+ return MaybeRead;
+ uint32_t Piece = MaybeRead.get();
+
+ if ((Piece & (1U << (NumBits-1))) == 0)
+ return uint64_t(Piece);
+
+ uint64_t Result = 0;
+ unsigned NextBit = 0;
+ while (true) {
+ Result |= uint64_t(Piece & ((1U << (NumBits-1))-1)) << NextBit;
+
+ if ((Piece & (1U << (NumBits-1))) == 0)
+ return Result;
+
+ NextBit += NumBits-1;
+ MaybeRead = Read(NumBits);
+ if (!MaybeRead)
+ return MaybeRead;
+ Piece = MaybeRead.get();
+ }
+ }
+
+ 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;
+ }
+
+ /// Skip to the end of the file.
+ void skipToEnd() { NextChar = BitcodeBytes.size(); }
+};
+
+/// When advancing through a bitstream cursor, each advance can discover a few
+/// different kinds of entries:
+struct BitstreamEntry {
+ enum {
+ 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.
+ } 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;
+ }
+};
+
+/// This represents a position within a bitcode file, implemented on top of a
+/// SimpleBitstreamCursor.
+///
+/// Unlike iterators, BitstreamCursors are heavy-weight objects that should not
+/// be passed by value.
+class BitstreamCursor : SimpleBitstreamCursor {
+ // This is the declared size of code values used for the current block, in
+ // bits.
+ unsigned CurCodeSize = 2;
+
+ /// Abbrevs installed at in this block.
+ std::vector<std::shared_ptr<BitCodeAbbrev>> CurAbbrevs;
+
+ struct Block {
+ unsigned PrevCodeSize;
+ std::vector<std::shared_ptr<BitCodeAbbrev>> PrevAbbrevs;
+
+ explicit Block(unsigned PCS) : PrevCodeSize(PCS) {}
+ };
+
+ /// This tracks the codesize of parent blocks.
+ SmallVector<Block, 8> BlockScope;
+
+ BitstreamBlockInfo *BlockInfo = nullptr;
+
+public:
+ static const size_t MaxChunkSize = sizeof(word_t) * 8;
+
+ BitstreamCursor() = default;
+ explicit BitstreamCursor(ArrayRef<uint8_t> BitcodeBytes)
+ : SimpleBitstreamCursor(BitcodeBytes) {}
+ explicit BitstreamCursor(StringRef BitcodeBytes)
+ : SimpleBitstreamCursor(BitcodeBytes) {}
+ explicit BitstreamCursor(MemoryBufferRef BitcodeBytes)
+ : SimpleBitstreamCursor(BitcodeBytes) {}
+
+ using SimpleBitstreamCursor::canSkipToPos;
+ using SimpleBitstreamCursor::AtEndOfStream;
+ using SimpleBitstreamCursor::getBitcodeBytes;
+ using SimpleBitstreamCursor::GetCurrentBitNo;
+ using SimpleBitstreamCursor::getCurrentByteNo;
+ using SimpleBitstreamCursor::getPointerToByte;
+ using SimpleBitstreamCursor::JumpToBit;
+ using SimpleBitstreamCursor::fillCurWord;
+ using SimpleBitstreamCursor::Read;
+ using SimpleBitstreamCursor::ReadVBR;
+ using SimpleBitstreamCursor::ReadVBR64;
+
+ /// Return the number of bits used to encode an abbrev #.
+ unsigned getAbbrevIDWidth() const { return CurCodeSize; }
+
+ /// Flags that modify the behavior of advance().
+ enum {
+ /// 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,
+
+ /// If this flag is used, abbrev entries are returned just like normal
+ /// records.
+ AF_DontAutoprocessAbbrevs = 2
+ };
+
+ /// Advance the current bitstream, returning the next entry in the stream.
+ Expected<BitstreamEntry> advance(unsigned Flags = 0) {
+ while (true) {
+ if (AtEndOfStream())
+ return BitstreamEntry::getError();
+
+ Expected<unsigned> MaybeCode = ReadCode();
+ if (!MaybeCode)
+ return MaybeCode.takeError();
+ unsigned Code = MaybeCode.get();
+
+ if (Code == bitc::END_BLOCK) {
+ // Pop the end of the block unless Flags tells us not to.
+ if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd())
+ return BitstreamEntry::getError();
+ return BitstreamEntry::getEndBlock();
+ }
+
+ if (Code == bitc::ENTER_SUBBLOCK) {
+ if (Expected<unsigned> MaybeSubBlock = ReadSubBlockID())
+ return BitstreamEntry::getSubBlock(MaybeSubBlock.get());
+ else
+ return MaybeSubBlock.takeError();
+ }
+
+ if (Code == bitc::DEFINE_ABBREV &&
+ !(Flags & AF_DontAutoprocessAbbrevs)) {
+ // We read and accumulate abbrev's, the client can't do anything with
+ // them anyway.
+ if (Error Err = ReadAbbrevRecord())
+ return std::move(Err);
+ continue;
+ }
+
+ return BitstreamEntry::getRecord(Code);
+ }
+ }
+
+ /// This is a convenience function for clients that don't expect any
+ /// subblocks. This just skips over them automatically.
+ Expected<BitstreamEntry> advanceSkippingSubblocks(unsigned Flags = 0) {
+ while (true) {
+ // If we found a normal entry, return it.
+ Expected<BitstreamEntry> MaybeEntry = advance(Flags);
+ if (!MaybeEntry)
+ return MaybeEntry;
+ BitstreamEntry Entry = MaybeEntry.get();
+
+ if (Entry.Kind != BitstreamEntry::SubBlock)
+ return Entry;
+
+ // If we found a sub-block, just skip over it and check the next entry.
+ if (Error Err = SkipBlock())
+ return std::move(Err);
+ }
+ }
+
+ Expected<unsigned> ReadCode() { return Read(CurCodeSize); }
+
+ // Block header:
+ // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
+
+ /// Having read the ENTER_SUBBLOCK code, read the BlockID for the block.
+ Expected<unsigned> ReadSubBlockID() { return ReadVBR(bitc::BlockIDWidth); }
+
+ /// Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body
+ /// of this block.
+ Error SkipBlock() {
+ // Read and ignore the codelen value.
+ if (Expected<uint32_t> 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();
+
+ SkipToFourByteBoundary();
+ Expected<unsigned> MaybeNum = Read(bitc::BlockSizeWidth);
+ if (!MaybeNum)
+ return MaybeNum.takeError();
+ size_t NumFourBytes = MaybeNum.get();
+
+ // 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");
+ if (!canSkipToPos(SkipTo / 8))
+ return createStringError(std::errc::illegal_byte_sequence,
+ "can't skip to bit %zu from %" PRIu64, SkipTo,
+ GetCurrentBitNo());
+
+ if (Error Res = JumpToBit(SkipTo))
+ return Res;
+
+ return Error::success();
+ }
+
+ /// Having read the ENTER_SUBBLOCK abbrevid, and enter the block.
+ Error EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr);
+
+ bool ReadBlockEnd() {
+ if (BlockScope.empty()) return true;
+
+ // Block tail:
+ // [END_BLOCK, <align4bytes>]
+ SkipToFourByteBoundary();
+
+ popBlockScope();
+ return false;
+ }
+
+private:
+ void popBlockScope() {
+ CurCodeSize = BlockScope.back().PrevCodeSize;
+
+ CurAbbrevs = std::move(BlockScope.back().PrevAbbrevs);
+ BlockScope.pop_back();
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Record Processing
+ //===--------------------------------------------------------------------===//
+
+public:
+ /// Return the abbreviation for the specified AbbrevId.
+ const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) {
+ unsigned AbbrevNo = AbbrevID - bitc::FIRST_APPLICATION_ABBREV;
+ if (AbbrevNo >= CurAbbrevs.size())
+ report_fatal_error("Invalid abbrev number");
+ return CurAbbrevs[AbbrevNo].get();
+ }
+
+ /// Read the current record and discard it, returning the code for the record.
+ Expected<unsigned> skipRecord(unsigned AbbrevID);
+
+ Expected<unsigned> readRecord(unsigned AbbrevID,
+ SmallVectorImpl<uint64_t> &Vals,
+ StringRef *Blob = nullptr);
+
+ //===--------------------------------------------------------------------===//
+ // Abbrev Processing
+ //===--------------------------------------------------------------------===//
+ Error ReadAbbrevRecord();
+
+ /// Read and return a block info block from the bitstream. If an error was
+ /// encountered, return None.
+ ///
+ /// \param ReadBlockInfoNames Whether to read block/record name information in
+ /// the BlockInfo block. Only llvm-bcanalyzer uses this.
+ Expected<Optional<BitstreamBlockInfo>>
+ ReadBlockInfoBlock(bool ReadBlockInfoNames = false);
+
+ /// Set the block info to be used by this BitstreamCursor to interpret
+ /// abbreviated records.
+ void setBlockInfo(BitstreamBlockInfo *BI) { BlockInfo = BI; }
+};
+
+} // end llvm namespace
+
+#endif // LLVM_BITSTREAM_BITSTREAMREADER_H
Added: llvm/trunk/include/llvm/Bitstream/BitstreamWriter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitstream/BitstreamWriter.h?rev=365091&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Bitstream/BitstreamWriter.h (added)
+++ llvm/trunk/include/llvm/Bitstream/BitstreamWriter.h Wed Jul 3 15:40:07 2019
@@ -0,0 +1,547 @@
+//===- BitstreamWriter.h - Low-level bitstream writer interface -*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines the BitstreamWriter class. This class can be used to
+// write an arbitrary bitstream, regardless of its contents.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_BITSTREAM_BITSTREAMWRITER_H
+#define LLVM_BITSTREAM_BITSTREAMWRITER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Bitstream/BitCodes.h"
+#include "llvm/Support/Endian.h"
+#include <vector>
+
+namespace llvm {
+
+class BitstreamWriter {
+ SmallVectorImpl<char> &Out;
+
+ /// CurBit - Always between 0 and 31 inclusive, specifies the next bit to use.
+ unsigned CurBit;
+
+ /// CurValue - The current value. Only bits < CurBit are valid.
+ uint32_t CurValue;
+
+ /// CurCodeSize - This is the declared size of code values used for the
+ /// current block, in bits.
+ unsigned CurCodeSize;
+
+ /// BlockInfoCurBID - When emitting a BLOCKINFO_BLOCK, this is the currently
+ /// selected BLOCK ID.
+ unsigned BlockInfoCurBID;
+
+ /// CurAbbrevs - Abbrevs installed at in this block.
+ std::vector<std::shared_ptr<BitCodeAbbrev>> CurAbbrevs;
+
+ struct Block {
+ unsigned PrevCodeSize;
+ size_t StartSizeWord;
+ std::vector<std::shared_ptr<BitCodeAbbrev>> PrevAbbrevs;
+ Block(unsigned PCS, size_t SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {}
+ };
+
+ /// BlockScope - This tracks the current blocks that we have entered.
+ std::vector<Block> BlockScope;
+
+ /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks.
+ /// These describe abbreviations that all blocks of the specified ID inherit.
+ struct BlockInfo {
+ unsigned BlockID;
+ std::vector<std::shared_ptr<BitCodeAbbrev>> Abbrevs;
+ };
+ std::vector<BlockInfo> BlockInfoRecords;
+
+ void WriteByte(unsigned char Value) {
+ Out.push_back(Value);
+ }
+
+ void WriteWord(unsigned Value) {
+ Value = support::endian::byte_swap<uint32_t, support::little>(Value);
+ Out.append(reinterpret_cast<const char *>(&Value),
+ reinterpret_cast<const char *>(&Value + 1));
+ }
+
+ size_t GetBufferOffset() const { return Out.size(); }
+
+ size_t GetWordIndex() const {
+ size_t Offset = GetBufferOffset();
+ assert((Offset & 3) == 0 && "Not 32-bit aligned");
+ return Offset / 4;
+ }
+
+public:
+ explicit BitstreamWriter(SmallVectorImpl<char> &O)
+ : Out(O), CurBit(0), CurValue(0), CurCodeSize(2) {}
+
+ ~BitstreamWriter() {
+ assert(CurBit == 0 && "Unflushed data remaining");
+ assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance");
+ }
+
+ /// Retrieve the current position in the stream, in bits.
+ uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 + CurBit; }
+
+ /// Retrieve the number of bits currently used to encode an abbrev ID.
+ unsigned GetAbbrevIDWidth() const { return CurCodeSize; }
+
+ //===--------------------------------------------------------------------===//
+ // Basic Primitives for emitting bits to the stream.
+ //===--------------------------------------------------------------------===//
+
+ /// Backpatch a 32-bit word in the output at the given bit offset
+ /// with the specified value.
+ void BackpatchWord(uint64_t BitNo, unsigned NewWord) {
+ using namespace llvm::support;
+ unsigned ByteNo = BitNo / 8;
+ assert((!endian::readAtBitAlignment<uint32_t, little, unaligned>(
+ &Out[ByteNo], BitNo & 7)) &&
+ "Expected to be patching over 0-value placeholders");
+ endian::writeAtBitAlignment<uint32_t, little, unaligned>(
+ &Out[ByteNo], NewWord, BitNo & 7);
+ }
+
+ void BackpatchWord64(uint64_t BitNo, uint64_t Val) {
+ BackpatchWord(BitNo, (uint32_t)Val);
+ BackpatchWord(BitNo + 32, (uint32_t)(Val >> 32));
+ }
+
+ void Emit(uint32_t Val, unsigned NumBits) {
+ assert(NumBits && NumBits <= 32 && "Invalid value size!");
+ assert((Val & ~(~0U >> (32-NumBits))) == 0 && "High bits set!");
+ CurValue |= Val << CurBit;
+ if (CurBit + NumBits < 32) {
+ CurBit += NumBits;
+ return;
+ }
+
+ // Add the current word.
+ WriteWord(CurValue);
+
+ if (CurBit)
+ CurValue = Val >> (32-CurBit);
+ else
+ CurValue = 0;
+ CurBit = (CurBit+NumBits) & 31;
+ }
+
+ void FlushToWord() {
+ if (CurBit) {
+ WriteWord(CurValue);
+ CurBit = 0;
+ CurValue = 0;
+ }
+ }
+
+ void EmitVBR(uint32_t Val, unsigned NumBits) {
+ assert(NumBits <= 32 && "Too many bits to emit!");
+ uint32_t Threshold = 1U << (NumBits-1);
+
+ // Emit the bits with VBR encoding, NumBits-1 bits at a time.
+ while (Val >= Threshold) {
+ Emit((Val & ((1 << (NumBits-1))-1)) | (1 << (NumBits-1)), NumBits);
+ Val >>= NumBits-1;
+ }
+
+ Emit(Val, NumBits);
+ }
+
+ void EmitVBR64(uint64_t Val, unsigned NumBits) {
+ assert(NumBits <= 32 && "Too many bits to emit!");
+ if ((uint32_t)Val == Val)
+ return EmitVBR((uint32_t)Val, NumBits);
+
+ uint32_t Threshold = 1U << (NumBits-1);
+
+ // Emit the bits with VBR encoding, NumBits-1 bits at a time.
+ while (Val >= Threshold) {
+ Emit(((uint32_t)Val & ((1 << (NumBits-1))-1)) |
+ (1 << (NumBits-1)), NumBits);
+ Val >>= NumBits-1;
+ }
+
+ Emit((uint32_t)Val, NumBits);
+ }
+
+ /// EmitCode - Emit the specified code.
+ void EmitCode(unsigned Val) {
+ Emit(Val, CurCodeSize);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Block Manipulation
+ //===--------------------------------------------------------------------===//
+
+ /// getBlockInfo - If there is block info for the specified ID, return it,
+ /// otherwise return null.
+ BlockInfo *getBlockInfo(unsigned BlockID) {
+ // Common case, the most recent entry matches BlockID.
+ if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID)
+ return &BlockInfoRecords.back();
+
+ for (unsigned i = 0, e = static_cast<unsigned>(BlockInfoRecords.size());
+ i != e; ++i)
+ if (BlockInfoRecords[i].BlockID == BlockID)
+ return &BlockInfoRecords[i];
+ return nullptr;
+ }
+
+ void EnterSubblock(unsigned BlockID, unsigned CodeLen) {
+ // Block header:
+ // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
+ EmitCode(bitc::ENTER_SUBBLOCK);
+ EmitVBR(BlockID, bitc::BlockIDWidth);
+ EmitVBR(CodeLen, bitc::CodeLenWidth);
+ FlushToWord();
+
+ size_t BlockSizeWordIndex = GetWordIndex();
+ unsigned OldCodeSize = CurCodeSize;
+
+ // Emit a placeholder, which will be replaced when the block is popped.
+ Emit(0, bitc::BlockSizeWidth);
+
+ CurCodeSize = CodeLen;
+
+ // Push the outer block's abbrev set onto the stack, start out with an
+ // empty abbrev set.
+ BlockScope.emplace_back(OldCodeSize, BlockSizeWordIndex);
+ BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
+
+ // If there is a blockinfo for this BlockID, add all the predefined abbrevs
+ // to the abbrev list.
+ if (BlockInfo *Info = getBlockInfo(BlockID)) {
+ CurAbbrevs.insert(CurAbbrevs.end(), Info->Abbrevs.begin(),
+ Info->Abbrevs.end());
+ }
+ }
+
+ void ExitBlock() {
+ assert(!BlockScope.empty() && "Block scope imbalance!");
+ const Block &B = BlockScope.back();
+
+ // Block tail:
+ // [END_BLOCK, <align4bytes>]
+ EmitCode(bitc::END_BLOCK);
+ FlushToWord();
+
+ // Compute the size of the block, in words, not counting the size field.
+ size_t SizeInWords = GetWordIndex() - B.StartSizeWord - 1;
+ uint64_t BitNo = uint64_t(B.StartSizeWord) * 32;
+
+ // Update the block size field in the header of this sub-block.
+ BackpatchWord(BitNo, SizeInWords);
+
+ // Restore the inner block's code size and abbrev table.
+ CurCodeSize = B.PrevCodeSize;
+ CurAbbrevs = std::move(B.PrevAbbrevs);
+ BlockScope.pop_back();
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Record Emission
+ //===--------------------------------------------------------------------===//
+
+private:
+ /// EmitAbbreviatedLiteral - Emit a literal value according to its abbrev
+ /// record. This is a no-op, since the abbrev specifies the literal to use.
+ template<typename uintty>
+ void EmitAbbreviatedLiteral(const BitCodeAbbrevOp &Op, uintty V) {
+ assert(Op.isLiteral() && "Not a literal");
+ // If the abbrev specifies the literal value to use, don't emit
+ // anything.
+ assert(V == Op.getLiteralValue() &&
+ "Invalid abbrev for record!");
+ }
+
+ /// EmitAbbreviatedField - Emit a single scalar field value with the specified
+ /// encoding.
+ template<typename uintty>
+ void EmitAbbreviatedField(const BitCodeAbbrevOp &Op, uintty V) {
+ assert(!Op.isLiteral() && "Literals should use EmitAbbreviatedLiteral!");
+
+ // Encode the value as we are commanded.
+ switch (Op.getEncoding()) {
+ default: llvm_unreachable("Unknown encoding!");
+ case BitCodeAbbrevOp::Fixed:
+ if (Op.getEncodingData())
+ Emit((unsigned)V, (unsigned)Op.getEncodingData());
+ break;
+ case BitCodeAbbrevOp::VBR:
+ if (Op.getEncodingData())
+ EmitVBR64(V, (unsigned)Op.getEncodingData());
+ break;
+ case BitCodeAbbrevOp::Char6:
+ Emit(BitCodeAbbrevOp::EncodeChar6((char)V), 6);
+ break;
+ }
+ }
+
+ /// EmitRecordWithAbbrevImpl - This is the core implementation of the record
+ /// emission code. If BlobData is non-null, then it specifies an array of
+ /// data that should be emitted as part of the Blob or Array operand that is
+ /// known to exist at the end of the record. If Code is specified, then
+ /// it is the record code to emit before the Vals, which must not contain
+ /// the code.
+ template <typename uintty>
+ void EmitRecordWithAbbrevImpl(unsigned Abbrev, ArrayRef<uintty> Vals,
+ StringRef Blob, Optional<unsigned> Code) {
+ const char *BlobData = Blob.data();
+ unsigned BlobLen = (unsigned) Blob.size();
+ unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV;
+ assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!");
+ const BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo].get();
+
+ EmitCode(Abbrev);
+
+ unsigned i = 0, e = static_cast<unsigned>(Abbv->getNumOperandInfos());
+ if (Code) {
+ assert(e && "Expected non-empty abbreviation");
+ const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i++);
+
+ if (Op.isLiteral())
+ EmitAbbreviatedLiteral(Op, Code.getValue());
+ else {
+ assert(Op.getEncoding() != BitCodeAbbrevOp::Array &&
+ Op.getEncoding() != BitCodeAbbrevOp::Blob &&
+ "Expected literal or scalar");
+ EmitAbbreviatedField(Op, Code.getValue());
+ }
+ }
+
+ unsigned RecordIdx = 0;
+ for (; i != e; ++i) {
+ const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
+ if (Op.isLiteral()) {
+ assert(RecordIdx < Vals.size() && "Invalid abbrev/record");
+ EmitAbbreviatedLiteral(Op, Vals[RecordIdx]);
+ ++RecordIdx;
+ } else if (Op.getEncoding() == BitCodeAbbrevOp::Array) {
+ // Array case.
+ assert(i + 2 == e && "array op not second to last?");
+ const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i);
+
+ // If this record has blob data, emit it, otherwise we must have record
+ // entries to encode this way.
+ if (BlobData) {
+ assert(RecordIdx == Vals.size() &&
+ "Blob data and record entries specified for array!");
+ // Emit a vbr6 to indicate the number of elements present.
+ EmitVBR(static_cast<uint32_t>(BlobLen), 6);
+
+ // Emit each field.
+ for (unsigned i = 0; i != BlobLen; ++i)
+ EmitAbbreviatedField(EltEnc, (unsigned char)BlobData[i]);
+
+ // Know that blob data is consumed for assertion below.
+ BlobData = nullptr;
+ } else {
+ // Emit a vbr6 to indicate the number of elements present.
+ EmitVBR(static_cast<uint32_t>(Vals.size()-RecordIdx), 6);
+
+ // Emit each field.
+ for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx)
+ EmitAbbreviatedField(EltEnc, Vals[RecordIdx]);
+ }
+ } else if (Op.getEncoding() == BitCodeAbbrevOp::Blob) {
+ // If this record has blob data, emit it, otherwise we must have record
+ // entries to encode this way.
+
+ if (BlobData) {
+ assert(RecordIdx == Vals.size() &&
+ "Blob data and record entries specified for blob operand!");
+
+ assert(Blob.data() == BlobData && "BlobData got moved");
+ assert(Blob.size() == BlobLen && "BlobLen got changed");
+ emitBlob(Blob);
+ BlobData = nullptr;
+ } else {
+ emitBlob(Vals.slice(RecordIdx));
+ }
+ } else { // Single scalar field.
+ assert(RecordIdx < Vals.size() && "Invalid abbrev/record");
+ EmitAbbreviatedField(Op, Vals[RecordIdx]);
+ ++RecordIdx;
+ }
+ }
+ assert(RecordIdx == Vals.size() && "Not all record operands emitted!");
+ assert(BlobData == nullptr &&
+ "Blob data specified for record that doesn't use it!");
+ }
+
+public:
+ /// Emit a blob, including flushing before and tail-padding.
+ template <class UIntTy>
+ void emitBlob(ArrayRef<UIntTy> Bytes, bool ShouldEmitSize = true) {
+ // Emit a vbr6 to indicate the number of elements present.
+ if (ShouldEmitSize)
+ EmitVBR(static_cast<uint32_t>(Bytes.size()), 6);
+
+ // Flush to a 32-bit alignment boundary.
+ FlushToWord();
+
+ // Emit literal bytes.
+ for (const auto &B : Bytes) {
+ assert(isUInt<8>(B) && "Value too large to emit as byte");
+ WriteByte((unsigned char)B);
+ }
+
+ // Align end to 32-bits.
+ while (GetBufferOffset() & 3)
+ WriteByte(0);
+ }
+ void emitBlob(StringRef Bytes, bool ShouldEmitSize = true) {
+ emitBlob(makeArrayRef((const uint8_t *)Bytes.data(), Bytes.size()),
+ ShouldEmitSize);
+ }
+
+ /// EmitRecord - Emit the specified record to the stream, using an abbrev if
+ /// we have one to compress the output.
+ template <typename Container>
+ void EmitRecord(unsigned Code, const Container &Vals, unsigned Abbrev = 0) {
+ if (!Abbrev) {
+ // If we don't have an abbrev to use, emit this in its fully unabbreviated
+ // form.
+ auto Count = static_cast<uint32_t>(makeArrayRef(Vals).size());
+ EmitCode(bitc::UNABBREV_RECORD);
+ EmitVBR(Code, 6);
+ EmitVBR(Count, 6);
+ for (unsigned i = 0, e = Count; i != e; ++i)
+ EmitVBR64(Vals[i], 6);
+ return;
+ }
+
+ EmitRecordWithAbbrevImpl(Abbrev, makeArrayRef(Vals), StringRef(), Code);
+ }
+
+ /// EmitRecordWithAbbrev - Emit a record with the specified abbreviation.
+ /// Unlike EmitRecord, the code for the record should be included in Vals as
+ /// the first entry.
+ template <typename Container>
+ void EmitRecordWithAbbrev(unsigned Abbrev, const Container &Vals) {
+ EmitRecordWithAbbrevImpl(Abbrev, makeArrayRef(Vals), StringRef(), None);
+ }
+
+ /// EmitRecordWithBlob - Emit the specified record to the stream, using an
+ /// abbrev that includes a blob at the end. The blob data to emit is
+ /// specified by the pointer and length specified at the end. In contrast to
+ /// EmitRecord, this routine expects that the first entry in Vals is the code
+ /// of the record.
+ template <typename Container>
+ void EmitRecordWithBlob(unsigned Abbrev, const Container &Vals,
+ StringRef Blob) {
+ EmitRecordWithAbbrevImpl(Abbrev, makeArrayRef(Vals), Blob, None);
+ }
+ template <typename Container>
+ void EmitRecordWithBlob(unsigned Abbrev, const Container &Vals,
+ const char *BlobData, unsigned BlobLen) {
+ return EmitRecordWithAbbrevImpl(Abbrev, makeArrayRef(Vals),
+ StringRef(BlobData, BlobLen), None);
+ }
+
+ /// EmitRecordWithArray - Just like EmitRecordWithBlob, works with records
+ /// that end with an array.
+ template <typename Container>
+ void EmitRecordWithArray(unsigned Abbrev, const Container &Vals,
+ StringRef Array) {
+ EmitRecordWithAbbrevImpl(Abbrev, makeArrayRef(Vals), Array, None);
+ }
+ template <typename Container>
+ void EmitRecordWithArray(unsigned Abbrev, const Container &Vals,
+ const char *ArrayData, unsigned ArrayLen) {
+ return EmitRecordWithAbbrevImpl(Abbrev, makeArrayRef(Vals),
+ StringRef(ArrayData, ArrayLen), None);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Abbrev Emission
+ //===--------------------------------------------------------------------===//
+
+private:
+ // Emit the abbreviation as a DEFINE_ABBREV record.
+ void EncodeAbbrev(const BitCodeAbbrev &Abbv) {
+ EmitCode(bitc::DEFINE_ABBREV);
+ EmitVBR(Abbv.getNumOperandInfos(), 5);
+ for (unsigned i = 0, e = static_cast<unsigned>(Abbv.getNumOperandInfos());
+ i != e; ++i) {
+ const BitCodeAbbrevOp &Op = Abbv.getOperandInfo(i);
+ Emit(Op.isLiteral(), 1);
+ if (Op.isLiteral()) {
+ EmitVBR64(Op.getLiteralValue(), 8);
+ } else {
+ Emit(Op.getEncoding(), 3);
+ if (Op.hasEncodingData())
+ EmitVBR64(Op.getEncodingData(), 5);
+ }
+ }
+ }
+public:
+
+ /// Emits the abbreviation \p Abbv to the stream.
+ unsigned EmitAbbrev(std::shared_ptr<BitCodeAbbrev> Abbv) {
+ EncodeAbbrev(*Abbv);
+ CurAbbrevs.push_back(std::move(Abbv));
+ return static_cast<unsigned>(CurAbbrevs.size())-1 +
+ bitc::FIRST_APPLICATION_ABBREV;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // BlockInfo Block Emission
+ //===--------------------------------------------------------------------===//
+
+ /// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK.
+ void EnterBlockInfoBlock() {
+ EnterSubblock(bitc::BLOCKINFO_BLOCK_ID, 2);
+ BlockInfoCurBID = ~0U;
+ BlockInfoRecords.clear();
+ }
+private:
+ /// SwitchToBlockID - If we aren't already talking about the specified block
+ /// ID, emit a BLOCKINFO_CODE_SETBID record.
+ void SwitchToBlockID(unsigned BlockID) {
+ if (BlockInfoCurBID == BlockID) return;
+ SmallVector<unsigned, 2> V;
+ V.push_back(BlockID);
+ EmitRecord(bitc::BLOCKINFO_CODE_SETBID, V);
+ BlockInfoCurBID = BlockID;
+ }
+
+ BlockInfo &getOrCreateBlockInfo(unsigned BlockID) {
+ if (BlockInfo *BI = getBlockInfo(BlockID))
+ return *BI;
+
+ // Otherwise, add a new record.
+ BlockInfoRecords.emplace_back();
+ BlockInfoRecords.back().BlockID = BlockID;
+ return BlockInfoRecords.back();
+ }
+
+public:
+
+ /// EmitBlockInfoAbbrev - Emit a DEFINE_ABBREV record for the specified
+ /// BlockID.
+ unsigned EmitBlockInfoAbbrev(unsigned BlockID, std::shared_ptr<BitCodeAbbrev> Abbv) {
+ SwitchToBlockID(BlockID);
+ EncodeAbbrev(*Abbv);
+
+ // Add the abbrev to the specified block record.
+ BlockInfo &Info = getOrCreateBlockInfo(BlockID);
+ Info.Abbrevs.push_back(std::move(Abbv));
+
+ return Info.Abbrevs.size()-1+bitc::FIRST_APPLICATION_ABBREV;
+ }
+};
+
+
+} // End llvm namespace
+
+#endif
Modified: llvm/trunk/include/llvm/Support/JSON.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/JSON.h?rev=365091&r1=365090&r2=365091&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/JSON.h (original)
+++ llvm/trunk/include/llvm/Support/JSON.h Wed Jul 3 15:40:07 2019
@@ -39,7 +39,7 @@
///
/// - LLVM bitstream is a space- and CPU- efficient binary format. Typically it
/// encodes LLVM IR ("bitcode"), but it can be a container for other data.
-/// Low-level reader/writer libraries are in Bitcode/Bitstream*.h
+/// Low-level reader/writer libraries are in Bitstream/Bitstream*.h
///
//===---------------------------------------------------------------------===//
Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=365091&r1=365090&r2=365091&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Wed Jul 3 15:40:07 2019
@@ -20,7 +20,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
-#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Bitstream/BitstreamReader.h"
#include "llvm/Bitcode/LLVMBitCodes.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/Argument.h"
Removed: llvm/trunk/lib/Bitcode/Reader/BitstreamReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitstreamReader.cpp?rev=365090&view=auto
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitstreamReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitstreamReader.cpp (removed)
@@ -1,510 +0,0 @@
-//===- 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/Bitcode/BitstreamReader.h"
-#include "llvm/ADT/StringRef.h"
-#include <cassert>
-#include <string>
-
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// BitstreamCursor implementation
-//===----------------------------------------------------------------------===//
-
-/// 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)) {
- CurAbbrevs.insert(CurAbbrevs.end(), Info->Abbrevs.begin(),
- Info->Abbrevs.end());
- }
- }
-
- // Get the codesize of this block.
- Expected<uint32_t> 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<word_t> 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<uint64_t> 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<unsigned> Res = Cursor.Read(6))
- return BitCodeAbbrevOp::DecodeChar6(Res.get());
- else
- return Res.takeError();
- }
- llvm_unreachable("invalid abbreviation encoding");
-}
-
-static Error skipAbbreviatedField(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);
- if (Expected<unsigned> Res = Cursor.Read((unsigned)Op.getEncodingData()))
- break;
- else
- return Res.takeError();
- case BitCodeAbbrevOp::VBR:
- assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize);
- if (Expected<uint64_t> Res =
- Cursor.ReadVBR64((unsigned)Op.getEncodingData()))
- break;
- else
- return Res.takeError();
- case BitCodeAbbrevOp::Char6:
- if (Expected<unsigned> Res = Cursor.Read(6))
- break;
- else
- return Res.takeError();
- }
- return ErrorSuccess();
-}
-
-/// skipRecord - Read the current record and discard it.
-Expected<unsigned> BitstreamCursor::skipRecord(unsigned AbbrevID) {
- // Skip unabbreviated records by reading past their entries.
- if (AbbrevID == bitc::UNABBREV_RECORD) {
- Expected<uint32_t> MaybeCode = ReadVBR(6);
- if (!MaybeCode)
- return MaybeCode.takeError();
- unsigned Code = MaybeCode.get();
- Expected<uint32_t> MaybeVBR = ReadVBR(6);
- if (!MaybeVBR)
- return MaybeVBR.get();
- unsigned NumElts = MaybeVBR.get();
- for (unsigned i = 0; i != NumElts; ++i)
- if (Expected<uint64_t> Res = ReadVBR64(6))
- ; // Skip!
- else
- return Res.takeError();
- return Code;
- }
-
- const BitCodeAbbrev *Abbv = getAbbrev(AbbrevID);
- 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<uint64_t> 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 (Error Err = skipAbbreviatedField(*this, Op))
- return std::move(Err);
- continue;
- }
-
- if (Op.getEncoding() == BitCodeAbbrevOp::Array) {
- // Array case. Read the number of elements as a vbr6.
- Expected<uint32_t> 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:
- report_fatal_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() +
- NumElts * EltEnc.getEncodingData()))
- return std::move(Err);
- break;
- case BitCodeAbbrevOp::VBR:
- assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize);
- for (; NumElts; --NumElts)
- if (Expected<uint64_t> Res =
- ReadVBR64((unsigned)EltEnc.getEncodingData()))
- ; // Skip!
- else
- return Res.takeError();
- break;
- case BitCodeAbbrevOp::Char6:
- if (Error Err = JumpToBit(GetCurrentBitNo() + NumElts * 6))
- return std::move(Err);
- break;
- }
- continue;
- }
-
- assert(Op.getEncoding() == BitCodeAbbrevOp::Blob);
- // Blob case. Read the number of bytes as a vbr6.
- Expected<uint32_t> 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.
- 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)) {
- skipToEnd();
- break;
- }
-
- // Skip over the blob.
- if (Error Err = JumpToBit(NewEnd))
- return std::move(Err);
- }
- return Code;
-}
-
-Expected<unsigned> BitstreamCursor::readRecord(unsigned AbbrevID,
- SmallVectorImpl<uint64_t> &Vals,
- StringRef *Blob) {
- if (AbbrevID == bitc::UNABBREV_RECORD) {
- Expected<uint32_t> MaybeCode = ReadVBR(6);
- if (!MaybeCode)
- return MaybeCode.takeError();
- uint32_t Code = MaybeCode.get();
- Expected<uint32_t> MaybeNumElts = ReadVBR(6);
- if (!MaybeNumElts)
- return MaybeNumElts.takeError();
- uint32_t NumElts = MaybeNumElts.get();
-
- for (unsigned i = 0; i != NumElts; ++i)
- if (Expected<uint64_t> MaybeVal = ReadVBR64(6))
- Vals.push_back(MaybeVal.get());
- else
- return MaybeVal.takeError();
- return Code;
- }
-
- const BitCodeAbbrev *Abbv = getAbbrev(AbbrevID);
-
- // 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)
- report_fatal_error("Abbreviation starts with an Array or a Blob");
- if (Expected<uint64_t> 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<uint64_t> 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<uint32_t> MaybeNumElts = ReadVBR(6);
- if (!MaybeNumElts)
- return MaybeNumElts.takeError();
- uint32_t NumElts = MaybeNumElts.get();
-
- // Get the element encoding.
- if (i + 2 != e)
- report_fatal_error("Array op not second to last");
- const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i);
- if (!EltEnc.isEncoding())
- report_fatal_error(
- "Array element type has to be an encoding of a type");
-
- // Read all the elements.
- switch (EltEnc.getEncoding()) {
- default:
- report_fatal_error("Array element type can't be an Array or a Blob");
- case BitCodeAbbrevOp::Fixed:
- for (; NumElts; --NumElts)
- if (Expected<SimpleBitstreamCursor::word_t> MaybeVal =
- Read((unsigned)EltEnc.getEncodingData()))
- Vals.push_back(MaybeVal.get());
- else
- return MaybeVal.takeError();
- break;
- case BitCodeAbbrevOp::VBR:
- for (; NumElts; --NumElts)
- if (Expected<uint64_t> MaybeVal =
- ReadVBR64((unsigned)EltEnc.getEncodingData()))
- Vals.push_back(MaybeVal.get());
- else
- return MaybeVal.takeError();
- break;
- case BitCodeAbbrevOp::Char6:
- for (; NumElts; --NumElts)
- if (Expected<SimpleBitstreamCursor::word_t> 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<uint32_t> 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();
- 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)) {
- Vals.append(NumElts, 0);
- skipToEnd();
- break;
- }
-
- // 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);
- 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.
- for (; NumElts; --NumElts)
- Vals.push_back((unsigned char)*Ptr++);
- }
- }
-
- return Code;
-}
-
-Error BitstreamCursor::ReadAbbrevRecord() {
- auto Abbv = std::make_shared<BitCodeAbbrev>();
- Expected<uint32_t> MaybeNumOpInfo = ReadVBR(5);
- if (!MaybeNumOpInfo)
- return MaybeNumOpInfo.takeError();
- unsigned NumOpInfo = MaybeNumOpInfo.get();
- for (unsigned i = 0; i != NumOpInfo; ++i) {
- Expected<word_t> MaybeIsLiteral = Read(1);
- if (!MaybeIsLiteral)
- return MaybeIsLiteral.takeError();
- bool IsLiteral = MaybeIsLiteral.get();
- if (IsLiteral) {
- Expected<uint64_t> MaybeOp = ReadVBR64(8);
- if (!MaybeOp)
- return MaybeOp.takeError();
- Abbv->Add(BitCodeAbbrevOp(MaybeOp.get()));
- continue;
- }
-
- Expected<word_t> MaybeEncoding = Read(3);
- if (!MaybeEncoding)
- return MaybeEncoding.takeError();
- BitCodeAbbrevOp::Encoding E =
- (BitCodeAbbrevOp::Encoding)MaybeEncoding.get();
- if (BitCodeAbbrevOp::hasEncodingData(E)) {
- Expected<uint64_t> 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)
- report_fatal_error(
- "Fixed or VBR abbrev record with size > MaxChunkData");
-
- Abbv->Add(BitCodeAbbrevOp(E, Data));
- } else
- Abbv->Add(BitCodeAbbrevOp(E));
- }
-
- if (Abbv->getNumOperandInfos() == 0)
- report_fatal_error("Abbrev record with no operands");
- CurAbbrevs.push_back(std::move(Abbv));
-
- return Error::success();
-}
-
-Expected<Optional<BitstreamBlockInfo>>
-BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) {
- if (llvm::Error Err = EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID))
- return std::move(Err);
-
- BitstreamBlockInfo NewBlockInfo;
-
- SmallVector<uint64_t, 64> Record;
- BitstreamBlockInfo::BlockInfo *CurBlockInfo = nullptr;
-
- // Read all the records for this module.
- while (true) {
- Expected<BitstreamEntry> 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 None;
- 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 None;
- if (Error Err = ReadAbbrevRecord())
- return std::move(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<unsigned> 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 None;
- CurBlockInfo = &NewBlockInfo.getOrCreateBlockInfo((unsigned)Record[0]);
- break;
- case bitc::BLOCKINFO_CODE_BLOCKNAME: {
- if (!CurBlockInfo)
- return None;
- if (!ReadBlockInfoNames)
- 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 None;
- if (!ReadBlockInfoNames)
- 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;
- }
- }
- }
-}
Modified: llvm/trunk/lib/Bitcode/Reader/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/CMakeLists.txt?rev=365091&r1=365090&r2=365091&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/CMakeLists.txt (original)
+++ llvm/trunk/lib/Bitcode/Reader/CMakeLists.txt Wed Jul 3 15:40:07 2019
@@ -1,7 +1,6 @@
add_llvm_library(LLVMBitReader
BitReader.cpp
BitcodeReader.cpp
- BitstreamReader.cpp
MetadataLoader.cpp
ValueList.cpp
Modified: llvm/trunk/lib/Bitcode/Reader/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/LLVMBuild.txt?rev=365091&r1=365090&r2=365091&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/LLVMBuild.txt (original)
+++ llvm/trunk/lib/Bitcode/Reader/LLVMBuild.txt Wed Jul 3 15:40:07 2019
@@ -18,4 +18,4 @@
type = Library
name = BitReader
parent = Bitcode
-required_libraries = Core Support
+required_libraries = BitstreamReader Core Support
Modified: llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp?rev=365091&r1=365090&r2=365091&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp Wed Jul 3 15:40:07 2019
@@ -22,7 +22,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Bitcode/BitcodeReader.h"
-#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Bitstream/BitstreamReader.h"
#include "llvm/Bitcode/LLVMBitCodes.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Attributes.h"
Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=365091&r1=365090&r2=365091&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Wed Jul 3 15:40:07 2019
@@ -24,8 +24,8 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/Bitcode/BitCodes.h"
-#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Bitstream/BitCodes.h"
+#include "llvm/Bitstream/BitstreamWriter.h"
#include "llvm/Bitcode/LLVMBitCodes.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/Attributes.h"
Added: llvm/trunk/lib/Bitstream/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitstream/CMakeLists.txt?rev=365091&view=auto
==============================================================================
--- llvm/trunk/lib/Bitstream/CMakeLists.txt (added)
+++ llvm/trunk/lib/Bitstream/CMakeLists.txt Wed Jul 3 15:40:07 2019
@@ -0,0 +1,2 @@
+add_subdirectory(Reader)
+# The writer is header-only.
Added: llvm/trunk/lib/Bitstream/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitstream/LLVMBuild.txt?rev=365091&view=auto
==============================================================================
--- llvm/trunk/lib/Bitstream/LLVMBuild.txt (added)
+++ llvm/trunk/lib/Bitstream/LLVMBuild.txt Wed Jul 3 15:40:07 2019
@@ -0,0 +1,23 @@
+;===- ./lib/Bitstream/LLVMBuild.txt ----------------------------*- Conf -*--===;
+;
+; 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
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[common]
+subdirectories = Reader
+
+[component_0]
+type = Group
+name = Bitstream
+parent = Libraries
Added: llvm/trunk/lib/Bitstream/Reader/BitstreamReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitstream/Reader/BitstreamReader.cpp?rev=365091&view=auto
==============================================================================
--- llvm/trunk/lib/Bitstream/Reader/BitstreamReader.cpp (added)
+++ llvm/trunk/lib/Bitstream/Reader/BitstreamReader.cpp Wed Jul 3 15:40:07 2019
@@ -0,0 +1,510 @@
+//===- 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 <cassert>
+#include <string>
+
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// BitstreamCursor implementation
+//===----------------------------------------------------------------------===//
+
+/// 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)) {
+ CurAbbrevs.insert(CurAbbrevs.end(), Info->Abbrevs.begin(),
+ Info->Abbrevs.end());
+ }
+ }
+
+ // Get the codesize of this block.
+ Expected<uint32_t> 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<word_t> 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<uint64_t> 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<unsigned> Res = Cursor.Read(6))
+ return BitCodeAbbrevOp::DecodeChar6(Res.get());
+ else
+ return Res.takeError();
+ }
+ llvm_unreachable("invalid abbreviation encoding");
+}
+
+static Error skipAbbreviatedField(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);
+ if (Expected<unsigned> Res = Cursor.Read((unsigned)Op.getEncodingData()))
+ break;
+ else
+ return Res.takeError();
+ case BitCodeAbbrevOp::VBR:
+ assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize);
+ if (Expected<uint64_t> Res =
+ Cursor.ReadVBR64((unsigned)Op.getEncodingData()))
+ break;
+ else
+ return Res.takeError();
+ case BitCodeAbbrevOp::Char6:
+ if (Expected<unsigned> Res = Cursor.Read(6))
+ break;
+ else
+ return Res.takeError();
+ }
+ return ErrorSuccess();
+}
+
+/// skipRecord - Read the current record and discard it.
+Expected<unsigned> BitstreamCursor::skipRecord(unsigned AbbrevID) {
+ // Skip unabbreviated records by reading past their entries.
+ if (AbbrevID == bitc::UNABBREV_RECORD) {
+ Expected<uint32_t> MaybeCode = ReadVBR(6);
+ if (!MaybeCode)
+ return MaybeCode.takeError();
+ unsigned Code = MaybeCode.get();
+ Expected<uint32_t> MaybeVBR = ReadVBR(6);
+ if (!MaybeVBR)
+ return MaybeVBR.get();
+ unsigned NumElts = MaybeVBR.get();
+ for (unsigned i = 0; i != NumElts; ++i)
+ if (Expected<uint64_t> Res = ReadVBR64(6))
+ ; // Skip!
+ else
+ return Res.takeError();
+ return Code;
+ }
+
+ const BitCodeAbbrev *Abbv = getAbbrev(AbbrevID);
+ 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<uint64_t> 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 (Error Err = skipAbbreviatedField(*this, Op))
+ return std::move(Err);
+ continue;
+ }
+
+ if (Op.getEncoding() == BitCodeAbbrevOp::Array) {
+ // Array case. Read the number of elements as a vbr6.
+ Expected<uint32_t> 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:
+ report_fatal_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() +
+ NumElts * EltEnc.getEncodingData()))
+ return std::move(Err);
+ break;
+ case BitCodeAbbrevOp::VBR:
+ assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize);
+ for (; NumElts; --NumElts)
+ if (Expected<uint64_t> Res =
+ ReadVBR64((unsigned)EltEnc.getEncodingData()))
+ ; // Skip!
+ else
+ return Res.takeError();
+ break;
+ case BitCodeAbbrevOp::Char6:
+ if (Error Err = JumpToBit(GetCurrentBitNo() + NumElts * 6))
+ return std::move(Err);
+ break;
+ }
+ continue;
+ }
+
+ assert(Op.getEncoding() == BitCodeAbbrevOp::Blob);
+ // Blob case. Read the number of bytes as a vbr6.
+ Expected<uint32_t> 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.
+ 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)) {
+ skipToEnd();
+ break;
+ }
+
+ // Skip over the blob.
+ if (Error Err = JumpToBit(NewEnd))
+ return std::move(Err);
+ }
+ return Code;
+}
+
+Expected<unsigned> BitstreamCursor::readRecord(unsigned AbbrevID,
+ SmallVectorImpl<uint64_t> &Vals,
+ StringRef *Blob) {
+ if (AbbrevID == bitc::UNABBREV_RECORD) {
+ Expected<uint32_t> MaybeCode = ReadVBR(6);
+ if (!MaybeCode)
+ return MaybeCode.takeError();
+ uint32_t Code = MaybeCode.get();
+ Expected<uint32_t> MaybeNumElts = ReadVBR(6);
+ if (!MaybeNumElts)
+ return MaybeNumElts.takeError();
+ uint32_t NumElts = MaybeNumElts.get();
+
+ for (unsigned i = 0; i != NumElts; ++i)
+ if (Expected<uint64_t> MaybeVal = ReadVBR64(6))
+ Vals.push_back(MaybeVal.get());
+ else
+ return MaybeVal.takeError();
+ return Code;
+ }
+
+ const BitCodeAbbrev *Abbv = getAbbrev(AbbrevID);
+
+ // 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)
+ report_fatal_error("Abbreviation starts with an Array or a Blob");
+ if (Expected<uint64_t> 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<uint64_t> 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<uint32_t> MaybeNumElts = ReadVBR(6);
+ if (!MaybeNumElts)
+ return MaybeNumElts.takeError();
+ uint32_t NumElts = MaybeNumElts.get();
+
+ // Get the element encoding.
+ if (i + 2 != e)
+ report_fatal_error("Array op not second to last");
+ const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i);
+ if (!EltEnc.isEncoding())
+ report_fatal_error(
+ "Array element type has to be an encoding of a type");
+
+ // Read all the elements.
+ switch (EltEnc.getEncoding()) {
+ default:
+ report_fatal_error("Array element type can't be an Array or a Blob");
+ case BitCodeAbbrevOp::Fixed:
+ for (; NumElts; --NumElts)
+ if (Expected<SimpleBitstreamCursor::word_t> MaybeVal =
+ Read((unsigned)EltEnc.getEncodingData()))
+ Vals.push_back(MaybeVal.get());
+ else
+ return MaybeVal.takeError();
+ break;
+ case BitCodeAbbrevOp::VBR:
+ for (; NumElts; --NumElts)
+ if (Expected<uint64_t> MaybeVal =
+ ReadVBR64((unsigned)EltEnc.getEncodingData()))
+ Vals.push_back(MaybeVal.get());
+ else
+ return MaybeVal.takeError();
+ break;
+ case BitCodeAbbrevOp::Char6:
+ for (; NumElts; --NumElts)
+ if (Expected<SimpleBitstreamCursor::word_t> 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<uint32_t> 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();
+ 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)) {
+ Vals.append(NumElts, 0);
+ skipToEnd();
+ break;
+ }
+
+ // 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);
+ 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.
+ for (; NumElts; --NumElts)
+ Vals.push_back((unsigned char)*Ptr++);
+ }
+ }
+
+ return Code;
+}
+
+Error BitstreamCursor::ReadAbbrevRecord() {
+ auto Abbv = std::make_shared<BitCodeAbbrev>();
+ Expected<uint32_t> MaybeNumOpInfo = ReadVBR(5);
+ if (!MaybeNumOpInfo)
+ return MaybeNumOpInfo.takeError();
+ unsigned NumOpInfo = MaybeNumOpInfo.get();
+ for (unsigned i = 0; i != NumOpInfo; ++i) {
+ Expected<word_t> MaybeIsLiteral = Read(1);
+ if (!MaybeIsLiteral)
+ return MaybeIsLiteral.takeError();
+ bool IsLiteral = MaybeIsLiteral.get();
+ if (IsLiteral) {
+ Expected<uint64_t> MaybeOp = ReadVBR64(8);
+ if (!MaybeOp)
+ return MaybeOp.takeError();
+ Abbv->Add(BitCodeAbbrevOp(MaybeOp.get()));
+ continue;
+ }
+
+ Expected<word_t> MaybeEncoding = Read(3);
+ if (!MaybeEncoding)
+ return MaybeEncoding.takeError();
+ BitCodeAbbrevOp::Encoding E =
+ (BitCodeAbbrevOp::Encoding)MaybeEncoding.get();
+ if (BitCodeAbbrevOp::hasEncodingData(E)) {
+ Expected<uint64_t> 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)
+ report_fatal_error(
+ "Fixed or VBR abbrev record with size > MaxChunkData");
+
+ Abbv->Add(BitCodeAbbrevOp(E, Data));
+ } else
+ Abbv->Add(BitCodeAbbrevOp(E));
+ }
+
+ if (Abbv->getNumOperandInfos() == 0)
+ report_fatal_error("Abbrev record with no operands");
+ CurAbbrevs.push_back(std::move(Abbv));
+
+ return Error::success();
+}
+
+Expected<Optional<BitstreamBlockInfo>>
+BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) {
+ if (llvm::Error Err = EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID))
+ return std::move(Err);
+
+ BitstreamBlockInfo NewBlockInfo;
+
+ SmallVector<uint64_t, 64> Record;
+ BitstreamBlockInfo::BlockInfo *CurBlockInfo = nullptr;
+
+ // Read all the records for this module.
+ while (true) {
+ Expected<BitstreamEntry> 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 None;
+ 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 None;
+ if (Error Err = ReadAbbrevRecord())
+ return std::move(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<unsigned> 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 None;
+ CurBlockInfo = &NewBlockInfo.getOrCreateBlockInfo((unsigned)Record[0]);
+ break;
+ case bitc::BLOCKINFO_CODE_BLOCKNAME: {
+ if (!CurBlockInfo)
+ return None;
+ if (!ReadBlockInfoNames)
+ 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 None;
+ if (!ReadBlockInfoNames)
+ 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;
+ }
+ }
+ }
+}
Added: llvm/trunk/lib/Bitstream/Reader/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitstream/Reader/CMakeLists.txt?rev=365091&view=auto
==============================================================================
--- llvm/trunk/lib/Bitstream/Reader/CMakeLists.txt (added)
+++ llvm/trunk/lib/Bitstream/Reader/CMakeLists.txt Wed Jul 3 15:40:07 2019
@@ -0,0 +1,7 @@
+add_llvm_library(LLVMBitstreamReader
+ BitstreamReader.cpp
+
+ ADDITIONAL_HEADER_DIRS
+ ${LLVM_MAIN_INCLUDE_DIR}/llvm/Bitcode
+ ${LLVM_MAIN_INCLUDE_DIR}/llvm/Bitstream
+ )
Added: llvm/trunk/lib/Bitstream/Reader/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitstream/Reader/LLVMBuild.txt?rev=365091&view=auto
==============================================================================
--- llvm/trunk/lib/Bitstream/Reader/LLVMBuild.txt (added)
+++ llvm/trunk/lib/Bitstream/Reader/LLVMBuild.txt Wed Jul 3 15:40:07 2019
@@ -0,0 +1,21 @@
+;===- ./lib/Bitstream/Reader/LLVMBuild.txt ---------------------*- Conf -*--===;
+;
+; 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
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = BitstreamReader
+parent = Bitstream
+required_libraries = Support
Modified: llvm/trunk/lib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CMakeLists.txt?rev=365091&r1=365090&r2=365091&view=diff
==============================================================================
--- llvm/trunk/lib/CMakeLists.txt (original)
+++ llvm/trunk/lib/CMakeLists.txt Wed Jul 3 15:40:07 2019
@@ -7,6 +7,7 @@ add_subdirectory(IRReader)
add_subdirectory(CodeGen)
add_subdirectory(BinaryFormat)
add_subdirectory(Bitcode)
+add_subdirectory(Bitstream)
add_subdirectory(Transforms)
add_subdirectory(Linker)
add_subdirectory(Analysis)
Modified: llvm/trunk/lib/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LLVMBuild.txt?rev=365091&r1=365090&r2=365091&view=diff
==============================================================================
--- llvm/trunk/lib/LLVMBuild.txt (original)
+++ llvm/trunk/lib/LLVMBuild.txt Wed Jul 3 15:40:07 2019
@@ -19,6 +19,7 @@ subdirectories =
Analysis
AsmParser
Bitcode
+ Bitstream
CodeGen
DebugInfo
Demangle
Modified: llvm/trunk/tools/llvm-bcanalyzer/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-bcanalyzer/CMakeLists.txt?rev=365091&r1=365090&r2=365091&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-bcanalyzer/CMakeLists.txt (original)
+++ llvm/trunk/tools/llvm-bcanalyzer/CMakeLists.txt Wed Jul 3 15:40:07 2019
@@ -1,5 +1,6 @@
set(LLVM_LINK_COMPONENTS
BitReader
+ BitstreamReader
Support
)
Modified: llvm/trunk/tools/llvm-bcanalyzer/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-bcanalyzer/LLVMBuild.txt?rev=365091&r1=365090&r2=365091&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-bcanalyzer/LLVMBuild.txt (original)
+++ llvm/trunk/tools/llvm-bcanalyzer/LLVMBuild.txt Wed Jul 3 15:40:07 2019
@@ -18,4 +18,4 @@
type = Tool
name = llvm-bcanalyzer
parent = Tools
-required_libraries = BitReader
+required_libraries = BitReader BitstreamReader Support
Modified: llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp?rev=365091&r1=365090&r2=365091&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp (original)
+++ llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp Wed Jul 3 15:40:07 2019
@@ -28,7 +28,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Bitcode/BitcodeReader.h"
-#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Bitstream/BitstreamReader.h"
#include "llvm/Bitcode/LLVMBitCodes.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Format.h"
Removed: llvm/trunk/unittests/Bitcode/BitstreamReaderTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Bitcode/BitstreamReaderTest.cpp?rev=365090&view=auto
==============================================================================
--- llvm/trunk/unittests/Bitcode/BitstreamReaderTest.cpp (original)
+++ llvm/trunk/unittests/Bitcode/BitstreamReaderTest.cpp (removed)
@@ -1,167 +0,0 @@
-//===- BitstreamReaderTest.cpp - Tests for BitstreamReader ----------------===//
-//
-// 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/Bitcode/BitstreamReader.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Bitcode/BitstreamWriter.h"
-#include "gtest/gtest.h"
-
-using namespace llvm;
-
-namespace {
-
-TEST(BitstreamReaderTest, AtEndOfStream) {
- uint8_t Bytes[4] = {
- 0x00, 0x01, 0x02, 0x03
- };
- BitstreamCursor Cursor(Bytes);
-
- EXPECT_FALSE(Cursor.AtEndOfStream());
- Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(8);
- EXPECT_TRUE((bool)MaybeRead);
- EXPECT_FALSE(Cursor.AtEndOfStream());
- MaybeRead = Cursor.Read(24);
- EXPECT_TRUE((bool)MaybeRead);
- EXPECT_TRUE(Cursor.AtEndOfStream());
-
- EXPECT_FALSE(Cursor.JumpToBit(0));
- EXPECT_FALSE(Cursor.AtEndOfStream());
-
- EXPECT_FALSE(Cursor.JumpToBit(32));
- EXPECT_TRUE(Cursor.AtEndOfStream());
-}
-
-TEST(BitstreamReaderTest, AtEndOfStreamJump) {
- uint8_t Bytes[4] = {
- 0x00, 0x01, 0x02, 0x03
- };
- BitstreamCursor Cursor(Bytes);
-
- EXPECT_FALSE(Cursor.JumpToBit(32));
- EXPECT_TRUE(Cursor.AtEndOfStream());
-}
-
-TEST(BitstreamReaderTest, AtEndOfStreamEmpty) {
- BitstreamCursor Cursor(ArrayRef<uint8_t>{});
-
- EXPECT_TRUE(Cursor.AtEndOfStream());
-}
-
-TEST(BitstreamReaderTest, getCurrentByteNo) {
- uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03};
- SimpleBitstreamCursor Cursor(Bytes);
-
- for (unsigned I = 0, E = 32; I != E; ++I) {
- EXPECT_EQ(I / 8, Cursor.getCurrentByteNo());
- Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(1);
- EXPECT_TRUE((bool)MaybeRead);
- }
- EXPECT_EQ(4u, Cursor.getCurrentByteNo());
-}
-
-TEST(BitstreamReaderTest, getPointerToByte) {
- uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
- SimpleBitstreamCursor Cursor(Bytes);
-
- for (unsigned I = 0, E = 8; I != E; ++I) {
- EXPECT_EQ(Bytes + I, Cursor.getPointerToByte(I, 1));
- }
-}
-
-TEST(BitstreamReaderTest, getPointerToBit) {
- uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
- SimpleBitstreamCursor Cursor(Bytes);
-
- for (unsigned I = 0, E = 8; I != E; ++I) {
- EXPECT_EQ(Bytes + I, Cursor.getPointerToBit(I * 8, 1));
- }
-}
-
-TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) {
- SmallVector<uint8_t, 1> BlobData;
- for (unsigned I = 0, E = 1024; I != E; ++I)
- BlobData.push_back(I);
-
- // Try a bunch of different sizes.
- const unsigned Magic = 0x12345678;
- const unsigned BlockID = bitc::FIRST_APPLICATION_BLOCKID;
- const unsigned RecordID = 1;
- for (unsigned I = 0, BlobSize = 0, E = BlobData.size(); BlobSize < E;
- BlobSize += ++I) {
- StringRef BlobIn((const char *)BlobData.begin(), BlobSize);
-
- // Write the bitcode.
- SmallVector<char, 1> Buffer;
- unsigned AbbrevID;
- {
- BitstreamWriter Stream(Buffer);
- Stream.Emit(Magic, 32);
- Stream.EnterSubblock(BlockID, 3);
-
- auto Abbrev = std::make_shared<BitCodeAbbrev>();
- Abbrev->Add(BitCodeAbbrevOp(RecordID));
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
- AbbrevID = Stream.EmitAbbrev(std::move(Abbrev));
- unsigned Record[] = {RecordID};
- Stream.EmitRecordWithBlob(AbbrevID, makeArrayRef(Record), BlobIn);
-
- Stream.ExitBlock();
- }
-
- // Stream the buffer into the reader.
- BitstreamCursor Stream(
- ArrayRef<uint8_t>((const uint8_t *)Buffer.begin(), Buffer.size()));
-
- // Header. Included in test so that we can run llvm-bcanalyzer to debug
- // when there are problems.
- Expected<SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(32);
- ASSERT_TRUE((bool)MaybeRead);
- ASSERT_EQ(Magic, MaybeRead.get());
-
- // Block.
- Expected<BitstreamEntry> MaybeEntry =
- Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
- ASSERT_TRUE((bool)MaybeEntry);
- BitstreamEntry Entry = MaybeEntry.get();
- ASSERT_EQ(BitstreamEntry::SubBlock, Entry.Kind);
- ASSERT_EQ(BlockID, Entry.ID);
- ASSERT_FALSE(Stream.EnterSubBlock(BlockID));
-
- // Abbreviation.
- MaybeEntry = Stream.advance();
- ASSERT_TRUE((bool)MaybeEntry);
- Entry = MaybeEntry.get();
- ASSERT_EQ(BitstreamEntry::Record, Entry.Kind);
- ASSERT_EQ(AbbrevID, Entry.ID);
-
- // Record.
- StringRef BlobOut;
- SmallVector<uint64_t, 1> Record;
- Expected<unsigned> MaybeRecord =
- Stream.readRecord(Entry.ID, Record, &BlobOut);
- ASSERT_TRUE((bool)MaybeRecord);
- ASSERT_EQ(RecordID, MaybeRecord.get());
- EXPECT_TRUE(Record.empty());
- EXPECT_EQ(BlobIn, BlobOut);
- }
-}
-
-TEST(BitstreamReaderTest, shortRead) {
- uint8_t Bytes[] = {8, 7, 6, 5, 4, 3, 2, 1};
- for (unsigned I = 1; I != 8; ++I) {
- SimpleBitstreamCursor Cursor(ArrayRef<uint8_t>(Bytes, I));
- Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(8);
- ASSERT_TRUE((bool)MaybeRead);
- EXPECT_EQ(8ull, MaybeRead.get());
- }
-}
-
-static_assert(is_trivially_copyable<BitCodeAbbrevOp>::value,
- "trivially copyable");
-
-} // end anonymous namespace
Removed: llvm/trunk/unittests/Bitcode/BitstreamWriterTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Bitcode/BitstreamWriterTest.cpp?rev=365090&view=auto
==============================================================================
--- llvm/trunk/unittests/Bitcode/BitstreamWriterTest.cpp (original)
+++ llvm/trunk/unittests/Bitcode/BitstreamWriterTest.cpp (removed)
@@ -1,58 +0,0 @@
-//===- BitstreamWriterTest.cpp - Tests for BitstreamWriter ----------------===//
-//
-// 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/Bitcode/BitstreamWriter.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "gtest/gtest.h"
-
-using namespace llvm;
-
-namespace {
-
-TEST(BitstreamWriterTest, emitBlob) {
- SmallString<64> Buffer;
- BitstreamWriter W(Buffer);
- W.emitBlob("str", /* ShouldEmitSize */ false);
- EXPECT_EQ(StringRef("str\0", 4), Buffer);
-}
-
-TEST(BitstreamWriterTest, emitBlobWithSize) {
- SmallString<64> Buffer;
- {
- BitstreamWriter W(Buffer);
- W.emitBlob("str");
- }
- SmallString<64> Expected;
- {
- BitstreamWriter W(Expected);
- W.EmitVBR(3, 6);
- W.FlushToWord();
- W.Emit('s', 8);
- W.Emit('t', 8);
- W.Emit('r', 8);
- W.Emit(0, 8);
- }
- EXPECT_EQ(StringRef(Expected), Buffer);
-}
-
-TEST(BitstreamWriterTest, emitBlobEmpty) {
- SmallString<64> Buffer;
- BitstreamWriter W(Buffer);
- W.emitBlob("", /* ShouldEmitSize */ false);
- EXPECT_EQ(StringRef(""), Buffer);
-}
-
-TEST(BitstreamWriterTest, emitBlob4ByteAligned) {
- SmallString<64> Buffer;
- BitstreamWriter W(Buffer);
- W.emitBlob("str0", /* ShouldEmitSize */ false);
- EXPECT_EQ(StringRef("str0"), Buffer);
-}
-
-} // end namespace
Modified: llvm/trunk/unittests/Bitcode/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Bitcode/CMakeLists.txt?rev=365091&r1=365090&r2=365091&view=diff
==============================================================================
--- llvm/trunk/unittests/Bitcode/CMakeLists.txt (original)
+++ llvm/trunk/unittests/Bitcode/CMakeLists.txt Wed Jul 3 15:40:07 2019
@@ -8,6 +8,4 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(BitcodeTests
BitReaderTest.cpp
- BitstreamReaderTest.cpp
- BitstreamWriterTest.cpp
)
Added: llvm/trunk/unittests/Bitstream/BitstreamReaderTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Bitstream/BitstreamReaderTest.cpp?rev=365091&view=auto
==============================================================================
--- llvm/trunk/unittests/Bitstream/BitstreamReaderTest.cpp (added)
+++ llvm/trunk/unittests/Bitstream/BitstreamReaderTest.cpp Wed Jul 3 15:40:07 2019
@@ -0,0 +1,167 @@
+//===- BitstreamReaderTest.cpp - Tests for BitstreamReader ----------------===//
+//
+// 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/STLExtras.h"
+#include "llvm/Bitstream/BitstreamWriter.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(BitstreamReaderTest, AtEndOfStream) {
+ uint8_t Bytes[4] = {
+ 0x00, 0x01, 0x02, 0x03
+ };
+ BitstreamCursor Cursor(Bytes);
+
+ EXPECT_FALSE(Cursor.AtEndOfStream());
+ Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(8);
+ EXPECT_TRUE((bool)MaybeRead);
+ EXPECT_FALSE(Cursor.AtEndOfStream());
+ MaybeRead = Cursor.Read(24);
+ EXPECT_TRUE((bool)MaybeRead);
+ EXPECT_TRUE(Cursor.AtEndOfStream());
+
+ EXPECT_FALSE(Cursor.JumpToBit(0));
+ EXPECT_FALSE(Cursor.AtEndOfStream());
+
+ EXPECT_FALSE(Cursor.JumpToBit(32));
+ EXPECT_TRUE(Cursor.AtEndOfStream());
+}
+
+TEST(BitstreamReaderTest, AtEndOfStreamJump) {
+ uint8_t Bytes[4] = {
+ 0x00, 0x01, 0x02, 0x03
+ };
+ BitstreamCursor Cursor(Bytes);
+
+ EXPECT_FALSE(Cursor.JumpToBit(32));
+ EXPECT_TRUE(Cursor.AtEndOfStream());
+}
+
+TEST(BitstreamReaderTest, AtEndOfStreamEmpty) {
+ BitstreamCursor Cursor(ArrayRef<uint8_t>{});
+
+ EXPECT_TRUE(Cursor.AtEndOfStream());
+}
+
+TEST(BitstreamReaderTest, getCurrentByteNo) {
+ uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03};
+ SimpleBitstreamCursor Cursor(Bytes);
+
+ for (unsigned I = 0, E = 32; I != E; ++I) {
+ EXPECT_EQ(I / 8, Cursor.getCurrentByteNo());
+ Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(1);
+ EXPECT_TRUE((bool)MaybeRead);
+ }
+ EXPECT_EQ(4u, Cursor.getCurrentByteNo());
+}
+
+TEST(BitstreamReaderTest, getPointerToByte) {
+ uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
+ SimpleBitstreamCursor Cursor(Bytes);
+
+ for (unsigned I = 0, E = 8; I != E; ++I) {
+ EXPECT_EQ(Bytes + I, Cursor.getPointerToByte(I, 1));
+ }
+}
+
+TEST(BitstreamReaderTest, getPointerToBit) {
+ uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
+ SimpleBitstreamCursor Cursor(Bytes);
+
+ for (unsigned I = 0, E = 8; I != E; ++I) {
+ EXPECT_EQ(Bytes + I, Cursor.getPointerToBit(I * 8, 1));
+ }
+}
+
+TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) {
+ SmallVector<uint8_t, 1> BlobData;
+ for (unsigned I = 0, E = 1024; I != E; ++I)
+ BlobData.push_back(I);
+
+ // Try a bunch of different sizes.
+ const unsigned Magic = 0x12345678;
+ const unsigned BlockID = bitc::FIRST_APPLICATION_BLOCKID;
+ const unsigned RecordID = 1;
+ for (unsigned I = 0, BlobSize = 0, E = BlobData.size(); BlobSize < E;
+ BlobSize += ++I) {
+ StringRef BlobIn((const char *)BlobData.begin(), BlobSize);
+
+ // Write the bitcode.
+ SmallVector<char, 1> Buffer;
+ unsigned AbbrevID;
+ {
+ BitstreamWriter Stream(Buffer);
+ Stream.Emit(Magic, 32);
+ Stream.EnterSubblock(BlockID, 3);
+
+ auto Abbrev = std::make_shared<BitCodeAbbrev>();
+ Abbrev->Add(BitCodeAbbrevOp(RecordID));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ AbbrevID = Stream.EmitAbbrev(std::move(Abbrev));
+ unsigned Record[] = {RecordID};
+ Stream.EmitRecordWithBlob(AbbrevID, makeArrayRef(Record), BlobIn);
+
+ Stream.ExitBlock();
+ }
+
+ // Stream the buffer into the reader.
+ BitstreamCursor Stream(
+ ArrayRef<uint8_t>((const uint8_t *)Buffer.begin(), Buffer.size()));
+
+ // Header. Included in test so that we can run llvm-bcanalyzer to debug
+ // when there are problems.
+ Expected<SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(32);
+ ASSERT_TRUE((bool)MaybeRead);
+ ASSERT_EQ(Magic, MaybeRead.get());
+
+ // Block.
+ Expected<BitstreamEntry> MaybeEntry =
+ Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
+ ASSERT_TRUE((bool)MaybeEntry);
+ BitstreamEntry Entry = MaybeEntry.get();
+ ASSERT_EQ(BitstreamEntry::SubBlock, Entry.Kind);
+ ASSERT_EQ(BlockID, Entry.ID);
+ ASSERT_FALSE(Stream.EnterSubBlock(BlockID));
+
+ // Abbreviation.
+ MaybeEntry = Stream.advance();
+ ASSERT_TRUE((bool)MaybeEntry);
+ Entry = MaybeEntry.get();
+ ASSERT_EQ(BitstreamEntry::Record, Entry.Kind);
+ ASSERT_EQ(AbbrevID, Entry.ID);
+
+ // Record.
+ StringRef BlobOut;
+ SmallVector<uint64_t, 1> Record;
+ Expected<unsigned> MaybeRecord =
+ Stream.readRecord(Entry.ID, Record, &BlobOut);
+ ASSERT_TRUE((bool)MaybeRecord);
+ ASSERT_EQ(RecordID, MaybeRecord.get());
+ EXPECT_TRUE(Record.empty());
+ EXPECT_EQ(BlobIn, BlobOut);
+ }
+}
+
+TEST(BitstreamReaderTest, shortRead) {
+ uint8_t Bytes[] = {8, 7, 6, 5, 4, 3, 2, 1};
+ for (unsigned I = 1; I != 8; ++I) {
+ SimpleBitstreamCursor Cursor(ArrayRef<uint8_t>(Bytes, I));
+ Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(8);
+ ASSERT_TRUE((bool)MaybeRead);
+ EXPECT_EQ(8ull, MaybeRead.get());
+ }
+}
+
+static_assert(is_trivially_copyable<BitCodeAbbrevOp>::value,
+ "trivially copyable");
+
+} // end anonymous namespace
Added: llvm/trunk/unittests/Bitstream/BitstreamWriterTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Bitstream/BitstreamWriterTest.cpp?rev=365091&view=auto
==============================================================================
--- llvm/trunk/unittests/Bitstream/BitstreamWriterTest.cpp (added)
+++ llvm/trunk/unittests/Bitstream/BitstreamWriterTest.cpp Wed Jul 3 15:40:07 2019
@@ -0,0 +1,58 @@
+//===- BitstreamWriterTest.cpp - Tests for BitstreamWriter ----------------===//
+//
+// 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/BitstreamWriter.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(BitstreamWriterTest, emitBlob) {
+ SmallString<64> Buffer;
+ BitstreamWriter W(Buffer);
+ W.emitBlob("str", /* ShouldEmitSize */ false);
+ EXPECT_EQ(StringRef("str\0", 4), Buffer);
+}
+
+TEST(BitstreamWriterTest, emitBlobWithSize) {
+ SmallString<64> Buffer;
+ {
+ BitstreamWriter W(Buffer);
+ W.emitBlob("str");
+ }
+ SmallString<64> Expected;
+ {
+ BitstreamWriter W(Expected);
+ W.EmitVBR(3, 6);
+ W.FlushToWord();
+ W.Emit('s', 8);
+ W.Emit('t', 8);
+ W.Emit('r', 8);
+ W.Emit(0, 8);
+ }
+ EXPECT_EQ(StringRef(Expected), Buffer);
+}
+
+TEST(BitstreamWriterTest, emitBlobEmpty) {
+ SmallString<64> Buffer;
+ BitstreamWriter W(Buffer);
+ W.emitBlob("", /* ShouldEmitSize */ false);
+ EXPECT_EQ(StringRef(""), Buffer);
+}
+
+TEST(BitstreamWriterTest, emitBlob4ByteAligned) {
+ SmallString<64> Buffer;
+ BitstreamWriter W(Buffer);
+ W.emitBlob("str0", /* ShouldEmitSize */ false);
+ EXPECT_EQ(StringRef("str0"), Buffer);
+}
+
+} // end namespace
Added: llvm/trunk/unittests/Bitstream/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Bitstream/CMakeLists.txt?rev=365091&view=auto
==============================================================================
--- llvm/trunk/unittests/Bitstream/CMakeLists.txt (added)
+++ llvm/trunk/unittests/Bitstream/CMakeLists.txt Wed Jul 3 15:40:07 2019
@@ -0,0 +1,8 @@
+set(LLVM_LINK_COMPONENTS
+ BitstreamReader
+ )
+
+add_llvm_unittest(BitstreamTests
+ BitstreamReaderTest.cpp
+ BitstreamWriterTest.cpp
+ )
Modified: llvm/trunk/unittests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CMakeLists.txt?rev=365091&r1=365090&r2=365091&view=diff
==============================================================================
--- llvm/trunk/unittests/CMakeLists.txt (original)
+++ llvm/trunk/unittests/CMakeLists.txt Wed Jul 3 15:40:07 2019
@@ -13,6 +13,7 @@ add_subdirectory(Analysis)
add_subdirectory(AsmParser)
add_subdirectory(BinaryFormat)
add_subdirectory(Bitcode)
+add_subdirectory(Bitstream)
add_subdirectory(CodeGen)
add_subdirectory(DebugInfo)
add_subdirectory(Demangle)
Modified: llvm/trunk/utils/GenLibDeps.pl
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/GenLibDeps.pl?rev=365091&r1=365090&r2=365091&view=diff
==============================================================================
--- llvm/trunk/utils/GenLibDeps.pl (original)
+++ llvm/trunk/utils/GenLibDeps.pl Wed Jul 3 15:40:07 2019
@@ -96,6 +96,8 @@ if ($PEROBJ) {
$libpath =~ s/^AsmPrinter/CodeGen\/AsmPrinter/;
$libpath =~ s/^BitReader/Bitcode\/Reader/;
$libpath =~ s/^BitWriter/Bitcode\/Writer/;
+ $libpath =~ s/^BitstreamReader/Bitstream\/Reader/;
+ $libpath =~ s/^BitstreamWriter/Bitstream\/Writer/;
$libpath =~ s/^MSIL/Target\/MSIL/;
$libpath =~ s/^Core/IR/;
$libpath =~ s/^Instrumentation/Transforms\/Instrumentation/;
@@ -136,6 +138,8 @@ if ($PEROBJ) {
$libpath =~ s/^AsmPrinter/CodeGen\/AsmPrinter/;
$libpath =~ s/^BitReader/Bitcode\/Reader/;
$libpath =~ s/^BitWriter/Bitcode\/Writer/;
+ $libpath =~ s/^BitstreamReader/Bitstream\/Reader/;
+ $libpath =~ s/^BitstreamWriter/Bitstream\/Writer/;
$libpath =~ s/^MSIL/Target\/MSIL/;
$libpath =~ s/^Core/VMCore/;
$libpath =~ s/^Instrumentation/Transforms\/Instrumentation/;
More information about the llvm-commits
mailing list