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
This commit is contained in:
John McCall
2010-02-28 09:55:58 +00:00
parent 5b0a7741ad
commit 1e7ad3993d
3 changed files with 132 additions and 12 deletions

View File

@@ -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;
}