#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"
/// 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<typename uintty>
void EmitRecordWithAbbrevImpl(unsigned Abbrev, SmallVectorImpl<uintty> &Vals,
- StringRef Blob) {
+ StringRef Blob, Optional<unsigned> Code) {
const char *BlobData = Blob.data();
unsigned BlobLen = (unsigned) Blob.size();
unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV;
EmitCode(Abbrev);
+ unsigned i = 0, e = static_cast<unsigned>(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<unsigned>(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");
++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
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.
/// the first entry.
template<typename uintty>
void EmitRecordWithAbbrev(unsigned Abbrev, SmallVectorImpl<uintty> &Vals) {
- EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef());
+ EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(), None);
}
/// EmitRecordWithBlob - Emit the specified record to the stream, using an
template<typename uintty>
void EmitRecordWithBlob(unsigned Abbrev, SmallVectorImpl<uintty> &Vals,
StringRef Blob) {
- EmitRecordWithAbbrevImpl(Abbrev, Vals, Blob);
+ EmitRecordWithAbbrevImpl(Abbrev, Vals, Blob, None);
}
template<typename uintty>
void EmitRecordWithBlob(unsigned Abbrev, SmallVectorImpl<uintty> &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
template<typename uintty>
void EmitRecordWithArray(unsigned Abbrev, SmallVectorImpl<uintty> &Vals,
StringRef Array) {
- EmitRecordWithAbbrevImpl(Abbrev, Vals, Array);
+ EmitRecordWithAbbrevImpl(Abbrev, Vals, Array, None);
}
template<typename uintty>
void EmitRecordWithArray(unsigned Abbrev, SmallVectorImpl<uintty> &Vals,
const char *ArrayData, unsigned ArrayLen) {
- return EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(ArrayData,
- ArrayLen));
+ return EmitRecordWithAbbrevImpl(Abbrev, Vals,
+ StringRef(ArrayData, ArrayLen), None);
}
//===--------------------------------------------------------------------===//