This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
labath marked an inline comment as done.
Closed by commit rG8a8a2dd3165e: [lldb/Utility] Simplify Scalar handling of
float types (authored by labath).
Changed prior to commit:
https://reviews.llvm.org/D86220?vs=286567&id=286812#toc
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D86220/new/
https://reviews.llvm.org/D86220
Files:
lldb/include/lldb/Utility/Scalar.h
lldb/source/Utility/Scalar.cpp
lldb/unittests/Utility/ScalarTest.cpp
Index: lldb/unittests/Utility/ScalarTest.cpp
===================================================================
--- lldb/unittests/Utility/ScalarTest.cpp
+++ lldb/unittests/Utility/ScalarTest.cpp
@@ -16,6 +16,7 @@
#include "llvm/Testing/Support/Error.h"
using namespace lldb_private;
+using llvm::APFloat;
using llvm::APInt;
using llvm::Failed;
using llvm::Succeeded;
@@ -304,12 +305,12 @@
EXPECT_FALSE(a.IntegralPromote(64, true));
- EXPECT_TRUE(a.FloatPromote(Scalar::e_double));
- EXPECT_EQ(Scalar::e_double, a.GetType());
+ EXPECT_TRUE(a.FloatPromote(APFloat::IEEEdouble()));
+ EXPECT_EQ(Scalar::e_float, a.GetType());
EXPECT_EQ(47.0, a.Double());
- EXPECT_FALSE(a.FloatPromote(Scalar::e_float));
- EXPECT_TRUE(a.FloatPromote(Scalar::e_long_double));
+ EXPECT_FALSE(a.FloatPromote(APFloat::IEEEsingle()));
+ EXPECT_TRUE(a.FloatPromote(APFloat::x87DoubleExtended()));
EXPECT_EQ(47.0L, a.LongDouble());
}
Index: lldb/source/Utility/Scalar.cpp
===================================================================
--- lldb/source/Utility/Scalar.cpp
+++ lldb/source/Utility/Scalar.cpp
@@ -26,17 +26,11 @@
using llvm::APFloat;
using llvm::APInt;
-namespace {
-enum class Category { Void, Integral, Float };
-}
-
-static Category GetCategory(Scalar::Type type) {
+Scalar::Category Scalar::GetCategory(Scalar::Type type) {
switch (type) {
case Scalar::e_void:
return Category::Void;
case Scalar::e_float:
- case Scalar::e_double:
- case Scalar::e_long_double:
return Category::Float;
case Scalar::e_sint:
case Scalar::e_uint:
@@ -52,49 +46,62 @@
return false;
case Scalar::e_sint:
case Scalar::e_float:
- case Scalar::e_double:
- case Scalar::e_long_double:
return true;
}
llvm_unreachable("Unhandled type!");
}
-Scalar::IntPromotionKey Scalar::GetIntKey() const {
- assert(GetCategory(GetType()) == Category::Integral);
- return {m_integer.getBitWidth(), !IsSigned(m_type)};
+Scalar::PromotionKey Scalar::GetPromoKey() const {
+ Category cat = GetCategory(m_type);
+ switch (cat) {
+ case Category::Void:
+ return {cat, 0, false};
+ case Category::Integral:
+ return {cat, m_integer.getBitWidth(), !IsSigned(m_type)};
+ case Category::Float:
+ return GetFloatPromoKey(m_float.getSemantics());
+ }
+ llvm_unreachable("Unhandled category!");
+}
+
+Scalar::PromotionKey Scalar::GetFloatPromoKey(const llvm::fltSemantics &sem) {
+ static const llvm::fltSemantics *const order[] = {
+ &APFloat::IEEEsingle(), &APFloat::IEEEdouble(),
+ &APFloat::x87DoubleExtended()};
+ for (const auto &entry : llvm::enumerate(order)) {
+ if (entry.value() == &sem)
+ return {Category::Float, entry.index(), false};
+ }
+ llvm_unreachable("Unsupported semantics!");
}
// Promote to max type currently follows the ANSI C rule for type promotion in
// expressions.
Scalar::Type Scalar::PromoteToMaxType(Scalar &lhs, Scalar &rhs) {
const auto &Promote = [](Scalar &a, const Scalar &b) {
- if (GetCategory(b.GetType()) == Category::Integral)
+ switch (GetCategory(b.GetType())) {
+ case Category::Void:
+ break;
+ case Category::Integral:
a.IntegralPromote(b.UInt128(APInt()).getBitWidth(),
IsSigned(b.GetType()));
- else
- a.FloatPromote(b.GetType());
+ break;
+ case Category::Float:
+ a.FloatPromote(b.m_float.getSemantics());
+ }
};
- // Extract the types of both the right and left hand side values
- Scalar::Type lhs_type = lhs.GetType();
- Scalar::Type rhs_type = rhs.GetType();
-
- if (GetCategory(lhs_type) == Category::Integral &&
- GetCategory(rhs_type) == Category::Integral) {
- IntPromotionKey lhs_key = lhs.GetIntKey();
- IntPromotionKey rhs_key = rhs.GetIntKey();
- if (lhs_key > rhs_key)
- Promote(rhs, lhs);
- else if (rhs_key > lhs_key)
- Promote(lhs, rhs);
- } else if (lhs_type > rhs_type)
+ PromotionKey lhs_key = lhs.GetPromoKey();
+ PromotionKey rhs_key = rhs.GetPromoKey();
+
+ if (lhs_key > rhs_key)
Promote(rhs, lhs);
- else if (lhs_type < rhs_type)
+ else if (rhs_key > lhs_key)
Promote(lhs, rhs);
// Make sure our type promotion worked as expected
- if (lhs.GetType() == rhs.GetType())
- return lhs.GetType(); // Return the resulting max type
+ if (lhs.GetPromoKey() == rhs.GetPromoKey())
+ return lhs.GetType(); // Return the resulting type
// Return the void type (zero) if we fail to promote either of the values.
return Scalar::e_void;
@@ -155,11 +162,7 @@
case e_uint:
return (m_integer.getBitWidth() / 8);
case e_float:
- return sizeof(float_t);
- case e_double:
- return sizeof(double_t);
- case e_long_double:
- return sizeof(long_double_t);
+ return m_float.bitcastToAPInt().getBitWidth() / 8;
}
return 0;
}
@@ -203,29 +206,13 @@
m_type = GetBestTypeForBitSize(bits, sign);
}
-static const llvm::fltSemantics &GetFltSemantics(Scalar::Type type) {
- switch (type) {
- case Scalar::e_void:
- case Scalar::e_sint:
- case Scalar::e_uint:
- llvm_unreachable("Only floating point types supported!");
- case Scalar::e_float:
- return llvm::APFloat::IEEEsingle();
- case Scalar::e_double:
- return llvm::APFloat::IEEEdouble();
- case Scalar::e_long_double:
- return llvm::APFloat::x87DoubleExtended();
- }
- llvm_unreachable("Unhandled type!");
-}
-
bool Scalar::IntegralPromote(uint16_t bits, bool sign) {
switch (GetCategory(m_type)) {
case Category::Void:
case Category::Float:
break;
case Category::Integral:
- if (GetIntKey() > IntPromotionKey(bits, !sign))
+ if (GetPromoKey() > PromotionKey(Category::Integral, bits, !sign))
break;
if (IsSigned(m_type))
m_integer = m_integer.sextOrTrunc(bits);
@@ -237,29 +224,27 @@
return false;
}
-bool Scalar::FloatPromote(Scalar::Type type) {
- assert(GetCategory(type) == Category::Float);
+bool Scalar::FloatPromote(const llvm::fltSemantics &semantics) {
bool success = false;
switch (GetCategory(m_type)) {
case Category::Void:
break;
case Category::Integral:
- m_float = llvm::APFloat(GetFltSemantics(type));
+ m_float = llvm::APFloat(semantics);
m_float.convertFromAPInt(m_integer, IsSigned(m_type),
llvm::APFloat::rmNearestTiesToEven);
success = true;
break;
case Category::Float:
- if (type < m_type)
+ if (GetFloatPromoKey(semantics) < GetFloatPromoKey(m_float.getSemantics()))
break;
bool ignore;
success = true;
- m_float.convert(GetFltSemantics(type), llvm::APFloat::rmNearestTiesToEven,
- &ignore);
+ m_float.convert(semantics, llvm::APFloat::rmNearestTiesToEven, &ignore);
}
if (success)
- m_type = type;
+ m_type = e_float;
return success;
}
@@ -273,10 +258,6 @@
return "unsigned int";
case e_float:
return "float";
- case e_double:
- return "double";
- case e_long_double:
- return "long double";
}
return "???";
}
@@ -291,16 +272,6 @@
return e_uint;
}
-Scalar::Type Scalar::GetValueTypeForFloatWithByteSize(size_t byte_size) {
- if (byte_size == sizeof(float_t))
- return e_float;
- if (byte_size == sizeof(double_t))
- return e_double;
- if (byte_size == sizeof(long_double_t))
- return e_long_double;
- return e_void;
-}
-
bool Scalar::MakeSigned() {
bool success = false;
@@ -317,12 +288,6 @@
case e_float:
success = true;
break;
- case e_double:
- success = true;
- break;
- case e_long_double:
- success = true;
- break;
}
return success;
@@ -344,12 +309,6 @@
case e_float:
success = true;
break;
- case e_double:
- success = true;
- break;
- case e_long_double:
- success = true;
- break;
}
return success;
@@ -524,8 +483,6 @@
switch (m_type) {
case e_void:
case e_float:
- case e_double:
- case e_long_double:
m_type = e_void;
break;
@@ -534,8 +491,6 @@
switch (rhs.m_type) {
case e_void:
case e_float:
- case e_double:
- case e_long_double:
m_type = e_void;
break;
case e_sint:
@@ -570,8 +525,6 @@
case e_uint:
return true;
case e_float:
- case e_double:
- case e_long_double:
m_float.clearSign();
return true;
}
@@ -610,13 +563,13 @@
const Scalar lldb_private::operator-(Scalar lhs, Scalar rhs) {
Scalar result;
if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
- switch (GetCategory(result.m_type)) {
- case Category::Void:
+ switch (Scalar::GetCategory(result.m_type)) {
+ case Scalar::Category::Void:
break;
- case Category::Integral:
+ case Scalar::Category::Integral:
result.m_integer = lhs.m_integer - rhs.m_integer;
break;
- case Category::Float:
+ case Scalar::Category::Float:
result.m_float = lhs.m_float - rhs.m_float;
break;
}
@@ -628,16 +581,16 @@
Scalar result;
if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void &&
!rhs.IsZero()) {
- switch (GetCategory(result.m_type)) {
- case Category::Void:
+ switch (Scalar::GetCategory(result.m_type)) {
+ case Scalar::Category::Void:
break;
- case Category::Integral:
+ case Scalar::Category::Integral:
if (IsSigned(result.m_type))
result.m_integer = lhs.m_integer.sdiv(rhs.m_integer);
else
result.m_integer = lhs.m_integer.udiv(rhs.m_integer);
return result;
- case Category::Float:
+ case Scalar::Category::Float:
result.m_float = lhs.m_float / rhs.m_float;
return result;
}
@@ -651,13 +604,13 @@
const Scalar lldb_private::operator*(Scalar lhs, Scalar rhs) {
Scalar result;
if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
- switch (GetCategory(result.m_type)) {
- case Category::Void:
+ switch (Scalar::GetCategory(result.m_type)) {
+ case Scalar::Category::Void:
break;
- case Category::Integral:
+ case Scalar::Category::Integral:
result.m_integer = lhs.m_integer * rhs.m_integer;
break;
- case Category::Float:
+ case Scalar::Category::Float:
result.m_float = lhs.m_float * rhs.m_float;
break;
}
@@ -668,7 +621,7 @@
const Scalar lldb_private::operator&(Scalar lhs, Scalar rhs) {
Scalar result;
if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
- if (GetCategory(result.m_type) == Category::Integral)
+ if (Scalar::GetCategory(result.m_type) == Scalar::Category::Integral)
result.m_integer = lhs.m_integer & rhs.m_integer;
else
result.m_type = Scalar::e_void;
@@ -679,7 +632,7 @@
const Scalar lldb_private::operator|(Scalar lhs, Scalar rhs) {
Scalar result;
if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
- if (GetCategory(result.m_type) == Category::Integral)
+ if (Scalar::GetCategory(result.m_type) == Scalar::Category::Integral)
result.m_integer = lhs.m_integer | rhs.m_integer;
else
result.m_type = Scalar::e_void;
@@ -690,7 +643,8 @@
const Scalar lldb_private::operator%(Scalar lhs, Scalar rhs) {
Scalar result;
if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
- if (!rhs.IsZero() && GetCategory(result.m_type) == Category::Integral) {
+ if (!rhs.IsZero() &&
+ Scalar::GetCategory(result.m_type) == Scalar::Category::Integral) {
if (IsSigned(result.m_type))
result.m_integer = lhs.m_integer.srem(rhs.m_integer);
else
@@ -705,7 +659,7 @@
const Scalar lldb_private::operator^(Scalar lhs, Scalar rhs) {
Scalar result;
if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
- if (GetCategory(result.m_type) == Category::Integral)
+ if (Scalar::GetCategory(result.m_type) == Scalar::Category::Integral)
result.m_integer = lhs.m_integer ^ rhs.m_integer;
else
result.m_type = Scalar::e_void;
@@ -773,16 +727,17 @@
}
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));
+ // FIXME: It's not possible to unambiguously map a byte size to a floating
+ // point type. This function should be refactored to take an explicit
+ // semantics argument.
+ const llvm::fltSemantics &sem =
+ byte_size <= 4 ? APFloat::IEEEsingle()
+ : byte_size <= 8 ? APFloat::IEEEdouble()
+ : APFloat::x87DoubleExtended();
+ APFloat f(sem);
if (llvm::Expected<APFloat::opStatus> op =
f.convertFromString(value_str, APFloat::rmNearestTiesToEven)) {
- m_type = type;
+ m_type = e_float;
m_float = std::move(f);
} else
error = op.takeError();
@@ -854,8 +809,6 @@
switch (m_type) {
case Scalar::e_void:
case Scalar::e_float:
- case Scalar::e_double:
- case Scalar::e_long_double:
return false;
case Scalar::e_sint:
@@ -910,8 +863,6 @@
switch (m_type) {
case Scalar::e_void:
case Scalar::e_float:
- case Scalar::e_double:
- case Scalar::e_long_double:
break;
case Scalar::e_sint:
@@ -942,8 +893,6 @@
case Scalar::e_uint:
return lhs.m_integer == rhs.m_integer;
case Scalar::e_float:
- case Scalar::e_double:
- case Scalar::e_long_double:
result = lhs.m_float.compare(rhs.m_float);
if (result == llvm::APFloat::cmpEqual)
return true;
@@ -968,8 +917,6 @@
case Scalar::e_uint:
return lhs.m_integer.ult(rhs.m_integer);
case Scalar::e_float:
- case Scalar::e_double:
- case Scalar::e_long_double:
result = lhs.m_float.compare(rhs.m_float);
if (result == llvm::APFloat::cmpLessThan)
return true;
@@ -998,8 +945,6 @@
m_integer.clearBit(bit);
return true;
case e_float:
- case e_double:
- case e_long_double:
break;
}
return false;
@@ -1014,8 +959,6 @@
m_integer.setBit(bit);
return true;
case e_float:
- case e_double:
- case e_long_double:
break;
}
return false;
Index: lldb/include/lldb/Utility/Scalar.h
===================================================================
--- lldb/include/lldb/Utility/Scalar.h
+++ lldb/include/lldb/Utility/Scalar.h
@@ -45,8 +45,6 @@
e_sint,
e_uint,
e_float,
- e_double,
- e_long_double
};
// Constructors and Destructors
@@ -70,8 +68,8 @@
: m_type(e_uint), m_integer(sizeof(v) * 8, uint64_t(v), false),
m_float(0.0f) {}
Scalar(float v) : m_type(e_float), m_float(v) {}
- Scalar(double v) : m_type(e_double), m_float(v) {}
- Scalar(long double v) : m_type(e_long_double), m_float(double(v)) {
+ Scalar(double v) : m_type(e_float), m_float(v) {}
+ Scalar(long double v) : m_type(e_float), m_float(double(v)) {
bool ignore;
m_float.convert(llvm::APFloat::x87DoubleExtended(),
llvm::APFloat::rmNearestTiesToEven, &ignore);
@@ -114,15 +112,13 @@
void GetValue(Stream *s, bool show_type) const;
- bool IsValid() const {
- return (m_type >= e_sint) && (m_type <= e_long_double);
- }
+ bool IsValid() const { return (m_type >= e_sint) && (m_type <= e_float); }
/// Convert to an integer with \p bits and the given signedness.
void TruncOrExtendTo(uint16_t bits, bool sign);
bool IntegralPromote(uint16_t bits, bool sign);
- bool FloatPromote(Scalar::Type type);
+ bool FloatPromote(const llvm::fltSemantics &semantics);
bool MakeSigned();
@@ -136,8 +132,6 @@
static Scalar::Type
GetValueTypeForUnsignedIntegerWithByteSize(size_t byte_size);
- static Scalar::Type GetValueTypeForFloatWithByteSize(size_t byte_size);
-
// All operators can benefits from the implicit conversions that will happen
// automagically by the compiler, so no temporary objects will need to be
// created. As a result, we currently don't need a variety of overloaded set
@@ -257,8 +251,13 @@
static Type PromoteToMaxType(Scalar &lhs, Scalar &rhs);
- using IntPromotionKey = std::pair<unsigned, bool>;
- IntPromotionKey GetIntKey() const;
+ enum class Category { Void, Integral, Float };
+ static Category GetCategory(Scalar::Type type);
+
+ using PromotionKey = std::tuple<Category, unsigned, bool>;
+ PromotionKey GetPromoKey() const;
+
+ static PromotionKey GetFloatPromoKey(const llvm::fltSemantics &semantics);
private:
friend const Scalar operator+(const Scalar &lhs, const Scalar &rhs);
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits