17#ifndef FORTRAN_LOWER_PFTBUILDER_H
18#define FORTRAN_LOWER_PFTBUILDER_H
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"
32namespace Fortran::lower::pft {
40using ContainedUnit = std::variant<CompilerDirectiveUnit, FunctionLikeUnit>;
41using ContainedUnitList = std::list<ContainedUnit>;
42using EvaluationList = std::list<Evaluation>;
47template <
bool isConst,
typename... A>
48class ReferenceVariantBase {
51 using BaseType = std::conditional_t<isConst, const B, B>;
55 ReferenceVariantBase() =
delete;
56 ReferenceVariantBase(std::variant<Ref<A>...> b) : u(b) {}
58 ReferenceVariantBase(Ref<T> b) : u(b) {}
61 constexpr BaseType<B> &get()
const {
62 return std::get<Ref<B>>(u).get();
65 constexpr BaseType<B> &getStatement()
const {
66 return std::get<Ref<parser::Statement<B>>>(u).get().statement;
69 constexpr BaseType<B> *getIf()
const {
70 const Ref<B> *ptr = std::get_if<Ref<B>>(&u);
71 return ptr ? &ptr->get() :
nullptr;
74 constexpr bool isA()
const {
75 return std::holds_alternative<Ref<B>>(u);
77 template <
typename VISITOR>
78 constexpr auto visit(VISITOR &&visitor)
const {
79 return Fortran::common::visit(
85 std::variant<Ref<A>...> u;
87template <
typename... A>
89template <
typename... A>
99using ActionStmts = std::tuple<
115using OtherStmts = std::tuple<parser::EntryStmt, parser::FormatStmt>;
117using ConstructStmts = std::tuple<
129 std::tuple<parser::EndProgramStmt, parser::EndFunctionStmt,
130 parser::EndSubroutineStmt, parser::EndMpSubprogramStmt>;
151static constexpr bool isActionStmt{common::HasMember<A, ActionStmts>};
154static constexpr bool isOtherStmt{common::HasMember<A, OtherStmts>};
157static constexpr bool isConstructStmt{common::HasMember<A, ConstructStmts>};
160static constexpr bool isEndStmt{common::HasMember<A, EndStmts>};
163static constexpr bool isConstruct{common::HasMember<A, Constructs>};
166static constexpr bool isDirective{common::HasMember<A, Directives>};
169static constexpr bool isDeclConstruct{common::HasMember<A, DeclConstructs>};
172static constexpr bool isIntermediateConstructStmt{common::HasMember<
173 A, std::tuple<parser::CaseStmt, parser::ElseIfStmt, parser::ElseStmt,
174 parser::SelectRankCaseStmt, parser::TypeGuardStmt>>};
177static constexpr bool isNopConstructStmt{common::HasMember<
178 A, std::tuple<parser::CaseStmt, parser::ElseIfStmt, parser::ElseStmt,
179 parser::EndIfStmt, parser::SelectRankCaseStmt,
180 parser::TypeGuardStmt>>};
183static constexpr bool isExecutableDirective{common::HasMember<
184 A, std::tuple<parser::CompilerDirective, parser::OpenACCConstruct,
185 parser::OpenMPConstruct, parser::CUFKernelDoConstruct>>};
188static constexpr bool isOpenMPDirective{
189 common::HasMember<A, std::tuple<parser::OpenMPConstruct,
190 parser::OpenMPDeclarativeConstruct>>};
193static constexpr bool isFunctionLike{common::HasMember<
194 A, std::tuple<parser::MainProgram, parser::FunctionSubprogram,
195 parser::SubroutineSubprogram,
196 parser::SeparateModuleSubprogram>>};
200template <
typename... A>
202 using type = ReferenceVariant<A...>;
204template <
typename... A>
206 using type = ReferenceVariant<A...>;
211using EvaluationTuple =
212 common::CombineTuples<ActionStmts, OtherStmts, ConstructStmts, EndStmts,
213 Constructs, Directives>;
217using EvaluationVariant = MakeReferenceVariant<EvaluationTuple>;
224 template <
typename A>
227 const std::optional<parser::Label> &label)
228 : EvaluationVariant{a}, parent{parent}, position{position}, label{label} {
232 template <
typename A>
234 : EvaluationVariant{a}, parent{parent} {
235 static_assert(pft::isConstruct<A> || pft::isDirective<A>,
236 "must be a construct or directive");
242 [](
auto &r) {
return pft::isActionStmt<std::decay_t<
decltype(r)>>; }});
244 constexpr bool isOtherStmt()
const {
246 [](
auto &r) {
return pft::isOtherStmt<std::decay_t<
decltype(r)>>; }});
248 constexpr bool isConstructStmt()
const {
249 return visit(common::visitors{[](
auto &r) {
250 return pft::isConstructStmt<std::decay_t<
decltype(r)>>;
253 constexpr bool isEndStmt()
const {
254 return visit(common::visitors{
255 [](
auto &r) {
return pft::isEndStmt<std::decay_t<
decltype(r)>>; }});
257 constexpr bool isConstruct()
const {
258 return visit(common::visitors{
259 [](
auto &r) {
return pft::isConstruct<std::decay_t<
decltype(r)>>; }});
261 constexpr bool isDirective()
const {
262 return visit(common::visitors{
263 [](
auto &r) {
return pft::isDirective<std::decay_t<
decltype(r)>>; }});
265 constexpr bool isNopConstructStmt()
const {
266 return visit(common::visitors{[](
auto &r) {
267 return pft::isNopConstructStmt<std::decay_t<
decltype(r)>>;
270 constexpr bool isExecutableDirective()
const {
271 return visit(common::visitors{[](
auto &r) {
272 return pft::isExecutableDirective<std::decay_t<
decltype(r)>>;
275 constexpr bool isOpenMPDirective()
const {
276 return visit(common::visitors{[](
auto &r) {
277 return pft::isOpenMPDirective<std::decay_t<
decltype(r)>>;
285 return pft::isIntermediateConstructStmt<std::decay_t<
decltype(r)>>;
289 LLVM_DUMP_METHOD
void dump()
const;
295 if (successor && successor->isNopConstructStmt())
296 successor = successor->parentConstruct->constructExit;
297 assert(successor &&
"missing successor");
303 return evaluationList && !evaluationList->empty();
308 assert(evaluationList &&
"no nested evaluations");
309 return *evaluationList;
314 return evaluationList->front();
319 return evaluationList->back();
325 bool lowerAsStructured()
const;
326 bool lowerAsUnstructured()
const;
327 bool forceAsUnstructured()
const;
364 std::optional<parser::Label> label{};
365 std::unique_ptr<EvaluationList> evaluationList;
367 llvm::SmallVector<const parser::CompilerDirective *, 1> dirs;
374 llvm::SmallVector<Evaluation *, 0> extraControlSuccessors;
376 bool isNewBlock{
false};
377 bool isUnstructured{
false};
378 bool negateCondition{
false};
379 bool activeConstruct{
false};
382 bool skipNextLowering{
false};
383 mlir::Block *block{
nullptr};
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;
426 : symbol{symbol}, depth{depth}, global{global} {}
429 bool isGlobal()
const {
return global; }
437 std::size_t aliasOffset{};
441 using Interval = std::tuple<std::size_t, std::size_t>;
446 struct AggregateStore {
449 bool isGlobal =
false)
454 :
interval{initialValueSym.offset(), initialValueSym.size()},
483 : var{
Nominal(&sym, depth, global)} {}
484 explicit Variable(AggregateStore &&istore) : var{std::move(istore)} {}
488 assert(
hasSymbol() &&
"variable is not nominal");
489 return *std::get<Nominal>(var).symbol;
498 return std::get<AggregateStore>(var);
504 return std::get<AggregateStore>(var).interval;
508 bool hasSymbol()
const {
return std::holds_alternative<Nominal>(var); }
512 return std::holds_alternative<AggregateStore>(var);
517 return Fortran::common::visit([](
const auto &x) {
return x.isGlobal(); },
524 return scope && scope->kind() == Fortran::semantics::Scope::Kind::Module;
528 return Fortran::common::visit(
530 [](
const Nominal &x) {
return &x.symbol->GetUltimate().owner(); },
531 [](
const AggregateStore &agg) {
return &agg.getOwningScope(); }},
535 bool isHeapAlloc()
const {
536 if (
auto *s = std::get_if<Nominal>(&var))
540 bool isPointer()
const {
541 if (
auto *s = std::get_if<Nominal>(&var))
545 bool isTarget()
const {
546 if (
auto *s = std::get_if<Nominal>(&var))
554 if (
auto *s = std::get_if<Nominal>(&var))
558 std::size_t getAliasOffset()
const {
559 if (
auto *s = std::get_if<Nominal>(&var))
560 return s->aliasOffset;
563 void setAlias(std::size_t offset) {
564 if (
auto *s = std::get_if<Nominal>(&var)) {
566 s->aliasOffset = offset;
568 llvm_unreachable(
"not a nominal var");
572 void setHeapAlloc(
bool to =
true) {
573 if (
auto *s = std::get_if<Nominal>(&var))
576 llvm_unreachable(
"not a nominal var");
578 void setPointer(
bool to =
true) {
579 if (
auto *s = std::get_if<Nominal>(&var))
582 llvm_unreachable(
"not a nominal var");
584 void setTarget(
bool to =
true) {
585 if (
auto *s = std::get_if<Nominal>(&var))
588 llvm_unreachable(
"not a nominal var");
593 if (
auto *s = std::get_if<Nominal>(&var))
598 LLVM_DUMP_METHOD
void dump()
const;
601 std::variant<Nominal, AggregateStore> var;
604using VariableList = std::vector<Variable>;
605using ScopeVariableListMap =
606 std::map<const Fortran::semantics::Scope *, VariableList>;
611 ScopeVariableListMap &map);
621struct FunctionLikeUnit;
626VariableList getHostModuleVariableList(
const FunctionLikeUnit &funit);
628void dump(VariableList &, std::string s = {});
632struct FunctionLikeUnit :
public ProgramUnit {
634 using FunctionStatement =
635 ReferenceVariant<parser::Statement<parser::ProgramStmt>,
656 FunctionLikeUnit(FunctionLikeUnit &&) =
default;
657 FunctionLikeUnit(
const FunctionLikeUnit &) =
delete;
659 bool isMainProgram()
const {
666 void setActiveEntry(
int entryIndex) {
667 assert(entryIndex >= 0 && entryIndex < (
int)
entryPointList.size() &&
668 "invalid entry point index");
678 llvm::report_fatal_error(
679 "not inside a procedure; do not call on main program.");
686 if (!isMainProgram()) {
687 llvm::report_fatal_error(
"call only on main program.");
702 void setHostAssociatedSymbols(
703 const llvm::SetVector<const semantics::Symbol *> &symbols) {
725 LLVM_DUMP_METHOD
void dump()
const;
732 FunctionStatement endStmt;
734 LabelEvalMap labelEvaluationMap;
735 SymbolLabelMap assignSymbolLabelMap;
736 ContainedUnitList containedUnitList;
737 EvaluationList evaluationList;
750 bool hasIeeeAccess{
false};
751 bool mayModifyHaltingMode{
false};
752 bool mayModifyRoundingMode{
false};
753 bool mayModifyUnderflowMode{
false};
762struct ModuleLikeUnit :
public ProgramUnit {
764 using ModuleStatement =
765 ReferenceVariant<parser::Statement<parser::ModuleStmt>,
772 ~ModuleLikeUnit() =
default;
773 ModuleLikeUnit(ModuleLikeUnit &&) =
default;
774 ModuleLikeUnit(
const ModuleLikeUnit &) =
delete;
776 LLVM_DUMP_METHOD
void dump()
const;
784 ModuleStatement beginStmt;
785 ModuleStatement endStmt;
786 ContainedUnitList containedUnitList;
787 EvaluationList evaluationList;
794struct BlockDataUnit :
public ProgramUnit {
797 BlockDataUnit(BlockDataUnit &&) =
default;
798 BlockDataUnit(
const BlockDataUnit &) =
delete;
800 LLVM_DUMP_METHOD
void dump()
const;
806struct CompilerDirectiveUnit :
public ProgramUnit {
808 const PftNode &parent)
809 : ProgramUnit{directive, parent} {};
810 CompilerDirectiveUnit(CompilerDirectiveUnit &&) =
default;
811 CompilerDirectiveUnit(
const CompilerDirectiveUnit &) =
delete;
815struct OpenACCDirectiveUnit :
public ProgramUnit {
817 const PftNode &parent)
818 : ProgramUnit{directive, parent}, routine{directive} {};
819 OpenACCDirectiveUnit(OpenACCDirectiveUnit &&) =
default;
820 OpenACCDirectiveUnit(
const OpenACCDirectiveUnit &) =
delete;
829 Program(semantics::CommonBlockList &&commonBlocks)
830 : commonBlocks{std::move(commonBlocks)} {}
831 Program(Program &&) =
default;
832 Program(
const Program &) =
delete;
834 const std::list<Units> &getUnits()
const {
return units; }
835 std::list<Units> &getUnits() {
return units; }
836 const semantics::CommonBlockList &getCommonBlocks()
const {
839 ScopeVariableListMap &getScopeVariableListMap() {
840 return scopeVariableListMap;
844 LLVM_DUMP_METHOD
void dump()
const;
847 std::list<Units> units;
848 semantics::CommonBlockList commonBlocks;
849 ScopeVariableListMap scopeVariableListMap;
856 return stmt.visit(
common::visitors{[](
const auto &x) {
return x.source; }});
860template <
typename ParentType,
typename A>
861ParentType *getAncestor(A &node) {
862 if (
auto *seekedParent = node.parent.template getIf<ParentType>())
864 return node.parent.visit(common::visitors{
865 [](Program &p) -> ParentType * {
return nullptr; },
866 [](
auto &p) -> ParentType * {
return getAncestor<ParentType>(p); }});
871ScopeVariableListMap &getScopeVariableListMap(A &node) {
872 Program *pftRoot = getAncestor<Program>(node);
873 assert(pftRoot &&
"pft must have a root");
874 return pftRoot->getScopeVariableListMap();
880 std::function<
void(
const semantics::Symbol &)> callBack);
885 std::function<
void(
const semantics::Symbol &)> callBack);
890bool isWrappableConstruct(
const Evaluation &eval,
891 const semantics::SemanticsContext &semaCtx);
906std::unique_ptr<pft::Program>
908 const Fortran::semantics::SemanticsContext &semanticsContext,
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 PFTBuilder.h:48
Definition char-block.h:26
Definition semantics.h:67
Definition ParserActions.h:24
void dumpPFT(llvm::raw_ostream &outputStream, const pft::Program &pft)
Dumper for displaying a PFT.
Definition PFTBuilder.cpp:2114
std::unique_ptr< pft::Program > createPFT(const parser::Program &root, const Fortran::semantics::SemanticsContext &semanticsContext, const LoweringOptions &loweringOptions)
Definition PFTBuilder.cpp:2106
Definition PFTBuilder.h:794
LLVM_DUMP_METHOD void dump() const
The BlockDataUnit dump is just the associated symbol table.
Definition PFTBuilder.cpp:2174
Definition PFTBuilder.h:806
Definition PFTBuilder.h:221
FunctionLikeUnit * getOwningProcedure() const
Return the FunctionLikeUnit containing this evaluation (or nullptr).
Definition PFTBuilder.cpp:1657
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:744
HostAssociations & parentHostAssoc()
Definition PFTBuilder.cpp:2020
bool parentHasHostAssoc()
Definition PFTBuilder.cpp:2032
int activeEntry
Current index into entryPointList. Index 0 is the primary entry point.
Definition PFTBuilder.h:746
mlir::Block * finalBlock
Terminal basic block (if any)
Definition PFTBuilder.h:755
std::list< Fortran::semantics::PreservedUseStmt > preservedUseStmts
Preserved USE statements for debug info generation.
Definition PFTBuilder.h:758
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this function like unit.
Definition PFTBuilder.cpp:2039
HostAssociations & getHostAssoc()
Definition PFTBuilder.h:722
const semantics::Symbol * primaryResult
Definition PFTBuilder.h:749
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:2026
Definition PFTBuilder.h:199
Module-like units contain a list of function-like units.
Definition PFTBuilder.h:762
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this module like unit.
Definition PFTBuilder.cpp:2061
std::list< Fortran::semantics::PreservedUseStmt > preservedUseStmts
Preserved USE statements for debug info generation.
Definition PFTBuilder.h:789
const Fortran::semantics::Scope & getScope() const
Get the module scope.
Definition PFTBuilder.cpp:2065
Definition PFTBuilder.h:815
A Program is the top-level root of the PFT.
Definition PFTBuilder.h:825
LLVM_DUMP_METHOD void dump() const
LLVM dump method on a Program.
Definition PFTBuilder.cpp:2119
Definition PFTBuilder.h:446
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:2088
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:2022
Definition parse-tree.h:3544
Definition parse-tree.h:3549
Definition parse-tree.h:3554
Definition parse-tree.h:2048
Definition parse-tree.h:2203
Definition parse-tree.h:2194
Definition parse-tree.h:2225
Definition parse-tree.h:3064
Definition parse-tree.h:6010
Definition parse-tree.h:3346
Definition parse-tree.h:2466
Definition parse-tree.h:2454
Definition parse-tree.h:2256
Definition parse-tree.h:2241
Definition parse-tree.h:2725
Definition parse-tree.h:3433
Definition parse-tree.h:2553
Definition parse-tree.h:2272
Definition parse-tree.h:2263
Definition parse-tree.h:2042
Definition parse-tree.h:2368
Definition parse-tree.h:2388
Definition parse-tree.h:2250
Definition parse-tree.h:2607
Definition parse-tree.h:2621
Definition parse-tree.h:2138
Definition parse-tree.h:2173
Definition parse-tree.h:2150
Definition parse-tree.h:3366
Definition parse-tree.h:2402
Definition parse-tree.h:2418
Definition parse-tree.h:2381
Definition parse-tree.h:2951
Definition parse-tree.h:2647
Definition parse-tree.h:2972
Definition parse-tree.h:2105
Definition parse-tree.h:3008
Definition parse-tree.h:2351
Definition parse-tree.h:2575
Definition parse-tree.h:5984
Definition parse-tree.h:5955
Definition parse-tree.h:5846
Definition parse-tree.h:5670
Definition parse-tree.h:5522
Definition parse-tree.h:2070
Definition parse-tree.h:2825
Definition parse-tree.h:2788
Definition parse-tree.h:2425
Definition parse-tree.h:2489
Definition parse-tree.h:2501
Definition parse-tree.h:2480
Definition parse-tree.h:2535
Definition parse-tree.h:2515
Definition parse-tree.h:3392
Definition parse-tree.h:362
Definition parse-tree.h:2567
Definition parse-tree.h:3050
Definition parse-tree.h:3376
Definition parse-tree.h:2585
Definition parse-tree.h:2598
Definition parse-tree.h:2524
Definition parse-tree.h:2657
Definition parse-tree.h:2089
Definition parse-tree.h:2120
Definition parse-tree.h:2083
Definition parse-tree.h:2810