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
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>
48class ReferenceVariantBase {
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>
90using MutableReferenceVariant = ReferenceVariantBase<false, A...>;
91
94using PftNode = MutableReferenceVariant<Program, ModuleLikeUnit,
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 isOpenMPDirective{
189 common::HasMember<A, std::tuple<parser::OpenMPConstruct,
190 parser::OpenMPDeclarativeConstruct>>};
191
192template <typename A>
193static constexpr bool isFunctionLike{common::HasMember<
194 A, std::tuple<parser::MainProgram, parser::FunctionSubprogram,
195 parser::SubroutineSubprogram,
196 parser::SeparateModuleSubprogram>>};
197
198template <typename A>
200template <typename... A>
201struct MakeReferenceVariantHelper<std::variant<A...>> {
202 using type = ReferenceVariant<A...>;
203};
204template <typename... A>
205struct MakeReferenceVariantHelper<std::tuple<A...>> {
206 using type = ReferenceVariant<A...>;
207};
208template <typename A>
209using MakeReferenceVariant = typename MakeReferenceVariantHelper<A>::type;
210
211using EvaluationTuple =
212 common::CombineTuples<ActionStmts, OtherStmts, ConstructStmts, EndStmts,
213 Constructs, Directives>;
217using EvaluationVariant = MakeReferenceVariant<EvaluationTuple>;
218
221struct Evaluation : EvaluationVariant {
222
224 template <typename A>
225 Evaluation(const A &a, const PftNode &parent,
226 const parser::CharBlock &position,
227 const std::optional<parser::Label> &label)
228 : EvaluationVariant{a}, parent{parent}, position{position}, label{label} {
229 }
230
232 template <typename A>
233 Evaluation(const A &a, const PftNode &parent)
234 : EvaluationVariant{a}, parent{parent} {
235 static_assert(pft::isConstruct<A> || pft::isDirective<A>,
236 "must be a construct or directive");
237 }
238
240 constexpr bool isActionStmt() const {
241 return visit(common::visitors{
242 [](auto &r) { return pft::isActionStmt<std::decay_t<decltype(r)>>; }});
243 }
244 constexpr bool isOtherStmt() const {
245 return visit(common::visitors{
246 [](auto &r) { return pft::isOtherStmt<std::decay_t<decltype(r)>>; }});
247 }
248 constexpr bool isConstructStmt() const {
249 return visit(common::visitors{[](auto &r) {
250 return pft::isConstructStmt<std::decay_t<decltype(r)>>;
251 }});
252 }
253 constexpr bool isEndStmt() const {
254 return visit(common::visitors{
255 [](auto &r) { return pft::isEndStmt<std::decay_t<decltype(r)>>; }});
256 }
257 constexpr bool isConstruct() const {
258 return visit(common::visitors{
259 [](auto &r) { return pft::isConstruct<std::decay_t<decltype(r)>>; }});
260 }
261 constexpr bool isDirective() const {
262 return visit(common::visitors{
263 [](auto &r) { return pft::isDirective<std::decay_t<decltype(r)>>; }});
264 }
265 constexpr bool isNopConstructStmt() const {
266 return visit(common::visitors{[](auto &r) {
267 return pft::isNopConstructStmt<std::decay_t<decltype(r)>>;
268 }});
269 }
270 constexpr bool isExecutableDirective() const {
271 return visit(common::visitors{[](auto &r) {
272 return pft::isExecutableDirective<std::decay_t<decltype(r)>>;
273 }});
274 }
275 constexpr bool isOpenMPDirective() const {
276 return visit(common::visitors{[](auto &r) {
277 return pft::isOpenMPDirective<std::decay_t<decltype(r)>>;
278 }});
279 }
280
283 constexpr bool isIntermediateConstructStmt() const {
284 return visit(common::visitors{[](auto &r) {
285 return pft::isIntermediateConstructStmt<std::decay_t<decltype(r)>>;
286 }});
287 }
288
289 LLVM_DUMP_METHOD void dump() const;
290
294 Evaluation *successor = lexicalSuccessor;
295 if (successor && successor->isNopConstructStmt())
296 successor = successor->parentConstruct->constructExit;
297 assert(successor && "missing successor");
298 return *successor;
299 }
300
302 bool hasNestedEvaluations() const {
303 return evaluationList && !evaluationList->empty();
304 }
305
307 EvaluationList &getNestedEvaluations() {
308 assert(evaluationList && "no nested evaluations");
309 return *evaluationList;
310 }
311
312 Evaluation &getFirstNestedEvaluation() {
313 assert(hasNestedEvaluations() && "no nested evaluations");
314 return evaluationList->front();
315 }
316
317 Evaluation &getLastNestedEvaluation() {
318 assert(hasNestedEvaluations() && "no nested evaluations");
319 return evaluationList->back();
320 }
321
323 FunctionLikeUnit *getOwningProcedure() const;
324
325 bool lowerAsStructured() const;
326 bool lowerAsUnstructured() const;
327 bool forceAsUnstructured() const;
328
329 // FIR generation looks primarily at PFT ActionStmt and ConstructStmt leaf
330 // nodes. Members such as lexicalSuccessor and block are applicable only
331 // to these nodes, plus some directives. The controlSuccessor member is
332 // used for nonlexical successors, such as linking to a GOTO target. For
333 // multiway branches, it is set to the first target. Successor and exit
334 // links always target statements or directives. An internal Construct
335 // node has a constructExit link that applies to exits from anywhere within
336 // the construct.
337 //
338 // An unstructured construct is one that contains some form of goto. This
339 // is indicated by the isUnstructured member flag, which may be set on a
340 // statement and propagated to enclosing constructs. This distinction allows
341 // a structured IF or DO statement to be materialized with custom structured
342 // FIR operations. An unstructured statement is materialized as mlir
343 // operation sequences that include explicit branches.
344 //
345 // The block member is set for statements that begin a new block. This
346 // block is the target of any branch to the statement. Statements may have
347 // additional (unstructured) "local" blocks, but such blocks cannot be the
348 // target of any explicit branch. The primary example of an (unstructured)
349 // statement that may have multiple associated blocks is NonLabelDoStmt,
350 // which may have a loop preheader block for loop initialization code (the
351 // block member), and always has a "local" header block that is the target
352 // of the loop back edge. If the NonLabelDoStmt is a concurrent loop, it
353 // may be associated with an arbitrary number of nested preheader, header,
354 // and mask blocks.
355 //
356 // The printIndex member is only set for statements. It is used for dumps
357 // (and debugging) and does not affect FIR generation.
358
359 PftNode parent;
360 parser::CharBlock position{};
361 std::optional<parser::Label> label{};
362 std::unique_ptr<EvaluationList> evaluationList; // nested evaluations
363 // associated compiler directives
364 llvm::SmallVector<const parser::CompilerDirective *, 1> dirs;
365 Evaluation *parentConstruct{nullptr}; // set for nodes below the top level
366 Evaluation *lexicalSuccessor{nullptr}; // set for leaf nodes, some directives
367 Evaluation *controlSuccessor{nullptr}; // set for some leaf nodes
368 Evaluation *constructExit{nullptr}; // set for constructs
369 bool isNewBlock{false}; // evaluation begins a new basic block
370 bool isUnstructured{false}; // evaluation has unstructured control flow
371 bool negateCondition{false}; // If[Then]Stmt condition must be negated
372 bool activeConstruct{false}; // temporarily set for some constructs
373 mlir::Block *block{nullptr}; // isNewBlock block (ActionStmt, ConstructStmt)
374 int printIndex{0}; // (ActionStmt, ConstructStmt) evaluation index for dumps
375};
376
377using ProgramVariant =
378 ReferenceVariant<parser::MainProgram, parser::FunctionSubprogram,
379 parser::SubroutineSubprogram, parser::Module,
380 parser::Submodule, parser::SeparateModuleSubprogram,
381 parser::BlockData, parser::CompilerDirective,
382 parser::OpenACCRoutineConstruct>;
385struct ProgramUnit : ProgramVariant {
386 template <typename A>
387 ProgramUnit(const A &p, const PftNode &parent)
388 : ProgramVariant{p}, parent{parent} {}
389 ProgramUnit(ProgramUnit &&) = default;
390 ProgramUnit(const ProgramUnit &) = delete;
391
392 PftNode parent;
393};
394
410struct Variable {
414 struct Nominal {
415 Nominal(const semantics::Symbol *symbol, int depth, bool global)
416 : symbol{symbol}, depth{depth}, global{global} {}
417 const semantics::Symbol *symbol{};
418
419 bool isGlobal() const { return global; }
420
421 int depth{};
422 bool global{};
423 bool heapAlloc{}; // variable needs deallocation on exit
424 bool pointer{};
425 bool target{};
426 bool aliaser{}; // participates in EQUIVALENCE union
427 std::size_t aliasOffset{};
428 };
429
431 using Interval = std::tuple<std::size_t, std::size_t>;
432
436 struct AggregateStore {
437 AggregateStore(Interval &&interval,
438 const Fortran::semantics::Symbol &namingSym,
439 bool isGlobal = false)
440 : interval{std::move(interval)}, namingSymbol{&namingSym},
441 isGlobalAggregate{isGlobal} {}
442 AggregateStore(const semantics::Symbol &initialValueSym,
443 const semantics::Symbol &namingSym, bool isGlobal = false)
444 : interval{initialValueSym.offset(), initialValueSym.size()},
445 namingSymbol{&namingSym}, initialValueSymbol{&initialValueSym},
446 isGlobalAggregate{isGlobal} {};
447
448 bool isGlobal() const { return isGlobalAggregate; }
450 std::size_t getOffset() const { return std::get<0>(interval); }
455
459 return getNamingSymbol().owner();
460 }
461
469 };
470
471 explicit Variable(const Fortran::semantics::Symbol &sym, bool global = false,
472 int depth = 0)
473 : var{Nominal(&sym, depth, global)} {}
474 explicit Variable(AggregateStore &&istore) : var{std::move(istore)} {}
475
478 assert(hasSymbol() && "variable is not nominal");
479 return *std::get<Nominal>(var).symbol;
480 }
481
483 bool isRuntimeTypeInfoData() const;
484
487 assert(isAggregateStore());
488 return std::get<AggregateStore>(var);
489 }
490
492 const Interval &getInterval() const {
493 assert(isAggregateStore());
494 return std::get<AggregateStore>(var).interval;
495 }
496
498 bool hasSymbol() const { return std::holds_alternative<Nominal>(var); }
499
501 bool isAggregateStore() const {
502 return std::holds_alternative<AggregateStore>(var);
503 }
504
506 bool isGlobal() const {
507 return Fortran::common::visit([](const auto &x) { return x.isGlobal(); },
508 var);
509 }
510
513 const semantics::Scope *scope = getOwningScope();
514 return scope && scope->kind() == Fortran::semantics::Scope::Kind::Module;
515 }
516
517 const Fortran::semantics::Scope *getOwningScope() const {
518 return Fortran::common::visit(
520 [](const Nominal &x) { return &x.symbol->GetUltimate().owner(); },
521 [](const AggregateStore &agg) { return &agg.getOwningScope(); }},
522 var);
523 }
524
525 bool isHeapAlloc() const {
526 if (auto *s = std::get_if<Nominal>(&var))
527 return s->heapAlloc;
528 return false;
529 }
530 bool isPointer() const {
531 if (auto *s = std::get_if<Nominal>(&var))
532 return s->pointer;
533 return false;
534 }
535 bool isTarget() const {
536 if (auto *s = std::get_if<Nominal>(&var))
537 return s->target;
538 return false;
539 }
540
543 bool isAlias() const {
544 if (auto *s = std::get_if<Nominal>(&var))
545 return s->aliaser;
546 return false;
547 }
548 std::size_t getAliasOffset() const {
549 if (auto *s = std::get_if<Nominal>(&var))
550 return s->aliasOffset;
551 return 0;
552 }
553 void setAlias(std::size_t offset) {
554 if (auto *s = std::get_if<Nominal>(&var)) {
555 s->aliaser = true;
556 s->aliasOffset = offset;
557 } else {
558 llvm_unreachable("not a nominal var");
559 }
560 }
561
562 void setHeapAlloc(bool to = true) {
563 if (auto *s = std::get_if<Nominal>(&var))
564 s->heapAlloc = to;
565 else
566 llvm_unreachable("not a nominal var");
567 }
568 void setPointer(bool to = true) {
569 if (auto *s = std::get_if<Nominal>(&var))
570 s->pointer = to;
571 else
572 llvm_unreachable("not a nominal var");
573 }
574 void setTarget(bool to = true) {
575 if (auto *s = std::get_if<Nominal>(&var))
576 s->target = to;
577 else
578 llvm_unreachable("not a nominal var");
579 }
580
582 int getDepth() const {
583 if (auto *s = std::get_if<Nominal>(&var))
584 return s->depth;
585 return 0;
586 }
587
588 LLVM_DUMP_METHOD void dump() const;
589
590private:
591 std::variant<Nominal, AggregateStore> var;
592};
593
594using VariableList = std::vector<Variable>;
595using ScopeVariableListMap =
596 std::map<const Fortran::semantics::Scope *, VariableList>;
597
600const VariableList &getScopeVariableList(const Fortran::semantics::Scope &scope,
601 ScopeVariableListMap &map);
602
605VariableList getScopeVariableList(const Fortran::semantics::Scope &scope);
606
609VariableList getDependentVariableList(const Fortran::semantics::Symbol &);
610
611void dump(VariableList &, std::string s = {}); // `s` is an optional dump label
612
615struct FunctionLikeUnit : public ProgramUnit {
616 // wrapper statements for function-like syntactic structures
617 using FunctionStatement =
618 ReferenceVariant<parser::Statement<parser::ProgramStmt>,
626
627 FunctionLikeUnit(
628 const parser::MainProgram &f, const PftNode &parent,
629 const Fortran::semantics::SemanticsContext &semanticsContext);
630 FunctionLikeUnit(
631 const parser::FunctionSubprogram &f, const PftNode &parent,
632 const Fortran::semantics::SemanticsContext &semanticsContext);
633 FunctionLikeUnit(
634 const parser::SubroutineSubprogram &f, const PftNode &parent,
635 const Fortran::semantics::SemanticsContext &semanticsContext);
636 FunctionLikeUnit(
637 const parser::SeparateModuleSubprogram &f, const PftNode &parent,
638 const Fortran::semantics::SemanticsContext &semanticsContext);
639 FunctionLikeUnit(FunctionLikeUnit &&) = default;
640 FunctionLikeUnit(const FunctionLikeUnit &) = delete;
641
642 bool isMainProgram() const {
643 return endStmt.isA<parser::Statement<parser::EndProgramStmt>>();
644 }
645
648
649 void setActiveEntry(int entryIndex) {
650 assert(entryIndex >= 0 && entryIndex < (int)entryPointList.size() &&
651 "invalid entry point index");
652 activeEntry = entryIndex;
653 }
654
659 const semantics::Symbol *symbol = entryPointList[activeEntry].first;
660 if (!symbol)
661 llvm::report_fatal_error(
662 "not inside a procedure; do not call on main program.");
663 return *symbol;
664 }
665
669 if (!isMainProgram()) {
670 llvm::report_fatal_error("call only on main program.");
671 }
672 return entryPointList[activeEntry].first;
673 }
674
678 return entryPointList[activeEntry].second;
679 }
680
681 //===--------------------------------------------------------------------===//
682 // Host associations
683 //===--------------------------------------------------------------------===//
684
685 void setHostAssociatedSymbols(
686 const llvm::SetVector<const semantics::Symbol *> &symbols) {
687 hostAssociations.addSymbolsToBind(symbols, getScope());
688 }
689
693
698
701 bool parentHasHostAssoc();
702
705 HostAssociations &getHostAssoc() { return hostAssociations; }
706 const HostAssociations &getHostAssoc() const { return hostAssociations; };
707
708 LLVM_DUMP_METHOD void dump() const;
709
711 const Fortran::semantics::Scope &getScope() const { return *scope; }
712
714 std::optional<FunctionStatement> beginStmt;
715 FunctionStatement endStmt;
716 const semantics::Scope *scope;
717 LabelEvalMap labelEvaluationMap;
718 SymbolLabelMap assignSymbolLabelMap;
719 ContainedUnitList containedUnitList;
720 EvaluationList evaluationList;
727 entryPointList{std::pair{nullptr, nullptr}};
729 int activeEntry = 0;
733 bool hasIeeeAccess{false};
734 bool mayModifyHaltingMode{false};
735 bool mayModifyRoundingMode{false};
736 bool mayModifyUnderflowMode{false};
738 mlir::Block *finalBlock{};
739 HostAssociations hostAssociations;
740};
741
743struct ModuleLikeUnit : public ProgramUnit {
744 // wrapper statements for module-like syntactic structures
745 using ModuleStatement =
746 ReferenceVariant<parser::Statement<parser::ModuleStmt>,
750
751 ModuleLikeUnit(const parser::Module &m, const PftNode &parent);
752 ModuleLikeUnit(const parser::Submodule &m, const PftNode &parent);
753 ~ModuleLikeUnit() = default;
754 ModuleLikeUnit(ModuleLikeUnit &&) = default;
755 ModuleLikeUnit(const ModuleLikeUnit &) = delete;
756
757 LLVM_DUMP_METHOD void dump() const;
758
761
763 const Fortran::semantics::Scope &getScope() const;
764
765 ModuleStatement beginStmt;
766 ModuleStatement endStmt;
767 ContainedUnitList containedUnitList;
768 EvaluationList evaluationList;
769};
770
773struct BlockDataUnit : public ProgramUnit {
774 BlockDataUnit(const parser::BlockData &bd, const PftNode &parent,
775 const Fortran::semantics::SemanticsContext &semanticsContext);
776 BlockDataUnit(BlockDataUnit &&) = default;
777 BlockDataUnit(const BlockDataUnit &) = delete;
778
779 LLVM_DUMP_METHOD void dump() const;
780
781 const Fortran::semantics::Scope &symTab; // symbol table
782};
783
784// Top level compiler directives
785struct CompilerDirectiveUnit : public ProgramUnit {
786 CompilerDirectiveUnit(const parser::CompilerDirective &directive,
787 const PftNode &parent)
788 : ProgramUnit{directive, parent} {};
789 CompilerDirectiveUnit(CompilerDirectiveUnit &&) = default;
790 CompilerDirectiveUnit(const CompilerDirectiveUnit &) = delete;
791};
792
793// Top level OpenACC routine directives
794struct OpenACCDirectiveUnit : public ProgramUnit {
795 OpenACCDirectiveUnit(const parser::OpenACCRoutineConstruct &directive,
796 const PftNode &parent)
797 : ProgramUnit{directive, parent}, routine{directive} {};
798 OpenACCDirectiveUnit(OpenACCDirectiveUnit &&) = default;
799 OpenACCDirectiveUnit(const OpenACCDirectiveUnit &) = delete;
800 const parser::OpenACCRoutineConstruct &routine;
801};
802
804struct Program {
805 using Units = std::variant<FunctionLikeUnit, ModuleLikeUnit, BlockDataUnit,
807
808 Program(semantics::CommonBlockList &&commonBlocks)
809 : commonBlocks{std::move(commonBlocks)} {}
810 Program(Program &&) = default;
811 Program(const Program &) = delete;
812
813 const std::list<Units> &getUnits() const { return units; }
814 std::list<Units> &getUnits() { return units; }
815 const semantics::CommonBlockList &getCommonBlocks() const {
816 return commonBlocks;
817 }
818 ScopeVariableListMap &getScopeVariableListMap() {
819 return scopeVariableListMap;
820 }
821
823 LLVM_DUMP_METHOD void dump() const;
824
825private:
826 std::list<Units> units;
827 semantics::CommonBlockList commonBlocks;
828 ScopeVariableListMap scopeVariableListMap; // module and submodule scopes
829};
830
833template <typename T>
834static parser::CharBlock stmtSourceLoc(const T &stmt) {
835 return stmt.visit(common::visitors{[](const auto &x) { return x.source; }});
836}
837
839template <typename ParentType, typename A>
840ParentType *getAncestor(A &node) {
841 if (auto *seekedParent = node.parent.template getIf<ParentType>())
842 return seekedParent;
843 return node.parent.visit(common::visitors{
844 [](Program &p) -> ParentType * { return nullptr; },
845 [](auto &p) -> ParentType * { return getAncestor<ParentType>(p); }});
846}
847
849template <typename A>
850ScopeVariableListMap &getScopeVariableListMap(A &node) {
851 Program *pftRoot = getAncestor<Program>(node);
852 assert(pftRoot && "pft must have a root");
853 return pftRoot->getScopeVariableListMap();
854}
855
858void visitAllSymbols(const FunctionLikeUnit &funit,
859 std::function<void(const semantics::Symbol &)> callBack);
860
863void visitAllSymbols(const Evaluation &eval,
864 std::function<void(const semantics::Symbol &)> callBack);
865
866} // namespace Fortran::lower::pft
867
868namespace Fortran::lower {
877std::unique_ptr<pft::Program>
878createPFT(const parser::Program &root,
879 const Fortran::semantics::SemanticsContext &semanticsContext);
880
882void dumpPFT(llvm::raw_ostream &outputStream, const pft::Program &pft);
883} // namespace Fortran::lower
884
885#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:778
Definition OpenACC.h:20
Definition ParserActions.h:24
void dumpPFT(llvm::raw_ostream &outputStream, const pft::Program &pft)
Dumper for displaying a PFT.
Definition PFTBuilder.cpp:1903
std::unique_ptr< pft::Program > createPFT(const parser::Program &root, const Fortran::semantics::SemanticsContext &semanticsContext)
Definition PFTBuilder.cpp:1896
Definition idioms.h:61
Definition PFTBuilder.h:773
LLVM_DUMP_METHOD void dump() const
The BlockDataUnit dump is just the associated symbol table.
Definition PFTBuilder.cpp:1963
Definition PFTBuilder.h:221
FunctionLikeUnit * getOwningProcedure() const
Return the FunctionLikeUnit containing this evaluation (or nullptr).
Definition PFTBuilder.cpp:1461
Evaluation(const A &a, const PftNode &parent)
Construct and Directive ctor.
Definition PFTBuilder.h:233
EvaluationList & getNestedEvaluations()
Return nested evaluation list.
Definition PFTBuilder.h:307
Evaluation(const A &a, const PftNode &parent, const parser::CharBlock &position, const std::optional< parser::Label > &label)
General ctor.
Definition PFTBuilder.h:225
Evaluation & nonNopSuccessor() const
Definition PFTBuilder.h:293
constexpr bool isIntermediateConstructStmt() const
Definition PFTBuilder.h:283
constexpr bool isActionStmt() const
Evaluation classification predicates.
Definition PFTBuilder.h:240
bool hasNestedEvaluations() const
Return true if this Evaluation has at least one nested evaluation.
Definition PFTBuilder.h:302
Definition PFTBuilder.h:615
Evaluation * getEntryEval() const
Definition PFTBuilder.h:677
llvm::SmallVector< std::pair< const semantics::Symbol *, Evaluation * >, 1 > entryPointList
Definition PFTBuilder.h:727
HostAssociations & parentHostAssoc()
Definition PFTBuilder.cpp:1810
bool parentHasHostAssoc()
Definition PFTBuilder.cpp:1822
int activeEntry
Current index into entryPointList. Index 0 is the primary entry point.
Definition PFTBuilder.h:729
mlir::Block * finalBlock
Terminal basic block (if any)
Definition PFTBuilder.h:738
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this function like unit.
Definition PFTBuilder.cpp:1829
HostAssociations & getHostAssoc()
Definition PFTBuilder.h:705
const semantics::Symbol * primaryResult
Definition PFTBuilder.h:732
std::optional< FunctionStatement > beginStmt
Anonymous programs do not have a begin statement.
Definition PFTBuilder.h:714
const semantics::Symbol * getMainProgramSymbol() const
Definition PFTBuilder.h:668
const Fortran::semantics::Scope & getScope() const
Get the function scope.
Definition PFTBuilder.h:711
const semantics::Symbol & getSubprogramSymbol() const
Definition PFTBuilder.h:658
bool parentHasTupleHostAssoc()
Definition PFTBuilder.cpp:1816
Module-like units contain a list of function-like units.
Definition PFTBuilder.h:743
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this module like unit.
Definition PFTBuilder.cpp:1851
const Fortran::semantics::Scope & getScope() const
Get the module scope.
Definition PFTBuilder.cpp:1855
A Program is the top-level root of the PFT.
Definition PFTBuilder.h:804
LLVM_DUMP_METHOD void dump() const
LLVM dump method on a Program.
Definition PFTBuilder.cpp:1908
std::size_t getOffset() const
Get offset of the aggregate inside its scope.
Definition PFTBuilder.h:450
const semantics::Symbol & getNamingSymbol() const
Returns the symbol that gives its name to the aggregate.
Definition PFTBuilder.h:456
const semantics::Symbol * namingSymbol
Symbol that gives its name to the aggregate. Always set by constructor.
Definition PFTBuilder.h:464
const semantics::Symbol * initialValueSymbol
Compiler generated symbol with the aggregate initial value if any.
Definition PFTBuilder.h:466
bool isGlobalAggregate
Is this a global aggregate?
Definition PFTBuilder.h:468
Interval interval
<offset, size> of the aggregate in its scope.
Definition PFTBuilder.h:462
const semantics::Symbol * getInitialValueSymbol() const
Returns symbols holding the aggregate initial value if any.
Definition PFTBuilder.h:452
const semantics::Scope & getOwningScope() const
Scope to which the aggregates belongs to.
Definition PFTBuilder.h:458
Definition PFTBuilder.h:414
Definition PFTBuilder.h:410
bool isAggregateStore() const
Is this an aggregate store?
Definition PFTBuilder.h:501
bool isRuntimeTypeInfoData() const
Is this variable a compiler generated global to describe derived types?
Definition PFTBuilder.cpp:1878
bool isGlobal() const
Is this variable a global?
Definition PFTBuilder.h:506
bool isModuleOrSubmoduleVariable() const
Is this a module or submodule variable?
Definition PFTBuilder.h:512
bool isAlias() const
Definition PFTBuilder.h:543
std::tuple< std::size_t, std::size_t > Interval
<offset, size> pair
Definition PFTBuilder.h:431
bool hasSymbol() const
Only nominal variable have front-end symbols.
Definition PFTBuilder.h:498
const Interval & getInterval() const
Return the interval range of an aggregate store.
Definition PFTBuilder.h:492
const Fortran::semantics::Symbol & getSymbol() const
Return the front-end symbol for a nominal variable.
Definition PFTBuilder.h:477
int getDepth() const
The depth is recorded for nominal variables as a debugging aid.
Definition PFTBuilder.h:582
const AggregateStore & getAggregateStore() const
Return the aggregate store.
Definition PFTBuilder.h:486
Definition parse-tree.h:1990
Definition parse-tree.h:3450
Definition parse-tree.h:3455
Definition parse-tree.h:3460
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:5509
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:3358
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:5167
Definition parse-tree.h:5483
Definition parse-tree.h:5345
Definition parse-tree.h:5192
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