Warning: This file is not a C or C++ file. It does not have highlighting.

1//===-- include/flang/Evaluate/common.h -------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef FORTRAN_EVALUATE_COMMON_H_
10#define FORTRAN_EVALUATE_COMMON_H_
11
12#include "flang/Common/Fortran-features.h"
13#include "flang/Common/Fortran.h"
14#include "flang/Common/default-kinds.h"
15#include "flang/Common/enum-set.h"
16#include "flang/Common/idioms.h"
17#include "flang/Common/indirection.h"
18#include "flang/Common/restorer.h"
19#include "flang/Parser/char-block.h"
20#include "flang/Parser/message.h"
21#include <cinttypes>
22#include <map>
23#include <set>
24#include <string>
25
26namespace Fortran::semantics {
27class DerivedTypeSpec;
28}
29
30namespace Fortran::evaluate {
31class IntrinsicProcTable;
32class TargetCharacteristics;
33
34using common::ConstantSubscript;
35using common::RelationalOperator;
36
37// Integers are always ordered; reals may not be.
38ENUM_CLASS(Ordering, Less, Equal, Greater)
39ENUM_CLASS(Relation, Less, Equal, Greater, Unordered)
40
41template <typename A>
42static constexpr Ordering Compare(const A &x, const A &y) {
43 if (x < y) {
44 return Ordering::Less;
45 } else if (x > y) {
46 return Ordering::Greater;
47 } else {
48 return Ordering::Equal;
49 }
50}
51
52template <typename CH>
53static constexpr Ordering Compare(
54 const std::basic_string<CH> &x, const std::basic_string<CH> &y) {
55 std::size_t xLen{x.size()}, yLen{y.size()};
56 using String = std::basic_string<CH>;
57 // Fortran CHARACTER comparison is defined with blank padding
58 // to extend a shorter operand.
59 if (xLen < yLen) {
60 return Compare(String{x}.append(yLen - xLen, CH{' '}), y);
61 } else if (xLen > yLen) {
62 return Compare(x, String{y}.append(xLen - yLen, CH{' '}));
63 } else if (x < y) {
64 return Ordering::Less;
65 } else if (x > y) {
66 return Ordering::Greater;
67 } else {
68 return Ordering::Equal;
69 }
70}
71
72static constexpr Ordering Reverse(Ordering ordering) {
73 if (ordering == Ordering::Less) {
74 return Ordering::Greater;
75 } else if (ordering == Ordering::Greater) {
76 return Ordering::Less;
77 } else {
78 return Ordering::Equal;
79 }
80}
81
82static constexpr Relation RelationFromOrdering(Ordering ordering) {
83 if (ordering == Ordering::Less) {
84 return Relation::Less;
85 } else if (ordering == Ordering::Greater) {
86 return Relation::Greater;
87 } else {
88 return Relation::Equal;
89 }
90}
91
92static constexpr Relation Reverse(Relation relation) {
93 if (relation == Relation::Less) {
94 return Relation::Greater;
95 } else if (relation == Relation::Greater) {
96 return Relation::Less;
97 } else {
98 return relation;
99 }
100}
101
102static constexpr bool Satisfies(RelationalOperator op, Ordering order) {
103 switch (order) {
104 case Ordering::Less:
105 return op == RelationalOperator::LT || op == RelationalOperator::LE ||
106 op == RelationalOperator::NE;
107 case Ordering::Equal:
108 return op == RelationalOperator::LE || op == RelationalOperator::EQ ||
109 op == RelationalOperator::GE;
110 case Ordering::Greater:
111 return op == RelationalOperator::NE || op == RelationalOperator::GE ||
112 op == RelationalOperator::GT;
113 }
114 return false; // silence g++ warning
115}
116
117static constexpr bool Satisfies(RelationalOperator op, Relation relation) {
118 switch (relation) {
119 case Relation::Less:
120 return Satisfies(op, Ordering::Less);
121 case Relation::Equal:
122 return Satisfies(op, Ordering::Equal);
123 case Relation::Greater:
124 return Satisfies(op, Ordering::Greater);
125 case Relation::Unordered:
126 return op == RelationalOperator::NE;
127 }
128 return false; // silence g++ warning
129}
130
131ENUM_CLASS(
132 RealFlag, Overflow, DivideByZero, InvalidArgument, Underflow, Inexact)
133
134using RealFlags = common::EnumSet<RealFlag, RealFlag_enumSize>;
135
136template <typename A> struct ValueWithRealFlags {
137 A AccumulateFlags(RealFlags &f) {
138 f |= flags;
139 return value;
140 }
141 A value;
142 RealFlags flags{};
143};
144
145#if FLANG_BIG_ENDIAN
146constexpr bool isHostLittleEndian{false};
147#elif FLANG_LITTLE_ENDIAN
148constexpr bool isHostLittleEndian{true};
149#else
150#error host endianness is not known
151#endif
152
153// HostUnsignedInt<BITS> finds the smallest native unsigned integer type
154// whose size is >= BITS.
155template <bool LE8, bool LE16, bool LE32, bool LE64> struct SmallestUInt {};
156template <> struct SmallestUInt<true, true, true, true> {
157 using type = std::uint8_t;
158};
159template <> struct SmallestUInt<false, true, true, true> {
160 using type = std::uint16_t;
161};
162template <> struct SmallestUInt<false, false, true, true> {
163 using type = std::uint32_t;
164};
165template <> struct SmallestUInt<false, false, false, true> {
166 using type = std::uint64_t;
167};
168template <int BITS>
169using HostUnsignedInt =
170 typename SmallestUInt<BITS <= 8, BITS <= 16, BITS <= 32, BITS <= 64>::type;
171
172// Many classes in this library follow a common paradigm.
173// - There is no default constructor (Class() {}), usually to prevent the
174// need for std::monostate as a default constituent in a std::variant<>.
175// - There are full copy and move semantics for construction and assignment.
176// - Discriminated unions have a std::variant<> member "u" and support
177// explicit copy and move constructors as well as comparison for equality.
178#define DECLARE_CONSTRUCTORS_AND_ASSIGNMENTS(t) \
179 t(const t &); \
180 t(t &&); \
181 t &operator=(const t &); \
182 t &operator=(t &&);
183#define DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(t) \
184 t(const t &) = default; \
185 t(t &&) = default; \
186 t &operator=(const t &) = default; \
187 t &operator=(t &&) = default;
188#define DEFINE_DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(t) \
189 t::t(const t &) = default; \
190 t::t(t &&) = default; \
191 t &t::operator=(const t &) = default; \
192 t &t::operator=(t &&) = default;
193#define CONSTEXPR_CONSTRUCTORS_AND_ASSIGNMENTS(t) \
194 constexpr t(const t &) = default; \
195 constexpr t(t &&) = default; \
196 constexpr t &operator=(const t &) = default; \
197 constexpr t &operator=(t &&) = default;
198
199#define CLASS_BOILERPLATE(t) \
200 t() = delete; \
201 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(t)
202
203#define UNION_CONSTRUCTORS(t) \
204 template <typename _A> explicit t(const _A &x) : u{x} {} \
205 template <typename _A, typename = common::NoLvalue<_A>> \
206 explicit t(_A &&x) : u(std::move(x)) {}
207
208#define EVALUATE_UNION_CLASS_BOILERPLATE(t) \
209 CLASS_BOILERPLATE(t) \
210 UNION_CONSTRUCTORS(t) \
211 bool operator==(const t &) const;
212
213// Forward definition of Expr<> so that it can be indirectly used in its own
214// definition
215template <typename A> class Expr;
216
217class FoldingContext {
218public:
219 FoldingContext(const common::IntrinsicTypeDefaultKinds &d,
220 const IntrinsicProcTable &t, const TargetCharacteristics &c,
221 const common::LanguageFeatureControl &lfc,
222 std::set<std::string> &tempNames)
223 : defaults_{d}, intrinsics_{t}, targetCharacteristics_{c},
224 languageFeatures_{lfc}, tempNames_{tempNames} {}
225 FoldingContext(const parser::ContextualMessages &m,
226 const common::IntrinsicTypeDefaultKinds &d, const IntrinsicProcTable &t,
227 const TargetCharacteristics &c, const common::LanguageFeatureControl &lfc,
228 std::set<std::string> &tempNames)
229 : messages_{m}, defaults_{d}, intrinsics_{t}, targetCharacteristics_{c},
230 languageFeatures_{lfc}, tempNames_{tempNames} {}
231 FoldingContext(const FoldingContext &that)
232 : messages_{that.messages_}, defaults_{that.defaults_},
233 intrinsics_{that.intrinsics_},
234 targetCharacteristics_{that.targetCharacteristics_},
235 pdtInstance_{that.pdtInstance_}, impliedDos_{that.impliedDos_},
236 languageFeatures_{that.languageFeatures_}, tempNames_{that.tempNames_} {
237 }
238 FoldingContext(
239 const FoldingContext &that, const parser::ContextualMessages &m)
240 : messages_{m}, defaults_{that.defaults_}, intrinsics_{that.intrinsics_},
241 targetCharacteristics_{that.targetCharacteristics_},
242 pdtInstance_{that.pdtInstance_}, impliedDos_{that.impliedDos_},
243 languageFeatures_{that.languageFeatures_}, tempNames_{that.tempNames_} {
244 }
245
246 parser::ContextualMessages &messages() { return messages_; }
247 const parser::ContextualMessages &messages() const { return messages_; }
248 const common::IntrinsicTypeDefaultKinds &defaults() const {
249 return defaults_;
250 }
251 const semantics::DerivedTypeSpec *pdtInstance() const { return pdtInstance_; }
252 const IntrinsicProcTable &intrinsics() const { return intrinsics_; }
253 const TargetCharacteristics &targetCharacteristics() const {
254 return targetCharacteristics_;
255 }
256 const common::LanguageFeatureControl &languageFeatures() const {
257 return languageFeatures_;
258 }
259 std::optional<parser::CharBlock> moduleFileName() const {
260 return moduleFileName_;
261 }
262 FoldingContext &set_moduleFileName(std::optional<parser::CharBlock> n) {
263 moduleFileName_ = n;
264 return *this;
265 }
266
267 ConstantSubscript &StartImpliedDo(parser::CharBlock, ConstantSubscript = 1);
268 std::optional<ConstantSubscript> GetImpliedDo(parser::CharBlock) const;
269 void EndImpliedDo(parser::CharBlock);
270
271 std::map<parser::CharBlock, ConstantSubscript> &impliedDos() {
272 return impliedDos_;
273 }
274
275 common::Restorer<const semantics::DerivedTypeSpec *> WithPDTInstance(
276 const semantics::DerivedTypeSpec &spec) {
277 return common::ScopedSet(pdtInstance_, &spec);
278 }
279 common::Restorer<const semantics::DerivedTypeSpec *> WithoutPDTInstance() {
280 return common::ScopedSet(pdtInstance_, nullptr);
281 }
282
283 parser::CharBlock SaveTempName(std::string &&name) {
284 return {*tempNames_.emplace(std::move(name)).first};
285 }
286
287private:
288 parser::ContextualMessages messages_;
289 const common::IntrinsicTypeDefaultKinds &defaults_;
290 const IntrinsicProcTable &intrinsics_;
291 const TargetCharacteristics &targetCharacteristics_;
292 const semantics::DerivedTypeSpec *pdtInstance_{nullptr};
293 std::optional<parser::CharBlock> moduleFileName_;
294 std::map<parser::CharBlock, ConstantSubscript> impliedDos_;
295 const common::LanguageFeatureControl &languageFeatures_;
296 std::set<std::string> &tempNames_;
297};
298
299void RealFlagWarnings(FoldingContext &, const RealFlags &, const char *op);
300} // namespace Fortran::evaluate
301#endif // FORTRAN_EVALUATE_COMMON_H_
302

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of flang/include/flang/Evaluate/common.h