Skip to content

[LLDB] Add APFloat helper functions to Scalar class. #86862

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lldb/include/lldb/Utility/Scalar.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class Scalar {
: 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);

Expand Down Expand Up @@ -186,6 +187,10 @@ class Scalar {
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;
Expand Down
42 changes: 42 additions & 0 deletions lldb/source/Utility/Scalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
58 changes: 58 additions & 0 deletions lldb/unittests/Utility/ScalarTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}