llvm::APInt m_integer;
llvm::APFloat m_float;
- template <typename T> T GetAsSigned(T fail_value) const;
- template <typename T> T GetAsUnsigned(T fail_value) const;
+ template <typename T> T GetAs(T fail_value) const;
private:
friend const Scalar operator+(const Scalar &lhs, const Scalar &rhs);
if (ResolveValue(scalar)) {
if (success)
*success = true;
+ scalar.MakeUnsigned();
return scalar.ULongLong(fail_value);
}
// fallthrough, otherwise...
if (ResolveValue(scalar)) {
if (success)
*success = true;
+ scalar.MakeSigned();
return scalar.SLongLong(fail_value);
}
// fallthrough, otherwise...
return std::string(ss.GetString());
}
- bool AssignToMatchType(lldb_private::Scalar &scalar, uint64_t u64value,
+ bool AssignToMatchType(lldb_private::Scalar &scalar, llvm::APInt value,
Type *type) {
size_t type_size = m_target_data.getTypeStoreSize(type);
if (type_size != 1)
type_size = PowerOf2Ceil(type_size);
- scalar = llvm::APInt(type_size*8, u64value);
+ scalar = value.zextOrTrunc(type_size * 8);
return true;
}
if (!ResolveConstantValue(value_apint, constant))
return false;
- return AssignToMatchType(scalar, value_apint.getLimitedValue(),
- value->getType());
+ return AssignToMatchType(scalar, value_apint, value->getType());
}
lldb::addr_t process_address = ResolveValue(value, module);
lldb::offset_t offset = 0;
if (value_size <= 8) {
uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size);
- return AssignToMatchType(scalar, u64value, value->getType());
+ return AssignToMatchType(scalar, llvm::APInt(64, u64value),
+ value->getType());
}
return false;
}
- bool AssignValue(const Value *value, lldb_private::Scalar &scalar,
+ bool AssignValue(const Value *value, lldb_private::Scalar scalar,
Module &module) {
lldb::addr_t process_address = ResolveValue(value, module);
lldb_private::Scalar cast_scalar;
- if (!AssignToMatchType(cast_scalar, scalar.ULongLong(), value->getType()))
+ scalar.MakeUnsigned();
+ if (!AssignToMatchType(cast_scalar, scalar.UInt128(llvm::APInt()),
+ value->getType()))
return false;
size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType());
return success;
}
-template <typename T> T Scalar::GetAsSigned(T fail_value) const {
- switch (GetCategory(m_type)) {
- case Category::Void:
- break;
- case Category::Integral:
- return m_integer.sextOrTrunc(sizeof(T) * 8).getSExtValue();
-
- case Category::Float: {
- llvm::APSInt result(sizeof(T) * 8, /*isUnsigned=*/false);
- bool isExact;
- m_float.convertToInteger(result, llvm::APFloat::rmTowardZero, &isExact);
- return result.getSExtValue();
- }
- }
- return fail_value;
-}
-
-template <typename T> T Scalar::GetAsUnsigned(T fail_value) const {
+template <typename T> T Scalar::GetAs(T fail_value) const {
switch (GetCategory(m_type)) {
case Category::Void:
break;
case Category::Integral:
+ if (IsSigned(m_type))
+ return m_integer.sextOrTrunc(sizeof(T) * 8).getSExtValue();
return m_integer.zextOrTrunc(sizeof(T) * 8).getZExtValue();
case Category::Float: {
- llvm::APSInt result(sizeof(T) * 8, /*isUnsigned=*/true);
+ llvm::APSInt result(sizeof(T) * 8, std::is_unsigned<T>::value);
bool isExact;
m_float.convertToInteger(result, llvm::APFloat::rmTowardZero, &isExact);
- return result.getZExtValue();
+ return result.getSExtValue();
}
}
return fail_value;
}
signed char Scalar::SChar(signed char fail_value) const {
- return GetAsSigned<signed char>(fail_value);
+ return GetAs<signed char>(fail_value);
}
unsigned char Scalar::UChar(unsigned char fail_value) const {
- return GetAsUnsigned<unsigned char>(fail_value);
+ return GetAs<unsigned char>(fail_value);
}
short Scalar::SShort(short fail_value) const {
- return GetAsSigned<short>(fail_value);
+ return GetAs<short>(fail_value);
}
unsigned short Scalar::UShort(unsigned short fail_value) const {
- return GetAsUnsigned<unsigned short>(fail_value);
+ return GetAs<unsigned short>(fail_value);
}
-int Scalar::SInt(int fail_value) const { return GetAsSigned<int>(fail_value); }
+int Scalar::SInt(int fail_value) const { return GetAs<int>(fail_value); }
unsigned int Scalar::UInt(unsigned int fail_value) const {
- return GetAsUnsigned<unsigned int>(fail_value);
+ return GetAs<unsigned int>(fail_value);
}
-long Scalar::SLong(long fail_value) const { return GetAsSigned<long>(fail_value); }
+long Scalar::SLong(long fail_value) const { return GetAs<long>(fail_value); }
unsigned long Scalar::ULong(unsigned long fail_value) const {
- return GetAsUnsigned<unsigned long>(fail_value);
+ return GetAs<unsigned long>(fail_value);
}
long long Scalar::SLongLong(long long fail_value) const {
- return GetAsSigned<long long>(fail_value);
+ return GetAs<long long>(fail_value);
}
unsigned long long Scalar::ULongLong(unsigned long long fail_value) const {
- return GetAsUnsigned<unsigned long long>(fail_value);
+ return GetAs<unsigned long long>(fail_value);
}
llvm::APInt Scalar::SInt128(const llvm::APInt &fail_value) const {
case e_void:
break;
case e_sint:
- case e_uint:
case e_slong:
- case e_ulong:
case e_slonglong:
- case e_ulonglong:
case e_sint128:
- case e_uint128:
case e_sint256:
- case e_uint256:
case e_sint512:
+ return llvm::APIntOps::RoundSignedAPIntToFloat(m_integer);
+
+ case e_uint:
+ case e_ulong:
+ case e_ulonglong:
+ case e_uint128:
+ case e_uint256:
case e_uint512:
return llvm::APIntOps::RoundAPIntToFloat(m_integer);
+
case e_float:
return m_float.convertToFloat();
case e_double:
case e_void:
break;
case e_sint:
- case e_uint:
case e_slong:
- case e_ulong:
case e_slonglong:
- case e_ulonglong:
case e_sint128:
- case e_uint128:
case e_sint256:
- case e_uint256:
case e_sint512:
+ return llvm::APIntOps::RoundSignedAPIntToDouble(m_integer);
+
+ case e_uint:
+ case e_ulong:
+ case e_ulonglong:
+ case e_uint128:
+ case e_uint256:
case e_uint512:
return llvm::APIntOps::RoundAPIntToDouble(m_integer);
+
case e_float:
return static_cast<double_t>(m_float.convertToFloat());
case e_double:
case e_void:
break;
case e_sint:
- case e_uint:
case e_slong:
- case e_ulong:
case e_slonglong:
- case e_ulonglong:
case e_sint128:
- case e_uint128:
case e_sint256:
- case e_uint256:
case e_sint512:
+ return static_cast<long_double_t>(
+ llvm::APIntOps::RoundSignedAPIntToDouble(m_integer));
+
+ case e_uint:
+ case e_ulong:
+ case e_ulonglong:
+ case e_uint128:
+ case e_uint256:
case e_uint512:
return static_cast<long_double_t>(
llvm::APIntOps::RoundAPIntToDouble(m_integer));
+
case e_float:
return static_cast<long_double_t>(m_float.convertToFloat());
case e_double:
options = lldb.SBExpressionOptions()
options.SetLanguage(lldb.eLanguageTypeC_plus_plus)
- set_up_expressions = ["int $i = 9", "int $j = 3", "int $k = 5"]
+ set_up_expressions = ["int $i = 9", "int $j = 3", "int $k = 5",
+ "unsigned long long $ull = -1", "unsigned $u = -1"]
expressions = ["$i + $j",
"$i - $j",
"$i << $j",
"$i & $j",
"$i | $j",
- "$i ^ $j"]
+ "$i ^ $j",
+ "($ull & -1) == $u"]
for expression in set_up_expressions:
self.frame().EvaluateExpression(expression, options)
ASSERT_TRUE(s2 >= s1);
}
+template <typename T1, typename T2>
+static T2 ConvertHost(T1 val, T2 (Scalar::*)(T2) const) {
+ return T2(val);
+}
+
+template <typename T1, typename T2>
+static T2 ConvertScalar(T1 val, T2 (Scalar::*conv)(T2) const) {
+ return (Scalar(val).*conv)(T2());
+}
+
+template <typename T> static void CheckConversion(T val) {
+ SCOPED_TRACE("val = " + std::to_string(val));
+ EXPECT_EQ((signed char)val, Scalar(val).SChar());
+ EXPECT_EQ((unsigned char)val, Scalar(val).UChar());
+ EXPECT_EQ((short)val, Scalar(val).SShort());
+ EXPECT_EQ((unsigned short)val, Scalar(val).UShort());
+ EXPECT_EQ((int)val, Scalar(val).SInt());
+ EXPECT_EQ((unsigned)val, Scalar(val).UInt());
+ EXPECT_EQ((long)val, Scalar(val).SLong());
+ EXPECT_EQ((unsigned long)val, Scalar(val).ULong());
+ EXPECT_EQ((long long)val, Scalar(val).SLongLong());
+ EXPECT_EQ((unsigned long long)val, Scalar(val).ULongLong());
+ EXPECT_NEAR((float)val, Scalar(val).Float(), std::abs(val / 1e6));
+ EXPECT_NEAR((double)val, Scalar(val).Double(), std::abs(val / 1e12));
+ EXPECT_NEAR((long double)val, Scalar(val).LongDouble(), std::abs(val / 1e12));
+}
+
+TEST(ScalarTest, Getters) {
+ CheckConversion<int>(0x87654321);
+ CheckConversion<unsigned int>(0x87654321u);
+ CheckConversion<long>(0x87654321l);
+ CheckConversion<unsigned long>(0x87654321ul);
+ CheckConversion<long long>(0x8765432112345678ll);
+ CheckConversion<unsigned long long>(0x8765432112345678ull);
+ CheckConversion<float>(42.25f);
+ CheckConversion<double>(42.25);
+}
+
TEST(ScalarTest, RightShiftOperator) {
int a = 0x00001000;
int b = 0xFFFFFFFF;
TEST(ScalarTest, TruncOrExtendTo) {
Scalar S(0xffff);
S.TruncOrExtendTo(12, true);
- EXPECT_EQ(S.ULong(), 0xfffu);
+ EXPECT_EQ(S.UInt128(APInt()), APInt(12, 0xfffu));
S.TruncOrExtendTo(20, true);
- EXPECT_EQ(S.ULong(), 0xfffffu);
+ EXPECT_EQ(S.UInt128(APInt()), APInt(20, 0xfffffu));
S.TruncOrExtendTo(24, false);
- EXPECT_EQ(S.ULong(), 0x0fffffu);
+ EXPECT_EQ(S.UInt128(APInt()), APInt(24, 0x0fffffu));
S.TruncOrExtendTo(16, false);
- EXPECT_EQ(S.ULong(), 0xffffu);
+ EXPECT_EQ(S.UInt128(APInt()), APInt(16, 0xffffu));
}