Skip to content

Commit ba6b2d2

Browse files
authored
[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.
1 parent e005a09 commit ba6b2d2

File tree

3 files changed

+105
-0
lines changed

3 files changed

+105
-0
lines changed

lldb/include/lldb/Utility/Scalar.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class Scalar {
7171
: m_type(e_int), m_integer(std::move(v), false), m_float(0.0f) {}
7272
Scalar(llvm::APSInt v)
7373
: m_type(e_int), m_integer(std::move(v)), m_float(0.0f) {}
74+
Scalar(llvm::APFloat v) : m_type(e_float), m_integer(0), m_float(v) {}
7475

7576
bool SignExtend(uint32_t bit_pos);
7677

@@ -186,6 +187,10 @@ class Scalar {
186187
Status SetValueFromData(const DataExtractor &data, lldb::Encoding encoding,
187188
size_t byte_size);
188189

190+
llvm::APFloat CreateAPFloatFromAPSInt(lldb::BasicType basic_type);
191+
192+
llvm::APFloat CreateAPFloatFromAPFloat(lldb::BasicType basic_type);
193+
189194
protected:
190195
Scalar::Type m_type = e_void;
191196
llvm::APSInt m_integer;

lldb/source/Utility/Scalar.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,48 @@ bool Scalar::ExtractBitfield(uint32_t bit_size, uint32_t bit_offset) {
813813
return false;
814814
}
815815

816+
llvm::APFloat Scalar::CreateAPFloatFromAPSInt(lldb::BasicType basic_type) {
817+
switch (basic_type) {
818+
case lldb::eBasicTypeFloat:
819+
return llvm::APFloat(
820+
m_integer.isSigned()
821+
? llvm::APIntOps::RoundSignedAPIntToFloat(m_integer)
822+
: llvm::APIntOps::RoundAPIntToFloat(m_integer));
823+
case lldb::eBasicTypeDouble:
824+
// No way to get more precision at the moment.
825+
case lldb::eBasicTypeLongDouble:
826+
return llvm::APFloat(
827+
m_integer.isSigned()
828+
? llvm::APIntOps::RoundSignedAPIntToDouble(m_integer)
829+
: llvm::APIntOps::RoundAPIntToDouble(m_integer));
830+
default:
831+
const llvm::fltSemantics &sem = APFloat::IEEEsingle();
832+
return llvm::APFloat::getNaN(sem);
833+
}
834+
}
835+
836+
llvm::APFloat Scalar::CreateAPFloatFromAPFloat(lldb::BasicType basic_type) {
837+
switch (basic_type) {
838+
case lldb::eBasicTypeFloat: {
839+
bool loses_info;
840+
m_float.convert(llvm::APFloat::IEEEsingle(),
841+
llvm::APFloat::rmNearestTiesToEven, &loses_info);
842+
return m_float;
843+
}
844+
case lldb::eBasicTypeDouble:
845+
// No way to get more precision at the moment.
846+
case lldb::eBasicTypeLongDouble: {
847+
bool loses_info;
848+
m_float.convert(llvm::APFloat::IEEEdouble(),
849+
llvm::APFloat::rmNearestTiesToEven, &loses_info);
850+
return m_float;
851+
}
852+
default:
853+
const llvm::fltSemantics &sem = APFloat::IEEEsingle();
854+
return llvm::APFloat::getNaN(sem);
855+
}
856+
}
857+
816858
bool lldb_private::operator==(Scalar lhs, Scalar rhs) {
817859
// If either entry is void then we can just compare the types
818860
if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)

lldb/unittests/Utility/ScalarTest.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,3 +402,61 @@ TEST(ScalarTest, TruncOrExtendTo) {
402402
S.TruncOrExtendTo(16, false);
403403
EXPECT_EQ(S.UInt128(APInt()), APInt(16, 0xffffu));
404404
}
405+
406+
TEST(ScalarTest, APFloatConstructor) {
407+
llvm::APFloat my_single(llvm::APFloatBase::IEEEsingle(), "3.14159");
408+
llvm::APFloat my_double(llvm::APFloatBase::IEEEdouble(), "3.14159");
409+
Scalar S(my_single);
410+
Scalar D(my_double);
411+
412+
EXPECT_EQ(S.GetType(), Scalar::e_float);
413+
EXPECT_EQ(D.GetType(), Scalar::e_float);
414+
ASSERT_TRUE(S != D);
415+
}
416+
417+
TEST(ScalarTest, CreateAPFloats) {
418+
llvm::APFloat ap_float(llvm::APFloatBase::IEEEsingle(), "3.14159");
419+
llvm::APFloat ap_nan = llvm::APFloat::getNaN(llvm::APFloat::IEEEsingle());
420+
llvm::APSInt int1("12");
421+
llvm::APSInt int2("-4");
422+
Scalar I1(int1);
423+
Scalar I2(int2);
424+
Scalar F(ap_float);
425+
426+
llvm::APFloat out1_float = I1.CreateAPFloatFromAPSInt(lldb::eBasicTypeFloat);
427+
llvm::APFloat out1_double =
428+
I1.CreateAPFloatFromAPSInt(lldb::eBasicTypeDouble);
429+
llvm::APFloat out1_longdouble =
430+
I1.CreateAPFloatFromAPSInt(lldb::eBasicTypeLongDouble);
431+
llvm::APFloat out1_nan =
432+
I1.CreateAPFloatFromAPSInt(lldb::eBasicTypeFloatComplex);
433+
EXPECT_TRUE(!out1_float.isNegative());
434+
EXPECT_TRUE(!out1_double.isNegative());
435+
EXPECT_TRUE(out1_double.bitwiseIsEqual(out1_longdouble));
436+
EXPECT_FALSE(out1_double.bitwiseIsEqual(out1_float));
437+
EXPECT_TRUE(out1_nan.bitwiseIsEqual(ap_nan));
438+
439+
llvm::APFloat out2_float = I2.CreateAPFloatFromAPSInt(lldb::eBasicTypeFloat);
440+
llvm::APFloat out2_double =
441+
I2.CreateAPFloatFromAPSInt(lldb::eBasicTypeDouble);
442+
llvm::APFloat out2_longdouble =
443+
I2.CreateAPFloatFromAPSInt(lldb::eBasicTypeLongDouble);
444+
llvm::APFloat out2_nan =
445+
I2.CreateAPFloatFromAPSInt(lldb::eBasicTypeFloatComplex);
446+
EXPECT_TRUE(out2_float.isNegative());
447+
EXPECT_TRUE(out2_double.isNegative());
448+
EXPECT_TRUE(out2_double.bitwiseIsEqual(out2_longdouble));
449+
EXPECT_FALSE(out2_double.bitwiseIsEqual(out2_float));
450+
EXPECT_TRUE(out2_nan.bitwiseIsEqual(ap_nan));
451+
452+
llvm::APFloat out3_float = F.CreateAPFloatFromAPFloat(lldb::eBasicTypeFloat);
453+
llvm::APFloat out3_double =
454+
F.CreateAPFloatFromAPFloat(lldb::eBasicTypeDouble);
455+
llvm::APFloat out3_longdouble =
456+
F.CreateAPFloatFromAPFloat(lldb::eBasicTypeLongDouble);
457+
llvm::APFloat out3_nan =
458+
F.CreateAPFloatFromAPFloat(lldb::eBasicTypeFloatComplex);
459+
EXPECT_TRUE(out3_double.bitwiseIsEqual(out3_longdouble));
460+
EXPECT_FALSE(out3_double.bitwiseIsEqual(out3_float));
461+
EXPECT_TRUE(out3_nan.bitwiseIsEqual(ap_nan));
462+
}

0 commit comments

Comments
 (0)