diff options
Diffstat (limited to 'include/llvm/Bitcode')
-rw-r--r-- | include/llvm/Bitcode/BitCodes.h | 65 | ||||
-rw-r--r-- | include/llvm/Bitcode/BitstreamReader.h | 3 | ||||
-rw-r--r-- | include/llvm/Bitcode/BitstreamWriter.h | 54 |
3 files changed, 109 insertions, 13 deletions
diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitcode/BitCodes.h index a3b741b2e9..98d18b194b 100644 --- a/include/llvm/Bitcode/BitCodes.h +++ b/include/llvm/Bitcode/BitCodes.h @@ -18,6 +18,10 @@ #ifndef LLVM_BITCODE_BITCODES_H #define LLVM_BITCODE_BITCODES_H +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataTypes.h" +#include <cassert> + namespace llvm { namespace bitc { enum StandardWidths { @@ -31,16 +35,71 @@ namespace bitc { enum FixedCodes { 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, - // Two codes are reserved for defining abbrevs and for emitting an - // unabbreviated record. - DEFINE_ABBREVS = 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_ABBREV = 4 }; } // 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 { + FixedWidth = 1, // A fixed with field, Val specifies number of bits. + VBR = 2 // A VBR field where Val specifies the width of each chunk. + }; + + BitCodeAbbrevOp(uint64_t V) : Val(V), IsLiteral(true) {} + BitCodeAbbrevOp(Encoding E, uint64_t Data) + : 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()); return Val; } + + bool hasEncodingData() const { return hasEncodingData(getEncoding()); } + static bool hasEncodingData(Encoding E) { + return true; + } +}; + +class BitCodeAbbrev { + SmallVector<BitCodeAbbrevOp, 8> OperandList; +public: + + unsigned getNumOperandInfos() const { return OperandList.size(); } + const BitCodeAbbrevOp &getOperandInfo(unsigned N) const { + return OperandList[N]; + } + + void Add(const BitCodeAbbrevOp &OpInfo) { + OperandList.push_back(OpInfo); + } +}; } // End llvm namespace #endif diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index acb76237f1..0ac71cd9da 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -16,9 +16,6 @@ #define BITSTREAM_READER_H #include "llvm/Bitcode/BitCodes.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/DataTypes.h" -#include <cassert> namespace llvm { diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h index 5de8293278..104508578d 100644 --- a/include/llvm/Bitcode/BitstreamWriter.h +++ b/include/llvm/Bitcode/BitstreamWriter.h @@ -16,9 +16,6 @@ #define BITSTREAM_WRITER_H #include "llvm/Bitcode/BitCodes.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/DataTypes.h" -#include <cassert> #include <vector> namespace llvm { @@ -39,11 +36,14 @@ class BitstreamWriter { struct Block { unsigned PrevCodeSize; unsigned StartSizeWord; + std::vector<BitCodeAbbrev*> PrevAbbrevs; Block(unsigned PCS, unsigned SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {} }; /// BlockScope - This tracks the current blocks that we have entered. std::vector<Block> BlockScope; + + std::vector<BitCodeAbbrev*> CurAbbrevs; public: BitstreamWriter(std::vector<unsigned char> &O) : Out(O), CurBit(0), CurValue(0), CurCodeSize(2) {} @@ -145,6 +145,12 @@ public: EmitVBR(CodeLen, bitc::CodeLenWidth); FlushToWord(); BlockScope.push_back(Block(CurCodeSize, Out.size()/4)); + + // Delete all abbrevs. + for (unsigned i = 0, e = CurAbbrevs.size(); i != e; ++i) + delete CurAbbrevs[i]; + + BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); // Emit a placeholder, which will be replaced when the block is popped. Emit(0, bitc::BlockSizeWidth); @@ -153,8 +159,7 @@ public: void ExitBlock() { assert(!BlockScope.empty() && "Block scope imbalance!"); - Block B = BlockScope.back(); - BlockScope.pop_back(); + const Block &B = BlockScope.back(); // Block tail: // [END_BLOCK, <align4bytes>] @@ -171,8 +176,10 @@ public: Out[ByteNo++] = (unsigned char)(SizeInWords >> 16); Out[ByteNo++] = (unsigned char)(SizeInWords >> 24); - // Restore the outer block's code size. + // Restore the inner block's code size and abbrev table. CurCodeSize = B.PrevCodeSize; + BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + BlockScope.pop_back(); } //===--------------------------------------------------------------------===// @@ -184,7 +191,14 @@ public: void EmitRecord(unsigned Code, SmallVectorImpl<uint64_t> &Vals, unsigned Abbrev = 0) { if (Abbrev) { - assert(0 && "abbrevs not implemented yet!"); + unsigned AbbrevNo = Abbrev-bitc::FIRST_ABBREV; + assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); + BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo]; + assert(0 && "TODO"); + for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) { + } + + } else { // If we don't have an abbrev to use, emit this in its fully unabbreviated // form. @@ -212,6 +226,32 @@ public: EmitVBR(Vals[i], 6); } } + + //===--------------------------------------------------------------------===// + // Abbrev Emission + //===--------------------------------------------------------------------===// + + /// EmitAbbrev - This emits an abbreviation to the stream. Note that this + /// method takes ownership of the specified abbrev. + unsigned EmitAbbrev(BitCodeAbbrev *Abbv) { + // Emit the abbreviation as a record. + EmitCode(bitc::DEFINE_ABBREV); + EmitVBR(Abbv->getNumOperandInfos(), 5); + for (unsigned i = 0, e = 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); + } + } + + CurAbbrevs.push_back(Abbv); + return CurAbbrevs.size()-1+bitc::FIRST_ABBREV; + } }; |