From: Chris Lattner Date: Mon, 6 Apr 2009 22:26:26 +0000 (+0000) Subject: Add a new EmitRecordWithBlob API that allows a blob to be emitted X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=298a82dd0d042479e419c4fa2219c1a08c1becc4;p=oota-llvm.git Add a new EmitRecordWithBlob API that allows a blob to be emitted without converting each byte to a uint64_t to stick in a SmallVector. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@68469 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h index 66384f8b31c..78b4f5e02ca 100644 --- a/include/llvm/Bitcode/BitstreamWriter.h +++ b/include/llvm/Bitcode/BitstreamWriter.h @@ -284,33 +284,19 @@ private: } } -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 the record. 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); - EmitVBR(Code, 6); - EmitVBR(static_cast(Vals.size()), 6); - for (unsigned i = 0, e = static_cast(Vals.size()); i != e; ++i) - EmitVBR64(Vals[i], 6); - return; - } - + void EmitRecordWithAbbrevImpl(unsigned Abbrev, SmallVectorImpl &Vals, + const char *BlobData, unsigned BlobLen) { unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV; assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo]; 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) { @@ -324,23 +310,57 @@ public: 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) - EmitAbbreviatedField(EltEnc, Vals[RecordIdx]); + // 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 { + // Emit a vbr6 to indicate the number of elements present. + EmitVBR(static_cast(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. + // Emit a vbr6 to indicate the number of elements present. - EmitVBR(static_cast(Vals.size()-RecordIdx), 6); + 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. - for (; RecordIdx != Vals.size(); ++RecordIdx) { - assert(Vals[RecordIdx] < 256 && "Value too large to emit as blob"); - Out.push_back((unsigned char)Vals[RecordIdx]); + 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) @@ -353,8 +373,61 @@ public: } } 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); + EmitVBR(Code, 6); + 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, 0, 0); + } + + /// 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, + const char *BlobData, unsigned BlobLen) { + EmitRecordWithAbbrevImpl(Abbrev, Vals, BlobData, BlobLen); } + /// EmitRecordWithArray - Just like EmitRecordWithBlob, works with records + /// that end with an array. + template + void EmitRecordWithArray(unsigned Abbrev, SmallVectorImpl &Vals, + const char *ArrayData, unsigned ArrayLen) { + EmitRecordWithAbbrevImpl(Abbrev, Vals, ArrayData, ArrayLen); + } + //===--------------------------------------------------------------------===// // Abbrev Emission //===--------------------------------------------------------------------===//