X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FBitcode%2FBitstreamWriter.h;h=31d513cfb02113e3dcf2d415d2f98300ed6750f4;hb=d928fb670fb3b0818fc23738e9c2418980bb141e;hp=aed7c2f48a14c3552dbd3112dd07f57f9c6c8610;hpb=d3ff4a188e823baa141c288d31eb532ddf632b6e;p=oota-llvm.git diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h index aed7c2f48a1..31d513cfb02 100644 --- a/include/llvm/Bitcode/BitstreamWriter.h +++ b/include/llvm/Bitcode/BitstreamWriter.h @@ -15,6 +15,7 @@ #ifndef BITSTREAM_WRITER_H #define BITSTREAM_WRITER_H +#include "llvm/ADT/StringRef.h" #include "llvm/Bitcode/BitCodes.h" #include @@ -79,6 +80,9 @@ public: std::vector &getBuffer() { return Out; } + /// \brief Retrieve the current position in the stream, in bits. + uint64_t GetCurrentBitNo() const { return Out.size() * 8 + CurBit; } + //===--------------------------------------------------------------------===// // Basic Primitives for emitting bits to the stream. //===--------------------------------------------------------------------===// @@ -252,18 +256,23 @@ 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. + template + 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 void EmitAbbreviatedField(const BitCodeAbbrevOp &Op, uintty V) { - if (Op.isLiteral()) { - // If the abbrev specifies the literal value to use, don't emit - // anything. - assert(V == Op.getLiteralValue() && - "Invalid abbrev for record!"); - return; - } - + assert(!Op.isLiteral() && "Literals should use EmitAbbreviatedLiteral!"); + // Encode the value as we are commanded. switch (Op.getEncoding()) { default: assert(0 && "Unknown encoding!"); @@ -278,46 +287,110 @@ private: break; } } -public: - - /// EmitRecord - Emit the specified record to the stream, using an abbrev if - /// we have one to compress the output. + + /// 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. template - void EmitRecord(unsigned Code, SmallVectorImpl &Vals, - unsigned Abbrev = 0) { - if (Abbrev) { - unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV; - assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); - BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo]; + void EmitRecordWithAbbrevImpl(unsigned Abbrev, SmallVectorImpl &Vals, + StringRef Blob) { + 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]; - EmitCode(Abbrev); + EmitCode(Abbrev); - // Insert the code into Vals to treat it uniformly. - Vals.insert(Vals.begin(), Code); - - unsigned RecordIdx = 0; - for (unsigned i = 0, e = static_cast(Abbv->getNumOperandInfos()); - i != e; ++i) { - const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); - if (Op.isLiteral() || Op.getEncoding() != BitCodeAbbrevOp::Array) { - assert(RecordIdx < Vals.size() && "Invalid abbrev/record"); - EmitAbbreviatedField(Op, Vals[RecordIdx]); - ++RecordIdx; + unsigned RecordIdx = 0; + for (unsigned i = 0, e = static_cast(Abbv->getNumOperandInfos()); + 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(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; } else { - // Array case. - assert(i+2 == e && "array op not second to last?"); - const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i); - // Emit a vbr6 to indicate the number of elements present. EmitVBR(static_cast(Vals.size()-RecordIdx), 6); // Emit each field. - for (; RecordIdx != Vals.size(); ++RecordIdx) + 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. + + // Emit a vbr6 to indicate the number of elements present. + if (BlobData) { + EmitVBR(static_cast(BlobLen), 6); + assert(RecordIdx == Vals.size() && + "Blob data and record entries specified for blob operand!"); + } 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]); + + // Know that blob data is consumed for assertion below. + BlobData = 0; + } 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]); + } + } + // Align end to 32-bits. + while (Out.size() & 3) + Out.push_back(0); + + } 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!"); - } else { + } + assert(RecordIdx == Vals.size() && "Not all record operands emitted!"); + assert(BlobData == 0 && + "Blob data specified for record that doesn't use it!"); + } + +public: + + /// EmitRecord - Emit the specified record to the stream, using an abbrev if + /// we have one to compress the output. + template + void EmitRecord(unsigned Code, SmallVectorImpl &Vals, + unsigned Abbrev = 0) { + if (!Abbrev) { // If we don't have an abbrev to use, emit this in its fully unabbreviated // form. EmitCode(bitc::UNABBREV_RECORD); @@ -325,9 +398,53 @@ public: EmitVBR(static_cast(Vals.size()), 6); for (unsigned i = 0, e = static_cast(Vals.size()); i != e; ++i) EmitVBR64(Vals[i], 6); + return; } + + // Insert the code into Vals to treat it uniformly. + Vals.insert(Vals.begin(), Code); + + EmitRecordWithAbbrev(Abbrev, Vals); + } + + /// 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()); + } + + /// 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 + void EmitRecordWithBlob(unsigned Abbrev, SmallVectorImpl &Vals, + StringRef Blob) { + EmitRecordWithAbbrevImpl(Abbrev, Vals, Blob); + } + template + void EmitRecordWithBlob(unsigned Abbrev, SmallVectorImpl &Vals, + const char *BlobData, unsigned BlobLen) { + return EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(BlobData, BlobLen)); } + /// EmitRecordWithArray - Just like EmitRecordWithBlob, works with records + /// that end with an array. + template + void EmitRecordWithArray(unsigned Abbrev, SmallVectorImpl &Vals, + StringRef Array) { + EmitRecordWithAbbrevImpl(Abbrev, Vals, Array); + } + template + void EmitRecordWithArray(unsigned Abbrev, SmallVectorImpl &Vals, + const char *ArrayData, unsigned ArrayLen) { + return EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(ArrayData, + ArrayLen)); + } + //===--------------------------------------------------------------------===// // Abbrev Emission //===--------------------------------------------------------------------===//