Path: blob/main/contrib/llvm-project/clang/lib/AST/ByteCode/BitcastBuffer.cpp
213799 views
//===-------------------- Bitcastbuffer.cpp ---------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7#include "BitcastBuffer.h"8#include "llvm/ADT/STLExtras.h"910using namespace clang;11using namespace clang::interp;1213/// Returns the value of the bit in the given sequence of bytes.14static inline bool bitof(const std::byte *B, Bits BitIndex) {15return (B[BitIndex.roundToBytes()] &16(std::byte{1} << BitIndex.getOffsetInByte())) != std::byte{0};17}1819void BitcastBuffer::pushData(const std::byte *In, Bits BitOffset, Bits BitWidth,20Endian TargetEndianness) {21for (unsigned It = 0; It != BitWidth.getQuantity(); ++It) {22bool BitValue = bitof(In, Bits(It));23if (!BitValue)24continue;2526Bits DstBit;27if (TargetEndianness == Endian::Little)28DstBit = BitOffset + Bits(It);29else30DstBit = size() - BitOffset - BitWidth + Bits(It);3132size_t DstByte = DstBit.roundToBytes();33Data[DstByte] |= std::byte{1} << DstBit.getOffsetInByte();34}35}3637std::unique_ptr<std::byte[]>38BitcastBuffer::copyBits(Bits BitOffset, Bits BitWidth, Bits FullBitWidth,39Endian TargetEndianness) const {40assert(BitWidth.getQuantity() <= FullBitWidth.getQuantity());41assert(FullBitWidth.isFullByte());42auto Out = std::make_unique<std::byte[]>(FullBitWidth.roundToBytes());4344for (unsigned It = 0; It != BitWidth.getQuantity(); ++It) {45Bits BitIndex;46if (TargetEndianness == Endian::Little)47BitIndex = BitOffset + Bits(It);48else49BitIndex = size() - BitWidth - BitOffset + Bits(It);5051bool BitValue = bitof(Data.get(), BitIndex);52if (!BitValue)53continue;5455Bits DstBit = Bits(It);56size_t DstByte = DstBit.roundToBytes();57Out[DstByte] |= std::byte{1} << DstBit.getOffsetInByte();58}5960return Out;61}6263bool BitcastBuffer::allInitialized() const {64return rangeInitialized(Bits::zero(), FinalBitSize);65}6667void BitcastBuffer::markInitialized(Bits Offset, Bits Length) {68if (Length.isZero())69return;7071BitRange Element(Offset, Offset + Length - Bits(1));72if (InitializedBits.empty()) {73InitializedBits.push_back(Element);74return;75}7677assert(InitializedBits.size() >= 1);78// Common case of just appending.79Bits End = InitializedBits.back().End;80if (End <= Offset) {81// Merge this range with the last one.82// In the best-case scenario, this means we only ever have83// one single bit range covering all bits.84if (End == (Offset - Bits(1))) {85InitializedBits.back().End = Element.End;86return;87}8889// Otherwise, we can simply append.90InitializedBits.push_back(Element);91} else {92// Insert sorted.93auto It = llvm::upper_bound(InitializedBits, Element);94InitializedBits.insert(It, Element);95}9697#ifndef NDEBUG98// Ensure ranges are sorted and non-overlapping.99assert(llvm::is_sorted(InitializedBits));100for (unsigned I = 1; I != InitializedBits.size(); ++I) {101[[maybe_unused]] auto Prev = InitializedBits[I - 1];102[[maybe_unused]] auto Cur = InitializedBits[I];103assert(Prev.End.N < Cur.Start.N);104}105#endif106}107108bool BitcastBuffer::rangeInitialized(Bits Offset, Bits Length) const {109if (Length.isZero())110return true;111112BitRange Range(Offset, Offset + Length - Bits(1));113Bits Sum;114bool FoundStart = false;115for (BitRange BR : InitializedBits) {116if (FoundStart) {117if (BR.contains(Range.End)) {118Sum += (Range.End - BR.Start + Bits(1));119break;120}121122// Else, BR is completely inside Range.123Sum += BR.size();124}125if (BR.contains(Range.Start)) {126Sum += (BR.End - Range.Start + Bits(1));127FoundStart = true;128}129}130131// Note that Sum can be larger than Range, e.g. when Range is fully132// contained in one range.133return Sum >= Range.size();134}135136#if 0137template<typename T>138static std::string hex(T t) {139std::stringstream stream;140stream << std::hex << (int)t;141return std::string(stream.str());142}143144145void BitcastBuffer::dump(bool AsHex = true) const {146llvm::errs() << "LSB\n ";147unsigned LineLength = 0;148for (unsigned I = 0; I != (FinalBitSize / 8); ++I) {149std::byte B = Data[I];150if (AsHex) {151std::stringstream stream;152stream << std::hex << (int)B;153llvm::errs() << stream.str();154LineLength += stream.str().size() + 1;155} else {156llvm::errs() << std::bitset<8>((int)B).to_string();157LineLength += 8 + 1;158// llvm::errs() << (int)B;159}160llvm::errs() << ' ';161}162llvm::errs() << '\n';163164for (unsigned I = 0; I != LineLength; ++I)165llvm::errs() << ' ';166llvm::errs() << "MSB\n";167}168#endif169170171