ADT: Add a string APSInt constructor.
authorAlex Lorenz <arphaman@gmail.com>
Tue, 23 Jun 2015 18:22:10 +0000 (18:22 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Tue, 23 Jun 2015 18:22:10 +0000 (18:22 +0000)
This commit moves the APSInt initialization code that's used by
the LLLexer class into a new APSInt constructor that constructs
APSInts from strings.

This change is useful for MIR Serialization, as it would allow
the MILexer class to use the same APSInt initialization as
LLexer when parsing immediate machine operands.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@240436 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/APSInt.h
lib/AsmParser/LLLexer.cpp
lib/Support/APSInt.cpp
unittests/ADT/APSIntTest.cpp

index 91ccda22f2f0befee3d38ed127833bce9aa44fbf..a187515f859291dbf1fc9c533f027971b99790c6 100644 (file)
@@ -33,6 +33,15 @@ public:
   explicit APSInt(APInt I, bool isUnsigned = true)
    : APInt(std::move(I)), IsUnsigned(isUnsigned) {}
 
+  /// Construct an APSInt from a string representation.
+  ///
+  /// This constructor interprets the string \p Str using the radix of 10.
+  /// The interpretation stops at the end of the string. The bit width of the
+  /// constructed APSInt is determined automatically.
+  ///
+  /// \param Str the string to be interpreted.
+  explicit APSInt(StringRef Str);
+
   APSInt &operator=(APInt RHS) {
     // Retain our current sign.
     APInt::operator=(std::move(RHS));
index 0bdc3506a30a051e1bda75d38df1c480441b329b..88f359d4fd5ccf0c49b7be59826c339de20763fe 100644 (file)
@@ -903,20 +903,7 @@ lltok::Kind LLLexer::LexDigitOrNegative() {
   if (CurPtr[0] != '.') {
     if (TokStart[0] == '0' && TokStart[1] == 'x')
       return Lex0x();
-    unsigned Len = CurPtr-TokStart;
-    uint32_t numBits = ((Len * 64) / 19) + 2;
-    APInt Tmp(numBits, StringRef(TokStart, Len), 10);
-    if (TokStart[0] == '-') {
-      uint32_t minBits = Tmp.getMinSignedBits();
-      if (minBits > 0 && minBits < numBits)
-        Tmp = Tmp.trunc(minBits);
-      APSIntVal = APSInt(Tmp, false);
-    } else {
-      uint32_t activeBits = Tmp.getActiveBits();
-      if (activeBits > 0 && activeBits < numBits)
-        Tmp = Tmp.trunc(activeBits);
-      APSIntVal = APSInt(Tmp, true);
-    }
+    APSIntVal = APSInt(StringRef(TokStart, CurPtr - TokStart));
     return lltok::APSInt;
   }
 
index 73acafa690c7b14f6bd18a407a91c95000043ad0..975457c070a59e504d687345dd344903402dcf7a 100644 (file)
 
 using namespace llvm;
 
+APSInt::APSInt(StringRef Str) {
+  assert(!Str.empty() && "Invalid string length");
+
+  // (Over-)estimate the required number of bits.
+  unsigned NumBits = ((Str.size() * 64) / 19) + 2;
+  APInt Tmp(NumBits, Str, /*Radix=*/10);
+  if (Str[0] == '-') {
+    unsigned MinBits = Tmp.getMinSignedBits();
+    if (MinBits > 0 && MinBits < NumBits)
+      Tmp = Tmp.trunc(MinBits);
+    *this = APSInt(Tmp, /*IsUnsigned=*/false);
+    return;
+  }
+  unsigned ActiveBits = Tmp.getActiveBits();
+  if (ActiveBits > 0 && ActiveBits < NumBits)
+    Tmp = Tmp.trunc(ActiveBits);
+  *this = APSInt(Tmp, /*IsUnsigned=*/true);
+}
+
 void APSInt::Profile(FoldingSetNodeID& ID) const {
   ID.AddInteger((unsigned) (IsUnsigned ? 1 : 0));
   APInt::Profile(ID);
index 5e4e87440bdb7eada411445d8229052567549ceb..44430055e90cb6d93c94f293354170f2d5b5bfbd 100644 (file)
@@ -143,4 +143,23 @@ TEST(APSIntTest, compareValues) {
   EXPECT_TRUE(APSInt::compareValues(U(8), S(-7).trunc(32)) > 0);
 }
 
+TEST(APSIntTest, FromString) {
+  EXPECT_EQ(APSInt("1").getExtValue(), 1);
+  EXPECT_EQ(APSInt("-1").getExtValue(), -1);
+  EXPECT_EQ(APSInt("0").getExtValue(), 0);
+  EXPECT_EQ(APSInt("56789").getExtValue(), 56789);
+  EXPECT_EQ(APSInt("-1234").getExtValue(), -1234);
 }
+
+#ifdef GTEST_HAS_DEATH_TEST
+#ifndef NDEBUG
+
+TEST(APSIntTest, StringDeath) {
+  EXPECT_DEATH(APSInt(""), "Invalid string length");
+  EXPECT_DEATH(APSInt("1a"), "Invalid character in digit string");
+}
+
+#endif
+#endif
+
+} // end anonymous namespace