xref: /llvm-project/clang/lib/AST/ByteCode/BitcastBuffer.cpp (revision b4150ed128a136409a2510ee00003bd318f703fb)
112ca72baSTimm Bäder //===-------------------- Bitcastbuffer.cpp ---------------------*- C++ -*-===//
212ca72baSTimm Bäder //
312ca72baSTimm Bäder // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
412ca72baSTimm Bäder // See https://llvm.org/LICENSE.txt for license information.
512ca72baSTimm Bäder // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
612ca72baSTimm Bäder //
712ca72baSTimm Bäder //===----------------------------------------------------------------------===//
812ca72baSTimm Bäder #include "BitcastBuffer.h"
92f9cd43aSTimm Baeder #include "llvm/ADT/STLExtras.h"
1012ca72baSTimm Bäder 
1112ca72baSTimm Bäder using namespace clang;
1212ca72baSTimm Bäder using namespace clang::interp;
1312ca72baSTimm Bäder 
1412ca72baSTimm Bäder /// Returns the value of the bit in the given sequence of bytes.
1512ca72baSTimm Bäder static inline bool bitof(const std::byte *B, Bits BitIndex) {
1612ca72baSTimm Bäder   return (B[BitIndex.roundToBytes()] &
1712ca72baSTimm Bäder           (std::byte{1} << BitIndex.getOffsetInByte())) != std::byte{0};
1812ca72baSTimm Bäder }
1912ca72baSTimm Bäder 
2012ca72baSTimm Bäder void BitcastBuffer::pushData(const std::byte *In, Bits BitOffset, Bits BitWidth,
2112ca72baSTimm Bäder                              Endian TargetEndianness) {
2212ca72baSTimm Bäder   for (unsigned It = 0; It != BitWidth.getQuantity(); ++It) {
2312ca72baSTimm Bäder     bool BitValue = bitof(In, Bits(It));
2412ca72baSTimm Bäder     if (!BitValue)
2512ca72baSTimm Bäder       continue;
2612ca72baSTimm Bäder 
2712ca72baSTimm Bäder     Bits DstBit;
2812ca72baSTimm Bäder     if (TargetEndianness == Endian::Little)
2912ca72baSTimm Bäder       DstBit = BitOffset + Bits(It);
3012ca72baSTimm Bäder     else
3112ca72baSTimm Bäder       DstBit = size() - BitOffset - BitWidth + Bits(It);
3212ca72baSTimm Bäder 
3312ca72baSTimm Bäder     size_t DstByte = DstBit.roundToBytes();
3412ca72baSTimm Bäder     Data[DstByte] |= std::byte{1} << DstBit.getOffsetInByte();
3512ca72baSTimm Bäder   }
3612ca72baSTimm Bäder }
3712ca72baSTimm Bäder 
3812ca72baSTimm Bäder std::unique_ptr<std::byte[]>
3912ca72baSTimm Bäder BitcastBuffer::copyBits(Bits BitOffset, Bits BitWidth, Bits FullBitWidth,
4012ca72baSTimm Bäder                         Endian TargetEndianness) const {
4112ca72baSTimm Bäder   assert(BitWidth.getQuantity() <= FullBitWidth.getQuantity());
4212ca72baSTimm Bäder   assert(FullBitWidth.isFullByte());
4312ca72baSTimm Bäder   auto Out = std::make_unique<std::byte[]>(FullBitWidth.roundToBytes());
4412ca72baSTimm Bäder 
4512ca72baSTimm Bäder   for (unsigned It = 0; It != BitWidth.getQuantity(); ++It) {
4612ca72baSTimm Bäder     Bits BitIndex;
4712ca72baSTimm Bäder     if (TargetEndianness == Endian::Little)
4812ca72baSTimm Bäder       BitIndex = BitOffset + Bits(It);
4912ca72baSTimm Bäder     else
5012ca72baSTimm Bäder       BitIndex = size() - BitWidth - BitOffset + Bits(It);
5112ca72baSTimm Bäder 
5212ca72baSTimm Bäder     bool BitValue = bitof(Data.get(), BitIndex);
5312ca72baSTimm Bäder     if (!BitValue)
5412ca72baSTimm Bäder       continue;
5512ca72baSTimm Bäder 
5612ca72baSTimm Bäder     Bits DstBit = Bits(It);
5712ca72baSTimm Bäder     size_t DstByte = DstBit.roundToBytes();
5812ca72baSTimm Bäder     Out[DstByte] |= std::byte{1} << DstBit.getOffsetInByte();
5912ca72baSTimm Bäder   }
6012ca72baSTimm Bäder 
6112ca72baSTimm Bäder   return Out;
6212ca72baSTimm Bäder }
6312ca72baSTimm Bäder 
642f9cd43aSTimm Baeder bool BitcastBuffer::allInitialized() const {
65*b4150ed1STimm Baeder   return rangeInitialized(Bits::zero(), FinalBitSize);
662f9cd43aSTimm Baeder }
672f9cd43aSTimm Baeder 
682f9cd43aSTimm Baeder void BitcastBuffer::markInitialized(Bits Offset, Bits Length) {
692f9cd43aSTimm Baeder   if (Length.isZero())
702f9cd43aSTimm Baeder     return;
712f9cd43aSTimm Baeder 
722f9cd43aSTimm Baeder   BitRange Element(Offset, Offset + Length - Bits(1));
732f9cd43aSTimm Baeder   if (InitializedBits.empty()) {
742f9cd43aSTimm Baeder     InitializedBits.push_back(Element);
752f9cd43aSTimm Baeder     return;
762f9cd43aSTimm Baeder   }
772f9cd43aSTimm Baeder 
782f9cd43aSTimm Baeder   assert(InitializedBits.size() >= 1);
792f9cd43aSTimm Baeder   // Common case of just appending.
802f9cd43aSTimm Baeder   Bits End = InitializedBits.back().End;
812f9cd43aSTimm Baeder   if (End <= Offset) {
822f9cd43aSTimm Baeder     // Merge this range with the last one.
832f9cd43aSTimm Baeder     // In the best-case scenario, this means we only ever have
842f9cd43aSTimm Baeder     // one single bit range covering all bits.
852f9cd43aSTimm Baeder     if (End == (Offset - Bits(1))) {
862f9cd43aSTimm Baeder       InitializedBits.back().End = Element.End;
872f9cd43aSTimm Baeder       return;
882f9cd43aSTimm Baeder     }
892f9cd43aSTimm Baeder 
902f9cd43aSTimm Baeder     // Otherwise, we can simply append.
912f9cd43aSTimm Baeder     InitializedBits.push_back(Element);
922f9cd43aSTimm Baeder   } else {
932f9cd43aSTimm Baeder     // Insert sorted.
942f9cd43aSTimm Baeder     auto It = std::upper_bound(InitializedBits.begin(), InitializedBits.end(),
952f9cd43aSTimm Baeder                                Element);
962f9cd43aSTimm Baeder     InitializedBits.insert(It, Element);
972f9cd43aSTimm Baeder   }
982f9cd43aSTimm Baeder 
992f9cd43aSTimm Baeder #ifndef NDEBUG
1002f9cd43aSTimm Baeder   // Ensure ranges are sorted and non-overlapping.
1012f9cd43aSTimm Baeder   assert(llvm::is_sorted(InitializedBits));
1022f9cd43aSTimm Baeder   for (unsigned I = 1; I != InitializedBits.size(); ++I) {
1032f9cd43aSTimm Baeder     [[maybe_unused]] auto Prev = InitializedBits[I - 1];
1042f9cd43aSTimm Baeder     [[maybe_unused]] auto Cur = InitializedBits[I];
1052f9cd43aSTimm Baeder     assert(Prev.End.N < Cur.Start.N);
1062f9cd43aSTimm Baeder   }
1072f9cd43aSTimm Baeder #endif
1082f9cd43aSTimm Baeder }
1092f9cd43aSTimm Baeder 
110*b4150ed1STimm Baeder bool BitcastBuffer::rangeInitialized(Bits Offset, Bits Length) const {
111*b4150ed1STimm Baeder   if (Length.isZero())
112*b4150ed1STimm Baeder     return true;
113*b4150ed1STimm Baeder 
114*b4150ed1STimm Baeder   BitRange Range(Offset, Offset + Length - Bits(1));
115*b4150ed1STimm Baeder   Bits Sum;
116*b4150ed1STimm Baeder   bool FoundStart = false;
117*b4150ed1STimm Baeder   for (BitRange BR : InitializedBits) {
118*b4150ed1STimm Baeder     if (FoundStart) {
119*b4150ed1STimm Baeder       if (BR.contains(Range.End)) {
120*b4150ed1STimm Baeder         Sum += (Range.End - BR.Start + Bits(1));
121*b4150ed1STimm Baeder         break;
122*b4150ed1STimm Baeder       }
123*b4150ed1STimm Baeder 
124*b4150ed1STimm Baeder       // Else, BR is completely inside Range.
125*b4150ed1STimm Baeder       Sum += BR.size();
126*b4150ed1STimm Baeder     }
127*b4150ed1STimm Baeder     if (BR.contains(Range.Start)) {
128*b4150ed1STimm Baeder       Sum += (BR.End - Range.Start + Bits(1));
129*b4150ed1STimm Baeder       FoundStart = true;
130*b4150ed1STimm Baeder     }
131*b4150ed1STimm Baeder   }
132*b4150ed1STimm Baeder 
133*b4150ed1STimm Baeder   // Note that Sum can be larger than Range, e.g. when Range is fully
134*b4150ed1STimm Baeder   // contained in one range.
135*b4150ed1STimm Baeder   return Sum >= Range.size();
136*b4150ed1STimm Baeder }
137*b4150ed1STimm Baeder 
13812ca72baSTimm Bäder #if 0
13912ca72baSTimm Bäder   template<typename T>
14012ca72baSTimm Bäder   static std::string hex(T t) {
14112ca72baSTimm Bäder     std::stringstream stream;
14212ca72baSTimm Bäder     stream << std::hex << (int)t;
14312ca72baSTimm Bäder     return std::string(stream.str());
14412ca72baSTimm Bäder   }
14512ca72baSTimm Bäder 
14612ca72baSTimm Bäder 
14712ca72baSTimm Bäder   void BitcastBuffer::dump(bool AsHex = true) const {
14812ca72baSTimm Bäder     llvm::errs() << "LSB\n  ";
14912ca72baSTimm Bäder     unsigned LineLength = 0;
15012ca72baSTimm Bäder     for (unsigned I = 0; I != (FinalBitSize / 8); ++I) {
15112ca72baSTimm Bäder       std::byte B = Data[I];
15212ca72baSTimm Bäder       if (AsHex) {
15312ca72baSTimm Bäder         std::stringstream stream;
15412ca72baSTimm Bäder         stream << std::hex << (int)B;
15512ca72baSTimm Bäder         llvm::errs() << stream.str();
15612ca72baSTimm Bäder         LineLength += stream.str().size() + 1;
15712ca72baSTimm Bäder       } else {
15812ca72baSTimm Bäder         llvm::errs() << std::bitset<8>((int)B).to_string();
15912ca72baSTimm Bäder         LineLength += 8 + 1;
16012ca72baSTimm Bäder         // llvm::errs() << (int)B;
16112ca72baSTimm Bäder       }
16212ca72baSTimm Bäder       llvm::errs() << ' ';
16312ca72baSTimm Bäder     }
16412ca72baSTimm Bäder     llvm::errs() << '\n';
16512ca72baSTimm Bäder 
16612ca72baSTimm Bäder     for (unsigned I = 0; I != LineLength; ++I)
16712ca72baSTimm Bäder       llvm::errs() << ' ';
16812ca72baSTimm Bäder     llvm::errs() << "MSB\n";
16912ca72baSTimm Bäder   }
17012ca72baSTimm Bäder #endif
171