FLANG

SymbolMap.h
1 //===-- SymbolMap.h -- lowering internal symbol map -------------*- 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 #ifndef FORTRAN_LOWER_SYMBOLMAP_H
10 #define FORTRAN_LOWER_SYMBOLMAP_H
11
12 #include "flang/Common/idioms.h"
13 #include "flang/Common/reference.h"
14 #include "flang/Lower/Support/BoxValue.h"
15 #include "flang/Optimizer/Dialect/FIRType.h"
16 #include "flang/Semantics/symbol.h"
17 #include "mlir/IR/Value.h"
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/ADT/DenseMap.h"
20 #include "llvm/ADT/Optional.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/Support/Compiler.h"
23
24 namespace Fortran::lower {
25
26 //===----------------------------------------------------------------------===//
27 // Symbol information
28 //===----------------------------------------------------------------------===//
29
42 struct SymbolBox {
43 // For lookups that fail, have a monostate
44 using None = std::monostate;
45
46 // Trivial intrinsic type
47 using Intrinsic = fir::AbstractBox;
48
49 // Array variable that uses bounds notation
50 using FullDim = fir::ArrayBoxValue;
51
52 // CHARACTER type variable with its dependent type LEN parameter
53 using Char = fir::CharBoxValue;
54
55 // CHARACTER array variable using bounds notation
56 using CharFullDim = fir::CharArrayBoxValue;
57
58 // Generalized derived type variable
59 using Derived = fir::BoxValue;
60
61 //===--------------------------------------------------------------------===//
62 // Constructors
63 //===--------------------------------------------------------------------===//
64
65 SymbolBox() : box{None{}} {}
66 template <typename A>
67 SymbolBox(const A &x) : box{x} {}
68
69 operator bool() const { return !std::holds_alternative<None>(box); }
70
71 // This operator returns the address of the boxed value. TODO: consider
72 // eliminating this in favor of explicit conversion.
73 operator mlir::Value() const { return getAddr(); }
74
75 //===--------------------------------------------------------------------===//
76 // Accessors
77 //===--------------------------------------------------------------------===//
78
82 mlir::Value getAddr() const {
83 return std::visit(common::visitors{
84 [](const None &) { return mlir::Value{}; },
85 [](const auto &x) { return x.getAddr(); },
86 },
87 box);
88 }
89
91 llvm::Optional<mlir::Value> getCharLen() const {
92 using T = llvm::Optional<mlir::Value>;
93 return std::visit(common::visitors{
94 [](const Char &x) { return T{x.getLen()}; },
95 [](const CharFullDim &x) { return T{x.getLen()}; },
96 [](const auto &) { return T{}; },
97 },
98 box);
99 }
100
102 bool isIntrinsic() const {
103 return std::visit(common::visitors{
104 [](const Intrinsic &) { return true; },
105 [](const Char &) { return true; },
106 [](const auto &x) { return false; },
107 },
108 box);
109 }
110
112 bool hasRank() const {
113 return std::visit(
114 common::visitors{
115 [](const Intrinsic &) { return false; },
116 [](const Char &) { return false; },
117 [](const None &) { return false; },
118 [](const auto &x) { return x.getExtents().size() > 0; },
119 },
120 box);
121 }
122
124 bool hasSimpleLBounds() const {
125 if (auto *arr = std::get_if<FullDim>(&box))
126 return arr->getLBounds().empty();
127 if (auto *arr = std::get_if<CharFullDim>(&box))
128 return arr->getLBounds().empty();
129 if (auto *arr = std::get_if<Derived>(&box))
130 return (arr->getExtents().size() > 0) && arr->getLBounds().empty();
131 return false;
132 }
133
135 bool hasConstantShape() const {
136 if (auto eleTy = fir::dyn_cast_ptrEleTy(getAddr().getType()))
137 if (auto arrTy = eleTy.dyn_cast<fir::SequenceType>())
138 return arrTy.hasConstantShape();
139 return false;
140 }
141
143 mlir::Value getLBound(unsigned dim) const {
144 return std::visit(
145 common::visitors{
146 [&](const FullDim &box) { return box.getLBounds()[dim]; },
147 [&](const CharFullDim &box) { return box.getLBounds()[dim]; },
148 [&](const Derived &box) { return box.getLBounds()[dim]; },
149 [](const auto &) { return mlir::Value{}; }},
150 box);
151 }
152
154 template <typename ON, typename RT>
155 constexpr RT apply(RT(&&func)(const ON &)) const {
156 if (auto *x = std::get_if<ON>(&box))
157 return func(*x);
158 return RT{};
159 }
160
161 std::variant<Intrinsic, FullDim, Char, CharFullDim, Derived, None> box;
162 };
163
164 //===----------------------------------------------------------------------===//
165 // Map of symbol information
166 //===----------------------------------------------------------------------===//
167
173 class SymMap {
174 public:
176 void addSymbol(semantics::SymbolRef sym, mlir::Value value,
177 bool force = false) {
178 makeSym(sym, SymbolBox::Intrinsic(value), force);
179 }
180
182 void addCharSymbol(semantics::SymbolRef sym, mlir::Value value,
183 mlir::Value len, bool force = false) {
184 makeSym(sym, SymbolBox::Char(value, len), force);
185 }
186
188 void addSymbolWithShape(semantics::SymbolRef sym, mlir::Value value,
189 llvm::ArrayRef<mlir::Value> shape,
190 bool force = false) {
191 makeSym(sym, SymbolBox::FullDim(value, shape), force);
192 }
193
195 void addCharSymbolWithShape(semantics::SymbolRef sym, mlir::Value value,
196 mlir::Value len,
197 llvm::ArrayRef<mlir::Value> shape,
198 bool force = false) {
199 makeSym(sym, SymbolBox::CharFullDim(value, len, shape), force);
200 }
201
203 void addSymbolWithBounds(semantics::SymbolRef sym, mlir::Value value,
204 llvm::ArrayRef<mlir::Value> extents,
205 llvm::ArrayRef<mlir::Value> lbounds,
206 bool force = false) {
207 makeSym(sym, SymbolBox::FullDim(value, extents, lbounds), force);
208 }
209
211 void addCharSymbolWithBounds(semantics::SymbolRef sym, mlir::Value value,
212 mlir::Value len,
213 llvm::ArrayRef<mlir::Value> extents,
214 llvm::ArrayRef<mlir::Value> lbounds,
215 bool force = false) {
216 makeSym(sym, SymbolBox::CharFullDim(value, len, extents, lbounds), force);
217 }
218
220 void addDerivedSymbol(semantics::SymbolRef sym, mlir::Value value,
221 mlir::Value size, llvm::ArrayRef<mlir::Value> extents,
222 llvm::ArrayRef<mlir::Value> lbounds,
223 llvm::ArrayRef<mlir::Value> params,
224 bool force = false) {
225 makeSym(sym, SymbolBox::Derived(value, size, params, extents, lbounds),
226 force);
227 }
228
230 SymbolBox lookupSymbol(semantics::SymbolRef sym) {
231 auto iter = symbolMap.find(&*sym);
232 return (iter == symbolMap.end()) ? SymbolBox() : iter->second;
233 }
234
236 void erase(semantics::SymbolRef sym) { symbolMap.erase(&*sym); }
237
239 void clear() { symbolMap.clear(); }
240
242 LLVM_DUMP_METHOD void dump() const;
243
244 private:
246 void makeSym(semantics::SymbolRef sym, const SymbolBox &box,
247 bool force = false) {
248 if (force)
249 erase(sym);
250 assert(box && "cannot add an undefined symbol box");
251 symbolMap.try_emplace(&*sym, box);
252 }
253
254 llvm::DenseMap<const semantics::Symbol *, SymbolBox> symbolMap;
255 };
256
257 } // namespace Fortran::lower
258
259 #endif // FORTRAN_LOWER_SYMBOLMAP_H
Fortran::lower::SymMap::clear
void clear()
Remove all symbols from the map.
Definition: SymbolMap.h:239
Fortran::lower::SymMap::lookupSymbol
SymbolBox lookupSymbol(semantics::SymbolRef sym)
Find symbol and return its value if it appears in the current mappings.
Definition: SymbolMap.h:230
Fortran::lower::SymMap::addSymbol
void addSymbol(semantics::SymbolRef sym, mlir::Value value, bool force=false)
Add a trivial symbol mapping to an address.
Definition: SymbolMap.h:176
Fortran::lower::SymbolBox::hasConstantShape
bool hasConstantShape() const
Does the boxed value have a constant shape?
Definition: SymbolMap.h:135
fir::ArrayBoxValue
Definition: BoxValue.h:109
Fortran::lower::SymbolBox
Definition: SymbolMap.h:42
Fortran::lower::SymMap::erase
void erase(semantics::SymbolRef sym)
Remove sym from the map.
Definition: SymbolMap.h:236
Fortran::lower::SymMap::addSymbolWithShape
void addSymbolWithShape(semantics::SymbolRef sym, mlir::Value value, llvm::ArrayRef< mlir::Value > shape, bool force=false)
Add an array mapping with (address, shape).
Definition: SymbolMap.h:188
Fortran::lower::SymMap
Definition: SymbolMap.h:173
Fortran::lower::SymMap::addCharSymbolWithShape
void addCharSymbolWithShape(semantics::SymbolRef sym, mlir::Value value, mlir::Value len, llvm::ArrayRef< mlir::Value > shape, bool force=false)
Add an array of CHARACTER mapping.
Definition: SymbolMap.h:195
Fortran::lower::SymMap::addCharSymbol
void addCharSymbol(semantics::SymbolRef sym, mlir::Value value, mlir::Value len, bool force=false)
Add a scalar CHARACTER mapping to an (address, len).
Definition: SymbolMap.h:182
Fortran::common::Reference< const Symbol >
Fortran::lower::SymMap::addCharSymbolWithBounds
void addCharSymbolWithBounds(semantics::SymbolRef sym, mlir::Value value, mlir::Value len, llvm::ArrayRef< mlir::Value > extents, llvm::ArrayRef< mlir::Value > lbounds, bool force=false)
Add an array of CHARACTER with bounds notation.
Definition: SymbolMap.h:211
Fortran::lower::SymbolBox::getCharLen
llvm::Optional< mlir::Value > getCharLen() const
Get the LEN type parameter of a CHARACTER boxed value.
Definition: SymbolMap.h:91
llvm::ArrayRef
Definition: FIRType.h:20
Fortran::lower::SymbolBox::getAddr
mlir::Value getAddr() const
Definition: SymbolMap.h:82
Fortran::lower::SymbolBox::apply
constexpr RT apply(RT(&&func)(const ON &)) const
Apply the lambda func to this box value.
Definition: SymbolMap.h:155
Fortran::lower::SymbolBox::isIntrinsic
bool isIntrinsic() const
Does the boxed value have an intrinsic type?
Definition: SymbolMap.h:102
Fortran::lower::SymMap::dump
LLVM_DUMP_METHOD void dump() const
Dump the map. For debugging.
Fortran::lower::SymMap::addDerivedSymbol
void addDerivedSymbol(semantics::SymbolRef sym, mlir::Value value, mlir::Value size, llvm::ArrayRef< mlir::Value > extents, llvm::ArrayRef< mlir::Value > lbounds, llvm::ArrayRef< mlir::Value > params, bool force=false)
Generalized derived type mapping.
Definition: SymbolMap.h:220
Fortran::lower::SymbolBox::getLBound
mlir::Value getLBound(unsigned dim) const
Get the lbound if the box explicitly contains it.
Definition: SymbolMap.h:143
fir::CharBoxValue
Definition: BoxValue.h:59
Fortran::lower::SymbolBox::hasRank
bool hasRank() const
Does the boxed value have a rank greater than zero?
Definition: SymbolMap.h:112
fir::AbstractBox
Abstract base class.
Definition: BoxValue.h:47
Fortran::lower::SymbolBox::hasSimpleLBounds
bool hasSimpleLBounds() const
Does the boxed value have trivial lower bounds (== 1)?
Definition: SymbolMap.h:124
fir::CharArrayBoxValue
Expressions of type CHARACTER and with rank > 0.
Definition: BoxValue.h:125
Fortran::common::visitors
Definition: idioms.h:58
fir::SequenceType
Definition: FIRType.h:323
fir::BoxValue
Definition: BoxValue.h:164
Fortran::lower::SymMap::addSymbolWithBounds
void addSymbolWithBounds(semantics::SymbolRef sym, mlir::Value value, llvm::ArrayRef< mlir::Value > extents, llvm::ArrayRef< mlir::Value > lbounds, bool force=false)
Add an array mapping with bounds notation.
Definition: SymbolMap.h:203