diff options
author | Tom Stellard <thomas.stellard@amd.com> | 2015-03-31 16:39:02 +0000 |
---|---|---|
committer | Tom Stellard <thomas.stellard@amd.com> | 2015-03-31 16:39:02 +0000 |
commit | b919c7d9eb8598b7f631c1edcd0b874bbdaf99d6 (patch) | |
tree | 43f14b55a031a8171ac44d23d72a1268e146f376 /clang/lib/Sema/SemaExpr.cpp | |
parent | bf441f4ffa478bc7aacafa19e71c6cb32969c9de (diff) | |
download | bcm5719-llvm-b919c7d9eb8598b7f631c1edcd0b874bbdaf99d6.tar.gz bcm5719-llvm-b919c7d9eb8598b7f631c1edcd0b874bbdaf99d6.zip |
Sema: Accept pointers to any address space for builtin functions
As long as they don't have an address space explicitly defined.
This allows builtins with pointer arguments to be used with OpenCL.
llvm-svn: 233706
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 97 |
1 files changed, 94 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 6eac5b6a936..d6e6ab4ec86 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4608,6 +4608,83 @@ static bool checkArgsForPlaceholders(Sema &S, MultiExprArg args) { return hasInvalid; } +/// If a builtin function has a pointer argument with no explicit address +/// space, than it should be able to accept a pointer to any address +/// space as input. In order to do this, we need to replace the +/// standard builtin declaration with one that uses the same address space +/// as the call. +/// +/// \returns nullptr If this builtin is not a candidate for a rewrite i.e. +/// it does not contain any pointer arguments without +/// an address space qualifer. Otherwise the rewritten +/// FunctionDecl is returned. +/// TODO: Handle pointer return types. +static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context, + const FunctionDecl *FDecl, + MultiExprArg ArgExprs) { + + QualType DeclType = FDecl->getType(); + const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(DeclType); + + if (!Context.BuiltinInfo.hasPtrArgsOrResult(FDecl->getBuiltinID()) || + !FT || FT->isVariadic() || ArgExprs.size() != FT->getNumParams()) + return nullptr; + + bool NeedsNewDecl = false; + unsigned i = 0; + SmallVector<QualType, 8> OverloadParams; + + for (QualType ParamType : FT->param_types()) { + + // Convert array arguments to pointer to simplify type lookup. + Expr *Arg = Sema->DefaultFunctionArrayLvalueConversion(ArgExprs[i++]).get(); + QualType ArgType = Arg->getType(); + if (!ParamType->isPointerType() || + ParamType.getQualifiers().hasAddressSpace() || + !ArgType->isPointerType() || + !ArgType->getPointeeType().getQualifiers().hasAddressSpace()) { + OverloadParams.push_back(ParamType); + continue; + } + + NeedsNewDecl = true; + unsigned AS = ArgType->getPointeeType().getQualifiers().getAddressSpace(); + + QualType PointeeType = ParamType->getPointeeType(); + PointeeType = Context.getAddrSpaceQualType(PointeeType, AS); + OverloadParams.push_back(Context.getPointerType(PointeeType)); + } + + if (!NeedsNewDecl) + return nullptr; + + FunctionProtoType::ExtProtoInfo EPI; + QualType OverloadTy = Context.getFunctionType(FT->getReturnType(), + OverloadParams, EPI); + DeclContext *Parent = Context.getTranslationUnitDecl(); + FunctionDecl *OverloadDecl = FunctionDecl::Create(Context, Parent, + FDecl->getLocation(), + FDecl->getLocation(), + FDecl->getIdentifier(), + OverloadTy, + /*TInfo=*/nullptr, + SC_Extern, false, + /*hasPrototype=*/true); + SmallVector<ParmVarDecl*, 16> Params; + FT = cast<FunctionProtoType>(OverloadTy); + for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { + QualType ParamType = FT->getParamType(i); + ParmVarDecl *Parm = + ParmVarDecl::Create(Context, OverloadDecl, SourceLocation(), + SourceLocation(), nullptr, ParamType, + /*TInfo=*/nullptr, SC_None, nullptr); + Parm->setScopeInfo(0, i); + Params.push_back(Parm); + } + OverloadDecl->setParams(Params); + return OverloadDecl; +} + /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. /// This provides the location of the left/right parens and a list of comma /// locations. @@ -4711,10 +4788,24 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn)) if (UnOp->getOpcode() == UO_AddrOf) NakedFn = UnOp->getSubExpr()->IgnoreParens(); - - if (isa<DeclRefExpr>(NakedFn)) + + if (isa<DeclRefExpr>(NakedFn)) { NDecl = cast<DeclRefExpr>(NakedFn)->getDecl(); - else if (isa<MemberExpr>(NakedFn)) + + FunctionDecl *FDecl = dyn_cast<FunctionDecl>(NDecl); + if (FDecl && FDecl->getBuiltinID()) { + // Rewrite the function decl for this builtin by replacing paramaters + // with no explicit address space with the address space of the arguments + // in ArgExprs. + if ((FDecl = rewriteBuiltinFunctionDecl(this, Context, FDecl, ArgExprs))) { + NDecl = FDecl; + Fn = DeclRefExpr::Create(Context, FDecl->getQualifierLoc(), + SourceLocation(), FDecl, false, + SourceLocation(), FDecl->getType(), + Fn->getValueKind(), FDecl); + } + } + } else if (isa<MemberExpr>(NakedFn)) NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl(); if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(NDecl)) { |