[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:22:00 PDT 2026


================
@@ -0,0 +1,626 @@
+//===-- lib/Evaluate/integer-value.cpp ------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "integer-value-impl.h"
+#include "flang/Evaluate/integer-value.h"
+#include <new>
+
+namespace Fortran::evaluate::value {
+
+IntegerValueImpl IntegerValueImpl::Zero(int kind) {
+  return withWordProto(kind, [](auto proto) {
+    using T = decltype(proto);
+    return FromWord(T{});
+  });
+}
+
+IntegerValueImpl IntegerValueImpl::FromRawBytes(
+    int kind, const void *raw, std::size_t expectedSize) {
+  CHECK(expectedSize == IntegerValue::bytesStored(kind));
+
+  return withWordProto(kind, [&](auto proto) {
+    assert(IntegerValue::bytesStored(kind) == sizeof(proto));
+    std::decay_t<decltype(proto)> t{};
+    memcpy(&t, raw, sizeof(proto));
+    return FromWord(t);
+  });
+}
+
+void IntegerValueImpl::print(llvm::raw_ostream &os) const {
+  os << SignedDecimal() << '_' << kind();
+}
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void IntegerValueImpl::dump() const {
+  print(llvm::errs());
+  llvm::errs() << '\n';
+}
+#endif
+
+int IntegerValueImpl::kind() const {
+  if (IsNull()) {
+    DIE("default-initialized value representing 0 with unknown "
+        "width does not know its kind");
+    return 0;
+  }
+  return withWord(
+      [](const auto &x) -> int { return std::decay_t<decltype(x)>::bits / 8; });
+}
+
+int IntegerValueImpl::bits() const {
+  if (IsNull()) {
+    return 0;
+  }
+  return withWord(
+      [](const auto &x) -> int { return std::decay_t<decltype(x)>::bits; });
+}
+
+bool IntegerValueImpl::IsZero() const {
+  if (IsNull()) {
+    return true; // uninitialized int representing 0 is zero
+  }
+  return withWord([](const auto &x) { return x.IsZero(); });
+}
+
+bool IntegerValueImpl::operator==(const IntegerValueImpl &y) const {
+  if (IsNull() && y.IsNull()) {
+    return true;
+  }
+  if (IsNull() != y.IsNull() || bits() != y.bits()) {
+    DIE("uncomparable integers");
+    return false;
+  }
+  return withWord([&](const auto &x) -> bool {
+    using T = std::decay_t<decltype(x)>;
+    return x == std::get<T>(y.storage_);
+  });
+}
+
+IntegerValueImpl IntegerValueImpl::MASKL(int kind, int places) {
+  return withWordProto(kind, [&](auto proto) {
+    using T = decltype(proto);
+    return FromWord(T::MASKL(places));
+  });
+}
+
+IntegerValueImpl IntegerValueImpl::MASKR(int kind, int places) {
+  return withWordProto(kind, [&](auto proto) {
+    using T = decltype(proto);
+    return FromWord(T::MASKR(places));
+  });
+}
+
+IntegerValueImpl IntegerValueImpl::HUGE(int kind) {
+  return withWordProto(kind, [&](auto proto) {
+    using T = decltype(proto);
+    return FromWord(T::HUGE());
+  });
+}
+
+IntegerValueImpl IntegerValueImpl::Least(int kind) {
+  return withWordProto(kind, [&](auto proto) {
+    using T = decltype(proto);
+    return FromWord(T::Least());
+  });
+}
+
+bool IntegerValueImpl::IsNegative() const {
+  if (IsNull()) {
+    return false; // uninitialized int representing 0 is not negative
+  }
+  return withWord([](const auto &x) { return x.IsNegative(); });
+}
+
+std::uint64_t IntegerValueImpl::ToUInt64() const {
+  if (IsNull()) {
+    return 0;
+  }
+  return withWord([](const auto &x) { return x.ToUInt64(); });
+}
+
+std::int64_t IntegerValueImpl::ToInt64() const {
+  if (IsNull()) {
+    return 0;
+  }
+  return withWord([](const auto &x) { return x.ToInt64(); });
+}
+
+Fortran::common::uint128_t IntegerValueImpl::ToUInt128() const {
+  if (IsNull()) {
+    return 0;
+  }
+  return withWord([](const auto &x) {
+    return x.template ToUInt<Fortran::common::uint128_t>();
+  });
+}
+
+Fortran::common::int128_t IntegerValueImpl::ToInt128() const {
+  if (IsNull()) {
+    return 0;
+  }
+  return withWord([](const auto &x) {
+    return x.template ToSInt<Fortran::common::int128_t,
+        Fortran::common::uint128_t>();
+  });
+}
+
+Ordering IntegerValueImpl::CompareSigned(const IntegerValueImpl &y) const {
+  if (IsNull() && y.IsNull()) {
+    // Both are considered to be zero
+    return Ordering::Equal;
+  } else if (IsNull()) {
+    switch (y.CompareToZeroSigned()) {
+    case Ordering::Less:
+      return Ordering::Greater;
+    case Ordering::Greater:
+      return Ordering::Less;
+    case Ordering::Equal:
+      return Ordering::Equal;
+    }
+  } else if (y.IsNull()) {
+    return CompareToZeroSigned();
+  }
+
+  return withWord([&](const auto &x) -> Ordering {
+    using T = std::decay_t<decltype(x)>;
+    return x.CompareSigned(Coerce<T>(y));
+  });
+}
+
+Ordering IntegerValueImpl::CompareUnsigned(const IntegerValueImpl &y) const {
+  if (IsNull() && y.IsNull()) {
+    // Both are considered to be zero
+    return Ordering::Equal;
+  } else if (IsNull()) {
+    return y.IsZero() ? Ordering::Equal : Ordering::Less;
+  } else if (y.IsNull()) {
+    return IsZero() ? Ordering::Equal : Ordering::Greater;
+  }
+
+  return withWord([&](const auto &x) -> Ordering {
+    using T = std::decay_t<decltype(x)>;
+    return x.CompareUnsigned(Coerce<T>(y));
----------------
Meinersbur wrote:

The assumption here is that kind for two-operand operations is the same, as it was in the KIND-templated code. That is, none of these operands are ever called with different KINDs, except in one unittests.

However, if the KIND is different. this find is even worse than indicated here: Coerce also truncates. So instead of finding the largest common bit width, it may truncate to one of the operand's bitwidth (usually `this`).

I replaced `Coerce` and `CoerceUnsigned` with `getWord` to require the KIND to be equal (or `DIE`), and remove the only unittest that tests for unequal KINDS. 

https://github.com/llvm/llvm-project/pull/216958


More information about the flang-commits mailing list