[OPENMP50]Add device/kind context selector support.
Summary: Added basic parsing/sema support for device/kind context selector.
Reviewers: jdoerfert
Subscribers: rampitec, aheejin, fedor.sergeev, simoncook, guansong, s.egerton, hfinkel, kkwli0, caomhin, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D70245
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 208e324..3cf3380 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -874,6 +874,7 @@
Data.emplace_back(OMP_CTX_SET_implementation, CSKind, Score, Vendors);
break;
}
+ case OMP_CTX_kind:
case OMP_CTX_unknown:
P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
<< "implementation";
@@ -885,6 +886,91 @@
}
}
+/// Parse context selector for 'device' selector set:
+/// 'kind' '(' <kind> { ',' <kind> } ')'
+static void
+parseDeviceSelector(Parser &P, SourceLocation Loc,
+ llvm::StringMap<SourceLocation> &UsedCtx,
+ SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) {
+ const Token &Tok = P.getCurToken();
+ // Parse inner context selector set name, if any.
+ if (!Tok.is(tok::identifier)) {
+ P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
+ << "device";
+ // Skip until either '}', ')', or end of directive.
+ while (!P.SkipUntil(tok::r_brace, tok::r_paren,
+ tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
+ ;
+ return;
+ }
+ Sema::OMPCtxStringType Buffer;
+ StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer);
+ auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation());
+ if (!Res.second) {
+ // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions.
+ // Each trait-selector-name can only be specified once.
+ P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use)
+ << CtxSelectorName << "device";
+ P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
+ << CtxSelectorName;
+ }
+ OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName);
+ (void)P.ConsumeToken();
+ switch (CSKind) {
+ case OMP_CTX_kind: {
+ // Parse '('.
+ BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
+ (void)T.expectAndConsume(diag::err_expected_lparen_after,
+ CtxSelectorName.data());
+ llvm::UniqueVector<Sema::OMPCtxStringType> Kinds;
+ do {
+ // Parse <kind>.
+ StringRef KindName;
+ if (Tok.is(tok::identifier)) {
+ Buffer.clear();
+ KindName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
+ SourceLocation SLoc = P.getCurToken().getLocation();
+ (void)P.ConsumeToken();
+ if (llvm::StringSwitch<bool>(KindName)
+ .Case("host", false)
+ .Case("nohost", false)
+ .Case("cpu", false)
+ .Case("gpu", false)
+ .Case("fpga", false)
+ .Default(true)) {
+ P.Diag(SLoc, diag::err_omp_wrong_device_kind_trait) << KindName;
+ } else {
+ Kinds.insert(KindName);
+ }
+ } else {
+ P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected)
+ << "'host', 'nohost', 'cpu', 'gpu', or 'fpga'"
+ << "kind"
+ << "device";
+ }
+ if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) {
+ P.Diag(Tok, diag::err_expected_punc)
+ << (KindName.empty() ? "kind of device" : KindName);
+ }
+ } while (Tok.is(tok::identifier));
+ // Parse ')'.
+ (void)T.consumeClose();
+ if (!Kinds.empty())
+ Data.emplace_back(OMP_CTX_SET_device, CSKind, ExprResult(), Kinds);
+ break;
+ }
+ case OMP_CTX_vendor:
+ case OMP_CTX_unknown:
+ P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
+ << "device";
+ // Skip until either '}', ')', or end of directive.
+ while (!P.SkipUntil(tok::r_brace, tok::r_paren,
+ tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
+ ;
+ return;
+ }
+}
+
/// Parses clauses for 'declare variant' directive.
/// clause:
/// <selector_set_name> '=' '{' <context_selectors> '}'
@@ -935,6 +1021,9 @@
case OMP_CTX_SET_implementation:
parseImplementationSelector(*this, Loc, UsedCtx, Data);
break;
+ case OMP_CTX_SET_device:
+ parseDeviceSelector(*this, Loc, UsedCtx, Data);
+ break;
case OMP_CTX_SET_unknown:
// Skip until either '}', ')', or end of directive.
while (!SkipUntil(tok::r_brace, tok::r_paren,