This patch implements the 'loop' construct AST, as well as the basic appertainment rule. Additionally, it sets up the 'parent' compute construct, which is necessary for codegen/other diagnostics. A 'loop' can apply to a for or range-for loop, otherwise it has no other restrictions (though some of its clauses do).
126 lines
4.8 KiB
C++
126 lines
4.8 KiB
C++
//===--- StmtOpenACC.cpp - Classes 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the subclasses of Stmt class declared in StmtOpenACC.h
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/AST/StmtOpenACC.h"
|
|
#include "clang/AST/ASTContext.h"
|
|
#include "clang/AST/RecursiveASTVisitor.h"
|
|
#include "clang/AST/StmtCXX.h"
|
|
using namespace clang;
|
|
|
|
OpenACCComputeConstruct *
|
|
OpenACCComputeConstruct::CreateEmpty(const ASTContext &C, unsigned NumClauses) {
|
|
void *Mem = C.Allocate(
|
|
OpenACCComputeConstruct::totalSizeToAlloc<const OpenACCClause *>(
|
|
NumClauses));
|
|
auto *Inst = new (Mem) OpenACCComputeConstruct(NumClauses);
|
|
return Inst;
|
|
}
|
|
|
|
OpenACCComputeConstruct *OpenACCComputeConstruct::Create(
|
|
const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc,
|
|
SourceLocation DirLoc, SourceLocation EndLoc,
|
|
ArrayRef<const OpenACCClause *> Clauses, Stmt *StructuredBlock,
|
|
ArrayRef<OpenACCLoopConstruct *> AssociatedLoopConstructs) {
|
|
void *Mem = C.Allocate(
|
|
OpenACCComputeConstruct::totalSizeToAlloc<const OpenACCClause *>(
|
|
Clauses.size()));
|
|
auto *Inst = new (Mem) OpenACCComputeConstruct(K, BeginLoc, DirLoc, EndLoc,
|
|
Clauses, StructuredBlock);
|
|
|
|
llvm::for_each(AssociatedLoopConstructs, [&](OpenACCLoopConstruct *C) {
|
|
C->setParentComputeConstruct(Inst);
|
|
});
|
|
|
|
return Inst;
|
|
}
|
|
|
|
void OpenACCComputeConstruct::findAndSetChildLoops() {
|
|
struct LoopConstructFinder : RecursiveASTVisitor<LoopConstructFinder> {
|
|
OpenACCComputeConstruct *Construct = nullptr;
|
|
|
|
LoopConstructFinder(OpenACCComputeConstruct *Construct)
|
|
: Construct(Construct) {}
|
|
|
|
bool TraverseOpenACCComputeConstruct(OpenACCComputeConstruct *C) {
|
|
// Stop searching if we find a compute construct.
|
|
return true;
|
|
}
|
|
bool TraverseOpenACCLoopConstruct(OpenACCLoopConstruct *C) {
|
|
// Stop searching if we find a loop construct, after taking ownership of
|
|
// it.
|
|
C->setParentComputeConstruct(Construct);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
LoopConstructFinder f(this);
|
|
f.TraverseStmt(getAssociatedStmt());
|
|
}
|
|
|
|
OpenACCLoopConstruct::OpenACCLoopConstruct(unsigned NumClauses)
|
|
: OpenACCAssociatedStmtConstruct(
|
|
OpenACCLoopConstructClass, OpenACCDirectiveKind::Loop,
|
|
SourceLocation{}, SourceLocation{}, SourceLocation{},
|
|
/*AssociatedStmt=*/nullptr) {
|
|
std::uninitialized_value_construct(
|
|
getTrailingObjects<const OpenACCClause *>(),
|
|
getTrailingObjects<const OpenACCClause *>() + NumClauses);
|
|
setClauseList(
|
|
MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), NumClauses));
|
|
}
|
|
|
|
OpenACCLoopConstruct::OpenACCLoopConstruct(
|
|
SourceLocation Start, SourceLocation DirLoc, SourceLocation End,
|
|
ArrayRef<const OpenACCClause *> Clauses, Stmt *Loop)
|
|
: OpenACCAssociatedStmtConstruct(OpenACCLoopConstructClass,
|
|
OpenACCDirectiveKind::Loop, Start, DirLoc,
|
|
End, Loop) {
|
|
// accept 'nullptr' for the loop. This is diagnosed somewhere, but this gives
|
|
// us some level of AST fidelity in the error case.
|
|
assert((Loop == nullptr || isa<ForStmt, CXXForRangeStmt>(Loop)) &&
|
|
"Associated Loop not a for loop?");
|
|
// Initialize the trailing storage.
|
|
std::uninitialized_copy(Clauses.begin(), Clauses.end(),
|
|
getTrailingObjects<const OpenACCClause *>());
|
|
|
|
setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
|
|
Clauses.size()));
|
|
}
|
|
|
|
void OpenACCLoopConstruct::setLoop(Stmt *Loop) {
|
|
assert((isa<ForStmt, CXXForRangeStmt>(Loop)) &&
|
|
"Associated Loop not a for loop?");
|
|
setAssociatedStmt(Loop);
|
|
}
|
|
|
|
OpenACCLoopConstruct *OpenACCLoopConstruct::CreateEmpty(const ASTContext &C,
|
|
unsigned NumClauses) {
|
|
void *Mem =
|
|
C.Allocate(OpenACCLoopConstruct::totalSizeToAlloc<const OpenACCClause *>(
|
|
NumClauses));
|
|
auto *Inst = new (Mem) OpenACCLoopConstruct(NumClauses);
|
|
return Inst;
|
|
}
|
|
|
|
OpenACCLoopConstruct *
|
|
OpenACCLoopConstruct::Create(const ASTContext &C, SourceLocation BeginLoc,
|
|
SourceLocation DirLoc, SourceLocation EndLoc,
|
|
ArrayRef<const OpenACCClause *> Clauses,
|
|
Stmt *Loop) {
|
|
void *Mem =
|
|
C.Allocate(OpenACCLoopConstruct::totalSizeToAlloc<const OpenACCClause *>(
|
|
Clauses.size()));
|
|
auto *Inst =
|
|
new (Mem) OpenACCLoopConstruct(BeginLoc, DirLoc, EndLoc, Clauses, Loop);
|
|
return Inst;
|
|
}
|