[clang] 88823d0 - [clang][bytecode][NFC] Switch BitcastBuffer to SmallVector (#114677)

via cfe-commits cfe-commits at lists.llvm.org
Sun Nov 3 02:17:03 PST 2024


Author: Timm Baeder
Date: 2024-11-03T11:16:59+01:00
New Revision: 88823d08ab850efc40cf20498a697f4532aad1fd

URL: https://github.com/llvm/llvm-project/commit/88823d08ab850efc40cf20498a697f4532aad1fd
DIFF: https://github.com/llvm/llvm-project/commit/88823d08ab850efc40cf20498a697f4532aad1fd.diff

LOG: [clang][bytecode][NFC] Switch BitcastBuffer to SmallVector (#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.

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
    clang/test/AST/ByteCode/builtin-bit-cast.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
index fde2c6d9b11ac8..1acd49de307b96 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
@@ -83,39 +83,33 @@ static void swapBytes(std::byte *M, size_t N) {
 /// have indeterminate value.
 /// All offsets are in bits.
 struct BitcastBuffer {
-  llvm::BitVector Data;
+  size_t SizeInBits = 0;
+  llvm::SmallVector<std::byte> Data;
 
   BitcastBuffer() = default;
 
-  size_t size() const { return Data.size(); }
+  size_t size() const { return SizeInBits; }
 
-  const std::byte *data() const {
-    unsigned NBytes = Data.size() / 8;
-    unsigned BitVectorWordSize = sizeof(uintptr_t);
-    bool FullWord = (NBytes % BitVectorWordSize == 0);
-
-    // llvm::BitVector uses 64-bit fields internally, so when we have
-    // fewer bytes than that, we need to compensate for that on
-    // big endian hosts.
-    unsigned DataPlus;
-    if (llvm::sys::IsBigEndianHost)
-      DataPlus = BitVectorWordSize - (NBytes % BitVectorWordSize);
-    else
-      DataPlus = 0;
-
-    return reinterpret_cast<const std::byte *>(Data.getData().data()) +
-           (FullWord ? 0 : DataPlus);
-  }
+  const std::byte *data() const { return Data.data(); }
 
   bool allInitialized() const {
     // FIXME: Implement.
     return true;
   }
 
+  bool atByteBoundary() const { return (Data.size() * 8) == SizeInBits; }
+
+  void pushBit(bool Value) {
+    if (atByteBoundary())
+      Data.push_back(std::byte{0});
+
+    if (Value)
+      Data.back() |= (std::byte{1} << (SizeInBits % 8));
+    ++SizeInBits;
+  }
+
   void pushData(const std::byte *data, size_t BitOffset, size_t BitWidth,
                 bool BigEndianTarget) {
-    Data.reserve(BitOffset + BitWidth);
-
     bool OnlyFullBytes = BitWidth % 8 == 0;
     unsigned NBytes = BitWidth / 8;
 
@@ -125,7 +119,7 @@ struct BitcastBuffer {
       std::byte B =
           BigEndianTarget ? data[NBytes - OnlyFullBytes - I] : data[I];
       for (unsigned X = 0; X != 8; ++X) {
-        Data.push_back(bitof(B, X));
+        pushBit(bitof(B, X));
         ++BitsHandled;
       }
     }
@@ -137,7 +131,7 @@ struct BitcastBuffer {
     assert((BitWidth - BitsHandled) < 8);
     std::byte B = BigEndianTarget ? data[0] : data[NBytes];
     for (size_t I = 0, E = (BitWidth - BitsHandled); I != E; ++I) {
-      Data.push_back(bitof(B, I));
+      pushBit(bitof(B, I));
       ++BitsHandled;
     }
 
@@ -363,5 +357,8 @@ bool clang::interp::DoBitCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
   HasIndeterminateBits = !Buffer.allInitialized();
   std::memcpy(Buff, Buffer.data(), BuffSize);
 
+  if (llvm::sys::IsBigEndianHost)
+    swapBytes(Buff, BuffSize);
+
   return Success;
 }

diff  --git a/clang/test/AST/ByteCode/builtin-bit-cast.cpp b/clang/test/AST/ByteCode/builtin-bit-cast.cpp
index 0e86da9133b33d..c5380647c94aee 100644
--- a/clang/test/AST/ByteCode/builtin-bit-cast.cpp
+++ b/clang/test/AST/ByteCode/builtin-bit-cast.cpp
@@ -74,6 +74,17 @@ constexpr bool operator==(const struct bits<N, T, P>& lhs, const struct bits<N,
 #ifdef __SIZEOF_INT128__
 static_assert(check_round_trip<__int128_t>((__int128_t)34));
 static_assert(check_round_trip<__int128_t>((__int128_t)-34));
+
+constexpr unsigned char OneBit[] = {
+  0x1, 0x0,  0x0,  0x0,
+  0x0, 0x0,  0x0,  0x0,
+  0x0, 0x0,  0x0,  0x0,
+  0x0, 0x0,  0x0,  0x0,
+};
+constexpr __int128_t One = 1;
+constexpr __int128_t Expected = One << 120;
+static_assert(__builtin_bit_cast(__int128_t, OneBit) == (LITTLE_END ? 1 : Expected));
+
 #endif
 
 


        


More information about the cfe-commits mailing list