Skip to content

Commit 525f12f

Browse files
committed
[flang][OpenMP] Use OmpDirectiveSpecification in DECLARE_TARGET
1 parent 30c575b commit 525f12f

16 files changed

+319
-254
lines changed

flang/include/flang/Parser/openmp-utils.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ struct ConstructId {
4141
MAKE_CONSTR_ID(OpenMPDeclarativeAllocate, D::OMPD_allocate);
4242
MAKE_CONSTR_ID(OpenMPDeclarativeAssumes, D::OMPD_assumes);
4343
MAKE_CONSTR_ID(OpenMPDeclareReductionConstruct, D::OMPD_declare_reduction);
44-
MAKE_CONSTR_ID(OpenMPDeclareTargetConstruct, D::OMPD_declare_target);
4544
MAKE_CONSTR_ID(OpenMPExecutableAllocate, D::OMPD_allocate);
4645
MAKE_CONSTR_ID(OpenMPRequiresConstruct, D::OMPD_requires);
4746

@@ -97,7 +96,6 @@ struct DirectiveNameScope {
9796
} else if constexpr (std::is_same_v<T, OpenMPDeclarativeAllocate> ||
9897
std::is_same_v<T, OpenMPDeclarativeAssumes> ||
9998
std::is_same_v<T, OpenMPDeclareReductionConstruct> ||
100-
std::is_same_v<T, OpenMPDeclareTargetConstruct> ||
10199
std::is_same_v<T, OpenMPExecutableAllocate> ||
102100
std::is_same_v<T, OpenMPRequiresConstruct>) {
103101
return MakeName(std::get<Verbatim>(x.t).source, ConstructId<T>::id);

flang/include/flang/Parser/parse-tree.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4961,10 +4961,16 @@ struct OmpDeclareTargetSpecifier {
49614961
std::variant<OmpDeclareTargetWithList, OmpDeclareTargetWithClause> u;
49624962
};
49634963

4964+
// Ref: [4.5:110-113], [5.0:180-185], [5.1:210-216], [5.2:206-207],
4965+
// [6.0:346-348]
4966+
//
4967+
// declare-target-directive -> // since 4.5
4968+
// DECLARE_TARGET[(extended-list)] |
4969+
// DECLARE_TARGET clause-list
49644970
struct OpenMPDeclareTargetConstruct {
4965-
TUPLE_CLASS_BOILERPLATE(OpenMPDeclareTargetConstruct);
4971+
WRAPPER_CLASS_BOILERPLATE(
4972+
OpenMPDeclareTargetConstruct, OmpDirectiveSpecification);
49664973
CharBlock source;
4967-
std::tuple<Verbatim, OmpDeclareTargetSpecifier> t;
49684974
};
49694975

49704976
// OMP v5.2: 5.8.8

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -761,19 +761,17 @@ static void promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr(
761761
static void getDeclareTargetInfo(
762762
lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx,
763763
lower::pft::Evaluation &eval,
764-
const parser::OpenMPDeclareTargetConstruct &declareTargetConstruct,
764+
const parser::OpenMPDeclareTargetConstruct &construct,
765765
mlir::omp::DeclareTargetOperands &clauseOps,
766766
llvm::SmallVectorImpl<DeclareTargetCaptureInfo> &symbolAndClause) {
767-
const auto &spec =
768-
std::get<parser::OmpDeclareTargetSpecifier>(declareTargetConstruct.t);
769-
if (const auto *objectList{parser::Unwrap<parser::OmpObjectList>(spec.u)}) {
770-
ObjectList objects{makeObjects(*objectList, semaCtx)};
767+
768+
if (!construct.v.Arguments().v.empty()) {
769+
ObjectList objects{makeObjects(construct.v.Arguments(), semaCtx)};
771770
// Case: declare target(func, var1, var2)
772771
gatherFuncAndVarSyms(objects, mlir::omp::DeclareTargetCaptureClause::to,
773772
symbolAndClause, /*automap=*/false);
774-
} else if (const auto *clauseList{
775-
parser::Unwrap<parser::OmpClauseList>(spec.u)}) {
776-
List<Clause> clauses = makeClauses(*clauseList, semaCtx);
773+
} else {
774+
List<Clause> clauses = makeClauses(construct.v.Clauses(), semaCtx);
777775
if (clauses.empty()) {
778776
Fortran::lower::pft::FunctionLikeUnit *owningProc =
779777
eval.getOwningProcedure();

flang/lib/Parser/openmp-parsers.cpp

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,23 +1773,11 @@ TYPE_PARSER(sourced(construct<OpenMPDeclareReductionConstruct>(
17731773
IsDirective(llvm::omp::Directive::OMPD_declare_reduction)) >=
17741774
Parser<OmpDirectiveSpecification>{})))
17751775

1776-
// declare-target with list
1777-
TYPE_PARSER(sourced(construct<OmpDeclareTargetWithList>(
1778-
parenthesized(Parser<OmpObjectList>{}))))
1779-
1780-
// declare-target with clause
1781-
TYPE_PARSER(
1782-
sourced(construct<OmpDeclareTargetWithClause>(Parser<OmpClauseList>{})))
1783-
1784-
// declare-target-specifier
1785-
TYPE_PARSER(
1786-
construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithList>{}) ||
1787-
construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithClause>{}))
1788-
17891776
// 2.10.6 Declare Target Construct
17901777
TYPE_PARSER(sourced(construct<OpenMPDeclareTargetConstruct>(
1791-
verbatim("DECLARE TARGET"_tok) || verbatim("DECLARE_TARGET"_tok),
1792-
Parser<OmpDeclareTargetSpecifier>{})))
1778+
predicated(Parser<OmpDirectiveName>{},
1779+
IsDirective(llvm::omp::Directive::OMPD_declare_target)) >=
1780+
Parser<OmpDirectiveSpecification>{})))
17931781

17941782
static OmpMapperSpecifier ConstructOmpMapperSpecifier(
17951783
std::optional<Name> &&mapperName, TypeSpec &&typeSpec, Name &&varName) {

flang/lib/Parser/unparse.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2582,8 +2582,8 @@ class UnparseVisitor {
25822582
}
25832583
void Unparse(const OpenMPDeclareTargetConstruct &x) {
25842584
BeginOpenMP();
2585-
Word("!$OMP DECLARE TARGET ");
2586-
Walk(std::get<parser::OmpDeclareTargetSpecifier>(x.t));
2585+
Word("!$OMP ");
2586+
Walk(x.v);
25872587
Put("\n");
25882588
EndOpenMP();
25892589
}

flang/lib/Semantics/check-omp-structure.cpp

Lines changed: 124 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -624,11 +624,6 @@ template <typename Checker> struct DirectiveSpellingVisitor {
624624
checker_(std::get<parser::Verbatim>(x.t).source, Directive::OMPD_assumes);
625625
return false;
626626
}
627-
bool Pre(const parser::OpenMPDeclareTargetConstruct &x) {
628-
checker_(
629-
std::get<parser::Verbatim>(x.t).source, Directive::OMPD_declare_target);
630-
return false;
631-
}
632627
bool Pre(const parser::OpenMPGroupprivate &x) {
633628
checker_(x.v.DirName().source, Directive::OMPD_groupprivate);
634629
return false;
@@ -1615,38 +1610,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Allocate &x) {
16151610
}
16161611
}
16171612

1618-
void OmpStructureChecker::Enter(const parser::OmpDeclareTargetWithClause &x) {
1619-
SetClauseSets(llvm::omp::Directive::OMPD_declare_target);
1620-
}
1621-
1622-
void OmpStructureChecker::Leave(const parser::OmpDeclareTargetWithClause &x) {
1623-
if (x.v.v.size() > 0) {
1624-
const parser::OmpClause *enterClause =
1625-
FindClause(llvm::omp::Clause::OMPC_enter);
1626-
const parser::OmpClause *toClause = FindClause(llvm::omp::Clause::OMPC_to);
1627-
const parser::OmpClause *linkClause =
1628-
FindClause(llvm::omp::Clause::OMPC_link);
1629-
const parser::OmpClause *indirectClause =
1630-
FindClause(llvm::omp::Clause::OMPC_indirect);
1631-
if (!enterClause && !toClause && !linkClause) {
1632-
context_.Say(x.source,
1633-
"If the DECLARE TARGET directive has a clause, it must contain at least one ENTER clause or LINK clause"_err_en_US);
1634-
}
1635-
if (indirectClause && !enterClause) {
1636-
context_.Say(x.source,
1637-
"The INDIRECT clause cannot be used without the ENTER clause with the DECLARE TARGET directive."_err_en_US);
1638-
}
1639-
unsigned version{context_.langOptions().OpenMPVersion};
1640-
if (toClause && version >= 52) {
1641-
context_.Warn(common::UsageWarning::OpenMPUsage, toClause->source,
1642-
"The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead."_warn_en_US);
1643-
}
1644-
if (indirectClause) {
1645-
CheckAllowedClause(llvm::omp::Clause::OMPC_indirect);
1646-
}
1647-
}
1648-
}
1649-
16501613
void OmpStructureChecker::Enter(const parser::OpenMPDeclareMapperConstruct &x) {
16511614
const parser::OmpDirectiveName &dirName{x.v.DirName()};
16521615
PushContextAndClauseSets(dirName.source, dirName.v);
@@ -1698,42 +1661,6 @@ void OmpStructureChecker::Leave(
16981661
dirContext_.pop_back();
16991662
}
17001663

1701-
void OmpStructureChecker::Enter(const parser::OpenMPDeclareTargetConstruct &x) {
1702-
const auto &dir{std::get<parser::Verbatim>(x.t)};
1703-
PushContext(dir.source, llvm::omp::Directive::OMPD_declare_target);
1704-
}
1705-
1706-
void OmpStructureChecker::Enter(const parser::OmpDeclareTargetWithList &x) {
1707-
SymbolSourceMap symbols;
1708-
GetSymbolsInObjectList(x.v, symbols);
1709-
for (auto &[symbol, source] : symbols) {
1710-
const GenericDetails *genericDetails = symbol->detailsIf<GenericDetails>();
1711-
if (genericDetails) {
1712-
context_.Say(source,
1713-
"The procedure '%s' in DECLARE TARGET construct cannot be a generic name."_err_en_US,
1714-
symbol->name());
1715-
genericDetails->specific();
1716-
}
1717-
if (IsProcedurePointer(*symbol)) {
1718-
context_.Say(source,
1719-
"The procedure '%s' in DECLARE TARGET construct cannot be a procedure pointer."_err_en_US,
1720-
symbol->name());
1721-
}
1722-
const SubprogramDetails *entryDetails =
1723-
symbol->detailsIf<SubprogramDetails>();
1724-
if (entryDetails && entryDetails->entryScope()) {
1725-
context_.Say(source,
1726-
"The procedure '%s' in DECLARE TARGET construct cannot be an entry name."_err_en_US,
1727-
symbol->name());
1728-
}
1729-
if (IsStmtFunction(*symbol)) {
1730-
context_.Say(source,
1731-
"The procedure '%s' in DECLARE TARGET construct cannot be a statement function."_err_en_US,
1732-
symbol->name());
1733-
}
1734-
}
1735-
}
1736-
17371664
void OmpStructureChecker::CheckSymbolName(
17381665
const parser::CharBlock &source, const parser::OmpObject &object) {
17391666
common::visit(
@@ -1766,62 +1693,138 @@ void OmpStructureChecker::CheckSymbolNames(
17661693
}
17671694
}
17681695

1696+
void OmpStructureChecker::Enter(const parser::OpenMPDeclareTargetConstruct &x) {
1697+
const parser::OmpDirectiveName &dirName{x.v.DirName()};
1698+
PushContext(dirName.source, dirName.v);
1699+
1700+
// Check if arguments are extended-list-items.
1701+
for (const parser::OmpArgument &arg : x.v.Arguments().v) {
1702+
const Symbol *symbol{GetArgumentSymbol(arg)};
1703+
if (!symbol) {
1704+
context_.Say(arg.source,
1705+
"An argument to the DECLARE TARGET directive should be an extended-list-item"_err_en_US);
1706+
continue;
1707+
}
1708+
const GenericDetails *genericDetails = symbol->detailsIf<GenericDetails>();
1709+
if (genericDetails) {
1710+
context_.Say(arg.source,
1711+
"The procedure '%s' in DECLARE TARGET construct cannot be a generic name."_err_en_US,
1712+
symbol->name());
1713+
genericDetails->specific();
1714+
}
1715+
if (IsProcedurePointer(*symbol)) {
1716+
context_.Say(arg.source,
1717+
"The procedure '%s' in DECLARE TARGET construct cannot be a procedure pointer."_err_en_US,
1718+
symbol->name());
1719+
}
1720+
const SubprogramDetails *entryDetails =
1721+
symbol->detailsIf<SubprogramDetails>();
1722+
if (entryDetails && entryDetails->entryScope()) {
1723+
context_.Say(arg.source,
1724+
"The procedure '%s' in DECLARE TARGET construct cannot be an entry name."_err_en_US,
1725+
symbol->name());
1726+
}
1727+
if (IsStmtFunction(*symbol)) {
1728+
context_.Say(arg.source,
1729+
"The procedure '%s' in DECLARE TARGET construct cannot be a statement function."_err_en_US,
1730+
symbol->name());
1731+
}
1732+
}
1733+
1734+
// Check if there are arguments or clauses, but not both.
1735+
if (!x.v.Clauses().v.empty()) {
1736+
if (!x.v.Arguments().v.empty()) {
1737+
context_.Say(x.source,
1738+
"DECLARE TARGET directive can have argument or clauses, but not both"_err_en_US);
1739+
}
1740+
SetClauseSets(llvm::omp::Directive::OMPD_declare_target);
1741+
}
1742+
}
1743+
17691744
void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) {
1770-
const auto &dir{std::get<parser::Verbatim>(x.t)};
1771-
const auto &spec{std::get<parser::OmpDeclareTargetSpecifier>(x.t)};
1745+
const parser::OmpDirectiveName &dirName{x.v.DirName()};
1746+
17721747
// Handle both forms of DECLARE TARGET.
17731748
// - Extended list: It behaves as if there was an ENTER/TO clause with the
17741749
// list of objects as argument. It accepts no explicit clauses.
17751750
// - With clauses.
1776-
if (const auto *objectList{parser::Unwrap<parser::OmpObjectList>(spec.u)}) {
1777-
deviceConstructFound_ = true;
1778-
CheckSymbolNames(dir.source, *objectList);
1779-
CheckVarIsNotPartOfAnotherVar(dir.source, *objectList);
1780-
CheckThreadprivateOrDeclareTargetVar(*objectList);
1781-
} else if (const auto *clauseList{
1782-
parser::Unwrap<parser::OmpClauseList>(spec.u)}) {
1783-
bool toClauseFound{false}, deviceTypeClauseFound{false},
1784-
enterClauseFound{false};
1785-
for (const auto &clause : clauseList->v) {
1786-
common::visit(
1787-
common::visitors{
1788-
[&](const parser::OmpClause::To &toClause) {
1789-
toClauseFound = true;
1790-
auto &objList{std::get<parser::OmpObjectList>(toClause.v.t)};
1791-
CheckSymbolNames(dir.source, objList);
1792-
CheckVarIsNotPartOfAnotherVar(dir.source, objList);
1793-
CheckThreadprivateOrDeclareTargetVar(objList);
1794-
},
1795-
[&](const parser::OmpClause::Link &linkClause) {
1796-
CheckSymbolNames(dir.source, linkClause.v);
1797-
CheckVarIsNotPartOfAnotherVar(dir.source, linkClause.v);
1798-
CheckThreadprivateOrDeclareTargetVar(linkClause.v);
1799-
},
1800-
[&](const parser::OmpClause::Enter &enterClause) {
1801-
enterClauseFound = true;
1802-
auto &objList{std::get<parser::OmpObjectList>(enterClause.v.t)};
1803-
CheckSymbolNames(dir.source, objList);
1804-
CheckVarIsNotPartOfAnotherVar(dir.source, objList);
1805-
CheckThreadprivateOrDeclareTargetVar(objList);
1806-
},
1807-
[&](const parser::OmpClause::DeviceType &deviceTypeClause) {
1808-
deviceTypeClauseFound = true;
1809-
if (deviceTypeClause.v.v !=
1810-
parser::OmpDeviceTypeClause::DeviceTypeDescription::Host) {
1811-
// Function / subroutine explicitly marked as runnable by the
1812-
// target device.
1813-
deviceConstructFound_ = true;
1814-
}
1815-
},
1816-
[&](const auto &) {},
1817-
},
1818-
clause.u);
1751+
for (const parser::OmpArgument &arg : x.v.Arguments().v) {
1752+
if (auto *object{GetArgumentObject(arg)}) {
1753+
deviceConstructFound_ = true;
1754+
CheckSymbolName(dirName.source, *object);
1755+
CheckVarIsNotPartOfAnotherVar(dirName.source, *object);
1756+
CheckThreadprivateOrDeclareTargetVar(*object);
1757+
}
1758+
}
18191759

1820-
if ((toClauseFound || enterClauseFound) && !deviceTypeClauseFound) {
1821-
deviceConstructFound_ = true;
1822-
}
1760+
if (!x.v.Clauses().v.empty()) {
1761+
const parser::OmpClause *enterClause =
1762+
FindClause(llvm::omp::Clause::OMPC_enter);
1763+
const parser::OmpClause *toClause = FindClause(llvm::omp::Clause::OMPC_to);
1764+
const parser::OmpClause *linkClause =
1765+
FindClause(llvm::omp::Clause::OMPC_link);
1766+
const parser::OmpClause *indirectClause =
1767+
FindClause(llvm::omp::Clause::OMPC_indirect);
1768+
if (!enterClause && !toClause && !linkClause) {
1769+
context_.Say(x.source,
1770+
"If the DECLARE TARGET directive has a clause, it must contain at least one ENTER clause or LINK clause"_err_en_US);
1771+
}
1772+
if (indirectClause && !enterClause) {
1773+
context_.Say(x.source,
1774+
"The INDIRECT clause cannot be used without the ENTER clause with the DECLARE TARGET directive."_err_en_US);
1775+
}
1776+
unsigned version{context_.langOptions().OpenMPVersion};
1777+
if (toClause && version >= 52) {
1778+
context_.Warn(common::UsageWarning::OpenMPUsage, toClause->source,
1779+
"The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead."_warn_en_US);
1780+
}
1781+
if (indirectClause) {
1782+
CheckAllowedClause(llvm::omp::Clause::OMPC_indirect);
18231783
}
18241784
}
1785+
1786+
bool toClauseFound{false}, deviceTypeClauseFound{false},
1787+
enterClauseFound{false};
1788+
for (const parser::OmpClause &clause : x.v.Clauses().v) {
1789+
common::visit(
1790+
common::visitors{
1791+
[&](const parser::OmpClause::To &toClause) {
1792+
toClauseFound = true;
1793+
auto &objList{std::get<parser::OmpObjectList>(toClause.v.t)};
1794+
CheckSymbolNames(dirName.source, objList);
1795+
CheckVarIsNotPartOfAnotherVar(dirName.source, objList);
1796+
CheckThreadprivateOrDeclareTargetVar(objList);
1797+
},
1798+
[&](const parser::OmpClause::Link &linkClause) {
1799+
CheckSymbolNames(dirName.source, linkClause.v);
1800+
CheckVarIsNotPartOfAnotherVar(dirName.source, linkClause.v);
1801+
CheckThreadprivateOrDeclareTargetVar(linkClause.v);
1802+
},
1803+
[&](const parser::OmpClause::Enter &enterClause) {
1804+
enterClauseFound = true;
1805+
auto &objList{std::get<parser::OmpObjectList>(enterClause.v.t)};
1806+
CheckSymbolNames(dirName.source, objList);
1807+
CheckVarIsNotPartOfAnotherVar(dirName.source, objList);
1808+
CheckThreadprivateOrDeclareTargetVar(objList);
1809+
},
1810+
[&](const parser::OmpClause::DeviceType &deviceTypeClause) {
1811+
deviceTypeClauseFound = true;
1812+
if (deviceTypeClause.v.v !=
1813+
parser::OmpDeviceTypeClause::DeviceTypeDescription::Host) {
1814+
// Function / subroutine explicitly marked as runnable by the
1815+
// target device.
1816+
deviceConstructFound_ = true;
1817+
}
1818+
},
1819+
[&](const auto &) {},
1820+
},
1821+
clause.u);
1822+
1823+
if ((toClauseFound || enterClauseFound) && !deviceTypeClauseFound) {
1824+
deviceConstructFound_ = true;
1825+
}
1826+
}
1827+
18251828
dirContext_.pop_back();
18261829
}
18271830

flang/lib/Semantics/check-omp-structure.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,6 @@ class OmpStructureChecker
113113
void Leave(const parser::OpenMPDeclareTargetConstruct &);
114114
void Enter(const parser::OpenMPDepobjConstruct &);
115115
void Leave(const parser::OpenMPDepobjConstruct &);
116-
void Enter(const parser::OmpDeclareTargetWithList &);
117-
void Enter(const parser::OmpDeclareTargetWithClause &);
118-
void Leave(const parser::OmpDeclareTargetWithClause &);
119116
void Enter(const parser::OpenMPDispatchConstruct &);
120117
void Leave(const parser::OpenMPDispatchConstruct &);
121118
void Enter(const parser::OmpErrorDirective &);

0 commit comments

Comments
 (0)