diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 719001aec639..85ce9621d928 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -116,6 +116,35 @@ public: static bool classof(const CXXMemberCallExpr *) { return true; } }; +/// CUDAKernelCallExpr - Represents a call to a CUDA kernel function. +class CUDAKernelCallExpr : public CallExpr { +private: + enum { CONFIG, END_PREARG }; + +public: + CUDAKernelCallExpr(ASTContext &C, Expr *fn, CallExpr *Config, + Expr **args, unsigned numargs, QualType t, + ExprValueKind VK, SourceLocation RP) + : CallExpr(C, CUDAKernelCallExprClass, fn, END_PREARG, args, numargs, t, VK, + RP) { + setConfig(Config); + } + + CUDAKernelCallExpr(ASTContext &C, EmptyShell Empty) + : CallExpr(C, CUDAKernelCallExprClass, END_PREARG, Empty) { } + + const CallExpr *getConfig() const { + return cast_or_null(getPreArg(CONFIG)); + } + CallExpr *getConfig() { return cast_or_null(getPreArg(CONFIG)); } + void setConfig(CallExpr *E) { setPreArg(CONFIG, E); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CUDAKernelCallExprClass; + } + static bool classof(const CUDAKernelCallExpr *) { return true; } +}; + /// CXXNamedCastExpr - Abstract class common to all of the C++ "named" /// casts, @c static_cast, @c dynamic_cast, @c reinterpret_cast, or @c /// const_cast. diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index b98d380799f1..700dd8eb6ba5 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1846,6 +1846,7 @@ DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { DEF_TRAVERSE_STMT(CXXOperatorCallExpr, { }) DEF_TRAVERSE_STMT(OpaqueValueExpr, { }) +DEF_TRAVERSE_STMT(CUDAKernelCallExpr, { }) // These operators (all of them) do not need any action except // iterating over the children. diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index 32dd6c1d6971..54e9c6723c47 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -125,6 +125,9 @@ def ObjCIvarRefExpr : DStmt; def ObjCPropertyRefExpr : DStmt; def ObjCIsaExpr : DStmt; +// CUDA Expressions. +def CUDAKernelCallExpr : DStmt; + // Clang Extensions. def ShuffleVectorExpr : DStmt; def BlockExpr : DStmt; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 8c48fc56ceb2..8b24e925ed8c 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1177,7 +1177,8 @@ public: UnresolvedLookupExpr *ULE, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, - SourceLocation RParenLoc); + SourceLocation RParenLoc, + Expr *ExecConfig); ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned Opc, @@ -1913,11 +1914,16 @@ public: /// This provides the location of the left/right parens and a list of comma /// locations. ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, - MultiExprArg Args, SourceLocation RParenLoc); + MultiExprArg Args, SourceLocation RParenLoc, + Expr *ExecConfig = 0); ExprResult BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, - SourceLocation RParenLoc); + SourceLocation RParenLoc, + Expr *ExecConfig = 0); + + ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, + MultiExprArg ExecConfig, SourceLocation GGGLoc); ExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc, ParsedType Ty, SourceLocation RParenLoc, diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 13e857511f45..c501804a671c 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -949,7 +949,11 @@ namespace clang { EXPR_PACK_EXPANSION, // PackExpansionExpr EXPR_SIZEOF_PACK, // SizeOfPackExpr - EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK // SubstNonTypeTemplateParmPackExpr + EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK,// SubstNonTypeTemplateParmPackExpr + + // CUDA + + EXPR_CUDA_KERNEL_CALL // CUDAKernelCallExpr }; /// \brief The kinds of designators that can occur in a diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index ba3b88b46524..593f7830b4ed 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -238,6 +238,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::CallExprClass: case Expr::CXXOperatorCallExprClass: case Expr::CXXMemberCallExprClass: + case Expr::CUDAKernelCallExprClass: return ClassifyUnnamed(Ctx, cast(E)->getCallReturnType()); // __builtin_choose_expr is equivalent to the chosen expression. diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 227c60e564a1..0c3f6475369d 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2599,6 +2599,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::AddrLabelExprClass: case Expr::StmtExprClass: case Expr::CXXMemberCallExprClass: + case Expr::CUDAKernelCallExprClass: case Expr::CXXDynamicCastExprClass: case Expr::CXXTypeidExprClass: case Expr::CXXUuidofExprClass: diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 0e050414eeb7..6608571ade7e 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -1732,7 +1732,8 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { case Expr::BinaryTypeTraitExprClass: case Expr::VAArgExprClass: case Expr::CXXUuidofExprClass: - case Expr::CXXNoexceptExprClass: { + case Expr::CXXNoexceptExprClass: + case Expr::CUDAKernelCallExprClass: { // As bad as this diagnostic is, it's better than crashing. Diagnostic &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error, diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 5d31fd61a5af..fa1736f37682 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -961,6 +961,15 @@ void StmtPrinter::VisitCXXMemberCallExpr(CXXMemberCallExpr *Node) { VisitCallExpr(cast(Node)); } +void StmtPrinter::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *Node) { + PrintExpr(Node->getCallee()); + OS << "<<<"; + PrintCallArgs(Node->getConfig()); + OS << ">>>("; + PrintCallArgs(Node); + OS << ")"; +} + void StmtPrinter::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) { OS << Node->getCastName() << '<'; OS << Node->getTypeAsWritten().getAsString(Policy) << ">("; diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 842a2d92d815..707cac4edfe9 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -644,6 +644,10 @@ void StmtProfiler::VisitCXXMemberCallExpr(CXXMemberCallExpr *S) { VisitCallExpr(S); } +void StmtProfiler::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *S) { + VisitCallExpr(S); +} + void StmtProfiler::VisitCXXNamedCastExpr(CXXNamedCastExpr *S) { VisitExplicitCastExpr(S); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 429804d6e93a..fcc56f149200 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4362,7 +4362,8 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, /// locations. ExprResult Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, - MultiExprArg args, SourceLocation RParenLoc) { + MultiExprArg args, SourceLocation RParenLoc, + Expr *ExecConfig) { unsigned NumArgs = args.size(); // Since this might be a postfix expression, get rid of ParenListExprs. @@ -4399,10 +4400,17 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, else if (Expr::hasAnyTypeDependentArguments(Args, NumArgs)) Dependent = true; - if (Dependent) - return Owned(new (Context) CallExpr(Context, Fn, Args, NumArgs, - Context.DependentTy, VK_RValue, - RParenLoc)); + if (Dependent) { + if (ExecConfig) { + return Owned(new (Context) CUDAKernelCallExpr( + Context, Fn, cast(ExecConfig), Args, NumArgs, + Context.DependentTy, VK_RValue, RParenLoc)); + } else { + return Owned(new (Context) CallExpr(Context, Fn, Args, NumArgs, + Context.DependentTy, VK_RValue, + RParenLoc)); + } + } // Determine whether this is a call to an object (C++ [over.call.object]). if (Fn->getType()->isRecordType()) @@ -4495,7 +4503,7 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, if (isa(NakedFn)) { UnresolvedLookupExpr *ULE = cast(NakedFn); return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs, - RParenLoc); + RParenLoc, ExecConfig); } NamedDecl *NDecl = 0; @@ -4506,7 +4514,23 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, if (isa(NakedFn)) NDecl = cast(NakedFn)->getDecl(); - return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc); + return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc, + ExecConfig); +} + +ExprResult +Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, + MultiExprArg execConfig, SourceLocation GGGLoc) { + FunctionDecl *ConfigDecl = Context.getcudaConfigureCallDecl(); + if (!ConfigDecl) + return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use) + << "cudaConfigureCall"); + QualType ConfigQTy = ConfigDecl->getType(); + + DeclRefExpr *ConfigDR = new (Context) DeclRefExpr( + ConfigDecl, ConfigQTy, VK_LValue, LLLLoc); + + return ActOnCallExpr(S, ConfigDR, LLLLoc, execConfig, GGGLoc, 0); } /// BuildResolvedCallExpr - Build a call to a resolved expression, @@ -4519,7 +4543,8 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, + Expr *Config) { FunctionDecl *FDecl = dyn_cast_or_null(NDecl); // Promote the function operand. @@ -4527,11 +4552,21 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, // Make the call expr early, before semantic checks. This guarantees cleanup // of arguments and function on error. - CallExpr *TheCall = new (Context) CallExpr(Context, Fn, - Args, NumArgs, - Context.BoolTy, - VK_RValue, - RParenLoc); + CallExpr *TheCall; + if (Config) { + TheCall = new (Context) CUDAKernelCallExpr(Context, Fn, + cast(Config), + Args, NumArgs, + Context.BoolTy, + VK_RValue, + RParenLoc); + } else { + TheCall = new (Context) CallExpr(Context, Fn, + Args, NumArgs, + Context.BoolTy, + VK_RValue, + RParenLoc); + } const FunctionType *FuncT; if (!Fn->getType()->isBlockPointerType()) { diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 916c5a198fa3..42e24116bfe2 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -7426,7 +7426,8 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, + Expr *ExecConfig) { #ifndef NDEBUG if (ULE->requiresADL()) { // To do ADL, we must have found an unqualified name. @@ -7466,8 +7467,8 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, DiagnoseUseOfDecl(FDecl? FDecl : Best->FoundDecl.getDecl(), ULE->getNameLoc()); Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl); - return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, - RParenLoc); + return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc, + ExecConfig); } case OR_No_Viable_Function: diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index bd110bd1f6fa..ca5d1c1ea0f3 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1348,9 +1348,10 @@ public: /// Subclasses may override this routine to provide different behavior. ExprResult RebuildCallExpr(Expr *Callee, SourceLocation LParenLoc, MultiExprArg Args, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, + Expr *ExecConfig = 0) { return getSema().ActOnCallExpr(/*Scope=*/0, Callee, LParenLoc, - move(Args), RParenLoc); + move(Args), RParenLoc, ExecConfig); } /// \brief Build a new member access expression. @@ -5919,6 +5920,39 @@ TreeTransform::TransformCXXMemberCallExpr(CXXMemberCallExpr *E) { return getDerived().TransformCallExpr(E); } +template +ExprResult +TreeTransform::TransformCUDAKernelCallExpr(CUDAKernelCallExpr *E) { + // Transform the callee. + ExprResult Callee = getDerived().TransformExpr(E->getCallee()); + if (Callee.isInvalid()) + return ExprError(); + + // Transform exec config. + ExprResult EC = getDerived().TransformCallExpr(E->getConfig()); + if (EC.isInvalid()) + return ExprError(); + + // Transform arguments. + bool ArgChanged = false; + ASTOwningVector Args(SemaRef); + if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), true, Args, + &ArgChanged)) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + Callee.get() == E->getCallee() && + !ArgChanged) + return SemaRef.Owned(E); + + // FIXME: Wrong source location information for the '('. + SourceLocation FakeLParenLoc + = ((Expr *)Callee.get())->getSourceRange().getBegin(); + return getDerived().RebuildCallExpr(Callee.get(), FakeLParenLoc, + move_arg(Args), + E->getRParenLoc(), EC.get()); +} + template ExprResult TreeTransform::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) { diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 8bd94b48ce2f..864c04283b0f 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -182,6 +182,9 @@ namespace clang { void VisitSubstNonTypeTemplateParmPackExpr( SubstNonTypeTemplateParmPackExpr *E); void VisitOpaqueValueExpr(OpaqueValueExpr *E); + + // CUDA Expressions + void VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E); }; } @@ -1323,6 +1326,15 @@ void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) { E->Loc = ReadSourceLocation(Record, Idx); } +//===----------------------------------------------------------------------===// +// CUDA Expressions and Statements +//===----------------------------------------------------------------------===// + +void ASTStmtReader::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E) { + VisitCallExpr(E); + E->setConfig(cast(Reader.ReadSubExpr())); +} + Stmt *ASTReader::ReadStmt(PerFileData &F) { switch (ReadingKind) { case Read_Decl: @@ -1872,6 +1884,10 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { case EXPR_OPAQUE_VALUE: S = new (Context) OpaqueValueExpr(Empty); break; + + case EXPR_CUDA_KERNEL_CALL: + S = new (Context) CUDAKernelCallExpr(*Context, Empty); + break; } // We hit a STMT_STOP, so we're done with this expression. diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index a5af03cfb06a..624cf1034909 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -691,6 +691,7 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(EXPR_PACK_EXPANSION); RECORD(EXPR_SIZEOF_PACK); RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK); + RECORD(EXPR_CUDA_KERNEL_CALL); #undef RECORD } diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index d721c18022e9..8a90ef16c30d 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -156,6 +156,9 @@ namespace clang { void VisitSubstNonTypeTemplateParmPackExpr( SubstNonTypeTemplateParmPackExpr *E); void VisitOpaqueValueExpr(OpaqueValueExpr *E); + + // CUDA Expressions + void VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E); }; } @@ -1324,6 +1327,16 @@ void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { Code = serialization::EXPR_OPAQUE_VALUE; } +//===----------------------------------------------------------------------===// +// CUDA Expressions and Statements. +//===----------------------------------------------------------------------===// + +void ASTStmtWriter::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E) { + VisitCallExpr(E); + Writer.AddStmt(E->getConfig()); + Code = serialization::EXPR_CUDA_KERNEL_CALL; +} + //===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp index e01d171d1905..0b202a186a66 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp @@ -894,6 +894,7 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, case Stmt::PredefinedExprClass: case Stmt::ShuffleVectorExprClass: case Stmt::VAArgExprClass: + case Stmt::CUDAKernelCallExprClass: // Fall through. // Cases we intentionally don't evaluate, since they don't need diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 7be547028462..a47caffd4529 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -187,6 +187,7 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, case Stmt::CallExprClass: case Stmt::CXXOperatorCallExprClass: case Stmt::CXXMemberCallExprClass: + case Stmt::CUDAKernelCallExprClass: case Stmt::CXXConstructExprClass: case Stmt::CXXTemporaryObjectExprClass: // FIXME: CXXUnresolvedConstructExpr