Warning: This file is not a C or C++ file. It does not have highlighting.
1 | //===-- Lower/ConvertExpr.h -- lowering of expressions ----------*- 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 | // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | /// |
13 | /// Implements the conversion from Fortran::evaluate::Expr trees to FIR. |
14 | /// |
15 | //===----------------------------------------------------------------------===// |
16 | |
17 | #ifndef FORTRAN_LOWER_CONVERTEXPR_H |
18 | #define FORTRAN_LOWER_CONVERTEXPR_H |
19 | |
20 | #include "flang/Lower/Support/Utils.h" |
21 | #include "flang/Optimizer/Builder/BoxValue.h" |
22 | #include "flang/Optimizer/Builder/FIRBuilder.h" |
23 | #include <optional> |
24 | |
25 | namespace mlir { |
26 | class Location; |
27 | class Value; |
28 | } // namespace mlir |
29 | |
30 | namespace fir { |
31 | class AllocMemOp; |
32 | class ArrayLoadOp; |
33 | class ShapeOp; |
34 | } // namespace fir |
35 | |
36 | namespace Fortran::lower { |
37 | |
38 | class AbstractConverter; |
39 | class ExplicitIterSpace; |
40 | class ImplicitIterSpace; |
41 | class StatementContext; |
42 | class SymMap; |
43 | |
44 | /// Create an extended expression value. |
45 | fir::ExtendedValue createSomeExtendedExpression(mlir::Location loc, |
46 | AbstractConverter &converter, |
47 | const SomeExpr &expr, |
48 | SymMap &symMap, |
49 | StatementContext &stmtCtx); |
50 | |
51 | /// Create the IR for the expression \p expr in an initialization context. |
52 | /// Expressions that appear in initializers may not allocate temporaries, do not |
53 | /// have a stack, etc. |
54 | fir::ExtendedValue createSomeInitializerExpression(mlir::Location loc, |
55 | AbstractConverter &converter, |
56 | const SomeExpr &expr, |
57 | SymMap &symMap, |
58 | StatementContext &stmtCtx); |
59 | |
60 | /// Create an extended expression address. |
61 | fir::ExtendedValue createSomeExtendedAddress(mlir::Location loc, |
62 | AbstractConverter &converter, |
63 | const SomeExpr &expr, |
64 | SymMap &symMap, |
65 | StatementContext &stmtCtx); |
66 | |
67 | /// Create an address in an initializer context. Must be a constant or a symbol |
68 | /// to be resolved at link-time. Expressions that appear in initializers may not |
69 | /// allocate temporaries, do not have a stack, etc. |
70 | fir::ExtendedValue createInitializerAddress(mlir::Location loc, |
71 | AbstractConverter &converter, |
72 | const SomeExpr &expr, |
73 | SymMap &symMap, |
74 | StatementContext &stmtCtx); |
75 | |
76 | /// Create the address of the box. |
77 | /// \p expr must be the designator of an allocatable/pointer entity. |
78 | fir::MutableBoxValue createMutableBox(mlir::Location loc, |
79 | AbstractConverter &converter, |
80 | const SomeExpr &expr, SymMap &symMap); |
81 | |
82 | /// Return true iff the expression is pointing to a parent component. |
83 | bool isParentComponent(const SomeExpr &expr); |
84 | |
85 | /// Update the extended value to represent the parent component. |
86 | fir::ExtendedValue updateBoxForParentComponent(AbstractConverter &converter, |
87 | fir::ExtendedValue exv, |
88 | const SomeExpr &expr); |
89 | |
90 | /// Create a fir::BoxValue describing the value of \p expr. |
91 | /// If \p expr is a variable without vector subscripts, the fir::BoxValue |
92 | /// described the variable storage. Otherwise, the created fir::BoxValue |
93 | /// describes a temporary storage containing \p expr evaluation, and clean-up |
94 | /// for the temporary is added to the provided StatementContext \p stmtCtx. |
95 | fir::ExtendedValue createBoxValue(mlir::Location loc, |
96 | AbstractConverter &converter, |
97 | const SomeExpr &expr, SymMap &symMap, |
98 | StatementContext &stmtCtx); |
99 | |
100 | /// Lower an array assignment expression. |
101 | /// |
102 | /// 1. Evaluate the lhs to determine the rank and how to form the ArrayLoad |
103 | /// (e.g., if there is a slicing op). |
104 | /// 2. Scan the rhs, creating the ArrayLoads and evaluate the scalar subparts to |
105 | /// be added to the map. |
106 | /// 3. Create the loop nest and evaluate the elemental expression, threading the |
107 | /// results. |
108 | /// 4. Copy the resulting array back with ArrayMergeStore to the lhs as |
109 | /// determined per step 1. |
110 | void createSomeArrayAssignment(AbstractConverter &converter, |
111 | const SomeExpr &lhs, const SomeExpr &rhs, |
112 | SymMap &symMap, StatementContext &stmtCtx); |
113 | |
114 | /// Lower an array assignment expression with a pre-evaluated left hand side. |
115 | /// |
116 | /// 1. Scan the rhs, creating the ArrayLoads and evaluate the scalar subparts to |
117 | /// be added to the map. |
118 | /// 2. Create the loop nest and evaluate the elemental expression, threading the |
119 | /// results. |
120 | /// 3. Copy the resulting array back with ArrayMergeStore to the lhs as |
121 | /// determined per step 1. |
122 | void createSomeArrayAssignment(AbstractConverter &converter, |
123 | const fir::ExtendedValue &lhs, |
124 | const SomeExpr &rhs, SymMap &symMap, |
125 | StatementContext &stmtCtx); |
126 | |
127 | /// Lower an array assignment expression with pre-evaluated left and right |
128 | /// hand sides. This implements an array copy taking into account |
129 | /// non-contiguity and potential overlaps. |
130 | void createSomeArrayAssignment(AbstractConverter &converter, |
131 | const fir::ExtendedValue &lhs, |
132 | const fir::ExtendedValue &rhs, SymMap &symMap, |
133 | StatementContext &stmtCtx); |
134 | |
135 | /// Common entry point for both explicit iteration spaces and implicit iteration |
136 | /// spaces with masks. |
137 | /// |
138 | /// For an implicit iteration space with masking, lowers an array assignment |
139 | /// expression with masking expression(s). |
140 | /// |
141 | /// 1. Evaluate the lhs to determine the rank and how to form the ArrayLoad |
142 | /// (e.g., if there is a slicing op). |
143 | /// 2. Scan the rhs, creating the ArrayLoads and evaluate the scalar subparts to |
144 | /// be added to the map. |
145 | /// 3. Create the loop nest. |
146 | /// 4. Create the masking condition. Step 5 is conditionally executed only when |
147 | /// the mask condition evaluates to true. |
148 | /// 5. Evaluate the elemental expression, threading the results. |
149 | /// 6. Copy the resulting array back with ArrayMergeStore to the lhs as |
150 | /// determined per step 1. |
151 | /// |
152 | /// For an explicit iteration space, lower a scalar or array assignment |
153 | /// expression with a user-defined iteration space and possibly with masking |
154 | /// expression(s). |
155 | /// |
156 | /// If the expression is scalar, then the assignment is an array assignment but |
157 | /// the array accesses are explicitly defined by the user and not implied for |
158 | /// each element in the array. Mask expressions are optional. |
159 | /// |
160 | /// If the expression has rank, then the assignment has a combined user-defined |
161 | /// iteration space as well as a inner (subordinate) implied iteration |
162 | /// space. The implied iteration space may include WHERE conditions, `masks`. |
163 | void createAnyMaskedArrayAssignment(AbstractConverter &converter, |
164 | const SomeExpr &lhs, const SomeExpr &rhs, |
165 | ExplicitIterSpace &explicitIterSpace, |
166 | ImplicitIterSpace &implicitIterSpace, |
167 | SymMap &symMap, StatementContext &stmtCtx); |
168 | |
169 | /// Lower an assignment to an allocatable array, allocating the array if |
170 | /// it is not allocated yet or reallocation it if it does not conform |
171 | /// with the right hand side. |
172 | void createAllocatableArrayAssignment(AbstractConverter &converter, |
173 | const SomeExpr &lhs, const SomeExpr &rhs, |
174 | ExplicitIterSpace &explicitIterSpace, |
175 | ImplicitIterSpace &implicitIterSpace, |
176 | SymMap &symMap, |
177 | StatementContext &stmtCtx); |
178 | |
179 | /// Lower a pointer assignment in an explicit iteration space. The explicit |
180 | /// space iterates over a data structure with a type of `!fir.array<... |
181 | /// !fir.box<!fir.ptr<T>> ...>`. Lower the assignment by copying the rhs box |
182 | /// value to each array element. |
183 | void createArrayOfPointerAssignment( |
184 | AbstractConverter &converter, const SomeExpr &lhs, const SomeExpr &rhs, |
185 | ExplicitIterSpace &explicitIterSpace, ImplicitIterSpace &implicitIterSpace, |
186 | const llvm::SmallVector<mlir::Value> &lbounds, |
187 | std::optional<llvm::SmallVector<mlir::Value>> ubounds, SymMap &symMap, |
188 | StatementContext &stmtCtx); |
189 | |
190 | /// Lower an array expression with "parallel" semantics. Such a rhs expression |
191 | /// is fully evaluated prior to being assigned back to a temporary array. |
192 | fir::ExtendedValue createSomeArrayTempValue(AbstractConverter &converter, |
193 | const SomeExpr &expr, |
194 | SymMap &symMap, |
195 | StatementContext &stmtCtx); |
196 | |
197 | /// Somewhat similar to createSomeArrayTempValue, but the temporary buffer is |
198 | /// allocated lazily (inside the loops instead of before the loops) to |
199 | /// accomodate buffers with shapes that cannot be precomputed. In fact, the |
200 | /// buffer need not even be hyperrectangular. The buffer may be created as an |
201 | /// instance of a ragged array, which may be useful if an array's extents are |
202 | /// functions of other loop indices. The ragged array structure is built with \p |
203 | /// raggedHeader being the root header variable. The header is a tuple of |
204 | /// `{rank, data-is-headers, [data]*, [extents]*}`, which is built recursively. |
205 | /// The base header, \p raggedHeader, must be initialized to zeros. |
206 | void createLazyArrayTempValue(AbstractConverter &converter, |
207 | const SomeExpr &expr, mlir::Value raggedHeader, |
208 | SymMap &symMap, StatementContext &stmtCtx); |
209 | |
210 | /// Lower an array expression to a value of type box. The expression must be a |
211 | /// variable. |
212 | fir::ExtendedValue createSomeArrayBox(AbstractConverter &converter, |
213 | const SomeExpr &expr, SymMap &symMap, |
214 | StatementContext &stmtCtx); |
215 | |
216 | /// Lower a subroutine call. This handles both elemental and non elemental |
217 | /// subroutines. \p isUserDefAssignment must be set if this is called in the |
218 | /// context of a user defined assignment. For subroutines with alternate |
219 | /// returns, the returned value indicates which label the code should jump to. |
220 | /// The returned value is null otherwise. |
221 | mlir::Value createSubroutineCall(AbstractConverter &converter, |
222 | const evaluate::ProcedureRef &call, |
223 | ExplicitIterSpace &explicitIterSpace, |
224 | ImplicitIterSpace &implicitIterSpace, |
225 | SymMap &symMap, StatementContext &stmtCtx, |
226 | bool isUserDefAssignment); |
227 | |
228 | mlir::Value addCrayPointerInst(mlir::Location loc, fir::FirOpBuilder &builder, |
229 | mlir::Value ptrVal, mlir::Type ptrTy, |
230 | mlir::Type pteTy); |
231 | } // namespace Fortran::lower |
232 | |
233 | #endif // FORTRAN_LOWER_CONVERTEXPR_H |
234 |
Warning: This file is not a C or C++ file. It does not have highlighting.