diff --git a/llvm/include/llvm/Bitstream/BitCodes.h b/llvm/include/llvm/Bitstream/BitCodes.h --- a/llvm/include/llvm/Bitstream/BitCodes.h +++ b/llvm/include/llvm/Bitstream/BitCodes.h @@ -40,11 +40,12 @@ VBR = 2, // A VBR field where Val specifies the width of each chunk. Array = 3, // A sequence of fields, next field species elt encoding. Char6 = 4, // A 6-bit fixed field which maps to [a-zA-Z0-9._]. - Blob = 5 // 32-bit aligned array of 8-bit characters. + Blob = 5, // 32-bit aligned array of 8-bit characters. + VBRZ = 6, // A nullable VBR field, Val specifies the width of each chunk. }; static bool isValidEncoding(uint64_t E) { - return E >= 1 && E <= 5; + return E >= 1 && E <= 6; } explicit BitCodeAbbrevOp(uint64_t V) : Val(V), IsLiteral(true) {} @@ -69,6 +70,7 @@ switch (E) { case Fixed: case VBR: + case VBRZ: return true; case Array: case Char6: diff --git a/llvm/include/llvm/Bitstream/BitstreamReader.h b/llvm/include/llvm/Bitstream/BitstreamReader.h --- a/llvm/include/llvm/Bitstream/BitstreamReader.h +++ b/llvm/include/llvm/Bitstream/BitstreamReader.h @@ -226,7 +226,15 @@ return R; } - Expected ReadVBR(const unsigned NumBits) { + Expected ReadVBR(const unsigned NumBits, bool ZeroBit = false) { + if (ZeroBit) { + Expected MaybeRead = Read(1); + if (!MaybeRead) + return MaybeRead; + if (*MaybeRead == 0) + return 0; + } + Expected MaybeRead = Read(NumBits); if (!MaybeRead) return MaybeRead; @@ -261,8 +269,16 @@ // Read a VBR that may have a value up to 64-bits in size. The chunk size of // the VBR must still be <= 32 bits though. - Expected ReadVBR64(const unsigned NumBits) { - Expected MaybeRead = Read(NumBits); + Expected ReadVBR64(const unsigned NumBits, bool ZeroBit = false) { + if (ZeroBit) { + Expected MaybeRead = Read(1); + if (!MaybeRead) + return MaybeRead; + if (*MaybeRead == 0) + return 0; + } + + Expected MaybeRead = Read(NumBits); if (!MaybeRead) return MaybeRead; uint32_t Piece = MaybeRead.get(); diff --git a/llvm/include/llvm/Bitstream/BitstreamWriter.h b/llvm/include/llvm/Bitstream/BitstreamWriter.h --- a/llvm/include/llvm/Bitstream/BitstreamWriter.h +++ b/llvm/include/llvm/Bitstream/BitstreamWriter.h @@ -221,7 +221,13 @@ } } - void EmitVBR(uint32_t Val, unsigned NumBits) { + void EmitVBR(uint32_t Val, unsigned NumBits, bool ZeroBit = false) { + if (ZeroBit) { + Emit(Val != 0, 1); + if (Val == 0) + return; + } + assert(NumBits <= 32 && "Too many bits to emit!"); uint32_t Threshold = 1U << (NumBits-1); @@ -234,10 +240,16 @@ Emit(Val, NumBits); } - void EmitVBR64(uint64_t Val, unsigned NumBits) { + void EmitVBR64(uint64_t Val, unsigned NumBits, bool ZeroBit = false) { assert(NumBits <= 32 && "Too many bits to emit!"); if ((uint32_t)Val == Val) - return EmitVBR((uint32_t)Val, NumBits); + return EmitVBR((uint32_t)Val, NumBits, ZeroBit); + + if (ZeroBit) { + Emit(Val != 0, 1); + if (Val == 0) + return; + } uint32_t Threshold = 1U << (NumBits-1); @@ -357,6 +369,10 @@ if (Op.getEncodingData()) EmitVBR64(V, (unsigned)Op.getEncodingData()); break; + case BitCodeAbbrevOp::VBRZ: + if (Op.getEncodingData()) + EmitVBR64(V, (unsigned)Op.getEncodingData(), /*ZeroBit=*/true); + break; case BitCodeAbbrevOp::Char6: Emit(BitCodeAbbrevOp::EncodeChar6((char)V), 6); break; @@ -491,7 +507,7 @@ EmitVBR(Code, 6); EmitVBR(Count, 6); for (unsigned i = 0, e = Count; i != e; ++i) - EmitVBR64(Vals[i], 6); + EmitVBR64(Vals[i], 6, /*ZeroBit=*/true); return; } diff --git a/llvm/lib/Bitstream/Reader/BitstreamReader.cpp b/llvm/lib/Bitstream/Reader/BitstreamReader.cpp --- a/llvm/lib/Bitstream/Reader/BitstreamReader.cpp +++ b/llvm/lib/Bitstream/Reader/BitstreamReader.cpp @@ -82,6 +82,9 @@ case BitCodeAbbrevOp::VBR: assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); return Cursor.ReadVBR64((unsigned)Op.getEncodingData()); + case BitCodeAbbrevOp::VBRZ: + assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); + return Cursor.ReadVBR64((unsigned)Op.getEncodingData(), /*ZeroBit=*/true); case BitCodeAbbrevOp::Char6: if (Expected Res = Cursor.Read(6)) return BitCodeAbbrevOp::DecodeChar6(Res.get()); @@ -104,7 +107,7 @@ return MaybeVBR.takeError(); unsigned NumElts = MaybeVBR.get(); for (unsigned i = 0; i != NumElts; ++i) - if (Expected Res = ReadVBR64(6)) + if (Expected Res = ReadVBR64(6, /*ZeroBit=*/true)) ; // Skip! else return Res.takeError(); @@ -169,10 +172,12 @@ return std::move(Err); break; case BitCodeAbbrevOp::VBR: + case BitCodeAbbrevOp::VBRZ: assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize); for (; NumElts; --NumElts) - if (Expected Res = - ReadVBR64((unsigned)EltEnc.getEncodingData())) + if (Expected Res = ReadVBR64( + (unsigned)EltEnc.getEncodingData(), + /*ZeroBit=*/EltEnc.getEncoding() == BitCodeAbbrevOp::VBRZ)) ; // Skip! else return Res.takeError(); @@ -229,7 +234,7 @@ Vals.reserve(Vals.size() + NumElts); for (unsigned i = 0; i != NumElts; ++i) - if (Expected MaybeVal = ReadVBR64(6)) + if (Expected MaybeVal = ReadVBR64(6, /*ZeroBit=*/true)) Vals.push_back(MaybeVal.get()); else return MaybeVal.takeError(); @@ -306,9 +311,11 @@ return MaybeVal.takeError(); break; case BitCodeAbbrevOp::VBR: + case BitCodeAbbrevOp::VBRZ: for (; NumElts; --NumElts) - if (Expected MaybeVal = - ReadVBR64((unsigned)EltEnc.getEncodingData())) + if (Expected MaybeVal = ReadVBR64( + (unsigned)EltEnc.getEncodingData(), + /*ZeroBit=*/EltEnc.getEncoding() == BitCodeAbbrevOp::VBRZ)) Vals.push_back(MaybeVal.get()); else return MaybeVal.takeError();