Author: Pavel Labath Date: 2020-07-13T16:44:42+02:00 New Revision: 1847f4dd7570f01f70646cd5067dd0c34257cd21
URL: https://github.com/llvm/llvm-project/commit/1847f4dd7570f01f70646cd5067dd0c34257cd21 DIFF: https://github.com/llvm/llvm-project/commit/1847f4dd7570f01f70646cd5067dd0c34257cd21.diff LOG: [lldb/Utility] Rewrite Scalar::SetValueFromCString The function's reliance on host types meant that it was needlessly complicated, and did not handle the newer (wider) types. Rewrite it in terms of APInt/APFloat functions to save code and improve functionality. Added: Modified: lldb/source/Utility/Scalar.cpp lldb/unittests/Utility/ScalarTest.cpp Removed: ################################################################################ diff --git a/lldb/source/Utility/Scalar.cpp b/lldb/source/Utility/Scalar.cpp index 87ac6c23892d..6c48bbde532f 100644 --- a/lldb/source/Utility/Scalar.cpp +++ b/lldb/source/Utility/Scalar.cpp @@ -24,6 +24,7 @@ using namespace lldb; using namespace lldb_private; using llvm::APFloat; +using llvm::APInt; namespace { enum class Category { Void, Integral, Float }; @@ -1002,116 +1003,60 @@ Status Scalar::SetValueFromCString(const char *value_str, Encoding encoding, error.SetErrorString("Invalid encoding."); break; - case eEncodingUint: - if (byte_size <= sizeof(uint64_t)) { - uint64_t uval64; - if (!llvm::to_integer(value_str, uval64)) - error.SetErrorStringWithFormat( - "'%s' is not a valid unsigned integer string value", value_str); - else if (!UIntValueIsValidForSize(uval64, byte_size)) - error.SetErrorStringWithFormat( - "value 0x%" PRIx64 " is too large to fit in a %" PRIu64 - " byte unsigned integer value", - uval64, static_cast<uint64_t>(byte_size)); - else { - m_type = Scalar::GetValueTypeForUnsignedIntegerWithByteSize(byte_size); - switch (m_type) { - case e_uint: - m_integer = llvm::APInt(sizeof(uint_t) * 8, uval64, false); - break; - case e_ulong: - m_integer = llvm::APInt(sizeof(ulong_t) * 8, uval64, false); - break; - case e_ulonglong: - m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, uval64, false); - break; - default: - error.SetErrorStringWithFormat( - "unsupported unsigned integer byte size: %" PRIu64 "", - static_cast<uint64_t>(byte_size)); - break; - } - } - } else { - error.SetErrorStringWithFormat( - "unsupported unsigned integer byte size: %" PRIu64 "", - static_cast<uint64_t>(byte_size)); - return error; - } - break; - case eEncodingSint: - if (byte_size <= sizeof(int64_t)) { - int64_t sval64; - if (!llvm::to_integer(value_str, sval64)) - error.SetErrorStringWithFormat( - "'%s' is not a valid signed integer string value", value_str); - else if (!SIntValueIsValidForSize(sval64, byte_size)) - error.SetErrorStringWithFormat( - "value 0x%" PRIx64 " is too large to fit in a %" PRIu64 - " byte signed integer value", - sval64, static_cast<uint64_t>(byte_size)); - else { - m_type = Scalar::GetValueTypeForSignedIntegerWithByteSize(byte_size); - switch (m_type) { - case e_sint: - m_integer = llvm::APInt(sizeof(sint_t) * 8, sval64, true); - break; - case e_slong: - m_integer = llvm::APInt(sizeof(slong_t) * 8, sval64, true); - break; - case e_slonglong: - m_integer = llvm::APInt(sizeof(slonglong_t) * 8, sval64, true); - break; - default: - error.SetErrorStringWithFormat( - "unsupported signed integer byte size: %" PRIu64 "", - static_cast<uint64_t>(byte_size)); - break; - } - } - } else { - error.SetErrorStringWithFormat( - "unsupported signed integer byte size: %" PRIu64 "", - static_cast<uint64_t>(byte_size)); - return error; + case eEncodingUint: { + llvm::StringRef str = value_str; + bool is_signed = encoding == eEncodingSint; + bool is_negative = is_signed && str.consume_front("-"); + APInt integer; + if (str.getAsInteger(0, integer)) { + error.SetErrorStringWithFormatv( + "'{0}' is not a valid integer string value", value_str); + break; + } + bool fits; + if (is_signed) { + integer = integer.zext(integer.getBitWidth() + 1); + if (is_negative) + integer.negate(); + fits = integer.isSignedIntN(byte_size * 8); + } else + fits = integer.isIntN(byte_size * 8); + if (!fits) { + error.SetErrorStringWithFormatv( + "value {0} is too large to fit in a {1} byte integer value", + value_str, byte_size); + break; + } + m_type = GetBestTypeForBitSize(8 * byte_size, is_signed); + if (m_type == e_void) { + error.SetErrorStringWithFormatv("unsupported integer byte size: {0}", + byte_size); + break; } + if (is_signed) + m_integer = integer.sextOrTrunc(GetBitSize(m_type)); + else + m_integer = integer.zextOrTrunc(GetBitSize(m_type)); break; + } - case eEncodingIEEE754: - static float f_val; - static double d_val; - static long double l_val; - if (byte_size == sizeof(float)) { - if (::sscanf(value_str, "%f", &f_val) == 1) { - m_float = llvm::APFloat(f_val); - m_type = e_float; - } else - error.SetErrorStringWithFormat("'%s' is not a valid float string value", - value_str); - } else if (byte_size == sizeof(double)) { - if (::sscanf(value_str, "%lf", &d_val) == 1) { - m_float = llvm::APFloat(d_val); - m_type = e_double; - } else - error.SetErrorStringWithFormat("'%s' is not a valid float string value", - value_str); - } else if (byte_size == sizeof(long double)) { - if (::sscanf(value_str, "%Lf", &l_val) == 1) { - m_float = llvm::APFloat( - llvm::APFloat::x87DoubleExtended(), - llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, - (reinterpret_cast<type128 *>(&l_val))->x)); - m_type = e_long_double; - } else - error.SetErrorStringWithFormat("'%s' is not a valid float string value", - value_str); - } else { - error.SetErrorStringWithFormat("unsupported float byte size: %" PRIu64 "", - static_cast<uint64_t>(byte_size)); - return error; + case eEncodingIEEE754: { + Type type = GetValueTypeForFloatWithByteSize(byte_size); + if (type == e_void) { + error.SetErrorStringWithFormatv("unsupported float byte size: {0}", + byte_size); + break; } + APFloat f(GetFltSemantics(type)); + if (llvm::Expected<APFloat::opStatus> op = + f.convertFromString(value_str, APFloat::rmNearestTiesToEven)) { + m_type = type; + m_float = std::move(f); + } else + error = op.takeError(); break; + } case eEncodingVector: error.SetErrorString("vector encoding unsupported."); diff --git a/lldb/unittests/Utility/ScalarTest.cpp b/lldb/unittests/Utility/ScalarTest.cpp index 42a2f2aaebf2..dd4683145b96 100644 --- a/lldb/unittests/Utility/ScalarTest.cpp +++ b/lldb/unittests/Utility/ScalarTest.cpp @@ -334,6 +334,20 @@ TEST(ScalarTest, SetValueFromCString) { EXPECT_THAT_ERROR( a.SetValueFromCString("-123", lldb::eEncodingUint, 8).ToError(), Failed()); + EXPECT_THAT_ERROR( + a.SetValueFromCString("-2147483648", lldb::eEncodingSint, 4).ToError(), + Succeeded()); + EXPECT_EQ(-2147483648, a); + EXPECT_THAT_ERROR( + a.SetValueFromCString("-2147483649", lldb::eEncodingSint, 4).ToError(), + Failed()); + EXPECT_THAT_ERROR( + a.SetValueFromCString("47.25", lldb::eEncodingIEEE754, 4).ToError(), + Succeeded()); + EXPECT_EQ(47.25f, a); + EXPECT_THAT_ERROR( + a.SetValueFromCString("asdf", lldb::eEncodingIEEE754, 4).ToError(), + Failed()); } TEST(ScalarTest, APIntConstructor) { _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits