From c0ef9f59937c3971c48b6fed37cf5bd8985c024b Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Fri, 20 Feb 2009 18:06:48 +0000 Subject: [PATCH] Set call attribute for direct calls (i.e. noreturn). - Remove an unused variant of EmitCallExpr overload. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65130 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCall.cpp | 6 +++--- lib/CodeGen/CGExpr.cpp | 33 ++++++++++++++---------------- lib/CodeGen/CodeGenFunction.h | 13 +++++++----- test/CodeGen/function-attributes.c | 13 +++++++++++- 4 files changed, 38 insertions(+), 27 deletions(-) diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 42f671a7e6..d0122fa4f9 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -1676,7 +1676,8 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::Value *Callee, - const CallArgList &CallArgs) { + const CallArgList &CallArgs, + const Decl *TargetDecl) { // FIXME: We no longer need the types from CallArgs; lift up and // simplify. llvm::SmallVector Args; @@ -1752,9 +1753,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::CallInst *CI = Builder.CreateCall(Callee,&Args[0],&Args[0]+Args.size()); - // FIXME: Provide TargetDecl so nounwind, noreturn, etc, etc get set. CodeGen::AttributeListType AttributeList; - CGM.ConstructAttributeList(CallInfo, 0, AttributeList); + CGM.ConstructAttributeList(CallInfo, TargetDecl, AttributeList); CI->setAttributes(llvm::AttrListPtr::get(AttributeList.begin(), AttributeList.size())); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 5da0de9cbb..22a6a2d02e 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -966,29 +966,25 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E) RValue CodeGenFunction::EmitCallExpr(const CallExpr *E) { + // Builtins never have block type. + if (E->getCallee()->getType()->isBlockPointerType()) + return EmitBlockCallExpr(E); + + const Decl *TargetDecl = 0; if (const ImplicitCastExpr *IcExpr = - dyn_cast(E->getCallee())) + dyn_cast(E->getCallee())) { if (const DeclRefExpr *DRExpr = - dyn_cast(IcExpr->getSubExpr())) - if (const FunctionDecl *FDecl = - dyn_cast(DRExpr->getDecl())) + dyn_cast(IcExpr->getSubExpr())) { + TargetDecl = DRExpr->getDecl(); + if (const FunctionDecl *FDecl = dyn_cast(TargetDecl)) if (unsigned builtinID = FDecl->getBuiltinID(getContext())) return EmitBuiltinExpr(FDecl, builtinID, E); - - if (E->getCallee()->getType()->isBlockPointerType()) - return EmitBlockCallExpr(E); + } + } llvm::Value *Callee = EmitScalarExpr(E->getCallee()); return EmitCallExpr(Callee, E->getCallee()->getType(), - E->arg_begin(), E->arg_end()); -} - -RValue CodeGenFunction::EmitCallExpr(Expr *FnExpr, - CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd) { - - llvm::Value *Callee = EmitScalarExpr(FnExpr); - return EmitCallExpr(Callee, FnExpr->getType(), ArgBeg, ArgEnd); + E->arg_begin(), E->arg_end(), TargetDecl); } LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) { @@ -1108,7 +1104,8 @@ CodeGenFunction::EmitObjCSuperExpr(const ObjCSuperExpr *E) { RValue CodeGenFunction::EmitCallExpr(llvm::Value *Callee, QualType CalleeType, CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd) { + CallExpr::const_arg_iterator ArgEnd, + const Decl *TargetDecl) { // Get the actual function type. The callee type will always be a // pointer to function type or a block pointer type. QualType ResultType; @@ -1127,5 +1124,5 @@ RValue CodeGenFunction::EmitCallExpr(llvm::Value *Callee, QualType CalleeType, I->getType())); return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), - Callee, Args); + Callee, Args, TargetDecl); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index bc602f3720..7072be8f60 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -618,18 +618,21 @@ public: /// EmitCall - Generate a call of the given function, expecting the given /// result type, and using the given argument list which specifies both the /// LLVM arguments and the types they were derived from. + /// + /// \param TargetDecl - If given, the decl of the function in a + /// direct call; used to set attributes on the call (noreturn, + /// etc.). RValue EmitCall(const CGFunctionInfo &FnInfo, llvm::Value *Callee, - const CallArgList &Args); + const CallArgList &Args, + const Decl *TargetDecl = 0); RValue EmitCallExpr(const CallExpr *E); - RValue EmitCallExpr(Expr *FnExpr, CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd); - RValue EmitCallExpr(llvm::Value *Callee, QualType FnType, CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd); + CallExpr::const_arg_iterator ArgEnd, + const Decl *TargetDecl = 0); RValue EmitBuiltinExpr(const FunctionDecl *FD, unsigned BuiltinID, const CallExpr *E); diff --git a/test/CodeGen/function-attributes.c b/test/CodeGen/function-attributes.c index dacfdd9675..ca16459fd9 100644 --- a/test/CodeGen/function-attributes.c +++ b/test/CodeGen/function-attributes.c @@ -7,7 +7,7 @@ // RUN: grep 'define zeroext i16 @f5(i32 %x) nounwind' %t && // RUN: grep 'define void @f6(i16 signext %x) nounwind' %t && // RUN: grep 'define void @f7(i16 zeroext %x) nounwind' %t && -// RUN: grep 'define void @f8() nounwind alwaysinline' %t +// RUN: grep 'define void @f8() nounwind alwaysinline' %t && signed char f0(int x) { return x; } @@ -26,3 +26,14 @@ void f6(signed short x) { } void f7(unsigned short x) { } void __attribute__((always_inline)) f8(void) { } + +// RUN: grep 'call void @f9_t() noreturn' %t && +void __attribute__((noreturn)) f9_t(void); +void f9(void) { f9_t(); } + +// FIXME: We should be setting nounwind on calls. +// RUN: grep 'call i32 @f10_t() readnone' %t && +int __attribute__((const)) f10_t(void); +int f10(void) { return f10_t(); } + +// RUN: true -- 2.40.0