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;
361 std::optional<parser::Label> label{};
362 std::unique_ptr<EvaluationList> evaluationList;
364 llvm::SmallVector<const parser::CompilerDirective *, 1> dirs;
369 bool isNewBlock{
false};
370 bool isUnstructured{
false};
371 bool negateCondition{
false};
372 bool activeConstruct{
false};
373 mlir::Block *block{
nullptr};
377using ProgramVariant =
378 ReferenceVariant<parser::MainProgram, parser::FunctionSubprogram,
379 parser::SubroutineSubprogram, parser::Module,
380 parser::Submodule, parser::SeparateModuleSubprogram,
381 parser::BlockData, parser::CompilerDirective,
382 parser::OpenACCRoutineConstruct>;
385struct ProgramUnit : ProgramVariant {
386 template <
typename A>
387 ProgramUnit(
const A &p,
const PftNode &parent)
388 : ProgramVariant{p}, parent{parent} {}
389 ProgramUnit(ProgramUnit &&) =
default;
390 ProgramUnit(
const ProgramUnit &) =
delete;
416 : symbol{symbol}, depth{depth}, global{global} {}
419 bool isGlobal()
const {
return global; }
427 std::size_t aliasOffset{};
431 using Interval = std::tuple<std::size_t, std::size_t>;
436 struct AggregateStore {
439 bool isGlobal =
false)
444 :
interval{initialValueSym.offset(), initialValueSym.size()},
473 : var{
Nominal(&sym, depth, global)} {}
474 explicit Variable(AggregateStore &&istore) : var{std::move(istore)} {}
478 assert(
hasSymbol() &&
"variable is not nominal");
479 return *std::get<Nominal>(var).symbol;
488 return std::get<AggregateStore>(var);
494 return std::get<AggregateStore>(var).interval;
498 bool hasSymbol()
const {
return std::holds_alternative<Nominal>(var); }
502 return std::holds_alternative<AggregateStore>(var);
507 return Fortran::common::visit([](
const auto &x) {
return x.isGlobal(); },
514 return scope && scope->kind() == Fortran::semantics::Scope::Kind::Module;
518 return Fortran::common::visit(
520 [](
const Nominal &x) {
return &x.symbol->GetUltimate().owner(); },
521 [](
const AggregateStore &agg) {
return &agg.getOwningScope(); }},
525 bool isHeapAlloc()
const {
526 if (
auto *s = std::get_if<Nominal>(&var))
530 bool isPointer()
const {
531 if (
auto *s = std::get_if<Nominal>(&var))
535 bool isTarget()
const {
536 if (
auto *s = std::get_if<Nominal>(&var))
544 if (
auto *s = std::get_if<Nominal>(&var))
548 std::size_t getAliasOffset()
const {
549 if (
auto *s = std::get_if<Nominal>(&var))
550 return s->aliasOffset;
553 void setAlias(std::size_t offset) {
554 if (
auto *s = std::get_if<Nominal>(&var)) {
556 s->aliasOffset = offset;
558 llvm_unreachable(
"not a nominal var");
562 void setHeapAlloc(
bool to =
true) {
563 if (
auto *s = std::get_if<Nominal>(&var))
566 llvm_unreachable(
"not a nominal var");
568 void setPointer(
bool to =
true) {
569 if (
auto *s = std::get_if<Nominal>(&var))
572 llvm_unreachable(
"not a nominal var");
574 void setTarget(
bool to =
true) {
575 if (
auto *s = std::get_if<Nominal>(&var))
578 llvm_unreachable(
"not a nominal var");
583 if (
auto *s = std::get_if<Nominal>(&var))
588 LLVM_DUMP_METHOD
void dump()
const;
591 std::variant<Nominal, AggregateStore> var;
594using VariableList = std::vector<Variable>;
595using ScopeVariableListMap =
596 std::map<const Fortran::semantics::Scope *, VariableList>;
601 ScopeVariableListMap &map);
611void dump(VariableList &, std::string s = {});
615struct FunctionLikeUnit :
public ProgramUnit {
617 using FunctionStatement =
618 ReferenceVariant<parser::Statement<parser::ProgramStmt>,
639 FunctionLikeUnit(FunctionLikeUnit &&) =
default;
640 FunctionLikeUnit(
const FunctionLikeUnit &) =
delete;
642 bool isMainProgram()
const {
649 void setActiveEntry(
int entryIndex) {
650 assert(entryIndex >= 0 && entryIndex < (
int)
entryPointList.size() &&
651 "invalid entry point index");
661 llvm::report_fatal_error(
662 "not inside a procedure; do not call on main program.");
669 if (!isMainProgram()) {
670 llvm::report_fatal_error(
"call only on main program.");
685 void setHostAssociatedSymbols(
686 const llvm::SetVector<const semantics::Symbol *> &symbols) {
708 LLVM_DUMP_METHOD
void dump()
const;
715 FunctionStatement endStmt;
717 LabelEvalMap labelEvaluationMap;
718 SymbolLabelMap assignSymbolLabelMap;
719 ContainedUnitList containedUnitList;
720 EvaluationList evaluationList;
733 bool hasIeeeAccess{
false};
734 bool mayModifyHaltingMode{
false};
735 bool mayModifyRoundingMode{
false};
736 bool mayModifyUnderflowMode{
false};
743struct ModuleLikeUnit :
public ProgramUnit {
745 using ModuleStatement =
746 ReferenceVariant<parser::Statement<parser::ModuleStmt>,
753 ~ModuleLikeUnit() =
default;
754 ModuleLikeUnit(ModuleLikeUnit &&) =
default;
755 ModuleLikeUnit(
const ModuleLikeUnit &) =
delete;
757 LLVM_DUMP_METHOD
void dump()
const;
765 ModuleStatement beginStmt;
766 ModuleStatement endStmt;
767 ContainedUnitList containedUnitList;
768 EvaluationList evaluationList;
773struct BlockDataUnit :
public ProgramUnit {
776 BlockDataUnit(BlockDataUnit &&) =
default;
777 BlockDataUnit(
const BlockDataUnit &) =
delete;
779 LLVM_DUMP_METHOD
void dump()
const;
785struct CompilerDirectiveUnit :
public ProgramUnit {
787 const PftNode &parent)
788 : ProgramUnit{directive, parent} {};
789 CompilerDirectiveUnit(CompilerDirectiveUnit &&) =
default;
790 CompilerDirectiveUnit(
const CompilerDirectiveUnit &) =
delete;
794struct OpenACCDirectiveUnit :
public ProgramUnit {
796 const PftNode &parent)
797 : ProgramUnit{directive, parent}, routine{directive} {};
798 OpenACCDirectiveUnit(OpenACCDirectiveUnit &&) =
default;
799 OpenACCDirectiveUnit(
const OpenACCDirectiveUnit &) =
delete;
808 Program(semantics::CommonBlockList &&commonBlocks)
809 : commonBlocks{std::move(commonBlocks)} {}
810 Program(Program &&) =
default;
811 Program(
const Program &) =
delete;
813 const std::list<Units> &getUnits()
const {
return units; }
814 std::list<Units> &getUnits() {
return units; }
815 const semantics::CommonBlockList &getCommonBlocks()
const {
818 ScopeVariableListMap &getScopeVariableListMap() {
819 return scopeVariableListMap;
823 LLVM_DUMP_METHOD
void dump()
const;
826 std::list<Units> units;
827 semantics::CommonBlockList commonBlocks;
828 ScopeVariableListMap scopeVariableListMap;
835 return stmt.visit(
common::visitors{[](
const auto &x) {
return x.source; }});
839template <
typename ParentType,
typename A>
840ParentType *getAncestor(A &node) {
841 if (
auto *seekedParent = node.parent.template getIf<ParentType>())
843 return node.parent.visit(common::visitors{
844 [](Program &p) -> ParentType * {
return nullptr; },
845 [](
auto &p) -> ParentType * {
return getAncestor<ParentType>(p); }});
850ScopeVariableListMap &getScopeVariableListMap(A &node) {
851 Program *pftRoot = getAncestor<Program>(node);
852 assert(pftRoot &&
"pft must have a root");
853 return pftRoot->getScopeVariableListMap();
859 std::function<
void(
const semantics::Symbol &)> callBack);
864 std::function<
void(
const semantics::Symbol &)> callBack);
877std::unique_ptr<pft::Program>
879 const Fortran::semantics::SemanticsContext &semanticsContext);
Definition reference.h:18
Definition HostAssociations.h:30
void addSymbolsToBind(const llvm::SetVector< const Fortran::semantics::Symbol * > &symbols, const Fortran::semantics::Scope &hostScope)
Definition HostAssociations.cpp:546
Definition PFTBuilder.h:48
Definition char-block.h:28
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:1903
std::unique_ptr< pft::Program > createPFT(const parser::Program &root, const Fortran::semantics::SemanticsContext &semanticsContext)
Definition PFTBuilder.cpp:1896
Definition PFTBuilder.h:773
LLVM_DUMP_METHOD void dump() const
The BlockDataUnit dump is just the associated symbol table.
Definition PFTBuilder.cpp:1963
Definition PFTBuilder.h:785
Definition PFTBuilder.h:221
FunctionLikeUnit * getOwningProcedure() const
Return the FunctionLikeUnit containing this evaluation (or nullptr).
Definition PFTBuilder.cpp:1461
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:615
Evaluation * getEntryEval() const
Definition PFTBuilder.h:677
llvm::SmallVector< std::pair< const semantics::Symbol *, Evaluation * >, 1 > entryPointList
Definition PFTBuilder.h:727
HostAssociations & parentHostAssoc()
Definition PFTBuilder.cpp:1810
bool parentHasHostAssoc()
Definition PFTBuilder.cpp:1822
int activeEntry
Current index into entryPointList. Index 0 is the primary entry point.
Definition PFTBuilder.h:729
mlir::Block * finalBlock
Terminal basic block (if any)
Definition PFTBuilder.h:738
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this function like unit.
Definition PFTBuilder.cpp:1829
HostAssociations & getHostAssoc()
Definition PFTBuilder.h:705
const semantics::Symbol * primaryResult
Definition PFTBuilder.h:732
std::optional< FunctionStatement > beginStmt
Anonymous programs do not have a begin statement.
Definition PFTBuilder.h:714
const semantics::Symbol * getMainProgramSymbol() const
Definition PFTBuilder.h:668
const Fortran::semantics::Scope & getScope() const
Get the function scope.
Definition PFTBuilder.h:711
const semantics::Symbol & getSubprogramSymbol() const
Definition PFTBuilder.h:658
bool parentHasTupleHostAssoc()
Definition PFTBuilder.cpp:1816
Definition PFTBuilder.h:199
Module-like units contain a list of function-like units.
Definition PFTBuilder.h:743
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this module like unit.
Definition PFTBuilder.cpp:1851
const Fortran::semantics::Scope & getScope() const
Get the module scope.
Definition PFTBuilder.cpp:1855
Definition PFTBuilder.h:794
A Program is the top-level root of the PFT.
Definition PFTBuilder.h:804
LLVM_DUMP_METHOD void dump() const
LLVM dump method on a Program.
Definition PFTBuilder.cpp:1908
Definition PFTBuilder.h:436
std::size_t getOffset() const
Get offset of the aggregate inside its scope.
Definition PFTBuilder.h:450
const semantics::Symbol & getNamingSymbol() const
Returns the symbol that gives its name to the aggregate.
Definition PFTBuilder.h:456
const semantics::Symbol * namingSymbol
Symbol that gives its name to the aggregate. Always set by constructor.
Definition PFTBuilder.h:464
const semantics::Symbol * initialValueSymbol
Compiler generated symbol with the aggregate initial value if any.
Definition PFTBuilder.h:466
bool isGlobalAggregate
Is this a global aggregate?
Definition PFTBuilder.h:468
Interval interval
<offset, size> of the aggregate in its scope.
Definition PFTBuilder.h:462
const semantics::Symbol * getInitialValueSymbol() const
Returns symbols holding the aggregate initial value if any.
Definition PFTBuilder.h:452
const semantics::Scope & getOwningScope() const
Scope to which the aggregates belongs to.
Definition PFTBuilder.h:458
Definition PFTBuilder.h:414
Definition PFTBuilder.h:410
bool isAggregateStore() const
Is this an aggregate store?
Definition PFTBuilder.h:501
bool isRuntimeTypeInfoData() const
Is this variable a compiler generated global to describe derived types?
Definition PFTBuilder.cpp:1878
bool isGlobal() const
Is this variable a global?
Definition PFTBuilder.h:506
bool isModuleOrSubmoduleVariable() const
Is this a module or submodule variable?
Definition PFTBuilder.h:512
bool isAlias() const
Definition PFTBuilder.h:543
std::tuple< std::size_t, std::size_t > Interval
<offset, size> pair
Definition PFTBuilder.h:431
bool hasSymbol() const
Only nominal variable have front-end symbols.
Definition PFTBuilder.h:498
const Interval & getInterval() const
Return the interval range of an aggregate store.
Definition PFTBuilder.h:492
const Fortran::semantics::Symbol & getSymbol() const
Return the front-end symbol for a nominal variable.
Definition PFTBuilder.h:477
int getDepth() const
The depth is recorded for nominal variables as a debugging aid.
Definition PFTBuilder.h:582
const AggregateStore & getAggregateStore() const
Return the aggregate store.
Definition PFTBuilder.h:486
Definition parse-tree.h:1990
Definition parse-tree.h:3450
Definition parse-tree.h:3455
Definition parse-tree.h:3460
Definition parse-tree.h:2016
Definition parse-tree.h:2173
Definition parse-tree.h:2164
Definition parse-tree.h:2195
Definition parse-tree.h:3027
Definition parse-tree.h:5509
Definition parse-tree.h:3276
Definition parse-tree.h:2437
Definition parse-tree.h:2425
Definition parse-tree.h:2226
Definition parse-tree.h:2211
Definition parse-tree.h:2695
Definition parse-tree.h:3358
Definition parse-tree.h:2524
Definition parse-tree.h:2242
Definition parse-tree.h:2233
Definition parse-tree.h:2010
Definition parse-tree.h:2338
Definition parse-tree.h:2358
Definition parse-tree.h:2220
Definition parse-tree.h:2578
Definition parse-tree.h:2592
Definition parse-tree.h:2108
Definition parse-tree.h:2143
Definition parse-tree.h:2120
Definition parse-tree.h:3298
Definition parse-tree.h:2372
Definition parse-tree.h:2388
Definition parse-tree.h:2351
Definition parse-tree.h:2915
Definition parse-tree.h:2618
Definition parse-tree.h:2936
Definition parse-tree.h:2075
Definition parse-tree.h:2971
Definition parse-tree.h:2321
Definition parse-tree.h:2546
Definition parse-tree.h:5167
Definition parse-tree.h:5483
Definition parse-tree.h:5454
Definition parse-tree.h:5345
Definition parse-tree.h:5192
Definition parse-tree.h:5009
Definition parse-tree.h:2040
Definition parse-tree.h:2791
Definition parse-tree.h:2754
Definition parse-tree.h:2395
Definition parse-tree.h:2460
Definition parse-tree.h:2472
Definition parse-tree.h:2451
Definition parse-tree.h:2506
Definition parse-tree.h:2486
Definition parse-tree.h:3324
Definition parse-tree.h:355
Definition parse-tree.h:2538
Definition parse-tree.h:3013
Definition parse-tree.h:3308
Definition parse-tree.h:2556
Definition parse-tree.h:2569
Definition parse-tree.h:2495
Definition parse-tree.h:2628
Definition parse-tree.h:2059
Definition parse-tree.h:2090
Definition parse-tree.h:2053
Definition parse-tree.h:2776