summaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode/BitcastBuffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ByteCode/BitcastBuffer.cpp')
-rw-r--r--clang/lib/AST/ByteCode/BitcastBuffer.cpp75
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) {