FLANG

constant.h
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 std::size_t TotalElementCount(const ConstantSubscripts &);
50
51 // Validate dimension re-ordering like ORDER in RESHAPE.
52 // On success, return a vector that can be used as dimOrder in
53 // ConstantBound::IncrementSubscripts().
54 std::optional<std::vector<int>> ValidateDimensionOrder(
55 int rank, const std::vector<int> &order);
56
57 bool IsValidShape(const ConstantSubscripts &);
58
59 class ConstantBounds {
60 public:
61 ConstantBounds() = default;
62 explicit ConstantBounds(const ConstantSubscripts &shape);
63 explicit ConstantBounds(ConstantSubscripts &&shape);
64 ~ConstantBounds();
65 const ConstantSubscripts &shape() const { return shape_; }
66 const ConstantSubscripts &lbounds() const { return lbounds_; }
67 void set_lbounds(ConstantSubscripts &&);
68 int Rank() const { return GetRank(shape_); }
69 Constant<SubscriptInteger> SHAPE() const;
70
71 // If no optional dimension order argument is passed, increments a vector of
72 // subscripts in Fortran array order (first dimension varying most quickly).
73 // Otherwise, increments the vector of subscripts according to the given
74 // dimension order (dimension dimOrder[0] varying most quickly; dimension
75 // indexing is zero based here). Returns false when last element was visited.
76 bool IncrementSubscripts(
77 ConstantSubscripts &, const std::vector<int> *dimOrder = nullptr) const;
78
79 protected:
80 ConstantSubscript SubscriptsToOffset(const ConstantSubscripts &) const;
81
82 private:
83 ConstantSubscripts shape_;
84 ConstantSubscripts lbounds_;
85 };
86
87 // Constant<> is specialized for Character kinds and SomeDerived.
88 // The non-Character intrinsic types, and SomeDerived, share enough
89 // common behavior that they use this common base class.
90 template <typename RESULT, typename ELEMENT = Scalar<RESULT>>
91 class ConstantBase : public ConstantBounds {
92 static_assert(RESULT::category != TypeCategory::Character);
93
94 public:
95 using Result = RESULT;
96 using Element = ELEMENT;
97
98 template <typename A>
99 ConstantBase(const A &x, Result res = Result{}) : result_{res}, values_{x} {}
100 template <typename A, typename = common::NoLvalue<A>>
101 ConstantBase(A &&x, Result res = Result{})
102 : result_{res}, values_{std::move(x)} {}
103 ConstantBase(
104 std::vector<Element> &&, ConstantSubscripts &&, Result = Result{});
105
106 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ConstantBase)
107 ~ConstantBase();
108
109 bool operator==(const ConstantBase &) const;
110 bool empty() const { return values_.empty(); }
111 std::size_t size() const { return values_.size(); }
112 const std::vector<Element> &values() const { return values_; }
113 constexpr Result result() const { return result_; }
114
115 constexpr DynamicType GetType() const { return result_.GetType(); }
116 llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
117
118 protected:
119 std::vector<Element> Reshape(const ConstantSubscripts &) const;
120 std::size_t CopyFrom(const ConstantBase &source, std::size_t count,
121 ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder);
122
123 Result result_;
124 std::vector<Element> values_;
125 };
126
127 template <typename T> class Constant : public ConstantBase<T> {
128 public:
129 using Result = T;
130 using Base = ConstantBase<T>;
131 using Element = Scalar<T>;
132
133 using Base::Base;
134 CLASS_BOILERPLATE(Constant)
135
136 std::optional<Scalar<T>> GetScalarValue() const {
137 if (ConstantBounds::Rank() == 0) {
138 return Base::values_.at(0);
139 } else {
140 return std::nullopt;
141 }
142 }
143
144 // Apply subscripts.
145 Element At(const ConstantSubscripts &) const;
146
147 Constant Reshape(ConstantSubscripts &&) const;
148 std::size_t CopyFrom(const Constant &source, std::size_t count,
149 ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder);
150 };
151
152 template <int KIND>
153 class Constant<Type<TypeCategory::Character, KIND>> : public ConstantBounds {
154 public:
155 using Result = Type<TypeCategory::Character, KIND>;
156 using Element = Scalar<Result>;
157
158 CLASS_BOILERPLATE(Constant)
159 explicit Constant(const Scalar<Result> &);
160 explicit Constant(Scalar<Result> &&);
161 Constant(
162 ConstantSubscript length, std::vector<Element> &&, ConstantSubscripts &&);
163 ~Constant();
164
165 bool operator==(const Constant &that) const {
166 return shape() == that.shape() && values_ == that.values_;
167 }
168 bool empty() const;
169 std::size_t size() const;
170
171 ConstantSubscript LEN() const { return length_; }
172
173 std::optional<Scalar<Result>> GetScalarValue() const {
174 if (Rank() == 0) {
175 return values_;
176 } else {
177 return std::nullopt;
178 }
179 }
180
181 // Apply subscripts
182 Scalar<Result> At(const ConstantSubscripts &) const;
183
184 Constant Reshape(ConstantSubscripts &&) const;
185 llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
186 static constexpr DynamicType GetType() {
187 return {TypeCategory::Character, KIND};
188 }
189 std::size_t CopyFrom(const Constant &source, std::size_t count,
190 ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder);
191
192 private:
193 Scalar<Result> values_; // one contiguous string
194 ConstantSubscript length_;
195 };
196
197 class StructureConstructor;
198 using StructureConstructorValues =
199 std::map<SymbolRef, common::CopyableIndirection<Expr<SomeType>>>;
200
201 template <>
202 class Constant<SomeDerived>
203 : public ConstantBase<SomeDerived, StructureConstructorValues> {
204 public:
205 using Result = SomeDerived;
206 using Element = StructureConstructorValues;
207 using Base = ConstantBase<SomeDerived, StructureConstructorValues>;
208
209 Constant(const StructureConstructor &);
210 Constant(StructureConstructor &&);
211 Constant(const semantics::DerivedTypeSpec &,
212 std::vector<StructureConstructorValues> &&, ConstantSubscripts &&);
213 Constant(const semantics::DerivedTypeSpec &,
214 std::vector<StructureConstructor> &&, ConstantSubscripts &&);
215 CLASS_BOILERPLATE(Constant)
216
217 std::optional<StructureConstructor> GetScalarValue() const;
218 StructureConstructor At(const ConstantSubscripts &) const;
219
220 Constant Reshape(ConstantSubscripts &&) const;
221 std::size_t CopyFrom(const Constant &source, std::size_t count,
222 ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder);
223 };
224
225 FOR_EACH_LENGTHLESS_INTRINSIC_KIND(extern template class ConstantBase, )
226 extern template class ConstantBase<SomeDerived, StructureConstructorValues>;
227 FOR_EACH_INTRINSIC_KIND(extern template class Constant, )
228
229 #define INSTANTIATE_CONSTANT_TEMPLATES \
230 FOR_EACH_LENGTHLESS_INTRINSIC_KIND(template class ConstantBase, ) \
231 template class ConstantBase<SomeDerived, StructureConstructorValues>; \
232 FOR_EACH_INTRINSIC_KIND(template class Constant, )
233 } // namespace Fortran::evaluate
234 #endif // FORTRAN_EVALUATE_CONSTANT_H_
Fortran::evaluate::Constant
Definition: constant.h:40
Fortran::evaluate::StructureConstructor
Definition: expression.h:687
Fortran::evaluate::DynamicType
Definition: type.h:85
Fortran::evaluate::Type
Definition: type.h:48
Fortran::semantics::DerivedTypeSpec
Definition: type.h:237
Fortran::evaluate::ConstantBounds
Definition: constant.h:59
Fortran::evaluate::ConstantBase
Definition: constant.h:91
Fortran::evaluate::SomeKind< TypeCategory::Derived >
Definition: type.h:390