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 // The enclosing evaluation-list traversal should skip this evaluation once
381 // because directive lowering already consumed it.
382 bool skipNextLowering{false};
383 mlir::Block *block{nullptr}; // isNewBlock block (ActionStmt, ConstructStmt)
384 int printIndex{0}; // (ActionStmt, ConstructStmt) evaluation index for dumps
385};
386
387using ProgramVariant =
388 ReferenceVariant<parser::MainProgram, parser::FunctionSubprogram,
389 parser::SubroutineSubprogram, parser::Module,
390 parser::Submodule, parser::SeparateModuleSubprogram,
391 parser::BlockData, parser::CompilerDirective,
392 parser::OpenACCRoutineConstruct>;
395struct ProgramUnit : ProgramVariant {
396 template <typename A>
397 ProgramUnit(const A &p, const PftNode &parent)
398 : ProgramVariant{p}, parent{parent} {}
399 ProgramUnit(ProgramUnit &&) = default;
400 ProgramUnit(const ProgramUnit &) = delete;
401
402 PftNode parent;
403};
404
420struct Variable {
424 struct Nominal {
425 Nominal(const semantics::Symbol *symbol, int depth, bool global)
426 : symbol{symbol}, depth{depth}, global{global} {}
427 const semantics::Symbol *symbol{};
428
429 bool isGlobal() const { return global; }
430
431 int depth{};
432 bool global{};
433 bool heapAlloc{}; // variable needs deallocation on exit
434 bool pointer{};
435 bool target{};
436 bool aliaser{}; // participates in EQUIVALENCE union
437 std::size_t aliasOffset{};
438 };
439
441 using Interval = std::tuple<std::size_t, std::size_t>;
442
446 struct AggregateStore {
447 AggregateStore(Interval &&interval,
448 const Fortran::semantics::Symbol &namingSym,
449 bool isGlobal = false)
450 : interval{std::move(interval)}, namingSymbol{&namingSym},
451 isGlobalAggregate{isGlobal} {}
452 AggregateStore(const semantics::Symbol &initialValueSym,
453 const semantics::Symbol &namingSym, bool isGlobal = false)
454 : interval{initialValueSym.offset(), initialValueSym.size()},
455 namingSymbol{&namingSym}, initialValueSymbol{&initialValueSym},
456 isGlobalAggregate{isGlobal} {};
457
458 bool isGlobal() const { return isGlobalAggregate; }
460 std::size_t getOffset() const { return std::get<0>(interval); }
465
469 return getNamingSymbol().owner();
470 }
471
479 };
480
481 explicit Variable(const Fortran::semantics::Symbol &sym, bool global = false,
482 int depth = 0)
483 : var{Nominal(&sym, depth, global)} {}
484 explicit Variable(AggregateStore &&istore) : var{std::move(istore)} {}
485
488 assert(hasSymbol() && "variable is not nominal");
489 return *std::get<Nominal>(var).symbol;
490 }
491
493 bool isRuntimeTypeInfoData() const;
494
497 assert(isAggregateStore());
498 return std::get<AggregateStore>(var);
499 }
500
502 const Interval &getInterval() const {
503 assert(isAggregateStore());
504 return std::get<AggregateStore>(var).interval;
505 }
506
508 bool hasSymbol() const { return std::holds_alternative<Nominal>(var); }
509
511 bool isAggregateStore() const {
512 return std::holds_alternative<AggregateStore>(var);
513 }
514
516 bool isGlobal() const {
517 return Fortran::common::visit([](const auto &x) { return x.isGlobal(); },
518 var);
519 }
520
523 const semantics::Scope *scope = getOwningScope();
524 return scope && scope->kind() == Fortran::semantics::Scope::Kind::Module;
525 }
526
527 const Fortran::semantics::Scope *getOwningScope() const {
528 return Fortran::common::visit(
530 [](const Nominal &x) { return &x.symbol->GetUltimate().owner(); },
531 [](const AggregateStore &agg) { return &agg.getOwningScope(); }},
532 var);
533 }
534
535 bool isHeapAlloc() const {
536 if (auto *s = std::get_if<Nominal>(&var))
537 return s->heapAlloc;
538 return false;
539 }
540 bool isPointer() const {
541 if (auto *s = std::get_if<Nominal>(&var))
542 return s->pointer;
543 return false;
544 }
545 bool isTarget() const {
546 if (auto *s = std::get_if<Nominal>(&var))
547 return s->target;
548 return false;
549 }
550
553 bool isAlias() const {
554 if (auto *s = std::get_if<Nominal>(&var))
555 return s->aliaser;
556 return false;
557 }
558 std::size_t getAliasOffset() const {
559 if (auto *s = std::get_if<Nominal>(&var))
560 return s->aliasOffset;
561 return 0;
562 }
563 void setAlias(std::size_t offset) {
564 if (auto *s = std::get_if<Nominal>(&var)) {
565 s->aliaser = true;
566 s->aliasOffset = offset;
567 } else {
568 llvm_unreachable("not a nominal var");
569 }
570 }
571
572 void setHeapAlloc(bool to = true) {
573 if (auto *s = std::get_if<Nominal>(&var))
574 s->heapAlloc = to;
575 else
576 llvm_unreachable("not a nominal var");
577 }
578 void setPointer(bool to = true) {
579 if (auto *s = std::get_if<Nominal>(&var))
580 s->pointer = to;
581 else
582 llvm_unreachable("not a nominal var");
583 }
584 void setTarget(bool to = true) {
585 if (auto *s = std::get_if<Nominal>(&var))
586 s->target = to;
587 else
588 llvm_unreachable("not a nominal var");
589 }
590
592 int getDepth() const {
593 if (auto *s = std::get_if<Nominal>(&var))
594 return s->depth;
595 return 0;
596 }
597
598 LLVM_DUMP_METHOD void dump() const;
599
600private:
601 std::variant<Nominal, AggregateStore> var;
602};
603
604using VariableList = std::vector<Variable>;
605using ScopeVariableListMap =
606 std::map<const Fortran::semantics::Scope *, VariableList>;
607
610const VariableList &getScopeVariableList(const Fortran::semantics::Scope &scope,
611 ScopeVariableListMap &map);
612
615VariableList getScopeVariableList(const Fortran::semantics::Scope &scope);
616
619VariableList getDependentVariableList(const Fortran::semantics::Symbol &);
620
621struct FunctionLikeUnit;
626VariableList getHostModuleVariableList(const FunctionLikeUnit &funit);
627
628void dump(VariableList &, std::string s = {}); // `s` is an optional dump label
629
632struct FunctionLikeUnit : public ProgramUnit {
633 // wrapper statements for function-like syntactic structures
634 using FunctionStatement =
635 ReferenceVariant<parser::Statement<parser::ProgramStmt>,
643
644 FunctionLikeUnit(
645 const parser::MainProgram &f, const PftNode &parent,
646 const Fortran::semantics::SemanticsContext &semanticsContext);
647 FunctionLikeUnit(
648 const parser::FunctionSubprogram &f, const PftNode &parent,
649 const Fortran::semantics::SemanticsContext &semanticsContext);
650 FunctionLikeUnit(
651 const parser::SubroutineSubprogram &f, const PftNode &parent,
652 const Fortran::semantics::SemanticsContext &semanticsContext);
653 FunctionLikeUnit(
654 const parser::SeparateModuleSubprogram &f, const PftNode &parent,
655 const Fortran::semantics::SemanticsContext &semanticsContext);
656 FunctionLikeUnit(FunctionLikeUnit &&) = default;
657 FunctionLikeUnit(const FunctionLikeUnit &) = delete;
658
659 bool isMainProgram() const {
660 return endStmt.isA<parser::Statement<parser::EndProgramStmt>>();
661 }
662
665
666 void setActiveEntry(int entryIndex) {
667 assert(entryIndex >= 0 && entryIndex < (int)entryPointList.size() &&
668 "invalid entry point index");
669 activeEntry = entryIndex;
670 }
671
676 const semantics::Symbol *symbol = entryPointList[activeEntry].first;
677 if (!symbol)
678 llvm::report_fatal_error(
679 "not inside a procedure; do not call on main program.");
680 return *symbol;
681 }
682
686 if (!isMainProgram()) {
687 llvm::report_fatal_error("call only on main program.");
688 }
689 return entryPointList[activeEntry].first;
690 }
691
695 return entryPointList[activeEntry].second;
696 }
697
698 //===--------------------------------------------------------------------===//
699 // Host associations
700 //===--------------------------------------------------------------------===//
701
702 void setHostAssociatedSymbols(
703 const llvm::SetVector<const semantics::Symbol *> &symbols) {
704 hostAssociations.addSymbolsToBind(symbols, getScope());
705 }
706
710
715
718 bool parentHasHostAssoc();
719
722 HostAssociations &getHostAssoc() { return hostAssociations; }
723 const HostAssociations &getHostAssoc() const { return hostAssociations; };
724
725 LLVM_DUMP_METHOD void dump() const;
726
728 const Fortran::semantics::Scope &getScope() const { return *scope; }
729
731 std::optional<FunctionStatement> beginStmt;
732 FunctionStatement endStmt;
733 const semantics::Scope *scope;
734 LabelEvalMap labelEvaluationMap;
735 SymbolLabelMap assignSymbolLabelMap;
740 IncomingBranchMap incomingBranches;
741 ContainedUnitList containedUnitList;
742 EvaluationList evaluationList;
749 entryPointList{std::pair{nullptr, nullptr}};
751 int activeEntry = 0;
755 bool hasIeeeAccess{false};
756 bool mayModifyHaltingMode{false};
757 bool mayModifyRoundingMode{false};
758 bool mayModifyUnderflowMode{false};
760 mlir::Block *finalBlock{};
761 HostAssociations hostAssociations;
763 std::list<Fortran::semantics::PreservedUseStmt> preservedUseStmts;
764};
765
767struct ModuleLikeUnit : public ProgramUnit {
768 // wrapper statements for module-like syntactic structures
769 using ModuleStatement =
770 ReferenceVariant<parser::Statement<parser::ModuleStmt>,
774
775 ModuleLikeUnit(const parser::Module &m, const PftNode &parent);
776 ModuleLikeUnit(const parser::Submodule &m, const PftNode &parent);
777 ~ModuleLikeUnit() = default;
778 ModuleLikeUnit(ModuleLikeUnit &&) = default;
779 ModuleLikeUnit(const ModuleLikeUnit &) = delete;
780
781 LLVM_DUMP_METHOD void dump() const;
782
785
787 const Fortran::semantics::Scope &getScope() const;
788
789 ModuleStatement beginStmt;
790 ModuleStatement endStmt;
791 ContainedUnitList containedUnitList;
792 EvaluationList evaluationList;
794 std::list<Fortran::semantics::PreservedUseStmt> preservedUseStmts;
795};
796
799struct BlockDataUnit : public ProgramUnit {
800 BlockDataUnit(const parser::BlockData &bd, const PftNode &parent,
801 const Fortran::semantics::SemanticsContext &semanticsContext);
802 BlockDataUnit(BlockDataUnit &&) = default;
803 BlockDataUnit(const BlockDataUnit &) = delete;
804
805 LLVM_DUMP_METHOD void dump() const;
806
807 const Fortran::semantics::Scope &symTab; // symbol table
808};
809
810// Top level compiler directives
811struct CompilerDirectiveUnit : public ProgramUnit {
812 CompilerDirectiveUnit(const parser::CompilerDirective &directive,
813 const PftNode &parent)
814 : ProgramUnit{directive, parent} {};
815 CompilerDirectiveUnit(CompilerDirectiveUnit &&) = default;
816 CompilerDirectiveUnit(const CompilerDirectiveUnit &) = delete;
817};
818
819// Top level OpenACC routine directives
820struct OpenACCDirectiveUnit : public ProgramUnit {
821 OpenACCDirectiveUnit(const parser::OpenACCRoutineConstruct &directive,
822 const PftNode &parent)
823 : ProgramUnit{directive, parent}, routine{directive} {};
824 OpenACCDirectiveUnit(OpenACCDirectiveUnit &&) = default;
825 OpenACCDirectiveUnit(const OpenACCDirectiveUnit &) = delete;
826 const parser::OpenACCRoutineConstruct &routine;
827};
828
830struct Program {
831 using Units = std::variant<FunctionLikeUnit, ModuleLikeUnit, BlockDataUnit,
833
834 Program(semantics::CommonBlockList &&commonBlocks)
835 : commonBlocks{std::move(commonBlocks)} {}
836 Program(Program &&) = default;
837 Program(const Program &) = delete;
838
839 const std::list<Units> &getUnits() const { return units; }
840 std::list<Units> &getUnits() { return units; }
841 const semantics::CommonBlockList &getCommonBlocks() const {
842 return commonBlocks;
843 }
844 ScopeVariableListMap &getScopeVariableListMap() {
845 return scopeVariableListMap;
846 }
847
849 LLVM_DUMP_METHOD void dump() const;
850
851private:
852 std::list<Units> units;
853 semantics::CommonBlockList commonBlocks;
854 ScopeVariableListMap scopeVariableListMap; // module and submodule scopes
855};
856
859template <typename T>
860static parser::CharBlock stmtSourceLoc(const T &stmt) {
861 return stmt.visit(common::visitors{[](const auto &x) { return x.source; }});
862}
863
865template <typename ParentType, typename A>
866ParentType *getAncestor(A &node) {
867 if (auto *seekedParent = node.parent.template getIf<ParentType>())
868 return seekedParent;
869 return node.parent.visit(common::visitors{
870 [](Program &p) -> ParentType * { return nullptr; },
871 [](auto &p) -> ParentType * { return getAncestor<ParentType>(p); }});
872}
873
875template <typename A>
876ScopeVariableListMap &getScopeVariableListMap(A &node) {
877 Program *pftRoot = getAncestor<Program>(node);
878 assert(pftRoot && "pft must have a root");
879 return pftRoot->getScopeVariableListMap();
880}
881
884void visitAllSymbols(const FunctionLikeUnit &funit,
885 std::function<void(const semantics::Symbol &)> callBack);
886
889void visitAllSymbols(const Evaluation &eval,
890 std::function<void(const semantics::Symbol &)> callBack);
891
895bool isWrappableConstruct(const Evaluation &eval,
896 const semantics::SemanticsContext &semaCtx);
897
898} // namespace Fortran::lower::pft
899
900namespace Fortran::lower {
901class LoweringOptions;
902
911std::unique_ptr<pft::Program>
912createPFT(const parser::Program &root,
913 const Fortran::semantics::SemanticsContext &semanticsContext,
914 const LoweringOptions &loweringOptions);
915
917void dumpPFT(llvm::raw_ostream &outputStream, const pft::Program &pft);
918} // namespace Fortran::lower
919
920#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:26
Definition scope.h:68
Definition semantics.h:67
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:2197
std::unique_ptr< pft::Program > createPFT(const parser::Program &root, const Fortran::semantics::SemanticsContext &semanticsContext, const LoweringOptions &loweringOptions)
Definition PFTBuilder.cpp:2189
Definition idioms.h:60
Definition PFTBuilder.h:799
LLVM_DUMP_METHOD void dump() const
The BlockDataUnit dump is just the associated symbol table.
Definition PFTBuilder.cpp:2257
Definition PFTBuilder.h:221
FunctionLikeUnit * getOwningProcedure() const
Return the FunctionLikeUnit containing this evaluation (or nullptr).
Definition PFTBuilder.cpp:1731
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:632
Evaluation * getEntryEval() const
Definition PFTBuilder.h:694
llvm::SmallVector< std::pair< const semantics::Symbol *, Evaluation * >, 1 > entryPointList
Definition PFTBuilder.h:749
HostAssociations & parentHostAssoc()
Definition PFTBuilder.cpp:2094
bool parentHasHostAssoc()
Definition PFTBuilder.cpp:2106
int activeEntry
Current index into entryPointList. Index 0 is the primary entry point.
Definition PFTBuilder.h:751
mlir::Block * finalBlock
Terminal basic block (if any)
Definition PFTBuilder.h:760
std::list< Fortran::semantics::PreservedUseStmt > preservedUseStmts
Preserved USE statements for debug info generation.
Definition PFTBuilder.h:763
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this function like unit.
Definition PFTBuilder.cpp:2113
HostAssociations & getHostAssoc()
Definition PFTBuilder.h:722
IncomingBranchMap incomingBranches
Definition PFTBuilder.h:740
const semantics::Symbol * primaryResult
Definition PFTBuilder.h:754
std::optional< FunctionStatement > beginStmt
Anonymous programs do not have a begin statement.
Definition PFTBuilder.h:731
const semantics::Symbol * getMainProgramSymbol() const
Definition PFTBuilder.h:685
const Fortran::semantics::Scope & getScope() const
Get the function scope.
Definition PFTBuilder.h:728
const semantics::Symbol & getSubprogramSymbol() const
Definition PFTBuilder.h:675
bool parentHasTupleHostAssoc()
Definition PFTBuilder.cpp:2100
Module-like units contain a list of function-like units.
Definition PFTBuilder.h:767
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this module like unit.
Definition PFTBuilder.cpp:2144
std::list< Fortran::semantics::PreservedUseStmt > preservedUseStmts
Preserved USE statements for debug info generation.
Definition PFTBuilder.h:794
const Fortran::semantics::Scope & getScope() const
Get the module scope.
Definition PFTBuilder.cpp:2148
A Program is the top-level root of the PFT.
Definition PFTBuilder.h:830
LLVM_DUMP_METHOD void dump() const
LLVM dump method on a Program.
Definition PFTBuilder.cpp:2202
std::size_t getOffset() const
Get offset of the aggregate inside its scope.
Definition PFTBuilder.h:460
const semantics::Symbol & getNamingSymbol() const
Returns the symbol that gives its name to the aggregate.
Definition PFTBuilder.h:466
const semantics::Symbol * namingSymbol
Symbol that gives its name to the aggregate. Always set by constructor.
Definition PFTBuilder.h:474
const semantics::Symbol * initialValueSymbol
Compiler generated symbol with the aggregate initial value if any.
Definition PFTBuilder.h:476
bool isGlobalAggregate
Is this a global aggregate?
Definition PFTBuilder.h:478
Interval interval
<offset, size> of the aggregate in its scope.
Definition PFTBuilder.h:472
const semantics::Symbol * getInitialValueSymbol() const
Returns symbols holding the aggregate initial value if any.
Definition PFTBuilder.h:462
const semantics::Scope & getOwningScope() const
Scope to which the aggregates belongs to.
Definition PFTBuilder.h:468
Definition PFTBuilder.h:424
Definition PFTBuilder.h:420
bool isAggregateStore() const
Is this an aggregate store?
Definition PFTBuilder.h:511
bool isRuntimeTypeInfoData() const
Is this variable a compiler generated global to describe derived types?
Definition PFTBuilder.cpp:2171
bool isGlobal() const
Is this variable a global?
Definition PFTBuilder.h:516
bool isModuleOrSubmoduleVariable() const
Is this a module or submodule variable?
Definition PFTBuilder.h:522
bool isAlias() const
Definition PFTBuilder.h:553
std::tuple< std::size_t, std::size_t > Interval
<offset, size> pair
Definition PFTBuilder.h:441
bool hasSymbol() const
Only nominal variable have front-end symbols.
Definition PFTBuilder.h:508
const Interval & getInterval() const
Return the interval range of an aggregate store.
Definition PFTBuilder.h:502
const Fortran::semantics::Symbol & getSymbol() const
Return the front-end symbol for a nominal variable.
Definition PFTBuilder.h:487
int getDepth() const
The depth is recorded for nominal variables as a debugging aid.
Definition PFTBuilder.h:592
const AggregateStore & getAggregateStore() const
Return the aggregate store.
Definition PFTBuilder.h:496
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