diff options
Diffstat (limited to 'clang/lib/AST/StmtOpenACC.cpp')
| -rw-r--r-- | clang/lib/AST/StmtOpenACC.cpp | 44 |
1 files changed, 32 insertions, 12 deletions
diff --git a/clang/lib/AST/StmtOpenACC.cpp b/clang/lib/AST/StmtOpenACC.cpp index 2b56c1e..462a10d 100644 --- a/clang/lib/AST/StmtOpenACC.cpp +++ b/clang/lib/AST/StmtOpenACC.cpp @@ -324,6 +324,18 @@ OpenACCAtomicConstruct *OpenACCAtomicConstruct::Create( return Inst; } +static std::pair<const Expr *, const Expr *> getBinaryOpArgs(const Expr *Op) { + if (const auto *BO = dyn_cast<BinaryOperator>(Op)) { + assert(BO->getOpcode() == BO_Assign); + return {BO->getLHS(), BO->getRHS()}; + } + + const auto *OO = cast<CXXOperatorCallExpr>(Op); + assert(OO->getOperator() == OO_Equal); + + return {OO->getArg(0), OO->getArg(1)}; +} + const OpenACCAtomicConstruct::StmtInfo OpenACCAtomicConstruct::getAssociatedStmtInfo() const { // This ends up being a vastly simplified version of SemaOpenACCAtomic, since @@ -333,27 +345,35 @@ OpenACCAtomicConstruct::getAssociatedStmtInfo() const { switch (AtomicKind) { case OpenACCAtomicKind::None: - case OpenACCAtomicKind::Write: case OpenACCAtomicKind::Update: case OpenACCAtomicKind::Capture: - assert(false && "Only 'read' has been implemented here"); + assert(false && "Only 'read'/'write' have been implemented here"); return {}; case OpenACCAtomicKind::Read: { // Read only supports the format 'v = x'; where both sides are a scalar // expression. This can come in 2 forms; BinaryOperator or // CXXOperatorCallExpr (rarely). - const Expr *AssignExpr = cast<const Expr>(getAssociatedStmt()); - if (const auto *BO = dyn_cast<BinaryOperator>(AssignExpr)) { - assert(BO->getOpcode() == BO_Assign); - return {BO->getLHS()->IgnoreImpCasts(), BO->getRHS()->IgnoreImpCasts()}; - } - - const auto *OO = cast<CXXOperatorCallExpr>(AssignExpr); - assert(OO->getOperator() == OO_Equal); - - return {OO->getArg(0)->IgnoreImpCasts(), OO->getArg(1)->IgnoreImpCasts()}; + std::pair<const Expr *, const Expr *> BinaryArgs = + getBinaryOpArgs(cast<const Expr>(getAssociatedStmt())); + // We want the L-value for each side, so we ignore implicit casts. + return {BinaryArgs.first->IgnoreImpCasts(), + BinaryArgs.second->IgnoreImpCasts(), /*expr=*/nullptr}; } + case OpenACCAtomicKind::Write: { + // Write supports only the format 'x = expr', where the expression is scalar + // type, and 'x' is a scalar l value. As above, this can come in 2 forms; + // Binary Operator or CXXOperatorCallExpr. + std::pair<const Expr *, const Expr *> BinaryArgs = + getBinaryOpArgs(cast<const Expr>(getAssociatedStmt())); + // We want the L-value for ONLY the X side, so we ignore implicit casts. For + // the right side (the expr), we emit it as an r-value so we need to + // maintain implicit casts. + return {/*v=*/nullptr, BinaryArgs.first->IgnoreImpCasts(), + BinaryArgs.second}; } + } + + llvm_unreachable("unknown OpenACC atomic kind"); } OpenACCCacheConstruct *OpenACCCacheConstruct::CreateEmpty(const ASTContext &C, |
