AST, Sema, Serialization: add CUDAKernelCallExpr and related semantic actions

llvm-svn: 125217
This commit is contained in:
Peter Collingbourne 2011-02-09 21:07:24 +00:00
parent 9e2c81f00a
commit 41f8546233
18 changed files with 184 additions and 23 deletions

View File

@ -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<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.

View File

@ -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.

View File

@ -125,6 +125,9 @@ def ObjCIvarRefExpr : DStmt<Expr>;
def ObjCPropertyRefExpr : DStmt<Expr>;
def ObjCIsaExpr : DStmt<Expr>;
// CUDA Expressions.
def CUDAKernelCallExpr : DStmt<CallExpr>;
// Clang Extensions.
def ShuffleVectorExpr : DStmt<Expr>;
def BlockExpr : DStmt<Expr>;

View File

@ -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,

View File

@ -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

View File

@ -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<CallExpr>(E)->getCallReturnType());
// __builtin_choose_expr is equivalent to the chosen expression.

View File

@ -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:

View File

@ -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,

View File

@ -961,6 +961,15 @@ void StmtPrinter::VisitCXXMemberCallExpr(CXXMemberCallExpr *Node) {
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) << ">(";

View File

@ -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);
}

View File

@ -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<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())
@ -4495,7 +4503,7 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
if (isa<UnresolvedLookupExpr>(NakedFn)) {
UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(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<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,
@ -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<FunctionDecl>(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<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()) {

View File

@ -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:

View File

@ -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<Derived>::TransformCXXMemberCallExpr(CXXMemberCallExpr *E) {
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) {

View File

@ -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<CallExpr>(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.

View File

@ -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
}

View File

@ -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
//===----------------------------------------------------------------------===//

View File

@ -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

View File

@ -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