1c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot//===- BitstreamReader.h - Low-level bitstream reader interface -*- C++ -*-===// 2c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot// 3c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot// The LLVM Compiler Infrastructure 4c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot// 5c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot// This file is distributed under the University of Illinois Open Source 6c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot// License. See LICENSE.TXT for details. 7c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot// 8c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot//===----------------------------------------------------------------------===// 9c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot// 10c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot// This header defines the BitstreamReader class. This class can be used to 11c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot// read an arbitrary bitstream, regardless of its contents. 12c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot// 13c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot//===----------------------------------------------------------------------===// 14c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 15c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#ifndef LLVM_BITCODE_BITSTREAMREADER_H 16c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#define LLVM_BITCODE_BITSTREAMREADER_H 17c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 18c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#include "llvm/ADT/ArrayRef.h" 19c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#include "llvm/ADT/SmallVector.h" 20c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#include "llvm/Bitcode/BitCodes.h" 21c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#include "llvm/Support/Endian.h" 22c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#include "llvm/Support/ErrorHandling.h" 23c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#include "llvm/Support/MathExtras.h" 24c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#include "llvm/Support/MemoryBuffer.h" 25c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#include <algorithm> 26c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#include <cassert> 27c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#include <climits> 28c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#include <cstddef> 29c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#include <cstdint> 30c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#include <memory> 31c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#include <string> 32c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#include <utility> 33c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#include <vector> 34c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 35c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robotnamespace llvm { 36c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 37c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot/// This class maintains the abbreviations read from a block info block. 38c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robotclass BitstreamBlockInfo { 39c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robotpublic: 40c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// This contains information emitted to BLOCKINFO_BLOCK blocks. These 41c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// describe abbreviations that all blocks of the specified ID inherit. 42c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot struct BlockInfo { 43c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned BlockID; 44c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot std::vector<std::shared_ptr<BitCodeAbbrev>> Abbrevs; 45c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot std::string Name; 46c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot std::vector<std::pair<unsigned, std::string> > RecordNames; 47c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot }; 48c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 49c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robotprivate: 50c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot std::vector<BlockInfo> BlockInfoRecords; 51c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 52c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robotpublic: 53c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// If there is block info for the specified ID, return it, otherwise return 54c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// null. 55c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot const BlockInfo *getBlockInfo(unsigned BlockID) const { 56c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // Common case, the most recent entry matches BlockID. 57c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) 58c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return &BlockInfoRecords.back(); 59c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 60c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot for (unsigned i = 0, e = static_cast<unsigned>(BlockInfoRecords.size()); 61c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot i != e; ++i) 62c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (BlockInfoRecords[i].BlockID == BlockID) 63c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return &BlockInfoRecords[i]; 64c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return nullptr; 65c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 66c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 67c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { 68c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (const BlockInfo *BI = getBlockInfo(BlockID)) 69c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return *const_cast<BlockInfo*>(BI); 70c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 71c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // Otherwise, add a new record. 72c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BlockInfoRecords.emplace_back(); 73c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BlockInfoRecords.back().BlockID = BlockID; 74c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return BlockInfoRecords.back(); 75c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 76c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot}; 77c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 78c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot/// This represents a position within a bitstream. There may be multiple 79c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot/// independent cursors reading within one bitstream, each maintaining their 80c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot/// own local state. 81c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robotclass SimpleBitstreamCursor { 82c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot ArrayRef<uint8_t> BitcodeBytes; 83c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot size_t NextChar = 0; 84c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 85c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robotpublic: 86c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// This is the current data we have pulled from the stream but have not 87c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// returned to the client. This is specifically and intentionally defined to 88c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// follow the word size of the host machine for efficiency. We use word_t in 89c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// places that are aware of this to make it perfectly explicit what is going 90c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// on. 91c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot typedef size_t word_t; 92c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 93c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robotprivate: 94c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot word_t CurWord = 0; 95c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 96c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// This is the number of bits in CurWord that are valid. This is always from 97c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// [0...bits_of(size_t)-1] inclusive. 98c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned BitsInCurWord = 0; 99c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 100c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robotpublic: 101c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot static const size_t MaxChunkSize = sizeof(word_t) * 8; 102c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 103c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot SimpleBitstreamCursor() = default; 104c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot explicit SimpleBitstreamCursor(ArrayRef<uint8_t> BitcodeBytes) 105c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot : BitcodeBytes(BitcodeBytes) {} 106c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot explicit SimpleBitstreamCursor(StringRef BitcodeBytes) 107c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot : BitcodeBytes(reinterpret_cast<const uint8_t *>(BitcodeBytes.data()), 108c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BitcodeBytes.size()) {} 109c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot explicit SimpleBitstreamCursor(MemoryBufferRef BitcodeBytes) 110c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot : SimpleBitstreamCursor(BitcodeBytes.getBuffer()) {} 111c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 112c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot bool canSkipToPos(size_t pos) const { 113c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // pos can be skipped to if it is a valid address or one byte past the end. 114c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return pos <= BitcodeBytes.size(); 115c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 116c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 117c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot bool AtEndOfStream() { 118c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return BitsInCurWord == 0 && BitcodeBytes.size() <= NextChar; 119c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 120c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 121c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// Return the bit # of the bit we are reading. 122c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot uint64_t GetCurrentBitNo() const { 123c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return NextChar*CHAR_BIT - BitsInCurWord; 124c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 125c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 126c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // Return the byte # of the current bit. 127c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot uint64_t getCurrentByteNo() const { return GetCurrentBitNo() / 8; } 128c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 129c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot ArrayRef<uint8_t> getBitcodeBytes() const { return BitcodeBytes; } 130c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 131c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// Reset the stream to the specified bit number. 132c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot void JumpToBit(uint64_t BitNo) { 133c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot size_t ByteNo = size_t(BitNo/8) & ~(sizeof(word_t)-1); 134c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); 135c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot assert(canSkipToPos(ByteNo) && "Invalid location"); 136c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 137c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // Move the cursor to the right word. 138c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot NextChar = ByteNo; 139c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BitsInCurWord = 0; 140c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 141c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // Skip over any bits that are already consumed. 142c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (WordBitNo) 143c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot Read(WordBitNo); 144c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 145c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 146c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// Get a pointer into the bitstream at the specified byte offset. 147c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot const uint8_t *getPointerToByte(uint64_t ByteNo, uint64_t NumBytes) { 148c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return BitcodeBytes.data() + ByteNo; 149c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 150c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 151c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// Get a pointer into the bitstream at the specified bit offset. 152c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// 153c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// The bit offset must be on a byte boundary. 154c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot const uint8_t *getPointerToBit(uint64_t BitNo, uint64_t NumBytes) { 155c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot assert(!(BitNo % 8) && "Expected bit on byte boundary"); 156c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return getPointerToByte(BitNo / 8, NumBytes); 157c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 158c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 159c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot void fillCurWord() { 160c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (NextChar >= BitcodeBytes.size()) 161c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot report_fatal_error("Unexpected end of file"); 162c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 163c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // Read the next word from the stream. 164c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot const uint8_t *NextCharPtr = BitcodeBytes.data() + NextChar; 165c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned BytesRead; 166c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (BitcodeBytes.size() >= NextChar + sizeof(word_t)) { 167c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BytesRead = sizeof(word_t); 168c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot CurWord = 169c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot support::endian::read<word_t, support::little, support::unaligned>( 170c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot NextCharPtr); 171c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } else { 172c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // Short read. 173c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BytesRead = BitcodeBytes.size() - NextChar; 174c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot CurWord = 0; 175c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot for (unsigned B = 0; B != BytesRead; ++B) 176c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot CurWord |= uint64_t(NextCharPtr[B]) << (B * 8); 177c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 178c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot NextChar += BytesRead; 179c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BitsInCurWord = BytesRead * 8; 180c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 181c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 182c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot word_t Read(unsigned NumBits) { 183c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot static const unsigned BitsInWord = MaxChunkSize; 184c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 185c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot assert(NumBits && NumBits <= BitsInWord && 186c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot "Cannot return zero or more than BitsInWord bits!"); 187c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 188c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot static const unsigned Mask = sizeof(word_t) > 4 ? 0x3f : 0x1f; 189c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 190c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // If the field is fully contained by CurWord, return it quickly. 191c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (BitsInCurWord >= NumBits) { 192c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot word_t R = CurWord & (~word_t(0) >> (BitsInWord - NumBits)); 193c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 194c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // Use a mask to avoid undefined behavior. 195c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot CurWord >>= (NumBits & Mask); 196c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 197c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BitsInCurWord -= NumBits; 198c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return R; 199c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 200c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 201c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot word_t R = BitsInCurWord ? CurWord : 0; 202c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned BitsLeft = NumBits - BitsInCurWord; 203c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 204c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot fillCurWord(); 205c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 206c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // If we run out of data, abort. 207c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (BitsLeft > BitsInCurWord) 208c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot report_fatal_error("Unexpected end of file"); 209c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 210c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft)); 211c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 212c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // Use a mask to avoid undefined behavior. 213c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot CurWord >>= (BitsLeft & Mask); 214c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 215c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BitsInCurWord -= BitsLeft; 216c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 217c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot R |= R2 << (NumBits - BitsLeft); 218c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 219c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return R; 220c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 221c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 222c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot uint32_t ReadVBR(unsigned NumBits) { 223c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot uint32_t Piece = Read(NumBits); 224c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if ((Piece & (1U << (NumBits-1))) == 0) 225c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return Piece; 226c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 227c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot uint32_t Result = 0; 228c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned NextBit = 0; 229c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot while (true) { 230c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot Result |= (Piece & ((1U << (NumBits-1))-1)) << NextBit; 231c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 232c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if ((Piece & (1U << (NumBits-1))) == 0) 233c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return Result; 234c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 235c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot NextBit += NumBits-1; 236c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot Piece = Read(NumBits); 237c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 238c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 239c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 240c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // Read a VBR that may have a value up to 64-bits in size. The chunk size of 241c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // the VBR must still be <= 32 bits though. 242c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot uint64_t ReadVBR64(unsigned NumBits) { 243c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot uint32_t Piece = Read(NumBits); 244c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if ((Piece & (1U << (NumBits-1))) == 0) 245c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return uint64_t(Piece); 246c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 247c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot uint64_t Result = 0; 248c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned NextBit = 0; 249c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot while (true) { 250c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot Result |= uint64_t(Piece & ((1U << (NumBits-1))-1)) << NextBit; 251c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 252c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if ((Piece & (1U << (NumBits-1))) == 0) 253c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return Result; 254c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 255c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot NextBit += NumBits-1; 256c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot Piece = Read(NumBits); 257c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 258c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 259c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 260c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot void SkipToFourByteBoundary() { 261c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // If word_t is 64-bits and if we've read less than 32 bits, just dump 262c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // the bits we have up to the next 32-bit boundary. 263c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (sizeof(word_t) > 4 && 264c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BitsInCurWord >= 32) { 265c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot CurWord >>= BitsInCurWord-32; 266c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BitsInCurWord = 32; 267c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return; 268c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 269c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 270c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BitsInCurWord = 0; 271c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 272c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 273c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// Skip to the end of the file. 274c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot void skipToEnd() { NextChar = BitcodeBytes.size(); } 275c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot}; 276c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 277c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot/// When advancing through a bitstream cursor, each advance can discover a few 278c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot/// different kinds of entries: 279c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robotstruct BitstreamEntry { 280c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot enum { 281c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot Error, // Malformed bitcode was found. 282c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot EndBlock, // We've reached the end of the current block, (or the end of the 283c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // file, which is treated like a series of EndBlock records. 284c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot SubBlock, // This is the start of a new subblock of a specific ID. 285c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot Record // This is a record with a specific AbbrevID. 286c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } Kind; 287c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 288c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned ID; 289c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 290c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot static BitstreamEntry getError() { 291c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BitstreamEntry E; E.Kind = Error; return E; 292c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 293c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 294c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot static BitstreamEntry getEndBlock() { 295c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BitstreamEntry E; E.Kind = EndBlock; return E; 296c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 297c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 298c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot static BitstreamEntry getSubBlock(unsigned ID) { 299c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E; 300c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 301c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 302c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot static BitstreamEntry getRecord(unsigned AbbrevID) { 303c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E; 304c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 305c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot}; 306c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 307c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot/// This represents a position within a bitcode file, implemented on top of a 308c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot/// SimpleBitstreamCursor. 309c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot/// 310c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot/// Unlike iterators, BitstreamCursors are heavy-weight objects that should not 311c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot/// be passed by value. 312c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robotclass BitstreamCursor : SimpleBitstreamCursor { 313c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // This is the declared size of code values used for the current block, in 314c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // bits. 315c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned CurCodeSize = 2; 316c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 317c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// Abbrevs installed at in this block. 318c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot std::vector<std::shared_ptr<BitCodeAbbrev>> CurAbbrevs; 319c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 320c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot struct Block { 321c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned PrevCodeSize; 322c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot std::vector<std::shared_ptr<BitCodeAbbrev>> PrevAbbrevs; 323c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 324c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot explicit Block(unsigned PCS) : PrevCodeSize(PCS) {} 325c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot }; 326c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 327c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// This tracks the codesize of parent blocks. 328c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot SmallVector<Block, 8> BlockScope; 329c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 330c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BitstreamBlockInfo *BlockInfo = nullptr; 331c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 332c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robotpublic: 333c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot static const size_t MaxChunkSize = sizeof(word_t) * 8; 334c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 335c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BitstreamCursor() = default; 336c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot explicit BitstreamCursor(ArrayRef<uint8_t> BitcodeBytes) 337c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot : SimpleBitstreamCursor(BitcodeBytes) {} 338c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot explicit BitstreamCursor(StringRef BitcodeBytes) 339c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot : SimpleBitstreamCursor(BitcodeBytes) {} 340c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot explicit BitstreamCursor(MemoryBufferRef BitcodeBytes) 341c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot : SimpleBitstreamCursor(BitcodeBytes) {} 342c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 343c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot using SimpleBitstreamCursor::canSkipToPos; 344c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot using SimpleBitstreamCursor::AtEndOfStream; 345c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot using SimpleBitstreamCursor::getBitcodeBytes; 346c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot using SimpleBitstreamCursor::GetCurrentBitNo; 347c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot using SimpleBitstreamCursor::getCurrentByteNo; 348c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot using SimpleBitstreamCursor::getPointerToByte; 349c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot using SimpleBitstreamCursor::JumpToBit; 350c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot using SimpleBitstreamCursor::fillCurWord; 351c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot using SimpleBitstreamCursor::Read; 352c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot using SimpleBitstreamCursor::ReadVBR; 353c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot using SimpleBitstreamCursor::ReadVBR64; 354c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 355c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// Return the number of bits used to encode an abbrev #. 356c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned getAbbrevIDWidth() const { return CurCodeSize; } 357c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 358c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// Flags that modify the behavior of advance(). 359c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot enum { 360c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// If this flag is used, the advance() method does not automatically pop 361c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// the block scope when the end of a block is reached. 362c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot AF_DontPopBlockAtEnd = 1, 363c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 364c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// If this flag is used, abbrev entries are returned just like normal 365c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// records. 366c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot AF_DontAutoprocessAbbrevs = 2 367c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot }; 368c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 369c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// Advance the current bitstream, returning the next entry in the stream. 370c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BitstreamEntry advance(unsigned Flags = 0) { 371c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot while (true) { 372c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (AtEndOfStream()) 373c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return BitstreamEntry::getError(); 374c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 375c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned Code = ReadCode(); 376c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (Code == bitc::END_BLOCK) { 377c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // Pop the end of the block unless Flags tells us not to. 378c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd()) 379c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return BitstreamEntry::getError(); 380c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return BitstreamEntry::getEndBlock(); 381c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 382c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 383c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (Code == bitc::ENTER_SUBBLOCK) 384c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return BitstreamEntry::getSubBlock(ReadSubBlockID()); 385c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 386c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (Code == bitc::DEFINE_ABBREV && 387c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot !(Flags & AF_DontAutoprocessAbbrevs)) { 388c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // We read and accumulate abbrev's, the client can't do anything with 389c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // them anyway. 390c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot ReadAbbrevRecord(); 391c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot continue; 392c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 393c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 394c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return BitstreamEntry::getRecord(Code); 395c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 396c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 397c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 398c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// This is a convenience function for clients that don't expect any 399c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// subblocks. This just skips over them automatically. 400c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) { 401c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot while (true) { 402c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // If we found a normal entry, return it. 403c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BitstreamEntry Entry = advance(Flags); 404c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (Entry.Kind != BitstreamEntry::SubBlock) 405c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return Entry; 406c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 407c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // If we found a sub-block, just skip over it and check the next entry. 408c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (SkipBlock()) 409c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return BitstreamEntry::getError(); 410c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 411c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 412c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 413c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned ReadCode() { 414c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return Read(CurCodeSize); 415c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 416c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 417c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // Block header: 418c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen] 419c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 420c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// Having read the ENTER_SUBBLOCK code, read the BlockID for the block. 421c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned ReadSubBlockID() { 422c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return ReadVBR(bitc::BlockIDWidth); 423c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 424c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 425c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body 426c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// of this block. If the block record is malformed, return true. 427c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot bool SkipBlock() { 428c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // Read and ignore the codelen value. Since we are skipping this block, we 429c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // don't care what code widths are used inside of it. 430c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot ReadVBR(bitc::CodeLenWidth); 431c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot SkipToFourByteBoundary(); 432c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned NumFourBytes = Read(bitc::BlockSizeWidth); 433c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 434c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // Check that the block wasn't partially defined, and that the offset isn't 435c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // bogus. 436c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot size_t SkipTo = GetCurrentBitNo() + NumFourBytes*4*8; 437c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (AtEndOfStream() || !canSkipToPos(SkipTo/8)) 438c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return true; 439c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 440c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot JumpToBit(SkipTo); 441c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return false; 442c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 443c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 444c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// Having read the ENTER_SUBBLOCK abbrevid, enter the block, and return true 445c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// if the block has an error. 446c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr); 447c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 448c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot bool ReadBlockEnd() { 449c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (BlockScope.empty()) return true; 450c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 451c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // Block tail: 452c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // [END_BLOCK, <align4bytes>] 453c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot SkipToFourByteBoundary(); 454c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 455c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot popBlockScope(); 456c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return false; 457c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 458c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 459c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robotprivate: 460c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot void popBlockScope() { 461c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot CurCodeSize = BlockScope.back().PrevCodeSize; 462c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 463c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot CurAbbrevs = std::move(BlockScope.back().PrevAbbrevs); 464c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot BlockScope.pop_back(); 465c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 466c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 467c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot //===--------------------------------------------------------------------===// 468c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // Record Processing 469c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot //===--------------------------------------------------------------------===// 470c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 471c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robotpublic: 472c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// Return the abbreviation for the specified AbbrevId. 473c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) { 474c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned AbbrevNo = AbbrevID - bitc::FIRST_APPLICATION_ABBREV; 475c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot if (AbbrevNo >= CurAbbrevs.size()) 476c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot report_fatal_error("Invalid abbrev number"); 477c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot return CurAbbrevs[AbbrevNo].get(); 478c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot } 479c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 480c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// Read the current record and discard it, returning the code for the record. 481c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned skipRecord(unsigned AbbrevID); 482c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 483c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals, 484c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot StringRef *Blob = nullptr); 485c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 486c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot //===--------------------------------------------------------------------===// 487c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot // Abbrev Processing 488c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot //===--------------------------------------------------------------------===// 489c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot void ReadAbbrevRecord(); 490c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 491c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// Read and return a block info block from the bitstream. If an error was 492c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// encountered, return None. 493c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// 494c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// \param ReadBlockInfoNames Whether to read block/record name information in 495c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// the BlockInfo block. Only llvm-bcanalyzer uses this. 496c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot Optional<BitstreamBlockInfo> 497c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot ReadBlockInfoBlock(bool ReadBlockInfoNames = false); 498c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 499c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// Set the block info to be used by this BitstreamCursor to interpret 500c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot /// abbreviated records. 501c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot void setBlockInfo(BitstreamBlockInfo *BI) { BlockInfo = BI; } 502c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot}; 503c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 504c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot} // end llvm namespace 505c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot 506c9cc9e7d29b8970d8ddb734c88fb62d01e0b727android-build-team Robot#endif // LLVM_BITCODE_BITSTREAMREADER_H 507