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 (computed GO TO, arithmetic IF), it is set to the
334 // first target and any additional targets are recorded in
335 // extraControlSuccessors so analyses that need to see every branch target
336 // (e.g. wrappability of an unstructured construct) can enumerate them all.
337 // Successor and exit links always target statements or directives. An
338 // internal Construct node has a constructExit link that applies to exits
339 // from anywhere within the construct.
340 //
341 // An unstructured construct is one that contains some form of goto. This
342 // is indicated by the isUnstructured member flag, which may be set on a
343 // statement and propagated to enclosing constructs. This distinction allows
344 // a structured IF or DO statement to be materialized with custom structured
345 // FIR operations. An unstructured statement is materialized as mlir
346 // operation sequences that include explicit branches.
347 //
348 // The block member is set for statements that begin a new block. This
349 // block is the target of any branch to the statement. Statements may have
350 // additional (unstructured) "local" blocks, but such blocks cannot be the
351 // target of any explicit branch. The primary example of an (unstructured)
352 // statement that may have multiple associated blocks is NonLabelDoStmt,
353 // which may have a loop preheader block for loop initialization code (the
354 // block member), and always has a "local" header block that is the target
355 // of the loop back edge. If the NonLabelDoStmt is a concurrent loop, it
356 // may be associated with an arbitrary number of nested preheader, header,
357 // and mask blocks.
358 //
359 // The printIndex member is only set for statements. It is used for dumps
360 // (and debugging) and does not affect FIR generation.
361
362 PftNode parent;
363 parser::CharBlock position{};
364 std::optional<parser::Label> label{};
365 std::unique_ptr<EvaluationList> evaluationList; // nested evaluations
366 // associated compiler directives
367 llvm::SmallVector<const parser::CompilerDirective *, 1> dirs;
368 Evaluation *parentConstruct{nullptr}; // set for nodes below the top level
369 Evaluation *lexicalSuccessor{nullptr}; // set for leaf nodes, some directives
370 Evaluation *controlSuccessor{nullptr}; // set for some leaf nodes
371 // Additional branch targets for multiway branches (computed GO TO,
372 // arithmetic IF). Empty for single-target branches; the first target is in
373 // controlSuccessor and the remaining ones are stored here in source order.
374 llvm::SmallVector<Evaluation *, 0> extraControlSuccessors;
375 Evaluation *constructExit{nullptr}; // set for constructs
376 bool isNewBlock{false}; // evaluation begins a new basic block
377 bool isUnstructured{false}; // evaluation has unstructured control flow
378 bool negateCondition{false}; // If[Then]Stmt condition must be negated
379 bool activeConstruct{false}; // temporarily set for some constructs
380 mlir::Block *block{nullptr}; // isNewBlock block (ActionStmt, ConstructStmt)
381 int printIndex{0}; // (ActionStmt, ConstructStmt) evaluation index for dumps
382};
383
384using ProgramVariant =
385 ReferenceVariant<parser::MainProgram, parser::FunctionSubprogram,
386 parser::SubroutineSubprogram, parser::Module,
387 parser::Submodule, parser::SeparateModuleSubprogram,
388 parser::BlockData, parser::CompilerDirective,
389 parser::OpenACCRoutineConstruct>;
392struct ProgramUnit : ProgramVariant {
393 template <typename A>
394 ProgramUnit(const A &p, const PftNode &parent)
395 : ProgramVariant{p}, parent{parent} {}
396 ProgramUnit(ProgramUnit &&) = default;
397 ProgramUnit(const ProgramUnit &) = delete;
398
399 PftNode parent;
400};
401
417struct Variable {
421 struct Nominal {
422 Nominal(const semantics::Symbol *symbol, int depth, bool global)
423 : symbol{symbol}, depth{depth}, global{global} {}
424 const semantics::Symbol *symbol{};
425
426 bool isGlobal() const { return global; }
427
428 int depth{};
429 bool global{};
430 bool heapAlloc{}; // variable needs deallocation on exit
431 bool pointer{};
432 bool target{};
433 bool aliaser{}; // participates in EQUIVALENCE union
434 std::size_t aliasOffset{};
435 };
436
438 using Interval = std::tuple<std::size_t, std::size_t>;
439
443 struct AggregateStore {
444 AggregateStore(Interval &&interval,
445 const Fortran::semantics::Symbol &namingSym,
446 bool isGlobal = false)
447 : interval{std::move(interval)}, namingSymbol{&namingSym},
448 isGlobalAggregate{isGlobal} {}
449 AggregateStore(const semantics::Symbol &initialValueSym,
450 const semantics::Symbol &namingSym, bool isGlobal = false)
451 : interval{initialValueSym.offset(), initialValueSym.size()},
452 namingSymbol{&namingSym}, initialValueSymbol{&initialValueSym},
453 isGlobalAggregate{isGlobal} {};
454
455 bool isGlobal() const { return isGlobalAggregate; }
457 std::size_t getOffset() const { return std::get<0>(interval); }
462
466 return getNamingSymbol().owner();
467 }
468
476 };
477
478 explicit Variable(const Fortran::semantics::Symbol &sym, bool global = false,
479 int depth = 0)
480 : var{Nominal(&sym, depth, global)} {}
481 explicit Variable(AggregateStore &&istore) : var{std::move(istore)} {}
482
485 assert(hasSymbol() && "variable is not nominal");
486 return *std::get<Nominal>(var).symbol;
487 }
488
490 bool isRuntimeTypeInfoData() const;
491
494 assert(isAggregateStore());
495 return std::get<AggregateStore>(var);
496 }
497
499 const Interval &getInterval() const {
500 assert(isAggregateStore());
501 return std::get<AggregateStore>(var).interval;
502 }
503
505 bool hasSymbol() const { return std::holds_alternative<Nominal>(var); }
506
508 bool isAggregateStore() const {
509 return std::holds_alternative<AggregateStore>(var);
510 }
511
513 bool isGlobal() const {
514 return Fortran::common::visit([](const auto &x) { return x.isGlobal(); },
515 var);
516 }
517
520 const semantics::Scope *scope = getOwningScope();
521 return scope && scope->kind() == Fortran::semantics::Scope::Kind::Module;
522 }
523
524 const Fortran::semantics::Scope *getOwningScope() const {
525 return Fortran::common::visit(
527 [](const Nominal &x) { return &x.symbol->GetUltimate().owner(); },
528 [](const AggregateStore &agg) { return &agg.getOwningScope(); }},
529 var);
530 }
531
532 bool isHeapAlloc() const {
533 if (auto *s = std::get_if<Nominal>(&var))
534 return s->heapAlloc;
535 return false;
536 }
537 bool isPointer() const {
538 if (auto *s = std::get_if<Nominal>(&var))
539 return s->pointer;
540 return false;
541 }
542 bool isTarget() const {
543 if (auto *s = std::get_if<Nominal>(&var))
544 return s->target;
545 return false;
546 }
547
550 bool isAlias() const {
551 if (auto *s = std::get_if<Nominal>(&var))
552 return s->aliaser;
553 return false;
554 }
555 std::size_t getAliasOffset() const {
556 if (auto *s = std::get_if<Nominal>(&var))
557 return s->aliasOffset;
558 return 0;
559 }
560 void setAlias(std::size_t offset) {
561 if (auto *s = std::get_if<Nominal>(&var)) {
562 s->aliaser = true;
563 s->aliasOffset = offset;
564 } else {
565 llvm_unreachable("not a nominal var");
566 }
567 }
568
569 void setHeapAlloc(bool to = true) {
570 if (auto *s = std::get_if<Nominal>(&var))
571 s->heapAlloc = to;
572 else
573 llvm_unreachable("not a nominal var");
574 }
575 void setPointer(bool to = true) {
576 if (auto *s = std::get_if<Nominal>(&var))
577 s->pointer = to;
578 else
579 llvm_unreachable("not a nominal var");
580 }
581 void setTarget(bool to = true) {
582 if (auto *s = std::get_if<Nominal>(&var))
583 s->target = to;
584 else
585 llvm_unreachable("not a nominal var");
586 }
587
589 int getDepth() const {
590 if (auto *s = std::get_if<Nominal>(&var))
591 return s->depth;
592 return 0;
593 }
594
595 LLVM_DUMP_METHOD void dump() const;
596
597private:
598 std::variant<Nominal, AggregateStore> var;
599};
600
601using VariableList = std::vector<Variable>;
602using ScopeVariableListMap =
603 std::map<const Fortran::semantics::Scope *, VariableList>;
604
607const VariableList &getScopeVariableList(const Fortran::semantics::Scope &scope,
608 ScopeVariableListMap &map);
609
612VariableList getScopeVariableList(const Fortran::semantics::Scope &scope);
613
616VariableList getDependentVariableList(const Fortran::semantics::Symbol &);
617
618struct FunctionLikeUnit;
623VariableList getHostModuleVariableList(const FunctionLikeUnit &funit);
624
625void dump(VariableList &, std::string s = {}); // `s` is an optional dump label
626
629struct FunctionLikeUnit : public ProgramUnit {
630 // wrapper statements for function-like syntactic structures
631 using FunctionStatement =
632 ReferenceVariant<parser::Statement<parser::ProgramStmt>,
640
641 FunctionLikeUnit(
642 const parser::MainProgram &f, const PftNode &parent,
643 const Fortran::semantics::SemanticsContext &semanticsContext);
644 FunctionLikeUnit(
645 const parser::FunctionSubprogram &f, const PftNode &parent,
646 const Fortran::semantics::SemanticsContext &semanticsContext);
647 FunctionLikeUnit(
648 const parser::SubroutineSubprogram &f, const PftNode &parent,
649 const Fortran::semantics::SemanticsContext &semanticsContext);
650 FunctionLikeUnit(
651 const parser::SeparateModuleSubprogram &f, const PftNode &parent,
652 const Fortran::semantics::SemanticsContext &semanticsContext);
653 FunctionLikeUnit(FunctionLikeUnit &&) = default;
654 FunctionLikeUnit(const FunctionLikeUnit &) = delete;
655
656 bool isMainProgram() const {
657 return endStmt.isA<parser::Statement<parser::EndProgramStmt>>();
658 }
659
662
663 void setActiveEntry(int entryIndex) {
664 assert(entryIndex >= 0 && entryIndex < (int)entryPointList.size() &&
665 "invalid entry point index");
666 activeEntry = entryIndex;
667 }
668
673 const semantics::Symbol *symbol = entryPointList[activeEntry].first;
674 if (!symbol)
675 llvm::report_fatal_error(
676 "not inside a procedure; do not call on main program.");
677 return *symbol;
678 }
679
683 if (!isMainProgram()) {
684 llvm::report_fatal_error("call only on main program.");
685 }
686 return entryPointList[activeEntry].first;
687 }
688
692 return entryPointList[activeEntry].second;
693 }
694
695 //===--------------------------------------------------------------------===//
696 // Host associations
697 //===--------------------------------------------------------------------===//
698
699 void setHostAssociatedSymbols(
700 const llvm::SetVector<const semantics::Symbol *> &symbols) {
701 hostAssociations.addSymbolsToBind(symbols, getScope());
702 }
703
707
712
715 bool parentHasHostAssoc();
716
719 HostAssociations &getHostAssoc() { return hostAssociations; }
720 const HostAssociations &getHostAssoc() const { return hostAssociations; };
721
722 LLVM_DUMP_METHOD void dump() const;
723
725 const Fortran::semantics::Scope &getScope() const { return *scope; }
726
728 std::optional<FunctionStatement> beginStmt;
729 FunctionStatement endStmt;
730 const semantics::Scope *scope;
731 LabelEvalMap labelEvaluationMap;
732 SymbolLabelMap assignSymbolLabelMap;
733 ContainedUnitList containedUnitList;
734 EvaluationList evaluationList;
741 entryPointList{std::pair{nullptr, nullptr}};
743 int activeEntry = 0;
747 bool hasIeeeAccess{false};
748 bool mayModifyHaltingMode{false};
749 bool mayModifyRoundingMode{false};
750 bool mayModifyUnderflowMode{false};
752 mlir::Block *finalBlock{};
753 HostAssociations hostAssociations;
755 std::list<Fortran::semantics::PreservedUseStmt> preservedUseStmts;
756};
757
759struct ModuleLikeUnit : public ProgramUnit {
760 // wrapper statements for module-like syntactic structures
761 using ModuleStatement =
762 ReferenceVariant<parser::Statement<parser::ModuleStmt>,
766
767 ModuleLikeUnit(const parser::Module &m, const PftNode &parent);
768 ModuleLikeUnit(const parser::Submodule &m, const PftNode &parent);
769 ~ModuleLikeUnit() = default;
770 ModuleLikeUnit(ModuleLikeUnit &&) = default;
771 ModuleLikeUnit(const ModuleLikeUnit &) = delete;
772
773 LLVM_DUMP_METHOD void dump() const;
774
777
779 const Fortran::semantics::Scope &getScope() const;
780
781 ModuleStatement beginStmt;
782 ModuleStatement endStmt;
783 ContainedUnitList containedUnitList;
784 EvaluationList evaluationList;
786 std::list<Fortran::semantics::PreservedUseStmt> preservedUseStmts;
787};
788
791struct BlockDataUnit : public ProgramUnit {
792 BlockDataUnit(const parser::BlockData &bd, const PftNode &parent,
793 const Fortran::semantics::SemanticsContext &semanticsContext);
794 BlockDataUnit(BlockDataUnit &&) = default;
795 BlockDataUnit(const BlockDataUnit &) = delete;
796
797 LLVM_DUMP_METHOD void dump() const;
798
799 const Fortran::semantics::Scope &symTab; // symbol table
800};
801
802// Top level compiler directives
803struct CompilerDirectiveUnit : public ProgramUnit {
804 CompilerDirectiveUnit(const parser::CompilerDirective &directive,
805 const PftNode &parent)
806 : ProgramUnit{directive, parent} {};
807 CompilerDirectiveUnit(CompilerDirectiveUnit &&) = default;
808 CompilerDirectiveUnit(const CompilerDirectiveUnit &) = delete;
809};
810
811// Top level OpenACC routine directives
812struct OpenACCDirectiveUnit : public ProgramUnit {
813 OpenACCDirectiveUnit(const parser::OpenACCRoutineConstruct &directive,
814 const PftNode &parent)
815 : ProgramUnit{directive, parent}, routine{directive} {};
816 OpenACCDirectiveUnit(OpenACCDirectiveUnit &&) = default;
817 OpenACCDirectiveUnit(const OpenACCDirectiveUnit &) = delete;
818 const parser::OpenACCRoutineConstruct &routine;
819};
820
822struct Program {
823 using Units = std::variant<FunctionLikeUnit, ModuleLikeUnit, BlockDataUnit,
825
826 Program(semantics::CommonBlockList &&commonBlocks)
827 : commonBlocks{std::move(commonBlocks)} {}
828 Program(Program &&) = default;
829 Program(const Program &) = delete;
830
831 const std::list<Units> &getUnits() const { return units; }
832 std::list<Units> &getUnits() { return units; }
833 const semantics::CommonBlockList &getCommonBlocks() const {
834 return commonBlocks;
835 }
836 ScopeVariableListMap &getScopeVariableListMap() {
837 return scopeVariableListMap;
838 }
839
841 LLVM_DUMP_METHOD void dump() const;
842
843private:
844 std::list<Units> units;
845 semantics::CommonBlockList commonBlocks;
846 ScopeVariableListMap scopeVariableListMap; // module and submodule scopes
847};
848
851template <typename T>
852static parser::CharBlock stmtSourceLoc(const T &stmt) {
853 return stmt.visit(common::visitors{[](const auto &x) { return x.source; }});
854}
855
857template <typename ParentType, typename A>
858ParentType *getAncestor(A &node) {
859 if (auto *seekedParent = node.parent.template getIf<ParentType>())
860 return seekedParent;
861 return node.parent.visit(common::visitors{
862 [](Program &p) -> ParentType * { return nullptr; },
863 [](auto &p) -> ParentType * { return getAncestor<ParentType>(p); }});
864}
865
867template <typename A>
868ScopeVariableListMap &getScopeVariableListMap(A &node) {
869 Program *pftRoot = getAncestor<Program>(node);
870 assert(pftRoot && "pft must have a root");
871 return pftRoot->getScopeVariableListMap();
872}
873
876void visitAllSymbols(const FunctionLikeUnit &funit,
877 std::function<void(const semantics::Symbol &)> callBack);
878
881void visitAllSymbols(const Evaluation &eval,
882 std::function<void(const semantics::Symbol &)> callBack);
883
886bool isWrappableConstruct(const Evaluation &eval);
887
888} // namespace Fortran::lower::pft
889
890namespace Fortran::lower {
891class LoweringOptions;
892
901std::unique_ptr<pft::Program>
902createPFT(const parser::Program &root,
903 const Fortran::semantics::SemanticsContext &semanticsContext,
904 const LoweringOptions &loweringOptions);
905
907void dumpPFT(llvm::raw_ostream &outputStream, const pft::Program &pft);
908} // namespace Fortran::lower
909
910#endif // FORTRAN_LOWER_PFTBUILDER_H
Definition reference.h:18
Definition HostAssociations.h:28
void addSymbolsToBind(const llvm::SetVector< const Fortran::semantics::Symbol * > &symbols, const Fortran::semantics::Scope &hostScope)
Definition HostAssociations.cpp:541
Definition LoweringOptions.h:35
Definition char-block.h:26
Definition scope.h:68
Definition semantics.h:67
Definition symbol.h:896
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:2102
std::unique_ptr< pft::Program > createPFT(const parser::Program &root, const Fortran::semantics::SemanticsContext &semanticsContext, const LoweringOptions &loweringOptions)
Definition PFTBuilder.cpp:2094
Definition idioms.h:60
Definition PFTBuilder.h:791
LLVM_DUMP_METHOD void dump() const
The BlockDataUnit dump is just the associated symbol table.
Definition PFTBuilder.cpp:2162
Definition PFTBuilder.h:221
FunctionLikeUnit * getOwningProcedure() const
Return the FunctionLikeUnit containing this evaluation (or nullptr).
Definition PFTBuilder.cpp:1645
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:629
Evaluation * getEntryEval() const
Definition PFTBuilder.h:691
llvm::SmallVector< std::pair< const semantics::Symbol *, Evaluation * >, 1 > entryPointList
Definition PFTBuilder.h:741
HostAssociations & parentHostAssoc()
Definition PFTBuilder.cpp:2008
bool parentHasHostAssoc()
Definition PFTBuilder.cpp:2020
int activeEntry
Current index into entryPointList. Index 0 is the primary entry point.
Definition PFTBuilder.h:743
mlir::Block * finalBlock
Terminal basic block (if any)
Definition PFTBuilder.h:752
std::list< Fortran::semantics::PreservedUseStmt > preservedUseStmts
Preserved USE statements for debug info generation.
Definition PFTBuilder.h:755
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this function like unit.
Definition PFTBuilder.cpp:2027
HostAssociations & getHostAssoc()
Definition PFTBuilder.h:719
const semantics::Symbol * primaryResult
Definition PFTBuilder.h:746
std::optional< FunctionStatement > beginStmt
Anonymous programs do not have a begin statement.
Definition PFTBuilder.h:728
const semantics::Symbol * getMainProgramSymbol() const
Definition PFTBuilder.h:682
const Fortran::semantics::Scope & getScope() const
Get the function scope.
Definition PFTBuilder.h:725
const semantics::Symbol & getSubprogramSymbol() const
Definition PFTBuilder.h:672
bool parentHasTupleHostAssoc()
Definition PFTBuilder.cpp:2014
Module-like units contain a list of function-like units.
Definition PFTBuilder.h:759
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this module like unit.
Definition PFTBuilder.cpp:2049
std::list< Fortran::semantics::PreservedUseStmt > preservedUseStmts
Preserved USE statements for debug info generation.
Definition PFTBuilder.h:786
const Fortran::semantics::Scope & getScope() const
Get the module scope.
Definition PFTBuilder.cpp:2053
A Program is the top-level root of the PFT.
Definition PFTBuilder.h:822
LLVM_DUMP_METHOD void dump() const
LLVM dump method on a Program.
Definition PFTBuilder.cpp:2107
std::size_t getOffset() const
Get offset of the aggregate inside its scope.
Definition PFTBuilder.h:457
const semantics::Symbol & getNamingSymbol() const
Returns the symbol that gives its name to the aggregate.
Definition PFTBuilder.h:463
const semantics::Symbol * namingSymbol
Symbol that gives its name to the aggregate. Always set by constructor.
Definition PFTBuilder.h:471
const semantics::Symbol * initialValueSymbol
Compiler generated symbol with the aggregate initial value if any.
Definition PFTBuilder.h:473
bool isGlobalAggregate
Is this a global aggregate?
Definition PFTBuilder.h:475
Interval interval
<offset, size> of the aggregate in its scope.
Definition PFTBuilder.h:469
const semantics::Symbol * getInitialValueSymbol() const
Returns symbols holding the aggregate initial value if any.
Definition PFTBuilder.h:459
const semantics::Scope & getOwningScope() const
Scope to which the aggregates belongs to.
Definition PFTBuilder.h:465
Definition PFTBuilder.h:421
Definition PFTBuilder.h:417
bool isAggregateStore() const
Is this an aggregate store?
Definition PFTBuilder.h:508
bool isRuntimeTypeInfoData() const
Is this variable a compiler generated global to describe derived types?
Definition PFTBuilder.cpp:2076
bool isGlobal() const
Is this variable a global?
Definition PFTBuilder.h:513
bool isModuleOrSubmoduleVariable() const
Is this a module or submodule variable?
Definition PFTBuilder.h:519
bool isAlias() const
Definition PFTBuilder.h:550
std::tuple< std::size_t, std::size_t > Interval
<offset, size> pair
Definition PFTBuilder.h:438
bool hasSymbol() const
Only nominal variable have front-end symbols.
Definition PFTBuilder.h:505
const Interval & getInterval() const
Return the interval range of an aggregate store.
Definition PFTBuilder.h:499
const Fortran::semantics::Symbol & getSymbol() const
Return the front-end symbol for a nominal variable.
Definition PFTBuilder.h:484
int getDepth() const
The depth is recorded for nominal variables as a debugging aid.
Definition PFTBuilder.h:589
const AggregateStore & getAggregateStore() const
Return the aggregate store.
Definition PFTBuilder.h:493
Definition parse-tree.h:2019
Definition parse-tree.h:3541
Definition parse-tree.h:3546
Definition parse-tree.h:3551
Definition parse-tree.h:2045
Definition parse-tree.h:2200
Definition parse-tree.h:2191
Definition parse-tree.h:2222
Definition parse-tree.h:3061
Definition parse-tree.h:5879
Definition parse-tree.h:3343
Definition parse-tree.h:2463
Definition parse-tree.h:2451
Definition parse-tree.h:2253
Definition parse-tree.h:2238
Definition parse-tree.h:2722
Definition parse-tree.h:3430
Definition parse-tree.h:2550
Definition parse-tree.h:2269
Definition parse-tree.h:2260
Definition parse-tree.h:2039
Definition parse-tree.h:2365
Definition parse-tree.h:2385
Definition parse-tree.h:2247
Definition parse-tree.h:2604
Definition parse-tree.h:2618
Definition parse-tree.h:2135
Definition parse-tree.h:2170
Definition parse-tree.h:2147
Definition parse-tree.h:2630
Definition parse-tree.h:3363
Definition parse-tree.h:2399
Definition parse-tree.h:2415
Definition parse-tree.h:2378
Definition parse-tree.h:2948
Definition parse-tree.h:2644
Definition parse-tree.h:2969
Definition parse-tree.h:2102
Definition parse-tree.h:3005
Definition parse-tree.h:2348
Definition parse-tree.h:2572
Definition parse-tree.h:5853
Definition parse-tree.h:5715
Definition parse-tree.h:5549
Definition parse-tree.h:2067
Definition parse-tree.h:2822
Definition parse-tree.h:2785
Definition parse-tree.h:2422
Definition parse-tree.h:2486
Definition parse-tree.h:2498
Definition parse-tree.h:2477
Definition parse-tree.h:2532
Definition parse-tree.h:2512
Definition parse-tree.h:3389
Definition parse-tree.h:361
Definition parse-tree.h:2564
Definition parse-tree.h:3047
Definition parse-tree.h:3373
Definition parse-tree.h:2582
Definition parse-tree.h:2595
Definition parse-tree.h:2521
Definition parse-tree.h:2654
Definition parse-tree.h:2086
Definition parse-tree.h:2117
Definition parse-tree.h:2080
Definition parse-tree.h:2807