diff options
Diffstat (limited to 'clang/lib/AST/ByteCode/BitcastBuffer.cpp')
| -rw-r--r-- | clang/lib/AST/ByteCode/BitcastBuffer.cpp | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/clang/lib/AST/ByteCode/BitcastBuffer.cpp b/clang/lib/AST/ByteCode/BitcastBuffer.cpp index 0cc97b0b6bf1..fbd500fd8f5f 100644 --- a/clang/lib/AST/ByteCode/BitcastBuffer.cpp +++ b/clang/lib/AST/ByteCode/BitcastBuffer.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// #include "BitcastBuffer.h" +#include "llvm/ADT/STLExtras.h" using namespace clang; using namespace clang::interp; @@ -60,6 +61,80 @@ BitcastBuffer::copyBits(Bits BitOffset, Bits BitWidth, Bits FullBitWidth, return Out; } +bool BitcastBuffer::allInitialized() const { + return rangeInitialized(Bits::zero(), FinalBitSize); +} + +void BitcastBuffer::markInitialized(Bits Offset, Bits Length) { + if (Length.isZero()) + return; + + BitRange Element(Offset, Offset + Length - Bits(1)); + if (InitializedBits.empty()) { + InitializedBits.push_back(Element); + return; + } + + assert(InitializedBits.size() >= 1); + // Common case of just appending. + Bits End = InitializedBits.back().End; + if (End <= Offset) { + // Merge this range with the last one. + // In the best-case scenario, this means we only ever have + // one single bit range covering all bits. + if (End == (Offset - Bits(1))) { + InitializedBits.back().End = Element.End; + return; + } + + // Otherwise, we can simply append. + InitializedBits.push_back(Element); + } else { + // Insert sorted. + auto It = std::upper_bound(InitializedBits.begin(), InitializedBits.end(), + Element); + InitializedBits.insert(It, Element); + } + +#ifndef NDEBUG + // Ensure ranges are sorted and non-overlapping. + assert(llvm::is_sorted(InitializedBits)); + for (unsigned I = 1; I != InitializedBits.size(); ++I) { + [[maybe_unused]] auto Prev = InitializedBits[I - 1]; + [[maybe_unused]] auto Cur = InitializedBits[I]; + assert(Prev.End.N < Cur.Start.N); + } +#endif +} + +bool BitcastBuffer::rangeInitialized(Bits Offset, Bits Length) const { + if (Length.isZero()) + return true; + + BitRange Range(Offset, Offset + Length - Bits(1)); + Bits Sum; + bool FoundStart = false; + for (BitRange BR : InitializedBits) { + if (FoundStart) { + if (BR.contains(Range.End)) { + Sum += (Range.End - BR.Start + Bits(1)); + break; + } + + // Else, BR is completely inside Range. + Sum += BR.size(); + } + if (BR.contains(Range.Start)) { + Sum += (BR.End - Range.Start + Bits(1)); + FoundStart = true; + } + } + + // Note that Sum can be larger than Range, e.g. when Range is fully + // contained in one range. + return Sum >= Range.size(); +} + #if 0 template<typename T> static std::string hex(T t) { |
