Files
swift-mirror/include/swift/Basic/ClusteredBitVector.h
Brent Royal-Gordon 99faa033fc [NFC] Standardize dump() methods in frontend
By convention, most structs and classes in the Swift compiler include a `dump()` method which prints debugging information. This method is meant to be called only from the debugger, but this means they’re often unused and may be eliminated from optimized binaries. On the other hand, some parts of the compiler call `dump()` methods directly despite them being intended as a pure debugging aid. clang supports attributes which can be used to avoid these problems, but they’re used very inconsistently across the compiler.

This commit adds `SWIFT_DEBUG_DUMP` and `SWIFT_DEBUG_DUMPER(<name>(<params>))` macros to declare `dump()` methods with the appropriate set of attributes and adopts this macro throughout the frontend. It does not pervasively adopt this macro in SILGen, SILOptimizer, or IRGen; these components use `dump()` methods in a different way where they’re frequently called from debugging code. Nor does it adopt it in runtime components like swiftRuntime and swiftReflection, because I’m a bit worried about size.

Despite the large number of files and lines affected, this change is NFC.
2019-10-31 18:37:42 -07:00

286 lines
7.6 KiB
C++

//===--- ClusteredBitVector.h - A size-optimized bit vector -----*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the ClusteredBitVector class, a bitset data
// structure.
//
// For example, this would be reasonable to use to describe the
// unoccupied bits in a memory layout.
//
// Primary mutators:
// - appending another vector to this vector
// - appending a constant vector (<0,0,...,0> or <1,1,...,1>) to this vector
//
// Primary observers:
// - testing a specific bit
// - converting to llvm::APInt
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_BASIC_CLUSTEREDBITVECTOR_H
#define SWIFT_BASIC_CLUSTEREDBITVECTOR_H
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/Optional.h"
#include "swift/Basic/Debug.h"
#include <cassert>
namespace swift {
/// A vector of bits.
class ClusteredBitVector {
using APInt = llvm::APInt;
/// Represents the bit vector as an integer.
/// The least-significant bit of the integer corresponds to the bit
/// at index 0. If the optional does not have a value then the bit
/// vector has a length of 0 bits.
llvm::Optional<APInt> Bits;
/// Copy constructor from APInt.
ClusteredBitVector(const APInt &bits) : Bits(bits) {}
/// Move constructor from APInt.
ClusteredBitVector(APInt &&bits) : Bits(std::move(bits)) {}
public:
/// Create a new bit vector of zero length. This does not perform
/// any allocations.
ClusteredBitVector() = default;
ClusteredBitVector(const ClusteredBitVector &other)
: Bits(other.Bits) {}
ClusteredBitVector(ClusteredBitVector &&other)
: Bits(std::move(other.Bits)) {}
/// Create a new ClusteredBitVector from the provided APInt,
/// with a size of 0 if the optional does not have a value.
ClusteredBitVector(const llvm::Optional<APInt> &bits)
: Bits(bits) {}
/// Create a new ClusteredBitVector from the provided APInt,
/// with a size of 0 if the optional does not have a value.
ClusteredBitVector(llvm::Optional<APInt> &&bits)
: Bits(std::move(bits)) {}
ClusteredBitVector &operator=(const ClusteredBitVector &other) {
this->Bits = other.Bits;
return *this;
}
ClusteredBitVector &operator=(ClusteredBitVector &&other) {
this->Bits = std::move(other.Bits);
return *this;
}
~ClusteredBitVector() = default;
/// Return true if this vector is zero-length (*not* if it does not
/// contain any set bits).
bool empty() const {
return !Bits.hasValue();
}
/// Return the length of this bit-vector.
size_t size() const {
return Bits ? Bits.getValue().getBitWidth() : 0;
}
/// Append the bits from the given vector to this one.
void append(const ClusteredBitVector &other) {
// Nothing to do if the other vector is empty.
if (!other.Bits) {
return;
}
if (!Bits) {
Bits = other.Bits;
return;
}
APInt &v = Bits.getValue();
unsigned w = v.getBitWidth();
v = v.zext(w + other.Bits.getValue().getBitWidth());
v.insertBits(other.Bits.getValue(), w);
return;
}
/// Add the low N bits from the given value to the vector.
void add(size_t numBits, uint64_t value) {
append(fromAPInt(APInt(numBits, value)));
}
/// Append a number of clear bits to this vector.
void appendClearBits(size_t numBits) {
if (numBits == 0) {
return;
}
if (Bits) {
APInt &v = Bits.getValue();
v = v.zext(v.getBitWidth() + numBits);
return;
}
Bits = APInt::getNullValue(numBits);
}
/// Extend the vector out to the given length with clear bits.
void extendWithClearBits(size_t newSize) {
assert(newSize >= size());
appendClearBits(newSize - size());
}
/// Append a number of set bits to this vector.
void appendSetBits(size_t numBits) {
if (numBits == 0) {
return;
}
if (Bits) {
APInt &v = Bits.getValue();
unsigned w = v.getBitWidth();
v = v.zext(w + numBits);
v.setBitsFrom(w);
return;
}
Bits = APInt::getAllOnesValue(numBits);
return;
}
/// Extend the vector out to the given length with set bits.
void extendWithSetBits(size_t newSize) {
assert(newSize >= size());
appendSetBits(newSize - size());
}
/// Test whether a particular bit is set.
bool operator[](size_t i) const {
assert(i < size());
return Bits.getValue()[i];
}
/// Intersect a bit-vector of the same size into this vector.
ClusteredBitVector &operator&=(const ClusteredBitVector &other) {
assert(size() == other.size());
if (Bits) {
APInt &v = Bits.getValue();
v &= other.Bits.getValue();
}
return *this;
}
/// Union a bit-vector of the same size into this vector.
ClusteredBitVector &operator|=(const ClusteredBitVector &other) {
assert(size() == other.size());
if (Bits) {
APInt &v = Bits.getValue();
v |= other.Bits.getValue();
}
return *this;
}
/// Set bit i.
void setBit(size_t i) {
assert(i < size());
Bits.getValue().setBit(i);
}
/// Clear bit i.
void clearBit(size_t i) {
assert(i < size());
Bits.getValue().clearBit(i);
}
/// Toggle bit i.
void flipBit(size_t i) {
assert(i < size());
Bits.getValue().flipBit(i);
}
/// Toggle all the bits in this vector.
void flipAll() {
if (Bits) {
Bits.getValue().flipAllBits();
}
}
/// Set the length of this vector to zero.
void clear() {
Bits.reset();
}
/// Count the number of set bits in this vector.
size_t count() const {
return Bits ? Bits.getValue().countPopulation() : 0;
}
/// Determine if there are any bits set in this vector.
bool any() const {
return Bits && Bits.getValue() != 0;
}
/// Determine if there are no bits set in this vector.
///
/// \return \c !any()
bool none() const {
return !any();
}
friend bool operator==(const ClusteredBitVector &lhs,
const ClusteredBitVector &rhs) {
if (lhs.size() != rhs.size()) {
return false;
}
if (lhs.size() == 0) {
return true;
}
return lhs.Bits.getValue() == rhs.Bits.getValue();
}
friend bool operator!=(const ClusteredBitVector &lhs,
const ClusteredBitVector &rhs) {
return !(lhs == rhs);
}
/// Return this bit-vector as an APInt, with low indices becoming
/// the least significant bits of the number.
APInt asAPInt() const {
// Return 1-bit wide zero APInt for a 0-bit vector.
return Bits ? Bits.getValue() : APInt();
}
/// Construct a bit-vector from an APInt.
static ClusteredBitVector fromAPInt(const APInt &value) {
return ClusteredBitVector(value);
}
/// Construct a bit-vector from an APInt.
static ClusteredBitVector fromAPInt(APInt &&value) {
return ClusteredBitVector(std::move(value));
}
/// Return a constant bit-vector of the given size.
static ClusteredBitVector getConstant(size_t numBits, bool value) {
if (numBits == 0) {
return ClusteredBitVector();
}
auto vec = APInt::getNullValue(numBits);
if (value) {
vec.flipAllBits();
}
return ClusteredBitVector(vec);
}
/// Pretty-print the vector.
void print(llvm::raw_ostream &out) const;
SWIFT_DEBUG_DUMP;
};
} // end namespace swift
#endif // SWIFT_BASIC_CLUSTEREDBITVECTOR_H