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<CallExpr>(getPreArg(CONFIG));
+ }
+ CallExpr *getConfig() { return cast_or_null<CallExpr>(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.
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.
def ObjCPropertyRefExpr : DStmt<Expr>;
def ObjCIsaExpr : DStmt<Expr>;
+// CUDA Expressions.
+def CUDAKernelCallExpr : DStmt<CallExpr>;
+
// Clang Extensions.
def ShuffleVectorExpr : DStmt<Expr>;
def BlockExpr : DStmt<Expr>;
UnresolvedLookupExpr *ULE,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
- SourceLocation RParenLoc);
+ SourceLocation RParenLoc,
+ Expr *ExecConfig);
ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
unsigned Opc,
/// 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,
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
case Expr::CallExprClass:
case Expr::CXXOperatorCallExprClass:
case Expr::CXXMemberCallExprClass:
+ case Expr::CUDAKernelCallExprClass:
return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType());
// __builtin_choose_expr is equivalent to the chosen expression.
case Expr::AddrLabelExprClass:
case Expr::StmtExprClass:
case Expr::CXXMemberCallExprClass:
+ case Expr::CUDAKernelCallExprClass:
case Expr::CXXDynamicCastExprClass:
case Expr::CXXTypeidExprClass:
case Expr::CXXUuidofExprClass:
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,
VisitCallExpr(cast<CallExpr>(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) << ">(";
VisitCallExpr(S);
}
+void StmtProfiler::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *S) {
+ VisitCallExpr(S);
+}
+
void StmtProfiler::VisitCXXNamedCastExpr(CXXNamedCastExpr *S) {
VisitExplicitCastExpr(S);
}
/// 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.
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<CallExpr>(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())
if (isa<UnresolvedLookupExpr>(NakedFn)) {
UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(NakedFn);
return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs,
- RParenLoc);
+ RParenLoc, ExecConfig);
}
NamedDecl *NDecl = 0;
if (isa<DeclRefExpr>(NakedFn))
NDecl = cast<DeclRefExpr>(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,
Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
- SourceLocation RParenLoc) {
+ SourceLocation RParenLoc,
+ Expr *Config) {
FunctionDecl *FDecl = dyn_cast_or_null<FunctionDecl>(NDecl);
// Promote the function operand.
// 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<CallExpr>(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()) {
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.
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:
/// 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.
return getDerived().TransformCallExpr(E);
}
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::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<Expr*> 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<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
void VisitSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E);
void VisitOpaqueValueExpr(OpaqueValueExpr *E);
+
+ // CUDA Expressions
+ void VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E);
};
}
E->Loc = ReadSourceLocation(Record, Idx);
}
+//===----------------------------------------------------------------------===//
+// CUDA Expressions and Statements
+//===----------------------------------------------------------------------===//
+
+void ASTStmtReader::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E) {
+ VisitCallExpr(E);
+ E->setConfig(cast<CallExpr>(Reader.ReadSubExpr()));
+}
+
Stmt *ASTReader::ReadStmt(PerFileData &F) {
switch (ReadingKind) {
case Read_Decl:
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.
RECORD(EXPR_PACK_EXPANSION);
RECORD(EXPR_SIZEOF_PACK);
RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK);
+ RECORD(EXPR_CUDA_KERNEL_CALL);
#undef RECORD
}
void VisitSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E);
void VisitOpaqueValueExpr(OpaqueValueExpr *E);
+
+ // CUDA Expressions
+ void VisitCUDAKernelCallExpr(CUDAKernelCallExpr *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
//===----------------------------------------------------------------------===//
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
case Stmt::CallExprClass:
case Stmt::CXXOperatorCallExprClass:
case Stmt::CXXMemberCallExprClass:
+ case Stmt::CUDAKernelCallExprClass:
case Stmt::CXXConstructExprClass:
case Stmt::CXXTemporaryObjectExprClass:
// FIXME: CXXUnresolvedConstructExpr