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 @@ -458,7 +458,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 @@ -43,6 +43,9 @@ // Header file included in the implementation code generated. Ususally the // output file of the declaration code generation. Can be left blank. string includeHeader = ""; + + // EnumSet class name used for clauses to generated the allowed clauses map. + string clauseEnumSetClass = ""; } // Information about a specific clause. @@ -92,6 +95,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/CMakeLists.txt b/llvm/include/llvm/Frontend/OpenMP/CMakeLists.txt --- a/llvm/include/llvm/Frontend/OpenMP/CMakeLists.txt +++ b/llvm/include/llvm/Frontend/OpenMP/CMakeLists.txt @@ -1,3 +1,4 @@ set(LLVM_TARGET_DEFINITIONS OMP.td) tablegen(LLVM OMP.h.inc --gen-directive-decl) +tablegen(LLVM OMP.cpp.inc --gen-directive-gen) add_public_tablegen_target(omp_gen) 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 @@ -24,6 +24,7 @@ let makeEnumAvailableInNamespace = 1; let enableBitmaskEnumInNamespace = 1; let includeHeader = "llvm/Frontend/OpenMP/OMP.h.inc"; + let clauseEnumSetClass = "OmpClauseSet"; } //===----------------------------------------------------------------------===// @@ -201,10 +202,7 @@ def OMP_ThreadPrivate : Directive<"threadprivate"> {} def OMP_Parallel : Directive<"parallel"> { let allowedClauses = [ - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -212,11 +210,14 @@ VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + ]; } def OMP_Task : Directive<"task"> { let allowedClauses = [ - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -224,12 +225,16 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause + ]; } def OMP_Simd : Directive<"simd"> { let allowedClauses = [ @@ -237,15 +242,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 = [ @@ -273,7 +280,8 @@ let allowedOnceClauses = [ VersionedClause, VersionedClause, - VersionedClause + VersionedClause, + VersionedClause ]; } def OMP_Sections : Directive<"sections"> { @@ -345,30 +353,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 = [ @@ -386,50 +398,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 = [ @@ -459,27 +485,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 + ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause ]; } def OMP_TargetUpdate : Directive<"target update"> { @@ -558,27 +588,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 +629,6 @@ def OMP_ParallelSections : Directive<"parallel sections"> { let allowedClauses = [ VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -608,6 +639,9 @@ VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause + ]; } def OMP_ForSimd : Directive<"for simd"> { let allowedClauses = [ @@ -643,7 +677,8 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause + VersionedClause, + VersionedClause ]; } def OMP_CancellationPoint : Directive<"cancellation point"> {} @@ -653,53 +688,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 +763,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 +793,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 +864,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 +951,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 +996,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 +1048,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 +1098,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 +1202,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 +1267,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 +1462,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/test/TableGen/directive1.td b/llvm/test/TableGen/directive1.td --- a/llvm/test/TableGen/directive1.td +++ b/llvm/test/TableGen/directive1.td @@ -1,5 +1,6 @@ // RUN: llvm-tblgen -gen-directive-decl -I %p/../../include %s | FileCheck -match-full-lines %s // RUN: llvm-tblgen -gen-directive-impl -I %p/../../include %s | FileCheck -match-full-lines %s -check-prefix=IMPL +// RUN: llvm-tblgen -gen-directive-gen -I %p/../../include %s | FileCheck -match-full-lines %s -check-prefix=GEN include "llvm/Frontend/Directive/DirectiveBase.td" @@ -126,3 +127,57 @@ // IMPL-NEXT: } // IMPL-NEXT: llvm_unreachable("Invalid Tdl Directive kind"); // IMPL-NEXT: } +// IMPL-EMPTY: + + + +// GEN: #ifdef GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// GEN-NEXT: #undef GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// GEN-EMPTY: +// GEN-NEXT: namespace llvm { +// GEN-NEXT: namespace tdl { +// GEN-EMPTY: +// GEN-NEXT: // Sets for dira +// GEN-EMPTY: +// GEN-NEXT: static allowedClauses_TDLD_dira { +// GEN-NEXT: llvm::tdl::Clause::TDLC_clausea, +// GEN-NEXT: llvm::tdl::Clause::TDLC_clauseb, +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: static allowedOnceClauses_TDLD_dira { +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: static allowedExclusiveClauses_TDLD_dira { +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: static requiredClauses_TDLD_dira { +// GEN-NEXT: }; +// GEN-NEXT: } // namespace tdl +// GEN-NEXT: } // namespace llvm +// GEN-EMPTY: +// GEN-NEXT: #endif // GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// GEN-EMPTY: +// GEN-NEXT: #ifdef GEN_FLANG_DIRECTIVE_CLAUSE_MAP +// GEN-NEXT: #undef GEN_FLANG_DIRECTIVE_CLAUSE_MAP +// GEN-EMPTY: +// GEN-NEXT: struct TdlDirectiveClauses { +// GEN-NEXT: const allowed; +// GEN-NEXT: const allowedOnce; +// GEN-NEXT: const allowedExclusive; +// GEN-NEXT: const requiredOneOf; +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: std::unordered_map +// GEN-NEXT: directiveClausesTable = { +// GEN-NEXT: {llvm::tdl::Directive::TDLD_dira, +// GEN-NEXT: { +// GEN-NEXT: llvm::tdl::allowedClauses_TDLD_dira, +// GEN-NEXT: llvm::tdl::allowedOnceClauses_TDLD_dira, +// GEN-NEXT: llvm::tdl::allowedExclusiveClauses_TDLD_dira, +// GEN-NEXT: llvm::tdl::requiredClauses_TDLD_dira, +// GEN-NEXT: } +// GEN-NEXT: }, +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-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 @@ -1,5 +1,6 @@ // RUN: llvm-tblgen -gen-directive-decl -I %p/../../include %s | FileCheck -match-full-lines %s // RUN: llvm-tblgen -gen-directive-impl -I %p/../../include %s | FileCheck -match-full-lines %s -check-prefix=IMPL +// RUN: llvm-tblgen -gen-directive-gen -I %p/../../include %s | FileCheck -match-full-lines %s -check-prefix=GEN include "llvm/Frontend/Directive/DirectiveBase.td" @@ -71,7 +72,7 @@ // IMPL-NEXT: using namespace llvm; // IMPL-NEXT: using namespace tdl; // IMPL-EMPTY: -// IMPL: Directive llvm::tdl::getTdlDirectiveKind(llvm::StringRef Str) { +// 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); @@ -119,3 +120,54 @@ // IMPL-NEXT: } // IMPL-NEXT: llvm_unreachable("Invalid Tdl Directive kind"); // IMPL-NEXT: } + + +// GEN: #ifdef GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// GEN-NEXT: #undef GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// GEN-EMPTY: +// GEN-NEXT: namespace llvm { +// GEN-NEXT: namespace tdl { +// GEN-EMPTY: +// GEN-NEXT: // Sets for dira +// GEN-EMPTY: +// GEN-NEXT: static allowedClauses_TDLD_dira { +// GEN-NEXT: llvm::tdl::Clause::TDLC_clausea, +// GEN-NEXT: llvm::tdl::Clause::TDLC_clauseb, +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: static allowedOnceClauses_TDLD_dira { +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: static allowedExclusiveClauses_TDLD_dira { +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: static requiredClauses_TDLD_dira { +// GEN-NEXT: }; +// GEN-NEXT: } // namespace tdl +// GEN-NEXT: } // namespace llvm +// GEN-EMPTY: +// GEN-NEXT: #endif // GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// GEN-EMPTY: +// GEN-NEXT: #ifdef GEN_FLANG_DIRECTIVE_CLAUSE_MAP +// GEN-NEXT: #undef GEN_FLANG_DIRECTIVE_CLAUSE_MAP +// GEN-EMPTY: +// GEN-NEXT: struct TdlDirectiveClauses { +// GEN-NEXT: const allowed; +// GEN-NEXT: const allowedOnce; +// GEN-NEXT: const allowedExclusive; +// GEN-NEXT: const requiredOneOf; +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: std::unordered_map +// GEN-NEXT: directiveClausesTable = { +// GEN-NEXT: {llvm::tdl::Directive::TDLD_dira, +// GEN-NEXT: { +// GEN-NEXT: llvm::tdl::allowedClauses_TDLD_dira, +// GEN-NEXT: llvm::tdl::allowedOnceClauses_TDLD_dira, +// GEN-NEXT: llvm::tdl::allowedExclusiveClauses_TDLD_dira, +// GEN-NEXT: llvm::tdl::requiredClauses_TDLD_dira, +// GEN-NEXT: } +// GEN-NEXT: }, +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-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 @@ -14,12 +14,30 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSet.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" 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 @@ -205,16 +223,21 @@ void GenerateCaseForVersionedClauses(const std::vector &Clauses, raw_ostream &OS, StringRef DirectiveName, StringRef DirectivePrefix, - StringRef ClausePrefix) { + StringRef ClausePrefix, + llvm::StringSet<> &Cases) { for (const auto &C : Clauses) { const auto MinVersion = C->getValueAsInt("minVersion"); const auto MaxVersion = C->getValueAsInt("maxVersion"); const auto SpecificClause = C->getValueAsDef("clause"); - const auto ClauseName = SpecificClause->getValueAsString("name"); - OS << " case " << ClausePrefix << getFormattedName(ClauseName) - << ":\n"; - OS << " return " << MinVersion << " <= Version && " << MaxVersion - << " >= Version;\n"; + const auto ClauseName = + getFormattedName(SpecificClause->getValueAsString("name")); + + if (Cases.find(ClauseName) == Cases.end()) { + Cases.insert(ClauseName); + OS << " case " << ClausePrefix << ClauseName << ":\n"; + OS << " return " << MinVersion << " <= Version && " << MaxVersion + << " >= Version;\n"; + } } } @@ -239,24 +262,32 @@ 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 << " case " << DirectivePrefix << getFormattedName(DirectiveName) << ":\n"; - if (AllowedClauses.size() == 0 && AllowedOnceClauses.size() == 0 && - AllowedOnceClauses.size() == 0) { + if (AllowedClauses.size() == 0 && AllowedOnceClauses.size() == 0 && + AllowedExclusiveClauses.size() == 0 && RequiredClauses.size() == 0) { OS << " return false;\n"; } else { OS << " switch (C) {\n"; + llvm::StringSet<> Cases; + GenerateCaseForVersionedClauses(AllowedClauses, OS, DirectiveName, - DirectivePrefix, ClausePrefix); + DirectivePrefix, ClausePrefix, Cases); GenerateCaseForVersionedClauses(AllowedOnceClauses, OS, DirectiveName, - DirectivePrefix, ClausePrefix); + DirectivePrefix, ClausePrefix, Cases); + + GenerateCaseForVersionedClauses(AllowedExclusiveClauses, OS, + DirectiveName, DirectivePrefix, + ClausePrefix, Cases); GenerateCaseForVersionedClauses(RequiredClauses, OS, DirectiveName, - DirectivePrefix, ClausePrefix); + DirectivePrefix, ClausePrefix, Cases); OS << " default:\n"; OS << " return false;\n"; @@ -271,9 +302,143 @@ OS << "}\n"; // End of function isAllowedClauseForDirective } +// 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) { + + OS << "\n"; + OS << " static " << ClauseEnumSetClass << " " << ClauseSetPrefix + << DirectivePrefix << getFormattedName(DirectiveName) << " {\n"; + + 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"; +} + +// 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) { + + 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"; +} + // Generate the implemenation section for the enumeration in the directive // language -void EmitDirectivesImpl(RecordKeeper &Records, raw_ostream &OS) { +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 EmitDirectivesGen(RecordKeeper &Records, raw_ostream &OS) { const auto &DirectiveLanguages = Records.getAllDerivedDefinitions("DirectiveLanguage"); @@ -289,12 +454,40 @@ StringRef LanguageName = DirectiveLanguage->getValueAsString("name"); StringRef ClausePrefix = DirectiveLanguage->getValueAsString("clausePrefix"); StringRef CppNamespace = DirectiveLanguage->getValueAsString("cppNamespace"); - StringRef IncludeHeader = - DirectiveLanguage->getValueAsString("includeHeader"); + StringRef ClauseEnumSetClass = + DirectiveLanguage->getValueAsString("clauseEnumSetClass"); const auto &Directives = Records.getAllDerivedDefinitions("Directive"); const auto &Clauses = Records.getAllDerivedDefinitions("Clause"); + EmitDirectivesFlangImpl(Directives, OS, LanguageName, ClauseEnumSetClass, + DirectivePrefix, ClausePrefix, CppNamespace); +} + +// Generate the implemenation for the enumeration in the directive +// language. This code can be included in library. +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"); + const auto &Directives = Records.getAllDerivedDefinitions("Directive"); + const auto &Clauses = Records.getAllDerivedDefinitions("Clause"); + + StringRef IncludeHeader = + DirectiveLanguage->getValueAsString("includeHeader"); + if (!IncludeHeader.empty()) OS << "#include \"" << IncludeHeader << "\"\n\n"; @@ -323,6 +516,7 @@ GenerateGetName(Clauses, OS, "Clause", ClausePrefix, LanguageName, CppNamespace); + // isAllowedClauseForDirective(Directive D, Clause C, unsigned Version) GenerateIsAllowedClause(Directives, OS, LanguageName, DirectivePrefix, ClausePrefix, CppNamespace); } diff --git a/llvm/utils/TableGen/TableGen.cpp b/llvm/utils/TableGen/TableGen.cpp --- a/llvm/utils/TableGen/TableGen.cpp +++ b/llvm/utils/TableGen/TableGen.cpp @@ -56,6 +56,7 @@ GenAutomata, GenDirectivesEnumDecl, GenDirectivesEnumImpl, + GenDirectivesEnumGen, }; namespace llvm { @@ -132,9 +133,11 @@ "Generate llvm-exegesis tables"), clEnumValN(GenAutomata, "gen-automata", "Generate generic automata"), clEnumValN(GenDirectivesEnumDecl, "gen-directive-decl", - "Generate directive related declaration code"), + "Generate directive related declaration code (header file)"), clEnumValN(GenDirectivesEnumImpl, "gen-directive-impl", - "Generate directive related implementation code"))); + "Generate directive related implementation code"), + clEnumValN(GenDirectivesEnumGen, "gen-directive-gen", + "Generate directive related implementation code part"))); cl::OptionCategory PrintEnumsCat("Options for -print-enums"); cl::opt Class("class", cl::desc("Print Enum list for this class"), @@ -265,6 +268,9 @@ case GenDirectivesEnumImpl: EmitDirectivesImpl(Records, OS); break; + case GenDirectivesEnumGen: + EmitDirectivesGen(Records, OS); + break; } return false; diff --git a/llvm/utils/TableGen/TableGenBackends.h b/llvm/utils/TableGen/TableGenBackends.h --- a/llvm/utils/TableGen/TableGenBackends.h +++ b/llvm/utils/TableGen/TableGenBackends.h @@ -92,6 +92,7 @@ void EmitAutomata(RecordKeeper &RK, raw_ostream &OS); void EmitDirectivesDecl(RecordKeeper &RK, raw_ostream &OS); void EmitDirectivesImpl(RecordKeeper &RK, raw_ostream &OS); +void EmitDirectivesGen(RecordKeeper &RK, raw_ostream &OS); } // End llvm namespace