13#ifndef FORTRAN_LOWER_SYMBOLMAP_H
14#define FORTRAN_LOWER_SYMBOLMAP_H
16#include "flang/Lower/Support/Utils.h"
17#include "flang/Optimizer/Builder/BoxValue.h"
18#include "flang/Optimizer/Dialect/FIRType.h"
19#include "flang/Optimizer/Dialect/FortranVariableInterface.h"
20#include "flang/Optimizer/Support/Matcher.h"
21#include "flang/Semantics/symbol.h"
22#include "mlir/IR/Value.h"
23#include "llvm/ADT/ArrayRef.h"
24#include "llvm/ADT/DenseMap.h"
25#include "llvm/ADT/SmallVector.h"
26#include "llvm/Support/Compiler.h"
33llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
const SymbolBox &symMap);
34llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
const SymMap &symMap);
54 using None = std::monostate;
79 std::variant<Intrinsic, FullDim, Char, CharFullDim, PointerOrAllocatable,
80 Box, fir::FortranVariableOpInterface, None>;
86 SymbolBox() : box{None{}} {}
88 SymbolBox(
const A &x) : box{x} {}
90 explicit operator bool()
const {
return !std::holds_alternative<None>(box); }
100 return match([](
const None &) {
return mlir::Value{}; },
101 [](
const fir::FortranVariableOpInterface &x) {
102 return fir::FortranVariableOpInterface(x).getBase();
104 [](
const auto &x) {
return x.getAddr(); });
107 std::optional<fir::FortranVariableOpInterface>
108 getIfFortranVariableOpInterface() {
110 [](
const fir::FortranVariableOpInterface &x)
111 -> std::optional<fir::FortranVariableOpInterface> {
return x; },
112 [](
const auto &x) -> std::optional<fir::FortranVariableOpInterface> {
118 template <
typename ON,
typename RT>
119 constexpr RT
apply(RT (&&func)(
const ON &))
const {
120 if (
auto *x = std::get_if<ON>(&box))
125 const VT &matchee()
const {
return box; }
127 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
128 const SymbolBox &symBox);
131 LLVM_DUMP_METHOD
void dump()
const;
143 fir::FortranVariableOpInterface definingOp) {
144 auto iter = componentMap.find(&component);
145 if (iter != componentMap.end()) {
146 iter->second = definingOp;
149 componentStorage.push_back(
150 std::make_unique<Fortran::evaluate::Component>(component));
151 componentMap.insert({componentStorage.back().get(), definingOp});
154 std::optional<fir::FortranVariableOpInterface>
156 auto iter = componentMap.find(component);
157 if (iter != componentMap.end())
162 LLVM_DUMP_METHOD
void dump()
const;
166 fir::FortranVariableOpInterface>
183 using AcDoVar = llvm::StringRef;
188 SymMap() { pushScope(); }
199 while (!sym->HasLocalLocality()) {
202 return sym->GetUltimate();
203 sym = &hostAssoc->symbol();
209 symbolMapStack.emplace_back();
210 deviceSymbolMapStack.emplace_back();
211 storageMapStack.emplace_back();
212 componentMapStack.emplace_back();
215 symbolMapStack.pop_back();
216 assert(symbolMapStack.size() >= 1);
217 deviceSymbolMapStack.pop_back();
218 assert(deviceSymbolMapStack.size() >= 1);
219 storageMapStack.pop_back();
220 assert(storageMapStack.size() >= 1);
221 componentMapStack.pop_back();
222 assert(componentMapStack.size() >= 1);
230 void addSymbol(semantics::SymbolRef sym, mlir::Value value,
231 bool force =
false) {
232 makeSym(sym, SymbolBox::Intrinsic(value), force);
237 mlir::Value len,
bool force =
false) {
238 makeSym(sym, SymbolBox::Char(value, len), force);
240 void addCharSymbol(semantics::SymbolRef sym,
const SymbolBox::Char &value,
241 bool force =
false) {
242 makeSym(sym, value, force);
248 bool force =
false) {
249 makeSym(sym, SymbolBox::FullDim(value, shape), force);
252 const SymbolBox::FullDim &value,
bool force =
false) {
253 makeSym(sym, value, force);
260 bool force =
false) {
261 makeSym(sym, SymbolBox::CharFullDim(value, len, shape), force);
264 const SymbolBox::CharFullDim &value,
265 bool force =
false) {
266 makeSym(sym, value, force);
273 bool force =
false) {
274 makeSym(sym, SymbolBox::FullDim(value, extents, lbounds), force);
277 const SymbolBox::FullDim &value,
278 bool force =
false) {
279 makeSym(sym, value, force);
287 bool force =
false) {
288 makeSym(sym, SymbolBox::CharFullDim(value, len, extents, lbounds), force);
291 const SymbolBox::CharFullDim &value,
292 bool force =
false) {
293 makeSym(sym, value, force);
296 void addAllocatableOrPointer(semantics::SymbolRef sym,
298 makeSym(sym, box, force);
301 void addBoxSymbol(semantics::SymbolRef sym, mlir::Value irBox,
305 bool force =
false) {
307 SymbolBox::Box(irBox, lbounds, explicitParams, explicitExtents),
310 void addBoxSymbol(semantics::SymbolRef sym,
const SymbolBox::Box &value,
311 bool force =
false) {
312 makeSym(sym, value, force);
325 fir::FortranVariableOpInterface definingOp,
326 bool force =
false) {
327 makeDeviceSym(symRef,
SymbolBox(definingOp), force);
329 SymbolBox lookupDeviceSymbol(semantics::SymbolRef);
330 bool copyDeviceBindingToCurrentScope(semantics::SymbolRef symRef) {
331 if (
SymbolBox box{lookupDeviceSymbol(symRef)}) {
332 makeSym(symRef, box,
true);
358 impliedDoStack.emplace_back(var, value);
363 assert(!impliedDoStack.empty());
364 impliedDoStack.pop_back();
373 symbolMapStack.clear();
374 symbolMapStack.emplace_back();
375 deviceSymbolMapStack.clear();
376 deviceSymbolMapStack.emplace_back();
377 assert(symbolMapStack.size() == 1);
378 impliedDoStack.clear();
379 storageMapStack.clear();
380 storageMapStack.emplace_back();
381 componentMapStack.clear();
382 componentMapStack.emplace_back();
385 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
389 LLVM_DUMP_METHOD
void dump()
const;
391 void addVariableDefinition(semantics::SymbolRef symRef,
392 fir::FortranVariableOpInterface definingOp,
393 bool force =
false) {
394 makeSym(symRef,
SymbolBox(definingOp), force);
397 void copySymbolBinding(semantics::SymbolRef src,
398 semantics::SymbolRef target) {
400 assert(symBox &&
"source binding does not exists");
401 makeSym(target, symBox,
false);
404 std::optional<fir::FortranVariableOpInterface>
405 lookupVariableDefinition(semantics::SymbolRef sym) {
407 return symBox.getIfFortranVariableOpInterface();
415 fir::FortranVariableOpInterface definingOp) {
416 assert(!componentMapStack.empty() &&
"component map stack is empty");
417 if (!componentMapStack.back())
418 componentMapStack.back() = std::make_unique<ComponentMap>();
419 componentMapStack.back().value()->insert(component, definingOp);
424 std::optional<fir::FortranVariableOpInterface>
426 for (
auto jmap = componentMapStack.rbegin(),
427 jend = componentMapStack.rend();
428 jmap != jend; ++jmap) {
430 auto iter = (**jmap)->lookup(&component);
431 if (iter != std::nullopt)
450 void makeSym(semantics::SymbolRef symRef,
const SymbolBox &box,
451 bool force =
false) {
452 auto *sym = &
getKey(symRef);
454 symbolMapStack.back().erase(sym);
455 assert(box &&
"cannot add an undefined symbol box");
456 symbolMapStack.back().try_emplace(sym, box);
459 void makeDeviceSym(semantics::SymbolRef symRef,
const SymbolBox &box,
460 bool force =
false) {
461 auto *sym = &
getKey(symRef);
463 deviceSymbolMapStack.back().erase(sym);
464 assert(box &&
"cannot add an undefined device symbol box");
465 deviceSymbolMapStack.back().try_emplace(sym, box);
468 llvm::SmallVector<llvm::DenseMap<const semantics::Symbol *, SymbolBox>>
470 llvm::SmallVector<llvm::DenseMap<const semantics::Symbol *, SymbolBox>>
471 deviceSymbolMapStack;
475 llvm::SmallVector<std::pair<AcDoVar, mlir::Value>> impliedDoStack;
478 llvm::SmallVector<llvm::DenseMap<const semantics::Symbol *, StorageDesc>>
484 llvm::SmallVector<std::optional<std::unique_ptr<ComponentMap>>>
491 explicit SymMapScope(
SymMap &map) : map(map) { map.pushScope(); }
492 ~SymMapScope() { map.popScope(); }
Definition SymbolMap.h:140
Definition SymbolMap.h:181
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:246
void addComponentOverride(const Fortran::evaluate::Component &component, fir::FortranVariableOpInterface definingOp)
Definition SymbolMap.h:414
void pushImpliedDoBinding(AcDoVar var, mlir::Value value)
Add a new binding from the ac-do-variable var to value.
Definition SymbolMap.h:357
SymbolBox lookupSymbol(semantics::SymbolRef sym)
Find symbol and return its value if it appears in the current mappings.
Definition SymbolMap.cpp:35
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:270
mlir::Value lookupImpliedDo(AcDoVar var)
Definition SymbolMap.cpp:99
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:257
void addDeviceVariableDefinition(semantics::SymbolRef symRef, fir::FortranVariableOpInterface definingOp, bool force=false)
Definition SymbolMap.h:324
void popImpliedDoBinding()
Pop the most recent implied do binding off the stack.
Definition SymbolMap.h:362
void addSymbol(semantics::SymbolRef sym, mlir::Value value, bool force=false)
Add a trivial symbol mapping to an address.
Definition SymbolMap.h:230
std::pair< mlir::Value, std::uint64_t > StorageDesc
Definition SymbolMap.h:186
std::optional< fir::FortranVariableOpInterface > lookupComponentOverride(const Fortran::evaluate::Component &component) const
Definition SymbolMap.h:425
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:283
void registerStorage(semantics::SymbolRef sym, StorageDesc storage)
Definition SymbolMap.cpp:106
void clear()
Remove all symbols from the map.
Definition SymbolMap.h:372
SymbolBox lookupOneLevelUpSymbol(semantics::SymbolRef sym)
Definition SymbolMap.cpp:82
void addSymbol(semantics::SymbolRef sym, const fir::ExtendedValue &ext, bool force=false)
Add an extended value to the symbol table.
Definition SymbolMap.cpp:19
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:236
static const semantics::Symbol & getKey(semantics::SymbolRef symRef)
Definition SymbolMap.h:197
SymbolBox shallowLookupSymbol(semantics::SymbolRef sym)
Definition SymbolMap.cpp:69
StorageDesc lookupStorage(semantics::SymbolRef sym)
Lookup the symbol's storage at the innermost level of the symbol table.
Definition SymbolMap.cpp:114
LLVM_DUMP_METHOD void dump() const
Dump the map. For debugging.
Definition SymbolMap.cpp:135
const semantics::Symbol * lookupSymbolByName(llvm::StringRef symName)
Definition SymbolMap.cpp:60
Abstract base class.
Definition BoxValue.h:60
Definition BoxValue.h:152
Definition BoxValue.h:292
Expressions of type CHARACTER and with rank > 0.
Definition BoxValue.h:169
Definition BoxValue.h:469
Definition BoxValue.h:361
Definition ParserActions.h:24
Definition SymbolMap.h:52
mlir::Value getAddr() const
Definition SymbolMap.h:99
constexpr RT apply(RT(&&func)(const ON &)) const
Apply the lambda func to this box value.
Definition SymbolMap.h:119
LLVM_DUMP_METHOD void dump() const
Dump the map. For debugging.
Definition SymbolMap.cpp:123