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