Warning: This file is not a C or C++ file. It does not have highlighting.
1 | //===-- HlfirIntrinsics.h -- lowering to HLFIR intrinsic ops ----*- 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 lowering of transformational intrinsics to HLFIR intrinsic |
14 | /// operations |
15 | /// |
16 | //===----------------------------------------------------------------------===// |
17 | |
18 | #ifndef FORTRAN_LOWER_HLFIRINTRINSICS_H |
19 | #define FORTRAN_LOWER_HLFIRINTRINSICS_H |
20 | |
21 | #include "flang/Optimizer/Builder/HLFIRTools.h" |
22 | #include "flang/Optimizer/Builder/Todo.h" |
23 | #include "flang/Optimizer/HLFIR/HLFIROps.h" |
24 | #include "llvm/ADT/SmallVector.h" |
25 | #include <cassert> |
26 | #include <optional> |
27 | #include <string> |
28 | |
29 | namespace mlir { |
30 | class Location; |
31 | class Type; |
32 | class Value; |
33 | class ValueRange; |
34 | } // namespace mlir |
35 | |
36 | namespace fir { |
37 | class FirOpBuilder; |
38 | struct IntrinsicArgumentLoweringRules; |
39 | } // namespace fir |
40 | |
41 | namespace Fortran::lower { |
42 | |
43 | /// This structure holds the initial lowered value of an actual argument that |
44 | /// was lowered regardless of the interface, and it holds whether or not it |
45 | /// may be absent at runtime and the dummy is optional. |
46 | struct PreparedActualArgument { |
47 | |
48 | PreparedActualArgument(hlfir::Entity actual, |
49 | std::optional<mlir::Value> isPresent) |
50 | : actual{actual}, isPresent{isPresent} {} |
51 | PreparedActualArgument(hlfir::ElementalAddrOp vectorSubscriptedActual) |
52 | : actual{vectorSubscriptedActual}, isPresent{std::nullopt} {} |
53 | void setElementalIndices(mlir::ValueRange &indices) { |
54 | oneBasedElementalIndices = &indices; |
55 | } |
56 | |
57 | /// Get the prepared actual. If this is an array argument in an elemental |
58 | /// call, the current element value will be returned. |
59 | hlfir::Entity getActual(mlir::Location loc, fir::FirOpBuilder &builder) const; |
60 | |
61 | void derefPointersAndAllocatables(mlir::Location loc, |
62 | fir::FirOpBuilder &builder) { |
63 | if (auto *actualEntity = std::get_if<hlfir::Entity>(&actual)) |
64 | actual = hlfir::derefPointersAndAllocatables(loc, builder, *actualEntity); |
65 | } |
66 | |
67 | void loadTrivialScalar(mlir::Location loc, fir::FirOpBuilder &builder) { |
68 | if (auto *actualEntity = std::get_if<hlfir::Entity>(&actual)) |
69 | actual = hlfir::loadTrivialScalar(loc, builder, *actualEntity); |
70 | } |
71 | |
72 | /// Ensure an array expression argument is fully evaluated in memory before |
73 | /// the call. Useful for impure elemental calls. |
74 | hlfir::AssociateOp associateIfArrayExpr(mlir::Location loc, |
75 | fir::FirOpBuilder &builder) { |
76 | if (auto *actualEntity = std::get_if<hlfir::Entity>(&actual)) { |
77 | if (!actualEntity->isVariable() && actualEntity->isArray()) { |
78 | mlir::Type storageType = actualEntity->getType(); |
79 | hlfir::AssociateOp associate = hlfir::genAssociateExpr( |
80 | loc, builder, *actualEntity, storageType, "adapt.impure_arg_eval"); |
81 | actual = hlfir::Entity{associate}; |
82 | return associate; |
83 | } |
84 | } |
85 | return {}; |
86 | } |
87 | |
88 | bool isArray() const { |
89 | return std::holds_alternative<hlfir::ElementalAddrOp>(actual) || |
90 | std::get<hlfir::Entity>(actual).isArray(); |
91 | } |
92 | |
93 | mlir::Value genShape(mlir::Location loc, fir::FirOpBuilder &builder) { |
94 | if (auto *actualEntity = std::get_if<hlfir::Entity>(&actual)) |
95 | return hlfir::genShape(loc, builder, *actualEntity); |
96 | return std::get<hlfir::ElementalAddrOp>(actual).getShape(); |
97 | } |
98 | |
99 | mlir::Value genCharLength(mlir::Location loc, fir::FirOpBuilder &builder) { |
100 | if (auto *actualEntity = std::get_if<hlfir::Entity>(&actual)) |
101 | return hlfir::genCharLength(loc, builder, *actualEntity); |
102 | auto typeParams = std::get<hlfir::ElementalAddrOp>(actual).getTypeparams(); |
103 | assert(typeParams.size() == 1 && |
104 | "failed to retrieve vector subscripted character length"); |
105 | return typeParams[0]; |
106 | } |
107 | |
108 | /// When the argument is polymorphic, get mold value with the same dynamic |
109 | /// type. |
110 | mlir::Value getPolymorphicMold(mlir::Location loc) const { |
111 | if (auto *actualEntity = std::get_if<hlfir::Entity>(&actual)) |
112 | return *actualEntity; |
113 | TODO(loc, "polymorphic vector subscripts"); |
114 | } |
115 | |
116 | bool handleDynamicOptional() const { return isPresent.has_value(); } |
117 | mlir::Value getIsPresent() const { |
118 | assert(handleDynamicOptional() && "not a dynamic optional"); |
119 | return *isPresent; |
120 | } |
121 | |
122 | void resetOptionalAspect() { isPresent = std::nullopt; } |
123 | |
124 | private: |
125 | std::variant<hlfir::Entity, hlfir::ElementalAddrOp> actual; |
126 | mlir::ValueRange *oneBasedElementalIndices{nullptr}; |
127 | // When the actual may be dynamically optional, "isPresent" |
128 | // holds a boolean value indicating the presence of the |
129 | // actual argument at runtime. |
130 | std::optional<mlir::Value> isPresent; |
131 | }; |
132 | |
133 | /// Vector of pre-lowered actual arguments. nullopt if the actual is |
134 | /// "statically" absent (if it was not syntactically provided). |
135 | using PreparedActualArguments = |
136 | llvm::SmallVector<std::optional<PreparedActualArgument>>; |
137 | |
138 | std::optional<hlfir::EntityWithAttributes> lowerHlfirIntrinsic( |
139 | fir::FirOpBuilder &builder, mlir::Location loc, const std::string &name, |
140 | const Fortran::lower::PreparedActualArguments &loweredActuals, |
141 | const fir::IntrinsicArgumentLoweringRules *argLowering, |
142 | mlir::Type stmtResultType); |
143 | |
144 | } // namespace Fortran::lower |
145 | #endif // FORTRAN_LOWER_HLFIRINTRINSICS_H |
146 |
Warning: This file is not a C or C++ file. It does not have highlighting.