xref: /llvm-project/flang/include/flang/Lower/ConvertExpr.h (revision 0ccef6a723cbfe3d72b85d34963badb37a6a9a53)
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