[flang-commits] [flang] [llvm] [Flang] Introduce *Value classes with unittests (PR #216958)
Michael Kruse via flang-commits
flang-commits at lists.llvm.org
Mon Sep 21 02:46:49 PDT 2026
================
@@ -0,0 +1,272 @@
+//===-- lib/Evaluate/real-value-impl.h ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_EVALUATE_REAL_VALUE_IMPL_H_
+#define FORTRAN_EVALUATE_REAL_VALUE_IMPL_H_
+
+#include "flang/Evaluate/real.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <type_traits>
+#include <utility>
+#include <variant>
+
+// Some environments, viz. glibc 2.17 and *BSD, allow the macro HUGE
+// to leak out of <math.h>.
+#undef HUGE
+
+namespace llvm {
+class raw_ostream;
+}
+
+namespace Fortran::evaluate::value {
+class IntegerValue;
+
+class RealValueImpl {
+public:
+ using R2 = Real<Integer<16>, 11>; // IEEE half
+ using R3 = Real<Integer<16>, 8>; // bfloat16
+ using R4 = Real<Integer<32>, 24>; // IEEE single
+ using R8 = Real<Integer<64>, 53>; // IEEE double
+ using R10 = Real<X87IntegerContainer, 64>; // 80387 extended precision
+ using R16 = Real<Integer<128>, 113>; // IEEE quad
+ using Storage = std::variant<std::monostate, R2, R3, R4, R8, R10, R16>;
+ using Word = IntegerValue;
+
+ // rule-of-five
+ ~RealValueImpl() = default;
+ RealValueImpl(const RealValueImpl &) = default;
+ RealValueImpl(RealValueImpl &&) = default;
+ RealValueImpl &operator=(const RealValueImpl &) = default;
+ RealValueImpl &operator=(RealValueImpl &&) = default;
+
+ RealValueImpl() = default;
+
+ // Interpret w as the raw bit pattern of a value of the given runtime kind.
+ RealValueImpl(int kind, const Word &w);
+
+ RealValueImpl(int kind, double x);
+
+ static RealValueImpl Zero(int kind);
+
+ template <typename T> static RealValueImpl FromWord(const T &r) {
+ RealValueImpl v;
+ v.storage_ = r;
+ return v;
+ }
+
+ template <typename T>
+ static ValueWithRealFlags<RealValueImpl> FromWord(
+ const ValueWithRealFlags<T> &x) {
+ ValueWithRealFlags<RealValueImpl> r;
+ r.value = FromWord(x.value);
+ r.flags = x.flags;
+ return r;
+ }
+
+ static RealValueImpl FromRawBytes(
+ int kind, const void *raw, std::size_t expectedSize);
+
+ void print(llvm::raw_ostream &os) const;
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ LLVM_DUMP_METHOD void dump() const;
+#endif
+
+ bool IsNull() const { return storage_.index() == 0; }
+ int kind() const;
+
+ int bits() const;
+
+ std::size_t bytesStored() const { return bytesStored(kind()); }
+ static constexpr std::size_t bytesStored(int kind) {
+ switch (kind) {
+ case 3:
+ return 2;
+ case 10:
+ return 16;
+ default:
+ return kind;
+ }
+ }
+
+ bool IsZero() const;
+
+ // Comparison operators
+ bool operator==(const RealValueImpl &y) const;
+ bool operator!=(const RealValueImpl &y) const { return !(*this == y); }
+
+ // Kind-property inquiries, formerly compile-time constants derived from the
+ // PREC template parameter; now selected by the runtime KIND.
+ static int DIGITS(int kind);
+ static int PRECISION(int kind);
+ static int RANGE(int kind);
+ static int MAXEXPONENT(int kind);
+ static int MINEXPONENT(int kind);
+
+ static RealValueImpl HUGE(int kind);
+ static RealValueImpl EPSILON(int kind);
+ static RealValueImpl TINY(int kind);
+ static RealValueImpl NotANumber(int kind);
+ static RealValueImpl Infinity(int kind, bool negative = false);
+ static RealValueImpl NegativeZero(int kind);
+
+ // Runtime kind / width accessors
+ bool IsNegative() const;
+ bool IsNotANumber() const;
+ bool IsSignalingNaN() const;
+ bool IsInfinite() const;
+ bool IsFinite() const;
+ bool IsNormal() const;
+ int Exponent() const;
+ void StoreRawBytes(void *dst, size_t size, bool *changed) const;
+
+ // The raw bit pattern at the value's runtime width.
+ IntegerValue RawBits() const;
+
+ // Comparisons
+ Relation Compare(const RealValueImpl &y) const;
+
+ // Unary operations
+ RealValueImpl ABS() const;
+ RealValueImpl Negate() const;
+ RealValueImpl SIGN(const RealValueImpl &x) const;
+ RealValueImpl SetSign(bool toNegative) const;
+ RealValueImpl FlushSubnormalToZero() const;
+
+ // Binary arithmetic
+ ValueWithRealFlags<RealValueImpl> Add(const RealValueImpl &y,
+ Rounding rounding = TargetCharacteristics::defaultRounding) const;
+ ValueWithRealFlags<RealValueImpl> Subtract(const RealValueImpl &y,
+ Rounding rounding = TargetCharacteristics::defaultRounding) const;
+ ValueWithRealFlags<RealValueImpl> Multiply(const RealValueImpl &y,
+ Rounding rounding = TargetCharacteristics::defaultRounding) const;
+ ValueWithRealFlags<RealValueImpl> Divide(const RealValueImpl &y,
+ Rounding rounding = TargetCharacteristics::defaultRounding) const;
+ ValueWithRealFlags<RealValueImpl> SQRT(
+ Rounding rounding = TargetCharacteristics::defaultRounding) const;
+ ValueWithRealFlags<RealValueImpl> HYPOT(const RealValueImpl &y,
+ Rounding rounding = TargetCharacteristics::defaultRounding) const;
+ ValueWithRealFlags<RealValueImpl> MOD(const RealValueImpl &y,
+ Rounding rounding = TargetCharacteristics::defaultRounding) const;
+ ValueWithRealFlags<RealValueImpl> MODULO(const RealValueImpl &y,
+ Rounding rounding = TargetCharacteristics::defaultRounding) const;
+ ValueWithRealFlags<RealValueImpl> DIM(const RealValueImpl &y,
+ Rounding rounding = TargetCharacteristics::defaultRounding) const;
+
+ RealValueImpl FRACTION() const;
+ RealValueImpl RRSPACING() const;
+ RealValueImpl SPACING() const;
+ RealValueImpl SET_EXPONENT(std::int64_t e) const;
+
+ ValueWithRealFlags<RealValueImpl> NEAREST(bool upward) const;
+ ValueWithRealFlags<RealValueImpl> ToWholeNumber(
+ common::RoundingMode mode = common::RoundingMode::ToZero) const;
+ // Convert this real to an integer of the given bit width.
+ ValueWithRealFlags<IntegerValue> ToInteger(
+ common::RoundingMode mode = common::RoundingMode::ToZero,
+ int toBits = 0) const;
+
+ ValueWithRealFlags<RealValueImpl> SCALE(const IntegerValue &by,
+ Rounding rounding = TargetCharacteristics::defaultRounding) const;
+
+ ValueWithRealFlags<RealValueImpl> KahanSummation(const RealValueImpl &y,
+ RealValueImpl &correction,
+ Rounding rounding = TargetCharacteristics::defaultRounding) const;
+
+ IntegerValue EXPONENT() const;
+
+ // Conversion from an integer facade (REAL()).
+ static ValueWithRealFlags<RealValueImpl> FromInteger(int kind,
+ const IntegerValue &n, bool isUnsigned = false,
+ Rounding rounding = TargetCharacteristics::defaultRounding);
+
+ // Conversion between real kinds.
+ static ValueWithRealFlags<RealValueImpl> Convert(int kind,
+ const RealValueImpl &from,
+ Rounding rounding = TargetCharacteristics::defaultRounding);
+
+ static ValueWithRealFlags<RealValueImpl> Read(int kind, const char *&pp,
+ Rounding rounding = TargetCharacteristics::defaultRounding);
+
+ std::string DumpHexadecimal() const;
+ llvm::raw_ostream &AsFortran(
+ llvm::raw_ostream &o, int kind, bool minimal = false) const;
+
+ template <typename V> static std::decay_t<V> AsWord(const RealValueImpl &y) {
+ using R = std::decay_t<V>;
+ if (y.IsNull()) {
+ return R{};
+ }
+
+ return y.withWord([](const auto &yv) -> R {
+ using YR = std::decay_t<decltype(yv)>;
+ if constexpr (std::is_same_v<YR, R>) {
+ return yv;
+ } else {
+ return R::Convert(yv).value;
----------------
Meinersbur wrote:
Same as above: Going to use `GetWord` that requires the kind to be the same, as suggested.
https://github.com/llvm/llvm-project/pull/216958
More information about the flang-commits
mailing list