[llvm-commits] [llvm] r139695 - in /llvm/trunk: include/llvm/ADT/APInt.h lib/Support/APInt.cpp unittests/ADT/APIntTest.cpp
Douglas Gregor
dgregor at apple.com
Wed Sep 14 08:54:46 PDT 2011
Author: dgregor
Date: Wed Sep 14 10:54:46 2011
New Revision: 139695
URL: http://llvm.org/viewvc/llvm-project?rev=139695&view=rev
Log:
Add APInt support for converting to/from hexatridecimal strings
Modified:
llvm/trunk/include/llvm/ADT/APInt.h
llvm/trunk/lib/Support/APInt.cpp
llvm/trunk/unittests/ADT/APIntTest.cpp
Modified: llvm/trunk/include/llvm/ADT/APInt.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APInt.h?rev=139695&r1=139694&r2=139695&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/APInt.h (original)
+++ llvm/trunk/include/llvm/ADT/APInt.h Wed Sep 14 10:54:46 2011
@@ -161,7 +161,7 @@
/// not assume that the string is well-formed and (2) grows the
/// result to hold the input.
///
- /// @param radix 2, 8, 10, or 16
+ /// @param radix 2, 8, 10, 16, or 36
/// @brief Convert a char array into an APInt
void fromString(unsigned numBits, StringRef str, uint8_t radix);
@@ -252,8 +252,8 @@
/// This constructor interprets the string \arg str in the given radix. The
/// interpretation stops when the first character that is not suitable for the
/// radix is encountered, or the end of the string. Acceptable radix values
- /// are 2, 8, 10 and 16. It is an error for the value implied by the string to
- /// require more bits than numBits.
+ /// are 2, 8, 10, 16, and 36. It is an error for the value implied by the
+ /// string to require more bits than numBits.
///
/// @param numBits the bit width of the constructed APInt
/// @param str the string to be interpreted
@@ -1257,13 +1257,13 @@
bool formatAsCLiteral = false) const;
/// Considers the APInt to be unsigned and converts it into a string in the
- /// radix given. The radix can be 2, 8, 10 or 16.
+ /// radix given. The radix can be 2, 8, 10 16, or 36.
void toStringUnsigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
toString(Str, Radix, false, false);
}
/// Considers the APInt to be signed and converts it into a string in the
- /// radix given. The radix can be 2, 8, 10 or 16.
+ /// radix given. The radix can be 2, 8, 10, 16, or 36.
void toStringSigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
toString(Str, Radix, true, false);
}
Modified: llvm/trunk/lib/Support/APInt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APInt.cpp?rev=139695&r1=139694&r2=139695&view=diff
==============================================================================
--- llvm/trunk/lib/Support/APInt.cpp (original)
+++ llvm/trunk/lib/Support/APInt.cpp Wed Sep 14 10:54:46 2011
@@ -48,17 +48,17 @@
inline static unsigned getDigit(char cdigit, uint8_t radix) {
unsigned r;
- if (radix == 16) {
+ if (radix == 16 || radix == 36) {
r = cdigit - '0';
if (r <= 9)
return r;
r = cdigit - 'A';
- if (r <= 5)
+ if (r <= radix-11)
return r + 10;
r = cdigit - 'a';
- if (r <= 5)
+ if (r <= radix-11)
return r + 10;
}
@@ -621,8 +621,9 @@
unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) {
assert(!str.empty() && "Invalid string length");
- assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) &&
- "Radix should be 2, 8, 10, or 16!");
+ assert((radix == 10 || radix == 8 || radix == 16 || radix == 2 ||
+ radix == 36) &&
+ "Radix should be 2, 8, 10, 16, or 36!");
size_t slen = str.size();
@@ -644,6 +645,8 @@
if (radix == 16)
return slen * 4 + isNegative;
+ // FIXME: base 36
+
// 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.
@@ -652,7 +655,9 @@
// be too large. This avoids the assertion in the constructor. This
// calculation doesn't work appropriately for the numbers 0-9, so just use 4
// bits in that case.
- unsigned sufficient = slen == 1 ? 4 : slen * 64/18;
+ unsigned sufficient
+ = radix == 10? (slen == 1 ? 4 : slen * 64/18)
+ : (slen == 1 ? 7 : slen * 16/3);
// Convert to the actual binary value.
APInt tmp(sufficient, StringRef(p, slen), radix);
@@ -2115,8 +2120,9 @@
void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) {
// Check our assumptions here
assert(!str.empty() && "Invalid string length");
- assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) &&
- "Radix should be 2, 8, 10, or 16!");
+ assert((radix == 10 || radix == 8 || radix == 16 || radix == 2 ||
+ radix == 36) &&
+ "Radix should be 2, 8, 10, 16, or 36!");
StringRef::iterator p = str.begin();
size_t slen = str.size();
@@ -2173,7 +2179,8 @@
void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix,
bool Signed, bool formatAsCLiteral) const {
- assert((Radix == 10 || Radix == 8 || Radix == 16 || Radix == 2) &&
+ assert((Radix == 10 || Radix == 8 || Radix == 16 || Radix == 2 ||
+ Radix == 36) &&
"Radix should be 2, 8, 10, or 16!");
const char *Prefix = "";
@@ -2203,7 +2210,7 @@
return;
}
- static const char Digits[] = "0123456789ABCDEF";
+ static const char Digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (isSingleWord()) {
char Buffer[65];
@@ -2257,7 +2264,7 @@
// For the 2, 8 and 16 bit cases, we can just shift instead of divide
// because the number of bits per digit (1, 3 and 4 respectively) divides
// equaly. We just shift until the value is zero.
- if (Radix != 10) {
+ if (Radix == 2 || Radix == 8 || Radix == 16) {
// Just shift tmp right for each digit width until it becomes zero
unsigned ShiftAmt = (Radix == 16 ? 4 : (Radix == 8 ? 3 : 1));
unsigned MaskAmt = Radix - 1;
@@ -2268,7 +2275,7 @@
Tmp = Tmp.lshr(ShiftAmt);
}
} else {
- APInt divisor(4, 10);
+ APInt divisor(Radix == 10? 4 : 8, Radix);
while (Tmp != 0) {
APInt APdigit(1, 0);
APInt tmp2(Tmp.getBitWidth(), 0);
Modified: llvm/trunk/unittests/ADT/APIntTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/APIntTest.cpp?rev=139695&r1=139694&r2=139695&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/APIntTest.cpp (original)
+++ llvm/trunk/unittests/ADT/APIntTest.cpp Wed Sep 14 10:54:46 2011
@@ -237,6 +237,20 @@
EXPECT_EQ(APInt(32, uint64_t(-16LL)), APInt(32, "-10", 16));
EXPECT_EQ(APInt(32, uint64_t(-31LL)), APInt(32, "-1F", 16));
EXPECT_EQ(APInt(32, uint64_t(-32LL)), APInt(32, "-20", 16));
+
+ EXPECT_EQ(APInt(32, 0), APInt(32, "0", 36));
+ EXPECT_EQ(APInt(32, 1), APInt(32, "1", 36));
+ EXPECT_EQ(APInt(32, 35), APInt(32, "Z", 36));
+ EXPECT_EQ(APInt(32, 36), APInt(32, "10", 36));
+ EXPECT_EQ(APInt(32, 71), APInt(32, "1Z", 36));
+ EXPECT_EQ(APInt(32, 72), APInt(32, "20", 36));
+
+ EXPECT_EQ(APInt(32, uint64_t(-0LL)), APInt(32, "-0", 36));
+ EXPECT_EQ(APInt(32, uint64_t(-1LL)), APInt(32, "-1", 36));
+ EXPECT_EQ(APInt(32, uint64_t(-35LL)), APInt(32, "-Z", 36));
+ EXPECT_EQ(APInt(32, uint64_t(-36LL)), APInt(32, "-10", 36));
+ EXPECT_EQ(APInt(32, uint64_t(-71LL)), APInt(32, "-1Z", 36));
+ EXPECT_EQ(APInt(32, uint64_t(-72LL)), APInt(32, "-20", 36));
}
TEST(APIntTest, FromArray) {
@@ -340,6 +354,9 @@
APInt(8, 0).toString(S, 16, true, true);
EXPECT_EQ(S.str().str(), "0x0");
S.clear();
+ APInt(8, 0).toString(S, 36, true, true);
+ EXPECT_EQ(S.str().str(), "0");
+ S.clear();
isSigned = false;
APInt(8, 255, isSigned).toString(S, 2, isSigned, true);
@@ -354,6 +371,9 @@
APInt(8, 255, isSigned).toString(S, 16, isSigned, true);
EXPECT_EQ(S.str().str(), "0xFF");
S.clear();
+ APInt(8, 255, isSigned).toString(S, 36, isSigned, true);
+ EXPECT_EQ(S.str().str(), "73");
+ S.clear();
isSigned = true;
APInt(8, 255, isSigned).toString(S, 2, isSigned, true);
@@ -368,6 +388,9 @@
APInt(8, 255, isSigned).toString(S, 16, isSigned, true);
EXPECT_EQ(S.str().str(), "-0x1");
S.clear();
+ APInt(8, 255, isSigned).toString(S, 36, isSigned, true);
+ EXPECT_EQ(S.str().str(), "-1");
+ S.clear();
}
TEST(APIntTest, Log2) {
@@ -407,7 +430,7 @@
TEST(APIntTest, StringDeath) {
EXPECT_DEATH(APInt(0, "", 0), "Bitwidth too small");
EXPECT_DEATH(APInt(32, "", 0), "Invalid string length");
- EXPECT_DEATH(APInt(32, "0", 0), "Radix should be 2, 8, 10, or 16!");
+ EXPECT_DEATH(APInt(32, "0", 0), "Radix should be 2, 8, 10, 16, or 36!");
EXPECT_DEATH(APInt(32, "", 10), "Invalid string length");
EXPECT_DEATH(APInt(32, "-", 10), "String is only a sign, needs a value.");
EXPECT_DEATH(APInt(1, "1234", 10), "Insufficient bit width");
More information about the llvm-commits
mailing list