Skip to content

Commit 88823d0

Browse files
authored
[clang][bytecode][NFC] Switch BitcastBuffer to SmallVector (llvm#114677)
This is a little easier to work with since we are guaranteed that the item type of the vector is byte sized and not something else.
1 parent e102338 commit 88823d0

File tree

2 files changed

+31
-23
lines changed

2 files changed

+31
-23
lines changed

clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -83,39 +83,33 @@ static void swapBytes(std::byte *M, size_t N) {
8383
/// have indeterminate value.
8484
/// All offsets are in bits.
8585
struct BitcastBuffer {
86-
llvm::BitVector Data;
86+
size_t SizeInBits = 0;
87+
llvm::SmallVector<std::byte> Data;
8788

8889
BitcastBuffer() = default;
8990

90-
size_t size() const { return Data.size(); }
91+
size_t size() const { return SizeInBits; }
9192

92-
const std::byte *data() const {
93-
unsigned NBytes = Data.size() / 8;
94-
unsigned BitVectorWordSize = sizeof(uintptr_t);
95-
bool FullWord = (NBytes % BitVectorWordSize == 0);
96-
97-
// llvm::BitVector uses 64-bit fields internally, so when we have
98-
// fewer bytes than that, we need to compensate for that on
99-
// big endian hosts.
100-
unsigned DataPlus;
101-
if (llvm::sys::IsBigEndianHost)
102-
DataPlus = BitVectorWordSize - (NBytes % BitVectorWordSize);
103-
else
104-
DataPlus = 0;
105-
106-
return reinterpret_cast<const std::byte *>(Data.getData().data()) +
107-
(FullWord ? 0 : DataPlus);
108-
}
93+
const std::byte *data() const { return Data.data(); }
10994

11095
bool allInitialized() const {
11196
// FIXME: Implement.
11297
return true;
11398
}
11499

100+
bool atByteBoundary() const { return (Data.size() * 8) == SizeInBits; }
101+
102+
void pushBit(bool Value) {
103+
if (atByteBoundary())
104+
Data.push_back(std::byte{0});
105+
106+
if (Value)
107+
Data.back() |= (std::byte{1} << (SizeInBits % 8));
108+
++SizeInBits;
109+
}
110+
115111
void pushData(const std::byte *data, size_t BitOffset, size_t BitWidth,
116112
bool BigEndianTarget) {
117-
Data.reserve(BitOffset + BitWidth);
118-
119113
bool OnlyFullBytes = BitWidth % 8 == 0;
120114
unsigned NBytes = BitWidth / 8;
121115

@@ -125,7 +119,7 @@ struct BitcastBuffer {
125119
std::byte B =
126120
BigEndianTarget ? data[NBytes - OnlyFullBytes - I] : data[I];
127121
for (unsigned X = 0; X != 8; ++X) {
128-
Data.push_back(bitof(B, X));
122+
pushBit(bitof(B, X));
129123
++BitsHandled;
130124
}
131125
}
@@ -137,7 +131,7 @@ struct BitcastBuffer {
137131
assert((BitWidth - BitsHandled) < 8);
138132
std::byte B = BigEndianTarget ? data[0] : data[NBytes];
139133
for (size_t I = 0, E = (BitWidth - BitsHandled); I != E; ++I) {
140-
Data.push_back(bitof(B, I));
134+
pushBit(bitof(B, I));
141135
++BitsHandled;
142136
}
143137

@@ -363,5 +357,8 @@ bool clang::interp::DoBitCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
363357
HasIndeterminateBits = !Buffer.allInitialized();
364358
std::memcpy(Buff, Buffer.data(), BuffSize);
365359

360+
if (llvm::sys::IsBigEndianHost)
361+
swapBytes(Buff, BuffSize);
362+
366363
return Success;
367364
}

clang/test/AST/ByteCode/builtin-bit-cast.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,17 @@ constexpr bool operator==(const struct bits<N, T, P>& lhs, const struct bits<N,
7474
#ifdef __SIZEOF_INT128__
7575
static_assert(check_round_trip<__int128_t>((__int128_t)34));
7676
static_assert(check_round_trip<__int128_t>((__int128_t)-34));
77+
78+
constexpr unsigned char OneBit[] = {
79+
0x1, 0x0, 0x0, 0x0,
80+
0x0, 0x0, 0x0, 0x0,
81+
0x0, 0x0, 0x0, 0x0,
82+
0x0, 0x0, 0x0, 0x0,
83+
};
84+
constexpr __int128_t One = 1;
85+
constexpr __int128_t Expected = One << 120;
86+
static_assert(__builtin_bit_cast(__int128_t, OneBit) == (LITTLE_END ? 1 : Expected));
87+
7788
#endif
7889

7990

0 commit comments

Comments
 (0)