[llvm] 65049d1 - [flang][openacc] OpenACC 3.0 parser
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 13 17:15:16 PDT 2020
Author: Valentin Clement
Date: 2020-07-13T20:15:06-04:00
New Revision: 65049d16100af360674659fb56e8f9bec96a0836
URL: https://github.com/llvm/llvm-project/commit/65049d16100af360674659fb56e8f9bec96a0836
DIFF: https://github.com/llvm/llvm-project/commit/65049d16100af360674659fb56e8f9bec96a0836.diff
LOG: [flang][openacc] OpenACC 3.0 parser
Summary:
This patch introduce the parser for OpenACC 3.0 in Flang. It uses the same TableGen mechanism
than OpenMP.
Reviewers: nvdatian, sscalpone, tskeith, klausler, ichoyjx, jdoerfert, DavidTruby
Reviewed By: klausler
Subscribers: SouraVX, mgorny, hiraditya, jfb, sstefan1, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D83649
Added:
flang/lib/Parser/openacc-parsers.cpp
flang/test/Semantics/acc-validity.f90
llvm/include/llvm/Frontend/CMakeLists.txt
llvm/include/llvm/Frontend/OpenACC/ACC.td
llvm/include/llvm/Frontend/OpenACC/CMakeLists.txt
llvm/lib/Frontend/OpenACC/CMakeLists.txt
Modified:
flang/include/flang/Common/Fortran-features.h
flang/include/flang/Parser/dump-parse-tree.h
flang/include/flang/Parser/parse-tree.h
flang/lib/Parser/CMakeLists.txt
flang/lib/Parser/executable-parsers.cpp
flang/lib/Parser/openmp-parsers.cpp
flang/lib/Parser/parsing.cpp
flang/lib/Parser/program-parsers.cpp
flang/lib/Parser/stmt-parser.h
flang/lib/Parser/token-parsers.h
flang/lib/Parser/type-parsers.h
flang/lib/Parser/unparse.cpp
flang/lib/Semantics/resolve-names.cpp
flang/tools/f18-parse-demo/CMakeLists.txt
flang/tools/f18/CMakeLists.txt
flang/tools/f18/f18.cpp
llvm/include/llvm/CMakeLists.txt
llvm/include/llvm/Frontend/Directive/DirectiveBase.td
llvm/lib/Frontend/CMakeLists.txt
Removed:
################################################################################
diff --git a/flang/include/flang/Common/Fortran-features.h b/flang/include/flang/Common/Fortran-features.h
index 823fa85ad12e..613aa69cc5d6 100644
--- a/flang/include/flang/Common/Fortran-features.h
+++ b/flang/include/flang/Common/Fortran-features.h
@@ -24,7 +24,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
OldStyleParameter, ComplexConstructor, PercentLOC, SignedPrimary, FileName,
Convert, Dispose, IOListLeadingComma, AbbreviatedEditDescriptor,
ProgramParentheses, PercentRefAndVal, OmitFunctionDummies, CrayPointer,
- Hollerith, ArithmeticIF, Assign, AssignedGOTO, Pause, OpenMP,
+ Hollerith, ArithmeticIF, Assign, AssignedGOTO, Pause, OpenACC, OpenMP,
CruftAfterAmpersand, ClassicCComments, AdditionalFormats, BigIntLiterals,
RealDoControls, EquivalenceNumericWithCharacter, AdditionalIntrinsics,
AnonymousParents, OldLabelDoEndStatements, LogicalIntegerAssignment,
@@ -37,6 +37,7 @@ class LanguageFeatureControl {
LanguageFeatureControl() {
// These features must be explicitly enabled by command line options.
disable_.set(LanguageFeature::OldDebugLines);
+ disable_.set(LanguageFeature::OpenACC);
disable_.set(LanguageFeature::OpenMP);
// These features, if enabled, conflict with valid standard usage,
// so there are disabled here by default.
@@ -50,7 +51,9 @@ class LanguageFeatureControl {
void WarnOnAllNonstandard(bool yes = true) { warnAll_ = yes; }
bool IsEnabled(LanguageFeature f) const { return !disable_.test(f); }
bool ShouldWarn(LanguageFeature f) const {
- return (warnAll_ && f != LanguageFeature::OpenMP) || warn_.test(f);
+ return (warnAll_ && f != LanguageFeature::OpenMP &&
+ f != LanguageFeature::OpenACC) ||
+ warn_.test(f);
}
// Return all spellings of operators names, depending on features enabled
std::vector<const char *> GetNames(LogicalOperator) const;
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 59333c7405ff..36e593eb3b78 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -53,6 +53,88 @@ class ParseTreeDumper {
NODE(format, IntrinsicTypeDataEditDesc)
NODE(format::IntrinsicTypeDataEditDesc, Kind)
NODE(parser, Abstract)
+ NODE(parser, AccAtomicCapture)
+ NODE(AccAtomicCapture, Stmt1)
+ NODE(AccAtomicCapture, Stmt2)
+ NODE(parser, AccAtomicRead)
+ NODE(parser, AccAtomicUpdate)
+ NODE(parser, AccAtomicWrite)
+ NODE(parser, AccBeginBlockDirective)
+ NODE(parser, AccBeginCombinedDirective)
+ NODE(parser, AccBeginLoopDirective)
+ NODE(parser, AccBlockDirective)
+ NODE(parser, AccClause)
+ NODE(AccClause, Auto)
+ NODE(AccClause, Async)
+ NODE(AccClause, Attach)
+ NODE(AccClause, Bind)
+ NODE(AccClause, Capture)
+ NODE(AccClause, Collapse)
+ NODE(AccClause, Copy)
+ NODE(AccClause, Copyin)
+ NODE(AccClause, Copyout)
+ NODE(AccClause, Create)
+ NODE(AccClause, Default)
+ NODE(AccClause, DefaultAsync)
+ NODE(AccClause, Delete)
+ NODE(AccClause, Detach)
+ NODE(AccClause, Device)
+ NODE(AccClause, DeviceNum)
+ NODE(AccClause, DevicePtr)
+ NODE(AccClause, DeviceResident)
+ NODE(AccClause, DeviceType)
+ NODE(AccClause, Finalize)
+ NODE(AccClause, FirstPrivate)
+ NODE(AccClause, Gang)
+ NODE(AccClause, Host)
+ NODE(AccClause, If)
+ NODE(AccClause, IfPresent)
+ NODE(AccClause, Independent)
+ NODE(AccClause, Link)
+ NODE(AccClause, NoCreate)
+ NODE(AccClause, NoHost)
+ NODE(AccClause, NumGangs)
+ NODE(AccClause, NumWorkers)
+ NODE(AccClause, Present)
+ NODE(AccClause, Private)
+ NODE(AccClause, Tile)
+ NODE(AccClause, UseDevice)
+ NODE(AccClause, Read)
+ NODE(AccClause, Reduction)
+ NODE(AccClause, Self)
+ NODE(AccClause, Seq)
+ NODE(AccClause, Vector)
+ NODE(AccClause, VectorLength)
+ NODE(AccClause, Wait)
+ NODE(AccClause, Worker)
+ NODE(AccClause, Write)
+ NODE(AccClause, Unknown)
+ NODE(parser, AccDefaultClause)
+ NODE_ENUM(parser::AccDefaultClause, Arg)
+ NODE(parser, AccClauseList)
+ NODE(parser, AccCombinedDirective)
+ NODE(parser, AccDataModifier)
+ NODE_ENUM(parser::AccDataModifier, Modifier)
+ NODE(parser, AccDeclarativeDirective)
+ NODE(parser, AccEndAtomic)
+ NODE(parser, AccEndBlockDirective)
+ NODE(parser, AccEndCombinedDirective)
+ NODE(parser, AccGangArgument)
+ NODE(parser, AccObject)
+ NODE(parser, AccObjectList)
+ NODE(parser, AccObjectListWithModifier)
+ NODE(parser, AccObjectListWithReduction)
+ NODE(parser, AccReductionOperator)
+ NODE(parser, AccSizeExpr)
+ NODE(parser, AccSizeExprList)
+ NODE(parser, AccStandaloneDirective)
+ NODE(parser, AccLoopDirective)
+ NODE(parser, AccWaitArgument)
+ static std::string GetNodeName(const llvm::acc::Directive &x) {
+ return llvm::Twine(
+ "llvm::acc::Directive = ", llvm::acc::getOpenACCDirectiveName(x))
+ .str();
+ }
NODE(parser, AcImpliedDo)
NODE(parser, AcImpliedDoControl)
NODE(parser, AcValue)
@@ -510,6 +592,17 @@ class ParseTreeDumper {
NODE(parser, OmpSectionsDirective)
NODE(parser, OmpSimpleStandaloneDirective)
NODE(parser, Only)
+ NODE(parser, OpenACCAtomicConstruct)
+ NODE(parser, OpenACCBlockConstruct)
+ NODE(parser, OpenACCCacheConstruct)
+ NODE(parser, OpenACCCombinedConstruct)
+ NODE(parser, OpenACCConstruct)
+ NODE(parser, OpenACCDeclarativeConstruct)
+ NODE(parser, OpenACCLoopConstruct)
+ NODE(parser, OpenACCRoutineConstruct)
+ NODE(parser, OpenACCStandaloneDeclarativeConstruct)
+ NODE(parser, OpenACCStandaloneConstruct)
+ NODE(parser, OpenACCWaitConstruct)
NODE(parser, OpenMPAtomicConstruct)
NODE(parser, OpenMPBlockConstruct)
NODE(parser, OpenMPCancelConstruct)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 67fd5741b097..d9ecebfc3fdd 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -25,6 +25,7 @@
#include "flang/Common/Fortran.h"
#include "flang/Common/idioms.h"
#include "flang/Common/indirection.h"
+#include "llvm/Frontend/OpenACC/ACC.h.inc"
#include "llvm/Frontend/OpenMP/OMPConstants.h"
#include <cinttypes>
#include <list>
@@ -256,6 +257,8 @@ struct ArithmeticIfStmt;
struct AssignStmt;
struct AssignedGotoStmt;
struct PauseStmt;
+struct OpenACCConstruct;
+struct OpenACCDeclarativeConstruct;
struct OpenMPConstruct;
struct OpenMPDeclarativeConstruct;
struct OmpEndLoopDirective;
@@ -386,6 +389,7 @@ struct SpecificationConstruct {
Statement<OtherSpecificationStmt>,
Statement<common::Indirection<TypeDeclarationStmt>>,
common::Indirection<StructureDef>,
+ common::Indirection<OpenACCDeclarativeConstruct>,
common::Indirection<OpenMPDeclarativeConstruct>,
common::Indirection<CompilerDirective>>
u;
@@ -424,7 +428,8 @@ struct DeclarationConstruct {
// from the implicit part to the declaration constructs
struct SpecificationPart {
TUPLE_CLASS_BOILERPLATE(SpecificationPart);
- std::tuple<std::list<OpenMPDeclarativeConstruct>,
+ std::tuple<std::list<OpenACCDeclarativeConstruct>,
+ std::list<OpenMPDeclarativeConstruct>,
std::list<Statement<common::Indirection<UseStmt>>>,
std::list<Statement<common::Indirection<ImportStmt>>>, ImplicitPart,
std::list<DeclarationConstruct>>
@@ -509,6 +514,7 @@ struct ExecutableConstruct {
common::Indirection<SelectTypeConstruct>,
common::Indirection<WhereConstruct>, common::Indirection<ForallConstruct>,
common::Indirection<CompilerDirective>,
+ common::Indirection<OpenACCConstruct>,
common::Indirection<OpenMPConstruct>,
common::Indirection<OmpEndLoopDirective>>
u;
@@ -3789,5 +3795,287 @@ struct OpenMPConstruct {
OpenMPCriticalConstruct>
u;
};
+
+// Parse tree nodes for OpenACC 3.0 directives and clauses
+
+struct AccObject {
+ UNION_CLASS_BOILERPLATE(AccObject);
+ std::variant<Designator, /*common block*/ Name> u;
+};
+
+WRAPPER_CLASS(AccObjectList, std::list<AccObject>);
+
+// OpenACC directive beginning or ending a block
+struct AccBlockDirective {
+ WRAPPER_CLASS_BOILERPLATE(AccBlockDirective, llvm::acc::Directive);
+ CharBlock source;
+};
+
+struct AccLoopDirective {
+ WRAPPER_CLASS_BOILERPLATE(AccLoopDirective, llvm::acc::Directive);
+ CharBlock source;
+};
+
+struct AccStandaloneDirective {
+ WRAPPER_CLASS_BOILERPLATE(AccStandaloneDirective, llvm::acc::Directive);
+ CharBlock source;
+};
+
+// 2.11 Combined constructs
+struct AccCombinedDirective {
+ WRAPPER_CLASS_BOILERPLATE(AccCombinedDirective, llvm::acc::Directive);
+ CharBlock source;
+};
+
+struct AccDeclarativeDirective {
+ WRAPPER_CLASS_BOILERPLATE(AccDeclarativeDirective, llvm::acc::Directive);
+ CharBlock source;
+};
+
+// OpenACC Clauses
+struct AccDefaultClause {
+ ENUM_CLASS(Arg, None, Present)
+ WRAPPER_CLASS_BOILERPLATE(AccDefaultClause, Arg);
+ CharBlock source;
+};
+
+struct AccDataModifier {
+ ENUM_CLASS(Modifier, ReadOnly, Zero)
+ WRAPPER_CLASS_BOILERPLATE(AccDataModifier, Modifier);
+ CharBlock source;
+};
+
+struct AccObjectListWithModifier {
+ TUPLE_CLASS_BOILERPLATE(AccObjectListWithModifier);
+ std::tuple<std::optional<AccDataModifier>, AccObjectList> t;
+};
+
+// 2.5.13: + | * | max | min | iand | ior | ieor | .and. | .or. | .eqv. | .neqv.
+struct AccReductionOperator {
+ UNION_CLASS_BOILERPLATE(AccReductionOperator);
+ std::variant<DefinedOperator, ProcedureDesignator> u;
+};
+
+struct AccObjectListWithReduction {
+ TUPLE_CLASS_BOILERPLATE(AccObjectListWithReduction);
+ std::tuple<AccReductionOperator, AccObjectList> t;
+};
+
+struct AccWaitArgument {
+ TUPLE_CLASS_BOILERPLATE(AccWaitArgument);
+ std::tuple<std::optional<ScalarIntExpr>, std::list<ScalarIntExpr>> t;
+};
+
+struct AccSizeExpr {
+ TUPLE_CLASS_BOILERPLATE(AccSizeExpr);
+ CharBlock source;
+ std::tuple<std::optional<ScalarIntExpr>> t; // if null then *
+};
+
+struct AccSizeExprList {
+ WRAPPER_CLASS_BOILERPLATE(AccSizeExprList, std::list<AccSizeExpr>);
+};
+
+struct AccGangArgument {
+ TUPLE_CLASS_BOILERPLATE(AccGangArgument);
+ std::tuple<std::optional<ScalarIntExpr>, std::optional<AccSizeExpr>> t;
+};
+
+struct AccClause {
+ UNION_CLASS_BOILERPLATE(AccClause);
+
+ EMPTY_CLASS(Auto);
+ WRAPPER_CLASS(Async, std::optional<ScalarIntExpr>);
+ WRAPPER_CLASS(Attach, AccObjectList);
+ WRAPPER_CLASS(Bind, Name);
+ EMPTY_CLASS(Capture);
+ WRAPPER_CLASS(Collapse, ScalarIntConstantExpr);
+ WRAPPER_CLASS(Copy, AccObjectList);
+ WRAPPER_CLASS(Copyin, AccObjectListWithModifier);
+ WRAPPER_CLASS(Copyout, AccObjectListWithModifier);
+ WRAPPER_CLASS(Create, AccObjectListWithModifier);
+ WRAPPER_CLASS(Default, AccDefaultClause);
+ WRAPPER_CLASS(DefaultAsync, ScalarIntExpr);
+ WRAPPER_CLASS(Delete, AccObjectList);
+ WRAPPER_CLASS(Detach, AccObjectList);
+ WRAPPER_CLASS(Device, AccObjectList);
+ WRAPPER_CLASS(DeviceNum, ScalarIntConstantExpr);
+ WRAPPER_CLASS(DevicePtr, AccObjectList);
+ WRAPPER_CLASS(DeviceResident, AccObjectList);
+ WRAPPER_CLASS(DeviceType, std::optional<std::list<Name>>);
+ EMPTY_CLASS(Finalize);
+ WRAPPER_CLASS(FirstPrivate, AccObjectList);
+ WRAPPER_CLASS(Gang, std::optional<AccGangArgument>);
+ WRAPPER_CLASS(Host, AccObjectList);
+ WRAPPER_CLASS(If, ScalarLogicalExpr);
+ EMPTY_CLASS(IfPresent);
+ EMPTY_CLASS(Independent);
+ WRAPPER_CLASS(Link, AccObjectList);
+ WRAPPER_CLASS(NoCreate, AccObjectList);
+ EMPTY_CLASS(NoHost);
+ WRAPPER_CLASS(NumGangs, ScalarIntExpr);
+ WRAPPER_CLASS(NumWorkers, ScalarIntExpr);
+ WRAPPER_CLASS(Present, AccObjectList);
+ WRAPPER_CLASS(Private, AccObjectList);
+ WRAPPER_CLASS(Tile, AccSizeExprList);
+ WRAPPER_CLASS(UseDevice, AccObjectList);
+ EMPTY_CLASS(Read);
+ WRAPPER_CLASS(Reduction, AccObjectListWithReduction);
+ WRAPPER_CLASS(Self, std::optional<ScalarLogicalExpr>);
+ EMPTY_CLASS(Seq);
+ WRAPPER_CLASS(Vector, std::optional<ScalarIntExpr>);
+ WRAPPER_CLASS(VectorLength, ScalarIntExpr);
+ WRAPPER_CLASS(Wait, std::optional<AccWaitArgument>);
+ WRAPPER_CLASS(Worker, std::optional<ScalarIntExpr>);
+ EMPTY_CLASS(Write);
+ EMPTY_CLASS(Unknown);
+
+ CharBlock source;
+
+ std::variant<Auto, Async, Attach, Bind, Capture, Collapse, Copy, Copyin,
+ Copyout, Create, Default, DefaultAsync, Delete, Detach, Device, DeviceNum,
+ DevicePtr, DeviceResident, DeviceType, Finalize, FirstPrivate, Gang, Host,
+ If, IfPresent, Independent, Link, NoCreate, NoHost, NumGangs, NumWorkers,
+ Present, Private, Tile, UseDevice, Read, Reduction, Self, Seq, Vector,
+ VectorLength, Wait, Worker, Write, Unknown>
+ u;
+};
+
+struct AccClauseList {
+ WRAPPER_CLASS_BOILERPLATE(AccClauseList, std::list<AccClause>);
+ CharBlock source;
+};
+
+struct OpenACCRoutineConstruct {
+ TUPLE_CLASS_BOILERPLATE(OpenACCRoutineConstruct);
+ CharBlock source;
+ std::tuple<Verbatim, std::optional<Name>, AccClauseList> t;
+};
+
+struct OpenACCCacheConstruct {
+ TUPLE_CLASS_BOILERPLATE(OpenACCCacheConstruct);
+ CharBlock source;
+ std::tuple<Verbatim, AccObjectListWithModifier> t;
+};
+
+struct OpenACCWaitConstruct {
+ TUPLE_CLASS_BOILERPLATE(OpenACCWaitConstruct);
+ CharBlock source;
+ std::tuple<Verbatim, std::optional<AccWaitArgument>, AccClauseList> t;
+};
+
+struct AccBeginLoopDirective {
+ TUPLE_CLASS_BOILERPLATE(AccBeginLoopDirective);
+ std::tuple<AccLoopDirective, AccClauseList> t;
+ CharBlock source;
+};
+
+struct AccBeginBlockDirective {
+ TUPLE_CLASS_BOILERPLATE(AccBeginBlockDirective);
+ CharBlock source;
+ std::tuple<AccBlockDirective, AccClauseList> t;
+};
+
+struct AccEndBlockDirective {
+ CharBlock source;
+ WRAPPER_CLASS_BOILERPLATE(AccEndBlockDirective, AccBlockDirective);
+};
+
+// ACC END ATOMIC
+EMPTY_CLASS(AccEndAtomic);
+
+// ACC ATOMIC READ
+struct AccAtomicRead {
+ TUPLE_CLASS_BOILERPLATE(AccAtomicRead);
+ std::tuple<Verbatim, Statement<AssignmentStmt>, std::optional<AccEndAtomic>>
+ t;
+};
+
+// ACC ATOMIC WRITE
+struct AccAtomicWrite {
+ TUPLE_CLASS_BOILERPLATE(AccAtomicWrite);
+ std::tuple<Verbatim, Statement<AssignmentStmt>, std::optional<AccEndAtomic>>
+ t;
+};
+
+// ACC ATOMIC UPDATE
+struct AccAtomicUpdate {
+ TUPLE_CLASS_BOILERPLATE(AccAtomicUpdate);
+ std::tuple<std::optional<Verbatim>, Statement<AssignmentStmt>,
+ std::optional<AccEndAtomic>>
+ t;
+};
+
+// ACC ATOMIC CAPTURE
+struct AccAtomicCapture {
+ TUPLE_CLASS_BOILERPLATE(AccAtomicCapture);
+ WRAPPER_CLASS(Stmt1, Statement<AssignmentStmt>);
+ WRAPPER_CLASS(Stmt2, Statement<AssignmentStmt>);
+ std::tuple<Verbatim, Stmt1, Stmt2, AccEndAtomic> t;
+};
+
+struct OpenACCAtomicConstruct {
+ UNION_CLASS_BOILERPLATE(OpenACCAtomicConstruct);
+ std::variant<AccAtomicRead, AccAtomicWrite, AccAtomicCapture, AccAtomicUpdate>
+ u;
+};
+
+struct OpenACCBlockConstruct {
+ TUPLE_CLASS_BOILERPLATE(OpenACCBlockConstruct);
+ std::tuple<AccBeginBlockDirective, Block, AccEndBlockDirective> t;
+};
+
+struct OpenACCStandaloneDeclarativeConstruct {
+ TUPLE_CLASS_BOILERPLATE(OpenACCStandaloneDeclarativeConstruct);
+ CharBlock source;
+ std::tuple<AccDeclarativeDirective, AccClauseList> t;
+};
+
+struct AccBeginCombinedDirective {
+ TUPLE_CLASS_BOILERPLATE(AccBeginCombinedDirective);
+ std::tuple<AccCombinedDirective, AccClauseList> t;
+};
+
+struct AccEndCombinedDirective {
+ WRAPPER_CLASS_BOILERPLATE(AccEndCombinedDirective, AccCombinedDirective);
+ CharBlock source;
+};
+
+struct OpenACCCombinedConstruct {
+ TUPLE_CLASS_BOILERPLATE(OpenACCCombinedConstruct);
+ CharBlock source;
+ std::tuple<AccBeginCombinedDirective, Block,
+ std::optional<AccEndCombinedDirective>>
+ t;
+};
+
+struct OpenACCDeclarativeConstruct {
+ UNION_CLASS_BOILERPLATE(OpenACCDeclarativeConstruct);
+ CharBlock source;
+ std::variant<OpenACCStandaloneDeclarativeConstruct> u;
+};
+
+// OpenACC directives enclosing do loop
+struct OpenACCLoopConstruct {
+ TUPLE_CLASS_BOILERPLATE(OpenACCLoopConstruct);
+ OpenACCLoopConstruct(AccBeginLoopDirective &&a)
+ : t({std::move(a), std::nullopt}) {}
+ std::tuple<AccBeginLoopDirective, std::optional<DoConstruct>> t;
+};
+
+struct OpenACCStandaloneConstruct {
+ TUPLE_CLASS_BOILERPLATE(OpenACCStandaloneConstruct);
+ CharBlock source;
+ std::tuple<AccStandaloneDirective, AccClauseList> t;
+};
+
+struct OpenACCConstruct {
+ UNION_CLASS_BOILERPLATE(OpenACCConstruct);
+ std::variant<OpenACCBlockConstruct, OpenACCCombinedConstruct,
+ OpenACCLoopConstruct, OpenACCStandaloneConstruct, OpenACCRoutineConstruct,
+ OpenACCCacheConstruct, OpenACCWaitConstruct, OpenACCAtomicConstruct>
+ u;
+};
+
} // namespace Fortran::parser
#endif // FORTRAN_PARSER_PARSE_TREE_H_
diff --git a/flang/lib/Parser/CMakeLists.txt b/flang/lib/Parser/CMakeLists.txt
index eb5126e1b937..e1e77ac6e92d 100644
--- a/flang/lib/Parser/CMakeLists.txt
+++ b/flang/lib/Parser/CMakeLists.txt
@@ -11,6 +11,7 @@ add_flang_library(FortranParser
instrumented-parser.cpp
io-parsers.cpp
message.cpp
+ openacc-parsers.cpp
openmp-parsers.cpp
parse-tree.cpp
parsing.cpp
@@ -32,4 +33,5 @@ add_flang_library(FortranParser
DEPENDS
omp_gen
+ acc_gen
)
diff --git a/flang/lib/Parser/executable-parsers.cpp b/flang/lib/Parser/executable-parsers.cpp
index 160b2dc376a4..d6dd4688dbac 100644
--- a/flang/lib/Parser/executable-parsers.cpp
+++ b/flang/lib/Parser/executable-parsers.cpp
@@ -50,6 +50,7 @@ constexpr auto executableConstruct{
construct<ExecutableConstruct>(indirect(whereConstruct)),
construct<ExecutableConstruct>(indirect(forallConstruct)),
construct<ExecutableConstruct>(indirect(ompEndLoopDirective)),
+ construct<ExecutableConstruct>(indirect(openaccConstruct)),
construct<ExecutableConstruct>(indirect(openmpConstruct)),
construct<ExecutableConstruct>(indirect(compilerDirective)))};
diff --git a/flang/lib/Parser/openacc-parsers.cpp b/flang/lib/Parser/openacc-parsers.cpp
new file mode 100644
index 000000000000..de55ea27f822
--- /dev/null
+++ b/flang/lib/Parser/openacc-parsers.cpp
@@ -0,0 +1,282 @@
+//===-- lib/Parser/openacc-parsers.cpp ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Top-level grammar specification for OpenACC 3.0.
+
+#include "basic-parsers.h"
+#include "expr-parsers.h"
+#include "misc-parsers.h"
+#include "stmt-parser.h"
+#include "token-parsers.h"
+#include "type-parser-implementation.h"
+#include "flang/Parser/parse-tree.h"
+
+// OpenACC Directives and Clauses
+namespace Fortran::parser {
+
+constexpr auto startAccLine = skipStuffBeforeStatement >> "!$ACC "_sptok;
+constexpr auto endAccLine = space >> endOfLine;
+
+// Basic clauses
+TYPE_PARSER("AUTO" >> construct<AccClause>(construct<AccClause::Auto>()) ||
+ "ASYNC" >> construct<AccClause>(construct<AccClause::Async>(
+ maybe(parenthesized(scalarIntExpr)))) ||
+ "ATTACH" >> construct<AccClause>(construct<AccClause::Attach>(
+ parenthesized(Parser<AccObjectList>{}))) ||
+ "BIND" >> construct<AccClause>(construct<AccClause::Bind>(
+ parenthesized(name))) ||
+ "CAPTURE" >> construct<AccClause>(construct<AccClause::Capture>()) ||
+ "COLLAPSE" >> construct<AccClause>(construct<AccClause::Collapse>(
+ parenthesized(scalarIntConstantExpr))) ||
+ ("COPY"_tok || "PRESENT_OR_COPY"_tok || "PCOPY"_tok) >>
+ construct<AccClause>(construct<AccClause::Copy>(
+ parenthesized(Parser<AccObjectList>{}))) ||
+ ("COPYIN"_tok || "PRESENT_OR_COPYIN"_tok || "PCOPYIN"_tok) >>
+ construct<AccClause>(construct<AccClause::Copyin>(
+ parenthesized(Parser<AccObjectListWithModifier>{}))) ||
+ ("COPYOUT"_tok || "PRESENT_OR_COPYOUT"_tok || "PCOPYOUT"_tok) >>
+ construct<AccClause>(construct<AccClause::Copyout>(
+ parenthesized(Parser<AccObjectListWithModifier>{}))) ||
+ ("CREATE"_tok || "PRESENT_OR_CREATE"_tok || "PCREATE"_tok) >>
+ construct<AccClause>(construct<AccClause::Create>(
+ parenthesized(Parser<AccObjectListWithModifier>{}))) ||
+ "DEFAULT" >> construct<AccClause>(construct<AccClause::Default>(
+ Parser<AccDefaultClause>{})) ||
+ "DEFAULT_ASYNC" >> construct<AccClause>(construct<AccClause::DefaultAsync>(
+ parenthesized(scalarIntExpr))) ||
+ "DELETE" >> construct<AccClause>(construct<AccClause::Delete>(
+ parenthesized(Parser<AccObjectList>{}))) ||
+ "DETACH" >> construct<AccClause>(construct<AccClause::Detach>(
+ parenthesized(Parser<AccObjectList>{}))) ||
+ "DEVICE" >> construct<AccClause>(construct<AccClause::Device>(
+ parenthesized(Parser<AccObjectList>{}))) ||
+ "DEVICEPTR" >> construct<AccClause>(construct<AccClause::DevicePtr>(
+ parenthesized(Parser<AccObjectList>{}))) ||
+ "DEVICENUM" >> construct<AccClause>(construct<AccClause::DeviceNum>(
+ parenthesized(scalarIntConstantExpr))) ||
+ "DEVICE_RESIDENT" >>
+ construct<AccClause>(construct<AccClause::DeviceResident>(
+ parenthesized(Parser<AccObjectList>{}))) ||
+ ("DEVICE_TYPE"_tok || "DTYPE"_tok) >> construct<AccClause>(
+ construct<AccClause::DeviceType>(parenthesized(
+ "*" >> construct<std::optional<std::list<Name>>>()))) ||
+ ("DEVICE_TYPE"_tok || "DTYPE"_tok) >> construct<AccClause>(
+ construct<AccClause::DeviceType>(
+ parenthesized(maybe(nonemptyList(name))))) ||
+ "FINALIZE" >> construct<AccClause>(construct<AccClause::Finalize>()) ||
+ "FIRSTPRIVATE" >> construct<AccClause>(construct<AccClause::FirstPrivate>(
+ parenthesized(Parser<AccObjectList>{}))) ||
+ "GANG" >> construct<AccClause>(construct<AccClause::Gang>(
+ maybe(parenthesized(Parser<AccGangArgument>{})))) ||
+ "HOST" >> construct<AccClause>(construct<AccClause::Host>(
+ parenthesized(Parser<AccObjectList>{}))) ||
+ "IF" >> construct<AccClause>(
+ construct<AccClause::If>(parenthesized(scalarLogicalExpr))) ||
+ "IF_PRESENT" >> construct<AccClause>(construct<AccClause::IfPresent>()) ||
+ "INDEPENDENT" >> construct<AccClause>(
+ construct<AccClause::Independent>()) ||
+ "LINK" >> construct<AccClause>(construct<AccClause::Link>(
+ parenthesized(Parser<AccObjectList>{}))) ||
+ "NO_CREATE" >> construct<AccClause>(construct<AccClause::NoCreate>(
+ parenthesized(Parser<AccObjectList>{}))) ||
+ "NOHOST" >> construct<AccClause>(construct<AccClause::NoHost>()) ||
+ "NUM_GANGS" >> construct<AccClause>(construct<AccClause::NumGangs>(
+ parenthesized(scalarIntExpr))) ||
+ "NUM_WORKERS" >> construct<AccClause>(construct<AccClause::NumWorkers>(
+ parenthesized(scalarIntExpr))) ||
+ "PRESENT" >> construct<AccClause>(construct<AccClause::Present>(
+ parenthesized(Parser<AccObjectList>{}))) ||
+ "PRIVATE" >> construct<AccClause>(construct<AccClause::Private>(
+ parenthesized(Parser<AccObjectList>{}))) ||
+ "READ" >> construct<AccClause>(construct<AccClause::Read>()) ||
+ "REDUCTION" >> construct<AccClause>(construct<AccClause::Reduction>(
+ parenthesized(construct<AccObjectListWithReduction>(
+ Parser<AccReductionOperator>{} / ":",
+ Parser<AccObjectList>{})))) ||
+ "SELF" >> construct<AccClause>(construct<AccClause::Self>(
+ maybe(parenthesized(scalarLogicalExpr)))) ||
+ "SEQ" >> construct<AccClause>(construct<AccClause::Seq>()) ||
+ "TILE" >> construct<AccClause>(construct<AccClause::Tile>(
+ parenthesized(Parser<AccSizeExprList>{}))) ||
+ "USE_DEVICE" >> construct<AccClause>(construct<AccClause::UseDevice>(
+ parenthesized(Parser<AccObjectList>{}))) ||
+ "VECTOR_LENGTH" >> construct<AccClause>(construct<AccClause::VectorLength>(
+ parenthesized(scalarIntExpr))) ||
+ "VECTOR" >> construct<AccClause>(construct<AccClause::Vector>(maybe(
+ parenthesized(("LENGTH:" >> scalarIntExpr || scalarIntExpr))))) ||
+ "WAIT" >> construct<AccClause>(construct<AccClause::Wait>(
+ maybe(Parser<AccWaitArgument>{}))) ||
+ "WORKER" >> construct<AccClause>(construct<AccClause::Worker>(maybe(
+ parenthesized(("NUM:" >> scalarIntExpr || scalarIntExpr))))) ||
+ "WRITE" >> construct<AccClause>(construct<AccClause::Auto>()))
+
+TYPE_PARSER(
+ construct<AccObject>(designator) || construct<AccObject>("/" >> name / "/"))
+
+TYPE_PARSER(construct<AccObjectList>(nonemptyList(Parser<AccObject>{})))
+
+TYPE_PARSER(construct<AccObjectListWithModifier>(
+ maybe(Parser<AccDataModifier>{}), Parser<AccObjectList>{}))
+
+TYPE_PARSER(construct<AccWaitArgument>(
+ maybe("DEVNUM:" >> scalarIntExpr / ":"), nonemptyList(scalarIntExpr)))
+
+// 2.9 (1609) size-expr is one of:
+// int-expr
+TYPE_PARSER(construct<AccSizeExpr>(scalarIntExpr) ||
+ construct<AccSizeExpr>("*" >> maybe(scalarIntExpr)))
+TYPE_PARSER(construct<AccSizeExprList>(nonemptyList(Parser<AccSizeExpr>{})))
+
+// 2.9 (1607) gang-arg is one of:
+// [num:]int-expr
+// static:size-expr
+TYPE_PARSER(construct<AccGangArgument>(maybe(scalarIntExpr),
+ maybe(","_tok / "STATIC:" >> Parser<AccSizeExpr>{})) ||
+ construct<AccGangArgument>(maybe("NUM:" >> scalarIntExpr),
+ maybe(","_tok / "STATIC:" >> Parser<AccSizeExpr>{})))
+
+// 2.5.13 Reduction
+TYPE_PARSER(construct<AccReductionOperator>(Parser<DefinedOperator>{}) ||
+ construct<AccReductionOperator>(Parser<ProcedureDesignator>{}))
+
+// 2.5.14 Default clause
+TYPE_PARSER(construct<AccDefaultClause>(
+ parenthesized(first("NONE" >> pure(AccDefaultClause::Arg::None),
+ "PRESENT" >> pure(AccDefaultClause::Arg::Present)))))
+
+// Modifier for copyin, copyout, cache and create
+TYPE_PARSER(construct<AccDataModifier>(
+ first("ZERO:" >> pure(AccDataModifier::Modifier::Zero),
+ "READONLY:" >> pure(AccDataModifier::Modifier::ReadOnly))))
+
+// Combined directives
+TYPE_PARSER(sourced(construct<AccCombinedDirective>(
+ first("KERNELS LOOP" >> pure(llvm::acc::Directive::ACCD_kernels_loop),
+ "PARALLEL LOOP" >> pure(llvm::acc::Directive::ACCD_parallel_loop),
+ "SERIAL LOOP" >> pure(llvm::acc::Directive::ACCD_serial_loop)))))
+
+// Block directives
+TYPE_PARSER(sourced(construct<AccBlockDirective>(
+ first("DATA" >> pure(llvm::acc::Directive::ACCD_data),
+ "HOST_DATA" >> pure(llvm::acc::Directive::ACCD_host_data),
+ "KERNELS" >> pure(llvm::acc::Directive::ACCD_kernels),
+ "PARALLEL" >> pure(llvm::acc::Directive::ACCD_parallel),
+ "SERIAL" >> pure(llvm::acc::Directive::ACCD_serial)))))
+
+// Standalone directives
+TYPE_PARSER(sourced(construct<AccStandaloneDirective>(
+ first("ENTER DATA" >> pure(llvm::acc::Directive::ACCD_enter_data),
+ "EXIT DATA" >> pure(llvm::acc::Directive::ACCD_exit_data),
+ "INIT" >> pure(llvm::acc::Directive::ACCD_init),
+ "SHUTDOWN" >> pure(llvm::acc::Directive::ACCD_shutdown),
+ "SET" >> pure(llvm::acc::Directive::ACCD_set),
+ "UPDATE" >> pure(llvm::acc::Directive::ACCD_update)))))
+
+// Loop directives
+TYPE_PARSER(sourced(construct<AccLoopDirective>(
+ first("LOOP" >> pure(llvm::acc::Directive::ACCD_loop)))))
+
+TYPE_PARSER(construct<AccBeginLoopDirective>(
+ sourced(Parser<AccLoopDirective>{}), Parser<AccClauseList>{}))
+
+TYPE_PARSER(
+ construct<OpenACCLoopConstruct>(sourced(Parser<AccBeginLoopDirective>{})))
+
+// 2.15.1 Routine directive
+TYPE_PARSER(sourced(construct<OpenACCRoutineConstruct>(verbatim("ROUTINE"_tok),
+ maybe(parenthesized(name)), Parser<AccClauseList>{})))
+
+// 2.10 Cache directive
+TYPE_PARSER(sourced(
+ construct<OpenACCCacheConstruct>(sourced(construct<Verbatim>("CACHE"_tok)),
+ parenthesized(Parser<AccObjectListWithModifier>{}))))
+
+// 2.11 Combined constructs
+TYPE_PARSER(startAccLine >> construct<AccEndCombinedDirective>(sourced(
+ "END"_tok >> Parser<AccCombinedDirective>{})))
+
+TYPE_PARSER(construct<AccBeginCombinedDirective>(
+ sourced(Parser<AccCombinedDirective>{}), Parser<AccClauseList>{}))
+
+TYPE_PARSER(construct<OpenACCCombinedConstruct>(
+ Parser<AccBeginCombinedDirective>{} / endAccLine, block,
+ maybe(Parser<AccEndCombinedDirective>{} / endAccLine)))
+
+// 2.12 Atomic constructs
+TYPE_PARSER(construct<AccEndAtomic>(startAccLine >> "END ATOMIC"_tok))
+
+TYPE_PARSER("ATOMIC" >>
+ construct<AccAtomicRead>(verbatim("READ"_tok) / endAccLine,
+ statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine)))
+
+TYPE_PARSER("ATOMIC" >>
+ construct<AccAtomicWrite>(verbatim("WRITE"_tok) / endAccLine,
+ statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine)))
+
+TYPE_PARSER("ATOMIC" >>
+ construct<AccAtomicUpdate>(maybe(verbatim("UPDATE"_tok)) / endAccLine,
+ statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine)))
+
+TYPE_PARSER("ATOMIC" >>
+ construct<AccAtomicCapture>(verbatim("CAPTURE"_tok) / endAccLine,
+ statement(assignmentStmt), statement(assignmentStmt),
+ Parser<AccEndAtomic>{} / endAccLine))
+
+TYPE_PARSER(construct<OpenACCAtomicConstruct>(Parser<AccAtomicRead>{}) ||
+ construct<OpenACCAtomicConstruct>(Parser<AccAtomicCapture>{}) ||
+ construct<OpenACCAtomicConstruct>(Parser<AccAtomicWrite>{}) ||
+ construct<OpenACCAtomicConstruct>(Parser<AccAtomicUpdate>{}))
+
+// 2.13 Declare constructs
+TYPE_PARSER(sourced(construct<AccDeclarativeDirective>(
+ first("DECLARE" >> pure(llvm::acc::Directive::ACCD_declare)))))
+
+// [Clause, [Clause], ...]
+TYPE_PARSER(sourced(construct<AccClauseList>(
+ many(maybe(","_tok) >> sourced(Parser<AccClause>{})))))
+
+// 2.16.3 Wait directive
+TYPE_PARSER(sourced(construct<OpenACCWaitConstruct>(
+ sourced(construct<Verbatim>("WAIT"_tok)),
+ maybe(parenthesized(Parser<AccWaitArgument>{})), Parser<AccClauseList>{})))
+
+// Block Constructs
+TYPE_PARSER(sourced(construct<AccBeginBlockDirective>(
+ sourced(Parser<AccBlockDirective>{}), Parser<AccClauseList>{})))
+
+TYPE_PARSER(startAccLine >> sourced(construct<AccEndBlockDirective>("END"_tok >>
+ sourced(Parser<AccBlockDirective>{}))))
+
+TYPE_PARSER(construct<OpenACCBlockConstruct>(
+ Parser<AccBeginBlockDirective>{} / endAccLine, block,
+ Parser<AccEndBlockDirective>{} / endAccLine))
+
+// Standalone constructs
+TYPE_PARSER(construct<OpenACCStandaloneConstruct>(
+ sourced(Parser<AccStandaloneDirective>{}), Parser<AccClauseList>{}))
+
+// Standalone declarative constructs
+TYPE_PARSER(construct<OpenACCStandaloneDeclarativeConstruct>(
+ sourced(Parser<AccDeclarativeDirective>{}), Parser<AccClauseList>{}))
+
+TYPE_PARSER(
+ startAccLine >> sourced(construct<OpenACCDeclarativeConstruct>(
+ Parser<OpenACCStandaloneDeclarativeConstruct>{})))
+
+// OpenACC constructs
+TYPE_CONTEXT_PARSER("OpenACC construct"_en_US,
+ startAccLine >>
+ first(construct<OpenACCConstruct>(Parser<OpenACCBlockConstruct>{}),
+ construct<OpenACCConstruct>(Parser<OpenACCCombinedConstruct>{}),
+ construct<OpenACCConstruct>(Parser<OpenACCLoopConstruct>{}),
+ construct<OpenACCConstruct>(Parser<OpenACCStandaloneConstruct>{}),
+ construct<OpenACCConstruct>(Parser<OpenACCRoutineConstruct>{}),
+ construct<OpenACCConstruct>(Parser<OpenACCCacheConstruct>{}),
+ construct<OpenACCConstruct>(Parser<OpenACCWaitConstruct>{}),
+ construct<OpenACCConstruct>(Parser<OpenACCAtomicConstruct>{})))
+} // namespace Fortran::parser
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 41a97ff902d9..a09a5554116f 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -23,10 +23,6 @@ namespace Fortran::parser {
constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok;
constexpr auto endOmpLine = space >> endOfLine;
-template <typename A> constexpr decltype(auto) verbatim(A x) {
- return sourced(construct<Verbatim>(x));
-}
-
// OpenMP Clauses
// 2.15.3.1 DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE)
TYPE_PARSER(construct<OmpDefaultClause>(
diff --git a/flang/lib/Parser/parsing.cpp b/flang/lib/Parser/parsing.cpp
index 5e12b5545f0a..d7a7d107878d 100644
--- a/flang/lib/Parser/parsing.cpp
+++ b/flang/lib/Parser/parsing.cpp
@@ -67,6 +67,9 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
prescanner.set_fixedForm(options.isFixedForm)
.set_fixedFormColumnLimit(options.fixedFormColumns)
.AddCompilerDirectiveSentinel("dir$");
+ if (options.features.IsEnabled(LanguageFeature::OpenACC)) {
+ prescanner.AddCompilerDirectiveSentinel("$acc");
+ }
if (options.features.IsEnabled(LanguageFeature::OpenMP)) {
prescanner.AddCompilerDirectiveSentinel("$omp");
prescanner.AddCompilerDirectiveSentinel("$"); // OMP conditional line
diff --git a/flang/lib/Parser/program-parsers.cpp b/flang/lib/Parser/program-parsers.cpp
index fc2c7c324eb6..9e18c458ea3c 100644
--- a/flang/lib/Parser/program-parsers.cpp
+++ b/flang/lib/Parser/program-parsers.cpp
@@ -60,7 +60,8 @@ TYPE_PARSER(construct<ProgramUnit>(indirect(Parser<Module>{})) ||
// [use-stmt]... [import-stmt]... [implicit-part]
// [declaration-construct]...
TYPE_CONTEXT_PARSER("specification part"_en_US,
- construct<SpecificationPart>(many(openmpDeclarativeConstruct),
+ construct<SpecificationPart>(many(openaccDeclarativeConstruct),
+ many(openmpDeclarativeConstruct),
many(statement(indirect(Parser<UseStmt>{}))),
many(unambiguousStatement(indirect(Parser<ImportStmt>{}))),
implicitPart, many(declarationConstruct)))
@@ -75,10 +76,10 @@ TYPE_CONTEXT_PARSER("specification part"_en_US,
// are in contexts that impose constraints on the kinds of statements that
// are allowed, and so we have a variant production for declaration-construct
// that implements those constraints.
-constexpr auto execPartLookAhead{
- first(actionStmt >> ok, ompEndLoopDirective >> ok, openmpConstruct >> ok,
- "ASSOCIATE ("_tok, "BLOCK"_tok, "SELECT"_tok, "CHANGE TEAM"_sptok,
- "CRITICAL"_tok, "DO"_tok, "IF ("_tok, "WHERE ("_tok, "FORALL ("_tok)};
+constexpr auto execPartLookAhead{first(actionStmt >> ok,
+ ompEndLoopDirective >> ok, openaccConstruct >> ok, openmpConstruct >> ok,
+ "ASSOCIATE ("_tok, "BLOCK"_tok, "SELECT"_tok, "CHANGE TEAM"_sptok,
+ "CRITICAL"_tok, "DO"_tok, "IF ("_tok, "WHERE ("_tok, "FORALL ("_tok)};
constexpr auto declErrorRecovery{
stmtErrorRecoveryStart >> !execPartLookAhead >> skipStmtErrorRecovery};
constexpr auto misplacedSpecificationStmt{Parser<UseStmt>{} >>
@@ -126,7 +127,8 @@ constexpr auto limitedDeclarationConstruct{recovery(
// specialized error recovery in the event of a spurious executable
// statement.
constexpr auto limitedSpecificationPart{inContext("specification part"_en_US,
- construct<SpecificationPart>(many(openmpDeclarativeConstruct),
+ construct<SpecificationPart>(many(openaccDeclarativeConstruct),
+ many(openmpDeclarativeConstruct),
many(statement(indirect(Parser<UseStmt>{}))),
many(unambiguousStatement(indirect(Parser<ImportStmt>{}))),
implicitPart, many(limitedDeclarationConstruct)))};
@@ -151,6 +153,8 @@ TYPE_CONTEXT_PARSER("specification construct"_en_US,
construct<SpecificationConstruct>(
statement(indirect(typeDeclarationStmt))),
construct<SpecificationConstruct>(indirect(Parser<StructureDef>{})),
+ construct<SpecificationConstruct>(
+ indirect(openaccDeclarativeConstruct)),
construct<SpecificationConstruct>(indirect(openmpDeclarativeConstruct)),
construct<SpecificationConstruct>(indirect(compilerDirective))))
diff --git a/flang/lib/Parser/stmt-parser.h b/flang/lib/Parser/stmt-parser.h
index 7dcc1f4620a9..cd1c69beedd4 100644
--- a/flang/lib/Parser/stmt-parser.h
+++ b/flang/lib/Parser/stmt-parser.h
@@ -80,6 +80,7 @@ constexpr auto skipBadLine{SkipPast<'\n'>{} >> construct<ErrorRecovery>()};
constexpr auto executionPartErrorRecovery{stmtErrorRecoveryStart >>
!"END"_tok >> !"CONTAINS"_tok >> !"ELSE"_tok >> !"CASE"_tok >>
!"TYPE IS"_tok >> !"CLASS"_tok >> !"RANK"_tok >>
+ !("!$ACC "_sptok >> "END"_tok) >>
!("!$OMP "_sptok >> ("END"_tok || "SECTION"_id)) >> skipBadLine};
// END statement error recovery
diff --git a/flang/lib/Parser/token-parsers.h b/flang/lib/Parser/token-parsers.h
index fe43182e386f..14ae12cda6f4 100644
--- a/flang/lib/Parser/token-parsers.h
+++ b/flang/lib/Parser/token-parsers.h
@@ -664,5 +664,10 @@ constexpr auto logicalFALSE{
constexpr auto rawHollerithLiteral{
deprecated<LanguageFeature::Hollerith>(HollerithLiteral{})};
+
+template <typename A> constexpr decltype(auto) verbatim(A x) {
+ return sourced(construct<Verbatim>(x));
+}
+
} // namespace Fortran::parser
#endif // FORTRAN_PARSER_TOKEN_PARSERS_H_
diff --git a/flang/lib/Parser/type-parsers.h b/flang/lib/Parser/type-parsers.h
index c7a1bce781ff..a2f38e90db21 100644
--- a/flang/lib/Parser/type-parsers.h
+++ b/flang/lib/Parser/type-parsers.h
@@ -130,6 +130,8 @@ constexpr Parser<EndSubroutineStmt> endSubroutineStmt; // R1537
constexpr Parser<EntryStmt> entryStmt; // R1541
constexpr Parser<ContainsStmt> containsStmt; // R1543
constexpr Parser<CompilerDirective> compilerDirective;
+constexpr Parser<OpenACCConstruct> openaccConstruct;
+constexpr Parser<OpenACCDeclarativeConstruct> openaccDeclarativeConstruct;
constexpr Parser<OpenMPConstruct> openmpConstruct;
constexpr Parser<OpenMPDeclarativeConstruct> openmpDeclarativeConstruct;
constexpr Parser<OmpEndLoopDirective> ompEndLoopDirective;
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 09acaaa37076..99792cbf706f 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -1777,6 +1777,375 @@ class UnparseVisitor {
}
Walk(std::get<Name>(x.t));
}
+
+ // OpenACC Directives & Clauses
+ void Unparse(const AccAtomicCapture &x) {
+ BeginOpenACC();
+ Word("!$ACC CAPTURE");
+ Put("\n");
+ EndOpenACC();
+ Walk(std::get<AccAtomicCapture::Stmt1>(x.t));
+ Put("\n");
+ Walk(std::get<AccAtomicCapture::Stmt2>(x.t));
+ BeginOpenACC();
+ Word("!$ACC END ATOMIC\n");
+ EndOpenACC();
+ }
+ void Unparse(const AccAtomicRead &x) {
+ BeginOpenACC();
+ Word("!$ACC ATOMIC READ");
+ Put("\n");
+ EndOpenACC();
+ Walk(std::get<Statement<AssignmentStmt>>(x.t));
+ BeginOpenACC();
+ Walk(std::get<std::optional<AccEndAtomic>>(x.t), "!$ACC END ATOMIC\n");
+ EndOpenACC();
+ }
+ void Unparse(const AccAtomicWrite &x) {
+ BeginOpenACC();
+ Word("!$ACC ATOMIC WRITE");
+ Put("\n");
+ EndOpenACC();
+ Walk(std::get<Statement<AssignmentStmt>>(x.t));
+ BeginOpenACC();
+ Walk(std::get<std::optional<AccEndAtomic>>(x.t), "!$ACC END ATOMIC\n");
+ EndOpenACC();
+ }
+ void Unparse(const AccAtomicUpdate &x) {
+ BeginOpenACC();
+ Word("!$ACC ATOMIC UPDATE");
+ Put("\n");
+ EndOpenACC();
+ Walk(std::get<Statement<AssignmentStmt>>(x.t));
+ BeginOpenACC();
+ Walk(std::get<std::optional<AccEndAtomic>>(x.t), "!$ACC END ATOMIC\n");
+ EndOpenACC();
+ }
+ void Unparse(const llvm::acc::Directive &x) {
+ Word(llvm::acc::getOpenACCDirectiveName(x).str());
+ }
+ void Before(const AccClause::Auto &) { Word("AUTO"); }
+ void Before(const AccClause::Capture &) { Word("CAPTURE"); }
+ void Before(const AccClause::Finalize &) { Word("FINALIZE"); }
+ void Before(const AccClause::IfPresent &) { Word("IF_PRESENT"); }
+ void Before(const AccClause::Independent &) { Word("INDEPENDENT"); }
+ void Before(const AccClause::NoHost &) { Word("NOHOST"); }
+ void Before(const AccClause::Read &) { Word("READ"); }
+ void Before(const AccClause::Seq &) { Word("SEQ"); }
+ void Before(const AccClause::Write &) { Word("WRITE"); }
+ void Before(const AccClause::Unknown &) { Word("UNKNOWN"); }
+ void Unparse(const AccClause::Attach &x) {
+ Word("ATTACH");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Bind &x) {
+ Word("BIND");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Collapse &x) {
+ Word("COLLAPSE");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Copy &x) {
+ Word("COPY");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Copyin &x) {
+ Word("COPYIN");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Copyout &x) {
+ Word("COPYOUT");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Create &x) {
+ Word("CREATE");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Default &x) {
+ Word("DEFAULT");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Delete &x) {
+ Word("DELETE");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Detach &x) {
+ Word("DETACH");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Device &x) {
+ Word("DEVICE");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::DevicePtr &x) {
+ Word("DEVICEPTR");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::DeviceResident &x) {
+ Word("DEVICE_RESIDENT");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::FirstPrivate &x) {
+ Word("FIRSTPRIVATE");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Host &x) {
+ Word("HOST");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::If &x) {
+ Word("IF");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Link &x) {
+ Word("LINK");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::NumGangs &x) {
+ Word("NUM_GANGS");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::NumWorkers &x) {
+ Word("NUM_WORKERS");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Present &x) {
+ Word("PRESENT");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Private &x) {
+ Word("PRIVATE");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Reduction &x) {
+ Word("REDUCTION");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::VectorLength &x) {
+ Word("VECTOR_LENGTH");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Async &x) {
+ Word("ASYNC");
+ Walk("(", x.v, ")");
+ }
+ void Unparse(const AccClause::DefaultAsync &x) {
+ Word("DEFAULT_ASYNC");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::DeviceNum &x) {
+ Word("DEVICE_NUM");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Gang &x) {
+ Word("GANG");
+ Walk("(", x.v, ")");
+ }
+ void Unparse(const AccClause::NoCreate &x) {
+ Word("NO_CREATE");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::UseDevice &x) {
+ Word("USE_DEVICE");
+ Put("(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const AccClause::Self &x) {
+ Word("SELF");
+ Walk("(", x.v, ")");
+ }
+ void Unparse(const AccClause::Vector &x) {
+ Word("VECTOR");
+ Walk("(", x.v, ")");
+ }
+ void Unparse(const AccClause::Wait &x) {
+ Word("WAIT");
+ Walk("(", x.v, ")");
+ }
+ void Unparse(const AccClause::Worker &x) {
+ Word("WORKER");
+ Walk("(", x.v, ")");
+ }
+ void Unparse(const AccClause::DeviceType &x) {
+ Word("DEVICE_TYPE");
+ Put("(");
+ if (x.v.has_value())
+ Walk(x.v);
+ else
+ Put("*");
+ Put(")");
+ }
+ void Unparse(const AccObjectListWithModifier &x) {
+ Walk(std::get<std::optional<AccDataModifier>>(x.t), ":");
+ Walk(std::get<AccObjectList>(x.t));
+ }
+ void Unparse(const AccDataModifier::Modifier &x) {
+ Word(AccDataModifier::EnumToString(x));
+ }
+ void Unparse(const AccDefaultClause &x) {
+ switch (x.v) {
+ case AccDefaultClause::Arg::None:
+ Put("NONE");
+ break;
+ case AccDefaultClause::Arg::Present:
+ Put("PRESENT");
+ break;
+ }
+ }
+ void Unparse(const AccClauseList &x) { Walk(" ", x.v, " "); }
+ void Unparse(const AccGangArgument &x) {
+ Walk("NUM:", std::get<std::optional<ScalarIntExpr>>(x.t));
+ Walk(", STATIC:", std::get<std::optional<AccSizeExpr>>(x.t));
+ }
+ void Unparse(const OpenACCBlockConstruct &x) {
+ BeginOpenACC();
+ Word("!$ACC ");
+ Walk(std::get<AccBeginBlockDirective>(x.t));
+ Put("\n");
+ EndOpenACC();
+ Walk(std::get<Block>(x.t), "");
+ BeginOpenACC();
+ Word("!$ACC END ");
+ Walk(std::get<AccEndBlockDirective>(x.t));
+ Put("\n");
+ EndOpenACC();
+ }
+ void Unparse(const OpenACCLoopConstruct &x) {
+ BeginOpenACC();
+ Word("!$ACC ");
+ Walk(std::get<AccBeginLoopDirective>(x.t));
+ Put("\n");
+ EndOpenACC();
+ Walk(std::get<std::optional<DoConstruct>>(x.t));
+ }
+ void Unparse(const AccBeginLoopDirective &x) {
+ Walk(std::get<AccLoopDirective>(x.t));
+ Walk(std::get<AccClauseList>(x.t));
+ }
+ void Unparse(const OpenACCStandaloneConstruct &x) {
+ BeginOpenACC();
+ Word("!$ACC ");
+ Walk(std::get<AccStandaloneDirective>(x.t));
+ Walk(std::get<AccClauseList>(x.t));
+ Put("\n");
+ EndOpenACC();
+ }
+ void Unparse(const OpenACCStandaloneDeclarativeConstruct &x) {
+ BeginOpenACC();
+ Word("!$ACC ");
+ Walk(std::get<AccDeclarativeDirective>(x.t));
+ Walk(std::get<AccClauseList>(x.t));
+ Put("\n");
+ EndOpenACC();
+ }
+ void Unparse(const OpenACCCombinedConstruct &x) {
+ BeginOpenACC();
+ Word("!$ACC ");
+ Walk(std::get<AccBeginCombinedDirective>(x.t));
+ Put("\n");
+ EndOpenACC();
+ Walk(std::get<Block>(x.t), "");
+ BeginOpenACC();
+ Word("!$ACC END ");
+ Walk(std::get<std::optional<AccEndCombinedDirective>>(x.t));
+ Put("\n");
+ EndOpenACC();
+ }
+ void Unparse(const OpenACCRoutineConstruct &x) {
+ BeginOpenACC();
+ Word("!$ACC ROUTINE");
+ Walk("(", std::get<std::optional<Name>>(x.t), ")");
+ Walk(std::get<AccClauseList>(x.t));
+ Put("\n");
+ EndOpenACC();
+ }
+ void Unparse(const AccObject &x) {
+ std::visit(common::visitors{
+ [&](const Designator &y) { Walk(y); },
+ [&](const Name &y) { Put("/"), Walk(y), Put("/"); },
+ },
+ x.u);
+ }
+ void Unparse(const AccObjectList &x) { Walk(x.v, ","); }
+ void Unparse(const AccObjectListWithReduction &x) {
+ Walk(std::get<AccReductionOperator>(x.t));
+ Put(":");
+ Walk(std::get<AccObjectList>(x.t));
+ }
+ void Unparse(const OpenACCCacheConstruct &x) {
+ BeginOpenACC();
+ Word("!$ACC ");
+ Word("CACHE(");
+ Walk(std::get<AccObjectListWithModifier>(x.t));
+ Put(")");
+ Put("\n");
+ EndOpenACC();
+ }
+ void Unparse(const OpenACCWaitConstruct &x) {
+ BeginOpenACC();
+ Word("!$ACC ");
+ Word("WAIT(");
+ Walk(std::get<std::optional<AccWaitArgument>>(x.t));
+ Walk(std::get<AccClauseList>(x.t));
+ Put(")");
+ Put("\n");
+ EndOpenACC();
+ }
+
// OpenMP Clauses & Directives
void Unparse(const OmpObject &x) {
std::visit(common::visitors{
@@ -2522,6 +2891,8 @@ class UnparseVisitor {
}
void BeginOpenMP() { openmpDirective_ = true; }
void EndOpenMP() { openmpDirective_ = false; }
+ void BeginOpenACC() { openaccDirective_ = true; }
+ void EndOpenACC() { openaccDirective_ = false; }
// Call back to the traversal framework.
template <typename T> void Walk(const T &x) {
@@ -2591,6 +2962,7 @@ class UnparseVisitor {
std::set<CharBlock> structureComponents_;
Encoding encoding_{Encoding::UTF_8};
bool capitalizeKeywords_{true};
+ bool openaccDirective_{false};
bool openmpDirective_{false};
bool backslashEscapes_{false};
preStatementType *preStatement_{nullptr};
@@ -2599,7 +2971,7 @@ class UnparseVisitor {
void UnparseVisitor::Put(char ch) {
int sav = indent_;
- if (openmpDirective_) {
+ if (openmpDirective_ || openaccDirective_) {
indent_ = 0;
}
if (column_ <= 1) {
@@ -2620,13 +2992,16 @@ void UnparseVisitor::Put(char ch) {
if (openmpDirective_) {
out_ << "!$OMP&";
column_ = 8;
+ } else if (openaccDirective_) {
+ out_ << "!$ACC&";
+ column_ = 8;
} else {
out_ << '&';
column_ = indent_ + 3;
}
}
out_ << ch;
- if (openmpDirective_) {
+ if (openmpDirective_ || openaccDirective_) {
indent_ = sav;
}
}
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 4d70f03dd553..bd566408cd2c 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -6010,7 +6010,8 @@ bool ResolveNamesVisitor::Pre(const parser::SpecificationPart &x) {
Walk(std::get<1>(x.t));
Walk(std::get<2>(x.t));
Walk(std::get<3>(x.t));
- const std::list<parser::DeclarationConstruct> &decls{std::get<4>(x.t)};
+ Walk(std::get<4>(x.t));
+ const std::list<parser::DeclarationConstruct> &decls{std::get<5>(x.t)};
for (const auto &decl : decls) {
if (const auto *spec{
std::get_if<parser::SpecificationConstruct>(&decl.u)}) {
diff --git a/flang/test/Semantics/acc-validity.f90 b/flang/test/Semantics/acc-validity.f90
new file mode 100644
index 000000000000..88f62a84d161
--- /dev/null
+++ b/flang/test/Semantics/acc-validity.f90
@@ -0,0 +1,169 @@
+! RUN: %S/test_errors.sh %s %t %f18 -fopenacc
+
+! Check OpenACC clause validity for the following construct and directive:
+! 2.6.5 Data
+! 2.5.1 Parallel
+! 2.5.2 Kernels
+! 2.5.3 Serial
+! 2.15.1 Routine
+! 2.11 Parallel Loop
+! 2.11 Kernels Loop
+! 2.11 Serial Loop
+
+program openacc_clause_validity
+
+ implicit none
+
+ integer :: i, j
+ integer :: N = 256
+
+ !$acc declare
+ real(8) :: a(256)
+
+ !$acc enter data
+
+ !$acc enter data copyin(zero: i)
+
+ !$acc enter data create(readonly: i)
+
+ !$acc data copyout(readonly: i)
+ !$acc end data
+
+ !$acc enter data copyin(i) copyout(i)
+
+ !$acc data copy(i) if(.true.) if(.true.)
+ !$acc end data
+
+ !$acc exit data
+
+ !$acc host_data
+ !$acc end host_data
+
+ !$acc set
+
+ !$acc data
+ !$acc end data
+
+ !$acc data copyin(i)
+ !$acc end data
+
+ !$acc data copyin(i)
+
+ !$acc end parallel
+
+ !$acc update device(i) device_type(*) async
+
+
+ !$acc update device(i) device_type(*) if(.TRUE.)
+
+ !$acc parallel
+
+ !$acc loop seq independent
+ do i = 1, N
+ a(i) = 3.14
+ end do
+ !$acc end parallel
+
+ !$acc parallel device_type(*) num_gangs(2)
+ !$acc loop
+ do i = 1, N
+ a(i) = 3.14
+ end do
+ !$acc end parallel
+
+ !$acc parallel
+
+ !$acc loop collapse(-1)
+ do i = 1, N
+ do j = 1, N
+ a(i) = 3.14 + j
+ end do
+ end do
+ !$acc end parallel
+
+ !$acc parallel
+
+ !$acc loop device_type(*) private(i)
+ do i = 1, N
+ a(i) = 3.14
+ end do
+ !$acc end parallel
+
+ !$acc parallel
+
+ !$acc loop gang seq
+ do i = 1, N
+ a(i) = 3.14
+ end do
+ !$acc end parallel
+
+
+ !$acc parallel device_type(*) if(.TRUE.)
+ !$acc loop
+ do i = 1, N
+ a(i) = 3.14
+ end do
+ !$acc end parallel
+
+
+ !$acc parallel loop device_type(*) if(.TRUE.)
+ do i = 1, N
+ a(i) = 3.14
+ end do
+ !$acc end parallel loop
+
+ !$acc kernels device_type(*) async
+ do i = 1, N
+ a(i) = 3.14
+ end do
+ !$acc end kernels
+
+
+ !$acc kernels device_type(*) if(.TRUE.)
+ do i = 1, N
+ a(i) = 3.14
+ end do
+ !$acc end kernels
+
+
+ !$acc kernels loop device_type(*) if(.TRUE.)
+ do i = 1, N
+ a(i) = 3.14
+ end do
+ !$acc end kernels loop
+
+ !$acc serial device_type(*) async
+ do i = 1, N
+ a(i) = 3.14
+ end do
+ !$acc end serial
+
+
+ !$acc serial device_type(*) if(.TRUE.)
+ do i = 1, N
+ a(i) = 3.14
+ end do
+ !$acc end serial
+
+
+ !$acc serial loop device_type(*) if(.TRUE.)
+ do i = 1, N
+ a(i) = 3.14
+ end do
+ !$acc end serial loop
+
+ contains
+
+ subroutine sub1(a)
+ real :: a(:)
+
+ !$acc routine
+ end subroutine sub1
+
+ subroutine sub2(a)
+ real :: a(:)
+
+ !$acc routine seq device_type(*) nohost
+ end subroutine sub2
+
+end program openacc_clause_validity
\ No newline at end of file
diff --git a/flang/tools/f18-parse-demo/CMakeLists.txt b/flang/tools/f18-parse-demo/CMakeLists.txt
index 465873ca00ff..a89e8ae8816c 100644
--- a/flang/tools/f18-parse-demo/CMakeLists.txt
+++ b/flang/tools/f18-parse-demo/CMakeLists.txt
@@ -1,4 +1,5 @@
set(LLVM_LINK_COMPONENTS
+ FrontendOpenACC
FrontendOpenMP
)
diff --git a/flang/tools/f18/CMakeLists.txt b/flang/tools/f18/CMakeLists.txt
index 8738561fe45e..46c38fa43a2e 100644
--- a/flang/tools/f18/CMakeLists.txt
+++ b/flang/tools/f18/CMakeLists.txt
@@ -1,4 +1,5 @@
set(LLVM_LINK_COMPONENTS
+ FrontendOpenACC
FrontendOpenMP
Support
)
@@ -59,7 +60,7 @@ install(TARGETS f18 DESTINATION bin)
set(FLANG_INTRINSIC_MODULES_DIR ${FLANG_BINARY_DIR}/include/flang)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/flang.sh.in ${CMAKE_BINARY_DIR}/tools/flang/bin/flang @ONLY)
-file(COPY ${CMAKE_BINARY_DIR}/tools/flang/bin/flang DESTINATION ${CMAKE_BINARY_DIR}/bin FILE_PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE)
+file(COPY ${CMAKE_BINARY_DIR}/tools/flang/bin/flang DESTINATION ${CMAKE_BINARY_DIR}/bin FILE_PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE)
# The flang script to be installed needs a
diff erent path to the headers.
set(FLANG_INTRINSIC_MODULES_DIR ${CMAKE_INSTALL_PREFIX}/include/flang)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/flang.sh.in ${FLANG_BINARY_DIR}/bin/flang-install.sh @ONLY)
diff --git a/flang/tools/f18/f18.cpp b/flang/tools/f18/f18.cpp
index 05766a9c6a6d..5f6070a0fe34 100644
--- a/flang/tools/f18/f18.cpp
+++ b/flang/tools/f18/f18.cpp
@@ -468,6 +468,9 @@ int main(int argc, char *const argv[]) {
} else if (arg == "-Mstandard" || arg == "-std=f95" ||
arg == "-std=f2003" || arg == "-std=f2008" || arg == "-std=legacy") {
driver.warnOnNonstandardUsage = true;
+ } else if (arg == "-fopenacc") {
+ options.features.Enable(Fortran::common::LanguageFeature::OpenACC);
+ options.predefinitions.emplace_back("_OPENACC", "201911");
} else if (arg == "-fopenmp") {
options.features.Enable(Fortran::common::LanguageFeature::OpenMP);
options.predefinitions.emplace_back("_OPENMP", "201511");
diff --git a/llvm/include/llvm/CMakeLists.txt b/llvm/include/llvm/CMakeLists.txt
index 7cf8699aa21e..b46319f24fc8 100644
--- a/llvm/include/llvm/CMakeLists.txt
+++ b/llvm/include/llvm/CMakeLists.txt
@@ -1,6 +1,6 @@
add_subdirectory(IR)
add_subdirectory(Support)
-add_subdirectory(Frontend/OpenMP)
+add_subdirectory(Frontend)
# If we're doing an out-of-tree build, copy a module map for generated
# header files into the build area.
diff --git a/llvm/include/llvm/Frontend/CMakeLists.txt b/llvm/include/llvm/Frontend/CMakeLists.txt
new file mode 100644
index 000000000000..ea66917b8936
--- /dev/null
+++ b/llvm/include/llvm/Frontend/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_subdirectory(OpenACC)
+add_subdirectory(OpenMP)
diff --git a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
index 3c295a1d7c5f..26049ca60db3 100644
--- a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
+++ b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
@@ -59,6 +59,9 @@ class Clause<string c> {
// Optional class holding value of the clause in clang AST.
string clangClass = ?;
+ // Optional class holding value of the clause in flang AST.
+ string flangClass = ?;
+
// Is clause implicit? If clause is set as implicit, the default kind will
// be return in get<LanguageName>ClauseKind instead of their own kind.
bit isImplicit = 0;
diff --git a/llvm/include/llvm/Frontend/OpenACC/ACC.td b/llvm/include/llvm/Frontend/OpenACC/ACC.td
new file mode 100644
index 000000000000..0bc0f2481db5
--- /dev/null
+++ b/llvm/include/llvm/Frontend/OpenACC/ACC.td
@@ -0,0 +1,604 @@
+//===-- ACC.td - OpenACC directive definition file ---------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the definition file for OpenACC directives and clauses.
+//
+//===----------------------------------------------------------------------===//
+
+include "llvm/Frontend/Directive/DirectiveBase.td"
+
+//===----------------------------------------------------------------------===//
+// Definition of general OpenACC information
+//===----------------------------------------------------------------------===//
+
+def OpenACC : DirectiveLanguage {
+ let name = "OpenACC";
+ let cppNamespace = "acc"; // final namespace will be llvm::acc
+ let directivePrefix = "ACCD_";
+ let clausePrefix = "ACCC_";
+ let makeEnumAvailableInNamespace = 1;
+ let enableBitmaskEnumInNamespace = 1;
+ let includeHeader = "llvm/Frontend/OpenACC/ACC.h.inc";
+ let clauseEnumSetClass = "AccClauseSet";
+}
+
+//===----------------------------------------------------------------------===//
+// Definition of OpenACC clauses
+//===----------------------------------------------------------------------===//
+
+// 2.9.6
+def ACCC_Auto : Clause<"auto"> {}
+
+// 2.16.1
+def ACCC_Async : Clause<"async"> {
+ let flangClass = "std::optional<ScalarIntExpr>";
+}
+
+// 2.7.11
+def ACCC_Attach : Clause<"attach"> {
+ let flangClass = "AccObjectList";
+}
+
+// 2.15.1
+def ACCC_Bind : Clause<"bind"> {
+ let flangClass = "Name";
+}
+
+// 2.12
+def ACCC_Capture : Clause<"capture"> {
+}
+
+// 2.9.1
+def ACCC_Collapse : Clause<"collapse"> {
+ let flangClass = "ScalarIntConstantExpr";
+}
+
+// 2.7.5
+def ACCC_Copy : Clause<"copy"> {
+ let flangClass = "AccObjectList";
+}
+// 2.7.6
+def ACCC_Copyin : Clause<"copyin"> {
+ let flangClass = "AccObjectListWithModifier";
+}
+
+// 2.7.7
+def ACCC_Copyout : Clause<"copyout"> {
+ let flangClass = "AccObjectListWithModifier";
+}
+
+// 2.7.8
+def ACCC_Create : Clause<"create"> {
+ let flangClass = "AccObjectListWithModifier";
+}
+
+// 2.5.14
+def ACCC_Default : Clause<"default"> {
+ let flangClass = "AccDefaultClause";
+}
+
+// 2.4.12
+def ACCC_DefaultAsync : Clause<"default_async"> {
+ let flangClass = "ScalarIntExpr";
+}
+
+// 2.7.10
+def ACCC_Delete : Clause<"delete"> {
+ let flangClass = "AccObjectList";
+}
+
+// 2.7.12
+def ACCC_Detach : Clause<"detach"> {
+ let flangClass = "AccObjectList";
+}
+
+// 2.14.4
+def ACCC_Device : Clause<"device"> {
+ let flangClass = "AccObjectList";
+}
+
+// 2.14.1
+def ACCC_DeviceNum : Clause<"devicenum"> {
+ let flangClass = "ScalarIntConstantExpr";
+}
+
+// 2.7.3
+def ACCC_DevicePtr : Clause<"deviceptr"> {
+ let flangClass = "AccObjectList";
+}
+
+// 2.13
+def ACCC_DeviceResident : Clause<"device_resident"> {
+ let flangClass = "AccObjectList";
+}
+
+// 2.4
+def ACCC_DeviceType : Clause<"device_type"> {
+ // (DeviceType, "*"
+ let flangClass = "std::optional<std::list<Name>>";
+}
+
+// 2.6.6
+def ACCC_Finalize : Clause<"finalize"> {}
+
+// 2.5.12
+def ACCC_FirstPrivate : Clause<"firstprivate"> {
+ let flangClass = "AccObjectList";
+}
+
+// 2.9.2
+def ACCC_Gang : Clause<"gang"> {
+ let flangClass = "std::optional<AccGangArgument>";
+}
+
+// 2.14.4
+def ACCC_Host : Clause<"host"> {
+ let flangClass = "AccObjectList";
+}
+
+// 2.5.4
+def ACCC_If : Clause <"if"> {
+ let flangClass = "ScalarLogicalExpr";
+}
+
+// 2.14.4
+def ACCC_IfPresent : Clause<"if_present"> {}
+
+// 2.9.9
+def ACCC_Independent : Clause<"independent"> {}
+
+// 2.13
+def ACCC_Link : Clause<"link"> {
+ let flangClass = "AccObjectList";
+}
+
+// 2.7.9
+def ACCC_NoCreate : Clause<"no_create"> {
+ let flangClass = "AccObjectList";
+}
+
+// 2.15.1
+def ACCC_NoHost : Clause<"nohost"> {}
+
+// 2.5.8
+def ACCC_NumGangs : Clause<"num_gangs"> {
+ let flangClass = "ScalarIntExpr";
+}
+
+// 2.5.9
+def ACCC_NumWorkers : Clause<"num_workers"> {
+ let flangClass = "ScalarIntExpr";
+}
+
+// 2.7.4
+def ACCC_Present : Clause<"present"> {
+ let flangClass = "AccObjectList";
+}
+
+// 2.5.11
+def ACCC_Private : Clause<"private"> {
+ let flangClass = "AccObjectList";
+}
+
+// 2.9.7
+def ACCC_Tile : Clause <"tile"> {
+ let flangClass = "AccSizeExprList";
+}
+
+// 2.8.1
+def ACCC_UseDevice : Clause <"use_device"> {
+ let flangClass = "AccObjectList";
+}
+
+// 2.12
+def ACCC_Read : Clause<"read"> {}
+
+// 2.5.13
+def ACCC_Reduction : Clause<"reduction"> {
+ let flangClass = "AccObjectListWithReduction";
+}
+
+// 2.5.5
+def ACCC_Self : Clause<"self"> {
+ let flangClass = "std::optional<ScalarLogicalExpr>";
+}
+
+// 2.9.5
+def ACCC_Seq : Clause<"seq"> {}
+
+// 2.9.4
+def ACCC_Vector : Clause<"vector"> {
+ let flangClass = "std::optional<ScalarIntExpr>";
+}
+
+// 2.5.10
+def ACCC_VectorLength : Clause<"vector_length"> {
+ let flangClass = "ScalarIntExpr";
+}
+
+// 2.16.2
+def ACCC_Wait : Clause<"wait"> {
+ let flangClass = "std::optional<AccWaitArgument>";
+}
+
+// 2.9.3
+def ACCC_Worker: Clause<"worker"> {
+ let flangClass = "std::optional<ScalarIntExpr>";
+}
+
+// 2.12
+def ACCC_Write : Clause<"write"> {}
+
+def ACCC_Unknown : Clause<"unknown"> {
+ let isDefault = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// Definition of OpenACC directives
+//===----------------------------------------------------------------------===//
+
+// 2.12
+def ACC_Atomic : Directive<"atomic"> {}
+
+// 2.6.5
+def ACC_Data : Directive<"data"> {
+ let allowedOnceClauses = [
+ VersionedClause<ACCC_If>
+ ];
+ let requiredClauses = [
+ VersionedClause<ACCC_Attach>,
+ VersionedClause<ACCC_Copy>,
+ VersionedClause<ACCC_Copyin>,
+ VersionedClause<ACCC_Copyout>,
+ VersionedClause<ACCC_Create>,
+ VersionedClause<ACCC_Default>,
+ VersionedClause<ACCC_DevicePtr>,
+ VersionedClause<ACCC_NoCreate>,
+ VersionedClause<ACCC_Present>
+ ];
+}
+
+// 2.13
+def ACC_Declare : Directive<"declare"> {
+ let allowedClauses = [
+ VersionedClause<ACCC_Copy>,
+ VersionedClause<ACCC_Copyin>,
+ VersionedClause<ACCC_Copyout>,
+ VersionedClause<ACCC_Create>,
+ VersionedClause<ACCC_Present>,
+ VersionedClause<ACCC_DevicePtr>,
+ VersionedClause<ACCC_DeviceResident>,
+ VersionedClause<ACCC_Link>
+ ];
+}
+
+// 2.5.2
+def ACC_Kernels : Directive<"kernels"> {
+ let allowedClauses = [
+ VersionedClause<ACCC_Attach>,
+ VersionedClause<ACCC_Copy>,
+ VersionedClause<ACCC_Copyin>,
+ VersionedClause<ACCC_Copyout>,
+ VersionedClause<ACCC_Create>,
+ VersionedClause<ACCC_DeviceType>,
+ VersionedClause<ACCC_NoCreate>,
+ VersionedClause<ACCC_Present>,
+ VersionedClause<ACCC_DevicePtr>
+ ];
+ let allowedOnceClauses = [
+ VersionedClause<ACCC_Async>,
+ VersionedClause<ACCC_Default>,
+ VersionedClause<ACCC_If>,
+ VersionedClause<ACCC_NumGangs>,
+ VersionedClause<ACCC_NumWorkers>,
+ VersionedClause<ACCC_Self>,
+ VersionedClause<ACCC_VectorLength>,
+ VersionedClause<ACCC_Wait>
+ ];
+}
+
+// 2.5.1
+def ACC_Parallel : Directive<"parallel"> {
+ let allowedClauses = [
+ VersionedClause<ACCC_Attach>,
+ VersionedClause<ACCC_Copy>,
+ VersionedClause<ACCC_Copyin>,
+ VersionedClause<ACCC_Copyout>,
+ VersionedClause<ACCC_Create>,
+ VersionedClause<ACCC_DevicePtr>,
+ VersionedClause<ACCC_DeviceType>,
+ VersionedClause<ACCC_NoCreate>,
+ VersionedClause<ACCC_Present>,
+ VersionedClause<ACCC_Private>,
+ VersionedClause<ACCC_FirstPrivate>,
+ VersionedClause<ACCC_Wait>
+ ];
+ let allowedOnceClauses = [
+ VersionedClause<ACCC_Async>,
+ VersionedClause<ACCC_Default>,
+ VersionedClause<ACCC_If>,
+ VersionedClause<ACCC_NumGangs>,
+ VersionedClause<ACCC_NumWorkers>,
+ VersionedClause<ACCC_Reduction>,
+ VersionedClause<ACCC_Self>,
+ VersionedClause<ACCC_VectorLength>
+ ];
+}
+
+// 2.5.3
+def ACC_Serial : Directive<"serial"> {
+ let allowedClauses = [
+ VersionedClause<ACCC_Attach>,
+ VersionedClause<ACCC_Copy>,
+ VersionedClause<ACCC_Copyin>,
+ VersionedClause<ACCC_Copyout>,
+ VersionedClause<ACCC_Create>,
+ VersionedClause<ACCC_DevicePtr>,
+ VersionedClause<ACCC_DeviceType>,
+ VersionedClause<ACCC_FirstPrivate>,
+ VersionedClause<ACCC_NoCreate>,
+ VersionedClause<ACCC_Present>,
+ VersionedClause<ACCC_Private>,
+ VersionedClause<ACCC_Wait>
+ ];
+ let allowedOnceClauses = [
+ VersionedClause<ACCC_Async>,
+ VersionedClause<ACCC_Default>,
+ VersionedClause<ACCC_If>,
+ VersionedClause<ACCC_Reduction>,
+ VersionedClause<ACCC_Self>
+ ];
+}
+
+// 2.9
+def ACC_Loop : Directive<"loop"> {
+ let allowedClauses = [
+ VersionedClause<ACCC_DeviceType>,
+ VersionedClause<ACCC_Private>
+ ];
+ let allowedOnceClauses = [
+ VersionedClause<ACCC_Collapse>,
+ VersionedClause<ACCC_Gang>,
+ VersionedClause<ACCC_Reduction>,
+ VersionedClause<ACCC_Tile>,
+ VersionedClause<ACCC_Vector>,
+ VersionedClause<ACCC_Worker>
+ ];
+ let allowedExclusiveClauses = [
+ VersionedClause<ACCC_Auto>,
+ VersionedClause<ACCC_Independent>,
+ VersionedClause<ACCC_Seq>
+ ];
+}
+
+// 2.10
+def ACC_Cache : Directive<"cache"> {}
+
+// 2.14.1
+def ACC_Init : Directive<"init"> {
+ let allowedOnceClauses = [
+ VersionedClause<ACCC_DeviceNum>,
+ VersionedClause<ACCC_DeviceType>,
+ VersionedClause<ACCC_If>
+ ];
+}
+
+// 2.15.1
+def ACC_Routine : Directive<"routine"> {
+ let allowedOnceClauses = [
+ VersionedClause<ACCC_Bind>,
+ VersionedClause<ACCC_DeviceType>,
+ VersionedClause<ACCC_NoHost>
+ ];
+ let requiredClauses = [
+ VersionedClause<ACCC_Gang>,
+ VersionedClause<ACCC_Seq>,
+ VersionedClause<ACCC_Vector>,
+ VersionedClause<ACCC_Worker>
+ ];
+}
+
+// 2.14.3
+def ACC_Set : Directive<"set"> {
+ let allowedOnceClauses = [
+ VersionedClause<ACCC_If>
+ ];
+ let requiredClauses = [
+ VersionedClause<ACCC_DefaultAsync>,
+ VersionedClause<ACCC_DeviceNum>,
+ VersionedClause<ACCC_DeviceType>
+ ];
+}
+
+// 2.14.2
+def ACC_Shutdown : Directive<"shutdown"> {
+ let allowedOnceClauses = [
+ VersionedClause<ACCC_DeviceNum>,
+ VersionedClause<ACCC_DeviceType>,
+ VersionedClause<ACCC_If>
+ ];
+}
+
+// 2.14.4
+def ACC_Update : Directive<"update"> {
+ let allowedClauses = [
+ VersionedClause<ACCC_DeviceType>,
+ VersionedClause<ACCC_Wait>
+ ];
+ let allowedOnceClauses = [
+ VersionedClause<ACCC_Async>,
+ VersionedClause<ACCC_If>,
+ VersionedClause<ACCC_IfPresent>
+ ];
+ let requiredClauses = [
+ VersionedClause<ACCC_Device>,
+ VersionedClause<ACCC_Host>,
+ VersionedClause<ACCC_Self>
+ ];
+}
+
+// 2.16.3
+def ACC_Wait : Directive<"wait"> {
+ let allowedOnceClauses = [
+ VersionedClause<ACCC_Async>,
+ VersionedClause<ACCC_If>
+ ];
+}
+
+// 2.14.6
+def ACC_EnterData : Directive<"enter data"> {
+ let allowedOnceClauses = [
+ VersionedClause<ACCC_Async>,
+ VersionedClause<ACCC_If>,
+ VersionedClause<ACCC_Wait>
+ ];
+ let requiredClauses = [
+ VersionedClause<ACCC_Attach>,
+ VersionedClause<ACCC_Create>,
+ VersionedClause<ACCC_Copyin>
+ ];
+}
+
+// 2.14.7
+def ACC_ExitData : Directive<"exit data"> {
+ let allowedClauses = [
+ VersionedClause<ACCC_Async>,
+ VersionedClause<ACCC_If>,
+ VersionedClause<ACCC_Wait>,
+ VersionedClause<ACCC_Finalize>
+ ];
+ let requiredClauses = [
+ VersionedClause<ACCC_Copyout>,
+ VersionedClause<ACCC_Delete>,
+ VersionedClause<ACCC_Detach>
+ ];
+}
+def ACC_HostData : Directive<"host_data"> {
+ let allowedClauses = [
+ VersionedClause<ACCC_If>,
+ VersionedClause<ACCC_IfPresent>
+ ];
+ let requiredClauses = [
+ VersionedClause<ACCC_UseDevice>
+ ];
+}
+
+// 2.11
+def ACC_KernelsLoop : Directive<"kernels loop"> {
+ let allowedClauses = [
+ VersionedClause<ACCC_Copy>,
+ VersionedClause<ACCC_Copyin>,
+ VersionedClause<ACCC_Copyout>,
+ VersionedClause<ACCC_Create>,
+ VersionedClause<ACCC_DeviceType>,
+ VersionedClause<ACCC_NoCreate>,
+ VersionedClause<ACCC_Present>,
+ VersionedClause<ACCC_Private>,
+ VersionedClause<ACCC_DevicePtr>,
+ VersionedClause<ACCC_Attach>
+ ];
+ let allowedOnceClauses = [
+ VersionedClause<ACCC_Async>,
+ VersionedClause<ACCC_Collapse>,
+ VersionedClause<ACCC_Default>,
+ VersionedClause<ACCC_Gang>,
+ VersionedClause<ACCC_If>,
+ VersionedClause<ACCC_Independent>,
+ VersionedClause<ACCC_NumGangs>,
+ VersionedClause<ACCC_NumWorkers>,
+ VersionedClause<ACCC_Reduction>,
+ VersionedClause<ACCC_Self>,
+ VersionedClause<ACCC_Tile>,
+ VersionedClause<ACCC_Vector>,
+ VersionedClause<ACCC_VectorLength>,
+ VersionedClause<ACCC_Wait>,
+ VersionedClause<ACCC_Worker>
+ ];
+ let allowedExclusiveClauses = [
+ VersionedClause<ACCC_Auto>,
+ VersionedClause<ACCC_Independent>,
+ VersionedClause<ACCC_Seq>
+ ];
+}
+
+// 2.11
+def ACC_ParallelLoop : Directive<"parallel loop"> {
+ let allowedClauses = [
+ VersionedClause<ACCC_Attach>,
+ VersionedClause<ACCC_Copy>,
+ VersionedClause<ACCC_Copyin>,
+ VersionedClause<ACCC_Copyout>,
+ VersionedClause<ACCC_Create>,
+ VersionedClause<ACCC_DevicePtr>,
+ VersionedClause<ACCC_DeviceType>,
+ VersionedClause<ACCC_FirstPrivate>,
+ VersionedClause<ACCC_NoCreate>,
+ VersionedClause<ACCC_Present>,
+ VersionedClause<ACCC_Private>,
+ VersionedClause<ACCC_Tile>,
+ VersionedClause<ACCC_Wait>
+ ];
+ let allowedOnceClauses = [
+ VersionedClause<ACCC_Async>,
+ VersionedClause<ACCC_Collapse>,
+ VersionedClause<ACCC_Default>,
+ VersionedClause<ACCC_Gang>,
+ VersionedClause<ACCC_If>,
+ VersionedClause<ACCC_NumGangs>,
+ VersionedClause<ACCC_NumWorkers>,
+ VersionedClause<ACCC_Reduction>,
+ VersionedClause<ACCC_Self>,
+ VersionedClause<ACCC_Vector>,
+ VersionedClause<ACCC_VectorLength>,
+ VersionedClause<ACCC_Worker>
+ ];
+ let allowedExclusiveClauses = [
+ VersionedClause<ACCC_Auto>,
+ VersionedClause<ACCC_Independent>,
+ VersionedClause<ACCC_Seq>
+ ];
+}
+
+// 2.11
+def ACC_SerialLoop : Directive<"serial loop"> {
+ let allowedClauses = [
+ VersionedClause<ACCC_Attach>,
+ VersionedClause<ACCC_Copy>,
+ VersionedClause<ACCC_Copyin>,
+ VersionedClause<ACCC_Copyout>,
+ VersionedClause<ACCC_Create>,
+ VersionedClause<ACCC_DevicePtr>,
+ VersionedClause<ACCC_DeviceType>,
+ VersionedClause<ACCC_FirstPrivate>,
+ VersionedClause<ACCC_NoCreate>,
+ VersionedClause<ACCC_Present>,
+ VersionedClause<ACCC_Private>,
+ VersionedClause<ACCC_Wait>
+ ];
+ let allowedOnceClauses = [
+ VersionedClause<ACCC_Async>,
+ VersionedClause<ACCC_Collapse>,
+ VersionedClause<ACCC_Default>,
+ VersionedClause<ACCC_Gang>,
+ VersionedClause<ACCC_If>,
+ VersionedClause<ACCC_Reduction>,
+ VersionedClause<ACCC_Self>,
+ VersionedClause<ACCC_Tile>,
+ VersionedClause<ACCC_Vector>,
+ VersionedClause<ACCC_Worker>
+ ];
+ let allowedExclusiveClauses = [
+ VersionedClause<ACCC_Auto>,
+ VersionedClause<ACCC_Independent>,
+ VersionedClause<ACCC_Seq>
+ ];
+}
+
+def ACC_Unknown : Directive<"unknown"> {
+ let isDefault = 1;
+}
\ No newline at end of file
diff --git a/llvm/include/llvm/Frontend/OpenACC/CMakeLists.txt b/llvm/include/llvm/Frontend/OpenACC/CMakeLists.txt
new file mode 100644
index 000000000000..82cc7cfaccc9
--- /dev/null
+++ b/llvm/include/llvm/Frontend/OpenACC/CMakeLists.txt
@@ -0,0 +1,4 @@
+set(LLVM_TARGET_DEFINITIONS ACC.td)
+tablegen(LLVM ACC.h.inc --gen-directive-decl)
+tablegen(LLVM ACC.cpp.inc --gen-directive-impl)
+add_public_tablegen_target(acc_gen)
diff --git a/llvm/lib/Frontend/CMakeLists.txt b/llvm/lib/Frontend/CMakeLists.txt
index 9730c8414edf..ea66917b8936 100644
--- a/llvm/lib/Frontend/CMakeLists.txt
+++ b/llvm/lib/Frontend/CMakeLists.txt
@@ -1 +1,2 @@
+add_subdirectory(OpenACC)
add_subdirectory(OpenMP)
diff --git a/llvm/lib/Frontend/OpenACC/CMakeLists.txt b/llvm/lib/Frontend/OpenACC/CMakeLists.txt
new file mode 100644
index 000000000000..021b680a33cf
--- /dev/null
+++ b/llvm/lib/Frontend/OpenACC/CMakeLists.txt
@@ -0,0 +1,15 @@
+set(LLVM_TARGET_DEFINITIONS ${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend/OpenACC/ACC.td)
+tablegen(LLVM ACC.cpp --gen-directive-impl)
+add_public_tablegen_target(acc_cpp)
+
+add_llvm_component_library(LLVMFrontendOpenACC
+ ACC.cpp # Generated by tablegen above
+
+ ADDITIONAL_HEADER_DIRS
+ ${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend
+ ${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend/OpenACC
+
+ DEPENDS
+ acc_gen
+ acc_cpp
+)
More information about the llvm-commits
mailing list