BitcodeWriter: Simplify and test writing blobs, NFC
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Sun, 27 Mar 2016 23:04:04 +0000 (23:04 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Sun, 27 Mar 2016 23:04:04 +0000 (23:04 +0000)
Split helper out of EmitRecordWithAbbrevImpl called emitBlob to reduce
code duplication, and add a few tests for it.

No functionality change intended.

llvm-svn: 264550

llvm/include/llvm/Bitcode/BitstreamWriter.h
llvm/unittests/Bitcode/BitstreamWriterTest.cpp [new file with mode: 0644]
llvm/unittests/Bitcode/CMakeLists.txt

index 438f4a6..d613f5e 100644 (file)
@@ -361,36 +361,17 @@ private:
         // 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<uint32_t>(BlobLen), 6);
           assert(RecordIdx == Vals.size() &&
                  "Blob data and record entries specified for blob operand!");
-        } else {
-          EmitVBR(static_cast<uint32_t>(Vals.size()-RecordIdx), 6);
-        }
-
-        // Flush to a 32-bit alignment boundary.
-        FlushToWord();
-
-        // Emit each field as a literal byte.
-        if (BlobData) {
-          for (unsigned i = 0; i != BlobLen; ++i)
-            WriteByte((unsigned char)BlobData[i]);
 
-          // Know that blob data is consumed for assertion below.
+          assert(Blob.data() == BlobData && "BlobData got moved");
+          assert(Blob.size() == BlobLen && "BlobLen got changed");
+          emitBlob(Blob);
           BlobData = nullptr;
         } else {
-          for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx) {
-            assert(isUInt<8>(Vals[RecordIdx]) &&
-                   "Value too large to emit as blob");
-            WriteByte((unsigned char)Vals[RecordIdx]);
-          }
+          emitBlob(Vals.slice(RecordIdx));
         }
-
-        // Align end to 32-bits.
-        while (GetBufferOffset() & 3)
-          WriteByte(0);
       } else {  // Single scalar field.
         assert(RecordIdx < Vals.size() && "Invalid abbrev/record");
         EmitAbbreviatedField(Op, Vals[RecordIdx]);
@@ -403,6 +384,30 @@ private:
   }
 
 public:
+  /// Emit a blob, including flushing before and tail-padding.
+  template <class UIntTy>
+  void emitBlob(ArrayRef<UIntTy> Bytes, bool ShouldEmitSize = true) {
+    // Emit a vbr6 to indicate the number of elements present.
+    if (ShouldEmitSize)
+      EmitVBR(static_cast<uint32_t>(Bytes.size()), 6);
+
+    // Flush to a 32-bit alignment boundary.
+    FlushToWord();
+
+    // Emit literal bytes.
+    for (const auto &B : Bytes) {
+      assert(isUInt<8>(B) && "Value too large to emit as byte");
+      WriteByte((unsigned char)B);
+    }
+
+    // Align end to 32-bits.
+    while (GetBufferOffset() & 3)
+      WriteByte(0);
+  }
+  void emitBlob(StringRef Bytes, bool ShouldEmitSize = true) {
+    emitBlob(makeArrayRef((const uint8_t *)Bytes.data(), Bytes.size()),
+             ShouldEmitSize);
+  }
 
   /// EmitRecord - Emit the specified record to the stream, using an abbrev if
   /// we have one to compress the output.
diff --git a/llvm/unittests/Bitcode/BitstreamWriterTest.cpp b/llvm/unittests/Bitcode/BitstreamWriterTest.cpp
new file mode 100644 (file)
index 0000000..f17cc15
--- /dev/null
@@ -0,0 +1,59 @@
+//===- BitstreamWriterTest.cpp - Tests for BitstreamWriter ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(BitstreamWriterTest, emitBlob) {
+  SmallString<64> Buffer;
+  BitstreamWriter W(Buffer);
+  W.emitBlob("str", /* ShouldEmitSize */ false);
+  EXPECT_EQ(StringRef("str\0", 4), Buffer);
+}
+
+TEST(BitstreamWriterTest, emitBlobWithSize) {
+  SmallString<64> Buffer;
+  {
+    BitstreamWriter W(Buffer);
+    W.emitBlob("str");
+  }
+  SmallString<64> Expected;
+  {
+    BitstreamWriter W(Expected);
+    W.EmitVBR(3, 6);
+    W.FlushToWord();
+    W.Emit('s', 8);
+    W.Emit('t', 8);
+    W.Emit('r', 8);
+    W.Emit(0, 8);
+  }
+  EXPECT_EQ(StringRef(Expected), Buffer);
+}
+
+TEST(BitstreamWriterTest, emitBlobEmpty) {
+  SmallString<64> Buffer;
+  BitstreamWriter W(Buffer);
+  W.emitBlob("", /* ShouldEmitSize */ false);
+  EXPECT_EQ(StringRef(""), Buffer);
+}
+
+TEST(BitstreamWriterTest, emitBlob4ByteAligned) {
+  SmallString<64> Buffer;
+  BitstreamWriter W(Buffer);
+  W.emitBlob("str0", /* ShouldEmitSize */ false);
+  EXPECT_EQ(StringRef("str0"), Buffer);
+}
+
+} // end namespace
index 09cbcdc..4d06f80 100644 (file)
@@ -9,4 +9,5 @@ set(LLVM_LINK_COMPONENTS
 add_llvm_unittest(BitcodeTests
   BitReaderTest.cpp
   BitstreamReaderTest.cpp
+  BitstreamWriterTest.cpp
   )