Warning: This file is not a C or C++ file. It does not have highlighting.
1 | //===-- include/flang/Evaluate/constant.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_CONSTANT_H_ |
10 | #define FORTRAN_EVALUATE_CONSTANT_H_ |
11 | |
12 | #include "formatting.h" |
13 | #include "type.h" |
14 | #include "flang/Common/default-kinds.h" |
15 | #include "flang/Common/reference.h" |
16 | #include <map> |
17 | #include <vector> |
18 | |
19 | namespace llvm { |
20 | class raw_ostream; |
21 | } |
22 | |
23 | namespace Fortran::semantics { |
24 | class Symbol; |
25 | } |
26 | |
27 | namespace Fortran::evaluate { |
28 | |
29 | using semantics::Symbol; |
30 | using SymbolRef = common::Reference<const Symbol>; |
31 | |
32 | // Wraps a constant value in a class templated by its resolved type. |
33 | // This Constant<> template class should be instantiated only for |
34 | // concrete intrinsic types and SomeDerived. There is no instance |
35 | // Constant<SomeType> since there is no way to constrain each |
36 | // element of its array to hold the same type. To represent a generic |
37 | // constant, use a generic expression like Expr<SomeInteger> or |
38 | // Expr<SomeType>) to wrap the appropriate instantiation of Constant<>. |
39 | |
40 | template <typename> class Constant; |
41 | |
42 | // When describing shapes of constants or specifying 1-based subscript |
43 | // values as indices into constants, use a vector of integers. |
44 | using ConstantSubscripts = std::vector<ConstantSubscript>; |
45 | inline int GetRank(const ConstantSubscripts &s) { |
46 | return static_cast<int>(s.size()); |
47 | } |
48 | |
49 | // Returns the number of elements of shape, if no overflow occurs. |
50 | std::optional<uint64_t> TotalElementCount(const ConstantSubscripts &shape); |
51 | |
52 | // Validate dimension re-ordering like ORDER in RESHAPE. |
53 | // On success, return a vector that can be used as dimOrder in |
54 | // ConstantBounds::IncrementSubscripts(). |
55 | std::optional<std::vector<int>> ValidateDimensionOrder( |
56 | int rank, const std::vector<int> &order); |
57 | |
58 | bool HasNegativeExtent(const ConstantSubscripts &); |
59 | |
60 | class ConstantBounds { |
61 | public: |
62 | ConstantBounds() = default; |
63 | explicit ConstantBounds(const ConstantSubscripts &shape); |
64 | explicit ConstantBounds(ConstantSubscripts &&shape); |
65 | ~ConstantBounds(); |
66 | const ConstantSubscripts &shape() const { return shape_; } |
67 | int Rank() const { return GetRank(shape_); } |
68 | Constant<SubscriptInteger> SHAPE() const; |
69 | |
70 | // It is possible in this representation for a constant array to have |
71 | // lower bounds other than 1, which is of course not expressible in |
72 | // Fortran. This case arises only from definitions of named constant |
73 | // arrays with such bounds, as in: |
74 | // REAL, PARAMETER :: NAMED(0:1) = [1.,2.] |
75 | // Bundling the lower bounds of the named constant with its |
76 | // constant value allows folding of subscripted array element |
77 | // references, LBOUND, and UBOUND without having to thread the named |
78 | // constant or its bounds throughout folding. |
79 | const ConstantSubscripts &lbounds() const { return lbounds_; } |
80 | ConstantSubscripts ComputeUbounds(std::optional<int> dim) const; |
81 | void set_lbounds(ConstantSubscripts &&); |
82 | void SetLowerBoundsToOne(); |
83 | bool HasNonDefaultLowerBound() const; |
84 | |
85 | // If no optional dimension order argument is passed, increments a vector of |
86 | // subscripts in Fortran array order (first dimension varying most quickly). |
87 | // Otherwise, increments the vector of subscripts according to the given |
88 | // dimension order (dimension dimOrder[0] varying most quickly; dimension |
89 | // indexing is zero based here). Returns false when last element was visited. |
90 | bool IncrementSubscripts( |
91 | ConstantSubscripts &, const std::vector<int> *dimOrder = nullptr) const; |
92 | |
93 | protected: |
94 | ConstantSubscript SubscriptsToOffset(const ConstantSubscripts &) const; |
95 | |
96 | private: |
97 | ConstantSubscripts shape_; |
98 | ConstantSubscripts lbounds_; |
99 | }; |
100 | |
101 | // Constant<> is specialized for Character kinds and SomeDerived. |
102 | // The non-Character intrinsic types, and SomeDerived, share enough |
103 | // common behavior that they use this common base class. |
104 | template <typename RESULT, typename ELEMENT = Scalar<RESULT>> |
105 | class ConstantBase : public ConstantBounds { |
106 | static_assert(RESULT::category != TypeCategory::Character); |
107 | |
108 | public: |
109 | using Result = RESULT; |
110 | using Element = ELEMENT; |
111 | |
112 | template <typename A> |
113 | ConstantBase(const A &x, Result res = Result{}) : result_{res}, values_{x} {} |
114 | ConstantBase(ELEMENT &&x, Result res = Result{}) |
115 | : result_{res}, values_{std::move(x)} {} |
116 | ConstantBase( |
117 | std::vector<Element> &&, ConstantSubscripts &&, Result = Result{}); |
118 | |
119 | DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ConstantBase) |
120 | ~ConstantBase(); |
121 | |
122 | bool operator==(const ConstantBase &) const; |
123 | bool empty() const { return values_.empty(); } |
124 | std::size_t size() const { return values_.size(); } |
125 | const std::vector<Element> &values() const { return values_; } |
126 | constexpr Result result() const { return result_; } |
127 | |
128 | constexpr DynamicType GetType() const { return result_.GetType(); } |
129 | llvm::raw_ostream &AsFortran(llvm::raw_ostream &, |
130 | const parser::CharBlock *derivedTypeRename = nullptr) const; |
131 | |
132 | protected: |
133 | std::vector<Element> Reshape(const ConstantSubscripts &) const; |
134 | std::size_t CopyFrom(const ConstantBase &source, std::size_t count, |
135 | ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder); |
136 | |
137 | Result result_; |
138 | std::vector<Element> values_; |
139 | }; |
140 | |
141 | template <typename T> class Constant : public ConstantBase<T> { |
142 | public: |
143 | using Result = T; |
144 | using Base = ConstantBase<T>; |
145 | using Element = Scalar<T>; |
146 | |
147 | using Base::Base; |
148 | CLASS_BOILERPLATE(Constant) |
149 | |
150 | std::optional<Scalar<T>> GetScalarValue() const { |
151 | if (ConstantBounds::Rank() == 0) { |
152 | return Base::values_.at(0); |
153 | } else { |
154 | return std::nullopt; |
155 | } |
156 | } |
157 | |
158 | // Apply subscripts. Excess subscripts are ignored, including the |
159 | // case of a scalar. |
160 | Element At(const ConstantSubscripts &) const; |
161 | |
162 | Constant Reshape(ConstantSubscripts &&) const; |
163 | std::size_t CopyFrom(const Constant &source, std::size_t count, |
164 | ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder); |
165 | }; |
166 | |
167 | template <int KIND> |
168 | class Constant<Type<TypeCategory::Character, KIND>> : public ConstantBounds { |
169 | public: |
170 | using Result = Type<TypeCategory::Character, KIND>; |
171 | using Element = Scalar<Result>; |
172 | |
173 | CLASS_BOILERPLATE(Constant) |
174 | explicit Constant(const Scalar<Result> &); |
175 | explicit Constant(Scalar<Result> &&); |
176 | Constant( |
177 | ConstantSubscript length, std::vector<Element> &&, ConstantSubscripts &&); |
178 | ~Constant(); |
179 | |
180 | bool operator==(const Constant &that) const { |
181 | return LEN() == that.LEN() && shape() == that.shape() && |
182 | values_ == that.values_; |
183 | } |
184 | bool empty() const; |
185 | std::size_t size() const; |
186 | |
187 | const Scalar<Result> &values() const { return values_; } |
188 | ConstantSubscript LEN() const { return length_; } |
189 | bool wasHollerith() const { return wasHollerith_; } |
190 | void set_wasHollerith(bool yes = true) { wasHollerith_ = yes; } |
191 | |
192 | std::optional<Scalar<Result>> GetScalarValue() const { |
193 | if (Rank() == 0) { |
194 | return values_; |
195 | } else { |
196 | return std::nullopt; |
197 | } |
198 | } |
199 | |
200 | // Apply subscripts, if any. |
201 | Scalar<Result> At(const ConstantSubscripts &) const; |
202 | |
203 | // Extract substring(s); returns nullopt for errors. |
204 | std::optional<Constant> Substring(ConstantSubscript, ConstantSubscript) const; |
205 | |
206 | Constant Reshape(ConstantSubscripts &&) const; |
207 | llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; |
208 | DynamicType GetType() const { return {KIND, length_}; } |
209 | std::size_t CopyFrom(const Constant &source, std::size_t count, |
210 | ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder); |
211 | |
212 | private: |
213 | Scalar<Result> values_; // one contiguous string |
214 | ConstantSubscript length_; |
215 | bool wasHollerith_{false}; |
216 | }; |
217 | |
218 | class StructureConstructor; |
219 | struct ComponentCompare { |
220 | bool operator()(SymbolRef x, SymbolRef y) const; |
221 | }; |
222 | using StructureConstructorValues = std::map<SymbolRef, |
223 | common::CopyableIndirection<Expr<SomeType>>, ComponentCompare>; |
224 | |
225 | template <> |
226 | class Constant<SomeDerived> |
227 | : public ConstantBase<SomeDerived, StructureConstructorValues> { |
228 | public: |
229 | using Result = SomeDerived; |
230 | using Element = StructureConstructorValues; |
231 | using Base = ConstantBase<SomeDerived, StructureConstructorValues>; |
232 | |
233 | Constant(const StructureConstructor &); |
234 | Constant(StructureConstructor &&); |
235 | Constant(const semantics::DerivedTypeSpec &, |
236 | std::vector<StructureConstructorValues> &&, ConstantSubscripts &&); |
237 | Constant(const semantics::DerivedTypeSpec &, |
238 | std::vector<StructureConstructor> &&, ConstantSubscripts &&); |
239 | CLASS_BOILERPLATE(Constant) |
240 | |
241 | std::optional<StructureConstructor> GetScalarValue() const; |
242 | StructureConstructor At(const ConstantSubscripts &) const; |
243 | |
244 | bool operator==(const Constant &) const; |
245 | Constant Reshape(ConstantSubscripts &&) const; |
246 | std::size_t CopyFrom(const Constant &source, std::size_t count, |
247 | ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder); |
248 | }; |
249 | |
250 | FOR_EACH_LENGTHLESS_INTRINSIC_KIND(extern template class ConstantBase, ) |
251 | extern template class ConstantBase<SomeDerived, StructureConstructorValues>; |
252 | FOR_EACH_INTRINSIC_KIND(extern template class Constant, ) |
253 | |
254 | #define INSTANTIATE_CONSTANT_TEMPLATES \ |
255 | FOR_EACH_LENGTHLESS_INTRINSIC_KIND(template class ConstantBase, ) \ |
256 | template class ConstantBase<SomeDerived, StructureConstructorValues>; \ |
257 | FOR_EACH_INTRINSIC_KIND(template class Constant, ) |
258 | } // namespace Fortran::evaluate |
259 | #endif // FORTRAN_EVALUATE_CONSTANT_H_ |
260 |
Warning: This file is not a C or C++ file. It does not have highlighting.