From 6f8a6be145875d96ed4e4ee78099805ddabfaaa0 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Tue, 23 Jun 2015 18:22:10 +0000 Subject: [PATCH] ADT: Add a string APSInt constructor. 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. llvm-svn: 240436 --- llvm/include/llvm/ADT/APSInt.h | 9 +++++++++ llvm/lib/AsmParser/LLLexer.cpp | 15 +-------------- llvm/lib/Support/APSInt.cpp | 19 +++++++++++++++++++ llvm/unittests/ADT/APSIntTest.cpp | 19 +++++++++++++++++++ 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/llvm/include/llvm/ADT/APSInt.h b/llvm/include/llvm/ADT/APSInt.h index 91ccda22f2f0..a187515f8592 100644 --- a/llvm/include/llvm/ADT/APSInt.h +++ b/llvm/include/llvm/ADT/APSInt.h @@ -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)); diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 0bdc3506a30a..88f359d4fd5c 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -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; } diff --git a/llvm/lib/Support/APSInt.cpp b/llvm/lib/Support/APSInt.cpp index 73acafa690c7..975457c070a5 100644 --- a/llvm/lib/Support/APSInt.cpp +++ b/llvm/lib/Support/APSInt.cpp @@ -17,6 +17,25 @@ 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); diff --git a/llvm/unittests/ADT/APSIntTest.cpp b/llvm/unittests/ADT/APSIntTest.cpp index 5e4e87440bdb..44430055e90c 100644 --- a/llvm/unittests/ADT/APSIntTest.cpp +++ b/llvm/unittests/ADT/APSIntTest.cpp @@ -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