Skip to content

Commit 87374a8

Browse files
authored
[flang] Add support for lowering directives at the CONTAINS level (#95123)
There is currently support for lowering directives that appear outside of a module or procedure, or inside the body of a module or procedure. Extend this to support directives at the CONTAINS level of a module or procedure, such as directives 3, 5, 7 9, and 10 in: !dir$ some directive 1 module m !dir$ some directive 2 contains !dir$ some directive 3 subroutine p !dir$ some directive 4 contains !dir$ some directive 5 subroutine s1 !dir$ some directive 6 end subroutine s1 !dir$ some directive 7 subroutine s2 !dir$ some directive 8 end subroutine s2 !dir$ some directive 9 end subroutine p !dir$ some directive 10 end module m !dir$ some directive 11 This is done by looking for CONTAINS statements at the module or procedure level, while ignoring CONTAINS statements at the derived type level.
1 parent 47afa10 commit 87374a8

File tree

4 files changed

+243
-91
lines changed

4 files changed

+243
-91
lines changed

flang/include/flang/Lower/PFTBuilder.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,14 @@
3131

3232
namespace Fortran::lower::pft {
3333

34+
struct CompilerDirectiveUnit;
3435
struct Evaluation;
35-
struct Program;
36-
struct ModuleLikeUnit;
3736
struct FunctionLikeUnit;
37+
struct ModuleLikeUnit;
38+
struct Program;
3839

40+
using ContainedUnit = std::variant<CompilerDirectiveUnit, FunctionLikeUnit>;
41+
using ContainedUnitList = std::list<ContainedUnit>;
3942
using EvaluationList = std::list<Evaluation>;
4043

4144
/// Provide a variant like container that can hold references. It can hold
@@ -594,8 +597,8 @@ VariableList getDependentVariableList(const Fortran::semantics::Symbol &);
594597

595598
void dump(VariableList &, std::string s = {}); // `s` is an optional dump label
596599

597-
/// Function-like units may contain evaluations (executable statements) and
598-
/// nested function-like units (internal procedures and function statements).
600+
/// Function-like units may contain evaluations (executable statements),
601+
/// directives, and internal (nested) function-like units.
599602
struct FunctionLikeUnit : public ProgramUnit {
600603
// wrapper statements for function-like syntactic structures
601604
using FunctionStatement =
@@ -697,10 +700,10 @@ struct FunctionLikeUnit : public ProgramUnit {
697700
std::optional<FunctionStatement> beginStmt;
698701
FunctionStatement endStmt;
699702
const semantics::Scope *scope;
700-
EvaluationList evaluationList;
701703
LabelEvalMap labelEvaluationMap;
702704
SymbolLabelMap assignSymbolLabelMap;
703-
std::list<FunctionLikeUnit> nestedFunctions;
705+
ContainedUnitList containedUnitList;
706+
EvaluationList evaluationList;
704707
/// <Symbol, Evaluation> pairs for each entry point. The pair at index 0
705708
/// is the primary entry point; remaining pairs are alternate entry points.
706709
/// The primary entry point symbol is Null for an anonymous program.
@@ -746,7 +749,7 @@ struct ModuleLikeUnit : public ProgramUnit {
746749

747750
ModuleStatement beginStmt;
748751
ModuleStatement endStmt;
749-
std::list<FunctionLikeUnit> nestedFunctions;
752+
ContainedUnitList containedUnitList;
750753
EvaluationList evaluationList;
751754
};
752755

flang/lib/Lower/Bridge.cpp

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -302,28 +302,32 @@ class FirConverter : public Fortran::lower::AbstractConverter {
302302
bool hasMainProgram = false;
303303
const Fortran::semantics::Symbol *globalOmpRequiresSymbol = nullptr;
304304
for (Fortran::lower::pft::Program::Units &u : pft.getUnits()) {
305-
std::visit(Fortran::common::visitors{
306-
[&](Fortran::lower::pft::FunctionLikeUnit &f) {
307-
if (f.isMainProgram())
308-
hasMainProgram = true;
309-
declareFunction(f);
310-
if (!globalOmpRequiresSymbol)
311-
globalOmpRequiresSymbol = f.getScope().symbol();
312-
},
313-
[&](Fortran::lower::pft::ModuleLikeUnit &m) {
314-
lowerModuleDeclScope(m);
315-
for (Fortran::lower::pft::FunctionLikeUnit &f :
316-
m.nestedFunctions)
317-
declareFunction(f);
318-
},
319-
[&](Fortran::lower::pft::BlockDataUnit &b) {
320-
if (!globalOmpRequiresSymbol)
321-
globalOmpRequiresSymbol = b.symTab.symbol();
322-
},
323-
[&](Fortran::lower::pft::CompilerDirectiveUnit &d) {},
324-
[&](Fortran::lower::pft::OpenACCDirectiveUnit &d) {},
325-
},
326-
u);
305+
std::visit(
306+
Fortran::common::visitors{
307+
[&](Fortran::lower::pft::FunctionLikeUnit &f) {
308+
if (f.isMainProgram())
309+
hasMainProgram = true;
310+
declareFunction(f);
311+
if (!globalOmpRequiresSymbol)
312+
globalOmpRequiresSymbol = f.getScope().symbol();
313+
},
314+
[&](Fortran::lower::pft::ModuleLikeUnit &m) {
315+
lowerModuleDeclScope(m);
316+
for (Fortran::lower::pft::ContainedUnit &unit :
317+
m.containedUnitList)
318+
if (auto *f =
319+
std::get_if<Fortran::lower::pft::FunctionLikeUnit>(
320+
&unit))
321+
declareFunction(*f);
322+
},
323+
[&](Fortran::lower::pft::BlockDataUnit &b) {
324+
if (!globalOmpRequiresSymbol)
325+
globalOmpRequiresSymbol = b.symTab.symbol();
326+
},
327+
[&](Fortran::lower::pft::CompilerDirectiveUnit &d) {},
328+
[&](Fortran::lower::pft::OpenACCDirectiveUnit &d) {},
329+
},
330+
u);
327331
}
328332

329333
// Create definitions of intrinsic module constants.
@@ -387,13 +391,15 @@ class FirConverter : public Fortran::lower::AbstractConverter {
387391

388392
// Compute the set of host associated entities from the nested functions.
389393
llvm::SetVector<const Fortran::semantics::Symbol *> escapeHost;
390-
for (Fortran::lower::pft::FunctionLikeUnit &f : funit.nestedFunctions)
391-
collectHostAssociatedVariables(f, escapeHost);
394+
for (Fortran::lower::pft::ContainedUnit &unit : funit.containedUnitList)
395+
if (auto *f = std::get_if<Fortran::lower::pft::FunctionLikeUnit>(&unit))
396+
collectHostAssociatedVariables(*f, escapeHost);
392397
funit.setHostAssociatedSymbols(escapeHost);
393398

394399
// Declare internal procedures
395-
for (Fortran::lower::pft::FunctionLikeUnit &f : funit.nestedFunctions)
396-
declareFunction(f);
400+
for (Fortran::lower::pft::ContainedUnit &unit : funit.containedUnitList)
401+
if (auto *f = std::get_if<Fortran::lower::pft::FunctionLikeUnit>(&unit))
402+
declareFunction(*f);
397403
}
398404

399405
/// Get the scope that is defining or using \p sym. The returned scope is not
@@ -5356,8 +5362,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {
53565362
endNewFunction(funit);
53575363
}
53585364
funit.setActiveEntry(0);
5359-
for (Fortran::lower::pft::FunctionLikeUnit &f : funit.nestedFunctions)
5360-
lowerFunc(f); // internal procedure
5365+
for (Fortran::lower::pft::ContainedUnit &unit : funit.containedUnitList)
5366+
if (auto *f = std::get_if<Fortran::lower::pft::FunctionLikeUnit>(&unit))
5367+
lowerFunc(*f); // internal procedure
53615368
}
53625369

53635370
/// Lower module variable definitions to fir::globalOp and OpenMP/OpenACC
@@ -5381,8 +5388,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {
53815388

53825389
/// Lower functions contained in a module.
53835390
void lowerMod(Fortran::lower::pft::ModuleLikeUnit &mod) {
5384-
for (Fortran::lower::pft::FunctionLikeUnit &f : mod.nestedFunctions)
5385-
lowerFunc(f);
5391+
for (Fortran::lower::pft::ContainedUnit &unit : mod.containedUnitList)
5392+
if (auto *f = std::get_if<Fortran::lower::pft::FunctionLikeUnit>(&unit))
5393+
lowerFunc(*f);
53865394
}
53875395

53885396
void setCurrentPosition(const Fortran::parser::CharBlock &position) {

0 commit comments

Comments
 (0)