mirror of
https://github.com/intel/llvm.git
synced 2026-01-25 19:44:38 +08:00
[LLDB] Add APFloat helper functions to Scalar class. (#86862)
This adds the ability to create a Scalar from an APFloat, and to create an APFloat from an APSInt or another APFloat.
This commit is contained in:
@@ -71,6 +71,7 @@ public:
|
||||
: m_type(e_int), m_integer(std::move(v), false), m_float(0.0f) {}
|
||||
Scalar(llvm::APSInt v)
|
||||
: m_type(e_int), m_integer(std::move(v)), m_float(0.0f) {}
|
||||
Scalar(llvm::APFloat v) : m_type(e_float), m_integer(0), m_float(v) {}
|
||||
|
||||
bool SignExtend(uint32_t bit_pos);
|
||||
|
||||
@@ -186,6 +187,10 @@ public:
|
||||
Status SetValueFromData(const DataExtractor &data, lldb::Encoding encoding,
|
||||
size_t byte_size);
|
||||
|
||||
llvm::APFloat CreateAPFloatFromAPSInt(lldb::BasicType basic_type);
|
||||
|
||||
llvm::APFloat CreateAPFloatFromAPFloat(lldb::BasicType basic_type);
|
||||
|
||||
protected:
|
||||
Scalar::Type m_type = e_void;
|
||||
llvm::APSInt m_integer;
|
||||
|
||||
@@ -813,6 +813,48 @@ bool Scalar::ExtractBitfield(uint32_t bit_size, uint32_t bit_offset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
llvm::APFloat Scalar::CreateAPFloatFromAPSInt(lldb::BasicType basic_type) {
|
||||
switch (basic_type) {
|
||||
case lldb::eBasicTypeFloat:
|
||||
return llvm::APFloat(
|
||||
m_integer.isSigned()
|
||||
? llvm::APIntOps::RoundSignedAPIntToFloat(m_integer)
|
||||
: llvm::APIntOps::RoundAPIntToFloat(m_integer));
|
||||
case lldb::eBasicTypeDouble:
|
||||
// No way to get more precision at the moment.
|
||||
case lldb::eBasicTypeLongDouble:
|
||||
return llvm::APFloat(
|
||||
m_integer.isSigned()
|
||||
? llvm::APIntOps::RoundSignedAPIntToDouble(m_integer)
|
||||
: llvm::APIntOps::RoundAPIntToDouble(m_integer));
|
||||
default:
|
||||
const llvm::fltSemantics &sem = APFloat::IEEEsingle();
|
||||
return llvm::APFloat::getNaN(sem);
|
||||
}
|
||||
}
|
||||
|
||||
llvm::APFloat Scalar::CreateAPFloatFromAPFloat(lldb::BasicType basic_type) {
|
||||
switch (basic_type) {
|
||||
case lldb::eBasicTypeFloat: {
|
||||
bool loses_info;
|
||||
m_float.convert(llvm::APFloat::IEEEsingle(),
|
||||
llvm::APFloat::rmNearestTiesToEven, &loses_info);
|
||||
return m_float;
|
||||
}
|
||||
case lldb::eBasicTypeDouble:
|
||||
// No way to get more precision at the moment.
|
||||
case lldb::eBasicTypeLongDouble: {
|
||||
bool loses_info;
|
||||
m_float.convert(llvm::APFloat::IEEEdouble(),
|
||||
llvm::APFloat::rmNearestTiesToEven, &loses_info);
|
||||
return m_float;
|
||||
}
|
||||
default:
|
||||
const llvm::fltSemantics &sem = APFloat::IEEEsingle();
|
||||
return llvm::APFloat::getNaN(sem);
|
||||
}
|
||||
}
|
||||
|
||||
bool lldb_private::operator==(Scalar lhs, Scalar rhs) {
|
||||
// If either entry is void then we can just compare the types
|
||||
if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
|
||||
|
||||
@@ -402,3 +402,61 @@ TEST(ScalarTest, TruncOrExtendTo) {
|
||||
S.TruncOrExtendTo(16, false);
|
||||
EXPECT_EQ(S.UInt128(APInt()), APInt(16, 0xffffu));
|
||||
}
|
||||
|
||||
TEST(ScalarTest, APFloatConstructor) {
|
||||
llvm::APFloat my_single(llvm::APFloatBase::IEEEsingle(), "3.14159");
|
||||
llvm::APFloat my_double(llvm::APFloatBase::IEEEdouble(), "3.14159");
|
||||
Scalar S(my_single);
|
||||
Scalar D(my_double);
|
||||
|
||||
EXPECT_EQ(S.GetType(), Scalar::e_float);
|
||||
EXPECT_EQ(D.GetType(), Scalar::e_float);
|
||||
ASSERT_TRUE(S != D);
|
||||
}
|
||||
|
||||
TEST(ScalarTest, CreateAPFloats) {
|
||||
llvm::APFloat ap_float(llvm::APFloatBase::IEEEsingle(), "3.14159");
|
||||
llvm::APFloat ap_nan = llvm::APFloat::getNaN(llvm::APFloat::IEEEsingle());
|
||||
llvm::APSInt int1("12");
|
||||
llvm::APSInt int2("-4");
|
||||
Scalar I1(int1);
|
||||
Scalar I2(int2);
|
||||
Scalar F(ap_float);
|
||||
|
||||
llvm::APFloat out1_float = I1.CreateAPFloatFromAPSInt(lldb::eBasicTypeFloat);
|
||||
llvm::APFloat out1_double =
|
||||
I1.CreateAPFloatFromAPSInt(lldb::eBasicTypeDouble);
|
||||
llvm::APFloat out1_longdouble =
|
||||
I1.CreateAPFloatFromAPSInt(lldb::eBasicTypeLongDouble);
|
||||
llvm::APFloat out1_nan =
|
||||
I1.CreateAPFloatFromAPSInt(lldb::eBasicTypeFloatComplex);
|
||||
EXPECT_TRUE(!out1_float.isNegative());
|
||||
EXPECT_TRUE(!out1_double.isNegative());
|
||||
EXPECT_TRUE(out1_double.bitwiseIsEqual(out1_longdouble));
|
||||
EXPECT_FALSE(out1_double.bitwiseIsEqual(out1_float));
|
||||
EXPECT_TRUE(out1_nan.bitwiseIsEqual(ap_nan));
|
||||
|
||||
llvm::APFloat out2_float = I2.CreateAPFloatFromAPSInt(lldb::eBasicTypeFloat);
|
||||
llvm::APFloat out2_double =
|
||||
I2.CreateAPFloatFromAPSInt(lldb::eBasicTypeDouble);
|
||||
llvm::APFloat out2_longdouble =
|
||||
I2.CreateAPFloatFromAPSInt(lldb::eBasicTypeLongDouble);
|
||||
llvm::APFloat out2_nan =
|
||||
I2.CreateAPFloatFromAPSInt(lldb::eBasicTypeFloatComplex);
|
||||
EXPECT_TRUE(out2_float.isNegative());
|
||||
EXPECT_TRUE(out2_double.isNegative());
|
||||
EXPECT_TRUE(out2_double.bitwiseIsEqual(out2_longdouble));
|
||||
EXPECT_FALSE(out2_double.bitwiseIsEqual(out2_float));
|
||||
EXPECT_TRUE(out2_nan.bitwiseIsEqual(ap_nan));
|
||||
|
||||
llvm::APFloat out3_float = F.CreateAPFloatFromAPFloat(lldb::eBasicTypeFloat);
|
||||
llvm::APFloat out3_double =
|
||||
F.CreateAPFloatFromAPFloat(lldb::eBasicTypeDouble);
|
||||
llvm::APFloat out3_longdouble =
|
||||
F.CreateAPFloatFromAPFloat(lldb::eBasicTypeLongDouble);
|
||||
llvm::APFloat out3_nan =
|
||||
F.CreateAPFloatFromAPFloat(lldb::eBasicTypeFloatComplex);
|
||||
EXPECT_TRUE(out3_double.bitwiseIsEqual(out3_longdouble));
|
||||
EXPECT_FALSE(out3_double.bitwiseIsEqual(out3_float));
|
||||
EXPECT_TRUE(out3_nan.bitwiseIsEqual(ap_nan));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user