FLANG
HlfirIntrinsics.h
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//===----------------------------------------------------------------------===//
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
47
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
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
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
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
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
Definition: FIRBuilder.h:55
Definition: HLFIRTools.h:51
bool isArray() const
Is this an array or an assumed ranked entity?
Definition: HLFIRTools.h:73
Definition: OpenACC.h:20
Definition: AbstractConverter.h:59
Definition: AbstractConverter.h:31
@ Value
Lower argument to a value. Mainly intended for scalar arguments.
Definition: AbstractConverter.h:27
Definition: HlfirIntrinsics.h:46
mlir::Value getPolymorphicMold(mlir::Location loc) const
Definition: HlfirIntrinsics.h:110
hlfir::Entity getActual(mlir::Location loc, fir::FirOpBuilder &builder) const
Definition: ConvertCall.cpp:2797
hlfir::AssociateOp associateIfArrayExpr(mlir::Location loc, fir::FirOpBuilder &builder)
Definition: HlfirIntrinsics.h:74
This is shared by intrinsics and intrinsic module procedures.
Definition: IntrinsicCall.h:529