xref: /llvm-project/llvm/unittests/Bitstream/BitstreamReaderTest.cpp (revision 38818b60c58c76ba89b990978cdfd2d7b6799260)
1e0308279SFrancis Visoiu Mistrih //===- BitstreamReaderTest.cpp - Tests for BitstreamReader ----------------===//
2e0308279SFrancis Visoiu Mistrih //
3e0308279SFrancis Visoiu Mistrih // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e0308279SFrancis Visoiu Mistrih // See https://llvm.org/LICENSE.txt for license information.
5e0308279SFrancis Visoiu Mistrih // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e0308279SFrancis Visoiu Mistrih //
7e0308279SFrancis Visoiu Mistrih //===----------------------------------------------------------------------===//
8e0308279SFrancis Visoiu Mistrih 
9e0308279SFrancis Visoiu Mistrih #include "llvm/Bitstream/BitstreamReader.h"
10e0308279SFrancis Visoiu Mistrih #include "llvm/ADT/STLExtras.h"
11e0308279SFrancis Visoiu Mistrih #include "llvm/Bitstream/BitstreamWriter.h"
12e0308279SFrancis Visoiu Mistrih #include "gtest/gtest.h"
13e0308279SFrancis Visoiu Mistrih 
14e0308279SFrancis Visoiu Mistrih using namespace llvm;
15e0308279SFrancis Visoiu Mistrih 
16e0308279SFrancis Visoiu Mistrih namespace {
17e0308279SFrancis Visoiu Mistrih 
TEST(BitstreamReaderTest,AtEndOfStream)18e0308279SFrancis Visoiu Mistrih TEST(BitstreamReaderTest, AtEndOfStream) {
19e0308279SFrancis Visoiu Mistrih   uint8_t Bytes[4] = {
20e0308279SFrancis Visoiu Mistrih     0x00, 0x01, 0x02, 0x03
21e0308279SFrancis Visoiu Mistrih   };
22e0308279SFrancis Visoiu Mistrih   BitstreamCursor Cursor(Bytes);
23e0308279SFrancis Visoiu Mistrih 
24e0308279SFrancis Visoiu Mistrih   EXPECT_FALSE(Cursor.AtEndOfStream());
25e0308279SFrancis Visoiu Mistrih   Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(8);
26e0308279SFrancis Visoiu Mistrih   EXPECT_TRUE((bool)MaybeRead);
27e0308279SFrancis Visoiu Mistrih   EXPECT_FALSE(Cursor.AtEndOfStream());
28e0308279SFrancis Visoiu Mistrih   MaybeRead = Cursor.Read(24);
29e0308279SFrancis Visoiu Mistrih   EXPECT_TRUE((bool)MaybeRead);
30e0308279SFrancis Visoiu Mistrih   EXPECT_TRUE(Cursor.AtEndOfStream());
31e0308279SFrancis Visoiu Mistrih 
32e0308279SFrancis Visoiu Mistrih   EXPECT_FALSE(Cursor.JumpToBit(0));
33e0308279SFrancis Visoiu Mistrih   EXPECT_FALSE(Cursor.AtEndOfStream());
34e0308279SFrancis Visoiu Mistrih 
35e0308279SFrancis Visoiu Mistrih   EXPECT_FALSE(Cursor.JumpToBit(32));
36e0308279SFrancis Visoiu Mistrih   EXPECT_TRUE(Cursor.AtEndOfStream());
37e0308279SFrancis Visoiu Mistrih }
38e0308279SFrancis Visoiu Mistrih 
TEST(BitstreamReaderTest,AtEndOfStreamJump)39e0308279SFrancis Visoiu Mistrih TEST(BitstreamReaderTest, AtEndOfStreamJump) {
40e0308279SFrancis Visoiu Mistrih   uint8_t Bytes[4] = {
41e0308279SFrancis Visoiu Mistrih     0x00, 0x01, 0x02, 0x03
42e0308279SFrancis Visoiu Mistrih   };
43e0308279SFrancis Visoiu Mistrih   BitstreamCursor Cursor(Bytes);
44e0308279SFrancis Visoiu Mistrih 
45e0308279SFrancis Visoiu Mistrih   EXPECT_FALSE(Cursor.JumpToBit(32));
46e0308279SFrancis Visoiu Mistrih   EXPECT_TRUE(Cursor.AtEndOfStream());
47e0308279SFrancis Visoiu Mistrih }
48e0308279SFrancis Visoiu Mistrih 
TEST(BitstreamReaderTest,AtEndOfStreamEmpty)49e0308279SFrancis Visoiu Mistrih TEST(BitstreamReaderTest, AtEndOfStreamEmpty) {
50e0308279SFrancis Visoiu Mistrih   BitstreamCursor Cursor(ArrayRef<uint8_t>{});
51e0308279SFrancis Visoiu Mistrih 
52e0308279SFrancis Visoiu Mistrih   EXPECT_TRUE(Cursor.AtEndOfStream());
53e0308279SFrancis Visoiu Mistrih }
54e0308279SFrancis Visoiu Mistrih 
TEST(BitstreamReaderTest,getCurrentByteNo)55e0308279SFrancis Visoiu Mistrih TEST(BitstreamReaderTest, getCurrentByteNo) {
56e0308279SFrancis Visoiu Mistrih   uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03};
57e0308279SFrancis Visoiu Mistrih   SimpleBitstreamCursor Cursor(Bytes);
58e0308279SFrancis Visoiu Mistrih 
59e0308279SFrancis Visoiu Mistrih   for (unsigned I = 0, E = 32; I != E; ++I) {
60e0308279SFrancis Visoiu Mistrih     EXPECT_EQ(I / 8, Cursor.getCurrentByteNo());
61e0308279SFrancis Visoiu Mistrih     Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(1);
62e0308279SFrancis Visoiu Mistrih     EXPECT_TRUE((bool)MaybeRead);
63e0308279SFrancis Visoiu Mistrih   }
64e0308279SFrancis Visoiu Mistrih   EXPECT_EQ(4u, Cursor.getCurrentByteNo());
65e0308279SFrancis Visoiu Mistrih }
66e0308279SFrancis Visoiu Mistrih 
TEST(BitstreamReaderTest,getPointerToByte)67e0308279SFrancis Visoiu Mistrih TEST(BitstreamReaderTest, getPointerToByte) {
68e0308279SFrancis Visoiu Mistrih   uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
69e0308279SFrancis Visoiu Mistrih   SimpleBitstreamCursor Cursor(Bytes);
70e0308279SFrancis Visoiu Mistrih 
71e0308279SFrancis Visoiu Mistrih   for (unsigned I = 0, E = 8; I != E; ++I) {
72e0308279SFrancis Visoiu Mistrih     EXPECT_EQ(Bytes + I, Cursor.getPointerToByte(I, 1));
73e0308279SFrancis Visoiu Mistrih   }
74e0308279SFrancis Visoiu Mistrih }
75e0308279SFrancis Visoiu Mistrih 
TEST(BitstreamReaderTest,getPointerToBit)76e0308279SFrancis Visoiu Mistrih TEST(BitstreamReaderTest, getPointerToBit) {
77e0308279SFrancis Visoiu Mistrih   uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
78e0308279SFrancis Visoiu Mistrih   SimpleBitstreamCursor Cursor(Bytes);
79e0308279SFrancis Visoiu Mistrih 
80e0308279SFrancis Visoiu Mistrih   for (unsigned I = 0, E = 8; I != E; ++I) {
81e0308279SFrancis Visoiu Mistrih     EXPECT_EQ(Bytes + I, Cursor.getPointerToBit(I * 8, 1));
82e0308279SFrancis Visoiu Mistrih   }
83e0308279SFrancis Visoiu Mistrih }
84e0308279SFrancis Visoiu Mistrih 
TEST(BitstreamReaderTest,readRecordWithBlobWhileStreaming)85e0308279SFrancis Visoiu Mistrih TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) {
86e0308279SFrancis Visoiu Mistrih   SmallVector<uint8_t, 1> BlobData;
87e0308279SFrancis Visoiu Mistrih   for (unsigned I = 0, E = 1024; I != E; ++I)
88e0308279SFrancis Visoiu Mistrih     BlobData.push_back(I);
89e0308279SFrancis Visoiu Mistrih 
90e0308279SFrancis Visoiu Mistrih   // Try a bunch of different sizes.
91e0308279SFrancis Visoiu Mistrih   const unsigned Magic = 0x12345678;
92e0308279SFrancis Visoiu Mistrih   const unsigned BlockID = bitc::FIRST_APPLICATION_BLOCKID;
93e0308279SFrancis Visoiu Mistrih   const unsigned RecordID = 1;
94e0308279SFrancis Visoiu Mistrih   for (unsigned I = 0, BlobSize = 0, E = BlobData.size(); BlobSize < E;
95e0308279SFrancis Visoiu Mistrih        BlobSize += ++I) {
96e0308279SFrancis Visoiu Mistrih     StringRef BlobIn((const char *)BlobData.begin(), BlobSize);
97e0308279SFrancis Visoiu Mistrih 
98e0308279SFrancis Visoiu Mistrih     // Write the bitcode.
99e0308279SFrancis Visoiu Mistrih     SmallVector<char, 1> Buffer;
100e0308279SFrancis Visoiu Mistrih     unsigned AbbrevID;
101e0308279SFrancis Visoiu Mistrih     {
102e0308279SFrancis Visoiu Mistrih       BitstreamWriter Stream(Buffer);
103e0308279SFrancis Visoiu Mistrih       Stream.Emit(Magic, 32);
104e0308279SFrancis Visoiu Mistrih       Stream.EnterSubblock(BlockID, 3);
105e0308279SFrancis Visoiu Mistrih 
106e0308279SFrancis Visoiu Mistrih       auto Abbrev = std::make_shared<BitCodeAbbrev>();
107e0308279SFrancis Visoiu Mistrih       Abbrev->Add(BitCodeAbbrevOp(RecordID));
108e0308279SFrancis Visoiu Mistrih       Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
109e0308279SFrancis Visoiu Mistrih       AbbrevID = Stream.EmitAbbrev(std::move(Abbrev));
110e0308279SFrancis Visoiu Mistrih       unsigned Record[] = {RecordID};
111*38818b60Sserge-sans-paille       Stream.EmitRecordWithBlob(AbbrevID, ArrayRef(Record), BlobIn);
112e0308279SFrancis Visoiu Mistrih 
113e0308279SFrancis Visoiu Mistrih       Stream.ExitBlock();
114e0308279SFrancis Visoiu Mistrih     }
115e0308279SFrancis Visoiu Mistrih 
116e0308279SFrancis Visoiu Mistrih     // Stream the buffer into the reader.
117e0308279SFrancis Visoiu Mistrih     BitstreamCursor Stream(
118e0308279SFrancis Visoiu Mistrih         ArrayRef<uint8_t>((const uint8_t *)Buffer.begin(), Buffer.size()));
119e0308279SFrancis Visoiu Mistrih 
120e0308279SFrancis Visoiu Mistrih     // Header.  Included in test so that we can run llvm-bcanalyzer to debug
121e0308279SFrancis Visoiu Mistrih     // when there are problems.
122e0308279SFrancis Visoiu Mistrih     Expected<SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(32);
123e0308279SFrancis Visoiu Mistrih     ASSERT_TRUE((bool)MaybeRead);
124e0308279SFrancis Visoiu Mistrih     ASSERT_EQ(Magic, MaybeRead.get());
125e0308279SFrancis Visoiu Mistrih 
126e0308279SFrancis Visoiu Mistrih     // Block.
127e0308279SFrancis Visoiu Mistrih     Expected<BitstreamEntry> MaybeEntry =
128e0308279SFrancis Visoiu Mistrih         Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
129e0308279SFrancis Visoiu Mistrih     ASSERT_TRUE((bool)MaybeEntry);
130e0308279SFrancis Visoiu Mistrih     BitstreamEntry Entry = MaybeEntry.get();
131e0308279SFrancis Visoiu Mistrih     ASSERT_EQ(BitstreamEntry::SubBlock, Entry.Kind);
132e0308279SFrancis Visoiu Mistrih     ASSERT_EQ(BlockID, Entry.ID);
133e0308279SFrancis Visoiu Mistrih     ASSERT_FALSE(Stream.EnterSubBlock(BlockID));
134e0308279SFrancis Visoiu Mistrih 
135e0308279SFrancis Visoiu Mistrih     // Abbreviation.
136e0308279SFrancis Visoiu Mistrih     MaybeEntry = Stream.advance();
137e0308279SFrancis Visoiu Mistrih     ASSERT_TRUE((bool)MaybeEntry);
138e0308279SFrancis Visoiu Mistrih     Entry = MaybeEntry.get();
139e0308279SFrancis Visoiu Mistrih     ASSERT_EQ(BitstreamEntry::Record, Entry.Kind);
140e0308279SFrancis Visoiu Mistrih     ASSERT_EQ(AbbrevID, Entry.ID);
141e0308279SFrancis Visoiu Mistrih 
142e0308279SFrancis Visoiu Mistrih     // Record.
143e0308279SFrancis Visoiu Mistrih     StringRef BlobOut;
144e0308279SFrancis Visoiu Mistrih     SmallVector<uint64_t, 1> Record;
145e0308279SFrancis Visoiu Mistrih     Expected<unsigned> MaybeRecord =
146e0308279SFrancis Visoiu Mistrih         Stream.readRecord(Entry.ID, Record, &BlobOut);
147e0308279SFrancis Visoiu Mistrih     ASSERT_TRUE((bool)MaybeRecord);
148e0308279SFrancis Visoiu Mistrih     ASSERT_EQ(RecordID, MaybeRecord.get());
149e0308279SFrancis Visoiu Mistrih     EXPECT_TRUE(Record.empty());
150e0308279SFrancis Visoiu Mistrih     EXPECT_EQ(BlobIn, BlobOut);
151e0308279SFrancis Visoiu Mistrih   }
152e0308279SFrancis Visoiu Mistrih }
153e0308279SFrancis Visoiu Mistrih 
TEST(BitstreamReaderTest,shortRead)154e0308279SFrancis Visoiu Mistrih TEST(BitstreamReaderTest, shortRead) {
155e0308279SFrancis Visoiu Mistrih   uint8_t Bytes[] = {8, 7, 6, 5, 4, 3, 2, 1};
156e0308279SFrancis Visoiu Mistrih   for (unsigned I = 1; I != 8; ++I) {
157e0308279SFrancis Visoiu Mistrih     SimpleBitstreamCursor Cursor(ArrayRef<uint8_t>(Bytes, I));
158e0308279SFrancis Visoiu Mistrih     Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(8);
159e0308279SFrancis Visoiu Mistrih     ASSERT_TRUE((bool)MaybeRead);
160e0308279SFrancis Visoiu Mistrih     EXPECT_EQ(8ull, MaybeRead.get());
161e0308279SFrancis Visoiu Mistrih   }
162e0308279SFrancis Visoiu Mistrih }
163e0308279SFrancis Visoiu Mistrih 
1646aa050a6SNathan James static_assert(std::is_trivially_copyable_v<BitCodeAbbrevOp>,
165e0308279SFrancis Visoiu Mistrih               "trivially copyable");
166e0308279SFrancis Visoiu Mistrih 
167e0308279SFrancis Visoiu Mistrih } // end anonymous namespace
168