Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 1 | //===-- lib/Semantics/check-acc-structure.cpp -----------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 8 | #include "check-acc-structure.h" |
| 9 | #include "flang/Parser/parse-tree.h" |
| 10 | #include "flang/Semantics/tools.h" |
| 11 | |
| 12 | #define CHECK_SIMPLE_CLAUSE(X, Y) \ |
| 13 | void AccStructureChecker::Enter(const parser::AccClause::X &) { \ |
| 14 | CheckAllowed(llvm::acc::Clause::Y); \ |
| 15 | } |
| 16 | |
| 17 | #define CHECK_REQ_SCALAR_INT_CONSTANT_CLAUSE(X, Y) \ |
| 18 | void AccStructureChecker::Enter(const parser::AccClause::X &c) { \ |
| 19 | CheckAllowed(llvm::acc::Clause::Y); \ |
| 20 | RequiresConstantPositiveParameter(llvm::acc::Clause::Y, c.v); \ |
| 21 | } |
| 22 | |
| 23 | namespace Fortran::semantics { |
| 24 | |
| 25 | static constexpr inline AccClauseSet |
Valentin Clement | d553243 | 2020-12-08 19:36:24 | [diff] [blame] | 26 | computeConstructOnlyAllowedAfterDeviceTypeClauses{ |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 27 | llvm::acc::Clause::ACCC_async, llvm::acc::Clause::ACCC_wait, |
| 28 | llvm::acc::Clause::ACCC_num_gangs, llvm::acc::Clause::ACCC_num_workers, |
| 29 | llvm::acc::Clause::ACCC_vector_length}; |
| 30 | |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 31 | static constexpr inline AccClauseSet loopOnlyAllowedAfterDeviceTypeClauses{ |
| 32 | llvm::acc::Clause::ACCC_auto, llvm::acc::Clause::ACCC_collapse, |
| 33 | llvm::acc::Clause::ACCC_independent, llvm::acc::Clause::ACCC_gang, |
| 34 | llvm::acc::Clause::ACCC_seq, llvm::acc::Clause::ACCC_tile, |
| 35 | llvm::acc::Clause::ACCC_vector, llvm::acc::Clause::ACCC_worker}; |
| 36 | |
| 37 | static constexpr inline AccClauseSet updateOnlyAllowedAfterDeviceTypeClauses{ |
| 38 | llvm::acc::Clause::ACCC_async, llvm::acc::Clause::ACCC_wait}; |
| 39 | |
| 40 | static constexpr inline AccClauseSet routineOnlyAllowedAfterDeviceTypeClauses{ |
| 41 | llvm::acc::Clause::ACCC_bind, llvm::acc::Clause::ACCC_gang, |
| 42 | llvm::acc::Clause::ACCC_vector, llvm::acc::Clause::ACCC_worker}; |
| 43 | |
Valentin Clement | 75ba29a | 2020-10-29 13:53:10 | [diff] [blame] | 44 | bool AccStructureChecker::CheckAllowedModifier(llvm::acc::Clause clause) { |
| 45 | if (GetContext().directive == llvm::acc::ACCD_enter_data || |
| 46 | GetContext().directive == llvm::acc::ACCD_exit_data) { |
| 47 | context_.Say(GetContext().clauseSource, |
| 48 | "Modifier is not allowed for the %s clause " |
| 49 | "on the %s directive"_err_en_US, |
| 50 | parser::ToUpperCaseLetters(getClauseName(clause).str()), |
| 51 | ContextDirectiveAsFortran()); |
| 52 | return true; |
| 53 | } |
| 54 | return false; |
| 55 | } |
| 56 | |
Valentin Clement | b53115b | 2020-12-08 20:14:24 | [diff] [blame] | 57 | bool AccStructureChecker::IsComputeConstruct( |
| 58 | llvm::acc::Directive directive) const { |
| 59 | return directive == llvm::acc::ACCD_parallel || |
| 60 | directive == llvm::acc::ACCD_parallel_loop || |
| 61 | directive == llvm::acc::ACCD_serial || |
| 62 | directive == llvm::acc::ACCD_serial_loop || |
| 63 | directive == llvm::acc::ACCD_kernels || |
| 64 | directive == llvm::acc::ACCD_kernels_loop; |
| 65 | } |
| 66 | |
| 67 | bool AccStructureChecker::IsInsideComputeConstruct() const { |
Diana Picus | 45cd405 | 2021-06-11 09:07:23 | [diff] [blame] | 68 | if (dirContext_.size() <= 1) { |
Valentin Clement | b53115b | 2020-12-08 20:14:24 | [diff] [blame] | 69 | return false; |
Diana Picus | 45cd405 | 2021-06-11 09:07:23 | [diff] [blame] | 70 | } |
Valentin Clement | b53115b | 2020-12-08 20:14:24 | [diff] [blame] | 71 | |
| 72 | // Check all nested context skipping the first one. |
| 73 | for (std::size_t i = dirContext_.size() - 1; i > 0; --i) { |
Diana Picus | 45cd405 | 2021-06-11 09:07:23 | [diff] [blame] | 74 | if (IsComputeConstruct(dirContext_[i - 1].directive)) { |
Valentin Clement | b53115b | 2020-12-08 20:14:24 | [diff] [blame] | 75 | return true; |
Diana Picus | 45cd405 | 2021-06-11 09:07:23 | [diff] [blame] | 76 | } |
Valentin Clement | b53115b | 2020-12-08 20:14:24 | [diff] [blame] | 77 | } |
| 78 | return false; |
| 79 | } |
| 80 | |
| 81 | void AccStructureChecker::CheckNotInComputeConstruct() { |
Diana Picus | 45cd405 | 2021-06-11 09:07:23 | [diff] [blame] | 82 | if (IsInsideComputeConstruct()) { |
Valentin Clement | b53115b | 2020-12-08 20:14:24 | [diff] [blame] | 83 | context_.Say(GetContext().directiveSource, |
| 84 | "Directive %s may not be called within a compute region"_err_en_US, |
| 85 | ContextDirectiveAsFortran()); |
Diana Picus | 45cd405 | 2021-06-11 09:07:23 | [diff] [blame] | 86 | } |
Valentin Clement | b53115b | 2020-12-08 20:14:24 | [diff] [blame] | 87 | } |
| 88 | |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 89 | void AccStructureChecker::Enter(const parser::AccClause &x) { |
| 90 | SetContextClause(x); |
| 91 | } |
| 92 | |
| 93 | void AccStructureChecker::Leave(const parser::AccClauseList &) {} |
| 94 | |
| 95 | void AccStructureChecker::Enter(const parser::OpenACCBlockConstruct &x) { |
| 96 | const auto &beginBlockDir{std::get<parser::AccBeginBlockDirective>(x.t)}; |
| 97 | const auto &endBlockDir{std::get<parser::AccEndBlockDirective>(x.t)}; |
| 98 | const auto &beginAccBlockDir{ |
| 99 | std::get<parser::AccBlockDirective>(beginBlockDir.t)}; |
| 100 | |
| 101 | CheckMatching(beginAccBlockDir, endBlockDir.v); |
| 102 | PushContextAndClauseSets(beginAccBlockDir.source, beginAccBlockDir.v); |
| 103 | } |
| 104 | |
| 105 | void AccStructureChecker::Leave(const parser::OpenACCBlockConstruct &x) { |
| 106 | const auto &beginBlockDir{std::get<parser::AccBeginBlockDirective>(x.t)}; |
| 107 | const auto &blockDir{std::get<parser::AccBlockDirective>(beginBlockDir.t)}; |
| 108 | const parser::Block &block{std::get<parser::Block>(x.t)}; |
| 109 | switch (blockDir.v) { |
| 110 | case llvm::acc::Directive::ACCD_kernels: |
| 111 | case llvm::acc::Directive::ACCD_parallel: |
Valentin Clement | d553243 | 2020-12-08 19:36:24 | [diff] [blame] | 112 | case llvm::acc::Directive::ACCD_serial: |
| 113 | // Restriction - line 1004-1005 |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 114 | CheckOnlyAllowedAfter(llvm::acc::Clause::ACCC_device_type, |
Valentin Clement | d553243 | 2020-12-08 19:36:24 | [diff] [blame] | 115 | computeConstructOnlyAllowedAfterDeviceTypeClauses); |
| 116 | // Restriction - line 1001 |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 117 | CheckNoBranching(block, GetContext().directive, blockDir.source); |
| 118 | break; |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 119 | case llvm::acc::Directive::ACCD_data: |
Valentin Clement | d553243 | 2020-12-08 19:36:24 | [diff] [blame] | 120 | // Restriction - line 1249-1250 |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 121 | CheckRequireAtLeastOneOf(); |
| 122 | break; |
| 123 | case llvm::acc::Directive::ACCD_host_data: |
Valentin Clement | d553243 | 2020-12-08 19:36:24 | [diff] [blame] | 124 | // Restriction - line 1746 |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 125 | CheckRequireAtLeastOneOf(); |
| 126 | break; |
| 127 | default: |
| 128 | break; |
| 129 | } |
Valentin Clement | 4062618 | 2020-08-05 18:20:26 | [diff] [blame] | 130 | dirContext_.pop_back(); |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 131 | } |
| 132 | |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 133 | void AccStructureChecker::Enter( |
| 134 | const parser::OpenACCStandaloneDeclarativeConstruct &x) { |
| 135 | const auto &declarativeDir{std::get<parser::AccDeclarativeDirective>(x.t)}; |
| 136 | PushContextAndClauseSets(declarativeDir.source, declarativeDir.v); |
| 137 | } |
| 138 | |
| 139 | void AccStructureChecker::Leave( |
Valentin Clement | b73736a | 2021-01-07 14:25:00 | [diff] [blame] | 140 | const parser::OpenACCStandaloneDeclarativeConstruct &x) { |
Valentin Clement | d553243 | 2020-12-08 19:36:24 | [diff] [blame] | 141 | // Restriction - line 2409 |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 142 | CheckAtLeastOneClause(); |
Valentin Clement | b73736a | 2021-01-07 14:25:00 | [diff] [blame] | 143 | |
| 144 | // Restriction - line 2417-2418 - In a Fortran module declaration section, |
| 145 | // only create, copyin, device_resident, and link clauses are allowed. |
| 146 | const auto &declarativeDir{std::get<parser::AccDeclarativeDirective>(x.t)}; |
| 147 | const auto &scope{context_.FindScope(declarativeDir.source)}; |
| 148 | const Scope &containingScope{GetProgramUnitContaining(scope)}; |
| 149 | if (containingScope.kind() == Scope::Kind::Module) { |
| 150 | for (auto cl : GetContext().actualClauses) { |
| 151 | if (cl != llvm::acc::Clause::ACCC_create && |
| 152 | cl != llvm::acc::Clause::ACCC_copyin && |
| 153 | cl != llvm::acc::Clause::ACCC_device_resident && |
Diana Picus | 45cd405 | 2021-06-11 09:07:23 | [diff] [blame] | 154 | cl != llvm::acc::Clause::ACCC_link) { |
Valentin Clement | b73736a | 2021-01-07 14:25:00 | [diff] [blame] | 155 | context_.Say(GetContext().directiveSource, |
| 156 | "%s clause is not allowed on the %s directive in module " |
| 157 | "declaration " |
| 158 | "section"_err_en_US, |
| 159 | parser::ToUpperCaseLetters( |
| 160 | llvm::acc::getOpenACCClauseName(cl).str()), |
| 161 | ContextDirectiveAsFortran()); |
Diana Picus | 45cd405 | 2021-06-11 09:07:23 | [diff] [blame] | 162 | } |
Valentin Clement | b73736a | 2021-01-07 14:25:00 | [diff] [blame] | 163 | } |
| 164 | } |
Valentin Clement | 4062618 | 2020-08-05 18:20:26 | [diff] [blame] | 165 | dirContext_.pop_back(); |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 166 | } |
| 167 | |
| 168 | void AccStructureChecker::Enter(const parser::OpenACCCombinedConstruct &x) { |
Valentin Clement | 05169af | 2020-08-13 18:04:43 | [diff] [blame] | 169 | const auto &beginCombinedDir{ |
| 170 | std::get<parser::AccBeginCombinedDirective>(x.t)}; |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 171 | const auto &combinedDir{ |
Valentin Clement | 05169af | 2020-08-13 18:04:43 | [diff] [blame] | 172 | std::get<parser::AccCombinedDirective>(beginCombinedDir.t)}; |
| 173 | |
| 174 | // check matching, End directive is optional |
| 175 | if (const auto &endCombinedDir{ |
| 176 | std::get<std::optional<parser::AccEndCombinedDirective>>(x.t)}) { |
| 177 | CheckMatching<parser::AccCombinedDirective>(combinedDir, endCombinedDir->v); |
| 178 | } |
| 179 | |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 180 | PushContextAndClauseSets(combinedDir.source, combinedDir.v); |
| 181 | } |
| 182 | |
| 183 | void AccStructureChecker::Leave(const parser::OpenACCCombinedConstruct &x) { |
| 184 | const auto &beginBlockDir{std::get<parser::AccBeginCombinedDirective>(x.t)}; |
| 185 | const auto &combinedDir{ |
| 186 | std::get<parser::AccCombinedDirective>(beginBlockDir.t)}; |
| 187 | switch (combinedDir.v) { |
| 188 | case llvm::acc::Directive::ACCD_kernels_loop: |
| 189 | case llvm::acc::Directive::ACCD_parallel_loop: |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 190 | case llvm::acc::Directive::ACCD_serial_loop: |
Valentin Clement | d553243 | 2020-12-08 19:36:24 | [diff] [blame] | 191 | // Restriction - line 1004-1005 |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 192 | CheckOnlyAllowedAfter(llvm::acc::Clause::ACCC_device_type, |
Valentin Clement | d553243 | 2020-12-08 19:36:24 | [diff] [blame] | 193 | computeConstructOnlyAllowedAfterDeviceTypeClauses); |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 194 | break; |
| 195 | default: |
| 196 | break; |
| 197 | } |
Valentin Clement | 4062618 | 2020-08-05 18:20:26 | [diff] [blame] | 198 | dirContext_.pop_back(); |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 199 | } |
| 200 | |
| 201 | void AccStructureChecker::Enter(const parser::OpenACCLoopConstruct &x) { |
| 202 | const auto &beginDir{std::get<parser::AccBeginLoopDirective>(x.t)}; |
| 203 | const auto &loopDir{std::get<parser::AccLoopDirective>(beginDir.t)}; |
| 204 | PushContextAndClauseSets(loopDir.source, loopDir.v); |
| 205 | } |
| 206 | |
| 207 | void AccStructureChecker::Leave(const parser::OpenACCLoopConstruct &x) { |
| 208 | const auto &beginDir{std::get<parser::AccBeginLoopDirective>(x.t)}; |
| 209 | const auto &loopDir{std::get<parser::AccLoopDirective>(beginDir.t)}; |
| 210 | if (loopDir.v == llvm::acc::Directive::ACCD_loop) { |
Valentin Clement | d553243 | 2020-12-08 19:36:24 | [diff] [blame] | 211 | // Restriction - line 1818-1819 |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 212 | CheckOnlyAllowedAfter(llvm::acc::Clause::ACCC_device_type, |
| 213 | loopOnlyAllowedAfterDeviceTypeClauses); |
Valentin Clement | d553243 | 2020-12-08 19:36:24 | [diff] [blame] | 214 | // Restriction - line 1834 |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 215 | CheckNotAllowedIfClause(llvm::acc::Clause::ACCC_seq, |
| 216 | {llvm::acc::Clause::ACCC_gang, llvm::acc::Clause::ACCC_vector, |
| 217 | llvm::acc::Clause::ACCC_worker}); |
| 218 | } |
Valentin Clement | 4062618 | 2020-08-05 18:20:26 | [diff] [blame] | 219 | dirContext_.pop_back(); |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 220 | } |
| 221 | |
| 222 | void AccStructureChecker::Enter(const parser::OpenACCStandaloneConstruct &x) { |
| 223 | const auto &standaloneDir{std::get<parser::AccStandaloneDirective>(x.t)}; |
| 224 | PushContextAndClauseSets(standaloneDir.source, standaloneDir.v); |
| 225 | } |
| 226 | |
| 227 | void AccStructureChecker::Leave(const parser::OpenACCStandaloneConstruct &x) { |
| 228 | const auto &standaloneDir{std::get<parser::AccStandaloneDirective>(x.t)}; |
| 229 | switch (standaloneDir.v) { |
| 230 | case llvm::acc::Directive::ACCD_enter_data: |
| 231 | case llvm::acc::Directive::ACCD_exit_data: |
Valentin Clement | d553243 | 2020-12-08 19:36:24 | [diff] [blame] | 232 | // Restriction - line 1310-1311 (ENTER DATA) |
| 233 | // Restriction - line 1312-1313 (EXIT DATA) |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 234 | CheckRequireAtLeastOneOf(); |
| 235 | break; |
Valentin Clement | b53115b | 2020-12-08 20:14:24 | [diff] [blame] | 236 | case llvm::acc::Directive::ACCD_set: |
| 237 | // Restriction - line 2610 |
| 238 | CheckRequireAtLeastOneOf(); |
| 239 | // Restriction - line 2602 |
| 240 | CheckNotInComputeConstruct(); |
| 241 | break; |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 242 | case llvm::acc::Directive::ACCD_update: |
Valentin Clement | 1dd24e6 | 2020-12-08 15:36:34 | [diff] [blame] | 243 | // Restriction - line 2636 |
| 244 | CheckRequireAtLeastOneOf(); |
Valentin Clement | d553243 | 2020-12-08 19:36:24 | [diff] [blame] | 245 | // Restriction - line 2669 |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 246 | CheckOnlyAllowedAfter(llvm::acc::Clause::ACCC_device_type, |
| 247 | updateOnlyAllowedAfterDeviceTypeClauses); |
| 248 | break; |
Valentin Clement | b53115b | 2020-12-08 20:14:24 | [diff] [blame] | 249 | case llvm::acc::Directive::ACCD_init: |
| 250 | case llvm::acc::Directive::ACCD_shutdown: |
| 251 | // Restriction - line 2525 (INIT) |
| 252 | // Restriction - line 2561 (SHUTDOWN) |
| 253 | CheckNotInComputeConstruct(); |
| 254 | break; |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 255 | default: |
| 256 | break; |
| 257 | } |
Valentin Clement | 4062618 | 2020-08-05 18:20:26 | [diff] [blame] | 258 | dirContext_.pop_back(); |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 259 | } |
| 260 | |
| 261 | void AccStructureChecker::Enter(const parser::OpenACCRoutineConstruct &x) { |
| 262 | PushContextAndClauseSets(x.source, llvm::acc::Directive::ACCD_routine); |
Valentin Clement | 71699a9 | 2020-12-17 16:32:52 | [diff] [blame] | 263 | const auto &optName{std::get<std::optional<parser::Name>>(x.t)}; |
| 264 | if (!optName) { |
| 265 | const auto &verbatim{std::get<parser::Verbatim>(x.t)}; |
| 266 | const auto &scope{context_.FindScope(verbatim.source)}; |
| 267 | const Scope &containingScope{GetProgramUnitContaining(scope)}; |
| 268 | if (containingScope.kind() == Scope::Kind::Module) { |
| 269 | context_.Say(GetContext().directiveSource, |
| 270 | "ROUTINE directive without name must appear within the specification " |
| 271 | "part of a subroutine or function definition, or within an interface " |
| 272 | "body for a subroutine or function in an interface block"_err_en_US); |
| 273 | } |
| 274 | } |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 275 | } |
| 276 | void AccStructureChecker::Leave(const parser::OpenACCRoutineConstruct &) { |
Valentin Clement | d553243 | 2020-12-08 19:36:24 | [diff] [blame] | 277 | // Restriction - line 2790 |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 278 | CheckRequireAtLeastOneOf(); |
Valentin Clement | d553243 | 2020-12-08 19:36:24 | [diff] [blame] | 279 | // Restriction - line 2788-2789 |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 280 | CheckOnlyAllowedAfter(llvm::acc::Clause::ACCC_device_type, |
| 281 | routineOnlyAllowedAfterDeviceTypeClauses); |
Valentin Clement | 4062618 | 2020-08-05 18:20:26 | [diff] [blame] | 282 | dirContext_.pop_back(); |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 283 | } |
| 284 | |
Valentin Clement | 676ff75 | 2020-10-23 14:31:33 | [diff] [blame] | 285 | void AccStructureChecker::Enter(const parser::OpenACCWaitConstruct &x) { |
| 286 | const auto &verbatim{std::get<parser::Verbatim>(x.t)}; |
| 287 | PushContextAndClauseSets(verbatim.source, llvm::acc::Directive::ACCD_wait); |
| 288 | } |
| 289 | void AccStructureChecker::Leave(const parser::OpenACCWaitConstruct &x) { |
| 290 | dirContext_.pop_back(); |
| 291 | } |
| 292 | |
| 293 | void AccStructureChecker::Enter(const parser::OpenACCAtomicConstruct &x) { |
| 294 | PushContextAndClauseSets(x.source, llvm::acc::Directive::ACCD_atomic); |
| 295 | } |
| 296 | void AccStructureChecker::Leave(const parser::OpenACCAtomicConstruct &x) { |
| 297 | dirContext_.pop_back(); |
| 298 | } |
| 299 | |
Valentin Clement | e73d8c7 | 2020-11-25 15:28:02 | [diff] [blame] | 300 | void AccStructureChecker::Enter(const parser::OpenACCCacheConstruct &x) { |
| 301 | const auto &verbatim = std::get<parser::Verbatim>(x.t); |
| 302 | PushContextAndClauseSets(verbatim.source, llvm::acc::Directive::ACCD_cache); |
| 303 | SetContextDirectiveSource(verbatim.source); |
| 304 | } |
| 305 | void AccStructureChecker::Leave(const parser::OpenACCCacheConstruct &x) { |
| 306 | dirContext_.pop_back(); |
| 307 | } |
| 308 | |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 309 | // Clause checkers |
| 310 | CHECK_REQ_SCALAR_INT_CONSTANT_CLAUSE(Collapse, ACCC_collapse) |
| 311 | |
| 312 | CHECK_SIMPLE_CLAUSE(Auto, ACCC_auto) |
| 313 | CHECK_SIMPLE_CLAUSE(Async, ACCC_async) |
| 314 | CHECK_SIMPLE_CLAUSE(Attach, ACCC_attach) |
| 315 | CHECK_SIMPLE_CLAUSE(Bind, ACCC_bind) |
| 316 | CHECK_SIMPLE_CLAUSE(Capture, ACCC_capture) |
| 317 | CHECK_SIMPLE_CLAUSE(Copy, ACCC_copy) |
| 318 | CHECK_SIMPLE_CLAUSE(Default, ACCC_default) |
| 319 | CHECK_SIMPLE_CLAUSE(DefaultAsync, ACCC_default_async) |
| 320 | CHECK_SIMPLE_CLAUSE(Delete, ACCC_delete) |
| 321 | CHECK_SIMPLE_CLAUSE(Detach, ACCC_detach) |
| 322 | CHECK_SIMPLE_CLAUSE(Device, ACCC_device) |
| 323 | CHECK_SIMPLE_CLAUSE(DeviceNum, ACCC_device_num) |
Valentin Clement | 16c1d25 | 2020-08-11 14:43:56 | [diff] [blame] | 324 | CHECK_SIMPLE_CLAUSE(Deviceptr, ACCC_deviceptr) |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 325 | CHECK_SIMPLE_CLAUSE(DeviceResident, ACCC_device_resident) |
| 326 | CHECK_SIMPLE_CLAUSE(DeviceType, ACCC_device_type) |
| 327 | CHECK_SIMPLE_CLAUSE(Finalize, ACCC_finalize) |
Valentin Clement | 16c1d25 | 2020-08-11 14:43:56 | [diff] [blame] | 328 | CHECK_SIMPLE_CLAUSE(Firstprivate, ACCC_firstprivate) |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 329 | CHECK_SIMPLE_CLAUSE(Gang, ACCC_gang) |
| 330 | CHECK_SIMPLE_CLAUSE(Host, ACCC_host) |
| 331 | CHECK_SIMPLE_CLAUSE(If, ACCC_if) |
| 332 | CHECK_SIMPLE_CLAUSE(IfPresent, ACCC_if_present) |
| 333 | CHECK_SIMPLE_CLAUSE(Independent, ACCC_independent) |
| 334 | CHECK_SIMPLE_CLAUSE(Link, ACCC_link) |
| 335 | CHECK_SIMPLE_CLAUSE(NoCreate, ACCC_no_create) |
Valentin Clement | 16c1d25 | 2020-08-11 14:43:56 | [diff] [blame] | 336 | CHECK_SIMPLE_CLAUSE(Nohost, ACCC_nohost) |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 337 | CHECK_SIMPLE_CLAUSE(NumGangs, ACCC_num_gangs) |
| 338 | CHECK_SIMPLE_CLAUSE(NumWorkers, ACCC_num_workers) |
| 339 | CHECK_SIMPLE_CLAUSE(Present, ACCC_present) |
| 340 | CHECK_SIMPLE_CLAUSE(Private, ACCC_private) |
| 341 | CHECK_SIMPLE_CLAUSE(Read, ACCC_read) |
| 342 | CHECK_SIMPLE_CLAUSE(Reduction, ACCC_reduction) |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 343 | CHECK_SIMPLE_CLAUSE(Seq, ACCC_seq) |
| 344 | CHECK_SIMPLE_CLAUSE(Tile, ACCC_tile) |
| 345 | CHECK_SIMPLE_CLAUSE(UseDevice, ACCC_use_device) |
| 346 | CHECK_SIMPLE_CLAUSE(Vector, ACCC_vector) |
| 347 | CHECK_SIMPLE_CLAUSE(VectorLength, ACCC_vector_length) |
| 348 | CHECK_SIMPLE_CLAUSE(Wait, ACCC_wait) |
| 349 | CHECK_SIMPLE_CLAUSE(Worker, ACCC_worker) |
| 350 | CHECK_SIMPLE_CLAUSE(Write, ACCC_write) |
Valentin Clement | 3f46c20 | 2021-02-01 18:33:07 | [diff] [blame] | 351 | CHECK_SIMPLE_CLAUSE(Unknown, ACCC_unknown) |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 352 | |
| 353 | void AccStructureChecker::Enter(const parser::AccClause::Create &c) { |
| 354 | CheckAllowed(llvm::acc::Clause::ACCC_create); |
| 355 | const auto &modifierClause{c.v}; |
| 356 | if (const auto &modifier{ |
| 357 | std::get<std::optional<parser::AccDataModifier>>(modifierClause.t)}) { |
| 358 | if (modifier->v != parser::AccDataModifier::Modifier::Zero) { |
| 359 | context_.Say(GetContext().clauseSource, |
| 360 | "Only the ZERO modifier is allowed for the %s clause " |
| 361 | "on the %s directive"_err_en_US, |
| 362 | parser::ToUpperCaseLetters( |
| 363 | llvm::acc::getOpenACCClauseName(llvm::acc::Clause::ACCC_create) |
| 364 | .str()), |
| 365 | ContextDirectiveAsFortran()); |
| 366 | } |
| 367 | } |
| 368 | } |
| 369 | |
| 370 | void AccStructureChecker::Enter(const parser::AccClause::Copyin &c) { |
| 371 | CheckAllowed(llvm::acc::Clause::ACCC_copyin); |
| 372 | const auto &modifierClause{c.v}; |
| 373 | if (const auto &modifier{ |
| 374 | std::get<std::optional<parser::AccDataModifier>>(modifierClause.t)}) { |
Diana Picus | 45cd405 | 2021-06-11 09:07:23 | [diff] [blame] | 375 | if (CheckAllowedModifier(llvm::acc::Clause::ACCC_copyin)) { |
Valentin Clement | 75ba29a | 2020-10-29 13:53:10 | [diff] [blame] | 376 | return; |
Diana Picus | 45cd405 | 2021-06-11 09:07:23 | [diff] [blame] | 377 | } |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 378 | if (modifier->v != parser::AccDataModifier::Modifier::ReadOnly) { |
| 379 | context_.Say(GetContext().clauseSource, |
| 380 | "Only the READONLY modifier is allowed for the %s clause " |
| 381 | "on the %s directive"_err_en_US, |
| 382 | parser::ToUpperCaseLetters( |
| 383 | llvm::acc::getOpenACCClauseName(llvm::acc::Clause::ACCC_copyin) |
| 384 | .str()), |
| 385 | ContextDirectiveAsFortran()); |
| 386 | } |
| 387 | } |
| 388 | } |
| 389 | |
| 390 | void AccStructureChecker::Enter(const parser::AccClause::Copyout &c) { |
| 391 | CheckAllowed(llvm::acc::Clause::ACCC_copyout); |
| 392 | const auto &modifierClause{c.v}; |
| 393 | if (const auto &modifier{ |
| 394 | std::get<std::optional<parser::AccDataModifier>>(modifierClause.t)}) { |
Diana Picus | 45cd405 | 2021-06-11 09:07:23 | [diff] [blame] | 395 | if (CheckAllowedModifier(llvm::acc::Clause::ACCC_copyout)) { |
Valentin Clement | 75ba29a | 2020-10-29 13:53:10 | [diff] [blame] | 396 | return; |
Diana Picus | 45cd405 | 2021-06-11 09:07:23 | [diff] [blame] | 397 | } |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 398 | if (modifier->v != parser::AccDataModifier::Modifier::Zero) { |
| 399 | context_.Say(GetContext().clauseSource, |
| 400 | "Only the ZERO modifier is allowed for the %s clause " |
| 401 | "on the %s directive"_err_en_US, |
| 402 | parser::ToUpperCaseLetters( |
| 403 | llvm::acc::getOpenACCClauseName(llvm::acc::Clause::ACCC_copyout) |
| 404 | .str()), |
| 405 | ContextDirectiveAsFortran()); |
| 406 | } |
| 407 | } |
| 408 | } |
| 409 | |
Valentin Clement | 1dd24e6 | 2020-12-08 15:36:34 | [diff] [blame] | 410 | void AccStructureChecker::Enter(const parser::AccClause::Self &x) { |
| 411 | CheckAllowed(llvm::acc::Clause::ACCC_self); |
| 412 | const parser::AccSelfClause &accSelfClause = x.v; |
| 413 | if (GetContext().directive == llvm::acc::Directive::ACCD_update && |
| 414 | std::holds_alternative<std::optional<parser::ScalarLogicalExpr>>( |
| 415 | accSelfClause.u)) { |
| 416 | context_.Say(GetContext().clauseSource, |
| 417 | "SELF clause on the %s directive must have a var-list"_err_en_US, |
| 418 | ContextDirectiveAsFortran()); |
| 419 | } else if (GetContext().directive != llvm::acc::Directive::ACCD_update && |
| 420 | std::holds_alternative<parser::AccObjectList>(accSelfClause.u)) { |
| 421 | const auto &accObjectList = |
| 422 | std::get<parser::AccObjectList>(accSelfClause.u); |
| 423 | if (accObjectList.v.size() != 1) { |
| 424 | context_.Say(GetContext().clauseSource, |
| 425 | "SELF clause on the %s directive only accepts optional scalar logical" |
| 426 | " expression"_err_en_US, |
| 427 | ContextDirectiveAsFortran()); |
| 428 | } |
| 429 | } |
| 430 | } |
| 431 | |
Valentin Clement | 4062618 | 2020-08-05 18:20:26 | [diff] [blame] | 432 | llvm::StringRef AccStructureChecker::getClauseName(llvm::acc::Clause clause) { |
| 433 | return llvm::acc::getOpenACCClauseName(clause); |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 434 | } |
| 435 | |
Valentin Clement | 4062618 | 2020-08-05 18:20:26 | [diff] [blame] | 436 | llvm::StringRef AccStructureChecker::getDirectiveName( |
| 437 | llvm::acc::Directive directive) { |
| 438 | return llvm::acc::getOpenACCDirectiveName(directive); |
Valentin Clement | 9aa3dca | 2020-07-15 00:43:40 | [diff] [blame] | 439 | } |
| 440 | |
| 441 | } // namespace Fortran::semantics |