123 lines · c
1//===-- lib/Semantics/check-acc-structure.h ---------------------*- C++ -*-===//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-exception6//7// OpenACC 3.3 structure validity check list8// 1. invalid clauses on directive9// 2. invalid repeated clauses on directive10// 3. invalid nesting of regions11//12//===----------------------------------------------------------------------===//13 14#ifndef FORTRAN_SEMANTICS_CHECK_ACC_STRUCTURE_H_15#define FORTRAN_SEMANTICS_CHECK_ACC_STRUCTURE_H_16 17#include "check-directive-structure.h"18#include "flang/Common/enum-set.h"19#include "flang/Parser/parse-tree.h"20#include "flang/Semantics/semantics.h"21#include "llvm/ADT/DenseMap.h"22#include "llvm/Frontend/OpenACC/ACC.h.inc"23 24using AccDirectiveSet = Fortran::common::EnumSet<llvm::acc::Directive,25 llvm::acc::Directive_enumSize>;26 27using AccClauseSet =28 Fortran::common::EnumSet<llvm::acc::Clause, llvm::acc::Clause_enumSize>;29 30#define GEN_FLANG_DIRECTIVE_CLAUSE_SETS31#include "llvm/Frontend/OpenACC/ACC.inc"32 33namespace Fortran::semantics {34 35class AccStructureChecker36 : public DirectiveStructureChecker<llvm::acc::Directive, llvm::acc::Clause,37 parser::AccClause, llvm::acc::Clause_enumSize> {38public:39 AccStructureChecker(SemanticsContext &context)40 : DirectiveStructureChecker(context,41#define GEN_FLANG_DIRECTIVE_CLAUSE_MAP42#include "llvm/Frontend/OpenACC/ACC.inc"43 ) {44 }45 46 // Construct and directives47 void Enter(const parser::OpenACCBlockConstruct &);48 void Leave(const parser::OpenACCBlockConstruct &);49 void Enter(const parser::OpenACCCombinedConstruct &);50 void Leave(const parser::OpenACCCombinedConstruct &);51 void Enter(const parser::OpenACCLoopConstruct &);52 void Leave(const parser::OpenACCLoopConstruct &);53 void Enter(const parser::OpenACCRoutineConstruct &);54 void Leave(const parser::OpenACCRoutineConstruct &);55 void Enter(const parser::OpenACCStandaloneConstruct &);56 void Leave(const parser::OpenACCStandaloneConstruct &);57 void Enter(const parser::OpenACCStandaloneDeclarativeConstruct &);58 void Leave(const parser::OpenACCStandaloneDeclarativeConstruct &);59 void Enter(const parser::OpenACCWaitConstruct &);60 void Leave(const parser::OpenACCWaitConstruct &);61 void Enter(const parser::OpenACCAtomicConstruct &);62 void Leave(const parser::OpenACCAtomicConstruct &);63 void Enter(const parser::OpenACCCacheConstruct &);64 void Leave(const parser::OpenACCCacheConstruct &);65 void Enter(const parser::AccAtomicUpdate &);66 void Enter(const parser::AccAtomicCapture &);67 void Enter(const parser::AccAtomicWrite &);68 void Enter(const parser::AccAtomicRead &);69 void Enter(const parser::OpenACCEndConstruct &);70 71 // Clauses72 void Leave(const parser::AccClauseList &);73 void Enter(const parser::AccClause &);74 75 void Enter(const parser::Module &);76 void Enter(const parser::SubroutineSubprogram &);77 void Enter(const parser::FunctionSubprogram &);78 void Enter(const parser::SeparateModuleSubprogram &);79 void Enter(const parser::DoConstruct &);80 void Leave(const parser::DoConstruct &);81 82#define GEN_FLANG_CLAUSE_CHECK_ENTER83#include "llvm/Frontend/OpenACC/ACC.inc"84 85private:86 void CheckAtomicStmt(87 const parser::AssignmentStmt &assign, const std::string &construct);88 void CheckAtomicUpdateStmt(const parser::AssignmentStmt &assign,89 const SomeExpr &updateVar, const SomeExpr *captureVar);90 void CheckAtomicCaptureStmt(const parser::AssignmentStmt &assign,91 const SomeExpr *updateVar, const SomeExpr &captureVar);92 void CheckAtomicWriteStmt(const parser::AssignmentStmt &assign,93 const SomeExpr &updateVar, const SomeExpr *captureVar);94 void CheckAtomicUpdateVariable(95 const parser::Variable &updateVar, const parser::Variable &captureVar);96 void CheckAtomicCaptureVariable(97 const parser::Variable &captureVar, const parser::Variable &updateVar);98 99 bool CheckAllowedModifier(llvm::acc::Clause clause);100 bool IsComputeConstruct(llvm::acc::Directive directive) const;101 bool IsLoopConstruct(llvm::acc::Directive directive) const;102 std::optional<llvm::acc::Directive> getParentComputeConstruct() const;103 bool IsInsideComputeConstruct() const;104 bool IsInsideKernelsConstruct() const;105 void CheckNotInComputeConstruct();106 std::optional<std::int64_t> getGangDimensionSize(107 DirectiveContext &dirContext);108 void CheckNotInSameOrSubLevelLoopConstruct();109 void CheckMultipleOccurrenceInDeclare(110 const parser::AccObjectList &, llvm::acc::Clause);111 void CheckMultipleOccurrenceInDeclare(112 const parser::AccObjectListWithModifier &, llvm::acc::Clause);113 llvm::StringRef getClauseName(llvm::acc::Clause clause) override;114 llvm::StringRef getDirectiveName(llvm::acc::Directive directive) override;115 116 llvm::SmallDenseMap<Symbol *, llvm::acc::Clause> declareSymbols;117 unsigned loopNestLevel = 0;118};119 120} // namespace Fortran::semantics121 122#endif // FORTRAN_SEMANTICS_CHECK_ACC_STRUCTURE_H_123