brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.3 KiB · 8d32351 Raw
134 lines · c
1//===--------------------- BitcastBuffer.h ----------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8#ifndef LLVM_CLANG_AST_INTERP_BITCAST_BUFFER_H9#define LLVM_CLANG_AST_INTERP_BITCAST_BUFFER_H10 11#include "llvm/ADT/SmallVector.h"12#include <cassert>13#include <cstddef>14#include <memory>15 16namespace clang {17namespace interp {18 19enum class Endian { Little, Big };20 21struct Bytes;22 23/// A quantity in bits.24struct Bits {25  size_t N = 0;26  Bits() = default;27  static Bits zero() { return Bits(0); }28  explicit Bits(size_t Quantity) : N(Quantity) {}29  size_t getQuantity() const { return N; }30  size_t roundToBytes() const { return N / 8; }31  size_t getOffsetInByte() const { return N % 8; }32  bool isFullByte() const { return N % 8 == 0; }33  bool nonZero() const { return N != 0; }34  bool isZero() const { return N == 0; }35  Bytes toBytes() const;36 37  Bits operator-(Bits Other) const { return Bits(N - Other.N); }38  Bits operator+(Bits Other) const { return Bits(N + Other.N); }39  Bits operator+=(size_t O) {40    N += O;41    return *this;42  }43  Bits operator+=(Bits O) {44    N += O.N;45    return *this;46  }47 48  bool operator>=(Bits Other) const { return N >= Other.N; }49  bool operator<=(Bits Other) const { return N <= Other.N; }50  bool operator==(Bits Other) const { return N == Other.N; }51  bool operator!=(Bits Other) const { return N != Other.N; }52};53 54/// A quantity in bytes.55struct Bytes {56  size_t N;57  explicit Bytes(size_t Quantity) : N(Quantity) {}58  size_t getQuantity() const { return N; }59  Bits toBits() const { return Bits(N * 8); }60};61 62inline Bytes Bits::toBytes() const {63  assert(isFullByte());64  return Bytes(N / 8);65}66 67/// A bit range. Both Start and End are inclusive.68struct BitRange {69  Bits Start;70  Bits End;71 72  BitRange(Bits Start, Bits End) : Start(Start), End(End) {}73  Bits size() const { return End - Start + Bits(1); }74  bool operator<(BitRange Other) const { return Start.N < Other.Start.N; }75 76  bool contains(Bits B) { return Start <= B && End >= B; }77};78 79/// Track what bits have been initialized to known values and which ones80/// have indeterminate value.81struct BitcastBuffer {82  Bits FinalBitSize;83  std::unique_ptr<std::byte[]> Data;84  llvm::SmallVector<BitRange> InitializedBits;85 86  BitcastBuffer(Bits FinalBitSize) : FinalBitSize(FinalBitSize) {87    assert(FinalBitSize.isFullByte());88    unsigned ByteSize = FinalBitSize.roundToBytes();89    Data = std::make_unique<std::byte[]>(ByteSize);90  }91 92  /// Returns the byte at the given offset.93  std::byte *atByte(unsigned Offset) {94    assert(Offset < FinalBitSize.roundToBytes());95    return Data.get() + Offset;96  }97 98  /// Returns the buffer size in bits.99  Bits size() const { return FinalBitSize; }100  Bytes byteSize() const { return FinalBitSize.toBytes(); }101 102  /// Returns \c true if all bits in the buffer have been initialized.103  bool allInitialized() const;104  /// Marks the bits in the given range as initialized.105  /// FIXME: Can we do this automatically in pushData()?106  void markInitialized(Bits Start, Bits Length);107  bool rangeInitialized(Bits Offset, Bits Length) const;108 109  /// Push \p BitWidth bits at \p BitOffset from \p In into the buffer.110  /// \p TargetEndianness is the endianness of the target we're compiling for.111  /// \p In must hold at least \p BitWidth many bits.112  void pushData(const std::byte *In, Bits BitOffset, Bits BitWidth,113                Endian TargetEndianness);114 115  /// Copy \p BitWidth bits at offset \p BitOffset from the buffer.116  /// \p TargetEndianness is the endianness of the target we're compiling for.117  ///118  /// The returned output holds exactly (\p FullBitWidth / 8) bytes.119  std::unique_ptr<std::byte[]> copyBits(Bits BitOffset, Bits BitWidth,120                                        Bits FullBitWidth,121                                        Endian TargetEndianness) const;122 123  /// Dereferences the value at the given offset.124  template <typename T> T deref(Bytes Offset) const {125    assert(Offset.getQuantity() < FinalBitSize.roundToBytes());126    assert((Offset.getQuantity() + sizeof(T)) <= FinalBitSize.roundToBytes());127    return *reinterpret_cast<T *>(Data.get() + Offset.getQuantity());128  }129};130 131} // namespace interp132} // namespace clang133#endif134