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;
741 ContainedUnitList containedUnitList;
742 EvaluationList evaluationList;
755 bool hasIeeeAccess{
false};
756 bool mayModifyHaltingMode{
false};
757 bool mayModifyRoundingMode{
false};
758 bool mayModifyUnderflowMode{
false};
767struct ModuleLikeUnit :
public ProgramUnit {
769 using ModuleStatement =
770 ReferenceVariant<parser::Statement<parser::ModuleStmt>,
777 ~ModuleLikeUnit() =
default;
778 ModuleLikeUnit(ModuleLikeUnit &&) =
default;
779 ModuleLikeUnit(
const ModuleLikeUnit &) =
delete;
781 LLVM_DUMP_METHOD
void dump()
const;
789 ModuleStatement beginStmt;
790 ModuleStatement endStmt;
791 ContainedUnitList containedUnitList;
792 EvaluationList evaluationList;
799struct BlockDataUnit :
public ProgramUnit {
802 BlockDataUnit(BlockDataUnit &&) =
default;
803 BlockDataUnit(
const BlockDataUnit &) =
delete;
805 LLVM_DUMP_METHOD
void dump()
const;
811struct CompilerDirectiveUnit :
public ProgramUnit {
813 const PftNode &parent)
814 : ProgramUnit{directive, parent} {};
815 CompilerDirectiveUnit(CompilerDirectiveUnit &&) =
default;
816 CompilerDirectiveUnit(
const CompilerDirectiveUnit &) =
delete;
820struct OpenACCDirectiveUnit :
public ProgramUnit {
822 const PftNode &parent)
823 : ProgramUnit{directive, parent}, routine{directive} {};
824 OpenACCDirectiveUnit(OpenACCDirectiveUnit &&) =
default;
825 OpenACCDirectiveUnit(
const OpenACCDirectiveUnit &) =
delete;
834 Program(semantics::CommonBlockList &&commonBlocks)
835 : commonBlocks{std::move(commonBlocks)} {}
836 Program(Program &&) =
default;
837 Program(
const Program &) =
delete;
839 const std::list<Units> &getUnits()
const {
return units; }
840 std::list<Units> &getUnits() {
return units; }
841 const semantics::CommonBlockList &getCommonBlocks()
const {
844 ScopeVariableListMap &getScopeVariableListMap() {
845 return scopeVariableListMap;
849 LLVM_DUMP_METHOD
void dump()
const;
852 std::list<Units> units;
853 semantics::CommonBlockList commonBlocks;
854 ScopeVariableListMap scopeVariableListMap;
861 return stmt.visit(
common::visitors{[](
const auto &x) {
return x.source; }});
865template <
typename ParentType,
typename A>
866ParentType *getAncestor(A &node) {
867 if (
auto *seekedParent = node.parent.template getIf<ParentType>())
869 return node.parent.visit(common::visitors{
870 [](Program &p) -> ParentType * {
return nullptr; },
871 [](
auto &p) -> ParentType * {
return getAncestor<ParentType>(p); }});
876ScopeVariableListMap &getScopeVariableListMap(A &node) {
877 Program *pftRoot = getAncestor<Program>(node);
878 assert(pftRoot &&
"pft must have a root");
879 return pftRoot->getScopeVariableListMap();
885 std::function<
void(
const semantics::Symbol &)> callBack);
890 std::function<
void(
const semantics::Symbol &)> callBack);
895bool isWrappableConstruct(
const Evaluation &eval,
896 const semantics::SemanticsContext &semaCtx);
911std::unique_ptr<pft::Program>
913 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:48
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:2197
std::unique_ptr< pft::Program > createPFT(const parser::Program &root, const Fortran::semantics::SemanticsContext &semanticsContext, const LoweringOptions &loweringOptions)
Definition PFTBuilder.cpp:2189
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:811
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
Definition PFTBuilder.h:199
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
Definition PFTBuilder.h:820
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
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: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: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:5966
Definition parse-tree.h:5857
Definition parse-tree.h:5681
Definition parse-tree.h:5533
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