| //===-- 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); |
| |
| 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 |