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#include <algorithm>
32
33namespace Fortran::lower::pft {
34
36struct Evaluation;
37struct FunctionLikeUnit;
38struct ModuleLikeUnit;
39struct Program;
40
41using ContainedUnit = std::variant<CompilerDirectiveUnit, FunctionLikeUnit>;
42using ContainedUnitList = std::list<ContainedUnit>;
43using EvaluationList = std::list<Evaluation>;
44
48template <bool isConst, typename... A>
49class ReferenceVariantBase {
50public:
51 template <typename B>
52 using BaseType = std::conditional_t<isConst, const B, B>;
53 template <typename B>
55
56 ReferenceVariantBase() = delete;
57 ReferenceVariantBase(std::variant<Ref<A>...> b) : u(b) {}
58 template <typename T>
59 ReferenceVariantBase(Ref<T> b) : u(b) {}
60
61 template <typename B>
62 constexpr BaseType<B> &get() const {
63 return std::get<Ref<B>>(u).get();
64 }
65 template <typename B>
66 constexpr BaseType<B> &getStatement() const {
67 return std::get<Ref<parser::Statement<B>>>(u).get().statement;
68 }
69 template <typename B>
70 constexpr BaseType<B> *getIf() const {
71 const Ref<B> *ptr = std::get_if<Ref<B>>(&u);
72 return ptr ? &ptr->get() : nullptr;
73 }
74 template <typename B>
75 constexpr bool isA() const {
76 return std::holds_alternative<Ref<B>>(u);
77 }
78 template <typename VISITOR>
79 constexpr auto visit(VISITOR &&visitor) const {
80 return Fortran::common::visit(
81 common::visitors{[&visitor](auto ref) { return visitor(ref.get()); }},
82 u);
83 }
84
85private:
86 std::variant<Ref<A>...> u;
87};
88template <typename... A>
89using ReferenceVariant = ReferenceVariantBase<true, A...>;
90template <typename... A>
91using MutableReferenceVariant = ReferenceVariantBase<false, A...>;
92
95using PftNode = MutableReferenceVariant<Program, ModuleLikeUnit,
97
99
100using ActionStmts = std::tuple<
101 parser::AllocateStmt, parser::AssignmentStmt, parser::BackspaceStmt,
102 parser::CallStmt, parser::CloseStmt, parser::ContinueStmt,
103 parser::CycleStmt, parser::DeallocateStmt, parser::EndfileStmt,
105 parser::FailImageStmt, parser::FlushStmt, parser::FormTeamStmt,
107 parser::NotifyWaitStmt, parser::NullifyStmt, parser::OpenStmt,
109 parser::ReturnStmt, parser::RewindStmt, parser::StopStmt,
110 parser::SyncAllStmt, parser::SyncImagesStmt, parser::SyncMemoryStmt,
111 parser::SyncTeamStmt, parser::UnlockStmt, parser::WaitStmt,
114 parser::AssignedGotoStmt, parser::PauseStmt>;
115
116using OtherStmts = std::tuple<parser::EntryStmt, parser::FormatStmt>;
117
118using ConstructStmts = std::tuple<
119 parser::AssociateStmt, parser::EndAssociateStmt, parser::BlockStmt,
120 parser::EndBlockStmt, parser::SelectCaseStmt, parser::CaseStmt,
122 parser::CriticalStmt, parser::EndCriticalStmt, parser::NonLabelDoStmt,
123 parser::EndDoStmt, parser::IfThenStmt, parser::ElseIfStmt, parser::ElseStmt,
126 parser::MaskedElsewhereStmt, parser::ElsewhereStmt, parser::EndWhereStmt,
127 parser::ForallConstructStmt, parser::EndForallStmt>;
128
129using EndStmts =
130 std::tuple<parser::EndProgramStmt, parser::EndFunctionStmt,
131 parser::EndSubroutineStmt, parser::EndMpSubprogramStmt>;
132
133using Constructs =
140
141using Directives =
147
148using DeclConstructs = std::tuple<parser::OpenMPDeclarativeConstruct,
150
151template <typename A>
152static constexpr bool isActionStmt{common::HasMember<A, ActionStmts>};
153
154template <typename A>
155static constexpr bool isOtherStmt{common::HasMember<A, OtherStmts>};
156
157template <typename A>
158static constexpr bool isConstructStmt{common::HasMember<A, ConstructStmts>};
159
160template <typename A>
161static constexpr bool isEndStmt{common::HasMember<A, EndStmts>};
162
163template <typename A>
164static constexpr bool isConstruct{common::HasMember<A, Constructs>};
165
166template <typename A>
167static constexpr bool isDirective{common::HasMember<A, Directives>};
168
169template <typename A>
170static constexpr bool isDeclConstruct{common::HasMember<A, DeclConstructs>};
171
172template <typename A>
173static constexpr bool isIntermediateConstructStmt{common::HasMember<
174 A, std::tuple<parser::CaseStmt, parser::ElseIfStmt, parser::ElseStmt,
175 parser::SelectRankCaseStmt, parser::TypeGuardStmt>>};
176
177template <typename A>
178static constexpr bool isNopConstructStmt{common::HasMember<
179 A, std::tuple<parser::CaseStmt, parser::ElseIfStmt, parser::ElseStmt,
180 parser::EndIfStmt, parser::SelectRankCaseStmt,
181 parser::TypeGuardStmt>>};
182
183template <typename A>
184static constexpr bool isExecutableDirective{common::HasMember<
185 A, std::tuple<parser::CompilerDirective, parser::OpenACCConstruct,
186 parser::OpenMPConstruct, parser::CUFKernelDoConstruct>>};
187
188template <typename A>
189static constexpr bool isOpenMPDirective{
190 common::HasMember<A, std::tuple<parser::OpenMPConstruct,
191 parser::OpenMPDeclarativeConstruct>>};
192
193template <typename A>
194static constexpr bool isFunctionLike{common::HasMember<
195 A, std::tuple<parser::MainProgram, parser::FunctionSubprogram,
196 parser::SubroutineSubprogram,
197 parser::SeparateModuleSubprogram>>};
198
199template <typename A>
201template <typename... A>
202struct MakeReferenceVariantHelper<std::variant<A...>> {
203 using type = ReferenceVariant<A...>;
204};
205template <typename... A>
206struct MakeReferenceVariantHelper<std::tuple<A...>> {
207 using type = ReferenceVariant<A...>;
208};
209template <typename A>
210using MakeReferenceVariant = typename MakeReferenceVariantHelper<A>::type;
211
212using EvaluationTuple =
213 common::CombineTuples<ActionStmts, OtherStmts, ConstructStmts, EndStmts,
214 Constructs, Directives>;
218using EvaluationVariant = MakeReferenceVariant<EvaluationTuple>;
219
222struct Evaluation : EvaluationVariant {
223
225 template <typename A>
226 Evaluation(const A &a, const PftNode &parent,
227 const parser::CharBlock &position,
228 const std::optional<parser::Label> &label)
229 : EvaluationVariant{a}, parent{parent}, position{position}, label{label} {
230 }
231
233 template <typename A>
234 Evaluation(const A &a, const PftNode &parent)
235 : EvaluationVariant{a}, parent{parent} {
236 static_assert(pft::isConstruct<A> || pft::isDirective<A>,
237 "must be a construct or directive");
238 }
239
241 constexpr bool isActionStmt() const {
242 return visit(common::visitors{
243 [](auto &r) { return pft::isActionStmt<std::decay_t<decltype(r)>>; }});
244 }
245 constexpr bool isOtherStmt() const {
246 return visit(common::visitors{
247 [](auto &r) { return pft::isOtherStmt<std::decay_t<decltype(r)>>; }});
248 }
249 constexpr bool isConstructStmt() const {
250 return visit(common::visitors{[](auto &r) {
251 return pft::isConstructStmt<std::decay_t<decltype(r)>>;
252 }});
253 }
254 constexpr bool isEndStmt() const {
255 return visit(common::visitors{
256 [](auto &r) { return pft::isEndStmt<std::decay_t<decltype(r)>>; }});
257 }
258 constexpr bool isConstruct() const {
259 return visit(common::visitors{
260 [](auto &r) { return pft::isConstruct<std::decay_t<decltype(r)>>; }});
261 }
262 constexpr bool isDirective() const {
263 return visit(common::visitors{
264 [](auto &r) { return pft::isDirective<std::decay_t<decltype(r)>>; }});
265 }
266 constexpr bool isNopConstructStmt() const {
267 return visit(common::visitors{[](auto &r) {
268 return pft::isNopConstructStmt<std::decay_t<decltype(r)>>;
269 }});
270 }
271 constexpr bool isExecutableDirective() const {
272 return visit(common::visitors{[](auto &r) {
273 return pft::isExecutableDirective<std::decay_t<decltype(r)>>;
274 }});
275 }
276 constexpr bool isOpenMPDirective() const {
277 return visit(common::visitors{[](auto &r) {
278 return pft::isOpenMPDirective<std::decay_t<decltype(r)>>;
279 }});
280 }
281
284 constexpr bool isIntermediateConstructStmt() const {
285 return visit(common::visitors{[](auto &r) {
286 return pft::isIntermediateConstructStmt<std::decay_t<decltype(r)>>;
287 }});
288 }
289
290 LLVM_DUMP_METHOD void dump() const;
291
295 Evaluation *successor = lexicalSuccessor;
296 if (successor && successor->isNopConstructStmt())
297 successor = successor->parentConstruct->constructExit;
298 assert(successor && "missing successor");
299 return *successor;
300 }
301
303 bool hasNestedEvaluations() const {
304 return evaluationList && !evaluationList->empty();
305 }
306
308 EvaluationList &getNestedEvaluations() {
309 assert(evaluationList && "no nested evaluations");
310 return *evaluationList;
311 }
312
313 Evaluation &getFirstNestedEvaluation() {
314 assert(hasNestedEvaluations() && "no nested evaluations");
315 return evaluationList->front();
316 }
317
318 Evaluation &getLastNestedEvaluation() {
319 assert(hasNestedEvaluations() && "no nested evaluations");
320 return evaluationList->back();
321 }
322
324 FunctionLikeUnit *getOwningProcedure() const;
325
342
347 controlFlow = std::max(controlFlow, kind);
348 }
349
350 void markUnstructured() { markControlFlow(ControlFlow::Unstructured); }
351
356 controlFlow = std::min(controlFlow, kind);
357 }
358
361 bool isUnstructured() const {
362 return controlFlow == ControlFlow::Unstructured;
363 }
364
365 bool hasUnstructuredInternals() const {
367 }
368
372 bool lowerBodyAsWrappedRegion() const;
373
374 bool lowerAsStructured() const;
375 bool lowerAsUnstructured() const;
376 bool forceAsUnstructured() const;
377
378 // FIR generation looks primarily at PFT ActionStmt and ConstructStmt leaf
379 // nodes. Members such as lexicalSuccessor and block are applicable only
380 // to these nodes, plus some directives. The controlSuccessor member is
381 // used for nonlexical successors, such as linking to a GOTO target. For
382 // multiway branches (computed GO TO, arithmetic IF), it is set to the
383 // first target and any additional targets are recorded in
384 // extraControlSuccessors so analyses that need to see every branch target
385 // (e.g. wrappability of an unstructured construct) can enumerate them all.
386 // Successor and exit links always target statements or directives. An
387 // internal Construct node has a constructExit link that applies to exits
388 // from anywhere within the construct.
389 //
390 // An unstructured construct is one that contains some form of goto. This
391 // is indicated by the controlFlow member, which may be set on a statement and
392 // propagated to enclosing constructs. This distinction allows a structured IF
393 // or DO statement to be materialized with custom structured FIR operations.
394 // An unstructured statement is materialized as mlir operation sequences that
395 // include explicit branches.
396 //
397 // The block member is set for statements that begin a new block. This
398 // block is the target of any branch to the statement. Statements may have
399 // additional (unstructured) "local" blocks, but such blocks cannot be the
400 // target of any explicit branch. The primary example of an (unstructured)
401 // statement that may have multiple associated blocks is NonLabelDoStmt,
402 // which may have a loop preheader block for loop initialization code (the
403 // block member), and always has a "local" header block that is the target
404 // of the loop back edge. If the NonLabelDoStmt is a concurrent loop, it
405 // may be associated with an arbitrary number of nested preheader, header,
406 // and mask blocks.
407 //
408 // The printIndex member is only set for statements. It is used for dumps
409 // (and debugging) and does not affect FIR generation.
410
411 PftNode parent;
412 parser::CharBlock position{};
413 std::optional<parser::Label> label{};
414 std::unique_ptr<EvaluationList> evaluationList; // nested evaluations
415 // associated compiler directives
417 Evaluation *parentConstruct{nullptr}; // set for nodes below the top level
418 Evaluation *lexicalSuccessor{nullptr}; // set for leaf nodes, some directives
419 Evaluation *controlSuccessor{nullptr}; // set for some leaf nodes
420 // Additional branch targets for multiway branches (computed GO TO,
421 // arithmetic IF). Empty for single-target branches; the first target is in
422 // controlSuccessor and the remaining ones are stored here in source order.
423 llvm::SmallVector<Evaluation *, 0> extraControlSuccessors;
424 Evaluation *constructExit{nullptr}; // set for constructs
425 bool isNewBlock{false}; // evaluation begins a new basic block
427 bool negateCondition{false}; // If[Then]Stmt condition must be negated
428 bool activeConstruct{false}; // temporarily set for some constructs
429 // The enclosing evaluation-list traversal should skip this evaluation once
430 // because directive lowering already consumed it.
431 bool skipNextLowering{false};
432 mlir::Block *block{nullptr}; // isNewBlock block (ActionStmt, ConstructStmt)
433 int printIndex{0}; // (ActionStmt, ConstructStmt) evaluation index for dumps
434};
435
436using ProgramVariant =
437 ReferenceVariant<parser::MainProgram, parser::FunctionSubprogram,
438 parser::SubroutineSubprogram, parser::Module,
439 parser::Submodule, parser::SeparateModuleSubprogram,
440 parser::BlockData, parser::CompilerDirective,
441 parser::OpenACCRoutineConstruct>;
444struct ProgramUnit : ProgramVariant {
445 template <typename A>
446 ProgramUnit(const A &p, const PftNode &parent)
447 : ProgramVariant{p}, parent{parent} {}
448 ProgramUnit(ProgramUnit &&) = default;
449 ProgramUnit(const ProgramUnit &) = delete;
450
451 PftNode parent;
452};
453
469struct Variable {
473 struct Nominal {
474 Nominal(const semantics::Symbol *symbol, int depth, bool global)
475 : symbol{symbol}, depth{depth}, global{global} {}
476 const semantics::Symbol *symbol{};
477
478 bool isGlobal() const { return global; }
479
480 int depth{};
481 bool global{};
482 bool heapAlloc{}; // variable needs deallocation on exit
483 bool pointer{};
484 bool target{};
485 bool aliaser{}; // participates in EQUIVALENCE union
486 std::size_t aliasOffset{};
487 };
488
490 using Interval = std::tuple<std::size_t, std::size_t>;
491
495 struct AggregateStore {
496 AggregateStore(Interval &&interval,
497 const Fortran::semantics::Symbol &namingSym,
498 bool isGlobal = false)
499 : interval{std::move(interval)}, namingSymbol{&namingSym},
500 isGlobalAggregate{isGlobal} {}
501 AggregateStore(const semantics::Symbol &initialValueSym,
502 const semantics::Symbol &namingSym, bool isGlobal = false)
503 : interval{initialValueSym.offset(), initialValueSym.size()},
504 namingSymbol{&namingSym}, initialValueSymbol{&initialValueSym},
505 isGlobalAggregate{isGlobal} {};
506
507 bool isGlobal() const { return isGlobalAggregate; }
509 std::size_t getOffset() const { return std::get<0>(interval); }
514
518 return getNamingSymbol().owner();
519 }
520
528 };
529
530 explicit Variable(const Fortran::semantics::Symbol &sym, bool global = false,
531 int depth = 0)
532 : var{Nominal(&sym, depth, global)} {}
533 explicit Variable(AggregateStore &&istore) : var{std::move(istore)} {}
534
537 assert(hasSymbol() && "variable is not nominal");
538 return *std::get<Nominal>(var).symbol;
539 }
540
542 bool isRuntimeTypeInfoData() const;
543
546 assert(isAggregateStore());
547 return std::get<AggregateStore>(var);
548 }
549
551 const Interval &getInterval() const {
552 assert(isAggregateStore());
553 return std::get<AggregateStore>(var).interval;
554 }
555
557 bool hasSymbol() const { return std::holds_alternative<Nominal>(var); }
558
560 bool isAggregateStore() const {
561 return std::holds_alternative<AggregateStore>(var);
562 }
563
565 bool isGlobal() const {
566 return Fortran::common::visit([](const auto &x) { return x.isGlobal(); },
567 var);
568 }
569
572 const semantics::Scope *scope = getOwningScope();
573 return scope && scope->kind() == Fortran::semantics::Scope::Kind::Module;
574 }
575
576 const Fortran::semantics::Scope *getOwningScope() const {
577 return Fortran::common::visit(
579 [](const Nominal &x) { return &x.symbol->GetUltimate().owner(); },
580 [](const AggregateStore &agg) { return &agg.getOwningScope(); }},
581 var);
582 }
583
584 bool isHeapAlloc() const {
585 if (auto *s = std::get_if<Nominal>(&var))
586 return s->heapAlloc;
587 return false;
588 }
589 bool isPointer() const {
590 if (auto *s = std::get_if<Nominal>(&var))
591 return s->pointer;
592 return false;
593 }
594 bool isTarget() const {
595 if (auto *s = std::get_if<Nominal>(&var))
596 return s->target;
597 return false;
598 }
599
602 bool isAlias() const {
603 if (auto *s = std::get_if<Nominal>(&var))
604 return s->aliaser;
605 return false;
606 }
607 std::size_t getAliasOffset() const {
608 if (auto *s = std::get_if<Nominal>(&var))
609 return s->aliasOffset;
610 return 0;
611 }
612 void setAlias(std::size_t offset) {
613 if (auto *s = std::get_if<Nominal>(&var)) {
614 s->aliaser = true;
615 s->aliasOffset = offset;
616 } else {
617 llvm_unreachable("not a nominal var");
618 }
619 }
620
621 void setHeapAlloc(bool to = true) {
622 if (auto *s = std::get_if<Nominal>(&var))
623 s->heapAlloc = to;
624 else
625 llvm_unreachable("not a nominal var");
626 }
627 void setPointer(bool to = true) {
628 if (auto *s = std::get_if<Nominal>(&var))
629 s->pointer = to;
630 else
631 llvm_unreachable("not a nominal var");
632 }
633 void setTarget(bool to = true) {
634 if (auto *s = std::get_if<Nominal>(&var))
635 s->target = to;
636 else
637 llvm_unreachable("not a nominal var");
638 }
639
641 int getDepth() const {
642 if (auto *s = std::get_if<Nominal>(&var))
643 return s->depth;
644 return 0;
645 }
646
647 LLVM_DUMP_METHOD void dump() const;
648
649private:
650 std::variant<Nominal, AggregateStore> var;
651};
652
653using VariableList = std::vector<Variable>;
654using ScopeVariableListMap =
655 std::map<const Fortran::semantics::Scope *, VariableList>;
656
659const VariableList &getScopeVariableList(const Fortran::semantics::Scope &scope,
660 ScopeVariableListMap &map);
661
664VariableList getScopeVariableList(const Fortran::semantics::Scope &scope);
665
668VariableList getDependentVariableList(const Fortran::semantics::Symbol &);
669
670struct FunctionLikeUnit;
675VariableList getHostModuleVariableList(const FunctionLikeUnit &funit);
676
677void dump(VariableList &, std::string s = {}); // `s` is an optional dump label
678
681struct FunctionLikeUnit : public ProgramUnit {
682 // wrapper statements for function-like syntactic structures
683 using FunctionStatement =
684 ReferenceVariant<parser::Statement<parser::ProgramStmt>,
692
693 FunctionLikeUnit(
694 const parser::MainProgram &f, const PftNode &parent,
695 const Fortran::semantics::SemanticsContext &semanticsContext);
696 FunctionLikeUnit(
697 const parser::FunctionSubprogram &f, const PftNode &parent,
698 const Fortran::semantics::SemanticsContext &semanticsContext);
699 FunctionLikeUnit(
700 const parser::SubroutineSubprogram &f, const PftNode &parent,
701 const Fortran::semantics::SemanticsContext &semanticsContext);
702 FunctionLikeUnit(
703 const parser::SeparateModuleSubprogram &f, const PftNode &parent,
704 const Fortran::semantics::SemanticsContext &semanticsContext);
705 FunctionLikeUnit(FunctionLikeUnit &&) = default;
706 FunctionLikeUnit(const FunctionLikeUnit &) = delete;
707
708 bool isMainProgram() const {
709 return endStmt.isA<parser::Statement<parser::EndProgramStmt>>();
710 }
711
714
715 void setActiveEntry(int entryIndex) {
716 assert(entryIndex >= 0 && entryIndex < (int)entryPointList.size() &&
717 "invalid entry point index");
718 activeEntry = entryIndex;
719 }
720
725 const semantics::Symbol *symbol = entryPointList[activeEntry].first;
726 if (!symbol)
727 llvm::report_fatal_error(
728 "not inside a procedure; do not call on main program.");
729 return *symbol;
730 }
731
735 if (!isMainProgram()) {
736 llvm::report_fatal_error("call only on main program.");
737 }
738 return entryPointList[activeEntry].first;
739 }
740
744 return entryPointList[activeEntry].second;
745 }
746
747 //===--------------------------------------------------------------------===//
748 // Host associations
749 //===--------------------------------------------------------------------===//
750
751 void setHostAssociatedSymbols(
752 const llvm::SetVector<const semantics::Symbol *> &symbols) {
753 hostAssociations.addSymbolsToBind(symbols, getScope());
754 }
755
759
764
767 bool parentHasHostAssoc();
768
771 HostAssociations &getHostAssoc() { return hostAssociations; }
772 const HostAssociations &getHostAssoc() const { return hostAssociations; };
773
774 LLVM_DUMP_METHOD void dump() const;
775
777 const Fortran::semantics::Scope &getScope() const { return *scope; }
778
780 std::optional<FunctionStatement> beginStmt;
781 FunctionStatement endStmt;
782 const semantics::Scope *scope;
783 LabelEvalMap labelEvaluationMap;
784 SymbolLabelMap assignSymbolLabelMap;
789 IncomingBranchMap incomingBranches;
790 ContainedUnitList containedUnitList;
791 EvaluationList evaluationList;
798 entryPointList{std::pair{nullptr, nullptr}};
800 int activeEntry = 0;
804 bool hasIeeeAccess{false};
805 bool mayModifyHaltingMode{false};
806 bool mayModifyRoundingMode{false};
807 bool mayModifyUnderflowMode{false};
809 mlir::Block *finalBlock{};
810 HostAssociations hostAssociations;
812 std::list<Fortran::semantics::PreservedUseStmt> preservedUseStmts;
813};
814
816struct ModuleLikeUnit : public ProgramUnit {
817 // wrapper statements for module-like syntactic structures
818 using ModuleStatement =
819 ReferenceVariant<parser::Statement<parser::ModuleStmt>,
823
824 ModuleLikeUnit(const parser::Module &m, const PftNode &parent);
825 ModuleLikeUnit(const parser::Submodule &m, const PftNode &parent);
826 ~ModuleLikeUnit() = default;
827 ModuleLikeUnit(ModuleLikeUnit &&) = default;
828 ModuleLikeUnit(const ModuleLikeUnit &) = delete;
829
830 LLVM_DUMP_METHOD void dump() const;
831
834
836 const Fortran::semantics::Scope &getScope() const;
837
838 ModuleStatement beginStmt;
839 ModuleStatement endStmt;
840 ContainedUnitList containedUnitList;
841 EvaluationList evaluationList;
843 std::list<Fortran::semantics::PreservedUseStmt> preservedUseStmts;
844};
845
848struct BlockDataUnit : public ProgramUnit {
849 BlockDataUnit(const parser::BlockData &bd, const PftNode &parent,
850 const Fortran::semantics::SemanticsContext &semanticsContext);
851 BlockDataUnit(BlockDataUnit &&) = default;
852 BlockDataUnit(const BlockDataUnit &) = delete;
853
854 LLVM_DUMP_METHOD void dump() const;
855
856 const Fortran::semantics::Scope &symTab; // symbol table
857};
858
859// Top level compiler directives
860struct CompilerDirectiveUnit : public ProgramUnit {
861 CompilerDirectiveUnit(const parser::CompilerDirective &directive,
862 const PftNode &parent)
863 : ProgramUnit{directive, parent} {};
864 CompilerDirectiveUnit(CompilerDirectiveUnit &&) = default;
865 CompilerDirectiveUnit(const CompilerDirectiveUnit &) = delete;
866};
867
868// Top level OpenACC routine directives
869struct OpenACCDirectiveUnit : public ProgramUnit {
870 OpenACCDirectiveUnit(const parser::OpenACCRoutineConstruct &directive,
871 const PftNode &parent)
872 : ProgramUnit{directive, parent}, routine{directive} {};
873 OpenACCDirectiveUnit(OpenACCDirectiveUnit &&) = default;
874 OpenACCDirectiveUnit(const OpenACCDirectiveUnit &) = delete;
875 const parser::OpenACCRoutineConstruct &routine;
876};
877
879struct Program {
880 using Units = std::variant<FunctionLikeUnit, ModuleLikeUnit, BlockDataUnit,
882
883 Program(semantics::CommonBlockList &&commonBlocks)
884 : commonBlocks{std::move(commonBlocks)} {}
885 Program(Program &&) = default;
886 Program(const Program &) = delete;
887
888 const std::list<Units> &getUnits() const { return units; }
889 std::list<Units> &getUnits() { return units; }
890 const semantics::CommonBlockList &getCommonBlocks() const {
891 return commonBlocks;
892 }
893 ScopeVariableListMap &getScopeVariableListMap() {
894 return scopeVariableListMap;
895 }
896
898 LLVM_DUMP_METHOD void dump() const;
899
900private:
901 std::list<Units> units;
902 semantics::CommonBlockList commonBlocks;
903 ScopeVariableListMap scopeVariableListMap; // module and submodule scopes
904};
905
908template <typename T>
909parser::CharBlock stmtSourceLoc(const T &stmt) {
910 return stmt.visit(common::visitors{[](const auto &x) { return x.source; }});
911}
912
914template <typename ParentType, typename A>
915ParentType *getAncestor(A &node) {
916 if (auto *seekedParent = node.parent.template getIf<ParentType>())
917 return seekedParent;
918 return node.parent.visit(common::visitors{
919 [](Program &p) -> ParentType * { return nullptr; },
920 [](auto &p) -> ParentType * { return getAncestor<ParentType>(p); }});
921}
922
924template <typename A>
925ScopeVariableListMap &getScopeVariableListMap(A &node) {
926 Program *pftRoot = getAncestor<Program>(node);
927 assert(pftRoot && "pft must have a root");
928 return pftRoot->getScopeVariableListMap();
929}
930
933void visitAllSymbols(const FunctionLikeUnit &funit,
934 std::function<void(const semantics::Symbol &)> callBack);
935
938void visitAllSymbols(const Evaluation &eval,
939 std::function<void(const semantics::Symbol &)> callBack);
940
944bool isWrappableConstruct(const Evaluation &eval,
945 const semantics::SemanticsContext &semaCtx);
946
947} // namespace Fortran::lower::pft
948
949namespace Fortran::lower {
950class LoweringOptions;
951
960std::unique_ptr<pft::Program>
961createPFT(const parser::Program &root,
962 const Fortran::semantics::SemanticsContext &semanticsContext,
963 const LoweringOptions &loweringOptions);
964
966void dumpPFT(llvm::raw_ostream &outputStream, const pft::Program &pft);
967} // namespace Fortran::lower
968
969#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:48
Definition char-block.h:27
Definition scope.h:68
Definition semantics.h:71
Definition symbol.h:916
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:2233
std::unique_ptr< pft::Program > createPFT(const parser::Program &root, const Fortran::semantics::SemanticsContext &semanticsContext, const LoweringOptions &loweringOptions)
Definition PFTBuilder.cpp:2225
Definition idioms.h:60
Definition PFTBuilder.h:848
LLVM_DUMP_METHOD void dump() const
The BlockDataUnit dump is just the associated symbol table.
Definition PFTBuilder.cpp:2293
Definition PFTBuilder.h:222
FunctionLikeUnit * getOwningProcedure() const
Return the FunctionLikeUnit containing this evaluation (or nullptr).
Definition PFTBuilder.cpp:1767
Evaluation(const A &a, const PftNode &parent)
Construct and Directive ctor.
Definition PFTBuilder.h:234
bool lowerBodyAsWrappedRegion() const
Definition PFTBuilder.cpp:1758
EvaluationList & getNestedEvaluations()
Return nested evaluation list.
Definition PFTBuilder.h:308
Evaluation(const A &a, const PftNode &parent, const parser::CharBlock &position, const std::optional< parser::Label > &label)
General ctor.
Definition PFTBuilder.h:226
Evaluation & nonNopSuccessor() const
Definition PFTBuilder.h:294
constexpr bool isIntermediateConstructStmt() const
Definition PFTBuilder.h:284
constexpr bool isActionStmt() const
Evaluation classification predicates.
Definition PFTBuilder.h:241
bool isUnstructured() const
Definition PFTBuilder.h:361
void markControlFlow(ControlFlow kind)
Definition PFTBuilder.h:346
bool hasNestedEvaluations() const
Return true if this Evaluation has at least one nested evaluation.
Definition PFTBuilder.h:303
void weakenControlFlow(ControlFlow kind)
Definition PFTBuilder.h:355
ControlFlow
Definition PFTBuilder.h:329
@ StructuredWithUnstructuredInternals
Definition PFTBuilder.h:338
@ Structured
Lowered structurally.
Definition PFTBuilder.h:331
@ Unstructured
Lowered as unstructured blocks.
Definition PFTBuilder.h:340
Definition PFTBuilder.h:681
Evaluation * getEntryEval() const
Definition PFTBuilder.h:743
llvm::SmallVector< std::pair< const semantics::Symbol *, Evaluation * >, 1 > entryPointList
Definition PFTBuilder.h:798
HostAssociations & parentHostAssoc()
Definition PFTBuilder.cpp:2130
bool parentHasHostAssoc()
Definition PFTBuilder.cpp:2142
int activeEntry
Current index into entryPointList. Index 0 is the primary entry point.
Definition PFTBuilder.h:800
mlir::Block * finalBlock
Terminal basic block (if any)
Definition PFTBuilder.h:809
std::list< Fortran::semantics::PreservedUseStmt > preservedUseStmts
Preserved USE statements for debug info generation.
Definition PFTBuilder.h:812
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this function like unit.
Definition PFTBuilder.cpp:2149
HostAssociations & getHostAssoc()
Definition PFTBuilder.h:771
IncomingBranchMap incomingBranches
Definition PFTBuilder.h:789
const semantics::Symbol * primaryResult
Definition PFTBuilder.h:803
std::optional< FunctionStatement > beginStmt
Anonymous programs do not have a begin statement.
Definition PFTBuilder.h:780
const semantics::Symbol * getMainProgramSymbol() const
Definition PFTBuilder.h:734
const Fortran::semantics::Scope & getScope() const
Get the function scope.
Definition PFTBuilder.h:777
const semantics::Symbol & getSubprogramSymbol() const
Definition PFTBuilder.h:724
bool parentHasTupleHostAssoc()
Definition PFTBuilder.cpp:2136
Module-like units contain a list of function-like units.
Definition PFTBuilder.h:816
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this module like unit.
Definition PFTBuilder.cpp:2180
std::list< Fortran::semantics::PreservedUseStmt > preservedUseStmts
Preserved USE statements for debug info generation.
Definition PFTBuilder.h:843
const Fortran::semantics::Scope & getScope() const
Get the module scope.
Definition PFTBuilder.cpp:2184
A Program is the top-level root of the PFT.
Definition PFTBuilder.h:879
LLVM_DUMP_METHOD void dump() const
LLVM dump method on a Program.
Definition PFTBuilder.cpp:2238
std::size_t getOffset() const
Get offset of the aggregate inside its scope.
Definition PFTBuilder.h:509
const semantics::Symbol & getNamingSymbol() const
Returns the symbol that gives its name to the aggregate.
Definition PFTBuilder.h:515
const semantics::Symbol * namingSymbol
Symbol that gives its name to the aggregate. Always set by constructor.
Definition PFTBuilder.h:523
const semantics::Symbol * initialValueSymbol
Compiler generated symbol with the aggregate initial value if any.
Definition PFTBuilder.h:525
bool isGlobalAggregate
Is this a global aggregate?
Definition PFTBuilder.h:527
Interval interval
<offset, size> of the aggregate in its scope.
Definition PFTBuilder.h:521
const semantics::Symbol * getInitialValueSymbol() const
Returns symbols holding the aggregate initial value if any.
Definition PFTBuilder.h:511
const semantics::Scope & getOwningScope() const
Scope to which the aggregates belongs to.
Definition PFTBuilder.h:517
Definition PFTBuilder.h:473
Definition PFTBuilder.h:469
bool isAggregateStore() const
Is this an aggregate store?
Definition PFTBuilder.h:560
bool isRuntimeTypeInfoData() const
Is this variable a compiler generated global to describe derived types?
Definition PFTBuilder.cpp:2207
bool isGlobal() const
Is this variable a global?
Definition PFTBuilder.h:565
bool isModuleOrSubmoduleVariable() const
Is this a module or submodule variable?
Definition PFTBuilder.h:571
bool isAlias() const
Definition PFTBuilder.h:602
std::tuple< std::size_t, std::size_t > Interval
<offset, size> pair
Definition PFTBuilder.h:490
bool hasSymbol() const
Only nominal variable have front-end symbols.
Definition PFTBuilder.h:557
const Interval & getInterval() const
Return the interval range of an aggregate store.
Definition PFTBuilder.h:551
const Fortran::semantics::Symbol & getSymbol() const
Return the front-end symbol for a nominal variable.
Definition PFTBuilder.h:536
int getDepth() const
The depth is recorded for nominal variables as a debugging aid.
Definition PFTBuilder.h:641
const AggregateStore & getAggregateStore() const
Return the aggregate store.
Definition PFTBuilder.h:545
Definition parse-tree.h:2033
Definition parse-tree.h:3555
Definition parse-tree.h:3560
Definition parse-tree.h:3565
Definition parse-tree.h:2059
Definition parse-tree.h:2214
Definition parse-tree.h:2205
Definition parse-tree.h:2236
Definition parse-tree.h:3075
Definition parse-tree.h:6021
Definition parse-tree.h:3357
Definition parse-tree.h:2477
Definition parse-tree.h:2465
Definition parse-tree.h:2267
Definition parse-tree.h:2252
Definition parse-tree.h:2736
Definition parse-tree.h:3444
Definition parse-tree.h:2564
Definition parse-tree.h:2283
Definition parse-tree.h:2274
Definition parse-tree.h:2053
Definition parse-tree.h:2379
Definition parse-tree.h:2399
Definition parse-tree.h:2261
Definition parse-tree.h:2618
Definition parse-tree.h:2632
Definition parse-tree.h:2149
Definition parse-tree.h:2184
Definition parse-tree.h:2161
Definition parse-tree.h:2644
Definition parse-tree.h:3377
Definition parse-tree.h:2413
Definition parse-tree.h:2429
Definition parse-tree.h:2392
Definition parse-tree.h:2962
Definition parse-tree.h:2658
Definition parse-tree.h:2983
Definition parse-tree.h:2116
Definition parse-tree.h:3019
Definition parse-tree.h:2362
Definition parse-tree.h:2586
Definition parse-tree.h:5995
Definition parse-tree.h:5857
Definition parse-tree.h:5681
Definition parse-tree.h:2081
Definition parse-tree.h:2836
Definition parse-tree.h:2799
Definition parse-tree.h:2436
Definition parse-tree.h:2500
Definition parse-tree.h:2512
Definition parse-tree.h:2491
Definition parse-tree.h:2546
Definition parse-tree.h:2526
Definition parse-tree.h:3403
Definition parse-tree.h:362
Definition parse-tree.h:2578
Definition parse-tree.h:3061
Definition parse-tree.h:3387
Definition parse-tree.h:2596
Definition parse-tree.h:2609
Definition parse-tree.h:2535
Definition parse-tree.h:2668
Definition parse-tree.h:2100
Definition parse-tree.h:2131
Definition parse-tree.h:2094
Definition parse-tree.h:2821