X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=include%2Fllvm%2FBitcode%2FBitstreamWriter.h;h=648a06e202e2e3ff44d70da19e908e8995fccd70;hp=250a20fde28c81f337adf2d95d0ac70bffcad928;hb=d08fb26a14516282e7a1a8f82219c3962667ead3;hpb=02a248afe310c86aea682302fc587f22bb999fa7 diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h index 250a20fde28..648a06e202e 100644 --- a/include/llvm/Bitcode/BitstreamWriter.h +++ b/include/llvm/Bitcode/BitstreamWriter.h @@ -12,17 +12,20 @@ // //===----------------------------------------------------------------------===// -#ifndef BITSTREAM_WRITER_H -#define BITSTREAM_WRITER_H +#ifndef LLVM_BITCODE_BITSTREAMWRITER_H +#define LLVM_BITCODE_BITSTREAMWRITER_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 namespace llvm { class BitstreamWriter { - std::vector &Out; + SmallVectorImpl &Out; /// CurBit - Always between 0 and 31 inclusive, specifies the next bit to use. unsigned CurBit; @@ -39,12 +42,12 @@ class BitstreamWriter { unsigned BlockInfoCurBID; /// CurAbbrevs - Abbrevs installed at in this block. - std::vector CurAbbrevs; + std::vector> CurAbbrevs; struct Block { unsigned PrevCodeSize; unsigned StartSizeWord; - std::vector PrevAbbrevs; + std::vector> PrevAbbrevs; Block(unsigned PCS, unsigned SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {} }; @@ -55,40 +58,47 @@ class BitstreamWriter { /// These describe abbreviations that all blocks of the specified ID inherit. struct BlockInfo { unsigned BlockID; - std::vector Abbrevs; + std::vector> Abbrevs; }; std::vector BlockInfoRecords; // BackpatchWord - Backpatch a 32-bit word in the output with the specified // value. void BackpatchWord(unsigned ByteNo, unsigned NewWord) { - Out[ByteNo++] = (unsigned char)(NewWord >> 0); - Out[ByteNo++] = (unsigned char)(NewWord >> 8); - Out[ByteNo++] = (unsigned char)(NewWord >> 16); - Out[ByteNo ] = (unsigned char)(NewWord >> 24); + support::endian::write32le(&Out[ByteNo], NewWord); + } + + void WriteByte(unsigned char Value) { + Out.push_back(Value); + } + + void WriteWord(unsigned Value) { + Value = support::endian::byte_swap(Value); + Out.append(reinterpret_cast(&Value), + reinterpret_cast(&Value + 1)); + } + + unsigned GetBufferOffset() const { + return Out.size(); + } + + unsigned GetWordIndex() const { + unsigned Offset = GetBufferOffset(); + assert((Offset & 3) == 0 && "Not 32-bit aligned"); + return Offset / 4; } public: - explicit BitstreamWriter(std::vector &O) + explicit BitstreamWriter(SmallVectorImpl &O) : Out(O), CurBit(0), CurValue(0), CurCodeSize(2) {} ~BitstreamWriter() { - assert(CurBit == 0 && "Unflused data remaining"); + assert(CurBit == 0 && "Unflushed data remaining"); assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance"); - - // Free the BlockInfoRecords. - while (!BlockInfoRecords.empty()) { - BlockInfo &Info = BlockInfoRecords.back(); - // Free blockinfo abbrev info. - for (unsigned i = 0, e = static_cast(Info.Abbrevs.size()); - i != e; ++i) - Info.Abbrevs[i]->dropRef(); - BlockInfoRecords.pop_back(); - } } /// \brief Retrieve the current position in the stream, in bits. - uint64_t GetCurrentBitNo() const { return Out.size() * 8 + CurBit; } + uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 + CurBit; } //===--------------------------------------------------------------------===// // Basic Primitives for emitting bits to the stream. @@ -104,11 +114,7 @@ public: } // Add the current word. - unsigned V = CurValue; - Out.push_back((unsigned char)(V >> 0)); - Out.push_back((unsigned char)(V >> 8)); - Out.push_back((unsigned char)(V >> 16)); - Out.push_back((unsigned char)(V >> 24)); + WriteWord(CurValue); if (CurBit) CurValue = Val >> (32-CurBit); @@ -128,17 +134,14 @@ public: void FlushToWord() { if (CurBit) { - unsigned V = CurValue; - Out.push_back((unsigned char)(V >> 0)); - Out.push_back((unsigned char)(V >> 8)); - Out.push_back((unsigned char)(V >> 16)); - Out.push_back((unsigned char)(V >> 24)); + 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. @@ -151,10 +154,11 @@ public: } 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); - uint64_t Threshold = 1U << (NumBits-1); + uint32_t Threshold = 1U << (NumBits-1); // Emit the bits with VBR encoding, NumBits-1 bits at a time. while (Val >= Threshold) { @@ -186,7 +190,7 @@ public: i != e; ++i) if (BlockInfoRecords[i].BlockID == BlockID) return &BlockInfoRecords[i]; - return 0; + return nullptr; } void EnterSubblock(unsigned BlockID, unsigned CodeLen) { @@ -197,7 +201,7 @@ public: EmitVBR(CodeLen, bitc::CodeLenWidth); FlushToWord(); - unsigned BlockSizeWordLoc = static_cast(Out.size()); + unsigned BlockSizeWordIndex = GetWordIndex(); unsigned OldCodeSize = CurCodeSize; // Emit a placeholder, which will be replaced when the block is popped. @@ -207,28 +211,19 @@ public: // Push the outer block's abbrev set onto the stack, start out with an // empty abbrev set. - BlockScope.push_back(Block(OldCodeSize, BlockSizeWordLoc/4)); + 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)) { - for (unsigned i = 0, e = static_cast(Info->Abbrevs.size()); - i != e; ++i) { - CurAbbrevs.push_back(Info->Abbrevs[i]); - Info->Abbrevs[i]->addRef(); - } + CurAbbrevs.insert(CurAbbrevs.end(), Info->Abbrevs.begin(), + Info->Abbrevs.end()); } } void ExitBlock() { assert(!BlockScope.empty() && "Block scope imbalance!"); - - // Delete all abbrevs. - for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); - i != e; ++i) - CurAbbrevs[i]->dropRef(); - const Block &B = BlockScope.back(); // Block tail: @@ -237,7 +232,7 @@ public: FlushToWord(); // Compute the size of the block, in words, not counting the size field. - unsigned SizeInWords= static_cast(Out.size())/4-B.StartSizeWord-1; + unsigned SizeInWords = GetWordIndex() - B.StartSizeWord - 1; unsigned ByteNo = B.StartSizeWord*4; // Update the block size field in the header of this sub-block. @@ -245,7 +240,7 @@ public: // Restore the inner block's code size and abbrev table. CurCodeSize = B.PrevCodeSize; - BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + CurAbbrevs = std::move(B.PrevAbbrevs); BlockScope.pop_back(); } @@ -255,7 +250,7 @@ public: private: /// EmitAbbreviatedLiteral - Emit a literal value according to its abbrev - /// record. This is a no-op, since the abbrev specifies the literal to use. + /// record. This is a no-op, since the abbrev specifies the literal to use. template void EmitAbbreviatedLiteral(const BitCodeAbbrevOp &Op, uintty V) { assert(Op.isLiteral() && "Not a literal"); @@ -264,13 +259,13 @@ private: assert(V == Op.getLiteralValue() && "Invalid abbrev for record!"); } - + /// EmitAbbreviatedField - Emit a single scalar field value with the specified /// encoding. template 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!"); @@ -287,25 +282,41 @@ private: 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. + /// 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 void EmitRecordWithAbbrevImpl(unsigned Abbrev, SmallVectorImpl &Vals, - StringRef Blob) { + StringRef Blob, Optional Code) { const char *BlobData = Blob.data(); unsigned BlobLen = (unsigned) Blob.size(); unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV; assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); - BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo]; + const BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo].get(); EmitCode(Abbrev); + unsigned i = 0, e = static_cast(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 (unsigned i = 0, e = static_cast(Abbv->getNumOperandInfos()); - i != e; ++i) { + for (; i != e; ++i) { const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); if (Op.isLiteral()) { assert(RecordIdx < Vals.size() && "Invalid abbrev/record"); @@ -313,7 +324,7 @@ private: ++RecordIdx; } else if (Op.getEncoding() == BitCodeAbbrevOp::Array) { // Array case. - assert(i+2 == e && "array op not second to last?"); + 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 @@ -323,13 +334,13 @@ private: "Blob data and record entries specified for array!"); // Emit a vbr6 to indicate the number of elements present. EmitVBR(static_cast(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 = 0; + BlobData = nullptr; } else { // Emit a vbr6 to indicate the number of elements present. EmitVBR(static_cast(Vals.size()-RecordIdx), 6); @@ -341,7 +352,7 @@ private: } else if (Op.getEncoding() == BitCodeAbbrevOp::Blob) { // If this record has blob data, emit it, otherwise we must have record // entries to encode this way. - + // Emit a vbr6 to indicate the number of elements present. if (BlobData) { EmitVBR(static_cast(BlobLen), 6); @@ -350,28 +361,28 @@ private: } else { EmitVBR(static_cast(Vals.size()-RecordIdx), 6); } - + // Flush to a 32-bit alignment boundary. FlushToWord(); - assert((Out.size() & 3) == 0 && "Not 32-bit aligned"); // Emit each field as a literal byte. if (BlobData) { for (unsigned i = 0; i != BlobLen; ++i) - Out.push_back((unsigned char)BlobData[i]); - + WriteByte((unsigned char)BlobData[i]); + // Know that blob data is consumed for assertion below. - BlobData = 0; + BlobData = nullptr; } else { for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx) { - assert(Vals[RecordIdx] < 256 && "Value too large to emit as blob"); - Out.push_back((unsigned char)Vals[RecordIdx]); + assert(isUInt<8>(Vals[RecordIdx]) && + "Value too large to emit as blob"); + WriteByte((unsigned char)Vals[RecordIdx]); } } + // Align end to 32-bits. - while (Out.size() & 3) - Out.push_back(0); - + while (GetBufferOffset() & 3) + WriteByte(0); } else { // Single scalar field. assert(RecordIdx < Vals.size() && "Invalid abbrev/record"); EmitAbbreviatedField(Op, Vals[RecordIdx]); @@ -379,10 +390,10 @@ private: } } assert(RecordIdx == Vals.size() && "Not all record operands emitted!"); - assert(BlobData == 0 && + assert(BlobData == nullptr && "Blob data specified for record that doesn't use it!"); } - + public: /// EmitRecord - Emit the specified record to the stream, using an abbrev if @@ -401,20 +412,17 @@ public: return; } - // Insert the code into Vals to treat it uniformly. - Vals.insert(Vals.begin(), Code); - - EmitRecordWithAbbrev(Abbrev, Vals); + EmitRecordWithAbbrevImpl(Abbrev, 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 void EmitRecordWithAbbrev(unsigned Abbrev, SmallVectorImpl &Vals) { - EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef()); + EmitRecordWithAbbrevImpl(Abbrev, 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 @@ -423,12 +431,13 @@ public: template void EmitRecordWithBlob(unsigned Abbrev, SmallVectorImpl &Vals, StringRef Blob) { - EmitRecordWithAbbrevImpl(Abbrev, Vals, Blob); + EmitRecordWithAbbrevImpl(Abbrev, Vals, Blob, None); } template void EmitRecordWithBlob(unsigned Abbrev, SmallVectorImpl &Vals, const char *BlobData, unsigned BlobLen) { - return EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(BlobData, BlobLen)); + return EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(BlobData, BlobLen), + None); } /// EmitRecordWithArray - Just like EmitRecordWithBlob, works with records @@ -436,15 +445,15 @@ public: template void EmitRecordWithArray(unsigned Abbrev, SmallVectorImpl &Vals, StringRef Array) { - EmitRecordWithAbbrevImpl(Abbrev, Vals, Array); + EmitRecordWithAbbrevImpl(Abbrev, Vals, Array, None); } template void EmitRecordWithArray(unsigned Abbrev, SmallVectorImpl &Vals, const char *ArrayData, unsigned ArrayLen) { - return EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(ArrayData, - ArrayLen)); + return EmitRecordWithAbbrevImpl(Abbrev, Vals, + StringRef(ArrayData, ArrayLen), None); } - + //===--------------------------------------------------------------------===// // Abbrev Emission //===--------------------------------------------------------------------===// @@ -486,7 +495,7 @@ public: /// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK. void EnterBlockInfoBlock(unsigned CodeWidth) { EnterSubblock(bitc::BLOCKINFO_BLOCK_ID, CodeWidth); - BlockInfoCurBID = -1U; + BlockInfoCurBID = ~0U; } private: /// SwitchToBlockID - If we aren't already talking about the specified block @@ -504,7 +513,7 @@ private: return *BI; // Otherwise, add a new record. - BlockInfoRecords.push_back(BlockInfo()); + BlockInfoRecords.emplace_back(); BlockInfoRecords.back().BlockID = BlockID; return BlockInfoRecords.back(); }