[flang-commits] [flang] [llvm] [Flang] Introduce *Value classes with unittests (PR #216958)
Michael Kruse via flang-commits
flang-commits at lists.llvm.org
Wed Sep 9 06:49:14 PDT 2026
================
@@ -0,0 +1,373 @@
+//===-- include/flang/Evaluate/integer-value.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_INTEGER_VALUE_H_
+#define FORTRAN_EVALUATE_INTEGER_VALUE_H_
+
+#include "flang/Common/uint128.h"
+#include "flang/Evaluate/common.h"
+#include "flang/Evaluate/object-sizes.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+#include <type_traits>
+
+// Some environments, viz. glibc 2.17 and *BSD, allow the macro HUGE
+// to leak out of <math.h>.
+#undef HUGE
+
+namespace Fortran::evaluate::value {
+class IntegerValueImpl;
+
+/// A two's-complement integer with dynamic bitwidth.
+///
+/// The bitwidth is dynamic, but only a predefined set of Fortran kinds are
+/// allowed. It is also kind-aware, i.e. knows which INTEGER kind it currently
+/// represents.
+///
+/// The implementation is hidden from this header using a pImpl-like idiom.
+class IntegerValue {
+ friend class RealValueImpl;
+
+public:
+ struct ValueWithOverflow;
+ struct ValueWithCarry;
+ struct Product;
+ struct QuotientWithRemainder;
+ struct PowerWithErrors;
+
+ IntegerValue();
+ ~IntegerValue();
+ IntegerValue(const IntegerValue &);
+ IntegerValue(IntegerValue &&);
+ IntegerValue &operator=(const IntegerValue &);
+ IntegerValue &operator=(IntegerValue &&);
+
+ IntegerValue(int kind, const IntegerValue &x) : IntegerValue(x) {
+ CHECK(x.kind() == kind);
+ }
+ IntegerValue(int kind, IntegerValue &&x) : IntegerValue(std::move(x)) {
+ CHECK(x.kind() == kind);
+ }
+
+ // Fortran::common::int128_t/uint128_t are 128-bit values -- either the
+ // host's native __int128/unsigned __int128, or the portable
+ // Fortran::common::Int128<> fallback when there is no native type -- and
+ // are handled by the dedicated branch below rather than by the general
+ // integral case, since some standard libraries don't consider native
+ // __int128 types to satisfy std::is_integral_v, and the portable fallback
+ // is a class type that never does.
+ template <typename INT,
+ typename = std::enable_if_t<std::numeric_limits<INT>::is_integer>>
+ IntegerValue(int kind, INT v) {
+ if constexpr (sizeof(INT) > 8) {
+ static_assert(sizeof(INT) == 16);
+ ConstructFromIntegral(kind, static_cast<Fortran::common::uint128_t>(v));
+ } else if constexpr (std::is_signed_v<INT>) {
+ ConstructFromIntegral(
+ kind, static_cast<uint64_t>(static_cast<int64_t>(v)), true);
+ } else {
+ ConstructFromIntegral(kind, static_cast<uint64_t>(v), false);
+ }
+ }
+
+ /// Creates an integer with value 0 of a given kind. This is different from
+ /// the default-ctor which creates a "monostate" that represents 0 of unknown
+ /// kind.
+ static IntegerValue Zero(int kind);
+
+ void print(llvm::raw_ostream &os) const;
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ LLVM_DUMP_METHOD void dump() const;
+#endif
+
+ /// Whether this object represents a default-initialized value (zero) of
+ /// not-yet-known kind.
+ bool IsMonostate() const;
+
+ /// The kind of the value currently stored.
+ int kind() const;
+
+ int bits() const { return bits(kind()); }
+ static constexpr int bits(int kind) { return bytesStored(kind) * 8; }
+
+ /// Number of bytes accessed by FromRawBytes/StoreRawBytes
+ std::size_t bytesStored() const { return bytesStored(kind()); }
+ static constexpr std::size_t bytesStored(int kind) {
+ switch (kind) {
+ case 3:
+ return 2;
+ case 10:
----------------
Meinersbur wrote:
`REAL(10)` also uses an integer as backing storage (`X87IntegerContainer`). It is separate from a true 128 bit integer (`Integer<128>`) which is why it needs its own kind (non-accessible from Fortran programs).
Long-term, I would like to use APFloat instead which has its own, specialized, storage classes.
https://github.com/llvm/llvm-project/pull/216958
More information about the flang-commits
mailing list