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
29namespace mlir {
30class Location;
31class Type;
32class Value;
33class ValueRange;
34} // namespace mlir
35
36namespace fir {
37class FirOpBuilder;
38struct IntrinsicArgumentLoweringRules;
39} // namespace fir
40
41namespace 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.
46struct 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
124private:
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).
135using PreparedActualArguments =
136 llvm::SmallVector<std::optional<PreparedActualArgument>>;
137
138std::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.

source code of flang/include/flang/Lower/HlfirIntrinsics.h