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 {
34struct CompilerDirectiveUnit;
36struct FunctionLikeUnit;
40using ContainedUnit = std::variant<CompilerDirectiveUnit, FunctionLikeUnit>;
41using ContainedUnitList = std::list<ContainedUnit>;
42using EvaluationList = std::list<Evaluation>;
47template <
bool isConst,
typename... A>
51 using BaseType = std::conditional_t<isConst, const B, 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 isFunctionLike{common::HasMember<
189 A, std::tuple<parser::MainProgram, parser::FunctionSubprogram,
190 parser::SubroutineSubprogram,
191 parser::SeparateModuleSubprogram>>};
195template <
typename... A>
199template <
typename... A>
206using EvaluationTuple =
207 common::CombineTuples<ActionStmts, OtherStmts, ConstructStmts, EndStmts,
208 Constructs, Directives>;
212using EvaluationVariant = MakeReferenceVariant<EvaluationTuple>;
219 template <
typename A>
222 const std::optional<parser::Label> &label)
223 : EvaluationVariant{a}, parent{parent}, position{position}, label{label} {
227 template <
typename A>
229 : EvaluationVariant{a}, parent{parent} {
230 static_assert(pft::isConstruct<A> || pft::isDirective<A>,
231 "must be a construct or directive");
237 [](
auto &r) {
return pft::isActionStmt<std::decay_t<
decltype(r)>>; }});
239 constexpr bool isOtherStmt()
const {
241 [](
auto &r) {
return pft::isOtherStmt<std::decay_t<
decltype(r)>>; }});
243 constexpr bool isConstructStmt()
const {
244 return visit(common::visitors{[](
auto &r) {
245 return pft::isConstructStmt<std::decay_t<
decltype(r)>>;
248 constexpr bool isEndStmt()
const {
249 return visit(common::visitors{
250 [](
auto &r) {
return pft::isEndStmt<std::decay_t<
decltype(r)>>; }});
252 constexpr bool isConstruct()
const {
253 return visit(common::visitors{
254 [](
auto &r) {
return pft::isConstruct<std::decay_t<
decltype(r)>>; }});
256 constexpr bool isDirective()
const {
257 return visit(common::visitors{
258 [](
auto &r) {
return pft::isDirective<std::decay_t<
decltype(r)>>; }});
260 constexpr bool isNopConstructStmt()
const {
261 return visit(common::visitors{[](
auto &r) {
262 return pft::isNopConstructStmt<std::decay_t<
decltype(r)>>;
265 constexpr bool isExecutableDirective()
const {
266 return visit(common::visitors{[](
auto &r) {
267 return pft::isExecutableDirective<std::decay_t<
decltype(r)>>;
275 return pft::isIntermediateConstructStmt<std::decay_t<
decltype(r)>>;
279 LLVM_DUMP_METHOD
void dump()
const;
285 if (successor && successor->isNopConstructStmt())
286 successor = successor->parentConstruct->constructExit;
287 assert(successor &&
"missing successor");
293 return evaluationList && !evaluationList->empty();
298 assert(evaluationList &&
"no nested evaluations");
299 return *evaluationList;
304 return evaluationList->front();
307 Evaluation &getLastNestedEvaluation() {
309 return evaluationList->back();
315 bool lowerAsStructured()
const;
316 bool lowerAsUnstructured()
const;
317 bool forceAsUnstructured()
const;
351 std::optional<parser::Label> label{};
352 std::unique_ptr<EvaluationList> evaluationList;
355 Evaluation *parentConstruct{
nullptr};
356 Evaluation *lexicalSuccessor{
nullptr};
357 Evaluation *controlSuccessor{
nullptr};
358 Evaluation *constructExit{
nullptr};
359 bool isNewBlock{
false};
360 bool isUnstructured{
false};
361 bool negateCondition{
false};
362 bool activeConstruct{
false};
363 mlir::Block *block{
nullptr};
367using ProgramVariant =
368 ReferenceVariant<parser::MainProgram, parser::FunctionSubprogram,
369 parser::SubroutineSubprogram, parser::Module,
370 parser::Submodule, parser::SeparateModuleSubprogram,
371 parser::BlockData, parser::CompilerDirective,
372 parser::OpenACCRoutineConstruct>;
376 template <
typename A>
406 : symbol{symbol}, depth{depth}, global{global} {}
409 bool isGlobal()
const {
return global; }
417 std::size_t aliasOffset{};
421 using Interval = std::tuple<std::size_t, std::size_t>;
429 bool isGlobal =
false)
434 :
interval{initialValueSym.offset(), initialValueSym.size()},
463 : var{
Nominal(&sym, depth, global)} {}
464 explicit Variable(AggregateStore &&istore) : var{std::move(istore)} {}
468 assert(
hasSymbol() &&
"variable is not nominal");
469 return *std::get<Nominal>(var).symbol;
478 return std::get<AggregateStore>(var);
484 return std::get<AggregateStore>(var).interval;
488 bool hasSymbol()
const {
return std::holds_alternative<Nominal>(var); }
492 return std::holds_alternative<AggregateStore>(var);
497 return Fortran::common::visit([](
const auto &x) {
return x.isGlobal(); },
504 return scope && scope->kind() == Fortran::semantics::Scope::Kind::Module;
508 return Fortran::common::visit(
510 [](
const Nominal &x) {
return &x.symbol->GetUltimate().owner(); },
511 [](
const AggregateStore &agg) {
return &agg.getOwningScope(); }},
515 bool isHeapAlloc()
const {
516 if (
auto *s = std::get_if<Nominal>(&var))
520 bool isPointer()
const {
521 if (
auto *s = std::get_if<Nominal>(&var))
525 bool isTarget()
const {
526 if (
auto *s = std::get_if<Nominal>(&var))
534 if (
auto *s = std::get_if<Nominal>(&var))
538 std::size_t getAliasOffset()
const {
539 if (
auto *s = std::get_if<Nominal>(&var))
540 return s->aliasOffset;
543 void setAlias(std::size_t offset) {
544 if (
auto *s = std::get_if<Nominal>(&var)) {
546 s->aliasOffset = offset;
548 llvm_unreachable(
"not a nominal var");
552 void setHeapAlloc(
bool to =
true) {
553 if (
auto *s = std::get_if<Nominal>(&var))
556 llvm_unreachable(
"not a nominal var");
558 void setPointer(
bool to =
true) {
559 if (
auto *s = std::get_if<Nominal>(&var))
562 llvm_unreachable(
"not a nominal var");
564 void setTarget(
bool to =
true) {
565 if (
auto *s = std::get_if<Nominal>(&var))
568 llvm_unreachable(
"not a nominal var");
573 if (
auto *s = std::get_if<Nominal>(&var))
578 LLVM_DUMP_METHOD
void dump()
const;
581 std::variant<Nominal, AggregateStore> var;
584using VariableList = std::vector<Variable>;
585using ScopeVariableListMap =
586 std::map<const Fortran::semantics::Scope *, VariableList>;
591 ScopeVariableListMap &map);
601void dump(VariableList &, std::string s = {});
632 bool isMainProgram()
const {
639 void setActiveEntry(
int entryIndex) {
640 assert(entryIndex >= 0 && entryIndex < (
int)
entryPointList.size() &&
641 "invalid entry point index");
651 llvm::report_fatal_error(
652 "not inside a procedure; do not call on main program.");
659 if (!isMainProgram()) {
660 llvm::report_fatal_error(
"call only on main program.");
675 void setHostAssociatedSymbols(
676 const llvm::SetVector<const semantics::Symbol *> &symbols) {
698 LLVM_DUMP_METHOD
void dump()
const;
707 LabelEvalMap labelEvaluationMap;
708 SymbolLabelMap assignSymbolLabelMap;
709 ContainedUnitList containedUnitList;
710 EvaluationList evaluationList;
723 bool hasIeeeAccess{
false};
724 bool mayModifyHaltingMode{
false};
725 bool mayModifyRoundingMode{
false};
726 bool mayModifyUnderflowMode{
false};
747 LLVM_DUMP_METHOD
void dump()
const;
757 ContainedUnitList containedUnitList;
758 EvaluationList evaluationList;
769 LLVM_DUMP_METHOD
void dump()
const;
787 :
ProgramUnit{directive, parent}, routine{directive} {};
798 Program(semantics::CommonBlockList &&commonBlocks)
799 : commonBlocks{std::move(commonBlocks)} {}
803 const std::list<Units> &getUnits()
const {
return units; }
804 std::list<Units> &getUnits() {
return units; }
805 const semantics::CommonBlockList &getCommonBlocks()
const {
808 ScopeVariableListMap &getScopeVariableListMap() {
809 return scopeVariableListMap;
813 LLVM_DUMP_METHOD
void dump()
const;
816 std::list<Units> units;
817 semantics::CommonBlockList commonBlocks;
818 ScopeVariableListMap scopeVariableListMap;
825 return stmt.visit(
common::visitors{[](
const auto &x) {
return x.source; }});
829template <
typename ParentType,
typename A>
830ParentType *getAncestor(A &node) {
831 if (
auto *seekedParent = node.parent.template getIf<ParentType>())
833 return node.parent.visit(common::visitors{
834 [](Program &p) -> ParentType * {
return nullptr; },
835 [](
auto &p) -> ParentType * {
return getAncestor<ParentType>(p); }});
840ScopeVariableListMap &getScopeVariableListMap(A &node) {
841 Program *pftRoot = getAncestor<Program>(node);
842 assert(pftRoot &&
"pft must have a root");
843 return pftRoot->getScopeVariableListMap();
848void visitAllSymbols(
const FunctionLikeUnit &funit,
849 std::function<
void(
const semantics::Symbol &)> callBack);
853void visitAllSymbols(
const Evaluation &eval,
854 std::function<
void(
const semantics::Symbol &)> callBack);
867std::unique_ptr<pft::Program>
872void dumpPFT(llvm::raw_ostream &outputStream,
const pft::Program &pft);
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: AbstractConverter.h:59
void dumpPFT(llvm::raw_ostream &outputStream, const pft::Program &pft)
Dumper for displaying a PFT.
Definition: PFTBuilder.cpp:1891
std::unique_ptr< pft::Program > createPFT(const parser::Program &root, const Fortran::semantics::SemanticsContext &semanticsContext)
Definition: PFTBuilder.cpp:1884
Definition: PFTBuilder.h:763
LLVM_DUMP_METHOD void dump() const
The BlockDataUnit dump is just the associated symbol table.
Definition: PFTBuilder.cpp:1951
Definition: PFTBuilder.h:775
Definition: PFTBuilder.h:216
FunctionLikeUnit * getOwningProcedure() const
Return the FunctionLikeUnit containing this evaluation (or nullptr).
Definition: PFTBuilder.cpp:1449
Evaluation(const A &a, const PftNode &parent)
Construct and Directive ctor.
Definition: PFTBuilder.h:228
EvaluationList & getNestedEvaluations()
Return nested evaluation list.
Definition: PFTBuilder.h:297
Evaluation(const A &a, const PftNode &parent, const parser::CharBlock &position, const std::optional< parser::Label > &label)
General ctor.
Definition: PFTBuilder.h:220
Evaluation & nonNopSuccessor() const
Definition: PFTBuilder.h:283
constexpr bool isIntermediateConstructStmt() const
Definition: PFTBuilder.h:273
constexpr bool isActionStmt() const
Evaluation classification predicates.
Definition: PFTBuilder.h:235
bool hasNestedEvaluations() const
Return true if this Evaluation has at least one nested evaluation.
Definition: PFTBuilder.h:292
Definition: PFTBuilder.h:605
Evaluation * getEntryEval() const
Definition: PFTBuilder.h:667
llvm::SmallVector< std::pair< const semantics::Symbol *, Evaluation * >, 1 > entryPointList
Definition: PFTBuilder.h:717
HostAssociations & parentHostAssoc()
Definition: PFTBuilder.cpp:1798
bool parentHasHostAssoc()
Definition: PFTBuilder.cpp:1810
int activeEntry
Current index into entryPointList. Index 0 is the primary entry point.
Definition: PFTBuilder.h:719
mlir::Block * finalBlock
Terminal basic block (if any)
Definition: PFTBuilder.h:728
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this function like unit.
Definition: PFTBuilder.cpp:1817
HostAssociations & getHostAssoc()
Definition: PFTBuilder.h:695
const semantics::Symbol * primaryResult
Definition: PFTBuilder.h:722
std::optional< FunctionStatement > beginStmt
Anonymous programs do not have a begin statement.
Definition: PFTBuilder.h:704
const semantics::Symbol * getMainProgramSymbol() const
Definition: PFTBuilder.h:658
const Fortran::semantics::Scope & getScope() const
Get the function scope.
Definition: PFTBuilder.h:701
const semantics::Symbol & getSubprogramSymbol() const
Definition: PFTBuilder.h:648
bool parentHasTupleHostAssoc()
Definition: PFTBuilder.cpp:1804
Definition: PFTBuilder.h:194
Module-like units contain a list of function-like units.
Definition: PFTBuilder.h:733
parser::CharBlock getStartingSourceLoc() const
Get the starting source location for this module like unit.
Definition: PFTBuilder.cpp:1839
const Fortran::semantics::Scope & getScope() const
Get the module scope.
Definition: PFTBuilder.cpp:1843
Definition: PFTBuilder.h:784
Definition: PFTBuilder.h:375
A Program is the top-level root of the PFT.
Definition: PFTBuilder.h:794
LLVM_DUMP_METHOD void dump() const
LLVM dump method on a Program.
Definition: PFTBuilder.cpp:1896
Definition: PFTBuilder.h:426
std::size_t getOffset() const
Get offset of the aggregate inside its scope.
Definition: PFTBuilder.h:440
const semantics::Symbol & getNamingSymbol() const
Returns the symbol that gives its name to the aggregate.
Definition: PFTBuilder.h:446
const semantics::Symbol * namingSymbol
Symbol that gives its name to the aggregate. Always set by constructor.
Definition: PFTBuilder.h:454
const semantics::Symbol * initialValueSymbol
Compiler generated symbol with the aggregate initial value if any.
Definition: PFTBuilder.h:456
bool isGlobalAggregate
Is this a global aggregate?
Definition: PFTBuilder.h:458
Interval interval
<offset, size> of the aggregate in its scope.
Definition: PFTBuilder.h:452
const semantics::Symbol * getInitialValueSymbol() const
Returns symbols holding the aggregate initial value if any.
Definition: PFTBuilder.h:442
const semantics::Scope & getOwningScope() const
Scope to which the aggregates belongs to.
Definition: PFTBuilder.h:448
Definition: PFTBuilder.h:404
Definition: PFTBuilder.h:400
bool isAggregateStore() const
Is this an aggregate store?
Definition: PFTBuilder.h:491
bool isRuntimeTypeInfoData() const
Is this variable a compiler generated global to describe derived types?
Definition: PFTBuilder.cpp:1866
bool isGlobal() const
Is this variable a global?
Definition: PFTBuilder.h:496
bool isModuleOrSubmoduleVariable() const
Is this a module or submodule variable?
Definition: PFTBuilder.h:502
bool isAlias() const
Definition: PFTBuilder.h:533
std::tuple< std::size_t, std::size_t > Interval
<offset, size> pair
Definition: PFTBuilder.h:421
bool hasSymbol() const
Only nominal variable have front-end symbols.
Definition: PFTBuilder.h:488
const Interval & getInterval() const
Return the interval range of an aggregate store.
Definition: PFTBuilder.h:482
const Fortran::semantics::Symbol & getSymbol() const
Return the front-end symbol for a nominal variable.
Definition: PFTBuilder.h:467
int getDepth() const
The depth is recorded for nominal variables as a debugging aid.
Definition: PFTBuilder.h:572
const AggregateStore & getAggregateStore() const
Return the aggregate store.
Definition: PFTBuilder.h:476
Definition: parse-tree.h:1990
Definition: parse-tree.h:3435
Definition: parse-tree.h:3440
Definition: parse-tree.h:3445
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:5071
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:3353
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:4723
Definition: parse-tree.h:5045
Definition: parse-tree.h:5016
Definition: parse-tree.h:4909
Definition: parse-tree.h:4756
Definition: parse-tree.h:4494
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