FLANG
PFTBuilder.h
1//===-- Lower/PFTBuilder.h -- PFT builder -----------------------*- 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// PFT (Pre-FIR Tree) interface.
14//
15//===----------------------------------------------------------------------===//
16
17#ifndef FORTRAN_LOWER_PFTBUILDER_H
18#define FORTRAN_LOWER_PFTBUILDER_H
19
20#include "flang/Common/reference.h"
21#include "flang/Common/template.h"
22#include "flang/Lower/HostAssociations.h"
23#include "flang/Lower/PFTDefs.h"
24#include "flang/Parser/parse-tree.h"
25#include "flang/Semantics/attr.h"
26#include "flang/Semantics/scope.h"
27#include "flang/Semantics/semantics.h"
28#include "flang/Semantics/symbol.h"
29#include "llvm/Support/ErrorHandling.h"
30#include "llvm/Support/raw_ostream.h"
31
32namespace Fortran::lower::pft {
33
34struct CompilerDirectiveUnit;
35struct Evaluation;
36struct FunctionLikeUnit;
37struct ModuleLikeUnit;
38struct Program;
39
40using ContainedUnit = std::variant<CompilerDirectiveUnit, FunctionLikeUnit>;
41using ContainedUnitList = std::list<ContainedUnit>;
42using EvaluationList = std::list<Evaluation>;
43
47template <bool isConst, typename... A>
49public:
50 template <typename B>
51 using BaseType = std::conditional_t<isConst, const B, B>;
52 template <typename B>
54
55 ReferenceVariantBase() = delete;
56 ReferenceVariantBase(std::variant<Ref<A>...> b) : u(b) {}
57 template <typename T>
58 ReferenceVariantBase(Ref<T> b) : u(b) {}
59
60 template <typename B>
61 constexpr BaseType<B> &get() const {
62 return std::get<Ref<B>>(u).get();
63 }
64 template <typename B>
65 constexpr BaseType<B> &getStatement() const {
66 return std::get<Ref<parser::Statement<B>>>(u).get().statement;
67 }
68 template <typename B>
69 constexpr BaseType<B> *getIf() const {
70 const Ref<B> *ptr = std::get_if<Ref<B>>(&u);
71 return ptr ? &ptr->get() : nullptr;
72 }
73 template <typename B>
74 constexpr bool isA() const {
75 return std::holds_alternative<Ref<B>>(u);
76 }
77 template <typename VISITOR>
78 constexpr auto visit(VISITOR &&visitor) const {
79 return Fortran::common::visit(
80 common::visitors{[&visitor](auto ref) { return visitor(ref.get()); }},
81 u);
82 }
83
84private:
85 std::variant<Ref<A>...> u;
86};
87template <typename... A>
88using ReferenceVariant = ReferenceVariantBase<true, A...>;
89template <typename... A>
91
96
98
99using ActionStmts = std::tuple<
100 parser::AllocateStmt, parser::AssignmentStmt, parser::BackspaceStmt,
101 parser::CallStmt, parser::CloseStmt, parser::ContinueStmt,
102 parser::CycleStmt, parser::DeallocateStmt, parser::EndfileStmt,
104 parser::FailImageStmt, parser::FlushStmt, parser::FormTeamStmt,
106 parser::NotifyWaitStmt, parser::NullifyStmt, parser::OpenStmt,
108 parser::ReturnStmt, parser::RewindStmt, parser::StopStmt,
109 parser::SyncAllStmt, parser::SyncImagesStmt, parser::SyncMemoryStmt,
110 parser::SyncTeamStmt, parser::UnlockStmt, parser::WaitStmt,
113 parser::AssignedGotoStmt, parser::PauseStmt>;
114
115using OtherStmts = std::tuple<parser::EntryStmt, parser::FormatStmt>;
116
117using ConstructStmts = std::tuple<
118 parser::AssociateStmt, parser::EndAssociateStmt, parser::BlockStmt,
119 parser::EndBlockStmt, parser::SelectCaseStmt, parser::CaseStmt,
121 parser::CriticalStmt, parser::EndCriticalStmt, parser::NonLabelDoStmt,
122 parser::EndDoStmt, parser::IfThenStmt, parser::ElseIfStmt, parser::ElseStmt,
125 parser::MaskedElsewhereStmt, parser::ElsewhereStmt, parser::EndWhereStmt,
126 parser::ForallConstructStmt, parser::EndForallStmt>;
127
128using EndStmts =
129 std::tuple<parser::EndProgramStmt, parser::EndFunctionStmt,
130 parser::EndSubroutineStmt, parser::EndMpSubprogramStmt>;
131
132using Constructs =
139
140using Directives =
146
147using DeclConstructs = std::tuple<parser::OpenMPDeclarativeConstruct,
149
150template <typename A>
151static constexpr bool isActionStmt{common::HasMember<A, ActionStmts>};
152
153template <typename A>
154static constexpr bool isOtherStmt{common::HasMember<A, OtherStmts>};
155
156template <typename A>
157static constexpr bool isConstructStmt{common::HasMember<A, ConstructStmts>};
158
159template <typename A>
160static constexpr bool isEndStmt{common::HasMember<A, EndStmts>};
161
162template <typename A>
163static constexpr bool isConstruct{common::HasMember<A, Constructs>};
164
165template <typename A>
166static constexpr bool isDirective{common::HasMember<A, Directives>};
167
168template <typename A>
169static constexpr bool isDeclConstruct{common::HasMember<A, DeclConstructs>};
170
171template <typename A>
172static constexpr bool isIntermediateConstructStmt{common::HasMember<
173 A, std::tuple<parser::CaseStmt, parser::ElseIfStmt, parser::ElseStmt,
174 parser::SelectRankCaseStmt, parser::TypeGuardStmt>>};
175
176template <typename A>
177static constexpr bool isNopConstructStmt{common::HasMember<
178 A, std::tuple<parser::CaseStmt, parser::ElseIfStmt, parser::ElseStmt,
179 parser::EndIfStmt, parser::SelectRankCaseStmt,
180 parser::TypeGuardStmt>>};
181
182template <typename A>
183static constexpr bool isExecutableDirective{common::HasMember<
184 A, std::tuple<parser::CompilerDirective, parser::OpenACCConstruct,
185 parser::OpenMPConstruct, parser::CUFKernelDoConstruct>>};
186
187template <typename A>
188static constexpr bool isFunctionLike{common::HasMember<
189 A, std::tuple<parser::MainProgram, parser::FunctionSubprogram,
190 parser::SubroutineSubprogram,
191 parser::SeparateModuleSubprogram>>};
192
193template <typename A>
195template <typename... A>
196struct MakeReferenceVariantHelper<std::variant<A...>> {
197 using type = ReferenceVariant<A...>;
198};
199template <typename... A>
200struct MakeReferenceVariantHelper<std::tuple<A...>> {
201 using type = ReferenceVariant<A...>;
202};
203template <typename A>
204using MakeReferenceVariant = typename MakeReferenceVariantHelper<A>::type;
205
206using EvaluationTuple =
207 common::CombineTuples<ActionStmts, OtherStmts, ConstructStmts, EndStmts,
208 Constructs, Directives>;
212using EvaluationVariant = MakeReferenceVariant<EvaluationTuple>;
213
216struct Evaluation : EvaluationVariant {
217
219 template <typename A>
220 Evaluation(const A &a, const PftNode &parent,
221 const parser::CharBlock &position,
222 const std::optional<parser::Label> &label)
223 : EvaluationVariant{a}, parent{parent}, position{position}, label{label} {
224 }
225
227 template <typename A>
228 Evaluation(const A &a, const PftNode &parent)
229 : EvaluationVariant{a}, parent{parent} {
230 static_assert(pft::isConstruct<A> || pft::isDirective<A>,
231 "must be a construct or directive");
232 }
233
235 constexpr bool isActionStmt() const {
236 return visit(common::visitors{
237 [](auto &r) { return pft::isActionStmt<std::decay_t<decltype(r)>>; }});
238 }
239 constexpr bool isOtherStmt() const {
240 return visit(common::visitors{
241 [](auto &r) { return pft::isOtherStmt<std::decay_t<decltype(r)>>; }});
242 }
243 constexpr bool isConstructStmt() const {
244 return visit(common::visitors{[](auto &r) {
245 return pft::isConstructStmt<std::decay_t<decltype(r)>>;
246 }});
247 }
248 constexpr bool isEndStmt() const {
249 return visit(common::visitors{
250 [](auto &r) { return pft::isEndStmt<std::decay_t<decltype(r)>>; }});
251 }
252 constexpr bool isConstruct() const {
253 return visit(common::visitors{
254 [](auto &r) { return pft::isConstruct<std::decay_t<decltype(r)>>; }});
255 }
256 constexpr bool isDirective() const {
257 return visit(common::visitors{
258 [](auto &r) { return pft::isDirective<std::decay_t<decltype(r)>>; }});
259 }
260 constexpr bool isNopConstructStmt() const {
261 return visit(common::visitors{[](auto &r) {
262 return pft::isNopConstructStmt<std::decay_t<decltype(r)>>;
263 }});
264 }
265 constexpr bool isExecutableDirective() const {
266 return visit(common::visitors{[](auto &r) {
267 return pft::isExecutableDirective<std::decay_t<decltype(r)>>;
268 }});
269 }
270
273 constexpr bool isIntermediateConstructStmt() const {
274 return visit(common::visitors{[](auto &r) {
275 return pft::isIntermediateConstructStmt<std::decay_t<decltype(r)>>;
276 }});
277 }
278
279 LLVM_DUMP_METHOD void dump() const;
280
284 Evaluation *successor = lexicalSuccessor;
285 if (successor && successor->isNopConstructStmt())
286 successor = successor->parentConstruct->constructExit;
287 assert(successor && "missing successor");
288 return *successor;
289 }
290
292 bool hasNestedEvaluations() const {
293 return evaluationList && !evaluationList->empty();
294 }
295
297 EvaluationList &getNestedEvaluations() {
298 assert(evaluationList && "no nested evaluations");
299 return *evaluationList;
300 }
301
302 Evaluation &getFirstNestedEvaluation() {
303 assert(hasNestedEvaluations() && "no nested evaluations");
304 return evaluationList->front();
305 }
306
307 Evaluation &getLastNestedEvaluation() {
308 assert(hasNestedEvaluations() && "no nested evaluations");
309 return evaluationList->back();
310 }
311
313 FunctionLikeUnit *getOwningProcedure() const;
314
315 bool lowerAsStructured() const;
316 bool lowerAsUnstructured() const;
317 bool forceAsUnstructured() const;
318
319 // FIR generation looks primarily at PFT ActionStmt and ConstructStmt leaf
320 // nodes. Members such as lexicalSuccessor and block are applicable only
321 // to these nodes, plus some directives. The controlSuccessor member is
322 // used for nonlexical successors, such as linking to a GOTO target. For
323 // multiway branches, it is set to the first target. Successor and exit
324 // links always target statements or directives. An internal Construct
325 // node has a constructExit link that applies to exits from anywhere within
326 // the construct.
327 //
328 // An unstructured construct is one that contains some form of goto. This
329 // is indicated by the isUnstructured member flag, which may be set on a
330 // statement and propagated to enclosing constructs. This distinction allows
331 // a structured IF or DO statement to be materialized with custom structured
332 // FIR operations. An unstructured statement is materialized as mlir
333 // operation sequences that include explicit branches.
334 //
335 // The block member is set for statements that begin a new block. This
336 // block is the target of any branch to the statement. Statements may have
337 // additional (unstructured) "local" blocks, but such blocks cannot be the
338 // target of any explicit branch. The primary example of an (unstructured)
339 // statement that may have multiple associated blocks is NonLabelDoStmt,
340 // which may have a loop preheader block for loop initialization code (the
341 // block member), and always has a "local" header block that is the target
342 // of the loop back edge. If the NonLabelDoStmt is a concurrent loop, it
343 // may be associated with an arbitrary number of nested preheader, header,
344 // and mask blocks.
345 //
346 // The printIndex member is only set for statements. It is used for dumps
347 // (and debugging) and does not affect FIR generation.
348
349 PftNode parent;
350 parser::CharBlock position{};
351 std::optional<parser::Label> label{};
352 std::unique_ptr<EvaluationList> evaluationList; // nested evaluations
353 // associated compiler directives
355 Evaluation *parentConstruct{nullptr}; // set for nodes below the top level
356 Evaluation *lexicalSuccessor{nullptr}; // set for leaf nodes, some directives
357 Evaluation *controlSuccessor{nullptr}; // set for some leaf nodes
358 Evaluation *constructExit{nullptr}; // set for constructs
359 bool isNewBlock{false}; // evaluation begins a new basic block
360 bool isUnstructured{false}; // evaluation has unstructured control flow
361 bool negateCondition{false}; // If[Then]Stmt condition must be negated
362 bool activeConstruct{false}; // temporarily set for some constructs
363 mlir::Block *block{nullptr}; // isNewBlock block (ActionStmt, ConstructStmt)
364 int printIndex{0}; // (ActionStmt, ConstructStmt) evaluation index for dumps
365};
366
367using ProgramVariant =
368 ReferenceVariant<parser::MainProgram, parser::FunctionSubprogram,
369 parser::SubroutineSubprogram, parser::Module,
370 parser::Submodule, parser::SeparateModuleSubprogram,
371 parser::BlockData, parser::CompilerDirective,
372 parser::OpenACCRoutineConstruct>;
376 template <typename A>
377 ProgramUnit(const A &p, const PftNode &parent)
378 : ProgramVariant{p}, parent{parent} {}
379 ProgramUnit(ProgramUnit &&) = default;
380 ProgramUnit(const ProgramUnit &) = delete;
381
382 PftNode parent;
383};
384
400struct Variable {
404 struct Nominal {
405 Nominal(const semantics::Symbol *symbol, int depth, bool global)
406 : symbol{symbol}, depth{depth}, global{global} {}
407 const semantics::Symbol *symbol{};
408
409 bool isGlobal() const { return global; }
410
411 int depth{};
412 bool global{};
413 bool heapAlloc{}; // variable needs deallocation on exit
414 bool pointer{};
415 bool target{};
416 bool aliaser{}; // participates in EQUIVALENCE union
417 std::size_t aliasOffset{};
418 };
419
421 using Interval = std::tuple<std::size_t, std::size_t>;
422
428 const Fortran::semantics::Symbol &namingSym,
429 bool isGlobal = false)
430 : interval{std::move(interval)}, namingSymbol{&namingSym},
431 isGlobalAggregate{isGlobal} {}
432 AggregateStore(const semantics::Symbol &initialValueSym,
433 const semantics::Symbol &namingSym, bool isGlobal = false)
434 : interval{initialValueSym.offset(), initialValueSym.size()},
435 namingSymbol{&namingSym}, initialValueSymbol{&initialValueSym},
436 isGlobalAggregate{isGlobal} {};
437
438 bool isGlobal() const { return isGlobalAggregate; }
440 std::size_t getOffset() const { return std::get<0>(interval); }
443 return initialValueSymbol;
444 }
449 return getNamingSymbol().owner();
450 }
459 };
460
461 explicit Variable(const Fortran::semantics::Symbol &sym, bool global = false,
462 int depth = 0)
463 : var{Nominal(&sym, depth, global)} {}
464 explicit Variable(AggregateStore &&istore) : var{std::move(istore)} {}
465
468 assert(hasSymbol() && "variable is not nominal");
469 return *std::get<Nominal>(var).symbol;
470 }
471
473 bool isRuntimeTypeInfoData() const;
474
477 assert(isAggregateStore());
478 return std::get<AggregateStore>(var);
479 }
480
482 const Interval &getInterval() const {
483 assert(isAggregateStore());
484 return std::get<AggregateStore>(var).interval;
485 }
486
488 bool hasSymbol() const { return std::holds_alternative<Nominal>(var); }
489
491 bool isAggregateStore() const {
492 return std::holds_alternative<AggregateStore>(var);
493 }
494
496 bool isGlobal() const {
497 return Fortran::common::visit([](const auto &x) { return x.isGlobal(); },
498 var);
499 }
500
503 const semantics::Scope *scope = getOwningScope();
504 return scope && scope->kind() == Fortran::semantics::Scope::Kind::Module;
505 }
506
507 const Fortran::semantics::Scope *getOwningScope() const {
508 return Fortran::common::visit(
510 [](const Nominal &x) { return &x.symbol->GetUltimate().owner(); },
511 [](const AggregateStore &agg) { return &agg.getOwningScope(); }},
512 var);
513 }
514
515 bool isHeapAlloc() const {
516 if (auto *s = std::get_if<Nominal>(&var))
517 return s->heapAlloc;
518 return false;
519 }
520 bool isPointer() const {
521 if (auto *s = std::get_if<Nominal>(&var))
522 return s->pointer;
523 return false;
524 }
525 bool isTarget() const {
526 if (auto *s = std::get_if<Nominal>(&var))
527 return s->target;
528 return false;
529 }
530
533 bool isAlias() const {
534 if (auto *s = std::get_if<Nominal>(&var))
535 return s->aliaser;
536 return false;
537 }
538 std::size_t getAliasOffset() const {
539 if (auto *s = std::get_if<Nominal>(&var))
540 return s->aliasOffset;
541 return 0;
542 }
543 void setAlias(std::size_t offset) {
544 if (auto *s = std::get_if<Nominal>(&var)) {
545 s->aliaser = true;
546 s->aliasOffset = offset;
547 } else {
548 llvm_unreachable("not a nominal var");
549 }
550 }
551
552 void setHeapAlloc(bool to = true) {
553 if (auto *s = std::get_if<Nominal>(&var))
554 s->heapAlloc = to;
555 else
556 llvm_unreachable("not a nominal var");
557 }
558 void setPointer(bool to = true) {
559 if (auto *s = std::get_if<Nominal>(&var))
560 s->pointer = to;
561 else
562 llvm_unreachable("not a nominal var");
563 }
564 void setTarget(bool to = true) {
565 if (auto *s = std::get_if<Nominal>(&var))
566 s->target = to;
567 else
568 llvm_unreachable("not a nominal var");
569 }
570
572 int getDepth() const {
573 if (auto *s = std::get_if<Nominal>(&var))
574 return s->depth;
575 return 0;
576 }
577
578 LLVM_DUMP_METHOD void dump() const;
579
580private:
581 std::variant<Nominal, AggregateStore> var;
582};
583
584using VariableList = std::vector<Variable>;
585using ScopeVariableListMap =
586 std::map<const Fortran::semantics::Scope *, VariableList>;
587
590const VariableList &getScopeVariableList(const Fortran::semantics::Scope &scope,
591 ScopeVariableListMap &map);
592
595VariableList getScopeVariableList(const Fortran::semantics::Scope &scope);
596
599VariableList getDependentVariableList(const Fortran::semantics::Symbol &);
600
601void dump(VariableList &, std::string s = {}); // `s` is an optional dump label
602
606 // wrapper statements for function-like syntactic structures
607 using FunctionStatement =
616
618 const parser::MainProgram &f, const PftNode &parent,
619 const Fortran::semantics::SemanticsContext &semanticsContext);
621 const parser::FunctionSubprogram &f, const PftNode &parent,
622 const Fortran::semantics::SemanticsContext &semanticsContext);
624 const parser::SubroutineSubprogram &f, const PftNode &parent,
625 const Fortran::semantics::SemanticsContext &semanticsContext);
627 const parser::SeparateModuleSubprogram &f, const PftNode &parent,
628 const Fortran::semantics::SemanticsContext &semanticsContext);
630 FunctionLikeUnit(const FunctionLikeUnit &) = delete;
631
632 bool isMainProgram() const {
633 return endStmt.isA<parser::Statement<parser::EndProgramStmt>>();
634 }
635
638
639 void setActiveEntry(int entryIndex) {
640 assert(entryIndex >= 0 && entryIndex < (int)entryPointList.size() &&
641 "invalid entry point index");
642 activeEntry = entryIndex;
643 }
644
649 const semantics::Symbol *symbol = entryPointList[activeEntry].first;
650 if (!symbol)
651 llvm::report_fatal_error(
652 "not inside a procedure; do not call on main program.");
653 return *symbol;
654 }
655
659 if (!isMainProgram()) {
660 llvm::report_fatal_error("call only on main program.");
661 }
662 return entryPointList[activeEntry].first;
663 }
664
668 return entryPointList[activeEntry].second;
669 }
670
671 //===--------------------------------------------------------------------===//
672 // Host associations
673 //===--------------------------------------------------------------------===//
674
675 void setHostAssociatedSymbols(
676 const llvm::SetVector<const semantics::Symbol *> &symbols) {
677 hostAssociations.addSymbolsToBind(symbols, getScope());
678 }
679
683
688
691 bool parentHasHostAssoc();
692
695 HostAssociations &getHostAssoc() { return hostAssociations; }
696 const HostAssociations &getHostAssoc() const { return hostAssociations; };
697
698 LLVM_DUMP_METHOD void dump() const;
699
701 const Fortran::semantics::Scope &getScope() const { return *scope; }
702
704 std::optional<FunctionStatement> beginStmt;
705 FunctionStatement endStmt;
706 const semantics::Scope *scope;
707 LabelEvalMap labelEvaluationMap;
708 SymbolLabelMap assignSymbolLabelMap;
709 ContainedUnitList containedUnitList;
710 EvaluationList evaluationList;
717 entryPointList{std::pair{nullptr, nullptr}};
719 int activeEntry = 0;
723 bool hasIeeeAccess{false};
724 bool mayModifyHaltingMode{false};
725 bool mayModifyRoundingMode{false};
726 bool mayModifyUnderflowMode{false};
728 mlir::Block *finalBlock{};
729 HostAssociations hostAssociations;
730};
731
734 // wrapper statements for module-like syntactic structures
735 using ModuleStatement =
740
741 ModuleLikeUnit(const parser::Module &m, const PftNode &parent);
742 ModuleLikeUnit(const parser::Submodule &m, const PftNode &parent);
743 ~ModuleLikeUnit() = default;
744 ModuleLikeUnit(ModuleLikeUnit &&) = default;
745 ModuleLikeUnit(const ModuleLikeUnit &) = delete;
746
747 LLVM_DUMP_METHOD void dump() const;
748
751
753 const Fortran::semantics::Scope &getScope() const;
754
755 ModuleStatement beginStmt;
756 ModuleStatement endStmt;
757 ContainedUnitList containedUnitList;
758 EvaluationList evaluationList;
759};
760
763struct BlockDataUnit : public ProgramUnit {
764 BlockDataUnit(const parser::BlockData &bd, const PftNode &parent,
765 const Fortran::semantics::SemanticsContext &semanticsContext);
766 BlockDataUnit(BlockDataUnit &&) = default;
767 BlockDataUnit(const BlockDataUnit &) = delete;
768
769 LLVM_DUMP_METHOD void dump() const;
770
771 const Fortran::semantics::Scope &symTab; // symbol table
772};
773
774// Top level compiler directives
777 const PftNode &parent)
778 : ProgramUnit{directive, parent} {};
781};
782
783// Top level OpenACC routine directives
786 const PftNode &parent)
787 : ProgramUnit{directive, parent}, routine{directive} {};
790 const parser::OpenACCRoutineConstruct &routine;
791};
792
794struct Program {
795 using Units = std::variant<FunctionLikeUnit, ModuleLikeUnit, BlockDataUnit,
797
798 Program(semantics::CommonBlockList &&commonBlocks)
799 : commonBlocks{std::move(commonBlocks)} {}
800 Program(Program &&) = default;
801 Program(const Program &) = delete;
802
803 const std::list<Units> &getUnits() const { return units; }
804 std::list<Units> &getUnits() { return units; }
805 const semantics::CommonBlockList &getCommonBlocks() const {
806 return commonBlocks;
807 }
808 ScopeVariableListMap &getScopeVariableListMap() {
809 return scopeVariableListMap;
810 }
811
813 LLVM_DUMP_METHOD void dump() const;
814
815private:
816 std::list<Units> units;
817 semantics::CommonBlockList commonBlocks;
818 ScopeVariableListMap scopeVariableListMap; // module and submodule scopes
819};
820
823template <typename T>
824static parser::CharBlock stmtSourceLoc(const T &stmt) {
825 return stmt.visit(common::visitors{[](const auto &x) { return x.source; }});
826}
827
829template <typename ParentType, typename A>
830ParentType *getAncestor(A &node) {
831 if (auto *seekedParent = node.parent.template getIf<ParentType>())
832 return seekedParent;
833 return node.parent.visit(common::visitors{
834 [](Program &p) -> ParentType * { return nullptr; },
835 [](auto &p) -> ParentType * { return getAncestor<ParentType>(p); }});
836}
837
839template <typename A>
840ScopeVariableListMap &getScopeVariableListMap(A &node) {
841 Program *pftRoot = getAncestor<Program>(node);
842 assert(pftRoot && "pft must have a root");
843 return pftRoot->getScopeVariableListMap();
844}
845
848void visitAllSymbols(const FunctionLikeUnit &funit,
849 std::function<void(const semantics::Symbol &)> callBack);
850
853void visitAllSymbols(const Evaluation &eval,
854 std::function<void(const semantics::Symbol &)> callBack);
855
856} // namespace Fortran::lower::pft
857
858namespace Fortran::lower {
867std::unique_ptr<pft::Program>
868createPFT(const parser::Program &root,
869 const Fortran::semantics::SemanticsContext &semanticsContext);
870
872void dumpPFT(llvm::raw_ostream &outputStream, const pft::Program &pft);
873} // namespace Fortran::lower
874
875#endif // FORTRAN_LOWER_PFTBUILDER_H
Definition: reference.h:18
Definition: HostAssociations.h:30
void addSymbolsToBind(const llvm::SetVector< const Fortran::semantics::Symbol * > &symbols, const Fortran::semantics::Scope &hostScope)
Definition: HostAssociations.cpp:546
Definition: char-block.h:28
Definition: scope.h:58
Definition: semantics.h:67
Definition: symbol.h:712
Definition: OpenACC.h:20
Definition: AbstractConverter.h:59
void dumpPFT(llvm::raw_ostream &outputStream, const pft::Program &pft)
Dumper for displaying a PFT.
Definition: PFTBuilder.cpp:1891
std::unique_ptr< pft::Program > createPFT(const parser::Program &root, const Fortran::semantics::SemanticsContext &semanticsContext)
Definition: PFTBuilder.cpp:1884
Definition: idioms.h:61
Definition: PFTBuilder.h:763
LLVM_DUMP_METHOD void dump() const
The BlockDataUnit dump is just the associated symbol table.
Definition: PFTBuilder.cpp:1951
Definition: PFTBuilder.h:775
Definition: PFTBuilder.h:216
FunctionLikeUnit * getOwningProcedure() const
Return the FunctionLikeUnit containing this evaluation (or nullptr).
Definition: PFTBuilder.cpp:1449
Evaluation(const A &a, const PftNode &parent)
Construct and Directive ctor.
Definition: PFTBuilder.h:228
EvaluationList & getNestedEvaluations()
Return nested evaluation list.
Definition: PFTBuilder.h:297
Evaluation(const A &a, const PftNode &parent, const parser::CharBlock &position, const std::optional< parser::Label > &label)
General ctor.
Definition: PFTBuilder.h:220
Evaluation & nonNopSuccessor() const
Definition: PFTBuilder.h:283
constexpr bool isIntermediateConstructStmt() const
Definition: PFTBuilder.h:273
constexpr bool isActionStmt() const
Evaluation classification predicates.
Definition: PFTBuilder.h:235
bool hasNestedEvaluations() const
Return true if this Evaluation has at least one nested evaluation.
Definition: PFTBuilder.h:292
Definition: PFTBuilder.h:605
Evaluation * getEntryEval() const
Definition: PFTBuilder.h:667
llvm::SmallVector< std::pair< const semantics::Symbol *, Evaluation * >, 1 > entryPointList
Definition: PFTBuilder.h:717
HostAssociations & parentHostAssoc()
Definition: PFTBuilder.cpp:1798
bool parentHasHostAssoc()
Definition: PFTBuilder.cpp:1810
int activeEntry
Current index into entryPointList. Index 0 is the primary entry point.
Definition: PFTBuilder.h:719
mlir::Block * finalBlock
Terminal basic block (if any)
Definition: PFTBuilder.h:728
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this function like unit.
Definition: PFTBuilder.cpp:1817
HostAssociations & getHostAssoc()
Definition: PFTBuilder.h:695
const semantics::Symbol * primaryResult
Definition: PFTBuilder.h:722
std::optional< FunctionStatement > beginStmt
Anonymous programs do not have a begin statement.
Definition: PFTBuilder.h:704
const semantics::Symbol * getMainProgramSymbol() const
Definition: PFTBuilder.h:658
const Fortran::semantics::Scope & getScope() const
Get the function scope.
Definition: PFTBuilder.h:701
const semantics::Symbol & getSubprogramSymbol() const
Definition: PFTBuilder.h:648
bool parentHasTupleHostAssoc()
Definition: PFTBuilder.cpp:1804
Module-like units contain a list of function-like units.
Definition: PFTBuilder.h:733
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this module like unit.
Definition: PFTBuilder.cpp:1839
const Fortran::semantics::Scope & getScope() const
Get the module scope.
Definition: PFTBuilder.cpp:1843
Definition: PFTBuilder.h:784
Definition: PFTBuilder.h:375
A Program is the top-level root of the PFT.
Definition: PFTBuilder.h:794
LLVM_DUMP_METHOD void dump() const
LLVM dump method on a Program.
Definition: PFTBuilder.cpp:1896
std::size_t getOffset() const
Get offset of the aggregate inside its scope.
Definition: PFTBuilder.h:440
const semantics::Symbol & getNamingSymbol() const
Returns the symbol that gives its name to the aggregate.
Definition: PFTBuilder.h:446
const semantics::Symbol * namingSymbol
Symbol that gives its name to the aggregate. Always set by constructor.
Definition: PFTBuilder.h:454
const semantics::Symbol * initialValueSymbol
Compiler generated symbol with the aggregate initial value if any.
Definition: PFTBuilder.h:456
bool isGlobalAggregate
Is this a global aggregate?
Definition: PFTBuilder.h:458
Interval interval
<offset, size> of the aggregate in its scope.
Definition: PFTBuilder.h:452
const semantics::Symbol * getInitialValueSymbol() const
Returns symbols holding the aggregate initial value if any.
Definition: PFTBuilder.h:442
const semantics::Scope & getOwningScope() const
Scope to which the aggregates belongs to.
Definition: PFTBuilder.h:448
Definition: PFTBuilder.h:404
Definition: PFTBuilder.h:400
bool isAggregateStore() const
Is this an aggregate store?
Definition: PFTBuilder.h:491
bool isRuntimeTypeInfoData() const
Is this variable a compiler generated global to describe derived types?
Definition: PFTBuilder.cpp:1866
bool isGlobal() const
Is this variable a global?
Definition: PFTBuilder.h:496
bool isModuleOrSubmoduleVariable() const
Is this a module or submodule variable?
Definition: PFTBuilder.h:502
bool isAlias() const
Definition: PFTBuilder.h:533
std::tuple< std::size_t, std::size_t > Interval
<offset, size> pair
Definition: PFTBuilder.h:421
bool hasSymbol() const
Only nominal variable have front-end symbols.
Definition: PFTBuilder.h:488
const Interval & getInterval() const
Return the interval range of an aggregate store.
Definition: PFTBuilder.h:482
const Fortran::semantics::Symbol & getSymbol() const
Return the front-end symbol for a nominal variable.
Definition: PFTBuilder.h:467
int getDepth() const
The depth is recorded for nominal variables as a debugging aid.
Definition: PFTBuilder.h:572
const AggregateStore & getAggregateStore() const
Return the aggregate store.
Definition: PFTBuilder.h:476
Definition: parse-tree.h:1990
Definition: parse-tree.h:3435
Definition: parse-tree.h:3440
Definition: parse-tree.h:3445
Definition: parse-tree.h:2016
Definition: parse-tree.h:2173
Definition: parse-tree.h:2164
Definition: parse-tree.h:2195
Definition: parse-tree.h:3027
Definition: parse-tree.h:5071
Definition: parse-tree.h:3276
Definition: parse-tree.h:2437
Definition: parse-tree.h:2425
Definition: parse-tree.h:2226
Definition: parse-tree.h:2211
Definition: parse-tree.h:2695
Definition: parse-tree.h:3353
Definition: parse-tree.h:2524
Definition: parse-tree.h:2242
Definition: parse-tree.h:2233
Definition: parse-tree.h:2010
Definition: parse-tree.h:2338
Definition: parse-tree.h:2358
Definition: parse-tree.h:2220
Definition: parse-tree.h:2578
Definition: parse-tree.h:2592
Definition: parse-tree.h:2108
Definition: parse-tree.h:2143
Definition: parse-tree.h:2120
Definition: parse-tree.h:2604
Definition: parse-tree.h:3298
Definition: parse-tree.h:2372
Definition: parse-tree.h:2388
Definition: parse-tree.h:2351
Definition: parse-tree.h:2915
Definition: parse-tree.h:2618
Definition: parse-tree.h:2936
Definition: parse-tree.h:2075
Definition: parse-tree.h:2971
Definition: parse-tree.h:2321
Definition: parse-tree.h:2546
Definition: parse-tree.h:4723
Definition: parse-tree.h:5045
Definition: parse-tree.h:4909
Definition: parse-tree.h:4756
Definition: parse-tree.h:4494
Definition: parse-tree.h:2040
Definition: parse-tree.h:2791
Definition: parse-tree.h:2754
Definition: parse-tree.h:2395
Definition: parse-tree.h:2460
Definition: parse-tree.h:2472
Definition: parse-tree.h:2451
Definition: parse-tree.h:2506
Definition: parse-tree.h:2486
Definition: parse-tree.h:3324
Definition: parse-tree.h:355
Definition: parse-tree.h:2538
Definition: parse-tree.h:3013
Definition: parse-tree.h:3308
Definition: parse-tree.h:2556
Definition: parse-tree.h:2569
Definition: parse-tree.h:2495
Definition: parse-tree.h:2628
Definition: parse-tree.h:2059
Definition: parse-tree.h:2090
Definition: parse-tree.h:2053
Definition: parse-tree.h:2776