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};
745struct ModuleLikeUnit :
public ProgramUnit {
747 using ModuleStatement =
748 ReferenceVariant<parser::Statement<parser::ModuleStmt>,
755 ~ModuleLikeUnit() =
default;
756 ModuleLikeUnit(ModuleLikeUnit &&) =
default;
757 ModuleLikeUnit(
const ModuleLikeUnit &) =
delete;
759 LLVM_DUMP_METHOD
void dump()
const;
767 ModuleStatement beginStmt;
768 ModuleStatement endStmt;
769 ContainedUnitList containedUnitList;
770 EvaluationList evaluationList;
775struct BlockDataUnit :
public ProgramUnit {
778 BlockDataUnit(BlockDataUnit &&) =
default;
779 BlockDataUnit(
const BlockDataUnit &) =
delete;
781 LLVM_DUMP_METHOD
void dump()
const;
787struct CompilerDirectiveUnit :
public ProgramUnit {
789 const PftNode &parent)
790 : ProgramUnit{directive, parent} {};
791 CompilerDirectiveUnit(CompilerDirectiveUnit &&) =
default;
792 CompilerDirectiveUnit(
const CompilerDirectiveUnit &) =
delete;
796struct OpenACCDirectiveUnit :
public ProgramUnit {
798 const PftNode &parent)
799 : ProgramUnit{directive, parent}, routine{directive} {};
800 OpenACCDirectiveUnit(OpenACCDirectiveUnit &&) =
default;
801 OpenACCDirectiveUnit(
const OpenACCDirectiveUnit &) =
delete;
810 Program(semantics::CommonBlockList &&commonBlocks)
811 : commonBlocks{std::move(commonBlocks)} {}
812 Program(Program &&) =
default;
813 Program(
const Program &) =
delete;
815 const std::list<Units> &getUnits()
const {
return units; }
816 std::list<Units> &getUnits() {
return units; }
817 const semantics::CommonBlockList &getCommonBlocks()
const {
820 ScopeVariableListMap &getScopeVariableListMap() {
821 return scopeVariableListMap;
825 LLVM_DUMP_METHOD
void dump()
const;
828 std::list<Units> units;
829 semantics::CommonBlockList commonBlocks;
830 ScopeVariableListMap scopeVariableListMap;
837 return stmt.visit(
common::visitors{[](
const auto &x) {
return x.source; }});
841template <
typename ParentType,
typename A>
842ParentType *getAncestor(A &node) {
843 if (
auto *seekedParent = node.parent.template getIf<ParentType>())
845 return node.parent.visit(common::visitors{
846 [](Program &p) -> ParentType * {
return nullptr; },
847 [](
auto &p) -> ParentType * {
return getAncestor<ParentType>(p); }});
852ScopeVariableListMap &getScopeVariableListMap(A &node) {
853 Program *pftRoot = getAncestor<Program>(node);
854 assert(pftRoot &&
"pft must have a root");
855 return pftRoot->getScopeVariableListMap();
861 std::function<
void(
const semantics::Symbol &)> callBack);
866 std::function<
void(
const semantics::Symbol &)> callBack);
881std::unique_ptr<pft::Program>
883 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 LoweringOptions.h:34
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:2009
std::unique_ptr< pft::Program > createPFT(const parser::Program &root, const Fortran::semantics::SemanticsContext &semanticsContext, const LoweringOptions &loweringOptions)
Definition PFTBuilder.cpp:2001
Definition PFTBuilder.h:775
LLVM_DUMP_METHOD void dump() const
The BlockDataUnit dump is just the associated symbol table.
Definition PFTBuilder.cpp:2069
Definition PFTBuilder.h:787
Definition PFTBuilder.h:221
FunctionLikeUnit * getOwningProcedure() const
Return the FunctionLikeUnit containing this evaluation (or nullptr).
Definition PFTBuilder.cpp:1566
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:1915
bool parentHasHostAssoc()
Definition PFTBuilder.cpp:1927
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
std::list< Fortran::semantics::PreservedUseStmt > preservedUseStmts
Preserved USE statements for debug info generation.
Definition PFTBuilder.h:741
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this function like unit.
Definition PFTBuilder.cpp:1934
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:1921
Definition PFTBuilder.h:199
Module-like units contain a list of function-like units.
Definition PFTBuilder.h:745
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this module like unit.
Definition PFTBuilder.cpp:1956
const Fortran::semantics::Scope & getScope() const
Get the module scope.
Definition PFTBuilder.cpp:1960
Definition PFTBuilder.h:796
A Program is the top-level root of the PFT.
Definition PFTBuilder.h:806
LLVM_DUMP_METHOD void dump() const
LLVM dump method on a Program.
Definition PFTBuilder.cpp:2014
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:1983
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:2003
Definition parse-tree.h:3481
Definition parse-tree.h:3486
Definition parse-tree.h:3491
Definition parse-tree.h:2029
Definition parse-tree.h:2184
Definition parse-tree.h:2175
Definition parse-tree.h:2206
Definition parse-tree.h:3039
Definition parse-tree.h:5805
Definition parse-tree.h:3288
Definition parse-tree.h:2448
Definition parse-tree.h:2436
Definition parse-tree.h:2237
Definition parse-tree.h:2222
Definition parse-tree.h:2706
Definition parse-tree.h:3374
Definition parse-tree.h:2535
Definition parse-tree.h:2253
Definition parse-tree.h:2244
Definition parse-tree.h:2023
Definition parse-tree.h:2349
Definition parse-tree.h:2369
Definition parse-tree.h:2231
Definition parse-tree.h:2589
Definition parse-tree.h:2603
Definition parse-tree.h:2119
Definition parse-tree.h:2154
Definition parse-tree.h:2131
Definition parse-tree.h:3309
Definition parse-tree.h:2383
Definition parse-tree.h:2399
Definition parse-tree.h:2362
Definition parse-tree.h:2927
Definition parse-tree.h:2629
Definition parse-tree.h:2948
Definition parse-tree.h:2086
Definition parse-tree.h:2983
Definition parse-tree.h:2332
Definition parse-tree.h:2557
Definition parse-tree.h:5444
Definition parse-tree.h:5779
Definition parse-tree.h:5750
Definition parse-tree.h:5641
Definition parse-tree.h:5475
Definition parse-tree.h:5307
Definition parse-tree.h:2051
Definition parse-tree.h:2803
Definition parse-tree.h:2766
Definition parse-tree.h:2406
Definition parse-tree.h:2471
Definition parse-tree.h:2483
Definition parse-tree.h:2462
Definition parse-tree.h:2517
Definition parse-tree.h:2497
Definition parse-tree.h:3335
Definition parse-tree.h:359
Definition parse-tree.h:2549
Definition parse-tree.h:3025
Definition parse-tree.h:3319
Definition parse-tree.h:2567
Definition parse-tree.h:2580
Definition parse-tree.h:2506
Definition parse-tree.h:2639
Definition parse-tree.h:2070
Definition parse-tree.h:2101
Definition parse-tree.h:2064
Definition parse-tree.h:2788