From 57ae4f5f01b6f8edf678d77ab935f3662993065d Mon Sep 17 00:00:00 2001 From: Reid Spencer Date: Fri, 13 Apr 2007 19:19:07 +0000 Subject: [PATCH] Implement a getBitsNeeded method to determine how many bits are needed to represent a string in binary form by an APInt. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35968 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/APInt.h | 6 ++++++ lib/Support/APInt.cpp | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index d9470ee3c80..e232550fdf1 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -840,6 +840,12 @@ public: assert(getActiveBits() <= 64 && "Too many bits for int64_t"); return int64_t(pVal[0]); } + + /// This method determines how many bits are required to hold the APInt + /// equivalent of the string given by \p str of length \p slen. + /// @brief Get bits required for string value. + static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix); + /// countLeadingZeros - This function is an APInt version of the /// countLeadingZeros_{32,64} functions in MathExtras.h. It counts the number /// of zeros from the most significant bit to the first one bit. diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp index 73ee3e18dc7..a35b116b42e 100644 --- a/lib/Support/APInt.cpp +++ b/lib/Support/APInt.cpp @@ -659,6 +659,43 @@ APInt& APInt::flip(uint32_t bitPosition) { return *this; } +uint32_t APInt::getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) { + assert(str != 0 && "Invalid value string"); + assert(slen > 0 && "Invalid string length"); + + // Each computation below needs to know if its negative + uint32_t isNegative = str[0] == '-'; + if (isNegative) { + slen--; + str++; + } + // For radixes of power-of-two values, the bits required is accurately and + // easily computed + if (radix == 2) + return slen + isNegative; + if (radix == 8) + return slen * 3 + isNegative; + if (radix == 16) + return slen * 4 + isNegative; + + // Otherwise it must be radix == 10, the hard case + assert(radix == 10 && "Invalid radix"); + + // This is grossly inefficient but accurate. We could probably do something + // with a computation of roughly slen*64/20 and then adjust by the value of + // the first few digits. But, I'm not sure how accurate that could be. + + // Compute a sufficient number of bits that is always large enough but might + // be too large. This avoids the assertion in the constructor. + uint32_t sufficient = slen*64/18; + + // Convert to the actual binary value. + APInt tmp(sufficient, str, slen, radix); + + // Compute how many bits are required. + return isNegative + tmp.logBase2(); +} + uint64_t APInt::getHashValue() const { // Put the bit width into the low order bits. uint64_t hash = BitWidth;