So far, all the work we've done for compute constructs has only used 'parallel'. This patch does the work to enable the same logic for 'serial' and 'kernels' constructs as well, since they are the same semantic behavior.
123 lines
4.6 KiB
C++
123 lines
4.6 KiB
C++
//===--- SemaOpenACC.cpp - Semantic Analysis for OpenACC constructs -------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
/// \file
|
|
/// This file implements semantic analysis for OpenACC constructs and
|
|
/// clauses.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/Basic/DiagnosticSema.h"
|
|
#include "clang/Basic/OpenACCKinds.h"
|
|
#include "clang/Sema/Sema.h"
|
|
|
|
using namespace clang;
|
|
|
|
namespace {
|
|
bool diagnoseConstructAppertainment(Sema &S, OpenACCDirectiveKind K,
|
|
SourceLocation StartLoc, bool IsStmt) {
|
|
switch (K) {
|
|
default:
|
|
case OpenACCDirectiveKind::Invalid:
|
|
// Nothing to do here, both invalid and unimplemented don't really need to
|
|
// do anything.
|
|
break;
|
|
case OpenACCDirectiveKind::Parallel:
|
|
case OpenACCDirectiveKind::Serial:
|
|
case OpenACCDirectiveKind::Kernels:
|
|
if (!IsStmt)
|
|
return S.Diag(StartLoc, diag::err_acc_construct_appertainment) << K;
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
} // namespace
|
|
|
|
bool Sema::ActOnOpenACCClause(OpenACCClauseKind ClauseKind,
|
|
SourceLocation StartLoc) {
|
|
if (ClauseKind == OpenACCClauseKind::Invalid)
|
|
return false;
|
|
// For now just diagnose that it is unsupported and leave the parsing to do
|
|
// whatever it can do. This function will eventually need to start returning
|
|
// some sort of Clause AST type, but for now just return true/false based on
|
|
// success.
|
|
return Diag(StartLoc, diag::warn_acc_clause_unimplemented) << ClauseKind;
|
|
}
|
|
void Sema::ActOnOpenACCConstruct(OpenACCDirectiveKind K,
|
|
SourceLocation StartLoc) {
|
|
switch (K) {
|
|
case OpenACCDirectiveKind::Invalid:
|
|
// Nothing to do here, an invalid kind has nothing we can check here. We
|
|
// want to continue parsing clauses as far as we can, so we will just
|
|
// ensure that we can still work and don't check any construct-specific
|
|
// rules anywhere.
|
|
break;
|
|
case OpenACCDirectiveKind::Parallel:
|
|
case OpenACCDirectiveKind::Serial:
|
|
case OpenACCDirectiveKind::Kernels:
|
|
// Nothing to do here, there is no real legalization that needs to happen
|
|
// here as these constructs do not take any arguments.
|
|
break;
|
|
default:
|
|
Diag(StartLoc, diag::warn_acc_construct_unimplemented) << K;
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool Sema::ActOnStartOpenACCStmtDirective(OpenACCDirectiveKind K,
|
|
SourceLocation StartLoc) {
|
|
return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true);
|
|
}
|
|
|
|
StmtResult Sema::ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K,
|
|
SourceLocation StartLoc,
|
|
SourceLocation EndLoc,
|
|
StmtResult AssocStmt) {
|
|
switch (K) {
|
|
default:
|
|
return StmtEmpty();
|
|
case OpenACCDirectiveKind::Invalid:
|
|
return StmtError();
|
|
case OpenACCDirectiveKind::Parallel:
|
|
case OpenACCDirectiveKind::Serial:
|
|
case OpenACCDirectiveKind::Kernels:
|
|
return OpenACCComputeConstruct::Create(
|
|
getASTContext(), K, StartLoc, EndLoc,
|
|
AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
|
|
}
|
|
llvm_unreachable("Unhandled case in directive handling?");
|
|
}
|
|
|
|
StmtResult Sema::ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K,
|
|
StmtResult AssocStmt) {
|
|
switch (K) {
|
|
default:
|
|
llvm_unreachable("Unimplemented associated statement application");
|
|
case OpenACCDirectiveKind::Parallel:
|
|
case OpenACCDirectiveKind::Serial:
|
|
case OpenACCDirectiveKind::Kernels:
|
|
// There really isn't any checking here that could happen. As long as we
|
|
// have a statement to associate, this should be fine.
|
|
// OpenACC 3.3 Section 6:
|
|
// Structured Block: in C or C++, an executable statement, possibly
|
|
// compound, with a single entry at the top and a single exit at the
|
|
// bottom.
|
|
// FIXME: Should we reject DeclStmt's here? The standard isn't clear, and
|
|
// an interpretation of it is to allow this and treat the initializer as
|
|
// the 'structured block'.
|
|
return AssocStmt;
|
|
}
|
|
llvm_unreachable("Invalid associated statement application");
|
|
}
|
|
|
|
bool Sema::ActOnStartOpenACCDeclDirective(OpenACCDirectiveKind K,
|
|
SourceLocation StartLoc) {
|
|
return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/false);
|
|
}
|
|
|
|
DeclGroupRef Sema::ActOnEndOpenACCDeclDirective() { return DeclGroupRef{}; }
|