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