2013-03-22 06:34:35 +00:00
|
|
|
//===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
|
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// 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
|
2013-03-22 06:34:35 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// \file
|
2018-05-09 01:00:01 +00:00
|
|
|
/// This file implements parsing of all OpenMP directives and clauses.
|
2013-03-22 06:34:35 +00:00
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2014-05-06 10:08:46 +00:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2020-04-03 12:35:30 -07:00
|
|
|
#include "clang/AST/OpenMPClause.h"
|
2013-07-19 03:13:43 +00:00
|
|
|
#include "clang/AST/StmtOpenMP.h"
|
2024-11-18 07:19:33 -08:00
|
|
|
#include "clang/Basic/DiagnosticParse.h"
|
2019-12-20 11:04:57 -05:00
|
|
|
#include "clang/Basic/OpenMPKinds.h"
|
[OpenMP] `omp begin/end declare variant` - part 2, sema ("+CG")
This is the second part loosely extracted from D71179 and cleaned up.
This patch provides semantic analysis support for `omp begin/end declare
variant`, mostly as defined in OpenMP technical report 8 (TR8) [0].
The sema handling makes code generation obsolete as we generate "the
right" calls that can just be handled as usual. This handling also
applies to the existing, albeit problematic, `omp declare variant
support`. As a consequence a lot of unneeded code generation and
complexity is removed.
A major purpose of this patch is to provide proper `math.h`/`cmath`
support for OpenMP target offloading. See PR42061, PR42798, PR42799. The
current code was developed with this feature in mind, see [1].
The logic is as follows:
If we have seen a `#pragma omp begin declare variant match(<SELECTOR>)`
but not the corresponding `end declare variant`, and we find a function
definition we will:
1) Create a function declaration for the definition we were about to generate.
2) Create a function definition but with a mangled name (according to
`<SELECTOR>`).
3) Annotate the declaration with the `OMPDeclareVariantAttr`, the same
one used already for `omp declare variant`, using and the mangled
function definition as specialization for the context defined by
`<SELECTOR>`.
When a call is created we inspect it. If the target has an
`OMPDeclareVariantAttr` attribute we try to specialize the call. To this
end, all variants are checked, the best applicable one is picked and a
new call to the specialization is created. The new call is used instead
of the original one to the base function. To keep the AST printing and
tooling possible we utilize the PseudoObjectExpr. The original call is
the syntactic expression, the specialized call is the semantic
expression.
[0] https://www.openmp.org/wp-content/uploads/openmp-TR8.pdf
[1] https://reviews.llvm.org/D61399#change-496lQkg0mhRN
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim, aaron.ballman
Subscribers: bollu, guansong, openmp-commits, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75779
2020-02-25 14:04:06 -08:00
|
|
|
#include "clang/Basic/TargetInfo.h"
|
2020-03-23 17:30:38 -04:00
|
|
|
#include "clang/Basic/TokenKinds.h"
|
2013-05-13 04:18:18 +00:00
|
|
|
#include "clang/Parse/Parser.h"
|
2017-03-23 15:11:07 +00:00
|
|
|
#include "clang/Parse/RAIIObjectsForParser.h"
|
2023-05-04 13:06:53 -04:00
|
|
|
#include "clang/Sema/EnterExpressionEvaluationContext.h"
|
2013-05-13 04:18:18 +00:00
|
|
|
#include "clang/Sema/Scope.h"
|
[clang] Introduce target-specific `Sema` components (#93179)
This patch introduces `SemaAMDGPU`, `SemaARM`, `SemaBPF`, `SemaHexagon`,
`SemaLoongArch`, `SemaMIPS`, `SemaNVPTX`, `SemaPPC`, `SemaSystemZ`,
`SemaWasm`. This continues previous efforts to split Sema up. Additional
context can be found in #84184 and #92682.
I decided to bundle target-specific components together because of their
low impact on `Sema`. That said, their impact on `SemaChecking.cpp` is
far from low, and I consider it a success.
Somewhat accidentally, I also moved Wasm- and AMDGPU-specific function
from `SemaDeclAttr.cpp`, because they were exposed in `Sema`. That went
well, and I consider it a success, too. I'd like to move the rest of
static target-specific functions out of `SemaDeclAttr.cpp` like we're
doing with built-ins in `SemaChecking.cpp` .
2024-05-30 19:59:59 +04:00
|
|
|
#include "clang/Sema/SemaAMDGPU.h"
|
2024-05-17 20:55:37 +04:00
|
|
|
#include "clang/Sema/SemaCodeCompletion.h"
|
2024-04-16 16:36:53 +04:00
|
|
|
#include "clang/Sema/SemaOpenMP.h"
|
2024-06-26 08:11:09 -05:00
|
|
|
#include "llvm/ADT/SmallBitVector.h"
|
2020-11-23 11:48:59 -06:00
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
2021-11-04 08:48:19 -05:00
|
|
|
#include "llvm/Frontend/OpenMP/OMPAssume.h"
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
#include "llvm/Frontend/OpenMP/OMPContext.h"
|
2023-01-14 11:07:21 -08:00
|
|
|
#include <optional>
|
2015-07-21 13:44:28 +00:00
|
|
|
|
2013-03-22 06:34:35 +00:00
|
|
|
using namespace clang;
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-04 22:00:49 -06:00
|
|
|
using namespace llvm::omp;
|
2013-03-22 06:34:35 +00:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// OpenMP declarative directives.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2016-02-13 06:53:38 +00:00
|
|
|
namespace {
|
|
|
|
enum OpenMPDirectiveKindEx {
|
[openmp] Base of tablegen generated OpenMP common declaration
Summary:
As discussed previously when landing patch for OpenMP in Flang, the idea is
to share common part of the OpenMP declaration between the different Frontend.
While doing this it was thought that moving to tablegen instead of Macros will also
give a cleaner and more powerful way of generating these declaration.
This first part of a future series of patches is setting up the base .td file for
DirectiveLanguage as well as the OpenMP version of it. The base file is meant to
be used by other directive language such as OpenACC.
In this first patch, the Directive and Clause enums are generated with tablegen
instead of the macros on OMPConstants.h. The next pacth will extend this
to other enum and move the Flang frontend to use it.
Reviewers: jdoerfert, DavidTruby, fghanim, ABataev, jdenny, hfinkel, jhuber6, kiranchandramohan, kiranktp
Reviewed By: jdoerfert, jdenny
Subscribers: arphaman, martong, cfe-commits, mgorny, yaxunl, hiraditya, guansong, jfb, sstefan1, aaron.ballman, llvm-commits
Tags: #llvm, #openmp, #clang
Differential Revision: https://reviews.llvm.org/D81736
2020-06-23 09:29:50 -04:00
|
|
|
OMPD_cancellation = llvm::omp::Directive_enumSize + 1,
|
2016-02-13 06:53:38 +00:00
|
|
|
OMPD_data,
|
2016-03-03 05:21:39 +00:00
|
|
|
OMPD_declare,
|
2016-04-06 11:38:59 +00:00
|
|
|
OMPD_end,
|
|
|
|
OMPD_end_declare,
|
2016-02-13 06:53:38 +00:00
|
|
|
OMPD_enter,
|
|
|
|
OMPD_exit,
|
|
|
|
OMPD_point,
|
2016-03-03 05:21:39 +00:00
|
|
|
OMPD_reduction,
|
2016-02-13 06:53:38 +00:00
|
|
|
OMPD_target_enter,
|
2016-05-26 17:30:50 +00:00
|
|
|
OMPD_target_exit,
|
|
|
|
OMPD_update,
|
2016-11-30 23:51:03 +00:00
|
|
|
OMPD_distribute_parallel,
|
2016-12-29 22:16:30 +00:00
|
|
|
OMPD_teams_distribute_parallel,
|
2019-02-01 20:25:04 +00:00
|
|
|
OMPD_target_teams_distribute_parallel,
|
|
|
|
OMPD_mapper,
|
2019-09-13 20:18:17 +00:00
|
|
|
OMPD_variant,
|
2020-02-20 19:50:47 -06:00
|
|
|
OMPD_begin,
|
|
|
|
OMPD_begin_declare,
|
2016-02-13 06:53:38 +00:00
|
|
|
};
|
2016-05-09 14:59:13 +00:00
|
|
|
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-04 22:00:49 -06:00
|
|
|
// Helper to unify the enum class OpenMPDirectiveKind with its extension
|
|
|
|
// the OpenMPDirectiveKindEx enum which allows to use them together as if they
|
|
|
|
// are unsigned values.
|
|
|
|
struct OpenMPDirectiveKindExWrapper {
|
|
|
|
OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {}
|
|
|
|
OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {}
|
2020-12-17 10:41:35 +00:00
|
|
|
bool operator==(OpenMPDirectiveKindExWrapper V) const {
|
|
|
|
return Value == V.Value;
|
|
|
|
}
|
|
|
|
bool operator!=(OpenMPDirectiveKindExWrapper V) const {
|
|
|
|
return Value != V.Value;
|
|
|
|
}
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-04 22:00:49 -06:00
|
|
|
bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); }
|
|
|
|
bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); }
|
|
|
|
bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); }
|
|
|
|
operator unsigned() const { return Value; }
|
|
|
|
operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value); }
|
|
|
|
unsigned Value;
|
|
|
|
};
|
|
|
|
|
2019-03-07 17:54:44 +00:00
|
|
|
class DeclDirectiveListParserHelper final {
|
2016-05-09 14:59:13 +00:00
|
|
|
SmallVector<Expr *, 4> Identifiers;
|
|
|
|
Parser *P;
|
2019-03-07 17:54:44 +00:00
|
|
|
OpenMPDirectiveKind Kind;
|
2016-05-09 14:59:13 +00:00
|
|
|
|
|
|
|
public:
|
2019-03-07 17:54:44 +00:00
|
|
|
DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
|
|
|
|
: P(P), Kind(Kind) {}
|
2016-05-09 14:59:13 +00:00
|
|
|
void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
|
2024-04-16 16:36:53 +04:00
|
|
|
ExprResult Res = P->getActions().OpenMP().ActOnOpenMPIdExpression(
|
2019-03-07 17:54:44 +00:00
|
|
|
P->getCurScope(), SS, NameInfo, Kind);
|
2016-05-09 14:59:13 +00:00
|
|
|
if (Res.isUsable())
|
|
|
|
Identifiers.push_back(Res.get());
|
|
|
|
}
|
|
|
|
llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
|
|
|
|
};
|
2016-02-13 06:53:38 +00:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
// Map token string to extended OMP token kind that are
|
|
|
|
// OpenMPDirectiveKind + OpenMPDirectiveKindEx.
|
|
|
|
static unsigned getOpenMPDirectiveKindEx(StringRef S) {
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-04 22:00:49 -06:00
|
|
|
OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S);
|
2016-02-13 06:53:38 +00:00
|
|
|
if (DKind != OMPD_unknown)
|
|
|
|
return DKind;
|
|
|
|
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-04 22:00:49 -06:00
|
|
|
return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S)
|
2016-02-13 06:53:38 +00:00
|
|
|
.Case("cancellation", OMPD_cancellation)
|
|
|
|
.Case("data", OMPD_data)
|
2016-03-03 05:21:39 +00:00
|
|
|
.Case("declare", OMPD_declare)
|
2016-04-06 11:38:59 +00:00
|
|
|
.Case("end", OMPD_end)
|
2016-02-13 06:53:38 +00:00
|
|
|
.Case("enter", OMPD_enter)
|
|
|
|
.Case("exit", OMPD_exit)
|
|
|
|
.Case("point", OMPD_point)
|
2016-03-03 05:21:39 +00:00
|
|
|
.Case("reduction", OMPD_reduction)
|
2016-05-26 17:30:50 +00:00
|
|
|
.Case("update", OMPD_update)
|
2019-02-01 20:25:04 +00:00
|
|
|
.Case("mapper", OMPD_mapper)
|
2019-09-13 20:18:17 +00:00
|
|
|
.Case("variant", OMPD_variant)
|
2020-02-20 19:50:47 -06:00
|
|
|
.Case("begin", OMPD_begin)
|
2016-02-13 06:53:38 +00:00
|
|
|
.Default(OMPD_unknown);
|
|
|
|
}
|
|
|
|
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-04 22:00:49 -06:00
|
|
|
static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
|
2014-09-18 05:12:34 +00:00
|
|
|
// Array of foldings: F[i][0] F[i][1] ===> F[i][2].
|
|
|
|
// E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
|
|
|
|
// TODO: add other combined directives in topological order.
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-04 22:00:49 -06:00
|
|
|
static const OpenMPDirectiveKindExWrapper F[][3] = {
|
2020-02-20 19:50:47 -06:00
|
|
|
{OMPD_begin, OMPD_declare, OMPD_begin_declare},
|
2020-11-23 11:48:59 -06:00
|
|
|
{OMPD_begin, OMPD_assumes, OMPD_begin_assumes},
|
2020-02-20 19:50:47 -06:00
|
|
|
{OMPD_end, OMPD_declare, OMPD_end_declare},
|
2020-11-23 11:48:59 -06:00
|
|
|
{OMPD_end, OMPD_assumes, OMPD_end_assumes},
|
2018-04-23 19:53:05 +00:00
|
|
|
{OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
|
|
|
|
{OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
|
2019-02-01 20:25:04 +00:00
|
|
|
{OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
|
2018-04-23 19:53:05 +00:00
|
|
|
{OMPD_declare, OMPD_simd, OMPD_declare_simd},
|
|
|
|
{OMPD_declare, OMPD_target, OMPD_declare_target},
|
2019-09-13 20:18:17 +00:00
|
|
|
{OMPD_declare, OMPD_variant, OMPD_declare_variant},
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
{OMPD_begin_declare, OMPD_target, OMPD_begin_declare_target},
|
2020-02-20 19:50:47 -06:00
|
|
|
{OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant},
|
|
|
|
{OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant},
|
2018-04-23 19:53:05 +00:00
|
|
|
{OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
|
|
|
|
{OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
|
|
|
|
{OMPD_distribute_parallel_for, OMPD_simd,
|
|
|
|
OMPD_distribute_parallel_for_simd},
|
|
|
|
{OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
|
|
|
|
{OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
|
|
|
|
{OMPD_target, OMPD_data, OMPD_target_data},
|
|
|
|
{OMPD_target, OMPD_enter, OMPD_target_enter},
|
|
|
|
{OMPD_target, OMPD_exit, OMPD_target_exit},
|
|
|
|
{OMPD_target, OMPD_update, OMPD_target_update},
|
|
|
|
{OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
|
|
|
|
{OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
|
|
|
|
{OMPD_for, OMPD_simd, OMPD_for_simd},
|
|
|
|
{OMPD_parallel, OMPD_for, OMPD_parallel_for},
|
|
|
|
{OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
|
2022-03-22 10:55:21 -07:00
|
|
|
{OMPD_parallel, OMPD_loop, OMPD_parallel_loop},
|
2018-04-23 19:53:05 +00:00
|
|
|
{OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
|
|
|
|
{OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
|
|
|
|
{OMPD_target, OMPD_parallel, OMPD_target_parallel},
|
|
|
|
{OMPD_target, OMPD_simd, OMPD_target_simd},
|
2022-03-23 15:37:06 -07:00
|
|
|
{OMPD_target_parallel, OMPD_loop, OMPD_target_parallel_loop},
|
2018-04-23 19:53:05 +00:00
|
|
|
{OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
|
|
|
|
{OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
|
|
|
|
{OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
|
|
|
|
{OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
|
|
|
|
{OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
|
|
|
|
{OMPD_teams_distribute_parallel, OMPD_for,
|
|
|
|
OMPD_teams_distribute_parallel_for},
|
|
|
|
{OMPD_teams_distribute_parallel_for, OMPD_simd,
|
|
|
|
OMPD_teams_distribute_parallel_for_simd},
|
2022-03-15 08:35:59 -07:00
|
|
|
{OMPD_teams, OMPD_loop, OMPD_teams_loop},
|
2018-04-23 19:53:05 +00:00
|
|
|
{OMPD_target, OMPD_teams, OMPD_target_teams},
|
|
|
|
{OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
|
2022-03-18 11:02:02 -07:00
|
|
|
{OMPD_target_teams, OMPD_loop, OMPD_target_teams_loop},
|
2018-04-23 19:53:05 +00:00
|
|
|
{OMPD_target_teams_distribute, OMPD_parallel,
|
|
|
|
OMPD_target_teams_distribute_parallel},
|
|
|
|
{OMPD_target_teams_distribute, OMPD_simd,
|
|
|
|
OMPD_target_teams_distribute_simd},
|
|
|
|
{OMPD_target_teams_distribute_parallel, OMPD_for,
|
|
|
|
OMPD_target_teams_distribute_parallel_for},
|
|
|
|
{OMPD_target_teams_distribute_parallel_for, OMPD_simd,
|
2019-10-10 20:13:02 +00:00
|
|
|
OMPD_target_teams_distribute_parallel_for_simd},
|
2019-10-14 17:17:41 +00:00
|
|
|
{OMPD_master, OMPD_taskloop, OMPD_master_taskloop},
|
2022-06-24 08:42:21 -07:00
|
|
|
{OMPD_masked, OMPD_taskloop, OMPD_masked_taskloop},
|
2019-10-18 16:47:35 +00:00
|
|
|
{OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},
|
2022-06-28 14:35:43 -07:00
|
|
|
{OMPD_masked_taskloop, OMPD_simd, OMPD_masked_taskloop_simd},
|
2019-10-14 17:17:41 +00:00
|
|
|
{OMPD_parallel, OMPD_master, OMPD_parallel_master},
|
2022-06-16 16:32:30 -07:00
|
|
|
{OMPD_parallel, OMPD_masked, OMPD_parallel_masked},
|
2019-10-25 10:27:13 -04:00
|
|
|
{OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop},
|
2022-06-30 10:59:33 -07:00
|
|
|
{OMPD_parallel_masked, OMPD_taskloop, OMPD_parallel_masked_taskloop},
|
2019-10-25 10:27:13 -04:00
|
|
|
{OMPD_parallel_master_taskloop, OMPD_simd,
|
2022-06-30 17:08:17 -07:00
|
|
|
OMPD_parallel_master_taskloop_simd},
|
|
|
|
{OMPD_parallel_masked_taskloop, OMPD_simd,
|
|
|
|
OMPD_parallel_masked_taskloop_simd}};
|
2016-03-03 05:21:39 +00:00
|
|
|
enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
|
2018-04-23 19:53:05 +00:00
|
|
|
Token Tok = P.getCurToken();
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-04 22:00:49 -06:00
|
|
|
OpenMPDirectiveKindExWrapper DKind =
|
2014-07-07 13:01:15 +00:00
|
|
|
Tok.isAnnotation()
|
2016-02-13 06:53:38 +00:00
|
|
|
? static_cast<unsigned>(OMPD_unknown)
|
|
|
|
: getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
|
|
|
|
if (DKind == OMPD_unknown)
|
|
|
|
return OMPD_unknown;
|
2015-07-21 13:44:28 +00:00
|
|
|
|
2022-08-20 21:18:32 -07:00
|
|
|
for (const auto &I : F) {
|
|
|
|
if (DKind != I[0])
|
2016-02-13 06:53:38 +00:00
|
|
|
continue;
|
2015-07-21 13:44:28 +00:00
|
|
|
|
2016-02-13 06:53:38 +00:00
|
|
|
Tok = P.getPreprocessor().LookAhead(0);
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-04 22:00:49 -06:00
|
|
|
OpenMPDirectiveKindExWrapper SDKind =
|
2016-02-13 06:53:38 +00:00
|
|
|
Tok.isAnnotation()
|
|
|
|
? static_cast<unsigned>(OMPD_unknown)
|
|
|
|
: getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
|
|
|
|
if (SDKind == OMPD_unknown)
|
|
|
|
continue;
|
2015-07-21 13:44:28 +00:00
|
|
|
|
2022-08-20 21:18:32 -07:00
|
|
|
if (SDKind == I[1]) {
|
2016-02-13 06:53:38 +00:00
|
|
|
P.ConsumeToken();
|
2022-08-20 21:18:32 -07:00
|
|
|
DKind = I[2];
|
2014-07-07 13:01:15 +00:00
|
|
|
}
|
|
|
|
}
|
2020-06-25 09:17:15 -04:00
|
|
|
return unsigned(DKind) < llvm::omp::Directive_enumSize
|
|
|
|
? static_cast<OpenMPDirectiveKind>(DKind)
|
|
|
|
: OMPD_unknown;
|
2016-03-03 05:21:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static DeclarationName parseOpenMPReductionId(Parser &P) {
|
2016-03-17 10:19:46 +00:00
|
|
|
Token Tok = P.getCurToken();
|
2016-03-03 05:21:39 +00:00
|
|
|
Sema &Actions = P.getActions();
|
|
|
|
OverloadedOperatorKind OOK = OO_None;
|
2016-03-17 10:19:46 +00:00
|
|
|
// Allow to use 'operator' keyword for C++ operators
|
|
|
|
bool WithOperator = false;
|
|
|
|
if (Tok.is(tok::kw_operator)) {
|
|
|
|
P.ConsumeToken();
|
|
|
|
Tok = P.getCurToken();
|
|
|
|
WithOperator = true;
|
|
|
|
}
|
2016-03-03 05:21:39 +00:00
|
|
|
switch (Tok.getKind()) {
|
|
|
|
case tok::plus: // '+'
|
|
|
|
OOK = OO_Plus;
|
|
|
|
break;
|
|
|
|
case tok::minus: // '-'
|
|
|
|
OOK = OO_Minus;
|
|
|
|
break;
|
|
|
|
case tok::star: // '*'
|
|
|
|
OOK = OO_Star;
|
|
|
|
break;
|
|
|
|
case tok::amp: // '&'
|
|
|
|
OOK = OO_Amp;
|
|
|
|
break;
|
|
|
|
case tok::pipe: // '|'
|
|
|
|
OOK = OO_Pipe;
|
|
|
|
break;
|
|
|
|
case tok::caret: // '^'
|
|
|
|
OOK = OO_Caret;
|
|
|
|
break;
|
|
|
|
case tok::ampamp: // '&&'
|
|
|
|
OOK = OO_AmpAmp;
|
|
|
|
break;
|
|
|
|
case tok::pipepipe: // '||'
|
|
|
|
OOK = OO_PipePipe;
|
|
|
|
break;
|
|
|
|
case tok::identifier: // identifier
|
2016-03-17 10:19:46 +00:00
|
|
|
if (!WithOperator)
|
|
|
|
break;
|
2022-08-08 09:12:46 -07:00
|
|
|
[[fallthrough]];
|
2016-03-03 05:21:39 +00:00
|
|
|
default:
|
|
|
|
P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
|
|
|
|
P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
Parser::StopBeforeMatch);
|
|
|
|
return DeclarationName();
|
|
|
|
}
|
|
|
|
P.ConsumeToken();
|
|
|
|
auto &DeclNames = Actions.getASTContext().DeclarationNames;
|
|
|
|
return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
|
|
|
|
: DeclNames.getCXXOperatorName(OOK);
|
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Parse 'omp declare reduction' construct.
|
2016-03-03 05:21:39 +00:00
|
|
|
///
|
|
|
|
/// declare-reduction-directive:
|
|
|
|
/// annot_pragma_openmp 'declare' 'reduction'
|
|
|
|
/// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
|
|
|
|
/// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
/// <reduction_id> is either a base language identifier or one of the following
|
|
|
|
/// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
|
|
|
|
///
|
|
|
|
Parser::DeclGroupPtrTy
|
|
|
|
Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
|
|
|
|
// Parse '('.
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-04 22:00:49 -06:00
|
|
|
if (T.expectAndConsume(
|
|
|
|
diag::err_expected_lparen_after,
|
|
|
|
getOpenMPDirectiveName(OMPD_declare_reduction).data())) {
|
2016-03-03 05:21:39 +00:00
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
}
|
|
|
|
|
|
|
|
DeclarationName Name = parseOpenMPReductionId(*this);
|
|
|
|
if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
|
|
|
|
// Consume ':'.
|
|
|
|
bool IsCorrect = !ExpectAndConsume(tok::colon);
|
|
|
|
|
|
|
|
if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
|
2016-03-17 10:19:46 +00:00
|
|
|
IsCorrect = IsCorrect && !Name.isEmpty();
|
|
|
|
|
2016-03-03 05:21:39 +00:00
|
|
|
if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_expected_type);
|
|
|
|
IsCorrect = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
|
|
|
|
SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
|
|
|
|
// Parse list of types until ':' token.
|
|
|
|
do {
|
|
|
|
ColonProtectionRAIIObject ColonRAII(*this);
|
|
|
|
SourceRange Range;
|
2020-11-10 23:40:12 -06:00
|
|
|
TypeResult TR = ParseTypeName(&Range, DeclaratorContext::Prototype, AS);
|
2016-03-03 05:21:39 +00:00
|
|
|
if (TR.isUsable()) {
|
2024-04-16 16:36:53 +04:00
|
|
|
QualType ReductionType = Actions.OpenMP().ActOnOpenMPDeclareReductionType(
|
|
|
|
Range.getBegin(), TR);
|
2016-03-03 05:21:39 +00:00
|
|
|
if (!ReductionType.isNull()) {
|
|
|
|
ReductionTypes.push_back(
|
|
|
|
std::make_pair(ReductionType, Range.getBegin()));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Consume ','.
|
|
|
|
if (ExpectAndConsume(tok::comma)) {
|
|
|
|
IsCorrect = false;
|
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_expected_type);
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (Tok.isNot(tok::annot_pragma_openmp_end));
|
|
|
|
|
|
|
|
if (ReductionTypes.empty()) {
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
|
|
|
|
// Consume ':'.
|
|
|
|
if (ExpectAndConsume(tok::colon))
|
|
|
|
IsCorrect = false;
|
|
|
|
|
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_expected_expression);
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
}
|
|
|
|
|
2024-04-16 16:36:53 +04:00
|
|
|
DeclGroupPtrTy DRD =
|
|
|
|
Actions.OpenMP().ActOnOpenMPDeclareReductionDirectiveStart(
|
|
|
|
getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes,
|
|
|
|
AS);
|
2016-03-03 05:21:39 +00:00
|
|
|
|
|
|
|
// Parse <combiner> expression and then parse initializer if any for each
|
|
|
|
// correct type.
|
|
|
|
unsigned I = 0, E = ReductionTypes.size();
|
2018-04-23 19:53:05 +00:00
|
|
|
for (Decl *D : DRD.get()) {
|
2016-03-03 05:21:39 +00:00
|
|
|
TentativeParsingAction TPA(*this);
|
|
|
|
ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
|
2017-08-10 15:43:06 +00:00
|
|
|
Scope::CompoundStmtScope |
|
2016-03-03 05:21:39 +00:00
|
|
|
Scope::OpenMPDirectiveScope);
|
|
|
|
// Parse <combiner> expression.
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
|
2020-01-08 09:39:44 -05:00
|
|
|
ExprResult CombinerResult = Actions.ActOnFinishFullExpr(
|
|
|
|
ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false);
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().ActOnOpenMPDeclareReductionCombinerEnd(
|
|
|
|
D, CombinerResult.get());
|
2016-03-03 05:21:39 +00:00
|
|
|
|
|
|
|
if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
TPA.Commit();
|
|
|
|
IsCorrect = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
|
|
|
|
ExprResult InitializerResult;
|
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
// Parse <initializer> expression.
|
|
|
|
if (Tok.is(tok::identifier) &&
|
2018-04-23 19:53:05 +00:00
|
|
|
Tok.getIdentifierInfo()->isStr("initializer")) {
|
2016-03-03 05:21:39 +00:00
|
|
|
ConsumeToken();
|
2018-04-23 19:53:05 +00:00
|
|
|
} else {
|
2016-03-03 05:21:39 +00:00
|
|
|
Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
|
|
|
|
TPA.Commit();
|
|
|
|
IsCorrect = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Parse '('.
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren,
|
|
|
|
tok::annot_pragma_openmp_end);
|
|
|
|
IsCorrect =
|
|
|
|
!T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
|
|
|
|
IsCorrect;
|
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
|
2017-08-10 15:43:06 +00:00
|
|
|
Scope::CompoundStmtScope |
|
2016-03-03 05:21:39 +00:00
|
|
|
Scope::OpenMPDirectiveScope);
|
|
|
|
// Parse expression.
|
2017-09-06 14:49:58 +00:00
|
|
|
VarDecl *OmpPrivParm =
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().ActOnOpenMPDeclareReductionInitializerStart(
|
|
|
|
getCurScope(), D);
|
2017-09-06 14:49:58 +00:00
|
|
|
// Check if initializer is omp_priv <init_expr> or something else.
|
|
|
|
if (Tok.is(tok::identifier) &&
|
|
|
|
Tok.getIdentifierInfo()->isStr("omp_priv")) {
|
2019-11-12 11:19:26 -05:00
|
|
|
ConsumeToken();
|
|
|
|
ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
|
2017-09-06 14:49:58 +00:00
|
|
|
} else {
|
|
|
|
InitializerResult = Actions.ActOnFinishFullExpr(
|
|
|
|
ParseAssignmentExpression().get(), D->getLocation(),
|
2019-01-04 16:58:14 +00:00
|
|
|
/*DiscardedValue*/ false);
|
2017-09-06 14:49:58 +00:00
|
|
|
}
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().ActOnOpenMPDeclareReductionInitializerEnd(
|
2017-09-06 14:49:58 +00:00
|
|
|
D, InitializerResult.get(), OmpPrivParm);
|
2016-03-03 05:21:39 +00:00
|
|
|
if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
TPA.Commit();
|
|
|
|
IsCorrect = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
IsCorrect =
|
|
|
|
!T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
++I;
|
|
|
|
// Revert parsing if not the last type, otherwise accept it, we're done with
|
|
|
|
// parsing.
|
|
|
|
if (I != E)
|
|
|
|
TPA.Revert();
|
|
|
|
else
|
|
|
|
TPA.Commit();
|
|
|
|
}
|
2024-04-16 16:36:53 +04:00
|
|
|
return Actions.OpenMP().ActOnOpenMPDeclareReductionDirectiveEnd(
|
|
|
|
getCurScope(), DRD, IsCorrect);
|
2014-07-07 13:01:15 +00:00
|
|
|
}
|
|
|
|
|
2017-09-06 14:49:58 +00:00
|
|
|
void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
|
|
|
|
// Parse declarator '=' initializer.
|
|
|
|
// If a '==' or '+=' is found, suggest a fixit to '='.
|
|
|
|
if (isTokenEqualOrEqualTypo()) {
|
|
|
|
ConsumeToken();
|
|
|
|
|
|
|
|
if (Tok.is(tok::code_completion)) {
|
2021-03-12 12:00:54 +01:00
|
|
|
cutOffParsing();
|
2024-05-17 20:55:37 +04:00
|
|
|
Actions.CodeCompletion().CodeCompleteInitializer(getCurScope(),
|
|
|
|
OmpPrivParm);
|
2017-09-06 14:49:58 +00:00
|
|
|
Actions.FinalizeDeclaration(OmpPrivParm);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-11-12 11:19:26 -05:00
|
|
|
PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm);
|
2020-01-02 15:49:08 -05:00
|
|
|
ExprResult Init = ParseInitializer();
|
2017-09-06 14:49:58 +00:00
|
|
|
|
|
|
|
if (Init.isInvalid()) {
|
|
|
|
SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
|
|
|
|
Actions.ActOnInitializerError(OmpPrivParm);
|
|
|
|
} else {
|
|
|
|
Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
|
|
|
|
/*DirectInit=*/false);
|
|
|
|
}
|
|
|
|
} else if (Tok.is(tok::l_paren)) {
|
|
|
|
// Parse C++ direct initializer: '(' expression-list ')'
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren);
|
|
|
|
T.consumeOpen();
|
|
|
|
|
|
|
|
ExprVector Exprs;
|
|
|
|
|
2018-08-30 13:08:03 +00:00
|
|
|
SourceLocation LParLoc = T.getOpenLocation();
|
2019-02-26 11:01:50 +00:00
|
|
|
auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
|
2024-05-17 20:55:37 +04:00
|
|
|
QualType PreferredType =
|
|
|
|
Actions.CodeCompletion().ProduceConstructorSignatureHelp(
|
|
|
|
OmpPrivParm->getType()->getCanonicalTypeInternal(),
|
|
|
|
OmpPrivParm->getLocation(), Exprs, LParLoc, /*Braced=*/false);
|
2019-02-26 11:01:50 +00:00
|
|
|
CalledSignatureHelp = true;
|
|
|
|
return PreferredType;
|
|
|
|
};
|
2022-11-17 15:49:30 +01:00
|
|
|
if (ParseExpressionList(Exprs, [&] {
|
2019-02-26 11:01:50 +00:00
|
|
|
PreferredType.enterFunctionArgument(Tok.getLocation(),
|
|
|
|
RunSignatureHelp);
|
|
|
|
})) {
|
|
|
|
if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
|
|
|
|
RunSignatureHelp();
|
2017-09-06 14:49:58 +00:00
|
|
|
Actions.ActOnInitializerError(OmpPrivParm);
|
|
|
|
SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
|
|
|
|
} else {
|
|
|
|
// Match the ')'.
|
2018-07-06 19:35:42 +00:00
|
|
|
SourceLocation RLoc = Tok.getLocation();
|
|
|
|
if (!T.consumeClose())
|
|
|
|
RLoc = T.getCloseLocation();
|
2017-09-06 14:49:58 +00:00
|
|
|
|
2018-07-06 19:35:42 +00:00
|
|
|
ExprResult Initializer =
|
|
|
|
Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
|
2017-09-06 14:49:58 +00:00
|
|
|
Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
|
|
|
|
/*DirectInit=*/true);
|
|
|
|
}
|
|
|
|
} else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
|
|
|
|
// Parse C++0x braced-init-list.
|
|
|
|
Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
|
|
|
|
|
|
|
|
ExprResult Init(ParseBraceInitializer());
|
|
|
|
|
|
|
|
if (Init.isInvalid()) {
|
|
|
|
Actions.ActOnInitializerError(OmpPrivParm);
|
|
|
|
} else {
|
|
|
|
Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
|
|
|
|
/*DirectInit=*/true);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Actions.ActOnUninitializedDecl(OmpPrivParm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-01 20:25:04 +00:00
|
|
|
/// Parses 'omp declare mapper' directive.
|
|
|
|
///
|
|
|
|
/// declare-mapper-directive:
|
|
|
|
/// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':']
|
|
|
|
/// <type> <var> ')' [<clause>[[,] <clause>] ... ]
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
/// <mapper-identifier> and <var> are base language identifiers.
|
|
|
|
///
|
|
|
|
Parser::DeclGroupPtrTy
|
|
|
|
Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
|
|
|
|
bool IsCorrect = true;
|
|
|
|
// Parse '('
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-04 22:00:49 -06:00
|
|
|
getOpenMPDirectiveName(OMPD_declare_mapper).data())) {
|
2019-02-01 20:25:04 +00:00
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse <mapper-identifier>
|
|
|
|
auto &DeclNames = Actions.getASTContext().DeclarationNames;
|
|
|
|
DeclarationName MapperId;
|
|
|
|
if (PP.LookAhead(0).is(tok::colon)) {
|
|
|
|
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
|
|
|
|
IsCorrect = false;
|
|
|
|
} else {
|
|
|
|
MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());
|
|
|
|
}
|
|
|
|
ConsumeToken();
|
|
|
|
// Consume ':'.
|
|
|
|
ExpectAndConsume(tok::colon);
|
|
|
|
} else {
|
|
|
|
// If no mapper identifier is provided, its name is "default" by default
|
|
|
|
MapperId =
|
|
|
|
DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
|
|
|
|
// Parse <type> <var>
|
|
|
|
DeclarationName VName;
|
|
|
|
QualType MapperType;
|
|
|
|
SourceRange Range;
|
|
|
|
TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS);
|
|
|
|
if (ParsedType.isUsable())
|
2024-04-16 16:36:53 +04:00
|
|
|
MapperType = Actions.OpenMP().ActOnOpenMPDeclareMapperType(Range.getBegin(),
|
|
|
|
ParsedType);
|
2019-02-01 20:25:04 +00:00
|
|
|
if (MapperType.isNull())
|
|
|
|
IsCorrect = false;
|
|
|
|
if (!IsCorrect) {
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Consume ')'.
|
|
|
|
IsCorrect &= !T.consumeClose();
|
|
|
|
if (!IsCorrect) {
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enter scope.
|
|
|
|
DeclarationNameInfo DirName;
|
|
|
|
SourceLocation Loc = Tok.getLocation();
|
|
|
|
unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
|
|
|
|
Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
|
|
|
|
ParseScope OMPDirectiveScope(this, ScopeFlags);
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().StartOpenMPDSABlock(OMPD_declare_mapper, DirName,
|
|
|
|
getCurScope(), Loc);
|
2019-02-01 20:25:04 +00:00
|
|
|
|
|
|
|
// Add the mapper variable declaration.
|
2024-04-16 16:36:53 +04:00
|
|
|
ExprResult MapperVarRef =
|
|
|
|
Actions.OpenMP().ActOnOpenMPDeclareMapperDirectiveVarDecl(
|
|
|
|
getCurScope(), MapperType, Range.getBegin(), VName);
|
2019-02-01 20:25:04 +00:00
|
|
|
|
|
|
|
// Parse map clauses.
|
|
|
|
SmallVector<OMPClause *, 6> Clauses;
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
OpenMPClauseKind CKind = Tok.isAnnotation()
|
|
|
|
? OMPC_unknown
|
|
|
|
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().StartOpenMPClause(CKind);
|
2019-02-01 20:25:04 +00:00
|
|
|
OMPClause *Clause =
|
[OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.
Summary:
Introduced OMPChildren class to handle all associated clauses, statement
and child expressions/statements. It allows to represent some directives
more correctly (like flush, depobj etc. with pseudo clauses, ordered
depend directives, which are standalone, and target data directives).
Also, it will make easier to avoid using of CapturedStmt in directives,
if required (atomic, tile etc. directives).
Also, it simplifies serialization/deserialization of the
executable/declarative directives.
Reduces number of allocation operations for mapper declarations.
Reviewers: jdoerfert
Subscribers: yaxunl, guansong, jfb, cfe-commits, sstefan1, aaron.ballman, caomhin
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83261
2020-06-26 17:42:31 -04:00
|
|
|
ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.empty());
|
2019-02-01 20:25:04 +00:00
|
|
|
if (Clause)
|
|
|
|
Clauses.push_back(Clause);
|
|
|
|
else
|
|
|
|
IsCorrect = false;
|
|
|
|
// Skip ',' if any.
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().EndOpenMPClause();
|
2019-02-01 20:25:04 +00:00
|
|
|
}
|
|
|
|
if (Clauses.empty()) {
|
|
|
|
Diag(Tok, diag::err_omp_expected_clause)
|
|
|
|
<< getOpenMPDirectiveName(OMPD_declare_mapper);
|
|
|
|
IsCorrect = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Exit scope.
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().EndOpenMPDSABlock(nullptr);
|
2019-02-01 20:25:04 +00:00
|
|
|
OMPDirectiveScope.Exit();
|
2024-04-16 16:36:53 +04:00
|
|
|
DeclGroupPtrTy DG = Actions.OpenMP().ActOnOpenMPDeclareMapperDirective(
|
[OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.
Summary:
Introduced OMPChildren class to handle all associated clauses, statement
and child expressions/statements. It allows to represent some directives
more correctly (like flush, depobj etc. with pseudo clauses, ordered
depend directives, which are standalone, and target data directives).
Also, it will make easier to avoid using of CapturedStmt in directives,
if required (atomic, tile etc. directives).
Also, it simplifies serialization/deserialization of the
executable/declarative directives.
Reduces number of allocation operations for mapper declarations.
Reviewers: jdoerfert
Subscribers: yaxunl, guansong, jfb, cfe-commits, sstefan1, aaron.ballman, caomhin
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83261
2020-06-26 17:42:31 -04:00
|
|
|
getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType,
|
|
|
|
Range.getBegin(), VName, AS, MapperVarRef.get(), Clauses);
|
2019-02-01 20:25:04 +00:00
|
|
|
if (!IsCorrect)
|
|
|
|
return DeclGroupPtrTy();
|
[OPENMP]Redesign of OMPExecutableDirective/OMPDeclarativeDirective representation.
Summary:
Introduced OMPChildren class to handle all associated clauses, statement
and child expressions/statements. It allows to represent some directives
more correctly (like flush, depobj etc. with pseudo clauses, ordered
depend directives, which are standalone, and target data directives).
Also, it will make easier to avoid using of CapturedStmt in directives,
if required (atomic, tile etc. directives).
Also, it simplifies serialization/deserialization of the
executable/declarative directives.
Reduces number of allocation operations for mapper declarations.
Reviewers: jdoerfert
Subscribers: yaxunl, guansong, jfb, cfe-commits, sstefan1, aaron.ballman, caomhin
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83261
2020-06-26 17:42:31 -04:00
|
|
|
|
|
|
|
return DG;
|
2019-02-01 20:25:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
|
|
|
|
DeclarationName &Name,
|
|
|
|
AccessSpecifier AS) {
|
|
|
|
// Parse the common declaration-specifiers piece.
|
|
|
|
Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
|
|
|
|
DeclSpec DS(AttrFactory);
|
|
|
|
ParseSpecifierQualifierList(DS, AS, DSC);
|
|
|
|
|
|
|
|
// Parse the declarator.
|
2020-11-10 23:40:12 -06:00
|
|
|
DeclaratorContext Context = DeclaratorContext::Prototype;
|
[clang] Reject non-declaration C++11 attributes on declarations
For backwards compatiblity, we emit only a warning instead of an error if the
attribute is one of the existing type attributes that we have historically
allowed to "slide" to the `DeclSpec` just as if it had been specified in GNU
syntax. (We will call these "legacy type attributes" below.)
The high-level changes that achieve this are:
- We introduce a new field `Declarator::DeclarationAttrs` (with appropriate
accessors) to store C++11 attributes occurring in the attribute-specifier-seq
at the beginning of a simple-declaration (and other similar declarations).
Previously, these attributes were placed on the `DeclSpec`, which made it
impossible to reconstruct later on whether the attributes had in fact been
placed on the decl-specifier-seq or ahead of the declaration.
- In the parser, we propgate declaration attributes and decl-specifier-seq
attributes separately until we can place them in
`Declarator::DeclarationAttrs` or `DeclSpec::Attrs`, respectively.
- In `ProcessDeclAttributes()`, in addition to processing declarator attributes,
we now also process the attributes from `Declarator::DeclarationAttrs` (except
if they are legacy type attributes).
- In `ConvertDeclSpecToType()`, in addition to processing `DeclSpec` attributes,
we also process any legacy type attributes that occur in
`Declarator::DeclarationAttrs` (and emit a warning).
- We make `ProcessDeclAttribute` emit an error if it sees any non-declaration
attributes in C++11 syntax, except in the following cases:
- If it is being called for attributes on a `DeclSpec` or `DeclaratorChunk`
- If the attribute is a legacy type attribute (in which case we only emit
a warning)
The standard justifies treating attributes at the beginning of a
simple-declaration and attributes after a declarator-id the same. Here are some
relevant parts of the standard:
- The attribute-specifier-seq at the beginning of a simple-declaration
"appertains to each of the entities declared by the declarators of the
init-declarator-list" (https://eel.is/c++draft/dcl.dcl#dcl.pre-3)
- "In the declaration for an entity, attributes appertaining to that entity can
appear at the start of the declaration and after the declarator-id for that
declaration." (https://eel.is/c++draft/dcl.dcl#dcl.pre-note-2)
- "The optional attribute-specifier-seq following a declarator-id appertains to
the entity that is declared."
(https://eel.is/c++draft/dcl.dcl#dcl.meaning.general-1)
The standard contains similar wording to that for a simple-declaration in other
similar types of declarations, for example:
- "The optional attribute-specifier-seq in a parameter-declaration appertains to
the parameter." (https://eel.is/c++draft/dcl.fct#3)
- "The optional attribute-specifier-seq in an exception-declaration appertains
to the parameter of the catch clause" (https://eel.is/c++draft/except.pre#1)
The new behavior is tested both on the newly added type attribute
`annotate_type`, for which we emit errors, and for the legacy type attribute
`address_space` (chosen somewhat randomly from the various legacy type
attributes), for which we emit warnings.
Depends On D111548
Reviewed By: aaron.ballman, rsmith
Differential Revision: https://reviews.llvm.org/D126061
2022-06-15 08:07:23 +02:00
|
|
|
Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), Context);
|
2019-02-01 20:25:04 +00:00
|
|
|
ParseDeclarator(DeclaratorInfo);
|
|
|
|
Range = DeclaratorInfo.getSourceRange();
|
|
|
|
if (DeclaratorInfo.getIdentifier() == nullptr) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();
|
|
|
|
|
2024-04-16 16:36:53 +04:00
|
|
|
return Actions.OpenMP().ActOnOpenMPDeclareMapperVarDecl(getCurScope(),
|
|
|
|
DeclaratorInfo);
|
2019-02-01 20:25:04 +00:00
|
|
|
}
|
|
|
|
|
2016-04-07 12:45:37 +00:00
|
|
|
namespace {
|
|
|
|
/// RAII that recreates function context for correct parsing of clauses of
|
|
|
|
/// 'declare simd' construct.
|
|
|
|
/// OpenMP, 2.8.2 declare simd Construct
|
|
|
|
/// The expressions appearing in the clauses of this directive are evaluated in
|
|
|
|
/// the scope of the arguments of the function declaration or definition.
|
|
|
|
class FNContextRAII final {
|
|
|
|
Parser &P;
|
|
|
|
Sema::CXXThisScopeRAII *ThisScope;
|
2020-06-16 16:55:56 -07:00
|
|
|
Parser::MultiParseScope Scopes;
|
2016-04-07 12:45:37 +00:00
|
|
|
bool HasFunScope = false;
|
|
|
|
FNContextRAII() = delete;
|
|
|
|
FNContextRAII(const FNContextRAII &) = delete;
|
|
|
|
FNContextRAII &operator=(const FNContextRAII &) = delete;
|
|
|
|
|
|
|
|
public:
|
2020-06-16 16:55:56 -07:00
|
|
|
FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P), Scopes(P) {
|
2016-04-07 12:45:37 +00:00
|
|
|
Decl *D = *Ptr.get().begin();
|
|
|
|
NamedDecl *ND = dyn_cast<NamedDecl>(D);
|
|
|
|
RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
|
|
|
|
Sema &Actions = P.getActions();
|
|
|
|
|
|
|
|
// Allow 'this' within late-parsed attributes.
|
2018-12-13 10:15:27 +00:00
|
|
|
ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
|
2016-04-07 12:45:37 +00:00
|
|
|
ND && ND->isCXXInstanceMember());
|
|
|
|
|
|
|
|
// If the Decl is templatized, add template parameters to scope.
|
2020-06-16 16:55:56 -07:00
|
|
|
// FIXME: Track CurTemplateDepth?
|
|
|
|
P.ReenterTemplateScopes(Scopes, D);
|
2016-04-07 12:45:37 +00:00
|
|
|
|
|
|
|
// If the Decl is on a function, add function parameters to the scope.
|
2020-06-16 16:55:56 -07:00
|
|
|
if (D->isFunctionOrFunctionTemplate()) {
|
|
|
|
HasFunScope = true;
|
|
|
|
Scopes.Enter(Scope::FnScope | Scope::DeclScope |
|
|
|
|
Scope::CompoundStmtScope);
|
2016-04-07 12:45:37 +00:00
|
|
|
Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
|
2020-06-16 16:55:56 -07:00
|
|
|
}
|
2016-04-07 12:45:37 +00:00
|
|
|
}
|
|
|
|
~FNContextRAII() {
|
2020-06-16 16:55:56 -07:00
|
|
|
if (HasFunScope)
|
2016-04-07 12:45:37 +00:00
|
|
|
P.getActions().ActOnExitFunctionContext();
|
|
|
|
delete ThisScope;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
} // namespace
|
|
|
|
|
2016-04-12 09:35:56 +00:00
|
|
|
/// Parses clauses for 'declare simd' directive.
|
|
|
|
/// clause:
|
|
|
|
/// 'inbranch' | 'notinbranch'
|
|
|
|
/// 'simdlen' '(' <expr> ')'
|
|
|
|
/// { 'uniform' '(' <argument_list> ')' }
|
|
|
|
/// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
|
2016-04-12 11:02:11 +00:00
|
|
|
/// { 'linear '(' <argument_list> [ ':' <step> ] ')' }
|
|
|
|
static bool parseDeclareSimdClauses(
|
|
|
|
Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
|
|
|
|
SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
|
|
|
|
SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
|
|
|
|
SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
|
2016-04-12 09:35:56 +00:00
|
|
|
SourceRange BSRange;
|
|
|
|
const Token &Tok = P.getCurToken();
|
|
|
|
bool IsError = false;
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
if (Tok.isNot(tok::identifier))
|
|
|
|
break;
|
|
|
|
OMPDeclareSimdDeclAttr::BranchStateTy Out;
|
|
|
|
IdentifierInfo *II = Tok.getIdentifierInfo();
|
|
|
|
StringRef ClauseName = II->getName();
|
|
|
|
// Parse 'inranch|notinbranch' clauses.
|
|
|
|
if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
|
|
|
|
if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
|
|
|
|
P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
|
|
|
|
<< ClauseName
|
|
|
|
<< OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
|
|
|
|
IsError = true;
|
|
|
|
}
|
|
|
|
BS = Out;
|
|
|
|
BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
|
|
|
|
P.ConsumeToken();
|
2024-05-11 11:38:52 -07:00
|
|
|
} else if (ClauseName == "simdlen") {
|
2016-04-12 09:35:56 +00:00
|
|
|
if (SimdLen.isUsable()) {
|
|
|
|
P.Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
|
|
|
|
IsError = true;
|
|
|
|
}
|
|
|
|
P.ConsumeToken();
|
|
|
|
SourceLocation RLoc;
|
|
|
|
SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
|
|
|
|
if (SimdLen.isInvalid())
|
|
|
|
IsError = true;
|
|
|
|
} else {
|
|
|
|
OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
|
2016-04-12 11:02:11 +00:00
|
|
|
if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
|
|
|
|
CKind == OMPC_linear) {
|
2024-04-16 16:36:53 +04:00
|
|
|
SemaOpenMP::OpenMPVarListDataTy Data;
|
2018-04-23 19:53:05 +00:00
|
|
|
SmallVectorImpl<Expr *> *Vars = &Uniforms;
|
2019-12-24 16:02:58 -05:00
|
|
|
if (CKind == OMPC_aligned) {
|
2016-04-12 09:35:56 +00:00
|
|
|
Vars = &Aligneds;
|
2019-12-24 16:02:58 -05:00
|
|
|
} else if (CKind == OMPC_linear) {
|
|
|
|
Data.ExtraModifier = OMPC_LINEAR_val;
|
2016-04-12 11:02:11 +00:00
|
|
|
Vars = &Linears;
|
2019-12-24 16:02:58 -05:00
|
|
|
}
|
2016-04-12 09:35:56 +00:00
|
|
|
|
|
|
|
P.ConsumeToken();
|
|
|
|
if (P.ParseOpenMPVarList(OMPD_declare_simd,
|
|
|
|
getOpenMPClauseKind(ClauseName), *Vars, Data))
|
|
|
|
IsError = true;
|
2018-04-23 19:53:05 +00:00
|
|
|
if (CKind == OMPC_aligned) {
|
2020-04-01 15:06:38 -04:00
|
|
|
Alignments.append(Aligneds.size() - Alignments.size(),
|
|
|
|
Data.DepModOrTailExpr);
|
2018-04-23 19:53:05 +00:00
|
|
|
} else if (CKind == OMPC_linear) {
|
2019-12-24 16:02:58 -05:00
|
|
|
assert(0 <= Data.ExtraModifier &&
|
|
|
|
Data.ExtraModifier <= OMPC_LINEAR_unknown &&
|
|
|
|
"Unexpected linear modifier.");
|
2024-04-16 16:36:53 +04:00
|
|
|
if (P.getActions().OpenMP().CheckOpenMPLinearModifier(
|
2019-12-20 11:04:57 -05:00
|
|
|
static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier),
|
2020-03-23 17:30:38 -04:00
|
|
|
Data.ExtraModifierLoc))
|
2019-12-20 11:04:57 -05:00
|
|
|
Data.ExtraModifier = OMPC_LINEAR_val;
|
2016-04-12 11:02:11 +00:00
|
|
|
LinModifiers.append(Linears.size() - LinModifiers.size(),
|
2019-12-20 11:04:57 -05:00
|
|
|
Data.ExtraModifier);
|
2020-04-01 15:06:38 -04:00
|
|
|
Steps.append(Linears.size() - Steps.size(), Data.DepModOrTailExpr);
|
2016-04-12 11:02:11 +00:00
|
|
|
}
|
2016-04-12 09:35:56 +00:00
|
|
|
} else
|
|
|
|
// TODO: add parsing of other clauses.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Skip ',' if any.
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
P.ConsumeToken();
|
|
|
|
}
|
|
|
|
return IsError;
|
|
|
|
}
|
|
|
|
|
2016-04-07 12:45:37 +00:00
|
|
|
/// Parse clauses for '#pragma omp declare simd'.
|
|
|
|
Parser::DeclGroupPtrTy
|
|
|
|
Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
|
|
|
|
CachedTokens &Toks, SourceLocation Loc) {
|
2019-05-17 09:32:05 +00:00
|
|
|
PP.EnterToken(Tok, /*IsReinject*/ true);
|
|
|
|
PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
|
|
|
|
/*IsReinject*/ true);
|
2016-04-07 12:45:37 +00:00
|
|
|
// Consume the previously pushed token.
|
|
|
|
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
|
2019-09-13 20:18:17 +00:00
|
|
|
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
|
2016-04-07 12:45:37 +00:00
|
|
|
|
|
|
|
FNContextRAII FnContext(*this, Ptr);
|
|
|
|
OMPDeclareSimdDeclAttr::BranchStateTy BS =
|
|
|
|
OMPDeclareSimdDeclAttr::BS_Undefined;
|
|
|
|
ExprResult Simdlen;
|
2016-04-12 05:28:34 +00:00
|
|
|
SmallVector<Expr *, 4> Uniforms;
|
2016-04-12 09:35:56 +00:00
|
|
|
SmallVector<Expr *, 4> Aligneds;
|
|
|
|
SmallVector<Expr *, 4> Alignments;
|
2016-04-12 11:02:11 +00:00
|
|
|
SmallVector<Expr *, 4> Linears;
|
|
|
|
SmallVector<unsigned, 4> LinModifiers;
|
|
|
|
SmallVector<Expr *, 4> Steps;
|
|
|
|
bool IsError =
|
|
|
|
parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
|
|
|
|
Alignments, Linears, LinModifiers, Steps);
|
2020-02-21 13:48:56 -06:00
|
|
|
skipUntilPragmaOpenMPEnd(OMPD_declare_simd);
|
2016-04-07 12:45:37 +00:00
|
|
|
// Skip the last annot_pragma_openmp_end.
|
2017-05-18 19:21:48 +00:00
|
|
|
SourceLocation EndLoc = ConsumeAnnotationToken();
|
2018-04-23 19:53:05 +00:00
|
|
|
if (IsError)
|
|
|
|
return Ptr;
|
2024-04-16 16:36:53 +04:00
|
|
|
return Actions.OpenMP().ActOnOpenMPDeclareSimdDirective(
|
2018-04-23 19:53:05 +00:00
|
|
|
Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
|
|
|
|
LinModifiers, Steps, SourceRange(Loc, EndLoc));
|
2016-04-04 10:12:15 +00:00
|
|
|
}
|
|
|
|
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
namespace {
|
|
|
|
/// Constant used in the diagnostics to distinguish the levels in an OpenMP
|
|
|
|
/// contexts: selector-set={selector(trait, ...), ...}, ....
|
|
|
|
enum OMPContextLvl {
|
|
|
|
CONTEXT_SELECTOR_SET_LVL = 0,
|
|
|
|
CONTEXT_SELECTOR_LVL = 1,
|
|
|
|
CONTEXT_TRAIT_LVL = 2,
|
|
|
|
};
|
|
|
|
|
|
|
|
static StringRef stringLiteralParser(Parser &P) {
|
|
|
|
ExprResult Res = P.ParseStringLiteralExpression(true);
|
|
|
|
return Res.isUsable() ? Res.getAs<StringLiteral>()->getString() : "";
|
|
|
|
}
|
|
|
|
|
|
|
|
static StringRef getNameFromIdOrString(Parser &P, Token &Tok,
|
|
|
|
OMPContextLvl Lvl) {
|
2021-09-16 11:28:31 -05:00
|
|
|
if (Tok.is(tok::identifier) || Tok.is(tok::kw_for)) {
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
llvm::SmallString<16> Buffer;
|
|
|
|
StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer);
|
|
|
|
(void)P.ConsumeToken();
|
|
|
|
return Name;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tok::isStringLiteral(Tok.getKind()))
|
|
|
|
return stringLiteralParser(P);
|
|
|
|
|
|
|
|
P.Diag(Tok.getLocation(),
|
|
|
|
diag::warn_omp_declare_variant_string_literal_or_identifier)
|
|
|
|
<< Lvl;
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool checkForDuplicates(Parser &P, StringRef Name,
|
|
|
|
SourceLocation NameLoc,
|
|
|
|
llvm::StringMap<SourceLocation> &Seen,
|
|
|
|
OMPContextLvl Lvl) {
|
|
|
|
auto Res = Seen.try_emplace(Name, NameLoc);
|
|
|
|
if (Res.second)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Each trait-set-selector-name, trait-selector-name and trait-name can
|
|
|
|
// only be specified once.
|
|
|
|
P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use)
|
|
|
|
<< Lvl << Name;
|
|
|
|
P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
|
|
|
|
<< Lvl << Name;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} // namespace
|
|
|
|
|
2020-10-29 18:44:28 -05:00
|
|
|
void Parser::parseOMPTraitPropertyKind(OMPTraitProperty &TIProperty,
|
|
|
|
llvm::omp::TraitSet Set,
|
|
|
|
llvm::omp::TraitSelector Selector,
|
|
|
|
llvm::StringMap<SourceLocation> &Seen) {
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
TIProperty.Kind = TraitProperty::invalid;
|
|
|
|
|
|
|
|
SourceLocation NameLoc = Tok.getLocation();
|
2025-02-05 19:24:24 +05:30
|
|
|
StringRef Name;
|
|
|
|
if (Selector == llvm::omp::TraitSelector::target_device_device_num) {
|
|
|
|
Name = "number";
|
|
|
|
TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);
|
|
|
|
ExprResult DeviceNumExprResult = ParseExpression();
|
|
|
|
if (DeviceNumExprResult.isUsable()) {
|
|
|
|
Expr *DeviceNumExpr = DeviceNumExprResult.get();
|
|
|
|
Actions.OpenMP().ActOnOpenMPDeviceNum(DeviceNumExpr);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Name = getNameFromIdOrString(*this, Tok, CONTEXT_TRAIT_LVL);
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
if (Name.empty()) {
|
|
|
|
Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
|
|
|
|
<< CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-07-07 01:08:03 -05:00
|
|
|
TIProperty.RawString = Name;
|
|
|
|
TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
if (TIProperty.Kind != TraitProperty::invalid) {
|
|
|
|
if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL))
|
|
|
|
TIProperty.Kind = TraitProperty::invalid;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// It follows diagnosis and helping notes.
|
|
|
|
// FIXME: We should move the diagnosis string generation into libFrontend.
|
|
|
|
Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property)
|
|
|
|
<< Name << getOpenMPContextTraitSelectorName(Selector)
|
|
|
|
<< getOpenMPContextTraitSetName(Set);
|
|
|
|
|
|
|
|
TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
|
|
|
|
if (SetForName != TraitSet::invalid) {
|
|
|
|
Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
|
|
|
|
<< Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL;
|
|
|
|
Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
|
|
|
|
<< Name << "<selector-name>"
|
|
|
|
<< "(<property-name>)";
|
|
|
|
return;
|
|
|
|
}
|
2025-02-05 19:24:24 +05:30
|
|
|
TraitSelector SelectorForName =
|
|
|
|
getOpenMPContextTraitSelectorKind(Name, SetForName);
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
if (SelectorForName != TraitSelector::invalid) {
|
|
|
|
Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
|
|
|
|
<< Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL;
|
|
|
|
bool AllowsTraitScore = false;
|
|
|
|
bool RequiresProperty = false;
|
|
|
|
isValidTraitSelectorForTraitSet(
|
|
|
|
SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
|
|
|
|
AllowsTraitScore, RequiresProperty);
|
|
|
|
Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
|
|
|
|
<< getOpenMPContextTraitSetName(
|
|
|
|
getOpenMPContextTraitSetForSelector(SelectorForName))
|
|
|
|
<< Name << (RequiresProperty ? "(<property-name>)" : "");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (const auto &PotentialSet :
|
|
|
|
{TraitSet::construct, TraitSet::user, TraitSet::implementation,
|
2025-02-05 19:24:24 +05:30
|
|
|
TraitSet::device, TraitSet::target_device}) {
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
TraitProperty PropertyForName =
|
2020-07-07 01:08:03 -05:00
|
|
|
getOpenMPContextTraitPropertyKind(PotentialSet, Selector, Name);
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
if (PropertyForName == TraitProperty::invalid)
|
|
|
|
continue;
|
|
|
|
Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
|
|
|
|
<< getOpenMPContextTraitSetName(
|
|
|
|
getOpenMPContextTraitSetForProperty(PropertyForName))
|
|
|
|
<< getOpenMPContextTraitSelectorName(
|
|
|
|
getOpenMPContextTraitSelectorForProperty(PropertyForName))
|
|
|
|
<< ("(" + Name + ")").str();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
|
|
|
|
<< CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
|
|
|
|
}
|
|
|
|
|
2020-04-03 11:29:53 -05:00
|
|
|
static bool checkExtensionProperty(Parser &P, SourceLocation Loc,
|
|
|
|
OMPTraitProperty &TIProperty,
|
|
|
|
OMPTraitSelector &TISelector,
|
|
|
|
llvm::StringMap<SourceLocation> &Seen) {
|
|
|
|
assert(TISelector.Kind ==
|
|
|
|
llvm::omp::TraitSelector::implementation_extension &&
|
|
|
|
"Only for extension properties, e.g., "
|
|
|
|
"`implementation={extension(PROPERTY)}`");
|
|
|
|
if (TIProperty.Kind == TraitProperty::invalid)
|
|
|
|
return false;
|
|
|
|
|
2020-08-12 16:49:10 -05:00
|
|
|
if (TIProperty.Kind ==
|
|
|
|
TraitProperty::implementation_extension_disable_implicit_base)
|
|
|
|
return true;
|
|
|
|
|
2020-05-31 11:40:09 -05:00
|
|
|
if (TIProperty.Kind ==
|
|
|
|
TraitProperty::implementation_extension_allow_templates)
|
|
|
|
return true;
|
|
|
|
|
2022-06-29 14:53:45 -04:00
|
|
|
if (TIProperty.Kind ==
|
|
|
|
TraitProperty::implementation_extension_bind_to_declaration)
|
|
|
|
return true;
|
|
|
|
|
2020-04-03 11:29:53 -05:00
|
|
|
auto IsMatchExtension = [](OMPTraitProperty &TP) {
|
|
|
|
return (TP.Kind ==
|
|
|
|
llvm::omp::TraitProperty::implementation_extension_match_all ||
|
|
|
|
TP.Kind ==
|
|
|
|
llvm::omp::TraitProperty::implementation_extension_match_any ||
|
|
|
|
TP.Kind ==
|
|
|
|
llvm::omp::TraitProperty::implementation_extension_match_none);
|
|
|
|
};
|
|
|
|
|
|
|
|
if (IsMatchExtension(TIProperty)) {
|
|
|
|
for (OMPTraitProperty &SeenProp : TISelector.Properties)
|
|
|
|
if (IsMatchExtension(SeenProp)) {
|
|
|
|
P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension);
|
2020-07-07 01:08:03 -05:00
|
|
|
StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName(
|
|
|
|
SeenProp.Kind, SeenProp.RawString);
|
2020-04-03 11:29:53 -05:00
|
|
|
SourceLocation SeenLoc = Seen[SeenName];
|
|
|
|
P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here)
|
|
|
|
<< CONTEXT_TRAIT_LVL << SeenName;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("Unknown extension property!");
|
|
|
|
}
|
|
|
|
|
2020-04-03 12:35:30 -07:00
|
|
|
void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector,
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
llvm::omp::TraitSet Set,
|
|
|
|
llvm::StringMap<SourceLocation> &Seen) {
|
|
|
|
assert(TISelector.Kind != TraitSelector::user_condition &&
|
|
|
|
"User conditions are special properties not handled here!");
|
|
|
|
|
|
|
|
SourceLocation PropertyLoc = Tok.getLocation();
|
2020-04-03 12:35:30 -07:00
|
|
|
OMPTraitProperty TIProperty;
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind, Seen);
|
|
|
|
|
2020-04-03 11:29:53 -05:00
|
|
|
if (TISelector.Kind == llvm::omp::TraitSelector::implementation_extension)
|
|
|
|
if (!checkExtensionProperty(*this, Tok.getLocation(), TIProperty,
|
|
|
|
TISelector, Seen))
|
|
|
|
TIProperty.Kind = TraitProperty::invalid;
|
|
|
|
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
// If we have an invalid property here we already issued a warning.
|
|
|
|
if (TIProperty.Kind == TraitProperty::invalid) {
|
|
|
|
if (PropertyLoc != Tok.getLocation())
|
|
|
|
Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
|
|
|
|
<< CONTEXT_TRAIT_LVL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind,
|
|
|
|
TISelector.Kind, Set)) {
|
2020-04-03 11:29:53 -05:00
|
|
|
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
// If we make it here the property, selector, set, score, condition, ... are
|
|
|
|
// all valid (or have been corrected). Thus we can record the property.
|
|
|
|
TISelector.Properties.push_back(TIProperty);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector)
|
2020-07-07 01:08:03 -05:00
|
|
|
<< getOpenMPContextTraitPropertyName(TIProperty.Kind,
|
|
|
|
TIProperty.RawString)
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
<< getOpenMPContextTraitSelectorName(TISelector.Kind)
|
|
|
|
<< getOpenMPContextTraitSetName(Set);
|
|
|
|
Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property)
|
2020-07-07 01:08:03 -05:00
|
|
|
<< getOpenMPContextTraitPropertyName(TIProperty.Kind,
|
|
|
|
TIProperty.RawString)
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
<< getOpenMPContextTraitSelectorName(
|
|
|
|
getOpenMPContextTraitSelectorForProperty(TIProperty.Kind))
|
|
|
|
<< getOpenMPContextTraitSetName(
|
|
|
|
getOpenMPContextTraitSetForProperty(TIProperty.Kind));
|
|
|
|
Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
|
|
|
|
<< CONTEXT_TRAIT_LVL;
|
|
|
|
}
|
|
|
|
|
2020-10-29 18:44:28 -05:00
|
|
|
void Parser::parseOMPTraitSelectorKind(OMPTraitSelector &TISelector,
|
|
|
|
llvm::omp::TraitSet Set,
|
|
|
|
llvm::StringMap<SourceLocation> &Seen) {
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
TISelector.Kind = TraitSelector::invalid;
|
|
|
|
|
|
|
|
SourceLocation NameLoc = Tok.getLocation();
|
2020-10-29 18:44:28 -05:00
|
|
|
StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_LVL);
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
if (Name.empty()) {
|
|
|
|
Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
|
|
|
|
<< CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2025-02-05 19:24:24 +05:30
|
|
|
TISelector.Kind = getOpenMPContextTraitSelectorKind(Name, Set);
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
if (TISelector.Kind != TraitSelector::invalid) {
|
|
|
|
if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL))
|
|
|
|
TISelector.Kind = TraitSelector::invalid;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// It follows diagnosis and helping notes.
|
|
|
|
Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector)
|
|
|
|
<< Name << getOpenMPContextTraitSetName(Set);
|
|
|
|
|
|
|
|
TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
|
|
|
|
if (SetForName != TraitSet::invalid) {
|
|
|
|
Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
|
|
|
|
<< Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL;
|
|
|
|
Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
|
|
|
|
<< Name << "<selector-name>"
|
|
|
|
<< "<property-name>";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (const auto &PotentialSet :
|
|
|
|
{TraitSet::construct, TraitSet::user, TraitSet::implementation,
|
2025-02-05 19:24:24 +05:30
|
|
|
TraitSet::device, TraitSet::target_device}) {
|
2020-07-07 01:08:03 -05:00
|
|
|
TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
|
|
|
|
PotentialSet, TraitSelector::invalid, Name);
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
if (PropertyForName == TraitProperty::invalid)
|
|
|
|
continue;
|
|
|
|
Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
|
|
|
|
<< Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL;
|
|
|
|
Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
|
|
|
|
<< getOpenMPContextTraitSetName(
|
|
|
|
getOpenMPContextTraitSetForProperty(PropertyForName))
|
|
|
|
<< getOpenMPContextTraitSelectorName(
|
|
|
|
getOpenMPContextTraitSelectorForProperty(PropertyForName))
|
|
|
|
<< ("(" + Name + ")").str();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
|
|
|
|
<< CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
|
|
|
|
}
|
|
|
|
|
2019-10-02 18:19:02 +00:00
|
|
|
/// Parse optional 'score' '(' <expr> ')' ':'.
|
|
|
|
static ExprResult parseContextScore(Parser &P) {
|
|
|
|
ExprResult ScoreExpr;
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
llvm::SmallString<16> Buffer;
|
2019-10-02 18:19:02 +00:00
|
|
|
StringRef SelectorName =
|
|
|
|
P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
|
2024-05-11 11:38:52 -07:00
|
|
|
if (SelectorName != "score")
|
2019-10-02 18:19:02 +00:00
|
|
|
return ScoreExpr;
|
|
|
|
(void)P.ConsumeToken();
|
|
|
|
SourceLocation RLoc;
|
|
|
|
ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);
|
|
|
|
// Parse ':'
|
|
|
|
if (P.getCurToken().is(tok::colon))
|
|
|
|
(void)P.ConsumeAnyToken();
|
|
|
|
else
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected)
|
|
|
|
<< "':'"
|
|
|
|
<< "score expression";
|
2019-10-02 18:19:02 +00:00
|
|
|
return ScoreExpr;
|
|
|
|
}
|
|
|
|
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
/// Parses an OpenMP context selector.
|
|
|
|
///
|
|
|
|
/// <trait-selector-name> ['('[<trait-score>] <trait-property> [, <t-p>]* ')']
|
|
|
|
void Parser::parseOMPContextSelector(
|
2020-04-03 12:35:30 -07:00
|
|
|
OMPTraitSelector &TISelector, llvm::omp::TraitSet Set,
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
llvm::StringMap<SourceLocation> &SeenSelectors) {
|
|
|
|
unsigned short OuterPC = ParenCount;
|
|
|
|
|
|
|
|
// If anything went wrong we issue an error or warning and then skip the rest
|
|
|
|
// of the selector. However, commas are ambiguous so we look for the nesting
|
|
|
|
// of parentheses here as well.
|
|
|
|
auto FinishSelector = [OuterPC, this]() -> void {
|
|
|
|
bool Done = false;
|
|
|
|
while (!Done) {
|
|
|
|
while (!SkipUntil({tok::r_brace, tok::r_paren, tok::comma,
|
|
|
|
tok::annot_pragma_openmp_end},
|
|
|
|
StopBeforeMatch))
|
|
|
|
;
|
|
|
|
if (Tok.is(tok::r_paren) && OuterPC > ParenCount)
|
|
|
|
(void)ConsumeParen();
|
|
|
|
if (OuterPC <= ParenCount) {
|
|
|
|
Done = true;
|
|
|
|
break;
|
2019-10-04 15:58:45 +00:00
|
|
|
}
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) {
|
|
|
|
Done = true;
|
|
|
|
break;
|
2019-10-04 15:58:45 +00:00
|
|
|
}
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
(void)ConsumeAnyToken();
|
|
|
|
}
|
|
|
|
Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
|
|
|
|
<< CONTEXT_SELECTOR_LVL;
|
|
|
|
};
|
|
|
|
|
|
|
|
SourceLocation SelectorLoc = Tok.getLocation();
|
|
|
|
parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors);
|
|
|
|
if (TISelector.Kind == TraitSelector::invalid)
|
|
|
|
return FinishSelector();
|
|
|
|
|
|
|
|
bool AllowsTraitScore = false;
|
|
|
|
bool RequiresProperty = false;
|
|
|
|
if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore,
|
|
|
|
RequiresProperty)) {
|
|
|
|
Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set)
|
|
|
|
<< getOpenMPContextTraitSelectorName(TISelector.Kind)
|
|
|
|
<< getOpenMPContextTraitSetName(Set);
|
|
|
|
Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector)
|
|
|
|
<< getOpenMPContextTraitSelectorName(TISelector.Kind)
|
|
|
|
<< getOpenMPContextTraitSetName(
|
|
|
|
getOpenMPContextTraitSetForSelector(TISelector.Kind))
|
|
|
|
<< RequiresProperty;
|
|
|
|
return FinishSelector();
|
2019-09-25 19:43:37 +00:00
|
|
|
}
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
|
|
|
|
if (!RequiresProperty) {
|
|
|
|
TISelector.Properties.push_back(
|
2020-07-07 01:08:03 -05:00
|
|
|
{getOpenMPContextTraitPropertyForSelector(TISelector.Kind),
|
|
|
|
getOpenMPContextTraitSelectorName(TISelector.Kind)});
|
2019-09-25 19:43:37 +00:00
|
|
|
return;
|
|
|
|
}
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
|
|
|
|
if (!Tok.is(tok::l_paren)) {
|
|
|
|
Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties)
|
|
|
|
<< getOpenMPContextTraitSelectorName(TISelector.Kind)
|
|
|
|
<< getOpenMPContextTraitSetName(Set);
|
|
|
|
return FinishSelector();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TISelector.Kind == TraitSelector::user_condition) {
|
|
|
|
SourceLocation RLoc;
|
|
|
|
ExprResult Condition = ParseOpenMPParensExpr("user condition", RLoc);
|
|
|
|
if (!Condition.isUsable())
|
|
|
|
return FinishSelector();
|
|
|
|
TISelector.ScoreOrCondition = Condition.get();
|
2020-07-07 01:08:03 -05:00
|
|
|
TISelector.Properties.push_back(
|
|
|
|
{TraitProperty::user_condition_unknown, "<condition>"});
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BalancedDelimiterTracker BDT(*this, tok::l_paren,
|
|
|
|
tok::annot_pragma_openmp_end);
|
|
|
|
// Parse '('.
|
|
|
|
(void)BDT.consumeOpen();
|
|
|
|
|
2020-02-20 19:50:47 -06:00
|
|
|
SourceLocation ScoreLoc = Tok.getLocation();
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
ExprResult Score = parseContextScore(*this);
|
|
|
|
|
2020-02-20 19:50:47 -06:00
|
|
|
if (!AllowsTraitScore && !Score.isUnset()) {
|
|
|
|
if (Score.isUsable()) {
|
|
|
|
Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
|
|
|
|
<< getOpenMPContextTraitSelectorName(TISelector.Kind)
|
|
|
|
<< getOpenMPContextTraitSetName(Set) << Score.get();
|
|
|
|
} else {
|
|
|
|
Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
|
|
|
|
<< getOpenMPContextTraitSelectorName(TISelector.Kind)
|
|
|
|
<< getOpenMPContextTraitSetName(Set) << "<invalid>";
|
|
|
|
}
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
Score = ExprResult();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Score.isUsable())
|
|
|
|
TISelector.ScoreOrCondition = Score.get();
|
|
|
|
|
|
|
|
llvm::StringMap<SourceLocation> SeenProperties;
|
|
|
|
do {
|
|
|
|
parseOMPContextProperty(TISelector, Set, SeenProperties);
|
|
|
|
} while (TryConsumeToken(tok::comma));
|
|
|
|
|
|
|
|
// Parse ')'.
|
|
|
|
BDT.consumeClose();
|
2019-09-25 19:43:37 +00:00
|
|
|
}
|
|
|
|
|
2020-04-03 12:35:30 -07:00
|
|
|
void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet,
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
llvm::StringMap<SourceLocation> &Seen) {
|
|
|
|
TISet.Kind = TraitSet::invalid;
|
|
|
|
|
|
|
|
SourceLocation NameLoc = Tok.getLocation();
|
2020-10-29 18:44:28 -05:00
|
|
|
StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_SET_LVL);
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
if (Name.empty()) {
|
|
|
|
Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
|
|
|
|
<< CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
|
2019-11-05 15:13:30 -05:00
|
|
|
return;
|
|
|
|
}
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
|
|
|
|
TISet.Kind = getOpenMPContextTraitSetKind(Name);
|
|
|
|
if (TISet.Kind != TraitSet::invalid) {
|
|
|
|
if (checkForDuplicates(*this, Name, NameLoc, Seen,
|
|
|
|
CONTEXT_SELECTOR_SET_LVL))
|
|
|
|
TISet.Kind = TraitSet::invalid;
|
|
|
|
return;
|
2019-11-05 15:13:30 -05:00
|
|
|
}
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
|
|
|
|
// It follows diagnosis and helping notes.
|
|
|
|
Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name;
|
|
|
|
|
2025-02-05 19:24:24 +05:30
|
|
|
TraitSelector SelectorForName =
|
|
|
|
getOpenMPContextTraitSelectorKind(Name, TISet.Kind);
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
if (SelectorForName != TraitSelector::invalid) {
|
|
|
|
Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
|
|
|
|
<< Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL;
|
|
|
|
bool AllowsTraitScore = false;
|
|
|
|
bool RequiresProperty = false;
|
|
|
|
isValidTraitSelectorForTraitSet(
|
|
|
|
SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
|
|
|
|
AllowsTraitScore, RequiresProperty);
|
|
|
|
Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
|
|
|
|
<< getOpenMPContextTraitSetName(
|
|
|
|
getOpenMPContextTraitSetForSelector(SelectorForName))
|
|
|
|
<< Name << (RequiresProperty ? "(<property-name>)" : "");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (const auto &PotentialSet :
|
|
|
|
{TraitSet::construct, TraitSet::user, TraitSet::implementation,
|
2025-02-05 19:24:24 +05:30
|
|
|
TraitSet::device, TraitSet::target_device}) {
|
2020-07-07 01:08:03 -05:00
|
|
|
TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
|
|
|
|
PotentialSet, TraitSelector::invalid, Name);
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
if (PropertyForName == TraitProperty::invalid)
|
|
|
|
continue;
|
|
|
|
Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
|
|
|
|
<< Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL;
|
|
|
|
Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
|
|
|
|
<< getOpenMPContextTraitSetName(
|
|
|
|
getOpenMPContextTraitSetForProperty(PropertyForName))
|
|
|
|
<< getOpenMPContextTraitSelectorName(
|
|
|
|
getOpenMPContextTraitSelectorForProperty(PropertyForName))
|
|
|
|
<< ("(" + Name + ")").str();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
|
|
|
|
<< CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parses an OpenMP context selector set.
|
|
|
|
///
|
|
|
|
/// <trait-set-selector-name> '=' '{' <trait-selector> [, <trait-selector>]* '}'
|
|
|
|
void Parser::parseOMPContextSelectorSet(
|
2020-10-29 18:44:28 -05:00
|
|
|
OMPTraitSet &TISet, llvm::StringMap<SourceLocation> &SeenSets) {
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
auto OuterBC = BraceCount;
|
|
|
|
|
|
|
|
// If anything went wrong we issue an error or warning and then skip the rest
|
|
|
|
// of the set. However, commas are ambiguous so we look for the nesting
|
|
|
|
// of braces here as well.
|
|
|
|
auto FinishSelectorSet = [this, OuterBC]() -> void {
|
|
|
|
bool Done = false;
|
|
|
|
while (!Done) {
|
|
|
|
while (!SkipUntil({tok::comma, tok::r_brace, tok::r_paren,
|
|
|
|
tok::annot_pragma_openmp_end},
|
|
|
|
StopBeforeMatch))
|
|
|
|
;
|
|
|
|
if (Tok.is(tok::r_brace) && OuterBC > BraceCount)
|
|
|
|
(void)ConsumeBrace();
|
|
|
|
if (OuterBC <= BraceCount) {
|
|
|
|
Done = true;
|
|
|
|
break;
|
2019-11-05 15:13:30 -05:00
|
|
|
}
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) {
|
|
|
|
Done = true;
|
|
|
|
break;
|
2019-11-05 15:13:30 -05:00
|
|
|
}
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
(void)ConsumeAnyToken();
|
|
|
|
}
|
|
|
|
Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
|
|
|
|
<< CONTEXT_SELECTOR_SET_LVL;
|
|
|
|
};
|
|
|
|
|
|
|
|
parseOMPTraitSetKind(TISet, SeenSets);
|
|
|
|
if (TISet.Kind == TraitSet::invalid)
|
|
|
|
return FinishSelectorSet();
|
|
|
|
|
|
|
|
// Parse '='.
|
|
|
|
if (!TryConsumeToken(tok::equal))
|
|
|
|
Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
|
|
|
|
<< "="
|
|
|
|
<< ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) +
|
|
|
|
"\"")
|
|
|
|
.str();
|
|
|
|
|
|
|
|
// Parse '{'.
|
|
|
|
if (Tok.is(tok::l_brace)) {
|
|
|
|
(void)ConsumeBrace();
|
|
|
|
} else {
|
|
|
|
Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
|
|
|
|
<< "{"
|
|
|
|
<< ("'=' that follows the context set name \"" +
|
|
|
|
getOpenMPContextTraitSetName(TISet.Kind) + "\"")
|
|
|
|
.str();
|
2019-11-05 15:13:30 -05:00
|
|
|
}
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
|
|
|
|
llvm::StringMap<SourceLocation> SeenSelectors;
|
|
|
|
do {
|
2020-04-03 12:35:30 -07:00
|
|
|
OMPTraitSelector TISelector;
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors);
|
|
|
|
if (TISelector.Kind != TraitSelector::invalid &&
|
|
|
|
!TISelector.Properties.empty())
|
|
|
|
TISet.Selectors.push_back(TISelector);
|
|
|
|
} while (TryConsumeToken(tok::comma));
|
|
|
|
|
|
|
|
// Parse '}'.
|
|
|
|
if (Tok.is(tok::r_brace)) {
|
|
|
|
(void)ConsumeBrace();
|
|
|
|
} else {
|
|
|
|
Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
|
|
|
|
<< "}"
|
|
|
|
<< ("context selectors for the context set \"" +
|
|
|
|
getOpenMPContextTraitSetName(TISet.Kind) + "\"")
|
|
|
|
.str();
|
2019-11-05 15:13:30 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
/// Parse OpenMP context selectors:
|
|
|
|
///
|
|
|
|
/// <trait-set-selector> [, <trait-set-selector>]*
|
2020-10-29 18:44:28 -05:00
|
|
|
bool Parser::parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo &TI) {
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
llvm::StringMap<SourceLocation> SeenSets;
|
2019-09-18 16:24:31 +00:00
|
|
|
do {
|
2020-04-03 12:35:30 -07:00
|
|
|
OMPTraitSet TISet;
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
parseOMPContextSelectorSet(TISet, SeenSets);
|
|
|
|
if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty())
|
|
|
|
TI.Sets.push_back(TISet);
|
|
|
|
} while (TryConsumeToken(tok::comma));
|
|
|
|
|
2019-09-13 20:18:17 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'.
|
2019-09-18 16:24:31 +00:00
|
|
|
void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
|
|
|
|
CachedTokens &Toks,
|
|
|
|
SourceLocation Loc) {
|
2019-09-13 20:18:17 +00:00
|
|
|
PP.EnterToken(Tok, /*IsReinject*/ true);
|
|
|
|
PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
|
|
|
|
/*IsReinject*/ true);
|
|
|
|
// Consume the previously pushed token.
|
|
|
|
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
|
|
|
|
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
|
|
|
|
|
|
|
|
FNContextRAII FnContext(*this, Ptr);
|
|
|
|
// Parse function declaration id.
|
|
|
|
SourceLocation RLoc;
|
|
|
|
// Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
|
|
|
|
// instead of MemberExprs.
|
2019-12-10 16:12:53 -05:00
|
|
|
ExprResult AssociatedFunction;
|
|
|
|
{
|
|
|
|
// Do not mark function as is used to prevent its emission if this is the
|
|
|
|
// only place where it is used.
|
|
|
|
EnterExpressionEvaluationContext Unevaluated(
|
|
|
|
Actions, Sema::ExpressionEvaluationContext::Unevaluated);
|
|
|
|
AssociatedFunction = ParseOpenMPParensExpr(
|
|
|
|
getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
|
|
|
|
/*IsAddressOfOperand=*/true);
|
|
|
|
}
|
2019-09-13 20:18:17 +00:00
|
|
|
if (!AssociatedFunction.isUsable()) {
|
|
|
|
if (!Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
|
|
|
|
;
|
|
|
|
// Skip the last annot_pragma_openmp_end.
|
|
|
|
(void)ConsumeAnnotationToken();
|
2019-09-18 16:24:31 +00:00
|
|
|
return;
|
2019-09-13 20:18:17 +00:00
|
|
|
}
|
|
|
|
|
2024-04-16 16:36:53 +04:00
|
|
|
OMPTraitInfo *ParentTI =
|
|
|
|
Actions.OpenMP().getOMPTraitInfoForSurroundingScope();
|
2020-08-13 01:05:51 -05:00
|
|
|
ASTContext &ASTCtx = Actions.getASTContext();
|
|
|
|
OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
|
2021-10-12 14:55:00 -07:00
|
|
|
SmallVector<Expr *, 6> AdjustNothing;
|
|
|
|
SmallVector<Expr *, 6> AdjustNeedDevicePtr;
|
2022-08-19 16:44:55 -07:00
|
|
|
SmallVector<OMPInteropInfo, 3> AppendArgs;
|
2021-10-14 14:28:51 -07:00
|
|
|
SourceLocation AdjustArgsLoc, AppendArgsLoc;
|
2021-10-12 14:55:00 -07:00
|
|
|
|
|
|
|
// At least one clause is required.
|
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
|
|
|
|
<< (getLangOpts().OpenMP < 51 ? 0 : 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsError = false;
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
OpenMPClauseKind CKind = Tok.isAnnotation()
|
|
|
|
? OMPC_unknown
|
|
|
|
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
|
|
|
if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind,
|
|
|
|
getLangOpts().OpenMP)) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
|
|
|
|
<< (getLangOpts().OpenMP < 51 ? 0 : 1);
|
|
|
|
IsError = true;
|
|
|
|
}
|
|
|
|
if (!IsError) {
|
|
|
|
switch (CKind) {
|
|
|
|
case OMPC_match:
|
|
|
|
IsError = parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI);
|
|
|
|
break;
|
|
|
|
case OMPC_adjust_args: {
|
2021-10-14 14:28:51 -07:00
|
|
|
AdjustArgsLoc = Tok.getLocation();
|
2021-10-12 14:55:00 -07:00
|
|
|
ConsumeToken();
|
2024-04-16 16:36:53 +04:00
|
|
|
SemaOpenMP::OpenMPVarListDataTy Data;
|
2021-10-12 14:55:00 -07:00
|
|
|
SmallVector<Expr *> Vars;
|
|
|
|
IsError = ParseOpenMPVarList(OMPD_declare_variant, OMPC_adjust_args,
|
|
|
|
Vars, Data);
|
|
|
|
if (!IsError)
|
|
|
|
llvm::append_range(Data.ExtraModifier == OMPC_ADJUST_ARGS_nothing
|
|
|
|
? AdjustNothing
|
|
|
|
: AdjustNeedDevicePtr,
|
|
|
|
Vars);
|
|
|
|
break;
|
|
|
|
}
|
2021-10-14 14:28:51 -07:00
|
|
|
case OMPC_append_args:
|
|
|
|
if (!AppendArgs.empty()) {
|
|
|
|
Diag(AppendArgsLoc, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(OMPD_declare_variant)
|
|
|
|
<< getOpenMPClauseName(CKind) << 0;
|
|
|
|
IsError = true;
|
|
|
|
}
|
|
|
|
if (!IsError) {
|
|
|
|
AppendArgsLoc = Tok.getLocation();
|
|
|
|
ConsumeToken();
|
|
|
|
IsError = parseOpenMPAppendArgs(AppendArgs);
|
|
|
|
}
|
|
|
|
break;
|
2021-10-12 14:55:00 -07:00
|
|
|
default:
|
|
|
|
llvm_unreachable("Unexpected clause for declare variant.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (IsError) {
|
|
|
|
while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
|
|
|
|
;
|
|
|
|
// Skip the last annot_pragma_openmp_end.
|
|
|
|
(void)ConsumeAnnotationToken();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Skip ',' if any.
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
|
|
|
}
|
2020-02-20 19:50:47 -06:00
|
|
|
|
2023-01-14 12:31:01 -08:00
|
|
|
std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().checkOpenMPDeclareVariantFunction(
|
2021-10-14 14:28:51 -07:00
|
|
|
Ptr, AssociatedFunction.get(), TI, AppendArgs.size(),
|
2020-02-20 19:50:47 -06:00
|
|
|
SourceRange(Loc, Tok.getLocation()));
|
|
|
|
|
|
|
|
if (DeclVarData && !TI.Sets.empty())
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().ActOnOpenMPDeclareVariantDirective(
|
2021-10-12 14:55:00 -07:00
|
|
|
DeclVarData->first, DeclVarData->second, TI, AdjustNothing,
|
2021-10-14 14:28:51 -07:00
|
|
|
AdjustNeedDevicePtr, AppendArgs, AdjustArgsLoc, AppendArgsLoc,
|
|
|
|
SourceRange(Loc, Tok.getLocation()));
|
2020-02-20 19:50:47 -06:00
|
|
|
|
|
|
|
// Skip the last annot_pragma_openmp_end.
|
|
|
|
(void)ConsumeAnnotationToken();
|
|
|
|
}
|
|
|
|
|
2021-10-14 14:28:51 -07:00
|
|
|
bool Parser::parseOpenMPAppendArgs(
|
2022-08-19 16:44:55 -07:00
|
|
|
SmallVectorImpl<OMPInteropInfo> &InteropInfos) {
|
2021-10-14 14:28:51 -07:00
|
|
|
bool HasError = false;
|
|
|
|
// Parse '('.
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
|
|
|
getOpenMPClauseName(OMPC_append_args).data()))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Parse the list of append-ops, each is;
|
|
|
|
// interop(interop-type[,interop-type]...)
|
|
|
|
while (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("interop")) {
|
|
|
|
ConsumeToken();
|
|
|
|
BalancedDelimiterTracker IT(*this, tok::l_paren,
|
|
|
|
tok::annot_pragma_openmp_end);
|
|
|
|
if (IT.expectAndConsume(diag::err_expected_lparen_after, "interop"))
|
|
|
|
return true;
|
|
|
|
|
2022-08-18 11:54:52 -07:00
|
|
|
OMPInteropInfo InteropInfo;
|
2022-08-19 16:44:55 -07:00
|
|
|
if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args))
|
2021-10-14 14:28:51 -07:00
|
|
|
HasError = true;
|
2022-08-19 16:44:55 -07:00
|
|
|
else
|
|
|
|
InteropInfos.push_back(InteropInfo);
|
2021-10-14 14:28:51 -07:00
|
|
|
|
|
|
|
IT.consumeClose();
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
|
|
|
}
|
2022-08-19 16:44:55 -07:00
|
|
|
if (!HasError && InteropInfos.empty()) {
|
2021-10-14 14:28:51 -07:00
|
|
|
HasError = true;
|
|
|
|
Diag(Tok.getLocation(), diag::err_omp_unexpected_append_op);
|
|
|
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
}
|
|
|
|
HasError = T.consumeClose() || HasError;
|
|
|
|
return HasError;
|
|
|
|
}
|
|
|
|
|
2020-02-20 19:50:47 -06:00
|
|
|
bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
|
2020-08-13 01:05:51 -05:00
|
|
|
OMPTraitInfo &TI,
|
|
|
|
OMPTraitInfo *ParentTI) {
|
2019-09-18 16:24:31 +00:00
|
|
|
// Parse 'match'.
|
2019-09-23 18:13:31 +00:00
|
|
|
OpenMPClauseKind CKind = Tok.isAnnotation()
|
|
|
|
? OMPC_unknown
|
|
|
|
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
|
|
|
if (CKind != OMPC_match) {
|
2019-09-18 16:24:31 +00:00
|
|
|
Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
|
2021-10-12 14:55:00 -07:00
|
|
|
<< (getLangOpts().OpenMP < 51 ? 0 : 1);
|
2020-02-20 19:50:47 -06:00
|
|
|
return true;
|
2019-09-13 20:18:17 +00:00
|
|
|
}
|
2019-09-18 16:24:31 +00:00
|
|
|
(void)ConsumeToken();
|
|
|
|
// Parse '('.
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
2019-09-23 18:13:31 +00:00
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
2021-10-12 14:55:00 -07:00
|
|
|
getOpenMPClauseName(OMPC_match).data()))
|
2020-02-20 19:50:47 -06:00
|
|
|
return true;
|
2019-09-18 16:24:31 +00:00
|
|
|
|
|
|
|
// Parse inner context selectors.
|
2020-02-15 18:07:42 -06:00
|
|
|
parseOMPContextSelectors(Loc, TI);
|
[OpenMP][Part 2] Use reusable OpenMP context/traits handling
This patch implements an almost complete handling of OpenMP
contexts/traits such that we can reuse most of the logic in Flang
through the OMPContext.{h,cpp} in llvm/Frontend/OpenMP.
All but construct SIMD specifiers, e.g., inbranch, and the device ISA
selector are define in `llvm/lib/Frontend/OpenMP/OMPKinds.def`. From
these definitions we generate the enum classes `TraitSet`,
`TraitSelector`, and `TraitProperty` as well as conversion and helper
functions in `llvm/lib/Frontend/OpenMP/OMPContext.{h,cpp}`.
The above enum classes are used in the parser, sema, and the AST
attribute. The latter is not a collection of multiple primitive variant
arguments that contain encodings via numbers and strings but instead a
tree that mirrors the `match` clause (see `struct OpenMPTraitInfo`).
The changes to the parser make it more forgiving when wrong syntax is
read and they also resulted in more specialized diagnostics. The tests
are updated and the core issues are detected as before. Here and
elsewhere this patch tries to be generic, thus we do not distinguish
what selector set, selector, or property is parsed except if they do
behave exceptionally, as for example `user={condition(EXPR)}` does.
The sema logic changed in two ways: First, the OMPDeclareVariantAttr
representation changed, as mentioned above, and the sema was adjusted to
work with the new `OpenMPTraitInfo`. Second, the matching and scoring
logic moved into `OMPContext.{h,cpp}`. It is implemented on a flat
representation of the `match` clause that is not tied to clang.
`OpenMPTraitInfo` provides a method to generate this flat structure (see
`struct VariantMatchInfo`) by computing integer score values and boolean
user conditions from the `clang::Expr` we keep for them.
The OpenMP context is now an explicit object (see `struct OMPContext`).
This is in anticipation of construct traits that need to be tracked. The
OpenMP context, as well as the `VariantMatchInfo`, are basically made up
of a set of active or respectively required traits, e.g., 'host', and an
ordered container of constructs which allows duplication. Matching and
scoring is kept as generic as possible to allow easy extension in the
future.
---
Test changes:
The messages checked in `OpenMP/declare_variant_messages.{c,cpp}` have
been auto generated to match the new warnings and notes of the parser.
The "subset" checks were reversed causing the wrong version to be
picked. The tests have been adjusted to correct this.
We do not print scores if the user did not provide one.
We print spaces to make lists in the `match` clause more legible.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: merge_guards_bot, rampitec, mgorny, hiraditya, aheejin, fedor.sergeev, simoncook, bollu, guansong, dexonsmith, jfb, s.egerton, llvm-commits, cfe-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71830
2019-12-19 20:42:12 -06:00
|
|
|
|
|
|
|
// Parse ')'
|
|
|
|
(void)T.consumeClose();
|
2020-08-13 01:05:51 -05:00
|
|
|
|
|
|
|
if (!ParentTI)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Merge the parent/outer trait info into the one we just parsed and diagnose
|
2021-03-11 23:47:10 -06:00
|
|
|
// problems.
|
2020-08-13 01:05:51 -05:00
|
|
|
// TODO: Keep some source location in the TI to provide better diagnostics.
|
|
|
|
// TODO: Perform some kind of equivalence check on the condition and score
|
|
|
|
// expressions.
|
2021-03-11 23:47:19 -06:00
|
|
|
for (const OMPTraitSet &ParentSet : ParentTI->Sets) {
|
2020-08-13 01:05:51 -05:00
|
|
|
bool MergedSet = false;
|
|
|
|
for (OMPTraitSet &Set : TI.Sets) {
|
|
|
|
if (Set.Kind != ParentSet.Kind)
|
|
|
|
continue;
|
|
|
|
MergedSet = true;
|
|
|
|
for (const OMPTraitSelector &ParentSelector : ParentSet.Selectors) {
|
|
|
|
bool MergedSelector = false;
|
|
|
|
for (OMPTraitSelector &Selector : Set.Selectors) {
|
|
|
|
if (Selector.Kind != ParentSelector.Kind)
|
|
|
|
continue;
|
|
|
|
MergedSelector = true;
|
|
|
|
for (const OMPTraitProperty &ParentProperty :
|
|
|
|
ParentSelector.Properties) {
|
|
|
|
bool MergedProperty = false;
|
|
|
|
for (OMPTraitProperty &Property : Selector.Properties) {
|
|
|
|
// Ignore "equivalent" properties.
|
|
|
|
if (Property.Kind != ParentProperty.Kind)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// If the kind is the same but the raw string not, we don't want
|
|
|
|
// to skip out on the property.
|
|
|
|
MergedProperty |= Property.RawString == ParentProperty.RawString;
|
|
|
|
|
|
|
|
if (Property.RawString == ParentProperty.RawString &&
|
|
|
|
Selector.ScoreOrCondition == ParentSelector.ScoreOrCondition)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (Selector.Kind == llvm::omp::TraitSelector::user_condition) {
|
|
|
|
Diag(Loc, diag::err_omp_declare_variant_nested_user_condition);
|
|
|
|
} else if (Selector.ScoreOrCondition !=
|
|
|
|
ParentSelector.ScoreOrCondition) {
|
|
|
|
Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait)
|
|
|
|
<< getOpenMPContextTraitPropertyName(
|
|
|
|
ParentProperty.Kind, ParentProperty.RawString)
|
|
|
|
<< getOpenMPContextTraitSelectorName(ParentSelector.Kind)
|
|
|
|
<< getOpenMPContextTraitSetName(ParentSet.Kind);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!MergedProperty)
|
|
|
|
Selector.Properties.push_back(ParentProperty);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!MergedSelector)
|
|
|
|
Set.Selectors.push_back(ParentSelector);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!MergedSet)
|
|
|
|
TI.Sets.push_back(ParentSet);
|
|
|
|
}
|
|
|
|
|
2020-02-20 19:50:47 -06:00
|
|
|
return false;
|
2019-09-13 20:18:17 +00:00
|
|
|
}
|
|
|
|
|
2022-11-10 18:12:35 -08:00
|
|
|
/// <clause> [clause[ [,] clause] ... ]
|
|
|
|
///
|
|
|
|
/// clauses: for error directive
|
|
|
|
/// 'at' '(' compilation | execution ')'
|
|
|
|
/// 'severity' '(' fatal | warning ')'
|
|
|
|
/// 'message' '(' msg-string ')'
|
|
|
|
/// ....
|
|
|
|
void Parser::ParseOpenMPClauses(OpenMPDirectiveKind DKind,
|
|
|
|
SmallVectorImpl<OMPClause *> &Clauses,
|
|
|
|
SourceLocation Loc) {
|
2024-05-30 14:49:13 -05:00
|
|
|
std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
|
2022-11-10 18:12:35 -08:00
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
OpenMPClauseKind CKind = Tok.isAnnotation()
|
|
|
|
? OMPC_unknown
|
|
|
|
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().StartOpenMPClause(CKind);
|
2024-05-30 14:49:13 -05:00
|
|
|
OMPClause *Clause =
|
|
|
|
ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
|
2022-11-10 18:12:35 -08:00
|
|
|
SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
2024-05-30 14:49:13 -05:00
|
|
|
SeenClauses[unsigned(CKind)] = true;
|
2022-11-10 18:12:35 -08:00
|
|
|
if (Clause != nullptr)
|
|
|
|
Clauses.push_back(Clause);
|
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end)) {
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().EndOpenMPClause();
|
2022-11-10 18:12:35 -08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Skip ',' if any.
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().EndOpenMPClause();
|
2022-11-10 18:12:35 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-23 11:48:59 -06:00
|
|
|
/// `omp assumes` or `omp begin/end assumes` <clause> [[,]<clause>]...
|
|
|
|
/// where
|
|
|
|
///
|
|
|
|
/// clause:
|
|
|
|
/// 'ext_IMPL_DEFINED'
|
|
|
|
/// 'absent' '(' directive-name [, directive-name]* ')'
|
|
|
|
/// 'contains' '(' directive-name [, directive-name]* ')'
|
|
|
|
/// 'holds' '(' scalar-expression ')'
|
|
|
|
/// 'no_openmp'
|
|
|
|
/// 'no_openmp_routines'
|
2025-02-06 12:41:10 -08:00
|
|
|
/// 'no_openmp_constructs' (OpenMP 6.0)
|
2020-11-23 11:48:59 -06:00
|
|
|
/// 'no_parallelism'
|
|
|
|
///
|
|
|
|
void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
|
|
|
|
SourceLocation Loc) {
|
2021-07-13 15:35:58 -05:00
|
|
|
SmallVector<std::string, 4> Assumptions;
|
2020-11-23 11:48:59 -06:00
|
|
|
bool SkippedClauses = false;
|
|
|
|
|
|
|
|
auto SkipBraces = [&](llvm::StringRef Spelling, bool IssueNote) {
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren,
|
|
|
|
tok::annot_pragma_openmp_end);
|
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after, Spelling.data()))
|
|
|
|
return;
|
|
|
|
T.skipToEnd();
|
|
|
|
if (IssueNote && T.getCloseLocation().isValid())
|
|
|
|
Diag(T.getCloseLocation(),
|
|
|
|
diag::note_omp_assumption_clause_continue_here);
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Helper to determine which AssumptionClauseMapping (ACM) in the
|
|
|
|
/// AssumptionClauseMappings table matches \p RawString. The return value is
|
|
|
|
/// the index of the matching ACM into the table or -1 if there was no match.
|
|
|
|
auto MatchACMClause = [&](StringRef RawString) {
|
|
|
|
llvm::StringSwitch<int> SS(RawString);
|
|
|
|
unsigned ACMIdx = 0;
|
|
|
|
for (const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) {
|
|
|
|
if (ACMI.StartsWith)
|
|
|
|
SS.StartsWith(ACMI.Identifier, ACMIdx++);
|
|
|
|
else
|
|
|
|
SS.Case(ACMI.Identifier, ACMIdx++);
|
|
|
|
}
|
|
|
|
return SS.Default(-1);
|
|
|
|
};
|
|
|
|
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
IdentifierInfo *II = nullptr;
|
|
|
|
SourceLocation StartLoc = Tok.getLocation();
|
|
|
|
int Idx = -1;
|
|
|
|
if (Tok.isAnyIdentifier()) {
|
|
|
|
II = Tok.getIdentifierInfo();
|
|
|
|
Idx = MatchACMClause(II->getName());
|
|
|
|
}
|
|
|
|
ConsumeAnyToken();
|
|
|
|
|
|
|
|
bool NextIsLPar = Tok.is(tok::l_paren);
|
|
|
|
// Handle unknown clauses by skipping them.
|
|
|
|
if (Idx == -1) {
|
|
|
|
Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id)
|
|
|
|
<< llvm::omp::getOpenMPDirectiveName(DKind)
|
|
|
|
<< llvm::omp::getAllAssumeClauseOptions() << NextIsLPar;
|
|
|
|
if (NextIsLPar)
|
|
|
|
SkipBraces(II ? II->getName() : "", /* IssueNote */ true);
|
|
|
|
SkippedClauses = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx];
|
|
|
|
if (ACMI.HasDirectiveList || ACMI.HasExpression) {
|
|
|
|
// TODO: We ignore absent, contains, and holds assumptions for now. We
|
|
|
|
// also do not verify the content in the parenthesis at all.
|
|
|
|
SkippedClauses = true;
|
|
|
|
SkipBraces(II->getName(), /* IssueNote */ false);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NextIsLPar) {
|
|
|
|
Diag(Tok.getLocation(),
|
|
|
|
diag::warn_omp_unknown_assumption_clause_without_args)
|
|
|
|
<< II;
|
|
|
|
SkipBraces(II->getName(), /* IssueNote */ true);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(II && "Expected an identifier clause!");
|
2021-07-13 15:35:58 -05:00
|
|
|
std::string Assumption = II->getName().str();
|
2020-11-23 11:48:59 -06:00
|
|
|
if (ACMI.StartsWith)
|
2021-07-13 15:35:58 -05:00
|
|
|
Assumption = "ompx_" + Assumption.substr(ACMI.Identifier.size());
|
|
|
|
else
|
|
|
|
Assumption = "omp_" + Assumption;
|
2020-11-23 11:48:59 -06:00
|
|
|
Assumptions.push_back(Assumption);
|
|
|
|
}
|
|
|
|
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().ActOnOpenMPAssumesDirective(Loc, DKind, Assumptions,
|
|
|
|
SkippedClauses);
|
2020-11-23 11:48:59 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) {
|
2024-04-16 16:36:53 +04:00
|
|
|
if (Actions.OpenMP().isInOpenMPAssumeScope())
|
|
|
|
Actions.OpenMP().ActOnOpenMPEndAssumesDirective();
|
2020-11-23 11:48:59 -06:00
|
|
|
else
|
|
|
|
Diag(Loc, diag::err_expected_begin_assumes);
|
|
|
|
}
|
|
|
|
|
2019-08-23 16:11:14 +00:00
|
|
|
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
|
|
|
|
///
|
|
|
|
/// default-clause:
|
2022-05-17 14:17:32 -07:00
|
|
|
/// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ')
|
2019-08-23 16:11:14 +00:00
|
|
|
///
|
|
|
|
/// proc_bind-clause:
|
|
|
|
/// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
|
|
|
|
///
|
|
|
|
/// device_type-clause:
|
|
|
|
/// 'device_type' '(' 'host' | 'nohost' | 'any' )'
|
|
|
|
namespace {
|
2020-10-29 18:44:28 -05:00
|
|
|
struct SimpleClauseData {
|
|
|
|
unsigned Type;
|
|
|
|
SourceLocation Loc;
|
|
|
|
SourceLocation LOpen;
|
|
|
|
SourceLocation TypeLoc;
|
|
|
|
SourceLocation RLoc;
|
|
|
|
SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,
|
|
|
|
SourceLocation TypeLoc, SourceLocation RLoc)
|
|
|
|
: Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
|
|
|
|
};
|
2019-08-23 16:11:14 +00:00
|
|
|
} // anonymous namespace
|
|
|
|
|
2023-01-14 12:31:01 -08:00
|
|
|
static std::optional<SimpleClauseData>
|
2019-08-23 16:11:14 +00:00
|
|
|
parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
|
|
|
|
const Token &Tok = P.getCurToken();
|
|
|
|
SourceLocation Loc = Tok.getLocation();
|
|
|
|
SourceLocation LOpen = P.ConsumeToken();
|
|
|
|
// Parse '('.
|
|
|
|
BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
|
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
2020-03-30 19:58:40 -05:00
|
|
|
getOpenMPClauseName(Kind).data()))
|
2022-12-03 11:54:46 -08:00
|
|
|
return std::nullopt;
|
2019-08-23 16:11:14 +00:00
|
|
|
|
|
|
|
unsigned Type = getOpenMPSimpleClauseType(
|
2020-07-22 10:14:00 -04:00
|
|
|
Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok),
|
[OpenMP][OpenACC] Implement `ompx_hold` map type modifier extension in Clang (1/2)
This patch implements Clang support for an original OpenMP extension
we have developed to support OpenACC: the `ompx_hold` map type
modifier. The next patch in this series, D106510, implements OpenMP
runtime support.
Consider the following example:
```
#pragma omp target data map(ompx_hold, tofrom: x) // holds onto mapping of x
{
foo(); // might have map(delete: x)
#pragma omp target map(present, alloc: x) // x is guaranteed to be present
printf("%d\n", x);
}
```
The `ompx_hold` map type modifier above specifies that the `target
data` directive holds onto the mapping for `x` throughout the
associated region regardless of any `target exit data` directives
executed during the call to `foo`. Thus, the presence assertion for
`x` at the enclosed `target` construct cannot fail. (As usual, the
standard OpenMP reference count for `x` must also reach zero before
the data is unmapped.)
Justification for inclusion in Clang and LLVM's OpenMP runtime:
* The `ompx_hold` modifier supports OpenACC functionality (structured
reference count) that cannot be achieved in standard OpenMP, as of
5.1.
* The runtime implementation for `ompx_hold` (next patch) will thus be
used by Flang's OpenACC support.
* The Clang implementation for `ompx_hold` (this patch) as well as the
runtime implementation are required for the Clang OpenACC support
being developed as part of the ECP Clacc project, which translates
OpenACC to OpenMP at the directive AST level. These patches are the
first step in upstreaming OpenACC functionality from Clacc.
* The Clang implementation for `ompx_hold` is also used by the tests
in the runtime implementation. That syntactic support makes the
tests more readable than low-level runtime calls can. Moreover,
upstream Flang and Clang do not yet support OpenACC syntax
sufficiently for writing the tests.
* More generally, the Clang implementation enables a clean separation
of concerns between OpenACC and OpenMP development in LLVM. That
is, LLVM's OpenMP developers can discuss, modify, and debug LLVM's
extended OpenMP implementation and test suite without directly
considering OpenACC's language and execution model, which can be
handled by LLVM's OpenACC developers.
* OpenMP users might find the `ompx_hold` modifier useful, as in the
above example.
See new documentation introduced by this patch in `openmp/docs` for
more detail on the functionality of this extension and its
relationship with OpenACC. For example, it explains how the runtime
must support two reference counts, as specified by OpenACC.
Clang recognizes `ompx_hold` unless `-fno-openmp-extensions`, a new
command-line option introduced by this patch, is specified.
Reviewed By: ABataev, jdoerfert, protze.joachim, grokos
Differential Revision: https://reviews.llvm.org/D106509
2021-08-31 15:17:07 -04:00
|
|
|
P.getLangOpts());
|
2019-08-23 16:11:14 +00:00
|
|
|
SourceLocation TypeLoc = Tok.getLocation();
|
|
|
|
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
P.ConsumeAnyToken();
|
|
|
|
|
|
|
|
// Parse ')'.
|
|
|
|
SourceLocation RLoc = Tok.getLocation();
|
|
|
|
if (!T.consumeClose())
|
|
|
|
RLoc = T.getCloseLocation();
|
|
|
|
|
|
|
|
return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
|
|
|
|
}
|
|
|
|
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
void Parser::ParseOMPDeclareTargetClauses(
|
2024-04-16 16:36:53 +04:00
|
|
|
SemaOpenMP::DeclareTargetContextInfo &DTCI) {
|
2019-08-23 16:11:14 +00:00
|
|
|
SourceLocation DeviceTypeLoc;
|
2022-01-10 16:20:02 -08:00
|
|
|
bool RequiresToOrLinkOrIndirectClause = false;
|
|
|
|
bool HasToOrLinkOrIndirectClause = false;
|
2018-11-21 20:15:57 +00:00
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
bool HasIdentifier = Tok.is(tok::identifier);
|
|
|
|
if (HasIdentifier) {
|
|
|
|
// If we see any clause we need a to or link clause.
|
2022-01-10 16:20:02 -08:00
|
|
|
RequiresToOrLinkOrIndirectClause = true;
|
2018-11-21 20:15:57 +00:00
|
|
|
IdentifierInfo *II = Tok.getIdentifierInfo();
|
|
|
|
StringRef ClauseName = II->getName();
|
2019-08-23 16:11:14 +00:00
|
|
|
bool IsDeviceTypeClause =
|
|
|
|
getLangOpts().OpenMP >= 50 &&
|
|
|
|
getOpenMPClauseKind(ClauseName) == OMPC_device_type;
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
|
2022-01-10 16:20:02 -08:00
|
|
|
bool IsIndirectClause = getLangOpts().OpenMP >= 51 &&
|
|
|
|
getOpenMPClauseKind(ClauseName) == OMPC_indirect;
|
2022-06-20 10:51:34 -07:00
|
|
|
if (DTCI.Indirect && IsIndirectClause) {
|
2022-01-10 16:20:02 -08:00
|
|
|
Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(OMPD_declare_target)
|
|
|
|
<< getOpenMPClauseName(OMPC_indirect) << 0;
|
|
|
|
break;
|
|
|
|
}
|
2022-11-16 17:23:48 -06:00
|
|
|
bool IsToEnterOrLinkClause =
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
|
2022-11-16 17:23:48 -06:00
|
|
|
assert((!IsDeviceTypeClause || !IsToEnterOrLinkClause) &&
|
|
|
|
"Cannot be both!");
|
|
|
|
|
|
|
|
// Starting with OpenMP 5.2 the `to` clause has been replaced by the
|
|
|
|
// `enter` clause.
|
|
|
|
if (getLangOpts().OpenMP >= 52 && ClauseName == "to") {
|
|
|
|
Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (getLangOpts().OpenMP <= 51 && ClauseName == "enter") {
|
|
|
|
Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause);
|
|
|
|
break;
|
|
|
|
}
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
|
2022-01-10 16:20:02 -08:00
|
|
|
if (!IsDeviceTypeClause && !IsIndirectClause &&
|
|
|
|
DTCI.Kind == OMPD_begin_declare_target) {
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
|
2022-01-10 16:20:02 -08:00
|
|
|
<< ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0);
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
break;
|
|
|
|
}
|
2022-11-16 17:23:48 -06:00
|
|
|
if (!IsDeviceTypeClause && !IsToEnterOrLinkClause && !IsIndirectClause) {
|
|
|
|
Diag(Tok, getLangOpts().OpenMP >= 52
|
|
|
|
? diag::err_omp_declare_target_unexpected_clause_52
|
|
|
|
: diag::err_omp_declare_target_unexpected_clause)
|
2022-01-10 16:20:02 -08:00
|
|
|
<< ClauseName
|
2022-11-16 17:23:48 -06:00
|
|
|
<< (getLangOpts().OpenMP >= 51
|
|
|
|
? 4
|
|
|
|
: getLangOpts().OpenMP >= 50 ? 2 : 1);
|
2018-11-21 20:15:57 +00:00
|
|
|
break;
|
|
|
|
}
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
|
2022-11-16 17:23:48 -06:00
|
|
|
if (IsToEnterOrLinkClause || IsIndirectClause)
|
2022-01-10 16:20:02 -08:00
|
|
|
HasToOrLinkOrIndirectClause = true;
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
|
2022-01-10 16:20:02 -08:00
|
|
|
if (IsIndirectClause) {
|
|
|
|
if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false))
|
|
|
|
break;
|
|
|
|
continue;
|
|
|
|
}
|
2019-08-23 16:11:14 +00:00
|
|
|
// Parse 'device_type' clause and go to next clause if any.
|
|
|
|
if (IsDeviceTypeClause) {
|
2023-01-14 12:31:01 -08:00
|
|
|
std::optional<SimpleClauseData> DevTypeData =
|
2019-08-23 16:11:14 +00:00
|
|
|
parseOpenMPSimpleClause(*this, OMPC_device_type);
|
2022-06-25 22:26:24 -07:00
|
|
|
if (DevTypeData) {
|
2019-08-23 16:11:14 +00:00
|
|
|
if (DeviceTypeLoc.isValid()) {
|
|
|
|
// We already saw another device_type clause, diagnose it.
|
2022-12-17 06:37:59 +00:00
|
|
|
Diag(DevTypeData->Loc,
|
2022-06-25 11:56:50 -07:00
|
|
|
diag::warn_omp_more_one_device_type_clause);
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
break;
|
2019-08-23 16:11:14 +00:00
|
|
|
}
|
2022-12-17 06:37:59 +00:00
|
|
|
switch (static_cast<OpenMPDeviceType>(DevTypeData->Type)) {
|
2019-08-23 16:11:14 +00:00
|
|
|
case OMPC_DEVICE_TYPE_any:
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;
|
2019-08-23 16:11:14 +00:00
|
|
|
break;
|
|
|
|
case OMPC_DEVICE_TYPE_host:
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host;
|
2019-08-23 16:11:14 +00:00
|
|
|
break;
|
|
|
|
case OMPC_DEVICE_TYPE_nohost:
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost;
|
2019-08-23 16:11:14 +00:00
|
|
|
break;
|
|
|
|
case OMPC_DEVICE_TYPE_unknown:
|
|
|
|
llvm_unreachable("Unexpected device_type");
|
|
|
|
}
|
2022-06-20 22:59:26 -07:00
|
|
|
DeviceTypeLoc = DevTypeData->Loc;
|
2019-08-23 16:11:14 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2018-11-21 20:15:57 +00:00
|
|
|
ConsumeToken();
|
|
|
|
}
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
|
|
|
|
if (DTCI.Kind == OMPD_declare_target || HasIdentifier) {
|
|
|
|
auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS,
|
|
|
|
DeclarationNameInfo NameInfo) {
|
2024-04-16 16:36:53 +04:00
|
|
|
NamedDecl *ND = Actions.OpenMP().lookupOpenMPDeclareTargetName(
|
|
|
|
getCurScope(), SS, NameInfo);
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
if (!ND)
|
|
|
|
return;
|
2024-04-16 16:36:53 +04:00
|
|
|
SemaOpenMP::DeclareTargetContextInfo::MapInfo MI{MT, NameInfo.getLoc()};
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second;
|
|
|
|
if (!FirstMapping)
|
|
|
|
Diag(NameInfo.getLoc(), diag::err_omp_declare_target_multiple)
|
|
|
|
<< NameInfo.getName();
|
|
|
|
};
|
|
|
|
if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
|
|
|
|
/*AllowScopeSpecifier=*/true))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Tok.is(tok::l_paren)) {
|
|
|
|
Diag(Tok,
|
|
|
|
diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok,
|
2022-11-16 17:23:48 -06:00
|
|
|
getLangOpts().OpenMP >= 52
|
|
|
|
? diag::err_omp_declare_target_wrong_clause_after_implicit_enter
|
|
|
|
: diag::err_omp_declare_target_wrong_clause_after_implicit_to);
|
2018-11-21 20:15:57 +00:00
|
|
|
break;
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
}
|
2018-11-21 20:15:57 +00:00
|
|
|
|
|
|
|
// Consume optional ','.
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
|
|
|
}
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
|
2022-06-20 10:51:34 -07:00
|
|
|
if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any)
|
2022-01-10 16:20:02 -08:00
|
|
|
Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);
|
|
|
|
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
// For declare target require at least 'to' or 'link' to be present.
|
2022-01-10 16:20:02 -08:00
|
|
|
if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause &&
|
|
|
|
!HasToOrLinkOrIndirectClause)
|
2022-11-16 17:23:48 -06:00
|
|
|
Diag(DTCI.Loc,
|
|
|
|
getLangOpts().OpenMP >= 52
|
|
|
|
? diag::err_omp_declare_target_missing_enter_or_link_clause
|
|
|
|
: diag::err_omp_declare_target_missing_to_or_link_clause)
|
2022-01-10 16:20:02 -08:00
|
|
|
<< (getLangOpts().OpenMP >= 51 ? 1 : 0);
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
|
2018-11-21 20:15:57 +00:00
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
|
|
|
}
|
|
|
|
|
2020-02-21 13:48:56 -06:00
|
|
|
void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) {
|
|
|
|
// The last seen token is annot_pragma_openmp_end - need to check for
|
|
|
|
// extra tokens.
|
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
return;
|
|
|
|
|
|
|
|
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
|
|
|
|
<< getOpenMPDirectiveName(DKind);
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
}
|
|
|
|
|
2020-02-20 19:50:47 -06:00
|
|
|
void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind,
|
|
|
|
OpenMPDirectiveKind ExpectedKind,
|
|
|
|
OpenMPDirectiveKind FoundKind,
|
|
|
|
SourceLocation BeginLoc,
|
|
|
|
SourceLocation FoundLoc,
|
|
|
|
bool SkipUntilOpenMPEnd) {
|
|
|
|
int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;
|
|
|
|
|
|
|
|
if (FoundKind == ExpectedKind) {
|
|
|
|
ConsumeAnyToken();
|
|
|
|
skipUntilPragmaOpenMPEnd(ExpectedKind);
|
2018-11-21 20:15:57 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-02-20 19:50:47 -06:00
|
|
|
|
|
|
|
Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)
|
|
|
|
<< DiagSelection;
|
|
|
|
Diag(BeginLoc, diag::note_matching)
|
|
|
|
<< ("'#pragma omp " + getOpenMPDirectiveName(BeginKind) + "'").str();
|
|
|
|
if (SkipUntilOpenMPEnd)
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
|
|
|
}
|
|
|
|
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,
|
|
|
|
OpenMPDirectiveKind EndDKind,
|
2020-02-20 19:50:47 -06:00
|
|
|
SourceLocation DKLoc) {
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,
|
|
|
|
Tok.getLocation(),
|
2020-02-20 19:50:47 -06:00
|
|
|
/* SkipUntilOpenMPEnd */ false);
|
2018-11-21 20:15:57 +00:00
|
|
|
// Skip the last annot_pragma_openmp_end.
|
2020-02-20 19:50:47 -06:00
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnnotationToken();
|
2018-11-21 20:15:57 +00:00
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Parsing of declarative OpenMP directives.
|
2013-05-13 04:18:18 +00:00
|
|
|
///
|
|
|
|
/// threadprivate-directive:
|
|
|
|
/// annot_pragma_openmp 'threadprivate' simple-variable-list
|
2016-03-03 05:21:39 +00:00
|
|
|
/// annot_pragma_openmp_end
|
2013-03-22 06:34:35 +00:00
|
|
|
///
|
2019-03-07 17:54:44 +00:00
|
|
|
/// allocate-directive:
|
2019-03-12 18:52:33 +00:00
|
|
|
/// annot_pragma_openmp 'allocate' simple-variable-list [<clause>]
|
2019-03-07 17:54:44 +00:00
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
///
|
2016-03-03 05:21:39 +00:00
|
|
|
/// declare-reduction-directive:
|
|
|
|
/// annot_pragma_openmp 'declare' 'reduction' [...]
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
///
|
2019-02-01 20:25:04 +00:00
|
|
|
/// declare-mapper-directive:
|
|
|
|
/// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
|
|
|
|
/// <type> <var> ')' [<clause>[[,] <clause>] ... ]
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
///
|
2016-03-30 10:43:55 +00:00
|
|
|
/// declare-simd-directive:
|
|
|
|
/// annot_pragma_openmp 'declare simd' {<clause> [,]}
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
/// <function declaration/definition>
|
|
|
|
///
|
2018-09-26 04:28:39 +00:00
|
|
|
/// requires directive:
|
|
|
|
/// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ]
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
///
|
2020-11-23 11:48:59 -06:00
|
|
|
/// assumes directive:
|
|
|
|
/// annot_pragma_openmp 'assumes' <clause> [[[,] <clause>] ... ]
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
/// or
|
|
|
|
/// annot_pragma_openmp 'begin assumes' <clause> [[[,] <clause>] ... ]
|
|
|
|
/// annot_pragma_openmp 'end assumes'
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
///
|
2016-03-30 10:43:55 +00:00
|
|
|
Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
|
2022-03-22 09:27:27 +01:00
|
|
|
AccessSpecifier &AS, ParsedAttributes &Attrs, bool Delayed,
|
2016-03-30 10:43:55 +00:00
|
|
|
DeclSpec::TST TagType, Decl *Tag) {
|
2021-07-12 06:51:19 -04:00
|
|
|
assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
|
|
|
|
"Not an OpenMP directive!");
|
2019-12-13 16:05:30 -05:00
|
|
|
ParsingOpenMPDirectiveRAII DirScope(*this);
|
2013-11-18 08:17:37 +00:00
|
|
|
ParenBraceBracketBalancer BalancerRAIIObj(*this);
|
2013-03-22 06:34:35 +00:00
|
|
|
|
2020-01-07 13:39:18 -05:00
|
|
|
SourceLocation Loc;
|
|
|
|
OpenMPDirectiveKind DKind;
|
|
|
|
if (Delayed) {
|
|
|
|
TentativeParsingAction TPA(*this);
|
|
|
|
Loc = ConsumeAnnotationToken();
|
|
|
|
DKind = parseOpenMPDirectiveKind(*this);
|
|
|
|
if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
|
|
|
|
// Need to delay parsing until completion of the parent class.
|
|
|
|
TPA.Revert();
|
|
|
|
CachedTokens Toks;
|
|
|
|
unsigned Cnt = 1;
|
|
|
|
Toks.push_back(Tok);
|
|
|
|
while (Cnt && Tok.isNot(tok::eof)) {
|
|
|
|
(void)ConsumeAnyToken();
|
2021-07-12 06:51:19 -04:00
|
|
|
if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp))
|
2020-01-07 13:39:18 -05:00
|
|
|
++Cnt;
|
|
|
|
else if (Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
--Cnt;
|
|
|
|
Toks.push_back(Tok);
|
|
|
|
}
|
|
|
|
// Skip last annot_pragma_openmp_end.
|
|
|
|
if (Cnt == 0)
|
|
|
|
(void)ConsumeAnyToken();
|
|
|
|
auto *LP = new LateParsedPragma(this, AS);
|
|
|
|
LP->takeToks(Toks);
|
|
|
|
getCurrentClass().LateParsedDeclarations.push_back(LP);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
TPA.Commit();
|
|
|
|
} else {
|
|
|
|
Loc = ConsumeAnnotationToken();
|
|
|
|
DKind = parseOpenMPDirectiveKind(*this);
|
|
|
|
}
|
2013-05-13 04:18:18 +00:00
|
|
|
|
|
|
|
switch (DKind) {
|
2016-05-09 14:59:13 +00:00
|
|
|
case OMPD_threadprivate: {
|
2013-03-22 06:34:35 +00:00
|
|
|
ConsumeToken();
|
2019-03-07 17:54:44 +00:00
|
|
|
DeclDirectiveListParserHelper Helper(this, DKind);
|
|
|
|
if (!ParseOpenMPSimpleVarList(DKind, Helper,
|
|
|
|
/*AllowScopeSpecifier=*/true)) {
|
2020-02-21 13:48:56 -06:00
|
|
|
skipUntilPragmaOpenMPEnd(DKind);
|
2013-05-13 04:18:18 +00:00
|
|
|
// Skip the last annot_pragma_openmp_end.
|
2017-05-18 19:21:48 +00:00
|
|
|
ConsumeAnnotationToken();
|
2024-04-16 16:36:53 +04:00
|
|
|
return Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
|
|
|
|
Loc, Helper.getIdentifiers());
|
2013-03-22 06:34:35 +00:00
|
|
|
}
|
|
|
|
break;
|
2016-05-09 14:59:13 +00:00
|
|
|
}
|
2019-03-07 17:54:44 +00:00
|
|
|
case OMPD_allocate: {
|
|
|
|
ConsumeToken();
|
|
|
|
DeclDirectiveListParserHelper Helper(this, DKind);
|
|
|
|
if (!ParseOpenMPSimpleVarList(DKind, Helper,
|
|
|
|
/*AllowScopeSpecifier=*/true)) {
|
2019-03-12 18:52:33 +00:00
|
|
|
SmallVector<OMPClause *, 1> Clauses;
|
2019-03-07 17:54:44 +00:00
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
2024-05-30 14:49:13 -05:00
|
|
|
std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
|
2019-03-12 18:52:33 +00:00
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
OpenMPClauseKind CKind =
|
|
|
|
Tok.isAnnotation() ? OMPC_unknown
|
|
|
|
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().StartOpenMPClause(CKind);
|
2024-05-30 14:49:13 -05:00
|
|
|
OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
|
|
|
|
!SeenClauses[unsigned(CKind)]);
|
2019-03-12 18:52:33 +00:00
|
|
|
SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
2024-05-30 14:49:13 -05:00
|
|
|
SeenClauses[unsigned(CKind)] = true;
|
2019-03-12 18:52:33 +00:00
|
|
|
if (Clause != nullptr)
|
|
|
|
Clauses.push_back(Clause);
|
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end)) {
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().EndOpenMPClause();
|
2019-03-12 18:52:33 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Skip ',' if any.
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().EndOpenMPClause();
|
2019-03-12 18:52:33 +00:00
|
|
|
}
|
2020-02-21 13:48:56 -06:00
|
|
|
skipUntilPragmaOpenMPEnd(DKind);
|
2019-03-07 17:54:44 +00:00
|
|
|
}
|
|
|
|
// Skip the last annot_pragma_openmp_end.
|
|
|
|
ConsumeAnnotationToken();
|
2024-04-16 16:36:53 +04:00
|
|
|
return Actions.OpenMP().ActOnOpenMPAllocateDirective(
|
|
|
|
Loc, Helper.getIdentifiers(), Clauses);
|
2019-03-07 17:54:44 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2018-09-26 04:28:39 +00:00
|
|
|
case OMPD_requires: {
|
|
|
|
SourceLocation StartLoc = ConsumeToken();
|
|
|
|
SmallVector<OMPClause *, 5> Clauses;
|
2024-06-26 08:11:09 -05:00
|
|
|
llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
|
2018-09-26 04:28:39 +00:00
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end)) {
|
2019-02-26 11:01:50 +00:00
|
|
|
Diag(Tok, diag::err_omp_expected_clause)
|
2018-09-26 04:28:39 +00:00
|
|
|
<< getOpenMPDirectiveName(OMPD_requires);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
OpenMPClauseKind CKind = Tok.isAnnotation()
|
|
|
|
? OMPC_unknown
|
|
|
|
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().StartOpenMPClause(CKind);
|
2024-05-30 14:49:13 -05:00
|
|
|
OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
|
|
|
|
!SeenClauses[unsigned(CKind)]);
|
2019-03-12 18:52:33 +00:00
|
|
|
SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
2024-05-30 14:49:13 -05:00
|
|
|
SeenClauses[unsigned(CKind)] = true;
|
2018-09-26 04:28:39 +00:00
|
|
|
if (Clause != nullptr)
|
|
|
|
Clauses.push_back(Clause);
|
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end)) {
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().EndOpenMPClause();
|
2018-09-26 04:28:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Skip ',' if any.
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().EndOpenMPClause();
|
2018-09-26 04:28:39 +00:00
|
|
|
}
|
|
|
|
// Consume final annot_pragma_openmp_end
|
2020-02-11 15:15:21 -05:00
|
|
|
if (Clauses.empty()) {
|
2018-09-26 04:28:39 +00:00
|
|
|
Diag(Tok, diag::err_omp_expected_clause)
|
|
|
|
<< getOpenMPDirectiveName(OMPD_requires);
|
|
|
|
ConsumeAnnotationToken();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
ConsumeAnnotationToken();
|
2024-04-16 16:36:53 +04:00
|
|
|
return Actions.OpenMP().ActOnOpenMPRequiresDirective(StartLoc, Clauses);
|
2018-09-26 04:28:39 +00:00
|
|
|
}
|
2022-11-10 18:12:35 -08:00
|
|
|
case OMPD_error: {
|
|
|
|
SmallVector<OMPClause *, 1> Clauses;
|
|
|
|
SourceLocation StartLoc = ConsumeToken();
|
|
|
|
ParseOpenMPClauses(DKind, Clauses, StartLoc);
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().ActOnOpenMPErrorDirective(Clauses, StartLoc,
|
|
|
|
SourceLocation(),
|
|
|
|
/*InExContext = */ false);
|
2022-11-10 18:12:35 -08:00
|
|
|
break;
|
|
|
|
}
|
2020-11-23 11:48:59 -06:00
|
|
|
case OMPD_assumes:
|
|
|
|
case OMPD_begin_assumes:
|
|
|
|
ParseOpenMPAssumesDirective(DKind, ConsumeToken());
|
|
|
|
break;
|
|
|
|
case OMPD_end_assumes:
|
|
|
|
ParseOpenMPEndAssumesDirective(ConsumeToken());
|
|
|
|
break;
|
2016-03-03 05:21:39 +00:00
|
|
|
case OMPD_declare_reduction:
|
|
|
|
ConsumeToken();
|
2018-04-23 19:53:05 +00:00
|
|
|
if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
|
2020-02-21 13:48:56 -06:00
|
|
|
skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
|
2016-03-03 05:21:39 +00:00
|
|
|
// Skip the last annot_pragma_openmp_end.
|
2017-05-18 19:21:48 +00:00
|
|
|
ConsumeAnnotationToken();
|
2016-03-03 05:21:39 +00:00
|
|
|
return Res;
|
|
|
|
}
|
|
|
|
break;
|
2019-02-01 20:25:04 +00:00
|
|
|
case OMPD_declare_mapper: {
|
|
|
|
ConsumeToken();
|
|
|
|
if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
|
|
|
|
// Skip the last annot_pragma_openmp_end.
|
|
|
|
ConsumeAnnotationToken();
|
|
|
|
return Res;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2020-02-20 19:50:47 -06:00
|
|
|
case OMPD_begin_declare_variant: {
|
|
|
|
// The syntax is:
|
|
|
|
// { #pragma omp begin declare variant clause }
|
|
|
|
// <function-declaration-or-definition-sequence>
|
|
|
|
// { #pragma omp end declare variant }
|
|
|
|
//
|
|
|
|
ConsumeToken();
|
2024-04-16 16:36:53 +04:00
|
|
|
OMPTraitInfo *ParentTI =
|
|
|
|
Actions.OpenMP().getOMPTraitInfoForSurroundingScope();
|
2020-08-13 01:05:51 -05:00
|
|
|
ASTContext &ASTCtx = Actions.getASTContext();
|
|
|
|
OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
|
2021-10-12 14:55:00 -07:00
|
|
|
if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) {
|
|
|
|
while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
|
|
|
|
;
|
|
|
|
// Skip the last annot_pragma_openmp_end.
|
|
|
|
(void)ConsumeAnnotationToken();
|
2020-02-20 19:50:47 -06:00
|
|
|
break;
|
2021-10-12 14:55:00 -07:00
|
|
|
}
|
2020-02-20 19:50:47 -06:00
|
|
|
|
|
|
|
// Skip last tokens.
|
|
|
|
skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);
|
|
|
|
|
2020-06-17 11:02:49 -04:00
|
|
|
ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
|
|
|
|
|
2020-02-20 19:50:47 -06:00
|
|
|
VariantMatchInfo VMI;
|
2020-04-03 11:29:53 -05:00
|
|
|
TI.getAsVariantMatchInfo(ASTCtx, VMI);
|
2020-07-07 01:08:03 -05:00
|
|
|
|
2022-01-27 08:55:08 +00:00
|
|
|
std::function<void(StringRef)> DiagUnknownTrait =
|
|
|
|
[this, Loc](StringRef ISATrait) {
|
|
|
|
// TODO Track the selector locations in a way that is accessible here
|
|
|
|
// to improve the diagnostic location.
|
|
|
|
Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
|
|
|
|
};
|
2021-09-16 11:28:31 -05:00
|
|
|
TargetOMPContext OMPCtx(
|
|
|
|
ASTCtx, std::move(DiagUnknownTrait),
|
|
|
|
/* CurrentFunctionDecl */ nullptr,
|
2025-02-05 19:24:24 +05:30
|
|
|
/* ConstructTraits */ ArrayRef<llvm::omp::TraitProperty>(),
|
|
|
|
Actions.OpenMP().getOpenMPDeviceNum());
|
2020-02-20 19:50:47 -06:00
|
|
|
|
2020-04-03 11:29:53 -05:00
|
|
|
if (isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ true)) {
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().ActOnOpenMPBeginDeclareVariant(Loc, TI);
|
2020-02-20 19:50:47 -06:00
|
|
|
break;
|
[OpenMP] `omp begin/end declare variant` - part 2, sema ("+CG")
This is the second part loosely extracted from D71179 and cleaned up.
This patch provides semantic analysis support for `omp begin/end declare
variant`, mostly as defined in OpenMP technical report 8 (TR8) [0].
The sema handling makes code generation obsolete as we generate "the
right" calls that can just be handled as usual. This handling also
applies to the existing, albeit problematic, `omp declare variant
support`. As a consequence a lot of unneeded code generation and
complexity is removed.
A major purpose of this patch is to provide proper `math.h`/`cmath`
support for OpenMP target offloading. See PR42061, PR42798, PR42799. The
current code was developed with this feature in mind, see [1].
The logic is as follows:
If we have seen a `#pragma omp begin declare variant match(<SELECTOR>)`
but not the corresponding `end declare variant`, and we find a function
definition we will:
1) Create a function declaration for the definition we were about to generate.
2) Create a function definition but with a mangled name (according to
`<SELECTOR>`).
3) Annotate the declaration with the `OMPDeclareVariantAttr`, the same
one used already for `omp declare variant`, using and the mangled
function definition as specialization for the context defined by
`<SELECTOR>`.
When a call is created we inspect it. If the target has an
`OMPDeclareVariantAttr` attribute we try to specialize the call. To this
end, all variants are checked, the best applicable one is picked and a
new call to the specialization is created. The new call is used instead
of the original one to the base function. To keep the AST printing and
tooling possible we utilize the PseudoObjectExpr. The original call is
the syntactic expression, the specialized call is the semantic
expression.
[0] https://www.openmp.org/wp-content/uploads/openmp-TR8.pdf
[1] https://reviews.llvm.org/D61399#change-496lQkg0mhRN
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim, aaron.ballman
Subscribers: bollu, guansong, openmp-commits, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75779
2020-02-25 14:04:06 -08:00
|
|
|
}
|
2020-02-20 19:50:47 -06:00
|
|
|
|
|
|
|
// Elide all the code till the matching end declare variant was found.
|
|
|
|
unsigned Nesting = 1;
|
|
|
|
SourceLocation DKLoc;
|
|
|
|
OpenMPDirectiveKind DK = OMPD_unknown;
|
|
|
|
do {
|
|
|
|
DKLoc = Tok.getLocation();
|
|
|
|
DK = parseOpenMPDirectiveKind(*this);
|
|
|
|
if (DK == OMPD_end_declare_variant)
|
|
|
|
--Nesting;
|
|
|
|
else if (DK == OMPD_begin_declare_variant)
|
|
|
|
++Nesting;
|
|
|
|
if (!Nesting || isEofOrEom())
|
|
|
|
break;
|
|
|
|
ConsumeAnyToken();
|
|
|
|
} while (true);
|
|
|
|
|
|
|
|
parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant,
|
|
|
|
DK, Loc, DKLoc, /* SkipUntilOpenMPEnd */ true);
|
|
|
|
if (isEofOrEom())
|
|
|
|
return nullptr;
|
|
|
|
break;
|
|
|
|
}
|
[OpenMP] `omp begin/end declare variant` - part 2, sema ("+CG")
This is the second part loosely extracted from D71179 and cleaned up.
This patch provides semantic analysis support for `omp begin/end declare
variant`, mostly as defined in OpenMP technical report 8 (TR8) [0].
The sema handling makes code generation obsolete as we generate "the
right" calls that can just be handled as usual. This handling also
applies to the existing, albeit problematic, `omp declare variant
support`. As a consequence a lot of unneeded code generation and
complexity is removed.
A major purpose of this patch is to provide proper `math.h`/`cmath`
support for OpenMP target offloading. See PR42061, PR42798, PR42799. The
current code was developed with this feature in mind, see [1].
The logic is as follows:
If we have seen a `#pragma omp begin declare variant match(<SELECTOR>)`
but not the corresponding `end declare variant`, and we find a function
definition we will:
1) Create a function declaration for the definition we were about to generate.
2) Create a function definition but with a mangled name (according to
`<SELECTOR>`).
3) Annotate the declaration with the `OMPDeclareVariantAttr`, the same
one used already for `omp declare variant`, using and the mangled
function definition as specialization for the context defined by
`<SELECTOR>`.
When a call is created we inspect it. If the target has an
`OMPDeclareVariantAttr` attribute we try to specialize the call. To this
end, all variants are checked, the best applicable one is picked and a
new call to the specialization is created. The new call is used instead
of the original one to the base function. To keep the AST printing and
tooling possible we utilize the PseudoObjectExpr. The original call is
the syntactic expression, the specialized call is the semantic
expression.
[0] https://www.openmp.org/wp-content/uploads/openmp-TR8.pdf
[1] https://reviews.llvm.org/D61399#change-496lQkg0mhRN
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim, aaron.ballman
Subscribers: bollu, guansong, openmp-commits, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75779
2020-02-25 14:04:06 -08:00
|
|
|
case OMPD_end_declare_variant: {
|
2024-04-16 16:36:53 +04:00
|
|
|
if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
|
|
|
|
Actions.OpenMP().ActOnOpenMPEndDeclareVariant();
|
[OpenMP] `omp begin/end declare variant` - part 2, sema ("+CG")
This is the second part loosely extracted from D71179 and cleaned up.
This patch provides semantic analysis support for `omp begin/end declare
variant`, mostly as defined in OpenMP technical report 8 (TR8) [0].
The sema handling makes code generation obsolete as we generate "the
right" calls that can just be handled as usual. This handling also
applies to the existing, albeit problematic, `omp declare variant
support`. As a consequence a lot of unneeded code generation and
complexity is removed.
A major purpose of this patch is to provide proper `math.h`/`cmath`
support for OpenMP target offloading. See PR42061, PR42798, PR42799. The
current code was developed with this feature in mind, see [1].
The logic is as follows:
If we have seen a `#pragma omp begin declare variant match(<SELECTOR>)`
but not the corresponding `end declare variant`, and we find a function
definition we will:
1) Create a function declaration for the definition we were about to generate.
2) Create a function definition but with a mangled name (according to
`<SELECTOR>`).
3) Annotate the declaration with the `OMPDeclareVariantAttr`, the same
one used already for `omp declare variant`, using and the mangled
function definition as specialization for the context defined by
`<SELECTOR>`.
When a call is created we inspect it. If the target has an
`OMPDeclareVariantAttr` attribute we try to specialize the call. To this
end, all variants are checked, the best applicable one is picked and a
new call to the specialization is created. The new call is used instead
of the original one to the base function. To keep the AST printing and
tooling possible we utilize the PseudoObjectExpr. The original call is
the syntactic expression, the specialized call is the semantic
expression.
[0] https://www.openmp.org/wp-content/uploads/openmp-TR8.pdf
[1] https://reviews.llvm.org/D61399#change-496lQkg0mhRN
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim, aaron.ballman
Subscribers: bollu, guansong, openmp-commits, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75779
2020-02-25 14:04:06 -08:00
|
|
|
else
|
|
|
|
Diag(Loc, diag::err_expected_begin_declare_variant);
|
2020-02-20 19:50:47 -06:00
|
|
|
ConsumeToken();
|
|
|
|
break;
|
[OpenMP] `omp begin/end declare variant` - part 2, sema ("+CG")
This is the second part loosely extracted from D71179 and cleaned up.
This patch provides semantic analysis support for `omp begin/end declare
variant`, mostly as defined in OpenMP technical report 8 (TR8) [0].
The sema handling makes code generation obsolete as we generate "the
right" calls that can just be handled as usual. This handling also
applies to the existing, albeit problematic, `omp declare variant
support`. As a consequence a lot of unneeded code generation and
complexity is removed.
A major purpose of this patch is to provide proper `math.h`/`cmath`
support for OpenMP target offloading. See PR42061, PR42798, PR42799. The
current code was developed with this feature in mind, see [1].
The logic is as follows:
If we have seen a `#pragma omp begin declare variant match(<SELECTOR>)`
but not the corresponding `end declare variant`, and we find a function
definition we will:
1) Create a function declaration for the definition we were about to generate.
2) Create a function definition but with a mangled name (according to
`<SELECTOR>`).
3) Annotate the declaration with the `OMPDeclareVariantAttr`, the same
one used already for `omp declare variant`, using and the mangled
function definition as specialization for the context defined by
`<SELECTOR>`.
When a call is created we inspect it. If the target has an
`OMPDeclareVariantAttr` attribute we try to specialize the call. To this
end, all variants are checked, the best applicable one is picked and a
new call to the specialization is created. The new call is used instead
of the original one to the base function. To keep the AST printing and
tooling possible we utilize the PseudoObjectExpr. The original call is
the syntactic expression, the specialized call is the semantic
expression.
[0] https://www.openmp.org/wp-content/uploads/openmp-TR8.pdf
[1] https://reviews.llvm.org/D61399#change-496lQkg0mhRN
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim, aaron.ballman
Subscribers: bollu, guansong, openmp-commits, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75779
2020-02-25 14:04:06 -08:00
|
|
|
}
|
2019-09-13 20:18:17 +00:00
|
|
|
case OMPD_declare_variant:
|
2016-03-30 10:43:55 +00:00
|
|
|
case OMPD_declare_simd: {
|
|
|
|
// The syntax is:
|
2019-09-13 20:18:17 +00:00
|
|
|
// { #pragma omp declare {simd|variant} }
|
2016-03-30 10:43:55 +00:00
|
|
|
// <function-declaration-or-definition>
|
|
|
|
//
|
2016-04-07 12:45:37 +00:00
|
|
|
CachedTokens Toks;
|
2019-09-13 20:18:17 +00:00
|
|
|
Toks.push_back(Tok);
|
|
|
|
ConsumeToken();
|
2020-10-29 18:44:28 -05:00
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
2016-04-12 05:28:34 +00:00
|
|
|
Toks.push_back(Tok);
|
|
|
|
ConsumeAnyToken();
|
|
|
|
}
|
|
|
|
Toks.push_back(Tok);
|
|
|
|
ConsumeAnyToken();
|
2016-03-30 10:43:55 +00:00
|
|
|
|
|
|
|
DeclGroupPtrTy Ptr;
|
2021-07-12 06:51:19 -04:00
|
|
|
if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {
|
2020-01-07 13:39:18 -05:00
|
|
|
Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
|
|
|
|
TagType, Tag);
|
2018-04-23 19:53:05 +00:00
|
|
|
} else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
|
2016-03-30 10:43:55 +00:00
|
|
|
// Here we expect to see some function declaration.
|
|
|
|
if (AS == AS_none) {
|
|
|
|
assert(TagType == DeclSpec::TST_unspecified);
|
2022-11-15 15:44:34 +00:00
|
|
|
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
|
2016-03-30 10:43:55 +00:00
|
|
|
MaybeParseCXX11Attributes(Attrs);
|
|
|
|
ParsingDeclSpec PDS(*this);
|
2022-11-15 15:44:34 +00:00
|
|
|
Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
|
2016-03-30 10:43:55 +00:00
|
|
|
} else {
|
|
|
|
Ptr =
|
|
|
|
ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!Ptr) {
|
2019-09-13 20:18:17 +00:00
|
|
|
Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
|
|
|
|
<< (DKind == OMPD_declare_simd ? 0 : 1);
|
2016-03-30 10:43:55 +00:00
|
|
|
return DeclGroupPtrTy();
|
|
|
|
}
|
2019-09-13 20:18:17 +00:00
|
|
|
if (DKind == OMPD_declare_simd)
|
|
|
|
return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
|
|
|
|
assert(DKind == OMPD_declare_variant &&
|
|
|
|
"Expected declare variant directive only");
|
2019-09-18 16:24:31 +00:00
|
|
|
ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
|
|
|
|
return Ptr;
|
2016-03-30 10:43:55 +00:00
|
|
|
}
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
case OMPD_begin_declare_target:
|
2016-04-06 11:38:59 +00:00
|
|
|
case OMPD_declare_target: {
|
|
|
|
SourceLocation DTLoc = ConsumeAnyToken();
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
|
2024-04-16 16:36:53 +04:00
|
|
|
SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
if (HasClauses)
|
|
|
|
ParseOMPDeclareTargetClauses(DTCI);
|
2022-06-26 18:51:54 -07:00
|
|
|
bool HasImplicitMappings = DKind == OMPD_begin_declare_target ||
|
|
|
|
!HasClauses ||
|
|
|
|
(DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
|
2016-05-09 14:59:13 +00:00
|
|
|
|
2016-04-06 11:38:59 +00:00
|
|
|
// Skip the last annot_pragma_openmp_end.
|
|
|
|
ConsumeAnyToken();
|
|
|
|
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
if (HasImplicitMappings) {
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().ActOnStartOpenMPDeclareTargetContext(DTCI);
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
return nullptr;
|
2016-04-06 11:38:59 +00:00
|
|
|
}
|
|
|
|
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
llvm::SmallVector<Decl *, 4> Decls;
|
|
|
|
for (auto &It : DTCI.ExplicitlyMapped)
|
|
|
|
Decls.push_back(It.first);
|
2018-03-28 14:28:54 +00:00
|
|
|
return Actions.BuildDeclaratorGroup(Decls);
|
2016-04-06 11:38:59 +00:00
|
|
|
}
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
case OMPD_end_declare_target: {
|
2024-04-16 16:36:53 +04:00
|
|
|
if (!Actions.OpenMP().isInOpenMPDeclareTargetContext()) {
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
Diag(Tok, diag::err_omp_unexpected_directive)
|
|
|
|
<< 1 << getOpenMPDirectiveName(DKind);
|
|
|
|
break;
|
|
|
|
}
|
2024-04-16 16:36:53 +04:00
|
|
|
const SemaOpenMP::DeclareTargetContextInfo &DTCI =
|
|
|
|
Actions.OpenMP().ActOnOpenMPEndDeclareTargetDirective();
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc);
|
|
|
|
return nullptr;
|
|
|
|
}
|
2024-08-05 12:37:07 +01:00
|
|
|
case OMPD_assume: {
|
|
|
|
Diag(Tok, diag::err_omp_unexpected_directive)
|
|
|
|
<< 1 << getOpenMPDirectiveName(DKind);
|
|
|
|
break;
|
|
|
|
}
|
2013-03-22 06:34:35 +00:00
|
|
|
case OMPD_unknown:
|
|
|
|
Diag(Tok, diag::err_omp_unknown_directive);
|
|
|
|
break;
|
[flang][openmp] Use common Directive and Clause enum from llvm/Frontend
Summary:
This patch is removing the custom enumeration for OpenMP Directives and Clauses and replace them
with the newly tablegen generated one from llvm/Frontend. This is a first patch and some will follow to share the same
infrastructure where possible. The next patch should use the clauses allowance defined in the tablegen file.
Reviewers: jdoerfert, DavidTruby, sscalpone, kiranchandramohan, ichoyjx
Reviewed By: DavidTruby, ichoyjx
Subscribers: jholewinski, cfe-commits, dblaikie, MaskRay, ymandel, ichoyjx, mgorny, yaxunl, guansong, jfb, sstefan1, aaron.ballman, llvm-commits
Tags: #llvm, #flang, #clang
Differential Revision: https://reviews.llvm.org/D82906
2020-07-01 20:57:11 -04:00
|
|
|
default:
|
2024-06-26 08:11:09 -05:00
|
|
|
switch (getDirectiveCategory(DKind)) {
|
|
|
|
case Category::Executable:
|
|
|
|
case Category::Meta:
|
|
|
|
case Category::Subsidiary:
|
|
|
|
case Category::Utility:
|
|
|
|
Diag(Tok, diag::err_omp_unexpected_directive)
|
|
|
|
<< 1 << getOpenMPDirectiveName(DKind);
|
|
|
|
break;
|
|
|
|
case Category::Declarative:
|
|
|
|
case Category::Informational:
|
|
|
|
break;
|
|
|
|
}
|
2013-03-22 06:34:35 +00:00
|
|
|
}
|
2016-03-03 05:21:39 +00:00
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
ConsumeAnyToken();
|
2016-01-15 23:43:25 +00:00
|
|
|
return nullptr;
|
2013-03-22 06:34:35 +00:00
|
|
|
}
|
|
|
|
|
2024-06-26 08:11:09 -05:00
|
|
|
StmtResult Parser::ParseOpenMPExecutableDirective(
|
|
|
|
ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
|
|
|
|
bool ReadDirectiveWithinMetadirective) {
|
2024-06-29 09:37:32 -05:00
|
|
|
assert(isOpenMPExecutableDirective(DKind) && "Unexpected directive category");
|
|
|
|
|
2024-06-26 08:11:09 -05:00
|
|
|
bool HasAssociatedStatement = true;
|
|
|
|
Association Assoc = getDirectiveAssociation(DKind);
|
|
|
|
|
|
|
|
// OMPD_ordered has None as association, but it comes in two variants,
|
|
|
|
// the second of which is associated with a block.
|
|
|
|
// OMPD_scan and OMPD_section are both "separating", but section is treated
|
|
|
|
// as if it was associated with a statement, while scan is not.
|
|
|
|
if (DKind != OMPD_ordered && DKind != OMPD_section &&
|
|
|
|
(Assoc == Association::None || Assoc == Association::Separating)) {
|
|
|
|
if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
|
|
|
|
ParsedStmtContext()) {
|
|
|
|
Diag(Tok, diag::err_omp_immediate_directive)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << 0;
|
|
|
|
if (DKind == OMPD_error) {
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end);
|
|
|
|
return StmtError();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
HasAssociatedStatement = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceLocation EndLoc;
|
|
|
|
SmallVector<OMPClause *, 5> Clauses;
|
|
|
|
llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
|
|
|
|
DeclarationNameInfo DirName;
|
|
|
|
OpenMPDirectiveKind CancelRegion = OMPD_unknown;
|
|
|
|
unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
|
|
|
|
Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
|
|
|
|
|
|
|
|
// Special processing for flush and depobj clauses.
|
|
|
|
Token ImplicitTok;
|
|
|
|
bool ImplicitClauseAllowed = false;
|
|
|
|
if (DKind == OMPD_flush || DKind == OMPD_depobj) {
|
|
|
|
ImplicitTok = Tok;
|
|
|
|
ImplicitClauseAllowed = true;
|
|
|
|
}
|
|
|
|
ConsumeToken();
|
|
|
|
// Parse directive name of the 'critical' directive if any.
|
|
|
|
if (DKind == OMPD_critical) {
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren,
|
|
|
|
tok::annot_pragma_openmp_end);
|
|
|
|
if (!T.consumeOpen()) {
|
|
|
|
if (Tok.isAnyIdentifier()) {
|
|
|
|
DirName =
|
|
|
|
DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
|
|
|
|
ConsumeAnyToken();
|
|
|
|
} else {
|
|
|
|
Diag(Tok, diag::err_omp_expected_identifier_for_critical);
|
|
|
|
}
|
|
|
|
T.consumeClose();
|
|
|
|
}
|
|
|
|
} else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
|
|
|
|
CancelRegion = parseOpenMPDirectiveKind(*this);
|
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeToken();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isOpenMPLoopDirective(DKind))
|
|
|
|
ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
|
|
|
|
if (isOpenMPSimdDirective(DKind))
|
|
|
|
ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
|
|
|
|
ParseScope OMPDirectiveScope(this, ScopeFlags);
|
|
|
|
Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
|
|
|
|
Loc);
|
|
|
|
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
// If we are parsing for a directive within a metadirective, the directive
|
|
|
|
// ends with a ')'.
|
|
|
|
if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
bool HasImplicitClause = false;
|
|
|
|
if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) {
|
|
|
|
HasImplicitClause = true;
|
|
|
|
// Push copy of the current token back to stream to properly parse
|
|
|
|
// pseudo-clause OMPFlushClause or OMPDepobjClause.
|
|
|
|
PP.EnterToken(Tok, /*IsReinject*/ true);
|
|
|
|
PP.EnterToken(ImplicitTok, /*IsReinject*/ true);
|
|
|
|
ConsumeAnyToken();
|
|
|
|
}
|
|
|
|
OpenMPClauseKind CKind = Tok.isAnnotation()
|
|
|
|
? OMPC_unknown
|
|
|
|
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
|
|
|
if (HasImplicitClause) {
|
|
|
|
assert(CKind == OMPC_unknown && "Must be unknown implicit clause.");
|
|
|
|
if (DKind == OMPD_flush) {
|
|
|
|
CKind = OMPC_flush;
|
|
|
|
} else {
|
|
|
|
assert(DKind == OMPD_depobj && "Expected flush or depobj directives.");
|
|
|
|
CKind = OMPC_depobj;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// No more implicit clauses allowed.
|
|
|
|
ImplicitClauseAllowed = false;
|
|
|
|
Actions.OpenMP().StartOpenMPClause(CKind);
|
|
|
|
HasImplicitClause = false;
|
|
|
|
OMPClause *Clause =
|
|
|
|
ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
|
|
|
|
SeenClauses[unsigned(CKind)] = true;
|
|
|
|
if (Clause)
|
|
|
|
Clauses.push_back(Clause);
|
|
|
|
|
|
|
|
// Skip ',' if any.
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
|
|
|
Actions.OpenMP().EndOpenMPClause();
|
|
|
|
}
|
|
|
|
// End location of the directive.
|
|
|
|
EndLoc = Tok.getLocation();
|
|
|
|
// Consume final annot_pragma_openmp_end.
|
|
|
|
ConsumeAnnotationToken();
|
|
|
|
|
|
|
|
if (DKind == OMPD_ordered) {
|
|
|
|
// If the depend or doacross clause is specified, the ordered construct
|
|
|
|
// is a stand-alone directive.
|
|
|
|
for (auto CK : {OMPC_depend, OMPC_doacross}) {
|
|
|
|
if (SeenClauses[unsigned(CK)]) {
|
|
|
|
if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
|
|
|
|
ParsedStmtContext()) {
|
|
|
|
Diag(Loc, diag::err_omp_immediate_directive)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << 1 << getOpenMPClauseName(CK);
|
|
|
|
}
|
|
|
|
HasAssociatedStatement = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-13 07:14:36 -05:00
|
|
|
if ((DKind == OMPD_tile || DKind == OMPD_stripe) &&
|
|
|
|
!SeenClauses[unsigned(OMPC_sizes)]) {
|
2024-06-26 08:11:09 -05:00
|
|
|
Diag(Loc, diag::err_omp_required_clause)
|
2025-02-13 07:14:36 -05:00
|
|
|
<< getOpenMPDirectiveName(DKind) << "sizes";
|
2024-06-26 08:11:09 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
StmtResult AssociatedStmt;
|
|
|
|
if (HasAssociatedStatement) {
|
|
|
|
// The body is a block scope like in Lambdas and Blocks.
|
|
|
|
Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
|
|
|
|
// FIXME: We create a bogus CompoundStmt scope to hold the contents of
|
|
|
|
// the captured region. Code elsewhere assumes that any FunctionScopeInfo
|
|
|
|
// should have at least one compound statement scope within it.
|
|
|
|
ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
|
|
|
|
{
|
|
|
|
Sema::CompoundScopeRAII Scope(Actions);
|
|
|
|
AssociatedStmt = ParseStatement();
|
|
|
|
|
|
|
|
if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) &&
|
|
|
|
getLangOpts().OpenMPIRBuilder)
|
|
|
|
AssociatedStmt =
|
|
|
|
Actions.OpenMP().ActOnOpenMPLoopnest(AssociatedStmt.get());
|
|
|
|
}
|
|
|
|
AssociatedStmt =
|
|
|
|
Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
|
|
|
|
} else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
|
|
|
|
DKind == OMPD_target_exit_data) {
|
|
|
|
Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
|
|
|
|
AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
|
2024-10-24 10:23:40 +01:00
|
|
|
Actions.ActOnCompoundStmt(Loc, Loc, {},
|
2024-06-26 08:11:09 -05:00
|
|
|
/*isStmtExpr=*/false));
|
|
|
|
AssociatedStmt =
|
|
|
|
Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
|
|
|
|
}
|
|
|
|
|
|
|
|
StmtResult Directive = Actions.OpenMP().ActOnOpenMPExecutableDirective(
|
|
|
|
DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, EndLoc);
|
|
|
|
|
|
|
|
// Exit scope.
|
|
|
|
Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
|
|
|
|
OMPDirectiveScope.Exit();
|
|
|
|
|
|
|
|
return Directive;
|
|
|
|
}
|
|
|
|
|
2024-08-05 12:37:07 +01:00
|
|
|
StmtResult Parser::ParseOpenMPInformationalDirective(
|
|
|
|
ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
|
|
|
|
bool ReadDirectiveWithinMetadirective) {
|
|
|
|
assert(isOpenMPInformationalDirective(DKind) &&
|
|
|
|
"Unexpected directive category");
|
|
|
|
|
|
|
|
bool HasAssociatedStatement = true;
|
|
|
|
|
|
|
|
SmallVector<OMPClause *, 5> Clauses;
|
|
|
|
llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
|
|
|
|
DeclarationNameInfo DirName;
|
|
|
|
unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
|
|
|
|
Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
|
|
|
|
ParseScope OMPDirectiveScope(this, ScopeFlags);
|
|
|
|
|
|
|
|
Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
|
|
|
|
Loc);
|
|
|
|
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
OpenMPClauseKind CKind = Tok.isAnnotation()
|
|
|
|
? OMPC_unknown
|
|
|
|
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
|
|
|
Actions.OpenMP().StartOpenMPClause(CKind);
|
|
|
|
OMPClause *Clause =
|
|
|
|
ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
|
|
|
|
SeenClauses[unsigned(CKind)] = true;
|
|
|
|
if (Clause)
|
|
|
|
Clauses.push_back(Clause);
|
|
|
|
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
|
|
|
Actions.OpenMP().EndOpenMPClause();
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceLocation EndLoc = Tok.getLocation();
|
|
|
|
ConsumeAnnotationToken();
|
|
|
|
|
|
|
|
StmtResult AssociatedStmt;
|
|
|
|
if (HasAssociatedStatement) {
|
|
|
|
Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
|
|
|
|
ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
|
|
|
|
{
|
|
|
|
Sema::CompoundScopeRAII Scope(Actions);
|
|
|
|
AssociatedStmt = ParseStatement();
|
|
|
|
}
|
|
|
|
AssociatedStmt =
|
|
|
|
Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
|
|
|
|
}
|
|
|
|
|
|
|
|
StmtResult Directive = Actions.OpenMP().ActOnOpenMPInformationalDirective(
|
|
|
|
DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);
|
|
|
|
|
|
|
|
Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
|
|
|
|
OMPDirectiveScope.Exit();
|
|
|
|
|
|
|
|
return Directive;
|
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Parsing of declarative or executable OpenMP directives.
|
2013-07-19 03:13:43 +00:00
|
|
|
///
|
|
|
|
/// threadprivate-directive:
|
|
|
|
/// annot_pragma_openmp 'threadprivate' simple-variable-list
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
///
|
2019-03-07 17:54:44 +00:00
|
|
|
/// allocate-directive:
|
|
|
|
/// annot_pragma_openmp 'allocate' simple-variable-list
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
///
|
2016-03-03 05:21:39 +00:00
|
|
|
/// declare-reduction-directive:
|
|
|
|
/// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
|
|
|
|
/// <type> {',' <type>} ':' <expression> ')' ['initializer' '('
|
|
|
|
/// ('omp_priv' '=' <expression>|<function_call>) ')']
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
///
|
2019-02-01 20:25:04 +00:00
|
|
|
/// declare-mapper-directive:
|
|
|
|
/// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
|
|
|
|
/// <type> <var> ')' [<clause>[[,] <clause>] ... ]
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
///
|
2014-06-25 11:44:49 +00:00
|
|
|
/// executable-directive:
|
2014-06-26 12:05:45 +00:00
|
|
|
/// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
|
2014-07-21 09:42:05 +00:00
|
|
|
/// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
|
2019-12-05 13:43:48 -05:00
|
|
|
/// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' |
|
2022-11-01 14:46:12 -07:00
|
|
|
/// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'error'
|
|
|
|
/// | 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target
|
2019-12-05 13:43:48 -05:00
|
|
|
/// data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
|
|
|
|
/// 'master taskloop' | 'master taskloop simd' | 'parallel master
|
|
|
|
/// taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target
|
|
|
|
/// enter data' | 'target exit data' | 'target parallel' | 'target
|
|
|
|
/// parallel for' | 'target update' | 'distribute parallel for' |
|
|
|
|
/// 'distribute paralle for simd' | 'distribute simd' | 'target parallel
|
|
|
|
/// for simd' | 'target simd' | 'teams distribute' | 'teams distribute
|
|
|
|
/// simd' | 'teams distribute parallel for simd' | 'teams distribute
|
|
|
|
/// parallel for' | 'target teams' | 'target teams distribute' | 'target
|
|
|
|
/// teams distribute parallel for' | 'target teams distribute parallel
|
2023-04-03 20:29:16 +00:00
|
|
|
/// for simd' | 'target teams distribute simd' | 'masked' |
|
|
|
|
/// 'parallel masked' {clause} annot_pragma_openmp_end
|
2013-07-19 03:13:43 +00:00
|
|
|
///
|
2022-02-14 11:36:12 -08:00
|
|
|
StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
|
|
|
|
ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) {
|
2021-09-17 16:03:01 -05:00
|
|
|
if (!ReadDirectiveWithinMetadirective)
|
|
|
|
assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
|
|
|
|
"Not an OpenMP directive!");
|
2019-12-13 16:05:30 -05:00
|
|
|
ParsingOpenMPDirectiveRAII DirScope(*this);
|
2013-11-18 08:17:37 +00:00
|
|
|
ParenBraceBracketBalancer BalancerRAIIObj(*this);
|
2021-09-17 16:03:01 -05:00
|
|
|
SourceLocation Loc = ReadDirectiveWithinMetadirective
|
|
|
|
? Tok.getLocation()
|
2024-06-26 08:11:09 -05:00
|
|
|
: ConsumeAnnotationToken();
|
2018-04-23 19:53:05 +00:00
|
|
|
OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
|
2021-09-17 16:03:01 -05:00
|
|
|
if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {
|
|
|
|
Diag(Tok, diag::err_omp_unknown_directive);
|
|
|
|
return StmtError();
|
|
|
|
}
|
2024-06-26 08:11:09 -05:00
|
|
|
|
2013-07-19 03:13:43 +00:00
|
|
|
StmtResult Directive = StmtError();
|
2024-06-26 08:11:09 -05:00
|
|
|
|
|
|
|
bool IsExecutable = [&]() {
|
|
|
|
if (DKind == OMPD_error) // OMPD_error is handled as executable
|
|
|
|
return true;
|
|
|
|
auto Res = getDirectiveCategory(DKind);
|
|
|
|
return Res == Category::Executable || Res == Category::Subsidiary;
|
|
|
|
}();
|
|
|
|
|
|
|
|
if (IsExecutable) {
|
|
|
|
Directive = ParseOpenMPExecutableDirective(
|
|
|
|
StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
|
|
|
|
assert(!Directive.isUnset() && "Executable directive remained unprocessed");
|
|
|
|
return Directive;
|
|
|
|
}
|
2013-07-19 03:13:43 +00:00
|
|
|
|
|
|
|
switch (DKind) {
|
2022-05-24 23:59:19 -05:00
|
|
|
case OMPD_nothing:
|
|
|
|
ConsumeToken();
|
2023-11-29 15:13:43 +05:30
|
|
|
// If we are parsing the directive within a metadirective, the directive
|
|
|
|
// ends with a ')'.
|
|
|
|
if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren))
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
else
|
|
|
|
skipUntilPragmaOpenMPEnd(DKind);
|
2022-05-24 23:59:19 -05:00
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnnotationToken();
|
2023-12-03 13:33:38 +05:30
|
|
|
// return an empty statement
|
|
|
|
return StmtEmpty();
|
2021-09-17 16:03:01 -05:00
|
|
|
case OMPD_metadirective: {
|
|
|
|
ConsumeToken();
|
|
|
|
SmallVector<VariantMatchInfo, 4> VMIs;
|
|
|
|
|
|
|
|
// First iteration of parsing all clauses of metadirective.
|
|
|
|
// This iteration only parses and collects all context selector ignoring the
|
|
|
|
// associated directives.
|
|
|
|
TentativeParsingAction TPA(*this);
|
|
|
|
ASTContext &ASTContext = Actions.getASTContext();
|
|
|
|
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren,
|
|
|
|
tok::annot_pragma_openmp_end);
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
OpenMPClauseKind CKind = Tok.isAnnotation()
|
|
|
|
? OMPC_unknown
|
|
|
|
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
|
|
|
SourceLocation Loc = ConsumeToken();
|
|
|
|
|
|
|
|
// Parse '('.
|
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
|
|
|
getOpenMPClauseName(CKind).data()))
|
|
|
|
return Directive;
|
|
|
|
|
|
|
|
OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
|
|
|
|
if (CKind == OMPC_when) {
|
|
|
|
// parse and get OMPTraitInfo to pass to the When clause
|
|
|
|
parseOMPContextSelectors(Loc, TI);
|
|
|
|
if (TI.Sets.size() == 0) {
|
|
|
|
Diag(Tok, diag::err_omp_expected_context_selector) << "when clause";
|
|
|
|
TPA.Commit();
|
|
|
|
return Directive;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse ':'
|
|
|
|
if (Tok.is(tok::colon))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
else {
|
|
|
|
Diag(Tok, diag::err_omp_expected_colon) << "when clause";
|
|
|
|
TPA.Commit();
|
|
|
|
return Directive;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Skip Directive for now. We will parse directive in the second iteration
|
|
|
|
int paren = 0;
|
|
|
|
while (Tok.isNot(tok::r_paren) || paren != 0) {
|
|
|
|
if (Tok.is(tok::l_paren))
|
|
|
|
paren++;
|
|
|
|
if (Tok.is(tok::r_paren))
|
|
|
|
paren--;
|
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok, diag::err_omp_expected_punc)
|
|
|
|
<< getOpenMPClauseName(CKind) << 0;
|
|
|
|
TPA.Commit();
|
|
|
|
return Directive;
|
|
|
|
}
|
|
|
|
ConsumeAnyToken();
|
|
|
|
}
|
|
|
|
// Parse ')'
|
|
|
|
if (Tok.is(tok::r_paren))
|
|
|
|
T.consumeClose();
|
|
|
|
|
|
|
|
VariantMatchInfo VMI;
|
|
|
|
TI.getAsVariantMatchInfo(ASTContext, VMI);
|
|
|
|
|
|
|
|
VMIs.push_back(VMI);
|
|
|
|
}
|
|
|
|
|
|
|
|
TPA.Revert();
|
|
|
|
// End of the first iteration. Parser is reset to the start of metadirective
|
|
|
|
|
2022-01-27 08:55:08 +00:00
|
|
|
std::function<void(StringRef)> DiagUnknownTrait =
|
|
|
|
[this, Loc](StringRef ISATrait) {
|
|
|
|
// TODO Track the selector locations in a way that is accessible here
|
|
|
|
// to improve the diagnostic location.
|
|
|
|
Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
|
|
|
|
};
|
2022-01-11 11:43:31 +00:00
|
|
|
TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait),
|
2021-09-17 16:03:01 -05:00
|
|
|
/* CurrentFunctionDecl */ nullptr,
|
2025-02-05 19:24:24 +05:30
|
|
|
ArrayRef<llvm::omp::TraitProperty>(),
|
|
|
|
Actions.OpenMP().getOpenMPDeviceNum());
|
2021-09-17 16:03:01 -05:00
|
|
|
|
|
|
|
// A single match is returned for OpenMP 5.0
|
|
|
|
int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
|
|
|
|
|
|
|
|
int Idx = 0;
|
|
|
|
// In OpenMP 5.0 metadirective is either replaced by another directive or
|
|
|
|
// ignored.
|
|
|
|
// TODO: In OpenMP 5.1 generate multiple directives based upon the matches
|
|
|
|
// found by getBestWhenMatchForContext.
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
// OpenMP 5.0 implementation - Skip to the best index found.
|
|
|
|
if (Idx++ != BestIdx) {
|
|
|
|
ConsumeToken(); // Consume clause name
|
|
|
|
T.consumeOpen(); // Consume '('
|
|
|
|
int paren = 0;
|
|
|
|
// Skip everything inside the clause
|
|
|
|
while (Tok.isNot(tok::r_paren) || paren != 0) {
|
|
|
|
if (Tok.is(tok::l_paren))
|
|
|
|
paren++;
|
|
|
|
if (Tok.is(tok::r_paren))
|
|
|
|
paren--;
|
|
|
|
ConsumeAnyToken();
|
|
|
|
}
|
|
|
|
// Parse ')'
|
|
|
|
if (Tok.is(tok::r_paren))
|
|
|
|
T.consumeClose();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
OpenMPClauseKind CKind = Tok.isAnnotation()
|
|
|
|
? OMPC_unknown
|
|
|
|
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
|
|
|
SourceLocation Loc = ConsumeToken();
|
|
|
|
|
|
|
|
// Parse '('.
|
|
|
|
T.consumeOpen();
|
|
|
|
|
|
|
|
// Skip ContextSelectors for when clause
|
|
|
|
if (CKind == OMPC_when) {
|
|
|
|
OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
|
|
|
|
// parse and skip the ContextSelectors
|
|
|
|
parseOMPContextSelectors(Loc, TI);
|
|
|
|
|
|
|
|
// Parse ':'
|
|
|
|
ConsumeAnyToken();
|
|
|
|
}
|
|
|
|
|
|
|
|
// If no directive is passed, skip in OpenMP 5.0.
|
|
|
|
// TODO: Generate nothing directive from OpenMP 5.1.
|
|
|
|
if (Tok.is(tok::r_paren)) {
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse Directive
|
2022-02-14 11:36:12 -08:00
|
|
|
Directive = ParseOpenMPDeclarativeOrExecutableDirective(
|
|
|
|
StmtCtx,
|
|
|
|
/*ReadDirectiveWithinMetadirective=*/true);
|
2021-09-17 16:03:01 -05:00
|
|
|
break;
|
|
|
|
}
|
2025-02-28 08:02:35 -05:00
|
|
|
// If no match is found and no otherwise clause is present, skip
|
|
|
|
// OMP5.2 Chapter 7.4: If no otherwise clause is specified the effect is as
|
|
|
|
// if one was specified without an associated directive variant.
|
|
|
|
if (BestIdx == -1 && Idx == 1) {
|
|
|
|
assert(Tok.is(tok::annot_pragma_openmp_end) &&
|
|
|
|
"Expecting the end of the pragma here");
|
|
|
|
ConsumeAnnotationToken();
|
|
|
|
return StmtEmpty();
|
|
|
|
}
|
2021-09-17 16:03:01 -05:00
|
|
|
break;
|
|
|
|
}
|
2016-05-09 14:59:13 +00:00
|
|
|
case OMPD_threadprivate: {
|
2019-02-15 00:27:53 +00:00
|
|
|
// FIXME: Should this be permitted in C++?
|
2023-11-20 10:52:11 -05:00
|
|
|
if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
|
2019-02-15 00:27:53 +00:00
|
|
|
ParsedStmtContext()) {
|
2016-01-13 11:18:54 +00:00
|
|
|
Diag(Tok, diag::err_omp_immediate_directive)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << 0;
|
|
|
|
}
|
2013-07-19 03:13:43 +00:00
|
|
|
ConsumeToken();
|
2019-03-07 17:54:44 +00:00
|
|
|
DeclDirectiveListParserHelper Helper(this, DKind);
|
|
|
|
if (!ParseOpenMPSimpleVarList(DKind, Helper,
|
|
|
|
/*AllowScopeSpecifier=*/false)) {
|
2020-02-21 13:48:56 -06:00
|
|
|
skipUntilPragmaOpenMPEnd(DKind);
|
2024-04-16 16:36:53 +04:00
|
|
|
DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
|
2016-05-09 14:59:13 +00:00
|
|
|
Loc, Helper.getIdentifiers());
|
2013-07-19 03:13:43 +00:00
|
|
|
Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
|
|
|
|
}
|
2013-12-18 19:10:49 +00:00
|
|
|
SkipUntil(tok::annot_pragma_openmp_end);
|
2013-07-19 03:13:43 +00:00
|
|
|
break;
|
2016-05-09 14:59:13 +00:00
|
|
|
}
|
2019-03-07 17:54:44 +00:00
|
|
|
case OMPD_allocate: {
|
|
|
|
// FIXME: Should this be permitted in C++?
|
2023-11-20 10:52:11 -05:00
|
|
|
if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
|
2019-03-07 17:54:44 +00:00
|
|
|
ParsedStmtContext()) {
|
|
|
|
Diag(Tok, diag::err_omp_immediate_directive)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << 0;
|
|
|
|
}
|
|
|
|
ConsumeToken();
|
|
|
|
DeclDirectiveListParserHelper Helper(this, DKind);
|
|
|
|
if (!ParseOpenMPSimpleVarList(DKind, Helper,
|
|
|
|
/*AllowScopeSpecifier=*/false)) {
|
2019-03-12 18:52:33 +00:00
|
|
|
SmallVector<OMPClause *, 1> Clauses;
|
2019-03-07 17:54:44 +00:00
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
2024-06-26 08:11:09 -05:00
|
|
|
llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
|
2019-03-12 18:52:33 +00:00
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
OpenMPClauseKind CKind =
|
|
|
|
Tok.isAnnotation() ? OMPC_unknown
|
|
|
|
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().StartOpenMPClause(CKind);
|
2024-05-30 14:49:13 -05:00
|
|
|
OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
|
|
|
|
!SeenClauses[unsigned(CKind)]);
|
2019-03-12 18:52:33 +00:00
|
|
|
SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
2024-05-30 14:49:13 -05:00
|
|
|
SeenClauses[unsigned(CKind)] = true;
|
2019-03-12 18:52:33 +00:00
|
|
|
if (Clause != nullptr)
|
|
|
|
Clauses.push_back(Clause);
|
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end)) {
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().EndOpenMPClause();
|
2019-03-12 18:52:33 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Skip ',' if any.
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().EndOpenMPClause();
|
2019-03-12 18:52:33 +00:00
|
|
|
}
|
2020-02-21 13:48:56 -06:00
|
|
|
skipUntilPragmaOpenMPEnd(DKind);
|
2019-03-07 17:54:44 +00:00
|
|
|
}
|
2024-04-16 16:36:53 +04:00
|
|
|
DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPAllocateDirective(
|
2019-03-12 18:52:33 +00:00
|
|
|
Loc, Helper.getIdentifiers(), Clauses);
|
2019-03-07 17:54:44 +00:00
|
|
|
Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
|
|
|
|
}
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end);
|
|
|
|
break;
|
|
|
|
}
|
2016-03-03 05:21:39 +00:00
|
|
|
case OMPD_declare_reduction:
|
|
|
|
ConsumeToken();
|
2018-04-23 19:53:05 +00:00
|
|
|
if (DeclGroupPtrTy Res =
|
|
|
|
ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
|
2020-02-21 13:48:56 -06:00
|
|
|
skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
|
2016-03-03 05:21:39 +00:00
|
|
|
ConsumeAnyToken();
|
|
|
|
Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
|
2018-04-23 19:53:05 +00:00
|
|
|
} else {
|
2016-03-03 05:21:39 +00:00
|
|
|
SkipUntil(tok::annot_pragma_openmp_end);
|
2018-04-23 19:53:05 +00:00
|
|
|
}
|
2016-03-03 05:21:39 +00:00
|
|
|
break;
|
2019-02-01 20:25:04 +00:00
|
|
|
case OMPD_declare_mapper: {
|
|
|
|
ConsumeToken();
|
|
|
|
if (DeclGroupPtrTy Res =
|
|
|
|
ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
|
|
|
|
// Skip the last annot_pragma_openmp_end.
|
|
|
|
ConsumeAnnotationToken();
|
|
|
|
Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
|
|
|
|
} else {
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2024-03-06 19:46:23 +05:30
|
|
|
case OMPD_declare_target: {
|
|
|
|
SourceLocation DTLoc = ConsumeAnyToken();
|
|
|
|
bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
|
2024-04-16 16:36:53 +04:00
|
|
|
SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
|
2024-03-06 19:46:23 +05:30
|
|
|
if (HasClauses)
|
|
|
|
ParseOMPDeclareTargetClauses(DTCI);
|
|
|
|
bool HasImplicitMappings =
|
|
|
|
!HasClauses || (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
|
|
|
|
|
|
|
|
if (HasImplicitMappings) {
|
|
|
|
Diag(Tok, diag::err_omp_unexpected_directive)
|
|
|
|
<< 1 << getOpenMPDirectiveName(DKind);
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Skip the last annot_pragma_openmp_end.
|
|
|
|
ConsumeAnyToken();
|
|
|
|
|
2024-04-16 16:36:53 +04:00
|
|
|
Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
|
2024-03-06 19:46:23 +05:30
|
|
|
break;
|
|
|
|
}
|
2016-03-30 10:43:55 +00:00
|
|
|
case OMPD_declare_simd:
|
[OpenMP] Overhaul `declare target` handling
This patch fixes various issues with our prior `declare target` handling
and extends it to support `omp begin declare target` as well.
This started with PR49649 in mind, trying to provide a way for users to
avoid the "ref" global use introduced for globals with internal linkage.
From there it went down the rabbit hole, e.g., all variables, even
`nohost` ones, were emitted into the device code so it was impossible to
determine if "ref" was needed late in the game (based on the name only).
To make it really useful, `begin declare target` was needed as it can
carry the `device_type`. Not emitting variables eagerly had a ripple
effect. Finally, the precedence of the (explicit) declare target list
items needed to be taken into account, that meant we cannot just look
for any declare target attribute to make a decision. This caused the
handling of functions to require fixup as well.
I tried to clean up things while I was at it, e.g., we should not "parse
declarations and defintions" as part of OpenMP parsing, this will always
break at some point. Instead, we keep track what region we are in and
act on definitions and declarations instead, this is what we do for
declare variant and other begin/end directives already.
Highlights:
- new diagnosis for restrictions specificed in the standard,
- delayed emission of globals not mentioned in an explicit
list of a declare target,
- omission of `nohost` globals on the host and `host` globals on the
device,
- no explicit parsing of declarations in-between `omp [begin] declare
variant` and the corresponding end anymore, regular parsing instead,
- precedence for explicit mentions in `declare target` lists over
implicit mentions in the declaration-definition-seq, and
- `omp allocate` declarations will now replace an earlier emitted
global, if necessary.
---
Notes:
The patch is larger than I hoped but it turns out that most changes do
on their own lead to "inconsistent states", which seem less desirable
overall.
After working through this I feel the standard should remove the
explicit declare target forms as the delayed emission is horrible.
That said, while we delay things anyway, it seems to me we check too
often for the current status even though that is often not sufficient to
act upon. There seems to be a lot of duplication that can probably be
trimmed down. Eagerly emitting some things seems pretty weak as an
argument to keep so much logic around.
---
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D101030
2021-04-22 00:57:28 -05:00
|
|
|
case OMPD_begin_declare_target:
|
2016-04-06 11:38:59 +00:00
|
|
|
case OMPD_end_declare_target:
|
2018-09-26 04:28:39 +00:00
|
|
|
case OMPD_requires:
|
2020-02-20 19:50:47 -06:00
|
|
|
case OMPD_begin_declare_variant:
|
|
|
|
case OMPD_end_declare_variant:
|
2019-09-13 20:18:17 +00:00
|
|
|
case OMPD_declare_variant:
|
2016-03-30 10:43:55 +00:00
|
|
|
Diag(Tok, diag::err_omp_unexpected_directive)
|
2018-02-16 18:36:44 +00:00
|
|
|
<< 1 << getOpenMPDirectiveName(DKind);
|
2016-03-30 10:43:55 +00:00
|
|
|
SkipUntil(tok::annot_pragma_openmp_end);
|
|
|
|
break;
|
2024-08-05 12:37:07 +01:00
|
|
|
case OMPD_assume: {
|
|
|
|
ConsumeToken();
|
|
|
|
Directive = ParseOpenMPInformationalDirective(
|
|
|
|
StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
|
|
|
|
assert(!Directive.isUnset() &&
|
|
|
|
"Informational directive remains unprocessed");
|
|
|
|
return Directive;
|
|
|
|
}
|
2013-07-19 03:13:43 +00:00
|
|
|
case OMPD_unknown:
|
[flang][openmp] Use common Directive and Clause enum from llvm/Frontend
Summary:
This patch is removing the custom enumeration for OpenMP Directives and Clauses and replace them
with the newly tablegen generated one from llvm/Frontend. This is a first patch and some will follow to share the same
infrastructure where possible. The next patch should use the clauses allowance defined in the tablegen file.
Reviewers: jdoerfert, DavidTruby, sscalpone, kiranchandramohan, ichoyjx
Reviewed By: DavidTruby, ichoyjx
Subscribers: jholewinski, cfe-commits, dblaikie, MaskRay, ymandel, ichoyjx, mgorny, yaxunl, guansong, jfb, sstefan1, aaron.ballman, llvm-commits
Tags: #llvm, #flang, #clang
Differential Revision: https://reviews.llvm.org/D82906
2020-07-01 20:57:11 -04:00
|
|
|
default:
|
2013-07-19 03:13:43 +00:00
|
|
|
Diag(Tok, diag::err_omp_unknown_directive);
|
2013-12-18 19:10:49 +00:00
|
|
|
SkipUntil(tok::annot_pragma_openmp_end);
|
2013-07-19 03:13:43 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return Directive;
|
|
|
|
}
|
|
|
|
|
2016-05-09 14:59:13 +00:00
|
|
|
// Parses simple list:
|
|
|
|
// simple-variable-list:
|
|
|
|
// '(' id-expression {, id-expression} ')'
|
|
|
|
//
|
|
|
|
bool Parser::ParseOpenMPSimpleVarList(
|
|
|
|
OpenMPDirectiveKind Kind,
|
2020-10-29 18:44:28 -05:00
|
|
|
const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)>
|
|
|
|
&Callback,
|
2016-05-09 14:59:13 +00:00
|
|
|
bool AllowScopeSpecifier) {
|
2013-03-22 06:34:35 +00:00
|
|
|
// Parse '('.
|
2013-12-18 19:10:49 +00:00
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
2013-07-19 03:13:43 +00:00
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-04 22:00:49 -06:00
|
|
|
getOpenMPDirectiveName(Kind).data()))
|
2013-07-19 03:13:43 +00:00
|
|
|
return true;
|
|
|
|
bool IsCorrect = true;
|
2013-05-13 04:18:18 +00:00
|
|
|
bool NoIdentIsFound = true;
|
2013-03-22 06:34:35 +00:00
|
|
|
|
|
|
|
// Read tokens while ')' or annot_pragma_openmp_end is not found.
|
2013-05-13 04:18:18 +00:00
|
|
|
while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
|
2013-03-22 06:34:35 +00:00
|
|
|
CXXScopeSpec SS;
|
|
|
|
UnqualifiedId Name;
|
|
|
|
// Read var name.
|
|
|
|
Token PrevTok = Tok;
|
2013-05-13 04:18:18 +00:00
|
|
|
NoIdentIsFound = false;
|
2013-03-22 06:34:35 +00:00
|
|
|
|
2013-05-13 04:18:18 +00:00
|
|
|
if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
|
2020-03-19 09:12:29 +01:00
|
|
|
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
|
2022-01-09 00:19:49 -08:00
|
|
|
/*ObjectHasErrors=*/false, false)) {
|
2013-03-22 06:34:35 +00:00
|
|
|
IsCorrect = false;
|
|
|
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
2013-12-18 19:10:49 +00:00
|
|
|
StopBeforeMatch);
|
2020-03-19 09:12:29 +01:00
|
|
|
} else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,
|
|
|
|
/*ObjectHadErrors=*/false, false, false,
|
|
|
|
false, false, nullptr, Name)) {
|
2013-05-13 04:18:18 +00:00
|
|
|
IsCorrect = false;
|
|
|
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
2013-12-18 19:10:49 +00:00
|
|
|
StopBeforeMatch);
|
2013-05-13 04:18:18 +00:00
|
|
|
} else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end)) {
|
2013-03-22 06:34:35 +00:00
|
|
|
IsCorrect = false;
|
|
|
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
2013-12-18 19:10:49 +00:00
|
|
|
StopBeforeMatch);
|
2013-12-24 09:48:30 +00:00
|
|
|
Diag(PrevTok.getLocation(), diag::err_expected)
|
|
|
|
<< tok::identifier
|
|
|
|
<< SourceRange(PrevTok.getLocation(), PrevTokLocation);
|
2013-03-22 06:34:35 +00:00
|
|
|
} else {
|
2016-05-09 14:59:13 +00:00
|
|
|
Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
|
2013-03-22 06:34:35 +00:00
|
|
|
}
|
|
|
|
// Consume ','.
|
|
|
|
if (Tok.is(tok::comma)) {
|
|
|
|
ConsumeToken();
|
|
|
|
}
|
2013-05-13 04:18:18 +00:00
|
|
|
}
|
2013-03-22 06:34:35 +00:00
|
|
|
|
2013-05-13 04:18:18 +00:00
|
|
|
if (NoIdentIsFound) {
|
2013-12-24 09:48:30 +00:00
|
|
|
Diag(Tok, diag::err_expected) << tok::identifier;
|
2013-05-13 04:18:18 +00:00
|
|
|
IsCorrect = false;
|
2013-03-22 06:34:35 +00:00
|
|
|
}
|
|
|
|
|
2013-05-13 04:18:18 +00:00
|
|
|
// Parse ')'.
|
2013-07-19 03:13:43 +00:00
|
|
|
IsCorrect = !T.consumeClose() && IsCorrect;
|
2013-05-13 04:18:18 +00:00
|
|
|
|
2016-05-09 14:59:13 +00:00
|
|
|
return !IsCorrect;
|
2013-03-22 06:34:35 +00:00
|
|
|
}
|
2013-07-19 03:13:43 +00:00
|
|
|
|
2021-02-12 11:26:59 -08:00
|
|
|
OMPClause *Parser::ParseOpenMPSizesClause() {
|
2024-05-13 16:10:58 +02:00
|
|
|
SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
|
2021-02-12 11:26:59 -08:00
|
|
|
SmallVector<Expr *, 4> ValExprs;
|
2024-05-13 16:10:58 +02:00
|
|
|
if (ParseOpenMPExprListClause(OMPC_sizes, ClauseNameLoc, OpenLoc, CloseLoc,
|
|
|
|
ValExprs))
|
2021-02-12 11:26:59 -08:00
|
|
|
return nullptr;
|
|
|
|
|
2024-05-13 16:10:58 +02:00
|
|
|
return Actions.OpenMP().ActOnOpenMPSizesClause(ValExprs, ClauseNameLoc,
|
|
|
|
OpenLoc, CloseLoc);
|
2021-02-12 11:26:59 -08:00
|
|
|
}
|
|
|
|
|
2024-10-09 14:56:43 +02:00
|
|
|
OMPClause *Parser::ParseOpenMPPermutationClause() {
|
|
|
|
SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
|
|
|
|
SmallVector<Expr *> ArgExprs;
|
|
|
|
if (ParseOpenMPExprListClause(OMPC_permutation, ClauseNameLoc, OpenLoc,
|
|
|
|
CloseLoc, ArgExprs,
|
|
|
|
/*ReqIntConst=*/true))
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
return Actions.OpenMP().ActOnOpenMPPermutationClause(ArgExprs, ClauseNameLoc,
|
|
|
|
OpenLoc, CloseLoc);
|
|
|
|
}
|
|
|
|
|
2020-04-21 13:21:00 -04:00
|
|
|
OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
|
|
|
|
SourceLocation Loc = Tok.getLocation();
|
|
|
|
ConsumeAnyToken();
|
|
|
|
|
|
|
|
// Parse '('.
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator"))
|
|
|
|
return nullptr;
|
2024-04-16 16:36:53 +04:00
|
|
|
SmallVector<SemaOpenMP::UsesAllocatorsData, 4> Data;
|
2020-04-21 13:21:00 -04:00
|
|
|
do {
|
2023-05-25 09:29:59 -07:00
|
|
|
CXXScopeSpec SS;
|
|
|
|
Token Replacement;
|
2021-06-14 10:04:59 -07:00
|
|
|
ExprResult Allocator =
|
2023-05-25 09:29:59 -07:00
|
|
|
getLangOpts().CPlusPlus
|
|
|
|
? ParseCXXIdExpression()
|
|
|
|
: tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false,
|
|
|
|
Replacement);
|
2020-04-21 13:21:00 -04:00
|
|
|
if (Allocator.isInvalid()) {
|
|
|
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
break;
|
|
|
|
}
|
2024-04-16 16:36:53 +04:00
|
|
|
SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();
|
2020-04-21 13:21:00 -04:00
|
|
|
D.Allocator = Allocator.get();
|
|
|
|
if (Tok.is(tok::l_paren)) {
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren,
|
|
|
|
tok::annot_pragma_openmp_end);
|
|
|
|
T.consumeOpen();
|
2021-06-14 10:04:59 -07:00
|
|
|
ExprResult AllocatorTraits =
|
|
|
|
getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
|
2020-04-21 13:21:00 -04:00
|
|
|
T.consumeClose();
|
|
|
|
if (AllocatorTraits.isInvalid()) {
|
|
|
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
D.AllocatorTraits = AllocatorTraits.get();
|
|
|
|
D.LParenLoc = T.getOpenLocation();
|
|
|
|
D.RParenLoc = T.getCloseLocation();
|
|
|
|
}
|
|
|
|
if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
|
|
|
|
Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0;
|
|
|
|
// Parse ','
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
} while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));
|
|
|
|
T.consumeClose();
|
2024-04-16 16:36:53 +04:00
|
|
|
return Actions.OpenMP().ActOnOpenMPUsesAllocatorClause(
|
|
|
|
Loc, T.getOpenLocation(), T.getCloseLocation(), Data);
|
2020-04-21 13:21:00 -04:00
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Parsing of OpenMP clauses.
|
2013-07-19 03:13:43 +00:00
|
|
|
///
|
|
|
|
/// clause:
|
2014-07-17 07:32:53 +00:00
|
|
|
/// if-clause | final-clause | num_threads-clause | safelen-clause |
|
|
|
|
/// default-clause | private-clause | firstprivate-clause | shared-clause
|
2021-11-03 14:57:01 -07:00
|
|
|
/// | linear-clause | aligned-clause | collapse-clause | bind-clause |
|
2014-07-17 07:32:53 +00:00
|
|
|
/// lastprivate-clause | reduction-clause | proc_bind-clause |
|
2014-07-17 12:47:03 +00:00
|
|
|
/// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
|
2014-07-23 10:25:33 +00:00
|
|
|
/// mergeable-clause | flush-clause | read-clause | write-clause |
|
2015-08-21 11:14:16 +00:00
|
|
|
/// update-clause | capture-clause | seq_cst-clause | device-clause |
|
2015-11-27 18:47:36 +00:00
|
|
|
/// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
|
2015-12-07 12:52:51 +00:00
|
|
|
/// thread_limit-clause | priority-clause | grainsize-clause |
|
2016-05-26 17:49:04 +00:00
|
|
|
/// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
|
2017-07-21 18:48:21 +00:00
|
|
|
/// from-clause | is_device_ptr-clause | task_reduction-clause |
|
2020-02-06 16:30:23 -05:00
|
|
|
/// in_reduction-clause | allocator-clause | allocate-clause |
|
2020-02-28 09:52:15 -05:00
|
|
|
/// acq_rel-clause | acquire-clause | release-clause | relaxed-clause |
|
2020-03-23 10:41:08 -04:00
|
|
|
/// depobj-clause | destroy-clause | detach-clause | inclusive-clause |
|
2022-04-06 20:30:44 -07:00
|
|
|
/// exclusive-clause | uses_allocators-clause | use_device_addr-clause |
|
|
|
|
/// has_device_addr
|
2013-07-19 03:13:43 +00:00
|
|
|
///
|
|
|
|
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
|
|
|
OpenMPClauseKind CKind, bool FirstClause) {
|
2020-07-09 13:27:32 -05:00
|
|
|
OMPClauseKind = CKind;
|
2014-05-21 06:02:52 +00:00
|
|
|
OMPClause *Clause = nullptr;
|
2013-07-19 03:13:43 +00:00
|
|
|
bool ErrorFound = false;
|
2018-01-09 19:21:04 +00:00
|
|
|
bool WrongDirective = false;
|
2013-07-19 03:13:43 +00:00
|
|
|
// Check if clause is allowed for the given directive.
|
2019-11-19 12:07:54 -05:00
|
|
|
if (CKind != OMPC_unknown &&
|
|
|
|
!isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
|
2020-10-29 18:44:28 -05:00
|
|
|
Diag(Tok, diag::err_omp_unexpected_clause)
|
|
|
|
<< getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
|
2013-07-19 03:13:43 +00:00
|
|
|
ErrorFound = true;
|
2018-01-09 19:21:04 +00:00
|
|
|
WrongDirective = true;
|
2013-07-19 03:13:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (CKind) {
|
2014-07-17 07:32:53 +00:00
|
|
|
case OMPC_final:
|
2014-03-06 06:15:19 +00:00
|
|
|
case OMPC_num_threads:
|
2014-03-21 04:51:18 +00:00
|
|
|
case OMPC_safelen:
|
2015-08-21 11:14:16 +00:00
|
|
|
case OMPC_simdlen:
|
2014-05-27 15:12:19 +00:00
|
|
|
case OMPC_collapse:
|
2015-07-30 11:36:16 +00:00
|
|
|
case OMPC_ordered:
|
2015-12-01 10:17:31 +00:00
|
|
|
case OMPC_priority:
|
2015-12-07 12:52:51 +00:00
|
|
|
case OMPC_grainsize:
|
2015-12-08 12:06:20 +00:00
|
|
|
case OMPC_num_tasks:
|
2015-12-15 08:19:24 +00:00
|
|
|
case OMPC_hint:
|
2019-03-12 18:52:33 +00:00
|
|
|
case OMPC_allocator:
|
2020-02-28 09:52:15 -05:00
|
|
|
case OMPC_depobj:
|
2020-03-17 09:17:42 -04:00
|
|
|
case OMPC_detach:
|
2021-03-31 12:26:47 -07:00
|
|
|
case OMPC_novariants:
|
2021-04-03 11:09:25 -07:00
|
|
|
case OMPC_nocontext:
|
2021-04-09 14:00:36 -05:00
|
|
|
case OMPC_filter:
|
2021-06-10 14:24:17 -05:00
|
|
|
case OMPC_partial:
|
2021-11-09 07:33:39 -05:00
|
|
|
case OMPC_align:
|
2022-11-17 22:03:00 -08:00
|
|
|
case OMPC_message:
|
2023-01-07 16:14:48 -08:00
|
|
|
case OMPC_ompx_dyn_cgroup_mem:
|
2014-02-13 05:29:23 +00:00
|
|
|
// OpenMP [2.5, Restrictions]
|
2014-03-06 06:15:19 +00:00
|
|
|
// At most one num_threads clause can appear on the directive.
|
2014-03-21 04:51:18 +00:00
|
|
|
// OpenMP [2.8.1, simd construct, Restrictions]
|
2014-05-27 15:12:19 +00:00
|
|
|
// Only one safelen clause can appear on a simd directive.
|
2015-08-21 11:14:16 +00:00
|
|
|
// Only one simdlen clause can appear on a simd directive.
|
2014-05-27 15:12:19 +00:00
|
|
|
// Only one collapse clause can appear on a simd directive.
|
2014-07-17 07:32:53 +00:00
|
|
|
// OpenMP [2.11.1, task Construct, Restrictions]
|
|
|
|
// At most one if clause can appear on the directive.
|
|
|
|
// At most one final clause can appear on the directive.
|
2015-11-24 20:50:12 +00:00
|
|
|
// OpenMP [teams Construct, Restrictions]
|
|
|
|
// At most one num_teams clause can appear on the directive.
|
2015-11-27 18:47:36 +00:00
|
|
|
// At most one thread_limit clause can appear on the directive.
|
2015-12-01 10:17:31 +00:00
|
|
|
// OpenMP [2.9.1, task Construct, Restrictions]
|
|
|
|
// At most one priority clause can appear on the directive.
|
2015-12-07 12:52:51 +00:00
|
|
|
// OpenMP [2.9.2, taskloop Construct, Restrictions]
|
|
|
|
// At most one grainsize clause can appear on the directive.
|
2015-12-08 12:06:20 +00:00
|
|
|
// OpenMP [2.9.2, taskloop Construct, Restrictions]
|
|
|
|
// At most one num_tasks clause can appear on the directive.
|
2019-03-12 18:52:33 +00:00
|
|
|
// OpenMP [2.11.3, allocate Directive, Restrictions]
|
|
|
|
// At most one allocator clause can appear on the directive.
|
2020-03-17 09:17:42 -04:00
|
|
|
// OpenMP 5.0, 2.10.1 task Construct, Restrictions.
|
|
|
|
// At most one detach clause can appear on the directive.
|
2021-03-31 12:26:47 -07:00
|
|
|
// OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.
|
|
|
|
// At most one novariants clause can appear on a dispatch directive.
|
2021-04-03 11:09:25 -07:00
|
|
|
// At most one nocontext clause can appear on a dispatch directive.
|
2022-11-17 22:03:00 -08:00
|
|
|
// OpenMP [5.1, error directive, Restrictions]
|
|
|
|
// At most one message clause can appear on the directive
|
2014-02-13 05:29:23 +00:00
|
|
|
if (!FirstClause) {
|
2015-09-03 07:23:48 +00:00
|
|
|
Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
|
2014-07-23 07:46:59 +00:00
|
|
|
ErrorFound = true;
|
2014-02-13 05:29:23 +00:00
|
|
|
}
|
|
|
|
|
2021-06-10 14:24:17 -05:00
|
|
|
if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
|
|
|
|
PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
|
2018-01-09 19:21:04 +00:00
|
|
|
Clause = ParseOpenMPClause(CKind, WrongDirective);
|
2022-11-18 15:21:49 -08:00
|
|
|
else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks)
|
2022-11-17 16:20:14 -08:00
|
|
|
Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
|
2015-07-30 11:36:16 +00:00
|
|
|
else
|
2018-01-09 19:21:04 +00:00
|
|
|
Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
|
2014-02-13 05:29:23 +00:00
|
|
|
break;
|
2023-11-26 13:33:36 -06:00
|
|
|
case OMPC_fail:
|
2013-07-19 03:13:43 +00:00
|
|
|
case OMPC_default:
|
2014-05-06 06:04:14 +00:00
|
|
|
case OMPC_proc_bind:
|
2018-11-02 12:18:11 +00:00
|
|
|
case OMPC_atomic_default_mem_order:
|
2022-11-10 18:12:35 -08:00
|
|
|
case OMPC_at:
|
2022-11-16 13:29:14 -08:00
|
|
|
case OMPC_severity:
|
2021-11-03 14:57:01 -07:00
|
|
|
case OMPC_bind:
|
2014-02-13 05:29:23 +00:00
|
|
|
// OpenMP [2.14.3.1, Restrictions]
|
|
|
|
// Only a single default clause may be specified on a parallel, task or
|
|
|
|
// teams directive.
|
2014-05-06 06:04:14 +00:00
|
|
|
// OpenMP [2.5, parallel Construct, Restrictions]
|
|
|
|
// At most one proc_bind clause can appear on the directive.
|
2018-11-02 12:18:11 +00:00
|
|
|
// OpenMP [5.0, Requires directive, Restrictions]
|
|
|
|
// At most one atomic_default_mem_order clause can appear
|
|
|
|
// on the directive
|
2022-11-16 13:29:14 -08:00
|
|
|
// OpenMP [5.1, error directive, Restrictions]
|
2022-11-10 18:12:35 -08:00
|
|
|
// At most one at clause can appear on the directive
|
2022-11-16 13:29:14 -08:00
|
|
|
// At most one severity clause can appear on the directive
|
2021-11-03 14:57:01 -07:00
|
|
|
// OpenMP 5.1, 2.11.7 loop Construct, Restrictions.
|
|
|
|
// At most one bind clause can appear on a loop directive.
|
2022-12-12 15:51:38 -06:00
|
|
|
if (!FirstClause) {
|
2015-09-03 07:23:48 +00:00
|
|
|
Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
|
2014-07-23 07:46:59 +00:00
|
|
|
ErrorFound = true;
|
2013-07-19 03:13:43 +00:00
|
|
|
}
|
|
|
|
|
2018-01-09 19:21:04 +00:00
|
|
|
Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
|
2013-07-19 03:13:43 +00:00
|
|
|
break;
|
2020-03-18 15:01:15 -04:00
|
|
|
case OMPC_device:
|
2014-06-20 07:16:17 +00:00
|
|
|
case OMPC_schedule:
|
2016-01-15 18:50:31 +00:00
|
|
|
case OMPC_dist_schedule:
|
2016-01-26 16:37:23 +00:00
|
|
|
case OMPC_defaultmap:
|
2022-12-12 15:51:38 -06:00
|
|
|
case OMPC_order:
|
2014-06-20 07:16:17 +00:00
|
|
|
// OpenMP [2.7.1, Restrictions, p. 3]
|
|
|
|
// Only one schedule clause can appear on a loop directive.
|
2019-11-15 13:02:06 -05:00
|
|
|
// OpenMP 4.5 [2.10.4, Restrictions, p. 106]
|
2016-01-26 16:37:23 +00:00
|
|
|
// At most one defaultmap clause can appear on the directive.
|
2020-03-18 15:01:15 -04:00
|
|
|
// OpenMP 5.0 [2.12.5, target construct, Restrictions]
|
|
|
|
// At most one device clause can appear on the directive.
|
2022-12-12 15:51:38 -06:00
|
|
|
// OpenMP 5.1 [2.11.3, order clause, Restrictions]
|
|
|
|
// At most one order clause may appear on a construct.
|
2019-11-15 13:02:06 -05:00
|
|
|
if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
|
2022-12-12 15:51:38 -06:00
|
|
|
(CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) {
|
2015-09-03 07:23:48 +00:00
|
|
|
Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
|
2014-07-23 07:46:59 +00:00
|
|
|
ErrorFound = true;
|
2014-06-20 07:16:17 +00:00
|
|
|
}
|
2022-08-08 09:12:46 -07:00
|
|
|
[[fallthrough]];
|
2015-09-03 07:23:48 +00:00
|
|
|
case OMPC_if:
|
2020-03-18 15:01:15 -04:00
|
|
|
Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
|
2014-06-20 07:16:17 +00:00
|
|
|
break;
|
2024-08-05 12:37:07 +01:00
|
|
|
case OMPC_holds:
|
|
|
|
Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
|
|
|
|
break;
|
2014-06-20 11:19:47 +00:00
|
|
|
case OMPC_nowait:
|
2014-07-17 12:19:31 +00:00
|
|
|
case OMPC_untied:
|
2014-07-17 12:47:03 +00:00
|
|
|
case OMPC_mergeable:
|
2014-07-23 02:27:21 +00:00
|
|
|
case OMPC_read:
|
2014-07-23 07:46:59 +00:00
|
|
|
case OMPC_write:
|
2014-07-24 06:46:57 +00:00
|
|
|
case OMPC_capture:
|
2021-12-24 08:16:33 -05:00
|
|
|
case OMPC_compare:
|
2014-07-24 08:55:34 +00:00
|
|
|
case OMPC_seq_cst:
|
2020-02-06 16:30:23 -05:00
|
|
|
case OMPC_acq_rel:
|
2020-02-10 14:30:39 -05:00
|
|
|
case OMPC_acquire:
|
2020-02-10 15:49:05 -05:00
|
|
|
case OMPC_release:
|
2020-02-11 11:10:43 -05:00
|
|
|
case OMPC_relaxed:
|
2024-01-31 17:02:06 +05:30
|
|
|
case OMPC_weak:
|
2015-09-25 10:37:12 +00:00
|
|
|
case OMPC_threads:
|
2015-09-28 06:39:35 +00:00
|
|
|
case OMPC_simd:
|
2015-12-07 10:51:44 +00:00
|
|
|
case OMPC_nogroup:
|
2018-09-26 04:28:39 +00:00
|
|
|
case OMPC_unified_address:
|
2018-10-01 13:47:43 +00:00
|
|
|
case OMPC_unified_shared_memory:
|
2018-10-03 20:07:58 +00:00
|
|
|
case OMPC_reverse_offload:
|
2018-10-11 14:41:10 +00:00
|
|
|
case OMPC_dynamic_allocators:
|
2021-06-10 14:24:17 -05:00
|
|
|
case OMPC_full:
|
2014-06-20 09:44:06 +00:00
|
|
|
// OpenMP [2.7.1, Restrictions, p. 9]
|
|
|
|
// Only one ordered clause can appear on a loop directive.
|
2014-06-20 11:19:47 +00:00
|
|
|
// OpenMP [2.7.1, Restrictions, C/C++, p. 4]
|
|
|
|
// Only one nowait clause can appear on a for directive.
|
2018-09-26 04:28:39 +00:00
|
|
|
// OpenMP [5.0, Requires directive, Restrictions]
|
|
|
|
// Each of the requires clauses can appear at most once on the directive.
|
2014-06-20 09:44:06 +00:00
|
|
|
if (!FirstClause) {
|
2015-09-03 07:23:48 +00:00
|
|
|
Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
|
2014-07-23 07:46:59 +00:00
|
|
|
ErrorFound = true;
|
2014-06-20 09:44:06 +00:00
|
|
|
}
|
|
|
|
|
2025-03-11 16:31:42 +05:30
|
|
|
Clause = ParseOpenMPClause(CKind, WrongDirective);
|
|
|
|
break;
|
|
|
|
case OMPC_self_maps:
|
|
|
|
// OpenMP [6.0, self_maps clause]
|
|
|
|
if (getLangOpts().OpenMP < 60) {
|
|
|
|
Diag(Tok, diag::err_omp_expected_clause)
|
|
|
|
<< getOpenMPDirectiveName(OMPD_requires);
|
|
|
|
ErrorFound = true;
|
|
|
|
}
|
|
|
|
if (!FirstClause) {
|
|
|
|
Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
|
|
|
|
ErrorFound = true;
|
|
|
|
}
|
2018-01-09 19:21:04 +00:00
|
|
|
Clause = ParseOpenMPClause(CKind, WrongDirective);
|
2014-06-20 09:44:06 +00:00
|
|
|
break;
|
2020-03-03 13:22:35 -05:00
|
|
|
case OMPC_update:
|
|
|
|
if (!FirstClause) {
|
|
|
|
Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
|
|
|
|
ErrorFound = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Clause = (DKind == OMPD_depobj)
|
|
|
|
? ParseOpenMPSimpleClause(CKind, WrongDirective)
|
|
|
|
: ParseOpenMPClause(CKind, WrongDirective);
|
|
|
|
break;
|
2024-08-06 10:55:15 -04:00
|
|
|
case OMPC_num_teams:
|
2024-08-10 09:54:58 -04:00
|
|
|
case OMPC_thread_limit:
|
2024-08-06 10:55:15 -04:00
|
|
|
if (!FirstClause) {
|
|
|
|
Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
|
|
|
|
ErrorFound = true;
|
|
|
|
}
|
2024-08-06 12:45:29 -04:00
|
|
|
[[fallthrough]];
|
2013-07-19 03:13:43 +00:00
|
|
|
case OMPC_private:
|
2013-10-01 05:32:34 +00:00
|
|
|
case OMPC_firstprivate:
|
2014-06-04 13:06:39 +00:00
|
|
|
case OMPC_lastprivate:
|
2013-09-06 18:03:48 +00:00
|
|
|
case OMPC_shared:
|
2014-06-16 07:08:35 +00:00
|
|
|
case OMPC_reduction:
|
2017-07-18 20:17:46 +00:00
|
|
|
case OMPC_task_reduction:
|
2017-07-21 18:48:21 +00:00
|
|
|
case OMPC_in_reduction:
|
2014-04-22 13:09:42 +00:00
|
|
|
case OMPC_linear:
|
2014-05-29 14:36:25 +00:00
|
|
|
case OMPC_aligned:
|
2014-03-31 03:36:38 +00:00
|
|
|
case OMPC_copyin:
|
2014-06-27 10:37:06 +00:00
|
|
|
case OMPC_copyprivate:
|
2014-07-21 11:26:11 +00:00
|
|
|
case OMPC_flush:
|
2015-06-23 14:25:19 +00:00
|
|
|
case OMPC_depend:
|
2015-11-23 05:32:03 +00:00
|
|
|
case OMPC_map:
|
2016-05-26 17:39:58 +00:00
|
|
|
case OMPC_to:
|
2016-05-26 17:49:04 +00:00
|
|
|
case OMPC_from:
|
2016-07-13 15:37:16 +00:00
|
|
|
case OMPC_use_device_ptr:
|
2020-05-21 08:30:23 -04:00
|
|
|
case OMPC_use_device_addr:
|
2016-07-13 17:16:49 +00:00
|
|
|
case OMPC_is_device_ptr:
|
2022-04-06 20:30:44 -07:00
|
|
|
case OMPC_has_device_addr:
|
2019-03-27 14:14:31 +00:00
|
|
|
case OMPC_allocate:
|
2019-12-16 15:54:17 -05:00
|
|
|
case OMPC_nontemporal:
|
2020-03-20 09:41:22 -04:00
|
|
|
case OMPC_inclusive:
|
2020-03-23 10:41:08 -04:00
|
|
|
case OMPC_exclusive:
|
2020-05-18 13:37:53 -04:00
|
|
|
case OMPC_affinity:
|
2023-06-21 16:26:35 -07:00
|
|
|
case OMPC_doacross:
|
2023-11-22 16:13:14 -06:00
|
|
|
case OMPC_enter:
|
2023-07-06 17:55:42 -07:00
|
|
|
if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered &&
|
|
|
|
CKind == OMPC_depend)
|
|
|
|
Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);
|
2018-01-09 19:21:04 +00:00
|
|
|
Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
|
2013-07-19 03:13:43 +00:00
|
|
|
break;
|
2021-02-12 11:26:59 -08:00
|
|
|
case OMPC_sizes:
|
|
|
|
if (!FirstClause) {
|
|
|
|
Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
|
|
|
|
ErrorFound = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Clause = ParseOpenMPSizesClause();
|
|
|
|
break;
|
2024-10-09 14:56:43 +02:00
|
|
|
case OMPC_permutation:
|
|
|
|
if (!FirstClause) {
|
|
|
|
Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
|
|
|
|
ErrorFound = true;
|
|
|
|
}
|
|
|
|
Clause = ParseOpenMPPermutationClause();
|
|
|
|
break;
|
2020-04-21 13:21:00 -04:00
|
|
|
case OMPC_uses_allocators:
|
|
|
|
Clause = ParseOpenMPUsesAllocatorClause(DKind);
|
|
|
|
break;
|
2021-03-17 16:43:47 -07:00
|
|
|
case OMPC_destroy:
|
|
|
|
if (DKind != OMPD_interop) {
|
|
|
|
if (!FirstClause) {
|
|
|
|
Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
|
|
|
|
ErrorFound = true;
|
|
|
|
}
|
|
|
|
Clause = ParseOpenMPClause(CKind, WrongDirective);
|
|
|
|
break;
|
|
|
|
}
|
2022-08-08 09:12:46 -07:00
|
|
|
[[fallthrough]];
|
2021-03-15 13:09:46 -07:00
|
|
|
case OMPC_init:
|
2021-03-17 13:04:08 -07:00
|
|
|
case OMPC_use:
|
2021-03-15 13:09:46 -07:00
|
|
|
Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
|
|
|
|
break;
|
2019-08-23 16:11:14 +00:00
|
|
|
case OMPC_device_type:
|
2013-07-19 03:13:43 +00:00
|
|
|
case OMPC_unknown:
|
2020-02-21 13:48:56 -06:00
|
|
|
skipUntilPragmaOpenMPEnd(DKind);
|
2013-07-19 03:13:43 +00:00
|
|
|
break;
|
|
|
|
case OMPC_threadprivate:
|
2016-04-12 05:28:34 +00:00
|
|
|
case OMPC_uniform:
|
2019-09-23 18:13:31 +00:00
|
|
|
case OMPC_match:
|
2018-01-09 19:21:04 +00:00
|
|
|
if (!WrongDirective)
|
|
|
|
Diag(Tok, diag::err_omp_unexpected_clause)
|
|
|
|
<< getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
|
2013-12-18 19:10:49 +00:00
|
|
|
SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
|
2013-07-19 03:13:43 +00:00
|
|
|
break;
|
2024-08-05 12:37:07 +01:00
|
|
|
case OMPC_absent:
|
|
|
|
case OMPC_contains: {
|
|
|
|
SourceLocation Loc = ConsumeToken();
|
|
|
|
SourceLocation LLoc = Tok.getLocation();
|
|
|
|
SourceLocation RLoc;
|
|
|
|
llvm::SmallVector<OpenMPDirectiveKind, 4> DKVec;
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren);
|
|
|
|
T.consumeOpen();
|
|
|
|
do {
|
|
|
|
OpenMPDirectiveKind DK = getOpenMPDirectiveKind(PP.getSpelling(Tok));
|
|
|
|
if (DK == OMPD_unknown) {
|
|
|
|
skipUntilPragmaOpenMPEnd(OMPD_assume);
|
|
|
|
Diag(Tok, diag::err_omp_unexpected_clause)
|
|
|
|
<< getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (isOpenMPExecutableDirective(DK)) {
|
|
|
|
DKVec.push_back(DK);
|
|
|
|
ConsumeToken();
|
|
|
|
} else {
|
|
|
|
Diag(Tok, diag::err_omp_unexpected_clause)
|
|
|
|
<< getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
|
|
|
|
}
|
|
|
|
} while (TryConsumeToken(tok::comma));
|
|
|
|
RLoc = Tok.getLocation();
|
|
|
|
T.consumeClose();
|
|
|
|
Clause = Actions.OpenMP().ActOnOpenMPDirectivePresenceClause(
|
|
|
|
CKind, DKVec, Loc, LLoc, RLoc);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OMPC_no_openmp:
|
|
|
|
case OMPC_no_openmp_routines:
|
2025-02-06 12:41:10 -08:00
|
|
|
case OMPC_no_openmp_constructs:
|
2024-08-05 12:37:07 +01:00
|
|
|
case OMPC_no_parallelism: {
|
|
|
|
if (!FirstClause) {
|
|
|
|
Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
|
|
|
|
ErrorFound = true;
|
|
|
|
}
|
|
|
|
SourceLocation Loc = ConsumeToken();
|
|
|
|
Clause = Actions.OpenMP().ActOnOpenMPNullaryAssumptionClause(
|
|
|
|
CKind, Loc, Tok.getLocation());
|
|
|
|
break;
|
|
|
|
}
|
2023-07-25 09:37:49 -07:00
|
|
|
case OMPC_ompx_attribute:
|
|
|
|
Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);
|
|
|
|
break;
|
Introduce the initial support for OpenMP kernel language (#66844)
This patch starts the support for OpenMP kernel language, basically to write
OpenMP target region in SIMT style, similar to kernel languages such as CUDA.
What included in this first patch is the `ompx_bare` clause for `target teams`
directive. When `ompx_bare` exists, globalization is disabled such that local
variables will not be globalized. The runtime init/deinit function calls will
not be emitted. That being said, almost all OpenMP executable directives are
not supported in the region, such as parallel, task. This patch doesn't include
the Sema checks for that, so the use of them is UB. Simple directives, such as
atomic, can be used. We provide a set of APIs (for C, they are prefix with
`ompx_`; for C++, they are in `ompx` namespace) to get thread id, block id, etc.
Please refer to
https://tianshilei.me/wp-content/uploads/llvm-hpc-2023.pdf for more details.
2023-10-05 17:34:40 -04:00
|
|
|
case OMPC_ompx_bare:
|
2024-12-13 21:44:43 +09:00
|
|
|
if (DKind == llvm::omp::Directive::OMPD_target) {
|
|
|
|
// Flang splits the combined directives which requires OMPD_target to be
|
|
|
|
// marked as accepting the `ompx_bare` clause in `OMP.td`. Thus, we need
|
|
|
|
// to explicitly check whether this clause is applied to an `omp target`
|
|
|
|
// without `teams` and emit an error.
|
|
|
|
Diag(Tok, diag::err_omp_unexpected_clause)
|
|
|
|
<< getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
|
|
|
|
ErrorFound = true;
|
|
|
|
WrongDirective = true;
|
|
|
|
}
|
Introduce the initial support for OpenMP kernel language (#66844)
This patch starts the support for OpenMP kernel language, basically to write
OpenMP target region in SIMT style, similar to kernel languages such as CUDA.
What included in this first patch is the `ompx_bare` clause for `target teams`
directive. When `ompx_bare` exists, globalization is disabled such that local
variables will not be globalized. The runtime init/deinit function calls will
not be emitted. That being said, almost all OpenMP executable directives are
not supported in the region, such as parallel, task. This patch doesn't include
the Sema checks for that, so the use of them is UB. Simple directives, such as
atomic, can be used. We provide a set of APIs (for C, they are prefix with
`ompx_`; for C++, they are in `ompx` namespace) to get thread id, block id, etc.
Please refer to
https://tianshilei.me/wp-content/uploads/llvm-hpc-2023.pdf for more details.
2023-10-05 17:34:40 -04:00
|
|
|
if (WrongDirective)
|
|
|
|
Diag(Tok, diag::note_ompx_bare_clause)
|
|
|
|
<< getOpenMPClauseName(CKind) << "target teams";
|
|
|
|
if (!ErrorFound && !getLangOpts().OpenMPExtensions) {
|
|
|
|
Diag(Tok, diag::err_omp_unexpected_clause_extension_only)
|
|
|
|
<< getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
|
|
|
|
ErrorFound = true;
|
|
|
|
}
|
|
|
|
Clause = ParseOpenMPClause(CKind, WrongDirective);
|
|
|
|
break;
|
[flang][openmp] Use common Directive and Clause enum from llvm/Frontend
Summary:
This patch is removing the custom enumeration for OpenMP Directives and Clauses and replace them
with the newly tablegen generated one from llvm/Frontend. This is a first patch and some will follow to share the same
infrastructure where possible. The next patch should use the clauses allowance defined in the tablegen file.
Reviewers: jdoerfert, DavidTruby, sscalpone, kiranchandramohan, ichoyjx
Reviewed By: DavidTruby, ichoyjx
Subscribers: jholewinski, cfe-commits, dblaikie, MaskRay, ymandel, ichoyjx, mgorny, yaxunl, guansong, jfb, sstefan1, aaron.ballman, llvm-commits
Tags: #llvm, #flang, #clang
Differential Revision: https://reviews.llvm.org/D82906
2020-07-01 20:57:11 -04:00
|
|
|
default:
|
|
|
|
break;
|
2013-07-19 03:13:43 +00:00
|
|
|
}
|
2014-05-21 06:02:52 +00:00
|
|
|
return ErrorFound ? nullptr : Clause;
|
2013-07-19 03:13:43 +00:00
|
|
|
}
|
|
|
|
|
2016-04-07 12:45:37 +00:00
|
|
|
/// Parses simple expression in parens for single-expression clauses of OpenMP
|
|
|
|
/// constructs.
|
|
|
|
/// \param RLoc Returned location of right paren.
|
|
|
|
ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
|
2019-09-13 20:18:17 +00:00
|
|
|
SourceLocation &RLoc,
|
|
|
|
bool IsAddressOfOperand) {
|
2016-04-07 12:45:37 +00:00
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
SourceLocation ELoc = Tok.getLocation();
|
2020-10-29 18:44:28 -05:00
|
|
|
ExprResult LHS(
|
|
|
|
ParseCastExpression(AnyCastExpr, IsAddressOfOperand, NotTypeCast));
|
2016-04-07 12:45:37 +00:00
|
|
|
ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
|
2019-01-04 16:58:14 +00:00
|
|
|
Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
|
2016-04-07 12:45:37 +00:00
|
|
|
|
|
|
|
// Parse ')'.
|
2018-07-06 19:35:42 +00:00
|
|
|
RLoc = Tok.getLocation();
|
|
|
|
if (!T.consumeClose())
|
|
|
|
RLoc = T.getCloseLocation();
|
2016-04-07 12:45:37 +00:00
|
|
|
|
|
|
|
return Val;
|
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Parsing of OpenMP clauses with single expressions like 'final',
|
2015-12-01 10:17:31 +00:00
|
|
|
/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
|
2020-03-17 09:17:42 -04:00
|
|
|
/// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'hint' or
|
|
|
|
/// 'detach'.
|
2014-02-13 05:29:23 +00:00
|
|
|
///
|
2014-07-17 07:32:53 +00:00
|
|
|
/// final-clause:
|
|
|
|
/// 'final' '(' expression ')'
|
|
|
|
///
|
2014-03-21 04:51:18 +00:00
|
|
|
/// num_threads-clause:
|
|
|
|
/// 'num_threads' '(' expression ')'
|
|
|
|
///
|
|
|
|
/// safelen-clause:
|
|
|
|
/// 'safelen' '(' expression ')'
|
|
|
|
///
|
2015-08-21 11:14:16 +00:00
|
|
|
/// simdlen-clause:
|
|
|
|
/// 'simdlen' '(' expression ')'
|
|
|
|
///
|
2014-05-27 15:12:19 +00:00
|
|
|
/// collapse-clause:
|
|
|
|
/// 'collapse' '(' expression ')'
|
|
|
|
///
|
2015-12-01 10:17:31 +00:00
|
|
|
/// priority-clause:
|
|
|
|
/// 'priority' '(' expression ')'
|
|
|
|
///
|
2015-12-07 12:52:51 +00:00
|
|
|
/// grainsize-clause:
|
|
|
|
/// 'grainsize' '(' expression ')'
|
|
|
|
///
|
2015-12-08 12:06:20 +00:00
|
|
|
/// num_tasks-clause:
|
|
|
|
/// 'num_tasks' '(' expression ')'
|
|
|
|
///
|
2015-12-15 08:19:24 +00:00
|
|
|
/// hint-clause:
|
|
|
|
/// 'hint' '(' expression ')'
|
|
|
|
///
|
2019-03-12 18:52:33 +00:00
|
|
|
/// allocator-clause:
|
|
|
|
/// 'allocator' '(' expression ')'
|
|
|
|
///
|
2020-03-17 09:17:42 -04:00
|
|
|
/// detach-clause:
|
|
|
|
/// 'detach' '(' event-handler-expression ')'
|
|
|
|
///
|
2021-11-09 07:33:39 -05:00
|
|
|
/// align-clause
|
|
|
|
/// 'align' '(' positive-integer-constant ')'
|
|
|
|
///
|
2024-08-05 12:37:07 +01:00
|
|
|
/// holds-clause
|
|
|
|
/// 'holds' '(' expression ')'
|
|
|
|
///
|
2018-01-09 19:21:04 +00:00
|
|
|
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
|
|
|
|
bool ParseOnly) {
|
2014-02-13 05:29:23 +00:00
|
|
|
SourceLocation Loc = ConsumeToken();
|
2016-04-07 12:45:37 +00:00
|
|
|
SourceLocation LLoc = Tok.getLocation();
|
|
|
|
SourceLocation RLoc;
|
2014-02-13 05:29:23 +00:00
|
|
|
|
2016-04-07 12:45:37 +00:00
|
|
|
ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
|
2014-02-13 05:29:23 +00:00
|
|
|
|
|
|
|
if (Val.isInvalid())
|
2014-05-21 06:02:52 +00:00
|
|
|
return nullptr;
|
2014-02-13 05:29:23 +00:00
|
|
|
|
2018-01-09 19:21:04 +00:00
|
|
|
if (ParseOnly)
|
|
|
|
return nullptr;
|
2024-04-16 16:36:53 +04:00
|
|
|
return Actions.OpenMP().ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc,
|
|
|
|
LLoc, RLoc);
|
2014-02-13 05:29:23 +00:00
|
|
|
}
|
|
|
|
|
2022-01-10 16:20:02 -08:00
|
|
|
/// Parse indirect clause for '#pragma omp declare target' directive.
|
|
|
|
/// 'indirect' '[' '(' invoked-by-fptr ')' ']'
|
|
|
|
/// where invoked-by-fptr is a constant boolean expression that evaluates to
|
|
|
|
/// true or false at compile time.
|
2024-04-16 16:36:53 +04:00
|
|
|
bool Parser::ParseOpenMPIndirectClause(
|
|
|
|
SemaOpenMP::DeclareTargetContextInfo &DTCI, bool ParseOnly) {
|
2022-01-10 16:20:02 -08:00
|
|
|
SourceLocation Loc = ConsumeToken();
|
|
|
|
SourceLocation RLoc;
|
|
|
|
|
|
|
|
if (Tok.isNot(tok::l_paren)) {
|
|
|
|
if (ParseOnly)
|
|
|
|
return false;
|
|
|
|
DTCI.Indirect = nullptr;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprResult Val =
|
|
|
|
ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc);
|
|
|
|
if (Val.isInvalid())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (ParseOnly)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() &&
|
|
|
|
!Val.get()->isInstantiationDependent() &&
|
|
|
|
!Val.get()->containsUnexpandedParameterPack()) {
|
|
|
|
ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get());
|
|
|
|
if (Ret.isInvalid())
|
|
|
|
return false;
|
|
|
|
llvm::APSInt Result;
|
|
|
|
Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result,
|
|
|
|
Sema::AllowFold);
|
|
|
|
if (Ret.isInvalid())
|
|
|
|
return false;
|
|
|
|
DTCI.Indirect = Val.get();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-08-18 11:54:52 -07:00
|
|
|
/// Parses a comma-separated list of interop-types and a prefer_type list.
|
|
|
|
///
|
|
|
|
bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,
|
|
|
|
OpenMPClauseKind Kind) {
|
|
|
|
const Token &Tok = getCurToken();
|
|
|
|
bool HasError = false;
|
|
|
|
bool IsTarget = false;
|
|
|
|
bool IsTargetSync = false;
|
|
|
|
|
|
|
|
while (Tok.is(tok::identifier)) {
|
|
|
|
// Currently prefer_type is only allowed with 'init' and it must be first.
|
|
|
|
bool PreferTypeAllowed = Kind == OMPC_init &&
|
|
|
|
InteropInfo.PreferTypes.empty() && !IsTarget &&
|
|
|
|
!IsTargetSync;
|
|
|
|
if (Tok.getIdentifierInfo()->isStr("target")) {
|
|
|
|
// OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
|
|
|
|
// Each interop-type may be specified on an action-clause at most
|
|
|
|
// once.
|
|
|
|
if (IsTarget)
|
|
|
|
Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";
|
|
|
|
IsTarget = true;
|
|
|
|
ConsumeToken();
|
|
|
|
} else if (Tok.getIdentifierInfo()->isStr("targetsync")) {
|
|
|
|
if (IsTargetSync)
|
|
|
|
Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
|
|
|
|
IsTargetSync = true;
|
|
|
|
ConsumeToken();
|
|
|
|
} else if (Tok.getIdentifierInfo()->isStr("prefer_type") &&
|
|
|
|
PreferTypeAllowed) {
|
|
|
|
ConsumeToken();
|
|
|
|
BalancedDelimiterTracker PT(*this, tok::l_paren,
|
|
|
|
tok::annot_pragma_openmp_end);
|
|
|
|
if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
|
|
|
|
HasError = true;
|
|
|
|
|
|
|
|
while (Tok.isNot(tok::r_paren)) {
|
|
|
|
SourceLocation Loc = Tok.getLocation();
|
|
|
|
ExprResult LHS = ParseCastExpression(AnyCastExpr);
|
|
|
|
ExprResult PTExpr = Actions.CorrectDelayedTyposInExpr(
|
|
|
|
ParseRHSOfBinaryExpression(LHS, prec::Conditional));
|
|
|
|
PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
|
|
|
|
/*DiscardedValue=*/false);
|
|
|
|
if (PTExpr.isUsable()) {
|
|
|
|
InteropInfo.PreferTypes.push_back(PTExpr.get());
|
|
|
|
} else {
|
|
|
|
HasError = true;
|
|
|
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
|
|
|
}
|
|
|
|
PT.consumeClose();
|
|
|
|
} else {
|
|
|
|
HasError = true;
|
|
|
|
Diag(Tok, diag::err_omp_expected_interop_type);
|
|
|
|
ConsumeToken();
|
|
|
|
}
|
|
|
|
if (!Tok.is(tok::comma))
|
|
|
|
break;
|
|
|
|
ConsumeToken();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!HasError && !IsTarget && !IsTargetSync) {
|
|
|
|
Diag(Tok, diag::err_omp_expected_interop_type);
|
|
|
|
HasError = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Kind == OMPC_init) {
|
|
|
|
if (Tok.isNot(tok::colon) && (IsTarget || IsTargetSync))
|
|
|
|
Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
|
|
|
|
if (Tok.is(tok::colon))
|
|
|
|
ConsumeToken();
|
|
|
|
}
|
|
|
|
|
|
|
|
// As of OpenMP 5.1,there are two interop-types, "target" and
|
|
|
|
// "targetsync". Either or both are allowed for a single interop.
|
|
|
|
InteropInfo.IsTarget = IsTarget;
|
|
|
|
InteropInfo.IsTargetSync = IsTargetSync;
|
|
|
|
|
|
|
|
return HasError;
|
|
|
|
}
|
|
|
|
|
2021-03-15 13:09:46 -07:00
|
|
|
/// Parsing of OpenMP clauses that use an interop-var.
|
|
|
|
///
|
|
|
|
/// init-clause:
|
|
|
|
/// init([interop-modifier, ]interop-type[[, interop-type] ... ]:interop-var)
|
|
|
|
///
|
|
|
|
/// destroy-clause:
|
|
|
|
/// destroy(interop-var)
|
|
|
|
///
|
|
|
|
/// use-clause:
|
|
|
|
/// use(interop-var)
|
|
|
|
///
|
|
|
|
/// interop-modifier:
|
|
|
|
/// prefer_type(preference-list)
|
|
|
|
///
|
|
|
|
/// preference-list:
|
|
|
|
/// foreign-runtime-id [, foreign-runtime-id]...
|
|
|
|
///
|
|
|
|
/// foreign-runtime-id:
|
|
|
|
/// <string-literal> | <constant-integral-expression>
|
|
|
|
///
|
|
|
|
/// interop-type:
|
|
|
|
/// target | targetsync
|
|
|
|
///
|
|
|
|
OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
|
|
|
|
bool ParseOnly) {
|
|
|
|
SourceLocation Loc = ConsumeToken();
|
|
|
|
// Parse '('.
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
|
|
|
getOpenMPClauseName(Kind).data()))
|
|
|
|
return nullptr;
|
|
|
|
|
2022-08-18 11:54:52 -07:00
|
|
|
bool InteropError = false;
|
|
|
|
OMPInteropInfo InteropInfo;
|
|
|
|
if (Kind == OMPC_init)
|
|
|
|
InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);
|
2021-03-15 13:09:46 -07:00
|
|
|
|
|
|
|
// Parse the variable.
|
|
|
|
SourceLocation VarLoc = Tok.getLocation();
|
|
|
|
ExprResult InteropVarExpr =
|
|
|
|
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
|
|
|
|
if (!InteropVarExpr.isUsable()) {
|
|
|
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse ')'.
|
|
|
|
SourceLocation RLoc = Tok.getLocation();
|
|
|
|
if (!T.consumeClose())
|
|
|
|
RLoc = T.getCloseLocation();
|
|
|
|
|
2022-08-18 11:54:52 -07:00
|
|
|
if (ParseOnly || !InteropVarExpr.isUsable() || InteropError)
|
2021-03-15 13:09:46 -07:00
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if (Kind == OMPC_init)
|
2024-04-16 16:36:53 +04:00
|
|
|
return Actions.OpenMP().ActOnOpenMPInitClause(
|
|
|
|
InteropVarExpr.get(), InteropInfo, Loc, T.getOpenLocation(), VarLoc,
|
|
|
|
RLoc);
|
2021-03-17 13:04:08 -07:00
|
|
|
if (Kind == OMPC_use)
|
2024-04-16 16:36:53 +04:00
|
|
|
return Actions.OpenMP().ActOnOpenMPUseClause(
|
|
|
|
InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
|
2021-03-15 13:09:46 -07:00
|
|
|
|
2021-03-17 16:43:47 -07:00
|
|
|
if (Kind == OMPC_destroy)
|
2024-04-16 16:36:53 +04:00
|
|
|
return Actions.OpenMP().ActOnOpenMPDestroyClause(
|
|
|
|
InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
|
2021-03-17 16:43:47 -07:00
|
|
|
|
2021-03-15 13:09:46 -07:00
|
|
|
llvm_unreachable("Unexpected interop variable clause.");
|
|
|
|
}
|
|
|
|
|
2023-07-25 09:37:49 -07:00
|
|
|
OMPClause *Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly) {
|
|
|
|
SourceLocation Loc = ConsumeToken();
|
|
|
|
// Parse '('.
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
|
|
|
getOpenMPClauseName(OMPC_ompx_attribute).data()))
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
ParsedAttributes ParsedAttrs(AttrFactory);
|
|
|
|
ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs);
|
|
|
|
|
|
|
|
// Parse ')'.
|
|
|
|
if (T.consumeClose())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if (ParseOnly)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
SmallVector<Attr *> Attrs;
|
|
|
|
for (const ParsedAttr &PA : ParsedAttrs) {
|
|
|
|
switch (PA.getKind()) {
|
|
|
|
case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
|
|
|
|
if (!PA.checkExactlyNumArgs(Actions, 2))
|
|
|
|
continue;
|
[clang] Introduce target-specific `Sema` components (#93179)
This patch introduces `SemaAMDGPU`, `SemaARM`, `SemaBPF`, `SemaHexagon`,
`SemaLoongArch`, `SemaMIPS`, `SemaNVPTX`, `SemaPPC`, `SemaSystemZ`,
`SemaWasm`. This continues previous efforts to split Sema up. Additional
context can be found in #84184 and #92682.
I decided to bundle target-specific components together because of their
low impact on `Sema`. That said, their impact on `SemaChecking.cpp` is
far from low, and I consider it a success.
Somewhat accidentally, I also moved Wasm- and AMDGPU-specific function
from `SemaDeclAttr.cpp`, because they were exposed in `Sema`. That went
well, and I consider it a success, too. I'd like to move the rest of
static target-specific functions out of `SemaDeclAttr.cpp` like we're
doing with built-ins in `SemaChecking.cpp` .
2024-05-30 19:59:59 +04:00
|
|
|
if (auto *A = Actions.AMDGPU().CreateAMDGPUFlatWorkGroupSizeAttr(
|
2023-07-25 09:37:49 -07:00
|
|
|
PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1)))
|
|
|
|
Attrs.push_back(A);
|
|
|
|
continue;
|
|
|
|
case ParsedAttr::AT_AMDGPUWavesPerEU:
|
|
|
|
if (!PA.checkAtLeastNumArgs(Actions, 1) ||
|
|
|
|
!PA.checkAtMostNumArgs(Actions, 2))
|
|
|
|
continue;
|
[clang] Introduce target-specific `Sema` components (#93179)
This patch introduces `SemaAMDGPU`, `SemaARM`, `SemaBPF`, `SemaHexagon`,
`SemaLoongArch`, `SemaMIPS`, `SemaNVPTX`, `SemaPPC`, `SemaSystemZ`,
`SemaWasm`. This continues previous efforts to split Sema up. Additional
context can be found in #84184 and #92682.
I decided to bundle target-specific components together because of their
low impact on `Sema`. That said, their impact on `SemaChecking.cpp` is
far from low, and I consider it a success.
Somewhat accidentally, I also moved Wasm- and AMDGPU-specific function
from `SemaDeclAttr.cpp`, because they were exposed in `Sema`. That went
well, and I consider it a success, too. I'd like to move the rest of
static target-specific functions out of `SemaDeclAttr.cpp` like we're
doing with built-ins in `SemaChecking.cpp` .
2024-05-30 19:59:59 +04:00
|
|
|
if (auto *A = Actions.AMDGPU().CreateAMDGPUWavesPerEUAttr(
|
2023-07-25 09:37:49 -07:00
|
|
|
PA, PA.getArgAsExpr(0),
|
|
|
|
PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr))
|
|
|
|
Attrs.push_back(A);
|
|
|
|
continue;
|
|
|
|
case ParsedAttr::AT_CUDALaunchBounds:
|
|
|
|
if (!PA.checkAtLeastNumArgs(Actions, 1) ||
|
|
|
|
!PA.checkAtMostNumArgs(Actions, 2))
|
|
|
|
continue;
|
|
|
|
if (auto *A = Actions.CreateLaunchBoundsAttr(
|
|
|
|
PA, PA.getArgAsExpr(0),
|
2023-09-29 08:39:31 +02:00
|
|
|
PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr,
|
|
|
|
PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) : nullptr))
|
2023-07-25 09:37:49 -07:00
|
|
|
Attrs.push_back(A);
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
Diag(Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;
|
|
|
|
continue;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2024-04-16 16:36:53 +04:00
|
|
|
return Actions.OpenMP().ActOnOpenMPXAttributeClause(
|
|
|
|
Attrs, Loc, T.getOpenLocation(), T.getCloseLocation());
|
2023-07-25 09:37:49 -07:00
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
|
2013-07-19 03:13:43 +00:00
|
|
|
///
|
|
|
|
/// default-clause:
|
2022-05-17 14:17:32 -07:00
|
|
|
/// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ')'
|
2013-07-19 03:13:43 +00:00
|
|
|
///
|
2014-05-06 06:04:14 +00:00
|
|
|
/// proc_bind-clause:
|
2020-03-03 13:22:35 -05:00
|
|
|
/// 'proc_bind' '(' 'master' | 'close' | 'spread' ')'
|
|
|
|
///
|
2021-11-03 14:57:01 -07:00
|
|
|
/// bind-clause:
|
|
|
|
/// 'bind' '(' 'teams' | 'parallel' | 'thread' ')'
|
|
|
|
///
|
2020-03-03 13:22:35 -05:00
|
|
|
/// update-clause:
|
2022-02-08 08:33:52 -05:00
|
|
|
/// 'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' |
|
|
|
|
/// 'inoutset' ')'
|
2014-05-06 06:04:14 +00:00
|
|
|
///
|
2018-01-09 19:21:04 +00:00
|
|
|
OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
|
|
|
|
bool ParseOnly) {
|
2023-01-14 12:31:01 -08:00
|
|
|
std::optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
|
2019-08-23 16:11:14 +00:00
|
|
|
if (!Val || ParseOnly)
|
2018-01-09 19:21:04 +00:00
|
|
|
return nullptr;
|
2020-07-12 22:19:40 -05:00
|
|
|
if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
|
2022-12-17 06:37:59 +00:00
|
|
|
(static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private ||
|
|
|
|
static_cast<DefaultKind>(Val->Type) ==
|
2022-06-25 11:56:50 -07:00
|
|
|
OMP_DEFAULT_firstprivate)) {
|
2022-12-17 06:37:59 +00:00
|
|
|
Diag(Val->LOpen, diag::err_omp_invalid_dsa)
|
|
|
|
<< getOpenMPClauseName(static_cast<DefaultKind>(Val->Type) ==
|
2022-05-17 14:17:32 -07:00
|
|
|
OMP_DEFAULT_private
|
|
|
|
? OMPC_private
|
|
|
|
: OMPC_firstprivate)
|
2020-07-12 22:19:40 -05:00
|
|
|
<< getOpenMPClauseName(OMPC_default) << "5.1";
|
|
|
|
return nullptr;
|
|
|
|
}
|
2024-04-16 16:36:53 +04:00
|
|
|
return Actions.OpenMP().ActOnOpenMPSimpleClause(
|
|
|
|
Kind, Val->Type, Val->TypeLoc, Val->LOpen, Val->Loc, Val->RLoc);
|
2013-07-19 03:13:43 +00:00
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Parsing of OpenMP clauses like 'ordered'.
|
2014-06-20 09:44:06 +00:00
|
|
|
///
|
|
|
|
/// ordered-clause:
|
|
|
|
/// 'ordered'
|
|
|
|
///
|
2014-06-20 11:19:47 +00:00
|
|
|
/// nowait-clause:
|
|
|
|
/// 'nowait'
|
|
|
|
///
|
2014-07-17 12:19:31 +00:00
|
|
|
/// untied-clause:
|
|
|
|
/// 'untied'
|
|
|
|
///
|
2014-07-17 12:47:03 +00:00
|
|
|
/// mergeable-clause:
|
|
|
|
/// 'mergeable'
|
|
|
|
///
|
2014-07-23 02:27:21 +00:00
|
|
|
/// read-clause:
|
|
|
|
/// 'read'
|
|
|
|
///
|
2015-09-25 10:37:12 +00:00
|
|
|
/// threads-clause:
|
|
|
|
/// 'threads'
|
|
|
|
///
|
2015-09-28 06:39:35 +00:00
|
|
|
/// simd-clause:
|
|
|
|
/// 'simd'
|
|
|
|
///
|
2015-12-07 10:51:44 +00:00
|
|
|
/// nogroup-clause:
|
|
|
|
/// 'nogroup'
|
|
|
|
///
|
2018-01-09 19:21:04 +00:00
|
|
|
OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
|
2014-06-20 09:44:06 +00:00
|
|
|
SourceLocation Loc = Tok.getLocation();
|
|
|
|
ConsumeAnyToken();
|
|
|
|
|
2018-01-09 19:21:04 +00:00
|
|
|
if (ParseOnly)
|
|
|
|
return nullptr;
|
2024-04-16 16:36:53 +04:00
|
|
|
return Actions.OpenMP().ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
|
2014-06-20 09:44:06 +00:00
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Parsing of OpenMP clauses with single expressions and some additional
|
2014-06-20 07:16:17 +00:00
|
|
|
/// argument like 'schedule' or 'dist_schedule'.
|
|
|
|
///
|
|
|
|
/// schedule-clause:
|
2015-12-28 07:25:51 +00:00
|
|
|
/// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
|
|
|
|
/// ')'
|
2014-06-20 07:16:17 +00:00
|
|
|
///
|
2015-09-03 07:23:48 +00:00
|
|
|
/// if-clause:
|
|
|
|
/// 'if' '(' [ directive-name-modifier ':' ] expression ')'
|
|
|
|
///
|
2016-01-26 16:37:23 +00:00
|
|
|
/// defaultmap:
|
2020-04-08 15:19:54 -04:00
|
|
|
/// 'defaultmap' '(' modifier [ ':' kind ] ')'
|
2016-01-26 16:37:23 +00:00
|
|
|
///
|
2020-03-18 15:01:15 -04:00
|
|
|
/// device-clause:
|
|
|
|
/// 'device' '(' [ device-modifier ':' ] expression ')'
|
|
|
|
///
|
|
|
|
OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
|
|
|
|
OpenMPClauseKind Kind,
|
2018-01-09 19:21:04 +00:00
|
|
|
bool ParseOnly) {
|
2014-06-20 07:16:17 +00:00
|
|
|
SourceLocation Loc = ConsumeToken();
|
2015-09-03 07:23:48 +00:00
|
|
|
SourceLocation DelimLoc;
|
2014-06-20 07:16:17 +00:00
|
|
|
// Parse '('.
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
2020-03-30 19:58:40 -05:00
|
|
|
getOpenMPClauseName(Kind).data()))
|
2014-06-20 07:16:17 +00:00
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
ExprResult Val;
|
2015-12-28 07:25:51 +00:00
|
|
|
SmallVector<unsigned, 4> Arg;
|
|
|
|
SmallVector<SourceLocation, 4> KLoc;
|
2015-09-03 07:23:48 +00:00
|
|
|
if (Kind == OMPC_schedule) {
|
2015-12-28 07:25:51 +00:00
|
|
|
enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
|
|
|
|
Arg.resize(NumberOfElements);
|
|
|
|
KLoc.resize(NumberOfElements);
|
|
|
|
Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
|
|
|
|
Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
|
|
|
|
Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
|
2018-04-23 19:53:05 +00:00
|
|
|
unsigned KindModifier = getOpenMPSimpleClauseType(
|
[OpenMP][OpenACC] Implement `ompx_hold` map type modifier extension in Clang (1/2)
This patch implements Clang support for an original OpenMP extension
we have developed to support OpenACC: the `ompx_hold` map type
modifier. The next patch in this series, D106510, implements OpenMP
runtime support.
Consider the following example:
```
#pragma omp target data map(ompx_hold, tofrom: x) // holds onto mapping of x
{
foo(); // might have map(delete: x)
#pragma omp target map(present, alloc: x) // x is guaranteed to be present
printf("%d\n", x);
}
```
The `ompx_hold` map type modifier above specifies that the `target
data` directive holds onto the mapping for `x` throughout the
associated region regardless of any `target exit data` directives
executed during the call to `foo`. Thus, the presence assertion for
`x` at the enclosed `target` construct cannot fail. (As usual, the
standard OpenMP reference count for `x` must also reach zero before
the data is unmapped.)
Justification for inclusion in Clang and LLVM's OpenMP runtime:
* The `ompx_hold` modifier supports OpenACC functionality (structured
reference count) that cannot be achieved in standard OpenMP, as of
5.1.
* The runtime implementation for `ompx_hold` (next patch) will thus be
used by Flang's OpenACC support.
* The Clang implementation for `ompx_hold` (this patch) as well as the
runtime implementation are required for the Clang OpenACC support
being developed as part of the ECP Clacc project, which translates
OpenACC to OpenMP at the directive AST level. These patches are the
first step in upstreaming OpenACC functionality from Clacc.
* The Clang implementation for `ompx_hold` is also used by the tests
in the runtime implementation. That syntactic support makes the
tests more readable than low-level runtime calls can. Moreover,
upstream Flang and Clang do not yet support OpenACC syntax
sufficiently for writing the tests.
* More generally, the Clang implementation enables a clean separation
of concerns between OpenACC and OpenMP development in LLVM. That
is, LLVM's OpenMP developers can discuss, modify, and debug LLVM's
extended OpenMP implementation and test suite without directly
considering OpenACC's language and execution model, which can be
handled by LLVM's OpenACC developers.
* OpenMP users might find the `ompx_hold` modifier useful, as in the
above example.
See new documentation introduced by this patch in `openmp/docs` for
more detail on the functionality of this extension and its
relationship with OpenACC. For example, it explains how the runtime
must support two reference counts, as specified by OpenACC.
Clang recognizes `ompx_hold` unless `-fno-openmp-extensions`, a new
command-line option introduced by this patch, is specified.
Reviewed By: ABataev, jdoerfert, protze.joachim, grokos
Differential Revision: https://reviews.llvm.org/D106509
2021-08-31 15:17:07 -04:00
|
|
|
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
|
2015-12-28 07:25:51 +00:00
|
|
|
if (KindModifier > OMPC_SCHEDULE_unknown) {
|
|
|
|
// Parse 'modifier'
|
|
|
|
Arg[Modifier1] = KindModifier;
|
|
|
|
KLoc[Modifier1] = Tok.getLocation();
|
|
|
|
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
if (Tok.is(tok::comma)) {
|
|
|
|
// Parse ',' 'modifier'
|
|
|
|
ConsumeAnyToken();
|
|
|
|
KindModifier = getOpenMPSimpleClauseType(
|
[OpenMP][OpenACC] Implement `ompx_hold` map type modifier extension in Clang (1/2)
This patch implements Clang support for an original OpenMP extension
we have developed to support OpenACC: the `ompx_hold` map type
modifier. The next patch in this series, D106510, implements OpenMP
runtime support.
Consider the following example:
```
#pragma omp target data map(ompx_hold, tofrom: x) // holds onto mapping of x
{
foo(); // might have map(delete: x)
#pragma omp target map(present, alloc: x) // x is guaranteed to be present
printf("%d\n", x);
}
```
The `ompx_hold` map type modifier above specifies that the `target
data` directive holds onto the mapping for `x` throughout the
associated region regardless of any `target exit data` directives
executed during the call to `foo`. Thus, the presence assertion for
`x` at the enclosed `target` construct cannot fail. (As usual, the
standard OpenMP reference count for `x` must also reach zero before
the data is unmapped.)
Justification for inclusion in Clang and LLVM's OpenMP runtime:
* The `ompx_hold` modifier supports OpenACC functionality (structured
reference count) that cannot be achieved in standard OpenMP, as of
5.1.
* The runtime implementation for `ompx_hold` (next patch) will thus be
used by Flang's OpenACC support.
* The Clang implementation for `ompx_hold` (this patch) as well as the
runtime implementation are required for the Clang OpenACC support
being developed as part of the ECP Clacc project, which translates
OpenACC to OpenMP at the directive AST level. These patches are the
first step in upstreaming OpenACC functionality from Clacc.
* The Clang implementation for `ompx_hold` is also used by the tests
in the runtime implementation. That syntactic support makes the
tests more readable than low-level runtime calls can. Moreover,
upstream Flang and Clang do not yet support OpenACC syntax
sufficiently for writing the tests.
* More generally, the Clang implementation enables a clean separation
of concerns between OpenACC and OpenMP development in LLVM. That
is, LLVM's OpenMP developers can discuss, modify, and debug LLVM's
extended OpenMP implementation and test suite without directly
considering OpenACC's language and execution model, which can be
handled by LLVM's OpenACC developers.
* OpenMP users might find the `ompx_hold` modifier useful, as in the
above example.
See new documentation introduced by this patch in `openmp/docs` for
more detail on the functionality of this extension and its
relationship with OpenACC. For example, it explains how the runtime
must support two reference counts, as specified by OpenACC.
Clang recognizes `ompx_hold` unless `-fno-openmp-extensions`, a new
command-line option introduced by this patch, is specified.
Reviewed By: ABataev, jdoerfert, protze.joachim, grokos
Differential Revision: https://reviews.llvm.org/D106509
2021-08-31 15:17:07 -04:00
|
|
|
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
|
2015-12-28 07:25:51 +00:00
|
|
|
Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
|
|
|
|
? KindModifier
|
2015-12-28 15:52:46 +00:00
|
|
|
: (unsigned)OMPC_SCHEDULE_unknown;
|
2015-12-28 07:25:51 +00:00
|
|
|
KLoc[Modifier2] = Tok.getLocation();
|
|
|
|
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
}
|
|
|
|
// Parse ':'
|
|
|
|
if (Tok.is(tok::colon))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
else
|
|
|
|
Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
|
|
|
|
KindModifier = getOpenMPSimpleClauseType(
|
[OpenMP][OpenACC] Implement `ompx_hold` map type modifier extension in Clang (1/2)
This patch implements Clang support for an original OpenMP extension
we have developed to support OpenACC: the `ompx_hold` map type
modifier. The next patch in this series, D106510, implements OpenMP
runtime support.
Consider the following example:
```
#pragma omp target data map(ompx_hold, tofrom: x) // holds onto mapping of x
{
foo(); // might have map(delete: x)
#pragma omp target map(present, alloc: x) // x is guaranteed to be present
printf("%d\n", x);
}
```
The `ompx_hold` map type modifier above specifies that the `target
data` directive holds onto the mapping for `x` throughout the
associated region regardless of any `target exit data` directives
executed during the call to `foo`. Thus, the presence assertion for
`x` at the enclosed `target` construct cannot fail. (As usual, the
standard OpenMP reference count for `x` must also reach zero before
the data is unmapped.)
Justification for inclusion in Clang and LLVM's OpenMP runtime:
* The `ompx_hold` modifier supports OpenACC functionality (structured
reference count) that cannot be achieved in standard OpenMP, as of
5.1.
* The runtime implementation for `ompx_hold` (next patch) will thus be
used by Flang's OpenACC support.
* The Clang implementation for `ompx_hold` (this patch) as well as the
runtime implementation are required for the Clang OpenACC support
being developed as part of the ECP Clacc project, which translates
OpenACC to OpenMP at the directive AST level. These patches are the
first step in upstreaming OpenACC functionality from Clacc.
* The Clang implementation for `ompx_hold` is also used by the tests
in the runtime implementation. That syntactic support makes the
tests more readable than low-level runtime calls can. Moreover,
upstream Flang and Clang do not yet support OpenACC syntax
sufficiently for writing the tests.
* More generally, the Clang implementation enables a clean separation
of concerns between OpenACC and OpenMP development in LLVM. That
is, LLVM's OpenMP developers can discuss, modify, and debug LLVM's
extended OpenMP implementation and test suite without directly
considering OpenACC's language and execution model, which can be
handled by LLVM's OpenACC developers.
* OpenMP users might find the `ompx_hold` modifier useful, as in the
above example.
See new documentation introduced by this patch in `openmp/docs` for
more detail on the functionality of this extension and its
relationship with OpenACC. For example, it explains how the runtime
must support two reference counts, as specified by OpenACC.
Clang recognizes `ompx_hold` unless `-fno-openmp-extensions`, a new
command-line option introduced by this patch, is specified.
Reviewed By: ABataev, jdoerfert, protze.joachim, grokos
Differential Revision: https://reviews.llvm.org/D106509
2021-08-31 15:17:07 -04:00
|
|
|
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
|
2015-12-28 07:25:51 +00:00
|
|
|
}
|
|
|
|
Arg[ScheduleKind] = KindModifier;
|
|
|
|
KLoc[ScheduleKind] = Tok.getLocation();
|
2015-09-03 07:23:48 +00:00
|
|
|
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
2015-12-28 07:25:51 +00:00
|
|
|
if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
|
|
|
|
Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
|
|
|
|
Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
|
2015-09-03 07:23:48 +00:00
|
|
|
Tok.is(tok::comma))
|
|
|
|
DelimLoc = ConsumeAnyToken();
|
2016-01-15 18:50:31 +00:00
|
|
|
} else if (Kind == OMPC_dist_schedule) {
|
|
|
|
Arg.push_back(getOpenMPSimpleClauseType(
|
[OpenMP][OpenACC] Implement `ompx_hold` map type modifier extension in Clang (1/2)
This patch implements Clang support for an original OpenMP extension
we have developed to support OpenACC: the `ompx_hold` map type
modifier. The next patch in this series, D106510, implements OpenMP
runtime support.
Consider the following example:
```
#pragma omp target data map(ompx_hold, tofrom: x) // holds onto mapping of x
{
foo(); // might have map(delete: x)
#pragma omp target map(present, alloc: x) // x is guaranteed to be present
printf("%d\n", x);
}
```
The `ompx_hold` map type modifier above specifies that the `target
data` directive holds onto the mapping for `x` throughout the
associated region regardless of any `target exit data` directives
executed during the call to `foo`. Thus, the presence assertion for
`x` at the enclosed `target` construct cannot fail. (As usual, the
standard OpenMP reference count for `x` must also reach zero before
the data is unmapped.)
Justification for inclusion in Clang and LLVM's OpenMP runtime:
* The `ompx_hold` modifier supports OpenACC functionality (structured
reference count) that cannot be achieved in standard OpenMP, as of
5.1.
* The runtime implementation for `ompx_hold` (next patch) will thus be
used by Flang's OpenACC support.
* The Clang implementation for `ompx_hold` (this patch) as well as the
runtime implementation are required for the Clang OpenACC support
being developed as part of the ECP Clacc project, which translates
OpenACC to OpenMP at the directive AST level. These patches are the
first step in upstreaming OpenACC functionality from Clacc.
* The Clang implementation for `ompx_hold` is also used by the tests
in the runtime implementation. That syntactic support makes the
tests more readable than low-level runtime calls can. Moreover,
upstream Flang and Clang do not yet support OpenACC syntax
sufficiently for writing the tests.
* More generally, the Clang implementation enables a clean separation
of concerns between OpenACC and OpenMP development in LLVM. That
is, LLVM's OpenMP developers can discuss, modify, and debug LLVM's
extended OpenMP implementation and test suite without directly
considering OpenACC's language and execution model, which can be
handled by LLVM's OpenACC developers.
* OpenMP users might find the `ompx_hold` modifier useful, as in the
above example.
See new documentation introduced by this patch in `openmp/docs` for
more detail on the functionality of this extension and its
relationship with OpenACC. For example, it explains how the runtime
must support two reference counts, as specified by OpenACC.
Clang recognizes `ompx_hold` unless `-fno-openmp-extensions`, a new
command-line option introduced by this patch, is specified.
Reviewed By: ABataev, jdoerfert, protze.joachim, grokos
Differential Revision: https://reviews.llvm.org/D106509
2021-08-31 15:17:07 -04:00
|
|
|
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
|
2016-01-15 18:50:31 +00:00
|
|
|
KLoc.push_back(Tok.getLocation());
|
|
|
|
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
|
|
|
|
DelimLoc = ConsumeAnyToken();
|
2016-01-26 16:37:23 +00:00
|
|
|
} else if (Kind == OMPC_defaultmap) {
|
|
|
|
// Get a defaultmap modifier
|
2019-11-15 13:02:06 -05:00
|
|
|
unsigned Modifier = getOpenMPSimpleClauseType(
|
[OpenMP][OpenACC] Implement `ompx_hold` map type modifier extension in Clang (1/2)
This patch implements Clang support for an original OpenMP extension
we have developed to support OpenACC: the `ompx_hold` map type
modifier. The next patch in this series, D106510, implements OpenMP
runtime support.
Consider the following example:
```
#pragma omp target data map(ompx_hold, tofrom: x) // holds onto mapping of x
{
foo(); // might have map(delete: x)
#pragma omp target map(present, alloc: x) // x is guaranteed to be present
printf("%d\n", x);
}
```
The `ompx_hold` map type modifier above specifies that the `target
data` directive holds onto the mapping for `x` throughout the
associated region regardless of any `target exit data` directives
executed during the call to `foo`. Thus, the presence assertion for
`x` at the enclosed `target` construct cannot fail. (As usual, the
standard OpenMP reference count for `x` must also reach zero before
the data is unmapped.)
Justification for inclusion in Clang and LLVM's OpenMP runtime:
* The `ompx_hold` modifier supports OpenACC functionality (structured
reference count) that cannot be achieved in standard OpenMP, as of
5.1.
* The runtime implementation for `ompx_hold` (next patch) will thus be
used by Flang's OpenACC support.
* The Clang implementation for `ompx_hold` (this patch) as well as the
runtime implementation are required for the Clang OpenACC support
being developed as part of the ECP Clacc project, which translates
OpenACC to OpenMP at the directive AST level. These patches are the
first step in upstreaming OpenACC functionality from Clacc.
* The Clang implementation for `ompx_hold` is also used by the tests
in the runtime implementation. That syntactic support makes the
tests more readable than low-level runtime calls can. Moreover,
upstream Flang and Clang do not yet support OpenACC syntax
sufficiently for writing the tests.
* More generally, the Clang implementation enables a clean separation
of concerns between OpenACC and OpenMP development in LLVM. That
is, LLVM's OpenMP developers can discuss, modify, and debug LLVM's
extended OpenMP implementation and test suite without directly
considering OpenACC's language and execution model, which can be
handled by LLVM's OpenACC developers.
* OpenMP users might find the `ompx_hold` modifier useful, as in the
above example.
See new documentation introduced by this patch in `openmp/docs` for
more detail on the functionality of this extension and its
relationship with OpenACC. For example, it explains how the runtime
must support two reference counts, as specified by OpenACC.
Clang recognizes `ompx_hold` unless `-fno-openmp-extensions`, a new
command-line option introduced by this patch, is specified.
Reviewed By: ABataev, jdoerfert, protze.joachim, grokos
Differential Revision: https://reviews.llvm.org/D106509
2021-08-31 15:17:07 -04:00
|
|
|
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
|
2024-07-25 21:30:14 +02:00
|
|
|
|
2019-11-15 13:02:06 -05:00
|
|
|
// Set defaultmap modifier to unknown if it is either scalar, aggregate, or
|
|
|
|
// pointer
|
|
|
|
if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
|
|
|
|
Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown;
|
|
|
|
Arg.push_back(Modifier);
|
2016-01-26 16:37:23 +00:00
|
|
|
KLoc.push_back(Tok.getLocation());
|
|
|
|
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
// Parse ':'
|
2020-04-08 15:19:54 -04:00
|
|
|
if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) {
|
|
|
|
if (Tok.is(tok::colon))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
|
|
|
|
Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
|
|
|
|
// Get a defaultmap kind
|
|
|
|
Arg.push_back(getOpenMPSimpleClauseType(
|
[OpenMP][OpenACC] Implement `ompx_hold` map type modifier extension in Clang (1/2)
This patch implements Clang support for an original OpenMP extension
we have developed to support OpenACC: the `ompx_hold` map type
modifier. The next patch in this series, D106510, implements OpenMP
runtime support.
Consider the following example:
```
#pragma omp target data map(ompx_hold, tofrom: x) // holds onto mapping of x
{
foo(); // might have map(delete: x)
#pragma omp target map(present, alloc: x) // x is guaranteed to be present
printf("%d\n", x);
}
```
The `ompx_hold` map type modifier above specifies that the `target
data` directive holds onto the mapping for `x` throughout the
associated region regardless of any `target exit data` directives
executed during the call to `foo`. Thus, the presence assertion for
`x` at the enclosed `target` construct cannot fail. (As usual, the
standard OpenMP reference count for `x` must also reach zero before
the data is unmapped.)
Justification for inclusion in Clang and LLVM's OpenMP runtime:
* The `ompx_hold` modifier supports OpenACC functionality (structured
reference count) that cannot be achieved in standard OpenMP, as of
5.1.
* The runtime implementation for `ompx_hold` (next patch) will thus be
used by Flang's OpenACC support.
* The Clang implementation for `ompx_hold` (this patch) as well as the
runtime implementation are required for the Clang OpenACC support
being developed as part of the ECP Clacc project, which translates
OpenACC to OpenMP at the directive AST level. These patches are the
first step in upstreaming OpenACC functionality from Clacc.
* The Clang implementation for `ompx_hold` is also used by the tests
in the runtime implementation. That syntactic support makes the
tests more readable than low-level runtime calls can. Moreover,
upstream Flang and Clang do not yet support OpenACC syntax
sufficiently for writing the tests.
* More generally, the Clang implementation enables a clean separation
of concerns between OpenACC and OpenMP development in LLVM. That
is, LLVM's OpenMP developers can discuss, modify, and debug LLVM's
extended OpenMP implementation and test suite without directly
considering OpenACC's language and execution model, which can be
handled by LLVM's OpenACC developers.
* OpenMP users might find the `ompx_hold` modifier useful, as in the
above example.
See new documentation introduced by this patch in `openmp/docs` for
more detail on the functionality of this extension and its
relationship with OpenACC. For example, it explains how the runtime
must support two reference counts, as specified by OpenACC.
Clang recognizes `ompx_hold` unless `-fno-openmp-extensions`, a new
command-line option introduced by this patch, is specified.
Reviewed By: ABataev, jdoerfert, protze.joachim, grokos
Differential Revision: https://reviews.llvm.org/D106509
2021-08-31 15:17:07 -04:00
|
|
|
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
|
2020-04-08 15:19:54 -04:00
|
|
|
KLoc.push_back(Tok.getLocation());
|
|
|
|
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
} else {
|
|
|
|
Arg.push_back(OMPC_DEFAULTMAP_unknown);
|
|
|
|
KLoc.push_back(SourceLocation());
|
|
|
|
}
|
2022-12-12 15:51:38 -06:00
|
|
|
} else if (Kind == OMPC_order) {
|
|
|
|
enum { Modifier, OrderKind, NumberOfElements };
|
|
|
|
Arg.resize(NumberOfElements);
|
|
|
|
KLoc.resize(NumberOfElements);
|
|
|
|
Arg[Modifier] = OMPC_ORDER_MODIFIER_unknown;
|
|
|
|
Arg[OrderKind] = OMPC_ORDER_unknown;
|
|
|
|
unsigned KindModifier = getOpenMPSimpleClauseType(
|
|
|
|
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
|
|
|
|
if (KindModifier > OMPC_ORDER_unknown) {
|
|
|
|
// Parse 'modifier'
|
|
|
|
Arg[Modifier] = KindModifier;
|
|
|
|
KLoc[Modifier] = Tok.getLocation();
|
|
|
|
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
// Parse ':'
|
|
|
|
if (Tok.is(tok::colon))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
else
|
|
|
|
Diag(Tok, diag::warn_pragma_expected_colon) << "order modifier";
|
|
|
|
KindModifier = getOpenMPSimpleClauseType(
|
|
|
|
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
|
|
|
|
}
|
|
|
|
Arg[OrderKind] = KindModifier;
|
|
|
|
KLoc[OrderKind] = Tok.getLocation();
|
|
|
|
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
2020-03-18 15:01:15 -04:00
|
|
|
} else if (Kind == OMPC_device) {
|
|
|
|
// Only target executable directives support extended device construct.
|
|
|
|
if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
|
|
|
|
NextToken().is(tok::colon)) {
|
|
|
|
// Parse optional <device modifier> ':'
|
|
|
|
Arg.push_back(getOpenMPSimpleClauseType(
|
[OpenMP][OpenACC] Implement `ompx_hold` map type modifier extension in Clang (1/2)
This patch implements Clang support for an original OpenMP extension
we have developed to support OpenACC: the `ompx_hold` map type
modifier. The next patch in this series, D106510, implements OpenMP
runtime support.
Consider the following example:
```
#pragma omp target data map(ompx_hold, tofrom: x) // holds onto mapping of x
{
foo(); // might have map(delete: x)
#pragma omp target map(present, alloc: x) // x is guaranteed to be present
printf("%d\n", x);
}
```
The `ompx_hold` map type modifier above specifies that the `target
data` directive holds onto the mapping for `x` throughout the
associated region regardless of any `target exit data` directives
executed during the call to `foo`. Thus, the presence assertion for
`x` at the enclosed `target` construct cannot fail. (As usual, the
standard OpenMP reference count for `x` must also reach zero before
the data is unmapped.)
Justification for inclusion in Clang and LLVM's OpenMP runtime:
* The `ompx_hold` modifier supports OpenACC functionality (structured
reference count) that cannot be achieved in standard OpenMP, as of
5.1.
* The runtime implementation for `ompx_hold` (next patch) will thus be
used by Flang's OpenACC support.
* The Clang implementation for `ompx_hold` (this patch) as well as the
runtime implementation are required for the Clang OpenACC support
being developed as part of the ECP Clacc project, which translates
OpenACC to OpenMP at the directive AST level. These patches are the
first step in upstreaming OpenACC functionality from Clacc.
* The Clang implementation for `ompx_hold` is also used by the tests
in the runtime implementation. That syntactic support makes the
tests more readable than low-level runtime calls can. Moreover,
upstream Flang and Clang do not yet support OpenACC syntax
sufficiently for writing the tests.
* More generally, the Clang implementation enables a clean separation
of concerns between OpenACC and OpenMP development in LLVM. That
is, LLVM's OpenMP developers can discuss, modify, and debug LLVM's
extended OpenMP implementation and test suite without directly
considering OpenACC's language and execution model, which can be
handled by LLVM's OpenACC developers.
* OpenMP users might find the `ompx_hold` modifier useful, as in the
above example.
See new documentation introduced by this patch in `openmp/docs` for
more detail on the functionality of this extension and its
relationship with OpenACC. For example, it explains how the runtime
must support two reference counts, as specified by OpenACC.
Clang recognizes `ompx_hold` unless `-fno-openmp-extensions`, a new
command-line option introduced by this patch, is specified.
Reviewed By: ABataev, jdoerfert, protze.joachim, grokos
Differential Revision: https://reviews.llvm.org/D106509
2021-08-31 15:17:07 -04:00
|
|
|
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
|
2020-03-18 15:01:15 -04:00
|
|
|
KLoc.push_back(Tok.getLocation());
|
|
|
|
ConsumeAnyToken();
|
|
|
|
// Parse ':'
|
|
|
|
ConsumeAnyToken();
|
|
|
|
} else {
|
|
|
|
Arg.push_back(OMPC_DEVICE_unknown);
|
|
|
|
KLoc.emplace_back();
|
|
|
|
}
|
2022-11-17 16:20:14 -08:00
|
|
|
} else if (Kind == OMPC_grainsize) {
|
|
|
|
// Parse optional <grainsize modifier> ':'
|
|
|
|
OpenMPGrainsizeClauseModifier Modifier =
|
|
|
|
static_cast<OpenMPGrainsizeClauseModifier>(getOpenMPSimpleClauseType(
|
|
|
|
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
|
|
|
|
getLangOpts()));
|
|
|
|
if (getLangOpts().OpenMP >= 51) {
|
|
|
|
if (NextToken().is(tok::colon)) {
|
|
|
|
Arg.push_back(Modifier);
|
|
|
|
KLoc.push_back(Tok.getLocation());
|
|
|
|
// Parse modifier
|
|
|
|
ConsumeAnyToken();
|
|
|
|
// Parse ':'
|
|
|
|
ConsumeAnyToken();
|
|
|
|
} else {
|
|
|
|
if (Modifier == OMPC_GRAINSIZE_strict) {
|
|
|
|
Diag(Tok, diag::err_modifier_expected_colon) << "strict";
|
|
|
|
// Parse modifier
|
|
|
|
ConsumeAnyToken();
|
|
|
|
}
|
|
|
|
Arg.push_back(OMPC_GRAINSIZE_unknown);
|
|
|
|
KLoc.emplace_back();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Arg.push_back(OMPC_GRAINSIZE_unknown);
|
|
|
|
KLoc.emplace_back();
|
|
|
|
}
|
2022-11-18 15:21:49 -08:00
|
|
|
} else if (Kind == OMPC_num_tasks) {
|
|
|
|
// Parse optional <num_tasks modifier> ':'
|
|
|
|
OpenMPNumTasksClauseModifier Modifier =
|
|
|
|
static_cast<OpenMPNumTasksClauseModifier>(getOpenMPSimpleClauseType(
|
|
|
|
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
|
|
|
|
getLangOpts()));
|
|
|
|
if (getLangOpts().OpenMP >= 51) {
|
|
|
|
if (NextToken().is(tok::colon)) {
|
|
|
|
Arg.push_back(Modifier);
|
|
|
|
KLoc.push_back(Tok.getLocation());
|
|
|
|
// Parse modifier
|
|
|
|
ConsumeAnyToken();
|
|
|
|
// Parse ':'
|
|
|
|
ConsumeAnyToken();
|
|
|
|
} else {
|
|
|
|
if (Modifier == OMPC_NUMTASKS_strict) {
|
|
|
|
Diag(Tok, diag::err_modifier_expected_colon) << "strict";
|
|
|
|
// Parse modifier
|
|
|
|
ConsumeAnyToken();
|
|
|
|
}
|
|
|
|
Arg.push_back(OMPC_NUMTASKS_unknown);
|
|
|
|
KLoc.emplace_back();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Arg.push_back(OMPC_NUMTASKS_unknown);
|
|
|
|
KLoc.emplace_back();
|
|
|
|
}
|
2015-09-03 07:23:48 +00:00
|
|
|
} else {
|
|
|
|
assert(Kind == OMPC_if);
|
2015-12-28 07:25:51 +00:00
|
|
|
KLoc.push_back(Tok.getLocation());
|
2016-12-20 12:10:05 +00:00
|
|
|
TentativeParsingAction TPA(*this);
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-04 22:00:49 -06:00
|
|
|
auto DK = parseOpenMPDirectiveKind(*this);
|
|
|
|
Arg.push_back(DK);
|
|
|
|
if (DK != OMPD_unknown) {
|
2015-09-03 07:23:48 +00:00
|
|
|
ConsumeToken();
|
2016-12-20 12:10:05 +00:00
|
|
|
if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
|
|
|
|
TPA.Commit();
|
2015-09-03 07:23:48 +00:00
|
|
|
DelimLoc = ConsumeToken();
|
2016-12-20 12:10:05 +00:00
|
|
|
} else {
|
|
|
|
TPA.Revert();
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-04 22:00:49 -06:00
|
|
|
Arg.back() = unsigned(OMPD_unknown);
|
2016-12-20 12:10:05 +00:00
|
|
|
}
|
2018-04-23 19:53:05 +00:00
|
|
|
} else {
|
2016-12-20 12:10:05 +00:00
|
|
|
TPA.Revert();
|
2018-04-23 19:53:05 +00:00
|
|
|
}
|
2015-09-03 07:23:48 +00:00
|
|
|
}
|
2014-06-20 07:16:17 +00:00
|
|
|
|
2016-01-15 18:50:31 +00:00
|
|
|
bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
|
|
|
|
(Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
|
2022-11-17 16:20:14 -08:00
|
|
|
Kind == OMPC_if || Kind == OMPC_device ||
|
2022-11-18 15:21:49 -08:00
|
|
|
Kind == OMPC_grainsize || Kind == OMPC_num_tasks;
|
2015-09-03 07:23:48 +00:00
|
|
|
if (NeedAnExpression) {
|
|
|
|
SourceLocation ELoc = Tok.getLocation();
|
2020-01-09 15:07:51 +02:00
|
|
|
ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));
|
2014-06-20 07:16:17 +00:00
|
|
|
Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
|
2019-01-04 16:58:14 +00:00
|
|
|
Val =
|
|
|
|
Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
|
2014-06-20 07:16:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Parse ')'.
|
2018-07-06 19:35:42 +00:00
|
|
|
SourceLocation RLoc = Tok.getLocation();
|
|
|
|
if (!T.consumeClose())
|
|
|
|
RLoc = T.getCloseLocation();
|
2014-06-20 07:16:17 +00:00
|
|
|
|
2015-09-03 07:23:48 +00:00
|
|
|
if (NeedAnExpression && Val.isInvalid())
|
|
|
|
return nullptr;
|
|
|
|
|
2018-01-09 19:21:04 +00:00
|
|
|
if (ParseOnly)
|
|
|
|
return nullptr;
|
2024-04-16 16:36:53 +04:00
|
|
|
return Actions.OpenMP().ActOnOpenMPSingleExprWithArgClause(
|
2018-07-06 19:35:42 +00:00
|
|
|
Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
|
2014-06-20 07:16:17 +00:00
|
|
|
}
|
|
|
|
|
2014-06-16 07:08:35 +00:00
|
|
|
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
|
|
|
|
UnqualifiedId &ReductionId) {
|
|
|
|
if (ReductionIdScopeSpec.isEmpty()) {
|
|
|
|
auto OOK = OO_None;
|
|
|
|
switch (P.getCurToken().getKind()) {
|
|
|
|
case tok::plus:
|
|
|
|
OOK = OO_Plus;
|
|
|
|
break;
|
|
|
|
case tok::minus:
|
|
|
|
OOK = OO_Minus;
|
|
|
|
break;
|
|
|
|
case tok::star:
|
|
|
|
OOK = OO_Star;
|
|
|
|
break;
|
|
|
|
case tok::amp:
|
|
|
|
OOK = OO_Amp;
|
|
|
|
break;
|
|
|
|
case tok::pipe:
|
|
|
|
OOK = OO_Pipe;
|
|
|
|
break;
|
|
|
|
case tok::caret:
|
|
|
|
OOK = OO_Caret;
|
|
|
|
break;
|
|
|
|
case tok::ampamp:
|
|
|
|
OOK = OO_AmpAmp;
|
|
|
|
break;
|
|
|
|
case tok::pipepipe:
|
|
|
|
OOK = OO_PipePipe;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (OOK != OO_None) {
|
|
|
|
SourceLocation OpLoc = P.ConsumeToken();
|
2014-06-18 07:08:49 +00:00
|
|
|
SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
|
2014-06-16 07:08:35 +00:00
|
|
|
ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2020-03-19 09:12:29 +01:00
|
|
|
return P.ParseUnqualifiedId(
|
|
|
|
ReductionIdScopeSpec, /*ObjectType=*/nullptr,
|
|
|
|
/*ObjectHadErrors=*/false, /*EnteringContext*/ false,
|
|
|
|
/*AllowDestructorName*/ false,
|
|
|
|
/*AllowConstructorName*/ false,
|
|
|
|
/*AllowDeductionGuide*/ false, nullptr, ReductionId);
|
2014-06-16 07:08:35 +00:00
|
|
|
}
|
|
|
|
|
2018-12-18 22:18:41 +00:00
|
|
|
/// Checks if the token is a valid map-type-modifier.
|
2020-07-22 10:14:00 -04:00
|
|
|
/// FIXME: It will return an OpenMPMapClauseKind if that's what it parses.
|
2018-12-18 22:18:41 +00:00
|
|
|
static OpenMPMapModifierKind isMapModifier(Parser &P) {
|
|
|
|
Token Tok = P.getCurToken();
|
|
|
|
if (!Tok.is(tok::identifier))
|
|
|
|
return OMPC_MAP_MODIFIER_unknown;
|
|
|
|
|
|
|
|
Preprocessor &PP = P.getPreprocessor();
|
2020-07-22 10:14:00 -04:00
|
|
|
OpenMPMapModifierKind TypeModifier =
|
|
|
|
static_cast<OpenMPMapModifierKind>(getOpenMPSimpleClauseType(
|
[OpenMP][OpenACC] Implement `ompx_hold` map type modifier extension in Clang (1/2)
This patch implements Clang support for an original OpenMP extension
we have developed to support OpenACC: the `ompx_hold` map type
modifier. The next patch in this series, D106510, implements OpenMP
runtime support.
Consider the following example:
```
#pragma omp target data map(ompx_hold, tofrom: x) // holds onto mapping of x
{
foo(); // might have map(delete: x)
#pragma omp target map(present, alloc: x) // x is guaranteed to be present
printf("%d\n", x);
}
```
The `ompx_hold` map type modifier above specifies that the `target
data` directive holds onto the mapping for `x` throughout the
associated region regardless of any `target exit data` directives
executed during the call to `foo`. Thus, the presence assertion for
`x` at the enclosed `target` construct cannot fail. (As usual, the
standard OpenMP reference count for `x` must also reach zero before
the data is unmapped.)
Justification for inclusion in Clang and LLVM's OpenMP runtime:
* The `ompx_hold` modifier supports OpenACC functionality (structured
reference count) that cannot be achieved in standard OpenMP, as of
5.1.
* The runtime implementation for `ompx_hold` (next patch) will thus be
used by Flang's OpenACC support.
* The Clang implementation for `ompx_hold` (this patch) as well as the
runtime implementation are required for the Clang OpenACC support
being developed as part of the ECP Clacc project, which translates
OpenACC to OpenMP at the directive AST level. These patches are the
first step in upstreaming OpenACC functionality from Clacc.
* The Clang implementation for `ompx_hold` is also used by the tests
in the runtime implementation. That syntactic support makes the
tests more readable than low-level runtime calls can. Moreover,
upstream Flang and Clang do not yet support OpenACC syntax
sufficiently for writing the tests.
* More generally, the Clang implementation enables a clean separation
of concerns between OpenACC and OpenMP development in LLVM. That
is, LLVM's OpenMP developers can discuss, modify, and debug LLVM's
extended OpenMP implementation and test suite without directly
considering OpenACC's language and execution model, which can be
handled by LLVM's OpenACC developers.
* OpenMP users might find the `ompx_hold` modifier useful, as in the
above example.
See new documentation introduced by this patch in `openmp/docs` for
more detail on the functionality of this extension and its
relationship with OpenACC. For example, it explains how the runtime
must support two reference counts, as specified by OpenACC.
Clang recognizes `ompx_hold` unless `-fno-openmp-extensions`, a new
command-line option introduced by this patch, is specified.
Reviewed By: ABataev, jdoerfert, protze.joachim, grokos
Differential Revision: https://reviews.llvm.org/D106509
2021-08-31 15:17:07 -04:00
|
|
|
OMPC_map, PP.getSpelling(Tok), P.getLangOpts()));
|
2018-12-18 22:18:41 +00:00
|
|
|
return TypeModifier;
|
|
|
|
}
|
|
|
|
|
2019-02-22 22:29:42 +00:00
|
|
|
/// Parse the mapper modifier in map, to, and from clauses.
|
2024-04-16 16:36:53 +04:00
|
|
|
bool Parser::parseMapperModifier(SemaOpenMP::OpenMPVarListDataTy &Data) {
|
2019-02-22 22:29:42 +00:00
|
|
|
// Parse '('.
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
|
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
|
|
|
|
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// Parse mapper-identifier
|
|
|
|
if (getLangOpts().CPlusPlus)
|
|
|
|
ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
|
|
|
|
/*ObjectType=*/nullptr,
|
2022-01-09 00:19:49 -08:00
|
|
|
/*ObjectHasErrors=*/false,
|
2019-02-22 22:29:42 +00:00
|
|
|
/*EnteringContext=*/false);
|
|
|
|
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
|
|
|
|
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
auto &DeclNames = Actions.getASTContext().DeclarationNames;
|
|
|
|
Data.ReductionOrMapperId = DeclarationNameInfo(
|
|
|
|
DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
|
|
|
|
ConsumeToken();
|
|
|
|
// Parse ')'.
|
|
|
|
return T.consumeClose();
|
|
|
|
}
|
|
|
|
|
2024-05-13 07:39:23 -07:00
|
|
|
static OpenMPMapClauseKind isMapType(Parser &P);
|
|
|
|
|
2018-12-18 22:18:41 +00:00
|
|
|
/// Parse map-type-modifiers in map clause.
|
2024-05-13 07:39:23 -07:00
|
|
|
/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] [map-type] : ] list)
|
2020-07-22 10:14:00 -04:00
|
|
|
/// where, map-type-modifier ::= always | close | mapper(mapper-identifier) |
|
|
|
|
/// present
|
2024-05-13 07:39:23 -07:00
|
|
|
/// where, map-type ::= alloc | delete | from | release | to | tofrom
|
2024-04-16 16:36:53 +04:00
|
|
|
bool Parser::parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data) {
|
2024-05-13 07:39:23 -07:00
|
|
|
bool HasMapType = false;
|
|
|
|
SourceLocation PreMapLoc = Tok.getLocation();
|
|
|
|
StringRef PreMapName = "";
|
2019-02-19 16:38:20 +00:00
|
|
|
while (getCurToken().isNot(tok::colon)) {
|
|
|
|
OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
|
2024-05-13 07:39:23 -07:00
|
|
|
OpenMPMapClauseKind MapKind = isMapType(*this);
|
2018-12-18 22:18:41 +00:00
|
|
|
if (TypeModifier == OMPC_MAP_MODIFIER_always ||
|
2020-07-22 10:14:00 -04:00
|
|
|
TypeModifier == OMPC_MAP_MODIFIER_close ||
|
[OpenMP][OpenACC] Implement `ompx_hold` map type modifier extension in Clang (1/2)
This patch implements Clang support for an original OpenMP extension
we have developed to support OpenACC: the `ompx_hold` map type
modifier. The next patch in this series, D106510, implements OpenMP
runtime support.
Consider the following example:
```
#pragma omp target data map(ompx_hold, tofrom: x) // holds onto mapping of x
{
foo(); // might have map(delete: x)
#pragma omp target map(present, alloc: x) // x is guaranteed to be present
printf("%d\n", x);
}
```
The `ompx_hold` map type modifier above specifies that the `target
data` directive holds onto the mapping for `x` throughout the
associated region regardless of any `target exit data` directives
executed during the call to `foo`. Thus, the presence assertion for
`x` at the enclosed `target` construct cannot fail. (As usual, the
standard OpenMP reference count for `x` must also reach zero before
the data is unmapped.)
Justification for inclusion in Clang and LLVM's OpenMP runtime:
* The `ompx_hold` modifier supports OpenACC functionality (structured
reference count) that cannot be achieved in standard OpenMP, as of
5.1.
* The runtime implementation for `ompx_hold` (next patch) will thus be
used by Flang's OpenACC support.
* The Clang implementation for `ompx_hold` (this patch) as well as the
runtime implementation are required for the Clang OpenACC support
being developed as part of the ECP Clacc project, which translates
OpenACC to OpenMP at the directive AST level. These patches are the
first step in upstreaming OpenACC functionality from Clacc.
* The Clang implementation for `ompx_hold` is also used by the tests
in the runtime implementation. That syntactic support makes the
tests more readable than low-level runtime calls can. Moreover,
upstream Flang and Clang do not yet support OpenACC syntax
sufficiently for writing the tests.
* More generally, the Clang implementation enables a clean separation
of concerns between OpenACC and OpenMP development in LLVM. That
is, LLVM's OpenMP developers can discuss, modify, and debug LLVM's
extended OpenMP implementation and test suite without directly
considering OpenACC's language and execution model, which can be
handled by LLVM's OpenACC developers.
* OpenMP users might find the `ompx_hold` modifier useful, as in the
above example.
See new documentation introduced by this patch in `openmp/docs` for
more detail on the functionality of this extension and its
relationship with OpenACC. For example, it explains how the runtime
must support two reference counts, as specified by OpenACC.
Clang recognizes `ompx_hold` unless `-fno-openmp-extensions`, a new
command-line option introduced by this patch, is specified.
Reviewed By: ABataev, jdoerfert, protze.joachim, grokos
Differential Revision: https://reviews.llvm.org/D106509
2021-08-31 15:17:07 -04:00
|
|
|
TypeModifier == OMPC_MAP_MODIFIER_present ||
|
|
|
|
TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {
|
2018-12-18 22:18:41 +00:00
|
|
|
Data.MapTypeModifiers.push_back(TypeModifier);
|
|
|
|
Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
|
2023-10-24 10:17:52 -07:00
|
|
|
if (PP.LookAhead(0).isNot(tok::comma) &&
|
|
|
|
PP.LookAhead(0).isNot(tok::colon) && getLangOpts().OpenMP >= 52)
|
|
|
|
Diag(Tok.getLocation(), diag::err_omp_missing_comma)
|
|
|
|
<< "map type modifier";
|
2019-02-19 16:38:20 +00:00
|
|
|
ConsumeToken();
|
|
|
|
} else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
|
|
|
|
Data.MapTypeModifiers.push_back(TypeModifier);
|
|
|
|
Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
|
|
|
|
ConsumeToken();
|
2019-02-22 22:29:42 +00:00
|
|
|
if (parseMapperModifier(Data))
|
2019-02-19 16:38:20 +00:00
|
|
|
return true;
|
2023-10-24 10:17:52 -07:00
|
|
|
if (Tok.isNot(tok::comma) && Tok.isNot(tok::colon) &&
|
|
|
|
getLangOpts().OpenMP >= 52)
|
|
|
|
Diag(Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma)
|
|
|
|
<< "map type modifier";
|
|
|
|
|
2024-05-13 07:39:23 -07:00
|
|
|
} else if (getLangOpts().OpenMP >= 60 && MapKind != OMPC_MAP_unknown) {
|
|
|
|
if (!HasMapType) {
|
|
|
|
HasMapType = true;
|
|
|
|
Data.ExtraModifier = MapKind;
|
|
|
|
MapKind = OMPC_MAP_unknown;
|
|
|
|
PreMapLoc = Tok.getLocation();
|
|
|
|
PreMapName = Tok.getIdentifierInfo()->getName();
|
|
|
|
} else {
|
|
|
|
Diag(Tok, diag::err_omp_more_one_map_type);
|
|
|
|
Diag(PreMapLoc, diag::note_previous_map_type_specified_here)
|
|
|
|
<< PreMapName;
|
|
|
|
}
|
|
|
|
ConsumeToken();
|
2025-03-11 16:31:42 +05:30
|
|
|
} else if (TypeModifier == OMPC_MAP_MODIFIER_self) {
|
|
|
|
Data.MapTypeModifiers.push_back(TypeModifier);
|
|
|
|
Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
|
|
|
|
if (PP.LookAhead(0).isNot(tok::comma) &&
|
|
|
|
PP.LookAhead(0).isNot(tok::colon))
|
|
|
|
Diag(Tok.getLocation(), diag::err_omp_missing_comma)
|
|
|
|
<< "map type modifier";
|
|
|
|
if (getLangOpts().OpenMP < 60)
|
|
|
|
Diag(Tok, diag::err_omp_unknown_map_type_modifier)
|
|
|
|
<< (getLangOpts().OpenMP >= 51
|
|
|
|
? (getLangOpts().OpenMP >= 52 ? 2 : 1)
|
|
|
|
: 0)
|
|
|
|
<< getLangOpts().OpenMPExtensions << 0;
|
|
|
|
ConsumeToken();
|
2018-12-18 22:18:41 +00:00
|
|
|
} else {
|
|
|
|
// For the case of unknown map-type-modifier or a map-type.
|
|
|
|
// Map-type is followed by a colon; the function returns when it
|
|
|
|
// encounters a token followed by a colon.
|
|
|
|
if (Tok.is(tok::comma)) {
|
2019-02-19 16:38:20 +00:00
|
|
|
Diag(Tok, diag::err_omp_map_type_modifier_missing);
|
|
|
|
ConsumeToken();
|
2018-12-18 22:18:41 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// Potential map-type token as it is followed by a colon.
|
2024-05-13 07:39:23 -07:00
|
|
|
if (PP.LookAhead(0).is(tok::colon)) {
|
|
|
|
if (getLangOpts().OpenMP >= 60) {
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-22 10:14:00 -04:00
|
|
|
Diag(Tok, diag::err_omp_unknown_map_type_modifier)
|
2023-01-06 11:17:57 -06:00
|
|
|
<< (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
|
|
|
|
: 0)
|
2025-03-11 16:31:42 +05:30
|
|
|
<< getLangOpts().OpenMPExtensions
|
|
|
|
<< (getLangOpts().OpenMP >= 60 ? 1 : 0);
|
2019-02-19 16:38:20 +00:00
|
|
|
ConsumeToken();
|
2018-12-18 22:18:41 +00:00
|
|
|
}
|
2019-02-19 16:38:20 +00:00
|
|
|
if (getCurToken().is(tok::comma))
|
|
|
|
ConsumeToken();
|
2018-12-18 22:18:41 +00:00
|
|
|
}
|
2024-05-13 07:39:23 -07:00
|
|
|
if (getLangOpts().OpenMP >= 60 && !HasMapType) {
|
|
|
|
if (!Tok.is(tok::colon)) {
|
|
|
|
Diag(Tok, diag::err_omp_unknown_map_type);
|
|
|
|
ConsumeToken();
|
|
|
|
} else {
|
|
|
|
Data.ExtraModifier = OMPC_MAP_unknown;
|
|
|
|
}
|
|
|
|
}
|
2019-02-19 16:38:20 +00:00
|
|
|
return false;
|
2018-12-18 22:18:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Checks if the token is a valid map-type.
|
2024-05-02 20:54:20 -07:00
|
|
|
/// If it is not MapType kind, OMPC_MAP_unknown is returned.
|
2018-12-18 22:18:41 +00:00
|
|
|
static OpenMPMapClauseKind isMapType(Parser &P) {
|
|
|
|
Token Tok = P.getCurToken();
|
|
|
|
// The map-type token can be either an identifier or the C++ delete keyword.
|
|
|
|
if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
|
|
|
|
return OMPC_MAP_unknown;
|
|
|
|
Preprocessor &PP = P.getPreprocessor();
|
2024-05-13 07:39:23 -07:00
|
|
|
unsigned MapType =
|
|
|
|
getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok), P.getLangOpts());
|
2024-05-02 20:54:20 -07:00
|
|
|
if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
|
|
|
|
MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||
|
|
|
|
MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)
|
2024-05-13 07:39:23 -07:00
|
|
|
return static_cast<OpenMPMapClauseKind>(MapType);
|
2024-05-02 20:54:20 -07:00
|
|
|
return OMPC_MAP_unknown;
|
2018-12-18 22:18:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Parse map-type in map clause.
|
|
|
|
/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
|
2019-02-26 11:01:50 +00:00
|
|
|
/// where, map-type ::= to | from | tofrom | alloc | release | delete
|
2024-04-16 16:36:53 +04:00
|
|
|
static void parseMapType(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data) {
|
2018-12-18 22:18:41 +00:00
|
|
|
Token Tok = P.getCurToken();
|
|
|
|
if (Tok.is(tok::colon)) {
|
|
|
|
P.Diag(Tok, diag::err_omp_map_type_missing);
|
|
|
|
return;
|
|
|
|
}
|
2019-12-20 11:04:57 -05:00
|
|
|
Data.ExtraModifier = isMapType(P);
|
|
|
|
if (Data.ExtraModifier == OMPC_MAP_unknown)
|
2018-12-18 22:18:41 +00:00
|
|
|
P.Diag(Tok, diag::err_omp_unknown_map_type);
|
|
|
|
P.ConsumeToken();
|
|
|
|
}
|
|
|
|
|
2020-04-01 15:06:38 -04:00
|
|
|
/// Parses simple expression in parens for single-expression clauses of OpenMP
|
|
|
|
/// constructs.
|
|
|
|
ExprResult Parser::ParseOpenMPIteratorsExpr() {
|
|
|
|
assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&
|
|
|
|
"Expected 'iterator' token.");
|
|
|
|
SourceLocation IteratorKwLoc = ConsumeToken();
|
|
|
|
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
SourceLocation LLoc = T.getOpenLocation();
|
2024-04-16 16:36:53 +04:00
|
|
|
SmallVector<SemaOpenMP::OMPIteratorData, 4> Data;
|
2020-04-01 15:06:38 -04:00
|
|
|
while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
// Check if the type parsing is required.
|
|
|
|
ParsedType IteratorType;
|
|
|
|
if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {
|
|
|
|
// identifier '=' is not found - parse type.
|
|
|
|
TypeResult TR = ParseTypeName();
|
|
|
|
if (TR.isInvalid()) {
|
|
|
|
T.skipToEnd();
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
IteratorType = TR.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse identifier.
|
|
|
|
IdentifierInfo *II = nullptr;
|
|
|
|
SourceLocation IdLoc;
|
|
|
|
if (Tok.is(tok::identifier)) {
|
|
|
|
II = Tok.getIdentifierInfo();
|
|
|
|
IdLoc = ConsumeToken();
|
|
|
|
} else {
|
|
|
|
Diag(Tok, diag::err_expected_unqualified_id) << 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse '='.
|
|
|
|
SourceLocation AssignLoc;
|
|
|
|
if (Tok.is(tok::equal))
|
|
|
|
AssignLoc = ConsumeToken();
|
|
|
|
else
|
|
|
|
Diag(Tok, diag::err_omp_expected_equal_in_iterator);
|
|
|
|
|
|
|
|
// Parse range-specification - <begin> ':' <end> [ ':' <step> ]
|
|
|
|
ColonProtectionRAIIObject ColonRAII(*this);
|
|
|
|
// Parse <begin>
|
|
|
|
SourceLocation Loc = Tok.getLocation();
|
|
|
|
ExprResult LHS = ParseCastExpression(AnyCastExpr);
|
|
|
|
ExprResult Begin = Actions.CorrectDelayedTyposInExpr(
|
|
|
|
ParseRHSOfBinaryExpression(LHS, prec::Conditional));
|
|
|
|
Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,
|
|
|
|
/*DiscardedValue=*/false);
|
|
|
|
// Parse ':'.
|
|
|
|
SourceLocation ColonLoc;
|
|
|
|
if (Tok.is(tok::colon))
|
|
|
|
ColonLoc = ConsumeToken();
|
|
|
|
|
|
|
|
// Parse <end>
|
|
|
|
Loc = Tok.getLocation();
|
|
|
|
LHS = ParseCastExpression(AnyCastExpr);
|
|
|
|
ExprResult End = Actions.CorrectDelayedTyposInExpr(
|
|
|
|
ParseRHSOfBinaryExpression(LHS, prec::Conditional));
|
|
|
|
End = Actions.ActOnFinishFullExpr(End.get(), Loc,
|
|
|
|
/*DiscardedValue=*/false);
|
|
|
|
|
|
|
|
SourceLocation SecColonLoc;
|
|
|
|
ExprResult Step;
|
|
|
|
// Parse optional step.
|
|
|
|
if (Tok.is(tok::colon)) {
|
|
|
|
// Parse ':'
|
|
|
|
SecColonLoc = ConsumeToken();
|
|
|
|
// Parse <step>
|
|
|
|
Loc = Tok.getLocation();
|
|
|
|
LHS = ParseCastExpression(AnyCastExpr);
|
|
|
|
Step = Actions.CorrectDelayedTyposInExpr(
|
|
|
|
ParseRHSOfBinaryExpression(LHS, prec::Conditional));
|
|
|
|
Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,
|
|
|
|
/*DiscardedValue=*/false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse ',' or ')'
|
|
|
|
if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
|
|
|
|
Diag(Tok, diag::err_omp_expected_punc_after_iterator);
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
|
|
|
|
2024-04-16 16:36:53 +04:00
|
|
|
SemaOpenMP::OMPIteratorData &D = Data.emplace_back();
|
2020-04-01 15:06:38 -04:00
|
|
|
D.DeclIdent = II;
|
|
|
|
D.DeclIdentLoc = IdLoc;
|
|
|
|
D.Type = IteratorType;
|
|
|
|
D.AssignLoc = AssignLoc;
|
|
|
|
D.ColonLoc = ColonLoc;
|
|
|
|
D.SecColonLoc = SecColonLoc;
|
|
|
|
D.Range.Begin = Begin.get();
|
|
|
|
D.Range.End = End.get();
|
|
|
|
D.Range.Step = Step.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse ')'.
|
|
|
|
SourceLocation RLoc = Tok.getLocation();
|
|
|
|
if (!T.consumeClose())
|
|
|
|
RLoc = T.getCloseLocation();
|
|
|
|
|
2024-04-16 16:36:53 +04:00
|
|
|
return Actions.OpenMP().ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc,
|
|
|
|
LLoc, RLoc, Data);
|
2020-04-01 15:06:38 -04:00
|
|
|
}
|
|
|
|
|
2022-05-17 10:11:00 -07:00
|
|
|
bool Parser::ParseOpenMPReservedLocator(OpenMPClauseKind Kind,
|
2024-04-16 16:36:53 +04:00
|
|
|
SemaOpenMP::OpenMPVarListDataTy &Data,
|
2022-05-17 10:11:00 -07:00
|
|
|
const LangOptions &LangOpts) {
|
|
|
|
// Currently the only reserved locator is 'omp_all_memory' which is only
|
|
|
|
// allowed on a depend clause.
|
|
|
|
if (Kind != OMPC_depend || LangOpts.OpenMP < 51)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (Tok.is(tok::identifier) &&
|
|
|
|
Tok.getIdentifierInfo()->isStr("omp_all_memory")) {
|
|
|
|
|
|
|
|
if (Data.ExtraModifier == OMPC_DEPEND_outallmemory ||
|
|
|
|
Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)
|
|
|
|
Diag(Tok, diag::warn_omp_more_one_omp_all_memory);
|
|
|
|
else if (Data.ExtraModifier != OMPC_DEPEND_out &&
|
|
|
|
Data.ExtraModifier != OMPC_DEPEND_inout)
|
|
|
|
Diag(Tok, diag::err_omp_requires_out_inout_depend_type);
|
|
|
|
else
|
|
|
|
Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out
|
|
|
|
? OMPC_DEPEND_outallmemory
|
|
|
|
: OMPC_DEPEND_inoutallmemory;
|
|
|
|
ConsumeToken();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-09-20 11:12:41 -07:00
|
|
|
/// Parse step size expression. Returns true if parsing is successfull,
|
|
|
|
/// otherwise returns false.
|
2024-04-16 16:36:53 +04:00
|
|
|
static bool parseStepSize(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data,
|
2023-09-20 11:12:41 -07:00
|
|
|
OpenMPClauseKind CKind, SourceLocation ELoc) {
|
|
|
|
ExprResult Tail = P.ParseAssignmentExpression();
|
|
|
|
Sema &Actions = P.getActions();
|
|
|
|
Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
|
|
|
|
/*DiscardedValue*/ false);
|
|
|
|
if (Tail.isUsable()) {
|
|
|
|
Data.DepModOrTailExpr = Tail.get();
|
|
|
|
Token CurTok = P.getCurToken();
|
|
|
|
if (CurTok.isNot(tok::r_paren) && CurTok.isNot(tok::comma)) {
|
|
|
|
P.Diag(CurTok, diag::err_expected_punc) << "step expression";
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-11-11 16:11:16 -08:00
|
|
|
/// Parse 'allocate' clause modifiers.
|
2025-01-13 05:44:48 -08:00
|
|
|
/// If allocator-modifier exists, return an expression for it. For both
|
|
|
|
/// allocator and align modifiers, set Data fields as appropriate.
|
2024-11-11 16:11:16 -08:00
|
|
|
static ExprResult
|
|
|
|
parseOpenMPAllocateClauseModifiers(Parser &P, OpenMPClauseKind Kind,
|
|
|
|
SemaOpenMP::OpenMPVarListDataTy &Data) {
|
|
|
|
const Token &Tok = P.getCurToken();
|
|
|
|
Preprocessor &PP = P.getPreprocessor();
|
|
|
|
ExprResult Tail;
|
2025-01-13 05:44:48 -08:00
|
|
|
ExprResult Val;
|
|
|
|
SourceLocation RLoc;
|
|
|
|
bool AllocatorSeen = false;
|
|
|
|
bool AlignSeen = false;
|
|
|
|
SourceLocation CurrentModifierLoc = Tok.getLocation();
|
|
|
|
auto CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
|
2024-11-11 16:11:16 -08:00
|
|
|
getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), P.getLangOpts()));
|
2025-01-13 05:44:48 -08:00
|
|
|
|
|
|
|
// Modifiers did not exist before 5.1
|
|
|
|
if (P.getLangOpts().OpenMP < 51)
|
|
|
|
return P.ParseAssignmentExpression();
|
|
|
|
|
|
|
|
// An allocator-simple-modifier is exclusive and must appear alone. See
|
|
|
|
// OpenMP6.0 spec, pg. 313, L1 on Modifiers, as well as Table 5.1, pg. 50,
|
|
|
|
// description of "exclusive" property. If we don't recognized an explicit
|
|
|
|
// simple-/complex- modifier, assume we're looking at expression
|
|
|
|
// representing allocator and consider ourselves done.
|
|
|
|
if (CurrentModifier == OMPC_ALLOCATE_unknown)
|
|
|
|
return P.ParseAssignmentExpression();
|
|
|
|
|
|
|
|
do {
|
2024-11-11 16:11:16 -08:00
|
|
|
P.ConsumeToken();
|
|
|
|
if (Tok.is(tok::l_paren)) {
|
2025-01-13 05:44:48 -08:00
|
|
|
switch (CurrentModifier) {
|
|
|
|
case OMPC_ALLOCATE_allocator: {
|
|
|
|
if (AllocatorSeen) {
|
|
|
|
P.Diag(Tok, diag::err_omp_duplicate_modifier)
|
|
|
|
<< getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
|
|
|
|
<< getOpenMPClauseName(Kind);
|
|
|
|
} else {
|
|
|
|
Data.AllocClauseModifiers.push_back(CurrentModifier);
|
|
|
|
Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
|
|
|
|
}
|
|
|
|
BalancedDelimiterTracker AllocateT(P, tok::l_paren,
|
|
|
|
tok::annot_pragma_openmp_end);
|
|
|
|
AllocateT.consumeOpen();
|
|
|
|
Tail = P.ParseAssignmentExpression();
|
|
|
|
AllocateT.consumeClose();
|
|
|
|
AllocatorSeen = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OMPC_ALLOCATE_align: {
|
|
|
|
if (AlignSeen) {
|
|
|
|
P.Diag(Tok, diag::err_omp_duplicate_modifier)
|
|
|
|
<< getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
|
|
|
|
<< getOpenMPClauseName(Kind);
|
|
|
|
} else {
|
|
|
|
Data.AllocClauseModifiers.push_back(CurrentModifier);
|
|
|
|
Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
|
|
|
|
}
|
|
|
|
Val = P.ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
|
|
|
|
if (Val.isUsable())
|
|
|
|
Data.AllocateAlignment = Val.get();
|
|
|
|
AlignSeen = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Unexpected allocate modifier");
|
|
|
|
}
|
2024-11-11 16:11:16 -08:00
|
|
|
} else {
|
|
|
|
P.Diag(Tok, diag::err_expected) << tok::l_paren;
|
|
|
|
}
|
2025-01-13 05:44:48 -08:00
|
|
|
if (Tok.isNot(tok::comma))
|
|
|
|
break;
|
|
|
|
P.ConsumeToken();
|
|
|
|
CurrentModifierLoc = Tok.getLocation();
|
|
|
|
CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
|
|
|
|
getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), P.getLangOpts()));
|
|
|
|
// A modifier followed by a comma implies another modifier.
|
|
|
|
if (CurrentModifier == OMPC_ALLOCATE_unknown) {
|
|
|
|
P.Diag(Tok, diag::err_omp_expected_modifier) << getOpenMPClauseName(Kind);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (!AllocatorSeen || !AlignSeen);
|
2024-11-11 16:11:16 -08:00
|
|
|
return Tail;
|
|
|
|
}
|
|
|
|
|
2016-04-12 05:28:34 +00:00
|
|
|
/// Parses clauses with list.
|
|
|
|
bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
|
|
|
|
OpenMPClauseKind Kind,
|
|
|
|
SmallVectorImpl<Expr *> &Vars,
|
2024-04-16 16:36:53 +04:00
|
|
|
SemaOpenMP::OpenMPVarListDataTy &Data) {
|
2016-04-12 05:28:34 +00:00
|
|
|
UnqualifiedId UnqualifiedReductionId;
|
2014-06-16 07:08:35 +00:00
|
|
|
bool InvalidReductionId = false;
|
2019-02-22 22:29:42 +00:00
|
|
|
bool IsInvalidMapperModifier = false;
|
2015-06-23 14:25:19 +00:00
|
|
|
|
2013-07-19 03:13:43 +00:00
|
|
|
// Parse '('.
|
2013-12-18 19:10:49 +00:00
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
2013-07-19 03:13:43 +00:00
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
2020-03-30 19:58:40 -05:00
|
|
|
getOpenMPClauseName(Kind).data()))
|
2016-04-12 05:28:34 +00:00
|
|
|
return true;
|
2013-07-19 03:13:43 +00:00
|
|
|
|
2020-05-18 13:37:53 -04:00
|
|
|
bool HasIterator = false;
|
2023-01-06 11:17:57 -06:00
|
|
|
bool InvalidIterator = false;
|
2015-08-20 10:54:39 +00:00
|
|
|
bool NeedRParenForLinear = false;
|
|
|
|
BalancedDelimiterTracker LinearT(*this, tok::l_paren,
|
2020-10-29 18:44:28 -05:00
|
|
|
tok::annot_pragma_openmp_end);
|
2014-06-16 07:08:35 +00:00
|
|
|
// Handle reduction-identifier for reduction clause.
|
2017-07-21 18:48:21 +00:00
|
|
|
if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
|
|
|
|
Kind == OMPC_in_reduction) {
|
2020-03-23 17:30:38 -04:00
|
|
|
Data.ExtraModifier = OMPC_REDUCTION_unknown;
|
|
|
|
if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&
|
|
|
|
(Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&
|
|
|
|
NextToken().is(tok::comma)) {
|
|
|
|
// Parse optional reduction modifier.
|
[OpenMP][OpenACC] Implement `ompx_hold` map type modifier extension in Clang (1/2)
This patch implements Clang support for an original OpenMP extension
we have developed to support OpenACC: the `ompx_hold` map type
modifier. The next patch in this series, D106510, implements OpenMP
runtime support.
Consider the following example:
```
#pragma omp target data map(ompx_hold, tofrom: x) // holds onto mapping of x
{
foo(); // might have map(delete: x)
#pragma omp target map(present, alloc: x) // x is guaranteed to be present
printf("%d\n", x);
}
```
The `ompx_hold` map type modifier above specifies that the `target
data` directive holds onto the mapping for `x` throughout the
associated region regardless of any `target exit data` directives
executed during the call to `foo`. Thus, the presence assertion for
`x` at the enclosed `target` construct cannot fail. (As usual, the
standard OpenMP reference count for `x` must also reach zero before
the data is unmapped.)
Justification for inclusion in Clang and LLVM's OpenMP runtime:
* The `ompx_hold` modifier supports OpenACC functionality (structured
reference count) that cannot be achieved in standard OpenMP, as of
5.1.
* The runtime implementation for `ompx_hold` (next patch) will thus be
used by Flang's OpenACC support.
* The Clang implementation for `ompx_hold` (this patch) as well as the
runtime implementation are required for the Clang OpenACC support
being developed as part of the ECP Clacc project, which translates
OpenACC to OpenMP at the directive AST level. These patches are the
first step in upstreaming OpenACC functionality from Clacc.
* The Clang implementation for `ompx_hold` is also used by the tests
in the runtime implementation. That syntactic support makes the
tests more readable than low-level runtime calls can. Moreover,
upstream Flang and Clang do not yet support OpenACC syntax
sufficiently for writing the tests.
* More generally, the Clang implementation enables a clean separation
of concerns between OpenACC and OpenMP development in LLVM. That
is, LLVM's OpenMP developers can discuss, modify, and debug LLVM's
extended OpenMP implementation and test suite without directly
considering OpenACC's language and execution model, which can be
handled by LLVM's OpenACC developers.
* OpenMP users might find the `ompx_hold` modifier useful, as in the
above example.
See new documentation introduced by this patch in `openmp/docs` for
more detail on the functionality of this extension and its
relationship with OpenACC. For example, it explains how the runtime
must support two reference counts, as specified by OpenACC.
Clang recognizes `ompx_hold` unless `-fno-openmp-extensions`, a new
command-line option introduced by this patch, is specified.
Reviewed By: ABataev, jdoerfert, protze.joachim, grokos
Differential Revision: https://reviews.llvm.org/D106509
2021-08-31 15:17:07 -04:00
|
|
|
Data.ExtraModifier =
|
|
|
|
getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
|
2020-03-23 17:30:38 -04:00
|
|
|
Data.ExtraModifierLoc = Tok.getLocation();
|
|
|
|
ConsumeToken();
|
|
|
|
assert(Tok.is(tok::comma) && "Expected comma.");
|
|
|
|
(void)ConsumeToken();
|
|
|
|
}
|
2025-03-21 14:19:08 +05:30
|
|
|
// Handle original(private / shared) Modifier
|
|
|
|
if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 60 &&
|
|
|
|
Tok.is(tok::identifier) && PP.getSpelling(Tok) == "original" &&
|
|
|
|
NextToken().is(tok::l_paren)) {
|
|
|
|
// Parse original(private) modifier.
|
|
|
|
ConsumeToken();
|
|
|
|
BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
|
|
|
|
ParenT.consumeOpen();
|
|
|
|
if (Tok.is(tok::kw_private)) {
|
|
|
|
Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_private;
|
|
|
|
Data.OriginalSharingModifierLoc = Tok.getLocation();
|
|
|
|
ConsumeToken();
|
|
|
|
} else if (Tok.is(tok::identifier) &&
|
|
|
|
(PP.getSpelling(Tok) == "shared" ||
|
|
|
|
PP.getSpelling(Tok) == "default")) {
|
|
|
|
Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_shared;
|
|
|
|
Data.OriginalSharingModifierLoc = Tok.getLocation();
|
|
|
|
ConsumeToken();
|
|
|
|
} else {
|
|
|
|
Diag(Tok.getLocation(), diag::err_expected)
|
|
|
|
<< "'private or shared or default'";
|
|
|
|
SkipUntil(tok::r_paren);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ParenT.consumeClose();
|
|
|
|
if (!Tok.is(tok::comma)) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_expected) << "',' (comma)";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
(void)ConsumeToken();
|
|
|
|
}
|
2014-06-16 07:08:35 +00:00
|
|
|
ColonProtectionRAIIObject ColonRAII(*this);
|
2016-03-17 10:19:46 +00:00
|
|
|
if (getLangOpts().CPlusPlus)
|
2019-02-19 16:38:20 +00:00
|
|
|
ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
|
2016-03-17 10:19:46 +00:00
|
|
|
/*ObjectType=*/nullptr,
|
2022-01-09 00:19:49 -08:00
|
|
|
/*ObjectHasErrors=*/false,
|
2016-03-17 10:19:46 +00:00
|
|
|
/*EnteringContext=*/false);
|
2019-02-19 16:38:20 +00:00
|
|
|
InvalidReductionId = ParseReductionId(
|
|
|
|
*this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
|
2014-06-16 07:08:35 +00:00
|
|
|
if (InvalidReductionId) {
|
|
|
|
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
}
|
2016-04-12 05:28:34 +00:00
|
|
|
if (Tok.is(tok::colon))
|
|
|
|
Data.ColonLoc = ConsumeToken();
|
|
|
|
else
|
2014-06-16 07:08:35 +00:00
|
|
|
Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
|
2016-04-12 05:28:34 +00:00
|
|
|
if (!InvalidReductionId)
|
2019-02-19 16:38:20 +00:00
|
|
|
Data.ReductionOrMapperId =
|
2016-04-12 05:28:34 +00:00
|
|
|
Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
|
2023-06-21 16:26:35 -07:00
|
|
|
} else if (Kind == OMPC_depend || Kind == OMPC_doacross) {
|
2020-04-01 15:06:38 -04:00
|
|
|
if (getLangOpts().OpenMP >= 50) {
|
|
|
|
if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
|
|
|
|
// Handle optional dependence modifier.
|
|
|
|
// iterator(iterators-definition)
|
|
|
|
// where iterators-definition is iterator-specifier [,
|
|
|
|
// iterators-definition ]
|
|
|
|
// where iterator-specifier is [ iterator-type ] identifier =
|
|
|
|
// range-specification
|
2020-05-18 13:37:53 -04:00
|
|
|
HasIterator = true;
|
2020-04-01 15:06:38 -04:00
|
|
|
EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
|
|
|
|
ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
|
|
|
|
Data.DepModOrTailExpr = IteratorRes.get();
|
|
|
|
// Parse ','
|
|
|
|
ExpectAndConsume(tok::comma);
|
|
|
|
}
|
|
|
|
}
|
2019-12-20 11:04:57 -05:00
|
|
|
// Handle dependency type for depend clause.
|
2015-06-23 14:25:19 +00:00
|
|
|
ColonProtectionRAIIObject ColonRAII(*this);
|
2019-12-20 11:04:57 -05:00
|
|
|
Data.ExtraModifier = getOpenMPSimpleClauseType(
|
2020-07-22 10:14:00 -04:00
|
|
|
Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
|
[OpenMP][OpenACC] Implement `ompx_hold` map type modifier extension in Clang (1/2)
This patch implements Clang support for an original OpenMP extension
we have developed to support OpenACC: the `ompx_hold` map type
modifier. The next patch in this series, D106510, implements OpenMP
runtime support.
Consider the following example:
```
#pragma omp target data map(ompx_hold, tofrom: x) // holds onto mapping of x
{
foo(); // might have map(delete: x)
#pragma omp target map(present, alloc: x) // x is guaranteed to be present
printf("%d\n", x);
}
```
The `ompx_hold` map type modifier above specifies that the `target
data` directive holds onto the mapping for `x` throughout the
associated region regardless of any `target exit data` directives
executed during the call to `foo`. Thus, the presence assertion for
`x` at the enclosed `target` construct cannot fail. (As usual, the
standard OpenMP reference count for `x` must also reach zero before
the data is unmapped.)
Justification for inclusion in Clang and LLVM's OpenMP runtime:
* The `ompx_hold` modifier supports OpenACC functionality (structured
reference count) that cannot be achieved in standard OpenMP, as of
5.1.
* The runtime implementation for `ompx_hold` (next patch) will thus be
used by Flang's OpenACC support.
* The Clang implementation for `ompx_hold` (this patch) as well as the
runtime implementation are required for the Clang OpenACC support
being developed as part of the ECP Clacc project, which translates
OpenACC to OpenMP at the directive AST level. These patches are the
first step in upstreaming OpenACC functionality from Clacc.
* The Clang implementation for `ompx_hold` is also used by the tests
in the runtime implementation. That syntactic support makes the
tests more readable than low-level runtime calls can. Moreover,
upstream Flang and Clang do not yet support OpenACC syntax
sufficiently for writing the tests.
* More generally, the Clang implementation enables a clean separation
of concerns between OpenACC and OpenMP development in LLVM. That
is, LLVM's OpenMP developers can discuss, modify, and debug LLVM's
extended OpenMP implementation and test suite without directly
considering OpenACC's language and execution model, which can be
handled by LLVM's OpenACC developers.
* OpenMP users might find the `ompx_hold` modifier useful, as in the
above example.
See new documentation introduced by this patch in `openmp/docs` for
more detail on the functionality of this extension and its
relationship with OpenACC. For example, it explains how the runtime
must support two reference counts, as specified by OpenACC.
Clang recognizes `ompx_hold` unless `-fno-openmp-extensions`, a new
command-line option introduced by this patch, is specified.
Reviewed By: ABataev, jdoerfert, protze.joachim, grokos
Differential Revision: https://reviews.llvm.org/D106509
2021-08-31 15:17:07 -04:00
|
|
|
getLangOpts());
|
2020-03-23 17:30:38 -04:00
|
|
|
Data.ExtraModifierLoc = Tok.getLocation();
|
2023-06-21 16:26:35 -07:00
|
|
|
if ((Kind == OMPC_depend && Data.ExtraModifier == OMPC_DEPEND_unknown) ||
|
|
|
|
(Kind == OMPC_doacross &&
|
|
|
|
Data.ExtraModifier == OMPC_DOACROSS_unknown)) {
|
2015-06-23 14:25:19 +00:00
|
|
|
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
} else {
|
|
|
|
ConsumeToken();
|
2015-12-18 05:05:56 +00:00
|
|
|
// Special processing for depend(source) clause.
|
2023-06-21 16:26:35 -07:00
|
|
|
if (DKind == OMPD_ordered && Kind == OMPC_depend &&
|
|
|
|
Data.ExtraModifier == OMPC_DEPEND_source) {
|
2015-12-18 05:05:56 +00:00
|
|
|
// Parse ')'.
|
|
|
|
T.consumeClose();
|
2016-04-12 05:28:34 +00:00
|
|
|
return false;
|
2015-12-18 05:05:56 +00:00
|
|
|
}
|
2015-06-23 14:25:19 +00:00
|
|
|
}
|
2018-04-23 19:53:05 +00:00
|
|
|
if (Tok.is(tok::colon)) {
|
2016-04-12 05:28:34 +00:00
|
|
|
Data.ColonLoc = ConsumeToken();
|
2023-07-05 08:04:07 -07:00
|
|
|
} else if (Kind != OMPC_doacross || Tok.isNot(tok::r_paren)) {
|
2015-12-18 05:05:56 +00:00
|
|
|
Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
|
|
|
|
: diag::warn_pragma_expected_colon)
|
2023-06-21 16:26:35 -07:00
|
|
|
<< (Kind == OMPC_depend ? "dependency type" : "dependence-type");
|
|
|
|
}
|
2023-07-05 08:04:07 -07:00
|
|
|
if (Kind == OMPC_doacross) {
|
|
|
|
if (Tok.is(tok::identifier) &&
|
|
|
|
Tok.getIdentifierInfo()->isStr("omp_cur_iteration")) {
|
|
|
|
Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source
|
|
|
|
? OMPC_DOACROSS_source_omp_cur_iteration
|
|
|
|
: OMPC_DOACROSS_sink_omp_cur_iteration;
|
|
|
|
ConsumeToken();
|
|
|
|
}
|
|
|
|
if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {
|
|
|
|
if (Tok.isNot(tok::minus)) {
|
|
|
|
Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
|
|
|
|
<< getOpenMPClauseName(Kind) << 0 << 0;
|
|
|
|
SkipUntil(tok::r_paren);
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
ConsumeToken();
|
|
|
|
SourceLocation Loc = Tok.getLocation();
|
|
|
|
uint64_t Value = 0;
|
|
|
|
if (Tok.isNot(tok::numeric_constant) ||
|
|
|
|
(PP.parseSimpleIntegerLiteral(Tok, Value) && Value != 1)) {
|
|
|
|
Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd)
|
|
|
|
<< getOpenMPClauseName(Kind) << 0 << 0;
|
|
|
|
SkipUntil(tok::r_paren);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {
|
|
|
|
if (Tok.isNot(tok::r_paren)) {
|
|
|
|
Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
|
|
|
|
<< getOpenMPClauseName(Kind) << 1 << 1;
|
|
|
|
SkipUntil(tok::r_paren);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Only the 'sink' case has the expression list.
|
|
|
|
if (Kind == OMPC_doacross &&
|
|
|
|
(Data.ExtraModifier == OMPC_DOACROSS_source ||
|
|
|
|
Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||
|
|
|
|
Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {
|
|
|
|
// Parse ')'.
|
|
|
|
T.consumeClose();
|
|
|
|
return false;
|
|
|
|
}
|
2015-06-23 14:25:19 +00:00
|
|
|
}
|
2015-08-20 10:54:39 +00:00
|
|
|
} else if (Kind == OMPC_linear) {
|
|
|
|
// Try to parse modifier if any.
|
2019-12-20 11:04:57 -05:00
|
|
|
Data.ExtraModifier = OMPC_LINEAR_val;
|
2015-08-20 10:54:39 +00:00
|
|
|
if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
|
[OpenMP][OpenACC] Implement `ompx_hold` map type modifier extension in Clang (1/2)
This patch implements Clang support for an original OpenMP extension
we have developed to support OpenACC: the `ompx_hold` map type
modifier. The next patch in this series, D106510, implements OpenMP
runtime support.
Consider the following example:
```
#pragma omp target data map(ompx_hold, tofrom: x) // holds onto mapping of x
{
foo(); // might have map(delete: x)
#pragma omp target map(present, alloc: x) // x is guaranteed to be present
printf("%d\n", x);
}
```
The `ompx_hold` map type modifier above specifies that the `target
data` directive holds onto the mapping for `x` throughout the
associated region regardless of any `target exit data` directives
executed during the call to `foo`. Thus, the presence assertion for
`x` at the enclosed `target` construct cannot fail. (As usual, the
standard OpenMP reference count for `x` must also reach zero before
the data is unmapped.)
Justification for inclusion in Clang and LLVM's OpenMP runtime:
* The `ompx_hold` modifier supports OpenACC functionality (structured
reference count) that cannot be achieved in standard OpenMP, as of
5.1.
* The runtime implementation for `ompx_hold` (next patch) will thus be
used by Flang's OpenACC support.
* The Clang implementation for `ompx_hold` (this patch) as well as the
runtime implementation are required for the Clang OpenACC support
being developed as part of the ECP Clacc project, which translates
OpenACC to OpenMP at the directive AST level. These patches are the
first step in upstreaming OpenACC functionality from Clacc.
* The Clang implementation for `ompx_hold` is also used by the tests
in the runtime implementation. That syntactic support makes the
tests more readable than low-level runtime calls can. Moreover,
upstream Flang and Clang do not yet support OpenACC syntax
sufficiently for writing the tests.
* More generally, the Clang implementation enables a clean separation
of concerns between OpenACC and OpenMP development in LLVM. That
is, LLVM's OpenMP developers can discuss, modify, and debug LLVM's
extended OpenMP implementation and test suite without directly
considering OpenACC's language and execution model, which can be
handled by LLVM's OpenACC developers.
* OpenMP users might find the `ompx_hold` modifier useful, as in the
above example.
See new documentation introduced by this patch in `openmp/docs` for
more detail on the functionality of this extension and its
relationship with OpenACC. For example, it explains how the runtime
must support two reference counts, as specified by OpenACC.
Clang recognizes `ompx_hold` unless `-fno-openmp-extensions`, a new
command-line option introduced by this patch, is specified.
Reviewed By: ABataev, jdoerfert, protze.joachim, grokos
Differential Revision: https://reviews.llvm.org/D106509
2021-08-31 15:17:07 -04:00
|
|
|
Data.ExtraModifier =
|
|
|
|
getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
|
2020-03-23 17:30:38 -04:00
|
|
|
Data.ExtraModifierLoc = ConsumeToken();
|
2015-08-20 10:54:39 +00:00
|
|
|
LinearT.consumeOpen();
|
|
|
|
NeedRParenForLinear = true;
|
2023-10-25 15:36:36 -07:00
|
|
|
if (getLangOpts().OpenMP >= 52)
|
|
|
|
Diag(Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax)
|
|
|
|
<< "linear-modifier(list)" << getOpenMPClauseName(Kind)
|
|
|
|
<< "linear(list: [linear-modifier,] step(step-size))";
|
2015-08-20 10:54:39 +00:00
|
|
|
}
|
2019-12-20 11:04:57 -05:00
|
|
|
} else if (Kind == OMPC_lastprivate) {
|
|
|
|
// Try to parse modifier if any.
|
|
|
|
Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
|
|
|
|
// Conditional modifier allowed only in OpenMP 5.0 and not supported in
|
|
|
|
// distribute and taskloop based directives.
|
|
|
|
if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
|
|
|
|
!isOpenMPTaskLoopDirective(DKind)) &&
|
|
|
|
Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
|
[OpenMP][OpenACC] Implement `ompx_hold` map type modifier extension in Clang (1/2)
This patch implements Clang support for an original OpenMP extension
we have developed to support OpenACC: the `ompx_hold` map type
modifier. The next patch in this series, D106510, implements OpenMP
runtime support.
Consider the following example:
```
#pragma omp target data map(ompx_hold, tofrom: x) // holds onto mapping of x
{
foo(); // might have map(delete: x)
#pragma omp target map(present, alloc: x) // x is guaranteed to be present
printf("%d\n", x);
}
```
The `ompx_hold` map type modifier above specifies that the `target
data` directive holds onto the mapping for `x` throughout the
associated region regardless of any `target exit data` directives
executed during the call to `foo`. Thus, the presence assertion for
`x` at the enclosed `target` construct cannot fail. (As usual, the
standard OpenMP reference count for `x` must also reach zero before
the data is unmapped.)
Justification for inclusion in Clang and LLVM's OpenMP runtime:
* The `ompx_hold` modifier supports OpenACC functionality (structured
reference count) that cannot be achieved in standard OpenMP, as of
5.1.
* The runtime implementation for `ompx_hold` (next patch) will thus be
used by Flang's OpenACC support.
* The Clang implementation for `ompx_hold` (this patch) as well as the
runtime implementation are required for the Clang OpenACC support
being developed as part of the ECP Clacc project, which translates
OpenACC to OpenMP at the directive AST level. These patches are the
first step in upstreaming OpenACC functionality from Clacc.
* The Clang implementation for `ompx_hold` is also used by the tests
in the runtime implementation. That syntactic support makes the
tests more readable than low-level runtime calls can. Moreover,
upstream Flang and Clang do not yet support OpenACC syntax
sufficiently for writing the tests.
* More generally, the Clang implementation enables a clean separation
of concerns between OpenACC and OpenMP development in LLVM. That
is, LLVM's OpenMP developers can discuss, modify, and debug LLVM's
extended OpenMP implementation and test suite without directly
considering OpenACC's language and execution model, which can be
handled by LLVM's OpenACC developers.
* OpenMP users might find the `ompx_hold` modifier useful, as in the
above example.
See new documentation introduced by this patch in `openmp/docs` for
more detail on the functionality of this extension and its
relationship with OpenACC. For example, it explains how the runtime
must support two reference counts, as specified by OpenACC.
Clang recognizes `ompx_hold` unless `-fno-openmp-extensions`, a new
command-line option introduced by this patch, is specified.
Reviewed By: ABataev, jdoerfert, protze.joachim, grokos
Differential Revision: https://reviews.llvm.org/D106509
2021-08-31 15:17:07 -04:00
|
|
|
Data.ExtraModifier =
|
|
|
|
getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
|
2020-03-23 17:30:38 -04:00
|
|
|
Data.ExtraModifierLoc = Tok.getLocation();
|
|
|
|
ConsumeToken();
|
2019-12-20 11:04:57 -05:00
|
|
|
assert(Tok.is(tok::colon) && "Expected colon.");
|
|
|
|
Data.ColonLoc = ConsumeToken();
|
|
|
|
}
|
2015-11-23 05:32:03 +00:00
|
|
|
} else if (Kind == OMPC_map) {
|
2023-01-06 11:17:57 -06:00
|
|
|
// Handle optional iterator map modifier.
|
|
|
|
if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
|
|
|
|
HasIterator = true;
|
|
|
|
EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
|
|
|
|
Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);
|
|
|
|
Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
|
|
|
|
ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
|
|
|
|
Data.IteratorExpr = IteratorRes.get();
|
|
|
|
// Parse ','
|
|
|
|
ExpectAndConsume(tok::comma);
|
|
|
|
if (getLangOpts().OpenMP < 52) {
|
|
|
|
Diag(Tok, diag::err_omp_unknown_map_type_modifier)
|
|
|
|
<< (getLangOpts().OpenMP >= 51 ? 1 : 0)
|
2025-03-11 16:31:42 +05:30
|
|
|
<< getLangOpts().OpenMPExtensions << 0;
|
2023-01-06 11:17:57 -06:00
|
|
|
InvalidIterator = true;
|
|
|
|
}
|
|
|
|
}
|
2015-11-23 05:32:03 +00:00
|
|
|
// Handle map type for map clause.
|
|
|
|
ColonProtectionRAIIObject ColonRAII(*this);
|
|
|
|
|
2016-02-27 00:01:58 +00:00
|
|
|
// The first identifier may be a list item, a map-type or a
|
2018-12-18 22:18:41 +00:00
|
|
|
// map-type-modifier. The map-type can also be delete which has the same
|
2016-02-27 00:01:58 +00:00
|
|
|
// spelling of the C++ delete keyword.
|
2019-12-20 11:04:57 -05:00
|
|
|
Data.ExtraModifier = OMPC_MAP_unknown;
|
2020-03-23 17:30:38 -04:00
|
|
|
Data.ExtraModifierLoc = Tok.getLocation();
|
2015-11-23 05:32:03 +00:00
|
|
|
|
2018-12-18 22:18:41 +00:00
|
|
|
// Check for presence of a colon in the map clause.
|
|
|
|
TentativeParsingAction TPA(*this);
|
|
|
|
bool ColonPresent = false;
|
|
|
|
if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
|
2020-10-29 18:44:28 -05:00
|
|
|
StopBeforeMatch)) {
|
2018-12-18 22:18:41 +00:00
|
|
|
if (Tok.is(tok::colon))
|
|
|
|
ColonPresent = true;
|
|
|
|
}
|
|
|
|
TPA.Revert();
|
|
|
|
// Only parse map-type-modifier[s] and map-type if a colon is present in
|
|
|
|
// the map clause.
|
|
|
|
if (ColonPresent) {
|
2024-05-13 07:39:23 -07:00
|
|
|
if (getLangOpts().OpenMP >= 60 && getCurToken().is(tok::colon))
|
|
|
|
Diag(Tok, diag::err_omp_map_modifier_specification_list);
|
2019-02-22 22:29:42 +00:00
|
|
|
IsInvalidMapperModifier = parseMapTypeModifiers(Data);
|
2024-05-13 07:39:23 -07:00
|
|
|
if (getLangOpts().OpenMP < 60 && !IsInvalidMapperModifier)
|
2019-02-19 16:38:20 +00:00
|
|
|
parseMapType(*this, Data);
|
2019-02-22 22:29:42 +00:00
|
|
|
else
|
|
|
|
SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
|
2018-12-18 22:18:41 +00:00
|
|
|
}
|
2019-12-20 11:04:57 -05:00
|
|
|
if (Data.ExtraModifier == OMPC_MAP_unknown) {
|
|
|
|
Data.ExtraModifier = OMPC_MAP_tofrom;
|
2022-11-17 15:30:53 -06:00
|
|
|
if (getLangOpts().OpenMP >= 52) {
|
|
|
|
if (DKind == OMPD_target_enter_data)
|
|
|
|
Data.ExtraModifier = OMPC_MAP_to;
|
|
|
|
else if (DKind == OMPD_target_exit_data)
|
|
|
|
Data.ExtraModifier = OMPC_MAP_from;
|
|
|
|
}
|
2016-04-12 05:28:34 +00:00
|
|
|
Data.IsMapTypeImplicit = true;
|
2015-11-23 05:32:03 +00:00
|
|
|
}
|
|
|
|
|
2016-04-12 05:28:34 +00:00
|
|
|
if (Tok.is(tok::colon))
|
|
|
|
Data.ColonLoc = ConsumeToken();
|
2019-02-25 20:34:15 +00:00
|
|
|
} else if (Kind == OMPC_to || Kind == OMPC_from) {
|
2020-07-29 12:18:45 -04:00
|
|
|
while (Tok.is(tok::identifier)) {
|
[OpenMP][OpenACC] Implement `ompx_hold` map type modifier extension in Clang (1/2)
This patch implements Clang support for an original OpenMP extension
we have developed to support OpenACC: the `ompx_hold` map type
modifier. The next patch in this series, D106510, implements OpenMP
runtime support.
Consider the following example:
```
#pragma omp target data map(ompx_hold, tofrom: x) // holds onto mapping of x
{
foo(); // might have map(delete: x)
#pragma omp target map(present, alloc: x) // x is guaranteed to be present
printf("%d\n", x);
}
```
The `ompx_hold` map type modifier above specifies that the `target
data` directive holds onto the mapping for `x` throughout the
associated region regardless of any `target exit data` directives
executed during the call to `foo`. Thus, the presence assertion for
`x` at the enclosed `target` construct cannot fail. (As usual, the
standard OpenMP reference count for `x` must also reach zero before
the data is unmapped.)
Justification for inclusion in Clang and LLVM's OpenMP runtime:
* The `ompx_hold` modifier supports OpenACC functionality (structured
reference count) that cannot be achieved in standard OpenMP, as of
5.1.
* The runtime implementation for `ompx_hold` (next patch) will thus be
used by Flang's OpenACC support.
* The Clang implementation for `ompx_hold` (this patch) as well as the
runtime implementation are required for the Clang OpenACC support
being developed as part of the ECP Clacc project, which translates
OpenACC to OpenMP at the directive AST level. These patches are the
first step in upstreaming OpenACC functionality from Clacc.
* The Clang implementation for `ompx_hold` is also used by the tests
in the runtime implementation. That syntactic support makes the
tests more readable than low-level runtime calls can. Moreover,
upstream Flang and Clang do not yet support OpenACC syntax
sufficiently for writing the tests.
* More generally, the Clang implementation enables a clean separation
of concerns between OpenACC and OpenMP development in LLVM. That
is, LLVM's OpenMP developers can discuss, modify, and debug LLVM's
extended OpenMP implementation and test suite without directly
considering OpenACC's language and execution model, which can be
handled by LLVM's OpenACC developers.
* OpenMP users might find the `ompx_hold` modifier useful, as in the
above example.
See new documentation introduced by this patch in `openmp/docs` for
more detail on the functionality of this extension and its
relationship with OpenACC. For example, it explains how the runtime
must support two reference counts, as specified by OpenACC.
Clang recognizes `ompx_hold` unless `-fno-openmp-extensions`, a new
command-line option introduced by this patch, is specified.
Reviewed By: ABataev, jdoerfert, protze.joachim, grokos
Differential Revision: https://reviews.llvm.org/D106509
2021-08-31 15:17:07 -04:00
|
|
|
auto Modifier = static_cast<OpenMPMotionModifierKind>(
|
|
|
|
getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
|
2020-07-29 12:18:45 -04:00
|
|
|
if (Modifier == OMPC_MOTION_MODIFIER_unknown)
|
|
|
|
break;
|
|
|
|
Data.MotionModifiers.push_back(Modifier);
|
|
|
|
Data.MotionModifiersLoc.push_back(Tok.getLocation());
|
|
|
|
ConsumeToken();
|
2020-07-28 18:06:05 -04:00
|
|
|
if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
|
2020-07-28 20:26:56 -04:00
|
|
|
IsInvalidMapperModifier = parseMapperModifier(Data);
|
2020-07-29 12:18:45 -04:00
|
|
|
if (IsInvalidMapperModifier)
|
|
|
|
break;
|
2020-07-28 18:06:24 -04:00
|
|
|
}
|
2020-07-29 12:18:45 -04:00
|
|
|
// OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
|
|
|
|
if (getLangOpts().OpenMP < 51)
|
|
|
|
break;
|
|
|
|
// OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
|
|
|
|
// TODO: Is that intentional?
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
|
|
|
}
|
|
|
|
if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {
|
|
|
|
if (!IsInvalidMapperModifier) {
|
|
|
|
if (getLangOpts().OpenMP < 51)
|
|
|
|
Diag(Tok, diag::warn_pragma_expected_colon) << ")";
|
|
|
|
else
|
|
|
|
Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier";
|
|
|
|
}
|
|
|
|
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
2019-02-22 22:29:42 +00:00
|
|
|
}
|
2020-07-29 12:18:45 -04:00
|
|
|
// OpenMP 5.1 permits a ':' even without a preceding modifier. TODO: Is
|
|
|
|
// that intentional?
|
|
|
|
if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&
|
|
|
|
Tok.is(tok::colon))
|
|
|
|
Data.ColonLoc = ConsumeToken();
|
2020-05-18 13:37:53 -04:00
|
|
|
} else if (Kind == OMPC_allocate ||
|
|
|
|
(Kind == OMPC_affinity && Tok.is(tok::identifier) &&
|
|
|
|
PP.getSpelling(Tok) == "iterator")) {
|
2025-01-13 05:44:48 -08:00
|
|
|
// Handle optional allocator and align modifiers followed by colon
|
|
|
|
// delimiter.
|
2019-03-27 14:14:31 +00:00
|
|
|
ColonProtectionRAIIObject ColonRAII(*this);
|
|
|
|
TentativeParsingAction TPA(*this);
|
2020-05-18 13:37:53 -04:00
|
|
|
// OpenMP 5.0, 2.10.1, task Construct.
|
|
|
|
// where aff-modifier is one of the following:
|
|
|
|
// iterator(iterators-definition)
|
|
|
|
ExprResult Tail;
|
|
|
|
if (Kind == OMPC_allocate) {
|
2024-11-11 16:11:16 -08:00
|
|
|
Tail = parseOpenMPAllocateClauseModifiers(*this, Kind, Data);
|
2020-05-18 13:37:53 -04:00
|
|
|
} else {
|
|
|
|
HasIterator = true;
|
|
|
|
EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
|
|
|
|
Tail = ParseOpenMPIteratorsExpr();
|
|
|
|
}
|
|
|
|
Tail = Actions.CorrectDelayedTyposInExpr(Tail);
|
2019-03-27 14:14:31 +00:00
|
|
|
Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
|
|
|
|
/*DiscardedValue=*/false);
|
2025-01-13 05:44:48 -08:00
|
|
|
if (Tail.isUsable() || Data.AllocateAlignment) {
|
2019-03-27 14:14:31 +00:00
|
|
|
if (Tok.is(tok::colon)) {
|
2025-01-13 05:44:48 -08:00
|
|
|
Data.DepModOrTailExpr = Tail.isUsable() ? Tail.get() : nullptr;
|
2019-03-27 14:14:31 +00:00
|
|
|
Data.ColonLoc = ConsumeToken();
|
|
|
|
TPA.Commit();
|
|
|
|
} else {
|
2020-05-18 13:37:53 -04:00
|
|
|
// Colon not found, parse only list of variables.
|
2019-03-27 14:14:31 +00:00
|
|
|
TPA.Revert();
|
2025-01-13 05:44:48 -08:00
|
|
|
if (Kind == OMPC_allocate && Data.AllocClauseModifiers.size()) {
|
2024-11-05 17:06:41 -08:00
|
|
|
SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
2025-01-13 05:44:48 -08:00
|
|
|
Diag(Tok, diag::err_modifier_expected_colon) << "allocate clause";
|
2024-11-05 17:06:41 -08:00
|
|
|
}
|
2019-03-27 14:14:31 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Parsing was unsuccessfull, revert and skip to the end of clause or
|
|
|
|
// directive.
|
|
|
|
TPA.Revert();
|
|
|
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
}
|
2021-10-12 14:55:00 -07:00
|
|
|
} else if (Kind == OMPC_adjust_args) {
|
|
|
|
// Handle adjust-op for adjust_args clause.
|
|
|
|
ColonProtectionRAIIObject ColonRAII(*this);
|
|
|
|
Data.ExtraModifier = getOpenMPSimpleClauseType(
|
|
|
|
Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
|
|
|
|
getLangOpts());
|
|
|
|
Data.ExtraModifierLoc = Tok.getLocation();
|
|
|
|
if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) {
|
2024-06-24 13:37:49 -07:00
|
|
|
Diag(Tok, diag::err_omp_unknown_adjust_args_op);
|
|
|
|
SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
|
2021-10-12 14:55:00 -07:00
|
|
|
} else {
|
|
|
|
ConsumeToken();
|
|
|
|
if (Tok.is(tok::colon))
|
|
|
|
Data.ColonLoc = Tok.getLocation();
|
|
|
|
ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
|
|
|
|
"adjust-op");
|
|
|
|
}
|
2014-06-16 07:08:35 +00:00
|
|
|
}
|
|
|
|
|
2017-07-21 18:48:21 +00:00
|
|
|
bool IsComma =
|
|
|
|
(Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
|
2023-06-21 16:26:35 -07:00
|
|
|
Kind != OMPC_in_reduction && Kind != OMPC_depend &&
|
2024-06-24 13:37:49 -07:00
|
|
|
Kind != OMPC_doacross && Kind != OMPC_map && Kind != OMPC_adjust_args) ||
|
2017-07-21 18:48:21 +00:00
|
|
|
(Kind == OMPC_reduction && !InvalidReductionId) ||
|
2019-12-20 11:04:57 -05:00
|
|
|
(Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
|
2021-10-12 14:55:00 -07:00
|
|
|
(Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) ||
|
2023-06-21 16:26:35 -07:00
|
|
|
(Kind == OMPC_doacross && Data.ExtraModifier != OMPC_DOACROSS_unknown) ||
|
2021-10-12 14:55:00 -07:00
|
|
|
(Kind == OMPC_adjust_args &&
|
|
|
|
Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown);
|
2014-05-29 14:36:25 +00:00
|
|
|
const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
|
2014-04-22 13:09:42 +00:00
|
|
|
while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
|
2013-07-19 03:13:43 +00:00
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))) {
|
2020-04-01 15:06:38 -04:00
|
|
|
ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
|
2014-04-22 13:09:42 +00:00
|
|
|
ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
|
2022-05-17 10:11:00 -07:00
|
|
|
if (!ParseOpenMPReservedLocator(Kind, Data, getLangOpts())) {
|
|
|
|
// Parse variable
|
|
|
|
ExprResult VarExpr =
|
|
|
|
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
|
|
|
|
if (VarExpr.isUsable()) {
|
|
|
|
Vars.push_back(VarExpr.get());
|
|
|
|
} else {
|
|
|
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
}
|
2013-07-19 03:13:43 +00:00
|
|
|
}
|
|
|
|
// Skip ',' if any
|
|
|
|
IsComma = Tok.is(tok::comma);
|
2016-04-01 08:43:42 +00:00
|
|
|
if (IsComma)
|
2013-07-19 03:13:43 +00:00
|
|
|
ConsumeToken();
|
2016-04-01 08:43:42 +00:00
|
|
|
else if (Tok.isNot(tok::r_paren) &&
|
2014-04-22 13:09:42 +00:00
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end) &&
|
|
|
|
(!MayHaveTail || Tok.isNot(tok::colon)))
|
2014-07-21 11:26:11 +00:00
|
|
|
Diag(Tok, diag::err_omp_expected_punc)
|
|
|
|
<< ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
|
|
|
|
: getOpenMPClauseName(Kind))
|
|
|
|
<< (Kind == OMPC_flush);
|
2014-04-22 13:09:42 +00:00
|
|
|
}
|
|
|
|
|
2015-08-20 10:54:39 +00:00
|
|
|
// Parse ')' for linear clause with modifier.
|
|
|
|
if (NeedRParenForLinear)
|
|
|
|
LinearT.consumeClose();
|
2023-09-20 11:12:41 -07:00
|
|
|
// Parse ':' linear modifiers (val, uval, ref or step(step-size))
|
|
|
|
// or parse ':' alignment.
|
2014-04-22 13:09:42 +00:00
|
|
|
const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
|
2023-09-20 11:12:41 -07:00
|
|
|
bool StepFound = false;
|
|
|
|
bool ModifierFound = false;
|
2014-04-22 13:09:42 +00:00
|
|
|
if (MustHaveTail) {
|
2016-04-12 05:28:34 +00:00
|
|
|
Data.ColonLoc = Tok.getLocation();
|
2015-09-03 07:23:48 +00:00
|
|
|
SourceLocation ELoc = ConsumeToken();
|
2023-09-20 11:12:41 -07:00
|
|
|
|
|
|
|
if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {
|
|
|
|
while (Tok.isNot(tok::r_paren)) {
|
|
|
|
if (Tok.is(tok::identifier)) {
|
|
|
|
// identifier could be a linear kind (val, uval, ref) or step
|
|
|
|
// modifier or step size
|
|
|
|
OpenMPLinearClauseKind LinKind =
|
|
|
|
static_cast<OpenMPLinearClauseKind>(getOpenMPSimpleClauseType(
|
|
|
|
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
|
|
|
|
getLangOpts()));
|
|
|
|
|
|
|
|
if (LinKind == OMPC_LINEAR_step) {
|
|
|
|
if (StepFound)
|
|
|
|
Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;
|
|
|
|
|
|
|
|
BalancedDelimiterTracker StepT(*this, tok::l_paren,
|
|
|
|
tok::annot_pragma_openmp_end);
|
|
|
|
SourceLocation StepModifierLoc = ConsumeToken();
|
|
|
|
// parse '('
|
|
|
|
if (StepT.consumeOpen())
|
|
|
|
Diag(StepModifierLoc, diag::err_expected_lparen_after) << "step";
|
|
|
|
|
|
|
|
// parse step size expression
|
|
|
|
StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
|
|
|
|
if (StepFound)
|
|
|
|
Data.StepModifierLoc = StepModifierLoc;
|
|
|
|
|
|
|
|
// parse ')'
|
|
|
|
StepT.consumeClose();
|
|
|
|
} else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {
|
|
|
|
if (ModifierFound)
|
|
|
|
Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;
|
|
|
|
|
|
|
|
Data.ExtraModifier = LinKind;
|
|
|
|
Data.ExtraModifierLoc = ConsumeToken();
|
|
|
|
ModifierFound = true;
|
|
|
|
} else {
|
|
|
|
StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// parse an integer expression as step size
|
|
|
|
StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
|
|
|
if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!StepFound && !ModifierFound)
|
|
|
|
Diag(ELoc, diag::err_expected_expression);
|
|
|
|
} else {
|
|
|
|
// for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)
|
|
|
|
ExprResult Tail = ParseAssignmentExpression();
|
|
|
|
Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
|
|
|
|
/*DiscardedValue*/ false);
|
|
|
|
if (Tail.isUsable())
|
|
|
|
Data.DepModOrTailExpr = Tail.get();
|
|
|
|
else
|
|
|
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
}
|
2013-07-19 03:13:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Parse ')'.
|
2018-07-06 19:35:42 +00:00
|
|
|
Data.RLoc = Tok.getLocation();
|
|
|
|
if (!T.consumeClose())
|
|
|
|
Data.RLoc = T.getCloseLocation();
|
2020-04-01 15:06:38 -04:00
|
|
|
// Exit from scope when the iterator is used in depend clause.
|
2020-05-18 13:37:53 -04:00
|
|
|
if (HasIterator)
|
2020-04-01 15:06:38 -04:00
|
|
|
ExitScope();
|
2023-06-21 16:26:35 -07:00
|
|
|
return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&
|
|
|
|
Vars.empty()) ||
|
2023-09-20 11:12:41 -07:00
|
|
|
(MustHaveTail && !Data.DepModOrTailExpr && StepFound) ||
|
|
|
|
InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;
|
2016-04-12 05:28:34 +00:00
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
|
2020-03-20 09:41:22 -04:00
|
|
|
/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction',
|
2020-03-23 10:41:08 -04:00
|
|
|
/// 'in_reduction', 'nontemporal', 'exclusive' or 'inclusive'.
|
2016-04-12 05:28:34 +00:00
|
|
|
///
|
|
|
|
/// private-clause:
|
|
|
|
/// 'private' '(' list ')'
|
|
|
|
/// firstprivate-clause:
|
|
|
|
/// 'firstprivate' '(' list ')'
|
|
|
|
/// lastprivate-clause:
|
|
|
|
/// 'lastprivate' '(' list ')'
|
|
|
|
/// shared-clause:
|
|
|
|
/// 'shared' '(' list ')'
|
|
|
|
/// linear-clause:
|
|
|
|
/// 'linear' '(' linear-list [ ':' linear-step ] ')'
|
|
|
|
/// aligned-clause:
|
|
|
|
/// 'aligned' '(' list [ ':' alignment ] ')'
|
|
|
|
/// reduction-clause:
|
2020-03-23 17:30:38 -04:00
|
|
|
/// 'reduction' '(' [ modifier ',' ] reduction-identifier ':' list ')'
|
2017-07-18 20:17:46 +00:00
|
|
|
/// task_reduction-clause:
|
|
|
|
/// 'task_reduction' '(' reduction-identifier ':' list ')'
|
2017-07-21 18:48:21 +00:00
|
|
|
/// in_reduction-clause:
|
|
|
|
/// 'in_reduction' '(' reduction-identifier ':' list ')'
|
2016-04-12 05:28:34 +00:00
|
|
|
/// copyprivate-clause:
|
|
|
|
/// 'copyprivate' '(' list ')'
|
|
|
|
/// flush-clause:
|
|
|
|
/// 'flush' '(' list ')'
|
|
|
|
/// depend-clause:
|
|
|
|
/// 'depend' '(' in | out | inout : list | source ')'
|
|
|
|
/// map-clause:
|
2018-12-18 22:18:41 +00:00
|
|
|
/// 'map' '(' [ [ always [,] ] [ close [,] ]
|
2019-02-22 22:29:42 +00:00
|
|
|
/// [ mapper '(' mapper-identifier ')' [,] ]
|
2016-04-12 05:28:34 +00:00
|
|
|
/// to | from | tofrom | alloc | release | delete ':' ] list ')';
|
2016-05-26 17:39:58 +00:00
|
|
|
/// to-clause:
|
2019-02-22 22:29:42 +00:00
|
|
|
/// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
|
2016-05-26 17:49:04 +00:00
|
|
|
/// from-clause:
|
2019-02-25 20:34:15 +00:00
|
|
|
/// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
|
2016-07-13 15:37:16 +00:00
|
|
|
/// use_device_ptr-clause:
|
|
|
|
/// 'use_device_ptr' '(' list ')'
|
2020-05-21 08:30:23 -04:00
|
|
|
/// use_device_addr-clause:
|
|
|
|
/// 'use_device_addr' '(' list ')'
|
2016-07-13 17:16:49 +00:00
|
|
|
/// is_device_ptr-clause:
|
|
|
|
/// 'is_device_ptr' '(' list ')'
|
2022-04-06 20:30:44 -07:00
|
|
|
/// has_device_addr-clause:
|
|
|
|
/// 'has_device_addr' '(' list ')'
|
2019-03-27 14:14:31 +00:00
|
|
|
/// allocate-clause:
|
|
|
|
/// 'allocate' '(' [ allocator ':' ] list ')'
|
2024-11-05 17:06:41 -08:00
|
|
|
/// As of OpenMP 5.1 there's also
|
|
|
|
/// 'allocate' '(' allocate-modifier: list ')'
|
|
|
|
/// where allocate-modifier is: 'allocator' '(' allocator ')'
|
2020-03-20 09:41:22 -04:00
|
|
|
/// nontemporal-clause:
|
|
|
|
/// 'nontemporal' '(' list ')'
|
|
|
|
/// inclusive-clause:
|
|
|
|
/// 'inclusive' '(' list ')'
|
2020-03-23 10:41:08 -04:00
|
|
|
/// exclusive-clause:
|
|
|
|
/// 'exclusive' '(' list ')'
|
2016-04-12 05:28:34 +00:00
|
|
|
///
|
|
|
|
/// For 'linear' clause linear-list may have the following forms:
|
|
|
|
/// list
|
|
|
|
/// modifier(list)
|
|
|
|
/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
|
|
|
|
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
|
2018-01-09 19:21:04 +00:00
|
|
|
OpenMPClauseKind Kind,
|
|
|
|
bool ParseOnly) {
|
2016-04-12 05:28:34 +00:00
|
|
|
SourceLocation Loc = Tok.getLocation();
|
|
|
|
SourceLocation LOpen = ConsumeToken();
|
|
|
|
SmallVector<Expr *, 4> Vars;
|
2024-04-16 16:36:53 +04:00
|
|
|
SemaOpenMP::OpenMPVarListDataTy Data;
|
2016-04-12 05:28:34 +00:00
|
|
|
|
|
|
|
if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
|
2014-05-21 06:02:52 +00:00
|
|
|
return nullptr;
|
2013-07-19 03:13:43 +00:00
|
|
|
|
2018-01-09 19:21:04 +00:00
|
|
|
if (ParseOnly)
|
|
|
|
return nullptr;
|
2019-02-19 16:38:20 +00:00
|
|
|
OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
|
2024-04-16 16:36:53 +04:00
|
|
|
return Actions.OpenMP().ActOnOpenMPVarListClause(Kind, Vars, Locs, Data);
|
2013-07-19 03:13:43 +00:00
|
|
|
}
|
2024-05-13 16:10:58 +02:00
|
|
|
|
|
|
|
bool Parser::ParseOpenMPExprListClause(OpenMPClauseKind Kind,
|
|
|
|
SourceLocation &ClauseNameLoc,
|
|
|
|
SourceLocation &OpenLoc,
|
|
|
|
SourceLocation &CloseLoc,
|
|
|
|
SmallVectorImpl<Expr *> &Exprs,
|
|
|
|
bool ReqIntConst) {
|
|
|
|
assert(getOpenMPClauseName(Kind) == PP.getSpelling(Tok) &&
|
|
|
|
"Expected parsing to start at clause name");
|
|
|
|
ClauseNameLoc = ConsumeToken();
|
|
|
|
|
|
|
|
// Parse inside of '(' and ')'.
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
|
|
|
if (T.consumeOpen()) {
|
|
|
|
Diag(Tok, diag::err_expected) << tok::l_paren;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse the list with interleaved commas.
|
|
|
|
do {
|
|
|
|
ExprResult Val =
|
|
|
|
ReqIntConst ? ParseConstantExpression() : ParseAssignmentExpression();
|
|
|
|
if (!Val.isUsable()) {
|
|
|
|
// Encountered something other than an expression; abort to ')'.
|
|
|
|
T.skipToEnd();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
Exprs.push_back(Val.get());
|
|
|
|
} while (TryConsumeToken(tok::comma));
|
|
|
|
|
|
|
|
bool Result = T.consumeClose();
|
|
|
|
OpenLoc = T.getOpenLocation();
|
|
|
|
CloseLoc = T.getCloseLocation();
|
|
|
|
return Result;
|
|
|
|
}
|