diff options
author | John McCall <rjmccall@apple.com> | 2010-02-28 09:55:58 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-02-28 09:55:58 +0000 |
commit | 2f1affab0af559475d87a3ff24be66f0fc508156 (patch) | |
tree | 559719ee3c95466fd921a748a0bddfb75670f6fd /lib/Support/StringRef.cpp | |
parent | 297637c4f42bb8fb4347b13bd39fef0896a09f33 (diff) | |
download | external_llvm-2f1affab0af559475d87a3ff24be66f0fc508156.zip external_llvm-2f1affab0af559475d87a3ff24be66f0fc508156.tar.gz external_llvm-2f1affab0af559475d87a3ff24be66f0fc508156.tar.bz2 |
Add an override to StringRef::getAsInteger which parses into an APInt.
It gets its own implementation totally divorced from the (presumably
performance-sensitive) routines which parse into a uint64_t.
Add APInt::operator|=(uint64_t), which is situationally much better than
using a full APInt.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97381 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Support/StringRef.cpp')
-rw-r--r-- | lib/Support/StringRef.cpp | 105 |
1 files changed, 93 insertions, 12 deletions
diff --git a/lib/Support/StringRef.cpp b/lib/Support/StringRef.cpp index ae2640b..2b262dc 100644 --- a/lib/Support/StringRef.cpp +++ b/lib/Support/StringRef.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/APInt.h" using namespace llvm; @@ -172,23 +173,28 @@ size_t StringRef::count(StringRef Str) const { return Count; } +static unsigned GetAutoSenseRadix(StringRef &Str) { + if (Str.startswith("0x")) { + Str = Str.substr(2); + return 16; + } else if (Str.startswith("0b")) { + Str = Str.substr(2); + return 2; + } else if (Str.startswith("0")) { + return 8; + } else { + return 10; + } +} + + /// GetAsUnsignedInteger - Workhorse method that converts a integer character /// sequence of radix up to 36 to an unsigned long long value. static bool GetAsUnsignedInteger(StringRef Str, unsigned Radix, unsigned long long &Result) { // Autosense radix if not specified. - if (Radix == 0) { - if (Str.startswith("0x")) { - Str = Str.substr(2); - Radix = 16; - } else if (Str.startswith("0b")) { - Str = Str.substr(2); - Radix = 2; - } else if (Str.startswith("0")) - Radix = 8; - else - Radix = 10; - } + if (Radix == 0) + Radix = GetAutoSenseRadix(Str); // Empty strings (after the radix autosense) are invalid. if (Str.empty()) return true; @@ -272,3 +278,78 @@ bool StringRef::getAsInteger(unsigned Radix, unsigned &Result) const { Result = Val; return false; } + +bool StringRef::getAsInteger(unsigned Radix, APInt &Result) const { + StringRef Str = *this; + + // Autosense radix if not specified. + if (Radix == 0) + Radix = GetAutoSenseRadix(Str); + + assert(Radix > 1 && Radix <= 36); + + // Empty strings (after the radix autosense) are invalid. + if (Str.empty()) return true; + + // Skip leading zeroes. This can be a significant improvement if + // it means we don't need > 64 bits. + while (!Str.empty() && Str.front() == '0') + Str = Str.substr(1); + + // If it was nothing but zeroes.... + if (Str.empty()) { + Result = APInt(64, 0); + return false; + } + + // (Over-)estimate the required number of bits. + unsigned Log2Radix = 0; + while ((1U << Log2Radix) < Radix) Log2Radix++; + bool IsPowerOf2Radix = ((1U << Log2Radix) == Radix); + + unsigned BitWidth = Log2Radix * Str.size(); + if (BitWidth < Result.getBitWidth()) + BitWidth = Result.getBitWidth(); // don't shrink the result + else + Result.zext(BitWidth); + + APInt RadixAP, CharAP; // unused unless !IsPowerOf2Radix + if (!IsPowerOf2Radix) { + // These must have the same bit-width as Result. + RadixAP = APInt(BitWidth, Radix); + CharAP = APInt(BitWidth, 0); + } + + // Parse all the bytes of the string given this radix. + Result = 0; + while (!Str.empty()) { + unsigned CharVal; + if (Str[0] >= '0' && Str[0] <= '9') + CharVal = Str[0]-'0'; + else if (Str[0] >= 'a' && Str[0] <= 'z') + CharVal = Str[0]-'a'+10; + else if (Str[0] >= 'A' && Str[0] <= 'Z') + CharVal = Str[0]-'A'+10; + else + return true; + + // If the parsed value is larger than the integer radix, the string is + // invalid. + if (CharVal >= Radix) + return true; + + // Add in this character. + if (IsPowerOf2Radix) { + Result <<= Log2Radix; + Result |= CharVal; + } else { + Result *= RadixAP; + CharAP = CharVal; + Result += CharAP; + } + + Str = Str.substr(1); + } + + return false; +} |