diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -25,6 +25,9 @@ using OmpClauseSet = Fortran::common::EnumSet; +#define GEN_FLANG_DIRECTIVE_CLAUSE_SETS +#include "llvm/Frontend/OpenMP/OMP.cpp.inc" + namespace llvm { namespace omp { static OmpDirectiveSet parallelSet{Directive::OMPD_distribute_parallel_do, @@ -151,6 +154,9 @@ void Enter(const parser::OmpScheduleClause &); private: +#define GEN_FLANG_DIRECTIVE_CLAUSE_MAP +#include "llvm/Frontend/OpenMP/OMP.cpp.inc" + struct OmpContext { OmpContext(parser::CharBlock source, llvm::omp::Directive d) : directiveSource{source}, directive{d} {} @@ -216,7 +222,20 @@ void PushContext(const parser::CharBlock &source, llvm::omp::Directive dir) { ompContext_.emplace_back(source, dir); } - + void SetClauseSets(llvm::omp::Directive dir) { + ompContext_.back().allowedClauses = directiveClausesTable[dir].allowed; + ompContext_.back().allowedOnceClauses = + directiveClausesTable[dir].allowedOnce; + ompContext_.back().allowedExclusiveClauses = + directiveClausesTable[dir].allowedExclusive; + ompContext_.back().requiredClauses = + directiveClausesTable[dir].requiredOneOf; + } + void PushContextAndClauseSets( + const parser::CharBlock &source, llvm::omp::Directive dir) { + PushContext(source, dir); + SetClauseSets(dir); + } void RequiresConstantPositiveParameter( const llvm::omp::Clause &clause, const parser::ScalarIntConstantExpr &i); void RequiresPositiveParameter( diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -13,58 +13,6 @@ namespace Fortran::semantics { -static OmpClauseSet doAllowedClauses{llvm::omp::Clause::OMPC_private, - llvm::omp::Clause::OMPC_firstprivate, llvm::omp::Clause::OMPC_lastprivate, - llvm::omp::Clause::OMPC_linear, llvm::omp::Clause::OMPC_reduction}; -static OmpClauseSet doAllowedOnceClauses{llvm::omp::Clause::OMPC_schedule, - llvm::omp::Clause::OMPC_collapse, llvm::omp::Clause::OMPC_ordered}; - -static OmpClauseSet simdAllowedClauses{llvm::omp::Clause::OMPC_linear, - llvm::omp::Clause::OMPC_aligned, llvm::omp::Clause::OMPC_private, - llvm::omp::Clause::OMPC_lastprivate, llvm::omp::Clause::OMPC_reduction}; -static OmpClauseSet simdAllowedOnceClauses{llvm::omp::Clause::OMPC_collapse, - llvm::omp::Clause::OMPC_safelen, llvm::omp::Clause::OMPC_simdlen}; - -static OmpClauseSet parallelAllowedClauses{llvm::omp::Clause::OMPC_default, - llvm::omp::Clause::OMPC_private, llvm::omp::Clause::OMPC_firstprivate, - llvm::omp::Clause::OMPC_shared, llvm::omp::Clause::OMPC_copyin, - llvm::omp::Clause::OMPC_reduction}; -static OmpClauseSet parallelAllowedOnceClauses{llvm::omp::Clause::OMPC_if, - llvm::omp::Clause::OMPC_num_threads, llvm::omp::Clause::OMPC_proc_bind}; - -static OmpClauseSet taskloopAllowedClauses{llvm::omp::Clause::OMPC_shared, - llvm::omp::Clause::OMPC_private, llvm::omp::Clause::OMPC_firstprivate, - llvm::omp::Clause::OMPC_lastprivate, llvm::omp::Clause::OMPC_default, - llvm::omp::Clause::OMPC_untied, llvm::omp::Clause::OMPC_mergeable, - llvm::omp::Clause::OMPC_nogroup}; -static OmpClauseSet taskloopAllowedOnceClauses{llvm::omp::Clause::OMPC_collapse, - llvm::omp::Clause::OMPC_if, llvm::omp::Clause::OMPC_final, - llvm::omp::Clause::OMPC_priority}; -static OmpClauseSet taskloopAllowedExclusiveClauses{ - llvm::omp::Clause::OMPC_grainsize, llvm::omp::Clause::OMPC_num_tasks}; - -static OmpClauseSet distributeAllowedClauses{llvm::omp::Clause::OMPC_private, - llvm::omp::Clause::OMPC_firstprivate, llvm::omp::Clause::OMPC_lastprivate}; -static OmpClauseSet distributeAllowedOnceClauses{ - llvm::omp::Clause::OMPC_collapse, llvm::omp::Clause::OMPC_dist_schedule}; - -static OmpClauseSet targetAllowedClauses{llvm::omp::Clause::OMPC_if, - llvm::omp::Clause::OMPC_private, llvm::omp::Clause::OMPC_firstprivate, - llvm::omp::Clause::OMPC_map, llvm::omp::Clause::OMPC_is_device_ptr, - llvm::omp::Clause::OMPC_depend}; -static OmpClauseSet targetAllowedOnceClauses{llvm::omp::Clause::OMPC_device, - llvm::omp::Clause::OMPC_defaultmap, llvm::omp::Clause::OMPC_nowait}; - -static OmpClauseSet teamsAllowedClauses{llvm::omp::Clause::OMPC_private, - llvm::omp::Clause::OMPC_firstprivate, llvm::omp::Clause::OMPC_shared, - llvm::omp::Clause::OMPC_reduction}; -static OmpClauseSet teamsAllowedOnceClauses{llvm::omp::Clause::OMPC_num_teams, - llvm::omp::Clause::OMPC_thread_limit, llvm::omp::Clause::OMPC_default}; - -static OmpClauseSet sectionsAllowedClauses{llvm::omp::Clause::OMPC_private, - llvm::omp::Clause::OMPC_firstprivate, llvm::omp::Clause::OMPC_lastprivate, - llvm::omp::Clause::OMPC_reduction}; - std::string OmpStructureChecker::ContextDirectiveAsFortran() { auto dir = llvm::omp::getOpenMPDirectiveName(GetContext().directive).str(); std::transform(dir.begin(), dir.end(), dir.begin(), @@ -186,19 +134,18 @@ CheckMatching(beginLoopDir, *endLoopDir); } - if (beginDir.v != llvm::omp::Directive::OMPD_do) - PushContext(beginDir.source, beginDir.v); + if (beginDir.v != llvm::omp::Directive::OMPD_do) { + PushContextAndClauseSets(beginDir.source, beginDir.v); + } else { + // 2.7.1 do-clause -> private-clause | + // firstprivate-clause | + // lastprivate-clause | + // linear-clause | + // reduction-clause | + // schedule-clause | + // collapse-clause | + // ordered-clause - switch (beginDir.v) { - // 2.7.1 do-clause -> private-clause | - // firstprivate-clause | - // lastprivate-clause | - // linear-clause | - // reduction-clause | - // schedule-clause | - // collapse-clause | - // ordered-clause - case llvm::omp::Directive::OMPD_do: { // nesting check HasInvalidWorksharingNesting(beginDir.source, {llvm::omp::Directive::OMPD_do, llvm::omp::Directive::OMPD_sections, @@ -210,218 +157,7 @@ llvm::omp::Directive::OMPD_ordered, llvm::omp::Directive::OMPD_atomic, llvm::omp::Directive::OMPD_master}); - PushContext(beginDir.source, llvm::omp::Directive::OMPD_do); - SetContextAllowed(doAllowedClauses); - SetContextAllowedOnce(doAllowedOnceClauses); - } break; - - // 2.11.1 parallel-do-clause -> parallel-clause | - // do-clause - case llvm::omp::Directive::OMPD_parallel_do: { - SetContextAllowed(parallelAllowedClauses | doAllowedClauses); - SetContextAllowedOnce(parallelAllowedOnceClauses | doAllowedOnceClauses); - } break; - - // 2.8.1 simd-clause -> safelen-clause | - // simdlen-clause | - // linear-clause | - // aligned-clause | - // private-clause | - // lastprivate-clause | - // reduction-clause | - // collapse-clause - case llvm::omp::Directive::OMPD_simd: { - SetContextAllowed(simdAllowedClauses); - SetContextAllowedOnce(simdAllowedOnceClauses); - } break; - - // 2.8.3 do-simd-clause -> do-clause | - // simd-clause - case llvm::omp::Directive::OMPD_do_simd: { - SetContextAllowed(doAllowedClauses | simdAllowedClauses); - SetContextAllowedOnce(doAllowedOnceClauses | simdAllowedOnceClauses); - } break; - - // 2.11.4 parallel-do-simd-clause -> parallel-clause | - // do-simd-clause - case llvm::omp::Directive::OMPD_parallel_do_simd: { - SetContextAllowed( - parallelAllowedClauses | doAllowedClauses | simdAllowedClauses); - SetContextAllowedOnce(parallelAllowedOnceClauses | doAllowedOnceClauses | - simdAllowedOnceClauses); - } break; - - // 2.9.2 taskloop-clause -> if-clause | - // shared-clause | - // private-clause | - // firstprivate-clause | - // lastprivate-clause | - // default-clause | - // grainsize-clause | - // num-tasks-clause | - // collapse-clause | - // final-clause | - // priority-clause | - // untied-clause | - // mergeable-clause | - // nogroup-clause - case llvm::omp::Directive::OMPD_taskloop: { - SetContextAllowed(taskloopAllowedClauses); - SetContextAllowedOnce(taskloopAllowedOnceClauses); - SetContextAllowedExclusive(taskloopAllowedExclusiveClauses); - } break; - - // 2.9.3 taskloop-simd-clause -> taskloop-clause | - // simd-clause - case llvm::omp::Directive::OMPD_taskloop_simd: { - SetContextAllowed((taskloopAllowedClauses | simdAllowedClauses) - - llvm::omp::Clause::OMPC_reduction); - SetContextAllowedOnce(taskloopAllowedOnceClauses | simdAllowedOnceClauses); - SetContextAllowedExclusive(taskloopAllowedExclusiveClauses); - } break; - - // 2.10.8 distribute-clause -> private-clause | - // firstprivate-clause | - // lastprivate-clause | - // collapse-clause | - // dist-schedule-clause - case llvm::omp::Directive::OMPD_distribute: { - SetContextAllowed(distributeAllowedClauses); - SetContextAllowedOnce(distributeAllowedOnceClauses); - } break; - - // 2.10.9 distribute-simd-clause -> distribute-clause | - // simd-clause - case llvm::omp::Directive::OMPD_distribute_simd: { - SetContextAllowed(distributeAllowedClauses | simdAllowedClauses); - SetContextAllowedOnce( - distributeAllowedOnceClauses | simdAllowedOnceClauses); - } break; - - // 2.10.10 distribute-parallel-do-clause -> distribute-clause | - // parallel-do-clause - case llvm::omp::Directive::OMPD_distribute_parallel_do: { - SetContextAllowed( - distributeAllowedClauses | parallelAllowedClauses | doAllowedClauses); - SetContextAllowedOnce(distributeAllowedOnceClauses | - parallelAllowedOnceClauses | doAllowedOnceClauses); - } break; - - // 2.10.11 distribute-parallel-do-simd-clause -> distribute-clause | - // parallel-do-simd-clause - case llvm::omp::Directive::OMPD_distribute_parallel_do_simd: { - SetContextAllowed(distributeAllowedClauses | parallelAllowedClauses | - doAllowedClauses | simdAllowedClauses); - SetContextAllowedOnce(distributeAllowedOnceClauses | - parallelAllowedOnceClauses | doAllowedOnceClauses | simdAllowedClauses); - } break; - - // 2.11.6 target-parallel-do-clause -> target-clause | - // parallel-do-clause - case llvm::omp::Directive::OMPD_target_parallel_do: { - SetContextAllowed( - targetAllowedClauses | parallelAllowedClauses | doAllowedClauses); - SetContextAllowedOnce( - (targetAllowedOnceClauses | parallelAllowedOnceClauses | - doAllowedOnceClauses) - - llvm::omp::Clause::OMPC_nowait); - } break; - - // 2.11.7 target-parallel-do-simd-clause -> target-clause | - // parallel-do-simd-clause - case llvm::omp::Directive::OMPD_target_parallel_do_simd: { - SetContextAllowed(targetAllowedClauses | parallelAllowedClauses | - doAllowedClauses | simdAllowedClauses); - SetContextAllowedOnce( - (targetAllowedOnceClauses | parallelAllowedOnceClauses | - doAllowedOnceClauses | simdAllowedOnceClauses) - - llvm::omp::Clause::OMPC_nowait); - } break; - - // 2.11.8 target-simd-clause -> target-clause | - // simd-clause - case llvm::omp::Directive::OMPD_target_simd: { - SetContextAllowed(targetAllowedClauses | simdAllowedClauses); - SetContextAllowedOnce(targetAllowedOnceClauses | simdAllowedOnceClauses); - } break; - - // 2.11.10 teams-distribute-clause -> teams-clause | - // distribute-clause - case llvm::omp::Directive::OMPD_teams_distribute: { - SetContextAllowed(teamsAllowedClauses | distributeAllowedClauses); - SetContextAllowedOnce( - teamsAllowedOnceClauses | distributeAllowedOnceClauses); - } break; - - // 2.11.11 teams-distribute-simd-clause -> teams-clause | - // distribute-simd-clause - case llvm::omp::Directive::OMPD_teams_distribute_simd: { - SetContextAllowed( - teamsAllowedClauses | distributeAllowedClauses | simdAllowedClauses); - SetContextAllowedOnce(teamsAllowedOnceClauses | - distributeAllowedOnceClauses | simdAllowedOnceClauses); - } break; - - // 2.11.12 target-teams-distribute-clause -> target-clause | - // teams-distribute-clause - case llvm::omp::Directive::OMPD_target_teams_distribute: { - SetContextAllowed( - targetAllowedClauses | teamsAllowedClauses | distributeAllowedClauses); - SetContextAllowedOnce(targetAllowedOnceClauses | teamsAllowedOnceClauses | - distributeAllowedOnceClauses); - } break; - - // 2.11.13 target-teams-distribute-simd-clause -> target-clause | - // teams-distribute-simd-clause - case llvm::omp::Directive::OMPD_target_teams_distribute_simd: { - SetContextAllowed(targetAllowedClauses | teamsAllowedClauses | - distributeAllowedClauses | simdAllowedClauses); - SetContextAllowed(targetAllowedOnceClauses | teamsAllowedOnceClauses | - distributeAllowedOnceClauses | simdAllowedOnceClauses); - } break; - - // 2.11.14 teams-distribute-parallel-do-clause -> teams-clause | - // distribute-parallel-do-clause - case llvm::omp::Directive::OMPD_teams_distribute_parallel_do: { - SetContextAllowed(teamsAllowedClauses | distributeAllowedClauses | - parallelAllowedClauses | doAllowedClauses); - SetContextAllowedOnce(teamsAllowedOnceClauses | - distributeAllowedOnceClauses | parallelAllowedOnceClauses | - doAllowedOnceClauses); - } break; - - // 2.11.15 target-teams-distribute-parallel-do-clause -> target-clause | - // teams-distribute-parallel-do-clause - case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do: { - SetContextAllowed(targetAllowedClauses | teamsAllowedClauses | - distributeAllowedClauses | parallelAllowedClauses | doAllowedClauses); - SetContextAllowedOnce(targetAllowedOnceClauses | teamsAllowedOnceClauses | - distributeAllowedOnceClauses | parallelAllowedOnceClauses | - doAllowedOnceClauses); - } break; - - // 2.11.16 teams-distribute-parallel-do-clause -> teams-clause | - // distribute-parallel-do-simd-clause - case llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd: { - SetContextAllowed(teamsAllowedClauses | distributeAllowedClauses | - parallelAllowedClauses | doAllowedClauses | simdAllowedClauses); - SetContextAllowedOnce(teamsAllowedOnceClauses | - distributeAllowedOnceClauses | parallelAllowedOnceClauses | - doAllowedOnceClauses | simdAllowedOnceClauses); - } break; - - case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd: { - SetContextAllowed(targetAllowedClauses | teamsAllowedClauses | - distributeAllowedClauses | parallelAllowedClauses | doAllowedClauses | - simdAllowedClauses); - SetContextAllowedOnce(targetAllowedOnceClauses | teamsAllowedOnceClauses | - distributeAllowedOnceClauses | parallelAllowedOnceClauses | - doAllowedOnceClauses | simdAllowedOnceClauses); - } break; - - default: - // TODO others - break; + PushContextAndClauseSets(beginDir.source, llvm::omp::Directive::OMPD_do); } } @@ -436,12 +172,8 @@ // 2.7.1 end-do -> END DO [nowait-clause] // 2.8.3 end-do-simd -> END DO SIMD [nowait-clause] case llvm::omp::Directive::OMPD_do: - SetContextDirectiveEnum(llvm::omp::Directive::OMPD_end_do); - SetContextAllowed(OmpClauseSet{llvm::omp::Clause::OMPC_nowait}); - break; case llvm::omp::Directive::OMPD_do_simd: - SetContextDirectiveEnum(llvm::omp::Directive::OMPD_end_do_simd); - SetContextAllowed(OmpClauseSet{llvm::omp::Clause::OMPC_nowait}); + SetClauseSets(dir.v); break; default: // no clauses are allowed @@ -455,112 +187,7 @@ const auto &beginDir{ CheckMatching(beginBlockDir, endBlockDir)}; - PushContext(beginDir.source, beginDir.v); - switch (beginDir.v) { - // 2.5 parallel-clause -> if-clause | - // num-threads-clause | - // default-clause | - // private-clause | - // firstprivate-clause | - // shared-clause | - // copyin-clause | - // reduction-clause | - // proc-bind-clause - case llvm::omp::Directive::OMPD_parallel: { - // reserve for nesting check - SetContextAllowed(parallelAllowedClauses); - SetContextAllowedOnce(parallelAllowedOnceClauses); - } break; - // 2.7.3 single-clause -> private-clause | - // firstprivate-clause - case llvm::omp::Directive::OMPD_single: - SetContextAllowed({llvm::omp::Clause::OMPC_private, - llvm::omp::Clause::OMPC_firstprivate}); - break; - // 2.7.4 workshare (no clauses are allowed) - case llvm::omp::Directive::OMPD_workshare: - break; - // 2.11.3 parallel-workshare-clause -> parallel-clause - case llvm::omp::Directive::OMPD_parallel_workshare: { - SetContextAllowed(parallelAllowedClauses); - SetContextAllowedOnce(parallelAllowedOnceClauses); - } break; - // 2.9.1 task-clause -> if-clause | - // final-clause | - // untied-clause | - // default-clause | - // mergeable-clause | - // private-clause | - // firstprivate-clause | - // shared-clause | - // depend-clause | - // priority-clause - case llvm::omp::Directive::OMPD_task: { - OmpClauseSet allowed{llvm::omp::Clause::OMPC_untied, - llvm::omp::Clause::OMPC_default, llvm::omp::Clause::OMPC_mergeable, - llvm::omp::Clause::OMPC_private, llvm::omp::Clause::OMPC_firstprivate, - llvm::omp::Clause::OMPC_shared, llvm::omp::Clause::OMPC_depend}; - SetContextAllowed(allowed); - OmpClauseSet allowedOnce{llvm::omp::Clause::OMPC_if, - llvm::omp::Clause::OMPC_final, llvm::omp::Clause::OMPC_priority}; - SetContextAllowedOnce(allowedOnce); - } break; - // 2.10.4 target-clause -> if-clause | - // device-clause | - // private-clause | - // firstprivate-clause | - // map-clause | - // is-device-ptr-clause | - // defaultmap-clause | - // nowait-clause | - // depend-clause - case llvm::omp::Directive::OMPD_target: { - SetContextAllowed(targetAllowedClauses); - SetContextAllowedOnce(targetAllowedOnceClauses); - } break; - // 2.10.7 teams-clause -> num-teams-clause | - // thread-limit-clause | - // default-clause | - // private-clause | - // firstprivate-clause | - // shared-clause | - // reduction-clause - case llvm::omp::Directive::OMPD_teams: { - SetContextAllowed(teamsAllowedClauses); - SetContextAllowedOnce(teamsAllowedOnceClauses); - } break; - // 2.11.9 target-teams -> target-clause | - // teams-clause - case llvm::omp::Directive::OMPD_target_teams: { - SetContextAllowed(targetAllowedClauses | teamsAllowedClauses); - SetContextAllowedOnce(targetAllowedOnceClauses | teamsAllowedOnceClauses); - } break; - // 2.10.1 target-data-clause -> if-clause | - // device-clause | - // map-clause | - // use-device-ptr-clause - case llvm::omp::Directive::OMPD_target_data: { - OmpClauseSet allowed{llvm::omp::Clause::OMPC_if, - llvm::omp::Clause::OMPC_map, llvm::omp::Clause::OMPC_use_device_ptr}; - SetContextAllowed(allowed); - SetContextAllowedOnce({llvm::omp::Clause::OMPC_device}); - SetContextRequired({llvm::omp::Clause::OMPC_map}); - } break; - // 2.13.1 master (no clauses are allowed) - case llvm::omp::Directive::OMPD_master: - break; - // 2.11.5 target-parallel-clause -> target-clause | - // parallel-clause - case llvm::omp::Directive::OMPD_target_parallel: { - SetContextAllowed((targetAllowedClauses | parallelAllowedClauses) - - llvm::omp::Clause::OMPC_copyin); - SetContextAllowedOnce( - targetAllowedOnceClauses | parallelAllowedOnceClauses); - } break; - default: - // TODO others - break; - } + PushContextAndClauseSets(beginDir.source, beginDir.v); } void OmpStructureChecker::Leave(const parser::OpenMPBlockConstruct &) { @@ -574,25 +201,7 @@ const auto &beginDir{CheckMatching( beginSectionsDir, endSectionsDir)}; - PushContext(beginDir.source, beginDir.v); - switch (beginDir.v) { - // 2.7.2 sections-clause -> private-clause | - // firstprivate-clause | - // lastprivate-clause | - // reduction-clause - case llvm::omp::Directive::OMPD_sections: { - SetContextAllowed(sectionsAllowedClauses); - } break; - // 2.11.2 -> parallel-sections-clause -> parallel-clause | - // sections-clause - case llvm::omp::Directive::OMPD_parallel_sections: { - SetContextAllowed(parallelAllowedClauses | sectionsAllowedClauses); - SetContextAllowedOnce(parallelAllowedOnceClauses); - } break; - default: - // TODO others - break; - } + PushContextAndClauseSets(beginDir.source, beginDir.v); } void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &) { @@ -616,19 +225,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPDeclareSimdConstruct &x) { const auto &dir{std::get(x.t)}; - PushContext(dir.source, llvm::omp::Directive::OMPD_declare_simd); - // 2.8.2 declare-simd-clause -> simdlen-clause | - // linear-clause | - // aligned-clause | - // uniform-clause | - // inbranch-clause | - // notinbranch-clause - OmpClauseSet allowed{llvm::omp::Clause::OMPC_linear, - llvm::omp::Clause::OMPC_aligned, llvm::omp::Clause::OMPC_uniform}; - SetContextAllowed(allowed); - SetContextAllowedOnce({llvm::omp::Clause::OMPC_simdlen}); - SetContextAllowedExclusive( - {llvm::omp::Clause::OMPC_inbranch, llvm::omp::Clause::OMPC_notinbranch}); + PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_declare_simd); } void OmpStructureChecker::Leave(const parser::OpenMPDeclareSimdConstruct &) { @@ -652,57 +249,7 @@ void OmpStructureChecker::Enter( const parser::OpenMPSimpleStandaloneConstruct &x) { const auto &dir{std::get(x.t)}; - PushContext(dir.source, dir.v); - switch (dir.v) { - case llvm::omp::Directive::OMPD_barrier: { - // 2.13.3 barrier - } break; - case llvm::omp::Directive::OMPD_taskwait: { - // 2.13.4 taskwait - } break; - case llvm::omp::Directive::OMPD_taskyield: { - // 2.9.4 taskyield - } break; - case llvm::omp::Directive::OMPD_target_enter_data: { - // 2.10.2 target-enter-data-clause -> if-clause | - // device-clause | - // map-clause | - // depend-clause | - // nowait-clause - OmpClauseSet allowed{llvm::omp::Clause::OMPC_map, - llvm::omp::Clause::OMPC_depend, llvm::omp::Clause::OMPC_nowait}; - SetContextAllowed(allowed); - OmpClauseSet allowedOnce{ - llvm::omp::Clause::OMPC_device, llvm::omp::Clause::OMPC_if}; - SetContextAllowedOnce(allowedOnce); - SetContextRequired({llvm::omp::Clause::OMPC_map}); - } break; - case llvm::omp::Directive::OMPD_target_exit_data: { - // 2.10.3 target-enter-data-clause -> if-clause | - // device-clause | - // map-clause | - // depend-clause | - // nowait-clause - OmpClauseSet allowed{llvm::omp::Clause::OMPC_map, - llvm::omp::Clause::OMPC_depend, llvm::omp::Clause::OMPC_nowait}; - SetContextAllowed(allowed); - OmpClauseSet allowedOnce{ - llvm::omp::Clause::OMPC_device, llvm::omp::Clause::OMPC_if}; - SetContextAllowedOnce(allowedOnce); - SetContextRequired({llvm::omp::Clause::OMPC_map}); - } break; - case llvm::omp::Directive::OMPD_target_update: { - // 2.10.5 target-update - } break; - case llvm::omp::Directive::OMPD_ordered: { - // 2.13.8 ordered-construct-clause -> depend-clause - OmpClauseSet allowed{llvm::omp::Clause::OMPC_depend}; - SetContextAllowed(allowed); - } break; - default: - // TODO others - break; - } + PushContextAndClauseSets(dir.source, dir.v); } void OmpStructureChecker::Leave( @@ -712,7 +259,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPFlushConstruct &x) { const auto &dir{std::get(x.t)}; - PushContext(dir.source, llvm::omp::Directive::OMPD_flush); + PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_flush); } void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &) { @@ -721,7 +268,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPCancelConstruct &x) { const auto &dir{std::get(x.t)}; - PushContext(dir.source, llvm::omp::Directive::OMPD_cancel); + PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_cancel); } void OmpStructureChecker::Leave(const parser::OpenMPCancelConstruct &) { @@ -731,7 +278,8 @@ void OmpStructureChecker::Enter( const parser::OpenMPCancellationPointConstruct &x) { const auto &dir{std::get(x.t)}; - PushContext(dir.source, llvm::omp::Directive::OMPD_cancellation_point); + PushContextAndClauseSets( + dir.source, llvm::omp::Directive::OMPD_cancellation_point); } void OmpStructureChecker::Leave( diff --git a/flang/test/Semantics/omp-clause-validity01.f90 b/flang/test/Semantics/omp-clause-validity01.f90 --- a/flang/test/Semantics/omp-clause-validity01.f90 +++ b/flang/test/Semantics/omp-clause-validity01.f90 @@ -454,7 +454,6 @@ enddo !$omp end taskloop simd - !ERROR: REDUCTION clause is not allowed on the TASKLOOP SIMD directive !$omp taskloop simd reduction(+:a) do i = 1, N a = a + 3.14 diff --git a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td --- a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td +++ b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td @@ -39,6 +39,9 @@ // Generate include and macro to enable LLVM BitmaskEnum. bit enableBitmaskEnumInNamespace = 0; + + // EnumSet class name used for clauses to generated the allowed clauses map. + string clauseEnumSetClass = ""; } // Information about a specific clause. @@ -88,6 +91,9 @@ // List of clauses that are allowed to appear only once. list allowedOnceClauses = []; + // List of clauses that are allowed but mutually exclusive. + list allowedExclusiveClauses = []; + // List of clauses that are required. list requiredClauses = []; diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -23,6 +23,7 @@ let clausePrefix = "OMPC_"; let makeEnumAvailableInNamespace = 1; let enableBitmaskEnumInNamespace = 1; + let clauseEnumSetClass = "OmpClauseSet"; } //===----------------------------------------------------------------------===// @@ -200,10 +201,7 @@ def OMP_ThreadPrivate : Directive<"threadprivate"> {} def OMP_Parallel : Directive<"parallel"> { let allowedClauses = [ - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -211,11 +209,14 @@ VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + ]; } def OMP_Task : Directive<"task"> { let allowedClauses = [ - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -223,12 +224,16 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause + ]; } def OMP_Simd : Directive<"simd"> { let allowedClauses = [ @@ -236,15 +241,17 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + ]; } def OMP_For : Directive<"for"> { let allowedClauses = [ @@ -272,7 +279,8 @@ let allowedOnceClauses = [ VersionedClause, VersionedClause, - VersionedClause + VersionedClause, + VersionedClause ]; } def OMP_Sections : Directive<"sections"> { @@ -344,30 +352,34 @@ def OMP_Target : Directive<"target"> { let allowedClauses = [ VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause + ]; } def OMP_Teams : Directive<"teams"> { let allowedClauses = [ - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause + ]; } def OMP_Cancel : Directive<"cancel"> { let allowedClauses = [ @@ -385,50 +397,64 @@ } def OMP_TargetData : Directive<"target data"> { let allowedClauses = [ - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause + ]; + let requiredClauses = [ + VersionedClause + ]; } def OMP_TargetEnterData : Directive<"target enter data"> { let allowedClauses = [ + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause + VersionedClause ]; } def OMP_TargetExitData : Directive<"target exit data"> { let allowedClauses = [ - VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause + VersionedClause, + VersionedClause + ]; + let requiredClauses = [ + VersionedClause ]; } def OMP_TargetParallel : Directive<"target parallel"> { let allowedClauses = [ - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; } def OMP_TargetParallelFor : Directive<"target parallel for"> { let allowedClauses = [ @@ -458,28 +484,31 @@ } def OMP_TargetParallelDo : Directive<"target parallel do"> { let allowedClauses = [ - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause ]; } def OMP_TargetUpdate : Directive<"target update"> { @@ -558,27 +587,29 @@ } def OMP_ParallelDoSimd : Directive<"parallel do simd"> { let allowedClauses = [ - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; } def OMP_ParallelMaster : Directive<"parallel master"> { let allowedClauses = [ @@ -597,7 +628,6 @@ def OMP_ParallelSections : Directive<"parallel sections"> { let allowedClauses = [ VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -608,6 +638,9 @@ VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause + ]; } def OMP_ForSimd : Directive<"for simd"> { let allowedClauses = [ @@ -643,7 +676,8 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause + VersionedClause, + VersionedClause ]; } def OMP_CancellationPoint : Directive<"cancellation point"> {} @@ -653,53 +687,74 @@ VersionedClause ]; } -def OMP_DeclareSimd : Directive<"declare simd"> {} +def OMP_DeclareSimd : Directive<"declare simd"> { + let allowedClauses = [ + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause + ]; + let allowedExclusiveClauses = [ + VersionedClause, + VersionedClause + ]; +} def OMP_TaskLoop : Directive<"taskloop"> { let allowedClauses = [ - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + ]; + let allowedExclusiveClauses = [ + VersionedClause, + VersionedClause + ]; } def OMP_TaskLoopSimd : Directive<"taskloop simd"> { let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, + VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedExclusiveClauses = [ + VersionedClause, + VersionedClause ]; } def OMP_Distribute : Directive<"distribute"> { @@ -707,10 +762,12 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause + ]; } def OMP_DeclareTarget : Directive<"declare target"> {} def OMP_EndDeclareTarget : Directive<"end declare target"> {} @@ -735,21 +792,25 @@ } def OMP_DistributeParallelDo : Directive<"distribute parallel do"> { let allowedClauses = [ + VersionedClause, VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause + VersionedClause ]; } def OMP_DistributeParallelForSimd : Directive<"distribute parallel for simd"> { @@ -802,22 +863,31 @@ } def OMP_DistributeSimd : Directive<"distribute simd"> { let allowedClauses = [ - VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause ]; } + def OMP_TargetParallelForSimd : Directive<"target parallel for simd"> { let allowedClauses = [ VersionedClause, @@ -880,27 +950,33 @@ } def OMP_TargetSimd : Directive<"target simd"> { let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, + VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; } def OMP_TeamsDistribute : Directive<"teams distribute"> { let allowedClauses = [ @@ -919,26 +995,29 @@ } def OMP_TeamsDistributeSimd : Directive<"teams distribute simd"> { let allowedClauses = [ - VersionedClause, - VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ VersionedClause, + VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause + VersionedClause ]; } + def OMP_TeamsDistributeParallelForSimd : Directive<"teams distribute parallel for simd"> { let allowedClauses = [ @@ -968,27 +1047,29 @@ def OMP_TeamsDistributeParallelDoSimd : Directive<"teams distribute parallel do simd"> { let allowedClauses = [ + VersionedClause, VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause + VersionedClause, ]; } def OMP_TeamsDistributeParallelFor : @@ -1016,68 +1097,78 @@ def OMP_TeamsDistributeParallelDo : Directive<"teams distribute parallel do"> { let allowedClauses = [ + VersionedClause, VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; +let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause + VersionedClause ]; } def OMP_TargetTeams : Directive<"target teams"> { let allowedClauses = [ VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause + VersionedClause, + VersionedClause + ]; + + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause ]; } def OMP_TargetTeamsDistribute : Directive<"target teams distribute"> { let allowedClauses = [ VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause + VersionedClause ]; } + def OMP_TargetTeamsDistributeParallelFor : Directive<"target teams distribute parallel for"> { let allowedClauses = [ @@ -1110,28 +1201,33 @@ Directive<"target teams distribute parallel do"> { let allowedClauses = [ VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause ]; } def OMP_TargetTeamsDistributeParallelForSimd : @@ -1170,63 +1266,69 @@ def OMP_TargetTeamsDistributeParallelDoSimd : Directive<"target teams distribute parallel do simd"> { let allowedClauses = [ - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause + VersionedClause ]; } def OMP_TargetTeamsDistributeSimd : Directive<"target teams distribute simd"> { let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause ]; } def OMP_Allocate : Directive<"allocate"> { @@ -1359,7 +1461,22 @@ } def OMP_BeginDeclareVariant : Directive<"begin declare variant"> {} def OMP_EndDeclareVariant : Directive<"end declare variant"> {} -def OMP_ParallelWorkshare : Directive<"parallel workshare"> {} +def OMP_ParallelWorkshare : Directive<"parallel workshare"> { + let allowedClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause + ]; +} def OMP_Workshare : Directive<"workshare"> {} def OMP_EndDo : Directive<"end do"> {} def OMP_EndDoSimd : Directive<"end do simd"> {} diff --git a/llvm/lib/Frontend/OpenMP/OMPConstants.cpp b/llvm/lib/Frontend/OpenMP/OMPConstants.cpp --- a/llvm/lib/Frontend/OpenMP/OMPConstants.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPConstants.cpp @@ -19,6 +19,7 @@ using namespace omp; using namespace types; +#define GEN_ENUMS_IMPL #include "llvm/Frontend/OpenMP/OMP.cpp.inc" /// Declarations for LLVM-IR types (simple, array, function and structure) are diff --git a/llvm/test/TableGen/directive1.td b/llvm/test/TableGen/directive1.td --- a/llvm/test/TableGen/directive1.td +++ b/llvm/test/TableGen/directive1.td @@ -71,8 +71,10 @@ // CHECK-NEXT: } // namespace llvm // CHECK-NEXT: #endif // LLVM_Tdl_INC - -// IMPL: Directive llvm::tdl::getTdlDirectiveKind(llvm::StringRef Str) { +// IMPL: #ifdef GEN_ENUMS_IMPL +// IMPL-NEXT: #undef GEN_ENUMS_IMPL +// IMPL-EMPTY: +// IMPL-NEXT: Directive llvm::tdl::getTdlDirectiveKind(llvm::StringRef Str) { // IMPL-NEXT: return llvm::StringSwitch(Str) // IMPL-NEXT: .Case("dira",TDLD_dira) // IMPL-NEXT: .Default(TDLD_dira); @@ -112,3 +114,56 @@ // IMPL-NEXT: return true; // IMPL-NEXT: return false; // IMPL-NEXT: } +// IMPL-EMPTY: +// IMPL-NEXT: #endif // GEN_ENUMS_IMPL +// IMPL-EMPTY: +// IMPL-NEXT: #ifdef GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// IMPL-NEXT: #undef GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// IMPL-EMPTY: +// IMPL-NEXT: namespace llvm { +// IMPL-NEXT: namespace tdl { +// IMPL-EMPTY: +// IMPL-NEXT: // Sets for dira +// IMPL-EMPTY: +// IMPL-NEXT: static allowedClauses_TDLD_dira { +// IMPL-NEXT: llvm::tdl::Clause::TDLC_clausea, +// IMPL-NEXT: llvm::tdl::Clause::TDLC_clauseb, +// IMPL-NEXT: }; +// IMPL-EMPTY: +// IMPL-NEXT: static allowedOnceClauses_TDLD_dira { +// IMPL-NEXT: }; +// IMPL-EMPTY: +// IMPL-NEXT: static allowedExclusiveClauses_TDLD_dira { +// IMPL-NEXT: }; +// IMPL-EMPTY: +// IMPL-NEXT: static requiredClauses_TDLD_dira { +// IMPL-NEXT: }; +// IMPL-NEXT: } // namespace tdl +// IMPL-NEXT: } // namespace llvm +// IMPL-EMPTY: +// IMPL-NEXT: #endif // GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// IMPL-EMPTY: +// IMPL-NEXT: #ifdef GEN_FLANG_DIRECTIVE_CLAUSE_MAP +// IMPL-NEXT: #undef GEN_FLANG_DIRECTIVE_CLAUSE_MAP +// IMPL-EMPTY: +// IMPL-NEXT: struct TdlDirectiveClauses { +// IMPL-NEXT: const allowed; +// IMPL-NEXT: const allowedOnce; +// IMPL-NEXT: const allowedExclusive; +// IMPL-NEXT: const requiredOneOf; +// IMPL-NEXT: }; +// IMPL-EMPTY: +// IMPL-NEXT: std::unordered_map +// IMPL-NEXT: directiveClausesTable = { +// IMPL-NEXT: {llvm::tdl::Directive::TDLD_dira, +// IMPL-NEXT: { +// IMPL-NEXT: llvm::tdl::allowedClauses_TDLD_dira, +// IMPL-NEXT: llvm::tdl::allowedOnceClauses_TDLD_dira, +// IMPL-NEXT: llvm::tdl::allowedExclusiveClauses_TDLD_dira, +// IMPL-NEXT: llvm::tdl::requiredClauses_TDLD_dira, +// IMPL-NEXT: } +// IMPL-NEXT: }, +// IMPL-NEXT: }; +// IMPL-EMPTY: +// IMPL-NEXT: #endif // GEN_FLANG_DIRECTIVE_CLAUSE_MAP + diff --git a/llvm/test/TableGen/directive2.td b/llvm/test/TableGen/directive2.td --- a/llvm/test/TableGen/directive2.td +++ b/llvm/test/TableGen/directive2.td @@ -63,7 +63,10 @@ // CHECK-NEXT: #endif // LLVM_Tdl_INC -// IMPL: Directive llvm::tdl::getTdlDirectiveKind(llvm::StringRef Str) { +// IMPL: #ifdef GEN_ENUMS_IMPL +// IMPL-NEXT: #undef GEN_ENUMS_IMPL +// IMPL-EMPTY: +// IMPL-NEXT: Directive llvm::tdl::getTdlDirectiveKind(llvm::StringRef Str) { // IMPL-NEXT: return llvm::StringSwitch(Str) // IMPL-NEXT: .Case("dira",TDLD_dira) // IMPL-NEXT: .Default(TDLD_dira); @@ -103,4 +106,55 @@ // IMPL-NEXT: return true; // IMPL-NEXT: return false; // IMPL-NEXT: } - +// IMPL-EMPTY: +// IMPL-NEXT: #endif // GEN_ENUMS_IMPL +// IMPL-EMPTY: +// IMPL-NEXT: #ifdef GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// IMPL-NEXT: #undef GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// IMPL-EMPTY: +// IMPL-NEXT: namespace llvm { +// IMPL-NEXT: namespace tdl { +// IMPL-EMPTY: +// IMPL-NEXT: // Sets for dira +// IMPL-EMPTY: +// IMPL-NEXT: static allowedClauses_TDLD_dira { +// IMPL-NEXT: llvm::tdl::Clause::TDLC_clausea, +// IMPL-NEXT: llvm::tdl::Clause::TDLC_clauseb, +// IMPL-NEXT: }; +// IMPL-EMPTY: +// IMPL-NEXT: static allowedOnceClauses_TDLD_dira { +// IMPL-NEXT: }; +// IMPL-EMPTY: +// IMPL-NEXT: static allowedExclusiveClauses_TDLD_dira { +// IMPL-NEXT: }; +// IMPL-EMPTY: +// IMPL-NEXT: static requiredClauses_TDLD_dira { +// IMPL-NEXT: }; +// IMPL-NEXT: } // namespace tdl +// IMPL-NEXT: } // namespace llvm +// IMPL-EMPTY: +// IMPL-NEXT: #endif // GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// IMPL-EMPTY: +// IMPL-NEXT: #ifdef GEN_FLANG_DIRECTIVE_CLAUSE_MAP +// IMPL-NEXT: #undef GEN_FLANG_DIRECTIVE_CLAUSE_MAP +// IMPL-EMPTY: +// IMPL-NEXT: struct TdlDirectiveClauses { +// IMPL-NEXT: const allowed; +// IMPL-NEXT: const allowedOnce; +// IMPL-NEXT: const allowedExclusive; +// IMPL-NEXT: const requiredOneOf; +// IMPL-NEXT: }; +// IMPL-EMPTY: +// IMPL-NEXT: std::unordered_map +// IMPL-NEXT: directiveClausesTable = { +// IMPL-NEXT: {llvm::tdl::Directive::TDLD_dira, +// IMPL-NEXT: { +// IMPL-NEXT: llvm::tdl::allowedClauses_TDLD_dira, +// IMPL-NEXT: llvm::tdl::allowedOnceClauses_TDLD_dira, +// IMPL-NEXT: llvm::tdl::allowedExclusiveClauses_TDLD_dira, +// IMPL-NEXT: llvm::tdl::requiredClauses_TDLD_dira, +// IMPL-NEXT: } +// IMPL-NEXT: }, +// IMPL-NEXT: }; +// IMPL-EMPTY: +// IMPL-NEXT: #endif // GEN_FLANG_DIRECTIVE_CLAUSE_MAP diff --git a/llvm/utils/TableGen/DirectiveEmitter.cpp b/llvm/utils/TableGen/DirectiveEmitter.cpp --- a/llvm/utils/TableGen/DirectiveEmitter.cpp +++ b/llvm/utils/TableGen/DirectiveEmitter.cpp @@ -20,6 +20,23 @@ using namespace llvm; +namespace { +// Simple RAII helper for defining ifdef-undef-endif scopes. +class IfDefScope { +public: + IfDefScope(StringRef Name, raw_ostream &OS) : Name(Name), OS(OS) { + OS << "#ifdef " << Name << "\n" + << "#undef " << Name << "\n"; + } + + ~IfDefScope() { OS << "\n#endif // " << Name << "\n\n"; } + +private: + StringRef Name; + raw_ostream &OS; +}; +} // end anonymous namespace + namespace llvm { // Get Directive or Clause name formatted by replacing whitespaces with @@ -245,6 +262,11 @@ GenerateTestForAllowedClauses(AllowedOnceClauses, OS, DirectiveName, DirectivePrefix, ClausePrefix); + const auto &AllowedExclusiveClauses = + D->getValueAsListOfDefs("allowedExclusiveClauses"); + GenerateTestForAllowedClauses(AllowedExclusiveClauses, OS, DirectiveName, + DirectivePrefix, ClausePrefix); + const auto &RequiredClauses = D->getValueAsListOfDefs("requiredClauses"); GenerateTestForAllowedClauses(RequiredClauses, OS, DirectiveName, DirectivePrefix, ClausePrefix); @@ -253,27 +275,132 @@ OS << "}\n"; } -// Generate the implemenation section for the enumeration in the directive -// language -void EmitDirectivesImpl(RecordKeeper &Records, raw_ostream &OS) { +// Generate a simple enum set with the give clauses. +void GenerateClauseSet(const std::vector &Clauses, raw_ostream &OS, + StringRef ClauseEnumSetClass, StringRef ClauseSetPrefix, + StringRef DirectiveName, StringRef DirectivePrefix, + StringRef ClausePrefix, StringRef CppNamespace) { - const auto &DirectiveLanguages = - Records.getAllDerivedDefinitions("DirectiveLanguage"); + OS << "\n"; + OS << " static " << ClauseEnumSetClass << " " << ClauseSetPrefix + << DirectivePrefix << getFormattedName(DirectiveName) << " {\n"; - if (DirectiveLanguages.size() != 1) { - PrintError("A single definition of DirectiveLanguage is needed."); - return; + for (const auto &C : Clauses) { + const auto SpecificClause = C->getValueAsDef("clause"); + const auto ClauseName = SpecificClause->getValueAsString("name"); + OS << " llvm::" << CppNamespace << "::Clause::" << ClausePrefix + << getFormattedName(ClauseName) << ",\n"; } + OS << " };\n"; +} - const auto &DirectiveLanguage = DirectiveLanguages[0]; - StringRef DirectivePrefix = - DirectiveLanguage->getValueAsString("directivePrefix"); - StringRef LanguageName = DirectiveLanguage->getValueAsString("name"); - StringRef ClausePrefix = DirectiveLanguage->getValueAsString("clausePrefix"); - StringRef CppNamespace = DirectiveLanguage->getValueAsString("cppNamespace"); +// Generate an enum set for the 4 kinds of clauses linked to a directive. +void GenerateDirectiveClauseSets(const std::vector &Directives, + raw_ostream &OS, StringRef LanguageName, + StringRef ClauseEnumSetClass, + StringRef DirectivePrefix, + StringRef ClausePrefix, + StringRef CppNamespace) { - const auto &Directives = Records.getAllDerivedDefinitions("Directive"); - const auto &Clauses = Records.getAllDerivedDefinitions("Clause"); + IfDefScope Scope("GEN_FLANG_DIRECTIVE_CLAUSE_SETS", OS); + + OS << "\n"; + OS << "namespace llvm {\n"; + + // Open namespaces defined in the directive language. + llvm::SmallVector Namespaces; + llvm::SplitString(CppNamespace, Namespaces, "::"); + for (auto Ns : Namespaces) + OS << "namespace " << Ns << " {\n"; + + for (const auto &D : Directives) { + const auto DirectiveName = D->getValueAsString("name"); + + const auto &AllowedClauses = D->getValueAsListOfDefs("allowedClauses"); + const auto &AllowedOnceClauses = + D->getValueAsListOfDefs("allowedOnceClauses"); + const auto &AllowedExclusiveClauses = + D->getValueAsListOfDefs("allowedExclusiveClauses"); + const auto &RequiredClauses = D->getValueAsListOfDefs("requiredClauses"); + + OS << "\n"; + OS << " // Sets for " << DirectiveName << "\n"; + + GenerateClauseSet(AllowedClauses, OS, ClauseEnumSetClass, "allowedClauses_", + DirectiveName, DirectivePrefix, ClausePrefix, + CppNamespace); + GenerateClauseSet(AllowedOnceClauses, OS, ClauseEnumSetClass, + "allowedOnceClauses_", DirectiveName, DirectivePrefix, + ClausePrefix, CppNamespace); + GenerateClauseSet(AllowedExclusiveClauses, OS, ClauseEnumSetClass, + "allowedExclusiveClauses_", DirectiveName, + DirectivePrefix, ClausePrefix, CppNamespace); + GenerateClauseSet(RequiredClauses, OS, ClauseEnumSetClass, + "requiredClauses_", DirectiveName, DirectivePrefix, + ClausePrefix, CppNamespace); + } + + // Closing namespaces + for (auto Ns : llvm::reverse(Namespaces)) + OS << "} // namespace " << Ns << "\n"; + + OS << "} // namespace llvm\n"; +} + +// Generate a map of directive (key) with DirectiveClauses struct as values. +// The struct holds the 4 sets of enumeration for the 4 kinds of clauses +// allowances (allowed, allowed once, allowed exclusive and required). +void GenerateDirectiveClauseMap(const std::vector &Directives, + raw_ostream &OS, StringRef LanguageName, + StringRef ClauseEnumSetClass, + StringRef DirectivePrefix, + StringRef ClausePrefix, + StringRef CppNamespace) { + + IfDefScope Scope("GEN_FLANG_DIRECTIVE_CLAUSE_MAP", OS); + + OS << "\n"; + OS << "struct " << LanguageName << "DirectiveClauses {\n"; + OS << " const " << ClauseEnumSetClass << " allowed;\n"; + OS << " const " << ClauseEnumSetClass << " allowedOnce;\n"; + OS << " const " << ClauseEnumSetClass << " allowedExclusive;\n"; + OS << " const " << ClauseEnumSetClass << " requiredOneOf;\n"; + OS << "};\n"; + + OS << "\n"; + + OS << "std::unordered_map\n"; + OS << " directiveClausesTable = {\n"; + + for (const auto &D : Directives) { + const auto FormattedDirectiveName = + getFormattedName(D->getValueAsString("name")); + OS << " {llvm::" << CppNamespace << "::Directive::" << DirectivePrefix + << FormattedDirectiveName << ",\n"; + OS << " {\n"; + OS << " llvm::" << CppNamespace << "::allowedClauses_" + << DirectivePrefix << FormattedDirectiveName << ",\n"; + OS << " llvm::" << CppNamespace << "::allowedOnceClauses_" + << DirectivePrefix << FormattedDirectiveName << ",\n"; + OS << " llvm::" << CppNamespace << "::allowedExclusiveClauses_" + << DirectivePrefix << FormattedDirectiveName << ",\n"; + OS << " llvm::" << CppNamespace << "::requiredClauses_" + << DirectivePrefix << FormattedDirectiveName << ",\n"; + OS << " }\n"; + OS << " },\n"; + } + + OS << "};\n"; +} + +void EmitDirectivesGeneralImpl(const std::vector &Directives, + const std::vector &Clauses, + raw_ostream &OS, StringRef LanguageName, + StringRef DirectivePrefix, + StringRef ClausePrefix, StringRef CppNamespace) { + + IfDefScope Scope("GEN_ENUMS_IMPL", OS); // getDirectiveKind(StringRef Str) GenerateGetKind(Directives, OS, "Directive", DirectivePrefix, LanguageName, @@ -291,8 +418,55 @@ GenerateGetName(Clauses, OS, "Clause", ClausePrefix, LanguageName, CppNamespace); + // isAllowedClauseForDirective(Directive D, Clause C, unsigned Version) GenerateIsAllowedClause(Directives, OS, DirectivePrefix, ClausePrefix, CppNamespace); } +// Generate the implemenation section for the enumeration in the directive +// language +void EmitDirectivesFlangImpl(const std::vector &Directives, + raw_ostream &OS, StringRef LanguageName, + StringRef ClauseEnumSetClass, + StringRef DirectivePrefix, StringRef ClausePrefix, + StringRef CppNamespace) { + + GenerateDirectiveClauseSets(Directives, OS, LanguageName, ClauseEnumSetClass, + DirectivePrefix, ClausePrefix, CppNamespace); + + GenerateDirectiveClauseMap(Directives, OS, LanguageName, ClauseEnumSetClass, + DirectivePrefix, ClausePrefix, CppNamespace); +} + +// Generate the implemenation section for the enumeration in the directive +// language +void EmitDirectivesImpl(RecordKeeper &Records, raw_ostream &OS) { + + const auto &DirectiveLanguages = + Records.getAllDerivedDefinitions("DirectiveLanguage"); + + if (DirectiveLanguages.size() != 1) { + PrintError("A single definition of DirectiveLanguage is needed."); + return; + } + + const auto &DirectiveLanguage = DirectiveLanguages[0]; + StringRef DirectivePrefix = + DirectiveLanguage->getValueAsString("directivePrefix"); + StringRef LanguageName = DirectiveLanguage->getValueAsString("name"); + StringRef ClausePrefix = DirectiveLanguage->getValueAsString("clausePrefix"); + StringRef CppNamespace = DirectiveLanguage->getValueAsString("cppNamespace"); + StringRef ClauseEnumSetClass = + DirectiveLanguage->getValueAsString("clauseEnumSetClass"); + + const auto &Directives = Records.getAllDerivedDefinitions("Directive"); + const auto &Clauses = Records.getAllDerivedDefinitions("Clause"); + + EmitDirectivesGeneralImpl(Directives, Clauses, OS, LanguageName, + DirectivePrefix, ClausePrefix, CppNamespace); + + EmitDirectivesFlangImpl(Directives, OS, LanguageName, ClauseEnumSetClass, + DirectivePrefix, ClausePrefix, CppNamespace); +} + } // namespace llvm